polkadot-cli 1.18.0 → 1.20.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 +120 -15
- package/dist/cli.mjs +350 -58
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -280,6 +280,10 @@ dot account create my-staking --path //staking
|
|
|
280
280
|
# Add a keyed account from a BIP39 mnemonic
|
|
281
281
|
dot account add treasury --secret "word1 word2 ... word12"
|
|
282
282
|
|
|
283
|
+
# Add from a 32-byte hex seed or a 64-byte raw sr25519 private key
|
|
284
|
+
dot account add seeded --secret 0x1111111111111111111111111111111111111111111111111111111111111111
|
|
285
|
+
dot account add raw-key --secret 0x<128-hex-char expanded secret> # no --path
|
|
286
|
+
|
|
283
287
|
# Add with a derivation path
|
|
284
288
|
dot account add hot-wallet --secret "word1 word2 ... word12" --path //hot
|
|
285
289
|
|
|
@@ -313,6 +317,7 @@ dot account inspect 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
|
|
|
313
317
|
dot account inspect 0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d
|
|
314
318
|
dot account inspect alice --prefix 0 # Polkadot mainnet prefix
|
|
315
319
|
dot account inspect alice --json # JSON output
|
|
320
|
+
dot account inspect dave --show-secret # reveal mnemonic + sr25519 private key
|
|
316
321
|
```
|
|
317
322
|
|
|
318
323
|
#### Watch-only accounts
|
|
@@ -373,6 +378,11 @@ dot account alice # shorthand — unknown subcommands fall th
|
|
|
373
378
|
|
|
374
379
|
dot account inspect 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
|
|
375
380
|
dot account inspect 0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d
|
|
381
|
+
|
|
382
|
+
# pallet-revive H160 — the 20-byte address shape from EVM tooling. Same
|
|
383
|
+
# input slot as SS58 / hex pubkey; resolved to the deterministic fallback
|
|
384
|
+
# AccountId32 (`H160 || 0xEE * 12`).
|
|
385
|
+
dot account inspect 0x9621DDe636dE098B43Efb0fA9b61fAcFE328F99D
|
|
376
386
|
```
|
|
377
387
|
|
|
378
388
|
Use `--prefix` to encode the SS58 address with a specific network prefix (default: 42):
|
|
@@ -390,6 +400,7 @@ dot account inspect alice --json
|
|
|
390
400
|
# {
|
|
391
401
|
# "publicKey": "0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d",
|
|
392
402
|
# "ss58": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
|
|
403
|
+
# "h160": "0x9621DDe636dE098B43Efb0fA9b61fAcFE328F99D",
|
|
393
404
|
# "prefix": 42,
|
|
394
405
|
# "name": "Alice",
|
|
395
406
|
# "kind": "dev"
|
|
@@ -407,10 +418,38 @@ dot account inspect alice
|
|
|
407
418
|
# Kind: dev
|
|
408
419
|
# Public Key: 0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d
|
|
409
420
|
# SS58: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
|
|
421
|
+
# H160: 0x9621DDe636dE098B43Efb0fA9b61fAcFE328F99D
|
|
422
|
+
# Prefix: 42
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
The `Kind:` line categorises the account: `dev` (built-in), `signer` (has a secret/env), `watch-only` (raw external address), `pallet sovereign` (derived from a `PalletId`), `parachain sovereign (child|sibling)` (derived from a parachain ID), or `revive H160 fallback` (a 20-byte input resolved to its deterministic Substrate AccountId32). For derived sovereigns, an extra `Source:` line shows what the address was derived from. For env-backed signers, an `Env:` line shows the variable; for derived child keys, `Derivation:` shows the path.
|
|
426
|
+
|
|
427
|
+
##### pallet-revive H160 address
|
|
428
|
+
|
|
429
|
+
Every Substrate account has a corresponding 20-byte H160 address under [pallet-revive](https://github.com/paritytech/polkadot-sdk/tree/master/substrate/frame/revive) (the new EVM-compatible smart-contracts pallet on Polkadot Hub / Asset Hub). `dot account inspect` always shows it, EIP-55 checksummed, on the `H160:` line. The mapping is offline and prefix-independent:
|
|
430
|
+
|
|
431
|
+
- **AccountId32 → H160:** if the last 12 bytes are `0xEE`, strip them (the account originated from an Eth address); otherwise `keccak256(accountId32)` and take the last 20 bytes.
|
|
432
|
+
- **H160 → AccountId32:** deterministic fallback is `H160 || 0xEE * 12`. (The full mapping after a successful `pallet_revive.map_account` extrinsic lives in on-chain `AddressSuffix` storage and isn't recoverable offline — that's a chain-state lookup.)
|
|
433
|
+
|
|
434
|
+
Pass a 20-byte hex value as the inspect input to resolve it back to its fallback Substrate account:
|
|
435
|
+
|
|
436
|
+
```bash
|
|
437
|
+
dot account inspect 0x9621DDe636dE098B43Efb0fA9b61fAcFE328F99D
|
|
438
|
+
# Output:
|
|
439
|
+
# Account Info
|
|
440
|
+
#
|
|
441
|
+
# Kind: revive H160 fallback
|
|
442
|
+
# Public Key: 0x9621dde636de098b43efb0fa9b61facfe328f99deeeeeeeeeeeeeeeeeeeeeeee
|
|
443
|
+
# SS58: 5FTZ6n1wY3GBqEZ2DWEdspbTarvRnp8DM8x2YXbWubu7JN98
|
|
444
|
+
# H160: 0x9621DDe636dE098B43Efb0fA9b61fAcFE328F99D
|
|
410
445
|
# Prefix: 42
|
|
446
|
+
|
|
447
|
+
# Script-friendly: just the H160 for a given account
|
|
448
|
+
dot account inspect alice --json | jq -r .h160
|
|
449
|
+
# 0x9621DDe636dE098B43Efb0fA9b61fAcFE328F99D
|
|
411
450
|
```
|
|
412
451
|
|
|
413
|
-
|
|
452
|
+
Note: `dot` implements the current `pallet-revive` master variant (keccak fallback). Older `stable2412` runtimes used plain `accountId32[..20]` truncation; if you target one, compute it manually until a `--revive-truncate` flag lands.
|
|
414
453
|
|
|
415
454
|
##### Stateless sovereign derivation (script-friendly)
|
|
416
455
|
|
|
@@ -450,16 +489,21 @@ dot account inspect --pallet-id py/trsry --json
|
|
|
450
489
|
|
|
451
490
|
Constraints (will error): cannot combine a positional input with derivation flags; `--pallet-id` and `--parachain` are mutually exclusive; `--parachain` requires `--parachain-type child|sibling`; `--show-secret` doesn't apply (derived sovereigns have no key).
|
|
452
491
|
|
|
453
|
-
#### Reveal the sr25519 private key
|
|
492
|
+
#### Reveal the mnemonic and sr25519 private key
|
|
454
493
|
|
|
455
|
-
For provisioning another signer (e.g. a server that expects a raw hex private key in an env var), add `--show-secret` to print the **64-byte sr25519 expanded secret** as `0x`-prefixed hex:
|
|
494
|
+
For provisioning another signer (e.g. a server that expects a raw hex private key in an env var), add `--show-secret` to print the **64-byte sr25519 expanded secret** as `0x`-prefixed hex. It also reveals the **stored mnemonic** (or hex seed) so you can back it up:
|
|
456
495
|
|
|
457
496
|
```bash
|
|
458
|
-
dot account inspect
|
|
459
|
-
#
|
|
497
|
+
dot account inspect my-validator --show-secret
|
|
498
|
+
# Mnemonic: word1 word2 ... word12 (only for accounts stored as a phrase)
|
|
499
|
+
# Private Key: 0x<128 hex chars> (sr25519 expanded, 64 bytes — never share)
|
|
460
500
|
```
|
|
461
501
|
|
|
462
|
-
Works for dev accounts (derived on-the-fly from the standard dev mnemonic) and for stored accounts that have a secret
|
|
502
|
+
Works for dev accounts (derived on-the-fly from the standard dev mnemonic) and for stored accounts that have a secret. Refuses on watch-only accounts, bare SS58 addresses, or hex public keys. The revealed line depends on how the account was stored: a phrase shows under `Mnemonic`, a 32-byte hex seed under `Seed`, and a raw private key shows only the `Private Key` (the stored secret already _is_ the expanded key). **Env-backed secrets are never resolved to disk output** — only the `$VAR` reference is shown. The expanded `Private Key` is the final secret after any derivation path is applied, so it can be fed directly to signers that don't accept a mnemonic+path (e.g. `@scure/sr25519`'s `sign`, or services like identity-backend that read a `PROXY_PRIVATE_KEY`). Combine with `--json` to include the values under the `mnemonic`/`seed` and `privateKey` fields.
|
|
503
|
+
|
|
504
|
+
The revealed `Private Key` round-trips: you can re-import it as a usable account (see [Import a raw private key](#import-a-raw-private-key) below).
|
|
505
|
+
|
|
506
|
+
> **Note:** if the account was stored with a derivation path, the revealed `Mnemonic`/`Seed` reproduces the original address **only when re-imported with the same `--path`** (shown on the `Derivation` line). The `Private Key` already bakes in the path, so it round-trips on its own.
|
|
463
507
|
|
|
464
508
|
#### Env-var-backed accounts
|
|
465
509
|
|
|
@@ -506,12 +550,29 @@ Signers
|
|
|
506
550
|
|
|
507
551
|
**Supported secret formats for import:**
|
|
508
552
|
|
|
509
|
-
| Format | Example |
|
|
510
|
-
|
|
511
|
-
| BIP39 mnemonic (12/24 words) | `"abandon abandon ... about"` |
|
|
512
|
-
| Hex seed (`0x` + 64 hex chars) | `
|
|
553
|
+
| Format | Example | `--path`? |
|
|
554
|
+
|--------|---------|-----------|
|
|
555
|
+
| BIP39 mnemonic (12/24 words) | `"abandon abandon ... about"` | Yes |
|
|
556
|
+
| Hex seed (`0x` + 64 hex chars = 32 bytes) | `0x1111...1111` | Yes |
|
|
557
|
+
| Raw private key (`0x` + 128 hex chars = 64-byte sr25519 expanded secret) | `0x20e0...5568` | No (cannot be HD-derived) |
|
|
558
|
+
|
|
559
|
+
All three formats work directly from the command line via `--secret` or via `--env`.
|
|
513
560
|
|
|
514
|
-
|
|
561
|
+
#### Import a raw private key
|
|
562
|
+
|
|
563
|
+
The 64-byte expanded secret that `--show-secret` prints can be re-imported as a fully usable, signing-capable account. This is the round-trip companion to `--show-secret` — handy when a key only exists in expanded form (e.g. exported from another tool or read from a `PROXY_PRIVATE_KEY` env var):
|
|
564
|
+
|
|
565
|
+
```bash
|
|
566
|
+
# Round-trip: reveal dave's expanded secret, then import it under a new name
|
|
567
|
+
SECRET=$(dot account inspect dave --show-secret --json | jq -r .privateKey)
|
|
568
|
+
dot account add raw-dave --secret "$SECRET"
|
|
569
|
+
# raw-dave now has the same address as dave and can sign
|
|
570
|
+
|
|
571
|
+
# Or from an environment variable (secret stays off disk)
|
|
572
|
+
dot account add server-signer --env PROXY_PRIVATE_KEY
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
A raw private key cannot be HD-derived, so `--path` is rejected for this format. Imported expanded-secret accounts sign exactly like mnemonic-backed ones.
|
|
515
576
|
|
|
516
577
|
#### Export/import accounts
|
|
517
578
|
|
|
@@ -659,6 +720,40 @@ dot polkadot-asset-hub.query.Assets.Metadata 1984
|
|
|
659
720
|
# }
|
|
660
721
|
```
|
|
661
722
|
|
|
723
|
+
#### Historical reads — `--at <block>`
|
|
724
|
+
|
|
725
|
+
Storage queries default to the latest finalized head. Pass `--at` to read
|
|
726
|
+
state at a specific block hash, the chain head (`best`), or `finalized`
|
|
727
|
+
(explicit). Accepted on both `query.*` and `apis.*` runtime calls.
|
|
728
|
+
|
|
729
|
+
```bash
|
|
730
|
+
# Read at the current best (non-finalized) head — useful for low-latency reads
|
|
731
|
+
dot polkadot.query.System.Number --at best
|
|
732
|
+
|
|
733
|
+
# Read at the last finalized block — same as the default, but explicit
|
|
734
|
+
dot polkadot.query.System.Number --at finalized
|
|
735
|
+
|
|
736
|
+
# Pin a finalized hash and read multiple items at that exact block
|
|
737
|
+
HASH=$(dot polkadot.rpc.chain_getFinalizedHead | tr -d '"')
|
|
738
|
+
dot polkadot.query.System.Number --at "$HASH"
|
|
739
|
+
dot polkadot.apis.Core.version --at "$HASH" --json | jq .spec_version
|
|
740
|
+
```
|
|
741
|
+
|
|
742
|
+
`--at` accepts a 32-byte `0x…` block hash, `"best"`, or `"finalized"`.
|
|
743
|
+
Anything else errors before any network call. Tx submission rejects `"best"`.
|
|
744
|
+
|
|
745
|
+
> **Archive-only blocks**: papi v2 talks to the `chainHead_v1_*` JSON-RPC API,
|
|
746
|
+
> which only serves *pinned* (recent) blocks. Querying a hash older than a
|
|
747
|
+
> few minutes against a non-archive node fails with a clean error that
|
|
748
|
+
> includes a copy-pasteable `--rpc wss://<archive-endpoint>` hint:
|
|
749
|
+
>
|
|
750
|
+
> ```
|
|
751
|
+
> ⚠ 0x… is not available on the current RPC endpoint.
|
|
752
|
+
> Public nodes serve only recent (pinned) blocks via chainHead_v1_*.
|
|
753
|
+
> For deep historical reads, point --rpc at an archive endpoint, e.g.:
|
|
754
|
+
> dot ... --at 0x… --rpc wss://<archive-endpoint>
|
|
755
|
+
> ```
|
|
756
|
+
|
|
662
757
|
### Look up constants
|
|
663
758
|
|
|
664
759
|
```bash
|
|
@@ -1340,7 +1435,7 @@ Override low-level transaction parameters. Useful for rapid-fire submission (cus
|
|
|
1340
1435
|
| `--nonce <n>` | non-negative integer | Override the auto-detected nonce |
|
|
1341
1436
|
| `--tip <amount>` | non-negative integer (planck) | Priority tip for the transaction pool |
|
|
1342
1437
|
| `--mortality <spec>` | `immortal` or period (min 4) | Transaction mortality window |
|
|
1343
|
-
| `--at <block>` | 0x-prefixed block hash | Block
|
|
1438
|
+
| `--at <block>` | 0x-prefixed block hash, `"best"`, or `"finalized"` | Block to read/validate against (defaults to finalized). Also honored on `query.*` and `apis.*` for historical reads; tx submission rejects `"best"`. |
|
|
1344
1439
|
|
|
1345
1440
|
```bash
|
|
1346
1441
|
# Fire-and-forget: submit two txs in rapid succession with manual nonces
|
|
@@ -1626,7 +1721,7 @@ All existing flags work with file input — `--chain` overrides the file's `chai
|
|
|
1626
1721
|
|
|
1627
1722
|
### Compute hashes
|
|
1628
1723
|
|
|
1629
|
-
Compute cryptographic hashes commonly used in Substrate. Supports BLAKE2b-256, BLAKE2b-128, Keccak-256, and
|
|
1724
|
+
Compute cryptographic hashes commonly used in Substrate. Supports BLAKE2b-256, BLAKE2b-128, Keccak-256, SHA-256, and the XXH64-based `twox64` / `twox128` / `twox256` family used to build Substrate storage keys.
|
|
1630
1725
|
|
|
1631
1726
|
```bash
|
|
1632
1727
|
# Hash hex-encoded data
|
|
@@ -1655,6 +1750,16 @@ dot hash blake2b256 0xdeadbeef --json
|
|
|
1655
1750
|
# "input": "0xdeadbeef",
|
|
1656
1751
|
# "hash": "0xf3e925002fed7cc0ded46842569eb5c90c910c091d8d04a1bdf96e0db719fd91"
|
|
1657
1752
|
# }
|
|
1753
|
+
|
|
1754
|
+
# Substrate twox128 — pallet/storage prefix used everywhere in Substrate state
|
|
1755
|
+
dot hash twox128 System
|
|
1756
|
+
# Output:
|
|
1757
|
+
# 0x26aa394eea5630e07c48ae0c9558cef7
|
|
1758
|
+
|
|
1759
|
+
# Build a full storage key for `System.Number` and read it raw via JSON-RPC
|
|
1760
|
+
PALLET=$(dot hash twox128 System)
|
|
1761
|
+
ITEM=$(dot hash twox128 Number)
|
|
1762
|
+
dot polkadot.rpc.state_getStorage "${PALLET}${ITEM:2}"
|
|
1658
1763
|
```
|
|
1659
1764
|
|
|
1660
1765
|
Run `dot hash` with no arguments to see all available algorithms.
|
|
@@ -1793,7 +1898,7 @@ dot verifiable alice
|
|
|
1793
1898
|
# Bandersnatch Member Key
|
|
1794
1899
|
#
|
|
1795
1900
|
# Account: alice
|
|
1796
|
-
# Member Key:
|
|
1901
|
+
# Member Key: 0xbb6ee099b568f1844d62fc00e6305c2e83aa8da30ce59e664ef39e089204d43c
|
|
1797
1902
|
|
|
1798
1903
|
# Derive keyed member key (full person — "candidate" context)
|
|
1799
1904
|
dot verifiable alice --context candidate
|
|
@@ -1802,7 +1907,7 @@ dot verifiable alice --context candidate
|
|
|
1802
1907
|
#
|
|
1803
1908
|
# Account: alice
|
|
1804
1909
|
# Context: candidate
|
|
1805
|
-
# Member Key:
|
|
1910
|
+
# Member Key: 0x5f915576987547d3e55bb4129ac8cae1d338f8933073dc74272b4c825f738592
|
|
1806
1911
|
|
|
1807
1912
|
# Arbitrary context string
|
|
1808
1913
|
dot verifiable alice --context pps
|
package/dist/cli.mjs
CHANGED
|
@@ -22,6 +22,12 @@ function isLikelyStaleMetadataError(err) {
|
|
|
22
22
|
return false;
|
|
23
23
|
return STALE_METADATA_PATTERNS.some((re) => re.test(msg));
|
|
24
24
|
}
|
|
25
|
+
function isBlockUnavailableError(err) {
|
|
26
|
+
const msg = err instanceof Error ? err.message : typeof err === "string" ? err : "";
|
|
27
|
+
if (!msg)
|
|
28
|
+
return false;
|
|
29
|
+
return BLOCK_UNAVAILABLE_PATTERNS.some((re) => re.test(msg));
|
|
30
|
+
}
|
|
25
31
|
function formatRuntimeError(err) {
|
|
26
32
|
const msg = err instanceof Error ? err.message : String(err);
|
|
27
33
|
if (/wasm trap|wasm `?unreachable`? instruction|Execution aborted due to trap/i.test(msg)) {
|
|
@@ -40,7 +46,7 @@ function formatRuntimeError(err) {
|
|
|
40
46
|
}
|
|
41
47
|
return msg;
|
|
42
48
|
}
|
|
43
|
-
var CliError, ConnectionError, MetadataError, STALE_METADATA_PATTERNS;
|
|
49
|
+
var CliError, ConnectionError, MetadataError, STALE_METADATA_PATTERNS, BLOCK_UNAVAILABLE_PATTERNS;
|
|
44
50
|
var init_errors = __esm(() => {
|
|
45
51
|
CliError = class CliError extends Error {
|
|
46
52
|
constructor(message) {
|
|
@@ -69,6 +75,11 @@ var init_errors = __esm(() => {
|
|
|
69
75
|
/Lookup failed/i,
|
|
70
76
|
/metadata.*mismatch/i
|
|
71
77
|
];
|
|
78
|
+
BLOCK_UNAVAILABLE_PATTERNS = [
|
|
79
|
+
/is not pinned/i,
|
|
80
|
+
/Invalid BlockHash/i,
|
|
81
|
+
/UnknownBlock.*Header was not found/i
|
|
82
|
+
];
|
|
72
83
|
});
|
|
73
84
|
|
|
74
85
|
// src/utils/runtime-fingerprint.ts
|
|
@@ -450,6 +461,7 @@ function suggestMessage(kind, input, candidates) {
|
|
|
450
461
|
}
|
|
451
462
|
|
|
452
463
|
// src/core/accounts.ts
|
|
464
|
+
import { hexToBytes as nobleHexToBytes } from "@noble/hashes/utils.js";
|
|
453
465
|
import { sr25519CreateDerive } from "@polkadot-labs/hdkd";
|
|
454
466
|
import {
|
|
455
467
|
DEV_PHRASE,
|
|
@@ -460,7 +472,7 @@ import {
|
|
|
460
472
|
ss58Decode,
|
|
461
473
|
validateMnemonic
|
|
462
474
|
} from "@polkadot-labs/hdkd-helpers";
|
|
463
|
-
import { HDKD, secretFromSeed } from "@scure/sr25519";
|
|
475
|
+
import { getPublicKey, HDKD, secretFromSeed, sign } from "@scure/sr25519";
|
|
464
476
|
import { getPolkadotSigner } from "polkadot-api/signer";
|
|
465
477
|
function isDevAccount(name) {
|
|
466
478
|
return DEV_NAMES.includes(name.toLowerCase());
|
|
@@ -475,18 +487,54 @@ function deriveFromMnemonic(mnemonic, path) {
|
|
|
475
487
|
return derive(path);
|
|
476
488
|
}
|
|
477
489
|
function deriveFromHexSeed(hexSeed, path) {
|
|
478
|
-
const
|
|
479
|
-
const seed = new Uint8Array(clean.length / 2);
|
|
480
|
-
for (let i = 0;i < clean.length; i += 2) {
|
|
481
|
-
seed[i / 2] = parseInt(clean.substring(i, i + 2), 16);
|
|
482
|
-
}
|
|
483
|
-
const derive = sr25519CreateDerive(seed);
|
|
490
|
+
const derive = sr25519CreateDerive(hexToBytes(hexSeed));
|
|
484
491
|
return derive(path);
|
|
485
492
|
}
|
|
486
493
|
function getDevKeypair(name) {
|
|
487
494
|
const path = devDerivationPath(name);
|
|
488
495
|
return deriveFromMnemonic(DEV_PHRASE, path);
|
|
489
496
|
}
|
|
497
|
+
function hexToBytes(hex) {
|
|
498
|
+
return nobleHexToBytes(hex.startsWith("0x") ? hex.slice(2) : hex);
|
|
499
|
+
}
|
|
500
|
+
function isExpandedSecret(secret) {
|
|
501
|
+
return EXPANDED_SECRET_RE.test(secret);
|
|
502
|
+
}
|
|
503
|
+
function isHexSeed(secret) {
|
|
504
|
+
return HEX_SEED_RE.test(secret);
|
|
505
|
+
}
|
|
506
|
+
function secretKind(secret) {
|
|
507
|
+
if (isExpandedSecret(secret))
|
|
508
|
+
return "expanded";
|
|
509
|
+
if (isHexSeed(secret))
|
|
510
|
+
return "seed";
|
|
511
|
+
return "mnemonic";
|
|
512
|
+
}
|
|
513
|
+
function assertNoPathForExpandedSecret(derivationPath) {
|
|
514
|
+
if (derivationPath) {
|
|
515
|
+
throw new Error("Stored account has a 64-byte expanded secret with a derivation path, which cannot be applied. An expanded secret cannot be HD-derived; remove the derivationPath from accounts.json.");
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
function keypairFromExpandedSecret(secret) {
|
|
519
|
+
return {
|
|
520
|
+
publicKey: getPublicKey(secret),
|
|
521
|
+
sign: (msg) => sign(secret, msg)
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
function keypairFromSecret(secret, derivationPath = "") {
|
|
525
|
+
if (isExpandedSecret(secret)) {
|
|
526
|
+
assertNoPathForExpandedSecret(derivationPath);
|
|
527
|
+
return keypairFromExpandedSecret(hexToBytes(secret));
|
|
528
|
+
}
|
|
529
|
+
return isHexSeed(secret) ? deriveFromHexSeed(secret, derivationPath) : deriveFromMnemonic(secret, derivationPath);
|
|
530
|
+
}
|
|
531
|
+
function expandedSecretFromStored(secret, derivationPath = "") {
|
|
532
|
+
if (isExpandedSecret(secret)) {
|
|
533
|
+
assertNoPathForExpandedSecret(derivationPath);
|
|
534
|
+
return hexToBytes(secret);
|
|
535
|
+
}
|
|
536
|
+
return deriveExpandedSecret(miniSecretFromSecret(secret), derivationPath);
|
|
537
|
+
}
|
|
490
538
|
function parseDerivations(path) {
|
|
491
539
|
const out = [];
|
|
492
540
|
for (const [, type, code] of path.matchAll(DERIVATION_RE)) {
|
|
@@ -517,17 +565,11 @@ function deriveExpandedSecret(miniSecret, path) {
|
|
|
517
565
|
return parseDerivations(path).reduce((sk, [type, code]) => type === "hard" ? HDKD.secretHard(sk, createChainCode(code)) : HDKD.secretSoft(sk, createChainCode(code)), secretFromSeed(miniSecret));
|
|
518
566
|
}
|
|
519
567
|
function miniSecretFromSecret(secret) {
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
const clean = secret.slice(2);
|
|
523
|
-
const bytes = new Uint8Array(32);
|
|
524
|
-
for (let i = 0;i < clean.length; i += 2) {
|
|
525
|
-
bytes[i / 2] = parseInt(clean.substring(i, i + 2), 16);
|
|
526
|
-
}
|
|
527
|
-
return bytes;
|
|
568
|
+
if (isHexSeed(secret)) {
|
|
569
|
+
return hexToBytes(secret);
|
|
528
570
|
}
|
|
529
571
|
if (!validateMnemonic(secret)) {
|
|
530
|
-
throw new Error("Invalid secret. Expected a 0x-prefixed 32-byte hex seed
|
|
572
|
+
throw new Error("Invalid secret. Expected a BIP39 mnemonic or a 0x-prefixed 32-byte hex seed.");
|
|
531
573
|
}
|
|
532
574
|
return entropyToMiniSecret(mnemonicToEntropy(secret));
|
|
533
575
|
}
|
|
@@ -544,13 +586,19 @@ function createNewAccount(path = "") {
|
|
|
544
586
|
return { mnemonic, publicKey: keypair.publicKey };
|
|
545
587
|
}
|
|
546
588
|
function importAccount(secret, path = "") {
|
|
547
|
-
|
|
548
|
-
|
|
589
|
+
if (isExpandedSecret(secret)) {
|
|
590
|
+
if (path) {
|
|
591
|
+
throw new Error("Derivation paths are not supported for raw private key (64-byte expanded secret) import. An expanded secret cannot be HD-derived; omit --path.");
|
|
592
|
+
}
|
|
593
|
+
const keypair2 = keypairFromExpandedSecret(hexToBytes(secret));
|
|
594
|
+
return { publicKey: keypair2.publicKey };
|
|
595
|
+
}
|
|
596
|
+
if (isHexSeed(secret)) {
|
|
549
597
|
const keypair2 = deriveFromHexSeed(secret, path);
|
|
550
598
|
return { publicKey: keypair2.publicKey };
|
|
551
599
|
}
|
|
552
600
|
if (!validateMnemonic(secret)) {
|
|
553
|
-
throw new Error("Invalid secret. Expected a 0x-prefixed 32-byte hex seed or a
|
|
601
|
+
throw new Error("Invalid secret. Expected a BIP39 mnemonic, a 0x-prefixed 32-byte hex seed, or a 0x-prefixed 64-byte sr25519 expanded secret.");
|
|
554
602
|
}
|
|
555
603
|
const keypair = deriveFromMnemonic(secret, path);
|
|
556
604
|
return { publicKey: keypair.publicKey };
|
|
@@ -616,9 +664,7 @@ async function resolveAccountKeypair(name) {
|
|
|
616
664
|
if (account.secret === undefined) {
|
|
617
665
|
throw new Error(`Account "${name}" is watch-only (no secret). Cannot sign. Import with --secret or --env.`);
|
|
618
666
|
}
|
|
619
|
-
|
|
620
|
-
const isHexSeed = /^0x[0-9a-fA-F]{64}$/.test(secret);
|
|
621
|
-
return isHexSeed ? deriveFromHexSeed(secret, account.derivationPath) : deriveFromMnemonic(secret, account.derivationPath);
|
|
667
|
+
return keypairFromSecret(resolveSecret(account.secret), account.derivationPath);
|
|
622
668
|
}
|
|
623
669
|
async function resolveAccountSigner(name) {
|
|
624
670
|
const keypair = await resolveAccountKeypair(name);
|
|
@@ -626,8 +672,8 @@ async function resolveAccountSigner(name) {
|
|
|
626
672
|
}
|
|
627
673
|
async function resolveAccountExpandedSecret(name) {
|
|
628
674
|
if (isDevAccount(name)) {
|
|
629
|
-
const
|
|
630
|
-
return deriveExpandedSecret(
|
|
675
|
+
const miniSecret = entropyToMiniSecret(mnemonicToEntropy(DEV_PHRASE));
|
|
676
|
+
return deriveExpandedSecret(miniSecret, devDerivationPath(name));
|
|
631
677
|
}
|
|
632
678
|
const accountsFile = await loadAccounts();
|
|
633
679
|
const account = findAccount(accountsFile, name);
|
|
@@ -644,16 +690,17 @@ async function resolveAccountExpandedSecret(name) {
|
|
|
644
690
|
if (account.secret === undefined) {
|
|
645
691
|
throw new Error(`Account "${name}" is watch-only (no secret). Cannot derive private key. Import with --secret or --env.`);
|
|
646
692
|
}
|
|
647
|
-
|
|
648
|
-
return deriveExpandedSecret(miniSecret, account.derivationPath);
|
|
693
|
+
return expandedSecretFromStored(resolveSecret(account.secret), account.derivationPath);
|
|
649
694
|
}
|
|
650
695
|
function bytesToHex(bytes) {
|
|
651
696
|
return "0x" + Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
652
697
|
}
|
|
653
|
-
var DEV_NAMES, DERIVATION_RE;
|
|
698
|
+
var DEV_NAMES, EXPANDED_SECRET_RE, HEX_SEED_RE, DERIVATION_RE;
|
|
654
699
|
var init_accounts = __esm(() => {
|
|
655
700
|
init_accounts_store();
|
|
656
701
|
DEV_NAMES = ["alice", "bob", "charlie", "dave", "eve", "ferdie"];
|
|
702
|
+
EXPANDED_SECRET_RE = /^0x[0-9a-fA-F]{128}$/;
|
|
703
|
+
HEX_SEED_RE = /^0x[0-9a-fA-F]{64}$/;
|
|
657
704
|
DERIVATION_RE = /(\/{1,2})([^/]+)/g;
|
|
658
705
|
});
|
|
659
706
|
|
|
@@ -1253,7 +1300,7 @@ async function fetchMetadataFromChain(clientHandle, chainName) {
|
|
|
1253
1300
|
let bytes;
|
|
1254
1301
|
try {
|
|
1255
1302
|
const hex = await withTimeout(client._request("state_call", ["Metadata_metadata_at_version", v15Arg]), chainName);
|
|
1256
|
-
const raw =
|
|
1303
|
+
const raw = hexToBytes3(hex);
|
|
1257
1304
|
const decoded = optionalOpaqueBytes.dec(raw);
|
|
1258
1305
|
if (decoded !== undefined) {
|
|
1259
1306
|
bytes = new Uint8Array(decoded);
|
|
@@ -1262,7 +1309,7 @@ async function fetchMetadataFromChain(clientHandle, chainName) {
|
|
|
1262
1309
|
if (!bytes) {
|
|
1263
1310
|
try {
|
|
1264
1311
|
const hex = await withTimeout(client._request("state_getMetadata", []), chainName);
|
|
1265
|
-
bytes =
|
|
1312
|
+
bytes = hexToBytes3(hex);
|
|
1266
1313
|
} catch (err) {
|
|
1267
1314
|
if (err instanceof ConnectionError)
|
|
1268
1315
|
throw err;
|
|
@@ -1311,6 +1358,24 @@ async function withStalenessSuggestion(chainName, clientHandle, task) {
|
|
|
1311
1358
|
` + ` Run: dot chain update ${chainName}`);
|
|
1312
1359
|
}
|
|
1313
1360
|
}
|
|
1361
|
+
async function withBlockAvailabilityHint(atRaw, task) {
|
|
1362
|
+
try {
|
|
1363
|
+
return await task();
|
|
1364
|
+
} catch (err) {
|
|
1365
|
+
if (!isBlockUnavailableError(err))
|
|
1366
|
+
throw err;
|
|
1367
|
+
const original = err instanceof Error ? err.message : String(err);
|
|
1368
|
+
const isExplicitHash = atRaw && atRaw !== "best" && atRaw !== "finalized";
|
|
1369
|
+
const target = isExplicitHash ? atRaw : "the requested block";
|
|
1370
|
+
const exampleAt = isExplicitHash ? atRaw : "<hash>";
|
|
1371
|
+
throw new CliError(`${original}
|
|
1372
|
+
|
|
1373
|
+
` + `⚠ ${target} is not available on the current RPC endpoint.
|
|
1374
|
+
` + ` Public nodes serve only recent (pinned) blocks via chainHead_v1_*.
|
|
1375
|
+
` + ` For deep historical reads, point --rpc at an archive endpoint, e.g.:
|
|
1376
|
+
` + ` dot ... --at ${exampleAt} --rpc wss://<archive-endpoint>`);
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1314
1379
|
async function getOrFetchMetadata(chainName, clientHandle) {
|
|
1315
1380
|
let raw = await loadMetadata(chainName);
|
|
1316
1381
|
if (!raw) {
|
|
@@ -1440,7 +1505,7 @@ function describeCallArgs(meta, palletName, callName) {
|
|
|
1440
1505
|
function describeEventFields(meta, palletName, eventName) {
|
|
1441
1506
|
return compactArgsString(getEventFields(meta, palletName, eventName));
|
|
1442
1507
|
}
|
|
1443
|
-
function
|
|
1508
|
+
function hexToBytes3(hex) {
|
|
1444
1509
|
const clean = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
1445
1510
|
const bytes = new Uint8Array(clean.length / 2);
|
|
1446
1511
|
for (let i = 0;i < clean.length; i += 2) {
|
|
@@ -1535,6 +1600,15 @@ import { compact as scaleCompact } from "@polkadot-api/substrate-bindings";
|
|
|
1535
1600
|
import { getViewBuilder } from "@polkadot-api/view-builder";
|
|
1536
1601
|
import { Binary as Binary2 } from "polkadot-api";
|
|
1537
1602
|
import { stringify as stringifyYaml } from "yaml";
|
|
1603
|
+
function parseAtForRead(raw) {
|
|
1604
|
+
if (raw === undefined)
|
|
1605
|
+
return;
|
|
1606
|
+
if (raw === "best" || raw === "finalized")
|
|
1607
|
+
return raw;
|
|
1608
|
+
if (/^0x[0-9a-fA-F]{64}$/.test(raw))
|
|
1609
|
+
return raw;
|
|
1610
|
+
throw new CliError(`Invalid --at value "${raw}". Use "best", "finalized", or a 0x-prefixed 32-byte block hash.`);
|
|
1611
|
+
}
|
|
1538
1612
|
async function parseStructArgs(meta, fields, args, callLabel) {
|
|
1539
1613
|
const fieldNames = Object.keys(fields);
|
|
1540
1614
|
if (args.length !== fieldNames.length) {
|
|
@@ -1943,8 +2017,10 @@ async function handleApis(target, args, opts) {
|
|
|
1943
2017
|
typeof opts.parsedArgs === "object" ? JSON.stringify(opts.parsedArgs) : String(opts.parsedArgs)
|
|
1944
2018
|
];
|
|
1945
2019
|
const parsedArgs = await parseRuntimeApiArgs(meta, method, effectiveArgs);
|
|
2020
|
+
const atArg = parseAtForRead(opts.at);
|
|
2021
|
+
const pullOpts = atArg !== undefined ? [{ at: atArg }] : [];
|
|
1946
2022
|
const unsafeApi = clientHandle.client.getUnsafeApi();
|
|
1947
|
-
const result = await unsafeApi.apis[api.name][method.name](...parsedArgs);
|
|
2023
|
+
const result = await withBlockAvailabilityHint(opts.at, () => unsafeApi.apis[api.name][method.name](...parsedArgs, ...pullOpts));
|
|
1948
2024
|
const format = isJsonOutput(opts) ? "json" : opts.output ?? "pretty";
|
|
1949
2025
|
printResult(result, format);
|
|
1950
2026
|
} finally {
|
|
@@ -3067,11 +3143,98 @@ var init_rpc_registry = __esm(() => {
|
|
|
3067
3143
|
};
|
|
3068
3144
|
});
|
|
3069
3145
|
|
|
3146
|
+
// src/core/xxh64.ts
|
|
3147
|
+
function rotl(v, r) {
|
|
3148
|
+
return (v << r | v >> 64n - r) & MASK;
|
|
3149
|
+
}
|
|
3150
|
+
function round(acc, val) {
|
|
3151
|
+
acc = acc + val * P2 & MASK;
|
|
3152
|
+
acc = rotl(acc, 31n);
|
|
3153
|
+
return acc * P1 & MASK;
|
|
3154
|
+
}
|
|
3155
|
+
function mergeRound(h, val) {
|
|
3156
|
+
const k = round(0n, val);
|
|
3157
|
+
return (h ^ k) * P1 + P4 & MASK;
|
|
3158
|
+
}
|
|
3159
|
+
function readU64LE(data, p) {
|
|
3160
|
+
return BigInt(data[p]) | BigInt(data[p + 1]) << 8n | BigInt(data[p + 2]) << 16n | BigInt(data[p + 3]) << 24n | BigInt(data[p + 4]) << 32n | BigInt(data[p + 5]) << 40n | BigInt(data[p + 6]) << 48n | BigInt(data[p + 7]) << 56n;
|
|
3161
|
+
}
|
|
3162
|
+
function readU32LE(data, p) {
|
|
3163
|
+
return BigInt(data[p]) | BigInt(data[p + 1]) << 8n | BigInt(data[p + 2]) << 16n | BigInt(data[p + 3]) << 24n;
|
|
3164
|
+
}
|
|
3165
|
+
function xxh64(input, seed = 0n) {
|
|
3166
|
+
const len = input.length;
|
|
3167
|
+
let p = 0;
|
|
3168
|
+
let h;
|
|
3169
|
+
if (len >= 32) {
|
|
3170
|
+
let v1 = seed + P1 + P2 & MASK;
|
|
3171
|
+
let v2 = seed + P2 & MASK;
|
|
3172
|
+
let v3 = seed & MASK;
|
|
3173
|
+
let v4 = seed - P1 & MASK;
|
|
3174
|
+
while (p <= len - 32) {
|
|
3175
|
+
v1 = round(v1, readU64LE(input, p));
|
|
3176
|
+
p += 8;
|
|
3177
|
+
v2 = round(v2, readU64LE(input, p));
|
|
3178
|
+
p += 8;
|
|
3179
|
+
v3 = round(v3, readU64LE(input, p));
|
|
3180
|
+
p += 8;
|
|
3181
|
+
v4 = round(v4, readU64LE(input, p));
|
|
3182
|
+
p += 8;
|
|
3183
|
+
}
|
|
3184
|
+
h = rotl(v1, 1n) + rotl(v2, 7n) + rotl(v3, 12n) + rotl(v4, 18n) & MASK;
|
|
3185
|
+
h = mergeRound(h, v1);
|
|
3186
|
+
h = mergeRound(h, v2);
|
|
3187
|
+
h = mergeRound(h, v3);
|
|
3188
|
+
h = mergeRound(h, v4);
|
|
3189
|
+
} else {
|
|
3190
|
+
h = seed + P5 & MASK;
|
|
3191
|
+
}
|
|
3192
|
+
h = h + BigInt(len) & MASK;
|
|
3193
|
+
while (p + 8 <= len) {
|
|
3194
|
+
const k = round(0n, readU64LE(input, p));
|
|
3195
|
+
h = rotl(h ^ k, 27n) * P1 + P4 & MASK;
|
|
3196
|
+
p += 8;
|
|
3197
|
+
}
|
|
3198
|
+
if (p + 4 <= len) {
|
|
3199
|
+
const k = readU32LE(input, p) * P1 & MASK;
|
|
3200
|
+
h = rotl(h ^ k, 23n) * P2 + P3 & MASK;
|
|
3201
|
+
p += 4;
|
|
3202
|
+
}
|
|
3203
|
+
while (p < len) {
|
|
3204
|
+
const k = BigInt(input[p]) * P5 & MASK;
|
|
3205
|
+
h = rotl(h ^ k, 11n) * P1 & MASK;
|
|
3206
|
+
p++;
|
|
3207
|
+
}
|
|
3208
|
+
h ^= h >> 33n;
|
|
3209
|
+
h = h * P2 & MASK;
|
|
3210
|
+
h ^= h >> 29n;
|
|
3211
|
+
h = h * P3 & MASK;
|
|
3212
|
+
h ^= h >> 32n;
|
|
3213
|
+
return h;
|
|
3214
|
+
}
|
|
3215
|
+
function u64ToLEBytes(v, out, offset) {
|
|
3216
|
+
for (let i = 0;i < 8; i++) {
|
|
3217
|
+
out[offset + i] = Number(v >> BigInt(i * 8) & 0xffn);
|
|
3218
|
+
}
|
|
3219
|
+
}
|
|
3220
|
+
function twox(input, bits) {
|
|
3221
|
+
const lanes = bits / 64;
|
|
3222
|
+
const out = new Uint8Array(bits / 8);
|
|
3223
|
+
for (let i = 0;i < lanes; i++) {
|
|
3224
|
+
u64ToLEBytes(xxh64(input, BigInt(i)), out, i * 8);
|
|
3225
|
+
}
|
|
3226
|
+
return out;
|
|
3227
|
+
}
|
|
3228
|
+
var MASK, P1 = 11400714785074694791n, P2 = 14029467366897019727n, P3 = 1609587929392839161n, P4 = 9650029242287828579n, P5 = 2870177450012600261n;
|
|
3229
|
+
var init_xxh64 = __esm(() => {
|
|
3230
|
+
MASK = (1n << 64n) - 1n;
|
|
3231
|
+
});
|
|
3232
|
+
|
|
3070
3233
|
// src/core/hash.ts
|
|
3071
3234
|
import { blake2b as blake2b2 } from "@noble/hashes/blake2.js";
|
|
3072
3235
|
import { sha256 } from "@noble/hashes/sha2.js";
|
|
3073
|
-
import { keccak_256 } from "@noble/hashes/sha3.js";
|
|
3074
|
-
import { bytesToHex as
|
|
3236
|
+
import { keccak_256 as keccak_2562 } from "@noble/hashes/sha3.js";
|
|
3237
|
+
import { bytesToHex as bytesToHex3, hexToBytes as hexToBytes4 } from "@noble/hashes/utils.js";
|
|
3075
3238
|
function computeHash(algorithm, data) {
|
|
3076
3239
|
const algo = ALGORITHMS[algorithm];
|
|
3077
3240
|
if (!algo) {
|
|
@@ -3085,12 +3248,12 @@ function parseInputData(input) {
|
|
|
3085
3248
|
if (hex.length % 2 !== 0) {
|
|
3086
3249
|
throw new Error(`Invalid hex input: odd number of characters`);
|
|
3087
3250
|
}
|
|
3088
|
-
return
|
|
3251
|
+
return hexToBytes4(hex);
|
|
3089
3252
|
}
|
|
3090
3253
|
return new TextEncoder().encode(input);
|
|
3091
3254
|
}
|
|
3092
3255
|
function toHex2(bytes) {
|
|
3093
|
-
return `0x${
|
|
3256
|
+
return `0x${bytesToHex3(bytes)}`;
|
|
3094
3257
|
}
|
|
3095
3258
|
function isValidAlgorithm(name) {
|
|
3096
3259
|
return name in ALGORITHMS;
|
|
@@ -3100,6 +3263,7 @@ function getAlgorithmNames() {
|
|
|
3100
3263
|
}
|
|
3101
3264
|
var ALGORITHMS;
|
|
3102
3265
|
var init_hash = __esm(() => {
|
|
3266
|
+
init_xxh64();
|
|
3103
3267
|
ALGORITHMS = {
|
|
3104
3268
|
blake2b256: {
|
|
3105
3269
|
compute: (data) => blake2b2(data, { dkLen: 32 }),
|
|
@@ -3112,7 +3276,7 @@ var init_hash = __esm(() => {
|
|
|
3112
3276
|
description: "BLAKE2b with 128-bit output"
|
|
3113
3277
|
},
|
|
3114
3278
|
keccak256: {
|
|
3115
|
-
compute: (data) =>
|
|
3279
|
+
compute: (data) => keccak_2562(data),
|
|
3116
3280
|
outputLen: 32,
|
|
3117
3281
|
description: "Keccak-256 (Ethereum-compatible)"
|
|
3118
3282
|
},
|
|
@@ -3120,6 +3284,21 @@ var init_hash = __esm(() => {
|
|
|
3120
3284
|
compute: (data) => sha256(data),
|
|
3121
3285
|
outputLen: 32,
|
|
3122
3286
|
description: "SHA-256"
|
|
3287
|
+
},
|
|
3288
|
+
twox64: {
|
|
3289
|
+
compute: (data) => twox(data, 64),
|
|
3290
|
+
outputLen: 8,
|
|
3291
|
+
description: "XXH64 with seed 0 (Substrate twox64)"
|
|
3292
|
+
},
|
|
3293
|
+
twox128: {
|
|
3294
|
+
compute: (data) => twox(data, 128),
|
|
3295
|
+
outputLen: 16,
|
|
3296
|
+
description: "XXH64 with seeds 0,1 (Substrate twox128, pallet/storage prefix)"
|
|
3297
|
+
},
|
|
3298
|
+
twox256: {
|
|
3299
|
+
compute: (data) => twox(data, 256),
|
|
3300
|
+
outputLen: 32,
|
|
3301
|
+
description: "XXH64 with seeds 0,1,2,3 (Substrate twox256)"
|
|
3123
3302
|
}
|
|
3124
3303
|
};
|
|
3125
3304
|
});
|
|
@@ -3517,13 +3696,73 @@ var init_complete = __esm(() => {
|
|
|
3517
3696
|
// src/cli.ts
|
|
3518
3697
|
import cac from "cac";
|
|
3519
3698
|
// package.json
|
|
3520
|
-
var version = "1.
|
|
3699
|
+
var version = "1.20.0";
|
|
3521
3700
|
|
|
3522
3701
|
// src/commands/account.ts
|
|
3523
3702
|
init_accounts_store();
|
|
3524
3703
|
init_accounts();
|
|
3525
|
-
init_output();
|
|
3526
3704
|
import { readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
|
|
3705
|
+
import { hexToBytes as nobleHexToBytes2 } from "@noble/hashes/utils.js";
|
|
3706
|
+
|
|
3707
|
+
// src/core/h160.ts
|
|
3708
|
+
import { keccak_256 } from "@noble/hashes/sha3.js";
|
|
3709
|
+
import { bytesToHex as bytesToHex2, hexToBytes as hexToBytes2 } from "@noble/hashes/utils.js";
|
|
3710
|
+
var ETH_DERIVED_SUFFIX_BYTE = 238;
|
|
3711
|
+
var H160_LEN = 20;
|
|
3712
|
+
var ACCOUNT_ID_LEN = 32;
|
|
3713
|
+
function hasEthDerivedSuffix(accountId) {
|
|
3714
|
+
if (accountId.length !== ACCOUNT_ID_LEN)
|
|
3715
|
+
return false;
|
|
3716
|
+
for (let i = H160_LEN;i < ACCOUNT_ID_LEN; i++) {
|
|
3717
|
+
if (accountId[i] !== ETH_DERIVED_SUFFIX_BYTE)
|
|
3718
|
+
return false;
|
|
3719
|
+
}
|
|
3720
|
+
return true;
|
|
3721
|
+
}
|
|
3722
|
+
function accountIdToH160(accountId) {
|
|
3723
|
+
if (accountId.length !== ACCOUNT_ID_LEN) {
|
|
3724
|
+
throw new Error(`accountIdToH160 expects 32 bytes, got ${accountId.length}`);
|
|
3725
|
+
}
|
|
3726
|
+
if (hasEthDerivedSuffix(accountId)) {
|
|
3727
|
+
return accountId.slice(0, H160_LEN);
|
|
3728
|
+
}
|
|
3729
|
+
return keccak_256(accountId).slice(ACCOUNT_ID_LEN - H160_LEN);
|
|
3730
|
+
}
|
|
3731
|
+
function h160ToFallbackAccountId(h160) {
|
|
3732
|
+
if (h160.length !== H160_LEN) {
|
|
3733
|
+
throw new Error(`h160ToFallbackAccountId expects 20 bytes, got ${h160.length}`);
|
|
3734
|
+
}
|
|
3735
|
+
const out = new Uint8Array(ACCOUNT_ID_LEN);
|
|
3736
|
+
out.set(h160, 0);
|
|
3737
|
+
out.fill(ETH_DERIVED_SUFFIX_BYTE, H160_LEN);
|
|
3738
|
+
return out;
|
|
3739
|
+
}
|
|
3740
|
+
function toEip55(h160) {
|
|
3741
|
+
if (h160.length !== H160_LEN) {
|
|
3742
|
+
throw new Error(`toEip55 expects 20 bytes, got ${h160.length}`);
|
|
3743
|
+
}
|
|
3744
|
+
const lowerHex = bytesToHex2(h160);
|
|
3745
|
+
const hashBytes = keccak_256(new TextEncoder().encode(lowerHex));
|
|
3746
|
+
let out = "0x";
|
|
3747
|
+
for (let i = 0;i < lowerHex.length; i++) {
|
|
3748
|
+
const c = lowerHex[i];
|
|
3749
|
+
const nibble = i % 2 === 0 ? hashBytes[i >> 1] >> 4 : hashBytes[i >> 1] & 15;
|
|
3750
|
+
out += nibble >= 8 ? c.toUpperCase() : c;
|
|
3751
|
+
}
|
|
3752
|
+
return out;
|
|
3753
|
+
}
|
|
3754
|
+
function isH160Hex(input) {
|
|
3755
|
+
return /^0x[0-9a-fA-F]{40}$/.test(input);
|
|
3756
|
+
}
|
|
3757
|
+
function h160FromHex(input) {
|
|
3758
|
+
if (!isH160Hex(input)) {
|
|
3759
|
+
throw new Error(`Not a valid 0x-prefixed 20-byte hex string: ${input}`);
|
|
3760
|
+
}
|
|
3761
|
+
return hexToBytes2(input.slice(2));
|
|
3762
|
+
}
|
|
3763
|
+
|
|
3764
|
+
// src/commands/account.ts
|
|
3765
|
+
init_output();
|
|
3527
3766
|
|
|
3528
3767
|
// src/core/pallet.ts
|
|
3529
3768
|
init_errors();
|
|
@@ -3594,7 +3833,8 @@ function isValidParaId(value) {
|
|
|
3594
3833
|
var ACCOUNT_HELP = `
|
|
3595
3834
|
${BOLD}Usage:${RESET}
|
|
3596
3835
|
$ dot account add <name> <ss58|hex> Add a watch-only address (no secret)
|
|
3597
|
-
$ dot account add <name> --secret <s> [--path <derivation>] Import from BIP39 mnemonic
|
|
3836
|
+
$ dot account add <name> --secret <s> [--path <derivation>] Import from BIP39 mnemonic or 32-byte hex seed
|
|
3837
|
+
$ dot account add <name> --secret 0x<128 hex> Import a raw 64-byte sr25519 private key (no --path)
|
|
3598
3838
|
$ dot account add <name> --env <VAR> [--path <derivation>] Import account backed by env variable
|
|
3599
3839
|
$ dot account add <name> --parachain <id> --parachain-type <t> Derive a parachain sovereign (t = child|sibling)
|
|
3600
3840
|
$ dot account add <name> --pallet-id <8 chars or 0x hex> Derive a pallet sovereign (e.g. py/trsry)
|
|
@@ -3611,6 +3851,7 @@ ${BOLD}Usage:${RESET}
|
|
|
3611
3851
|
${BOLD}Examples:${RESET}
|
|
3612
3852
|
$ dot account add treasury 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
|
|
3613
3853
|
$ dot account add treasury --secret "word1 word2 ... word12"
|
|
3854
|
+
$ dot account add raw-key --secret 0x<128-hex-char sr25519 expanded secret>
|
|
3614
3855
|
$ dot account add ci-signer --env MY_SECRET --path //ci
|
|
3615
3856
|
$ dot account add Treasury --pallet-id py/trsry
|
|
3616
3857
|
$ dot account add Bounties --pallet-id 0x70792f626f756e74
|
|
@@ -3638,16 +3879,21 @@ ${BOLD}Examples:${RESET}
|
|
|
3638
3879
|
|
|
3639
3880
|
${YELLOW}Note: Secrets are stored unencrypted in ~/.polkadot/accounts.json.
|
|
3640
3881
|
Use --env to keep secrets off disk entirely.
|
|
3641
|
-
|
|
3882
|
+
--secret accepts a BIP39 mnemonic, a 0x 32-byte hex seed, or a
|
|
3883
|
+
0x 64-byte raw sr25519 private key (the value --show-secret prints).
|
|
3884
|
+
Raw private keys cannot be HD-derived, so --path is rejected for them.${RESET}
|
|
3642
3885
|
`.trimStart();
|
|
3643
3886
|
function registerAccountCommands(cli) {
|
|
3644
|
-
cli.command("account [action] [...names]", "Manage local accounts (create, import, list, remove, export)").alias("accounts").option("--secret <value>", "Secret
|
|
3887
|
+
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) => {
|
|
3645
3888
|
if (!action) {
|
|
3646
3889
|
if (process.argv[2] === "accounts")
|
|
3647
3890
|
return accountList(opts);
|
|
3648
3891
|
console.log(ACCOUNT_HELP);
|
|
3649
3892
|
return;
|
|
3650
3893
|
}
|
|
3894
|
+
const rawSecret = rawArgValue("--secret");
|
|
3895
|
+
if (rawSecret != null)
|
|
3896
|
+
opts.secret = rawSecret;
|
|
3651
3897
|
switch (action) {
|
|
3652
3898
|
case "new":
|
|
3653
3899
|
case "create":
|
|
@@ -4226,6 +4472,7 @@ async function accountInspect(input, opts) {
|
|
|
4226
4472
|
let hasSecret = false;
|
|
4227
4473
|
let storedAccount;
|
|
4228
4474
|
let isDev = false;
|
|
4475
|
+
let isH160Fallback = false;
|
|
4229
4476
|
let virtualSource;
|
|
4230
4477
|
if (sovereignSource) {
|
|
4231
4478
|
if (sovereignSource.kind === "pallet") {
|
|
@@ -4273,18 +4520,24 @@ async function accountInspect(input, opts) {
|
|
|
4273
4520
|
}
|
|
4274
4521
|
} else if (isHexPublicKey(input)) {
|
|
4275
4522
|
publicKeyHex = input;
|
|
4523
|
+
} else if (isH160Hex(input)) {
|
|
4524
|
+
const fallback = h160ToFallbackAccountId(h160FromHex(input));
|
|
4525
|
+
publicKeyHex = publicKeyToHex(fallback);
|
|
4526
|
+
isH160Fallback = true;
|
|
4276
4527
|
} else {
|
|
4277
4528
|
try {
|
|
4278
4529
|
const decoded = fromSs58(input);
|
|
4279
4530
|
publicKeyHex = publicKeyToHex(decoded);
|
|
4280
4531
|
} catch {
|
|
4281
|
-
console.error(`Cannot identify "${input}" as an account name, SS58 address,
|
|
4532
|
+
console.error(`Cannot identify "${input}" as an account name, SS58 address, hex public key, or H160.`);
|
|
4282
4533
|
process.exit(1);
|
|
4283
4534
|
}
|
|
4284
4535
|
}
|
|
4285
4536
|
}
|
|
4286
4537
|
const ss58 = toSs58(publicKeyHex, prefix);
|
|
4538
|
+
const h160Hex = toEip55(accountIdToH160(nobleHexToBytes2(publicKeyHex.slice(2))));
|
|
4287
4539
|
let privateKeyHex;
|
|
4540
|
+
let revealedSecret;
|
|
4288
4541
|
if (opts.showSecret) {
|
|
4289
4542
|
if (!name) {
|
|
4290
4543
|
console.error("--show-secret requires an account name; raw addresses and hex keys have no secret to reveal.");
|
|
@@ -4300,6 +4553,14 @@ async function accountInspect(input, opts) {
|
|
|
4300
4553
|
console.error(err.message);
|
|
4301
4554
|
process.exit(1);
|
|
4302
4555
|
}
|
|
4556
|
+
if (storedAccount?.secret !== undefined && !isEnvSecret(storedAccount.secret)) {
|
|
4557
|
+
const kind = secretKind(storedAccount.secret);
|
|
4558
|
+
if (kind === "mnemonic") {
|
|
4559
|
+
revealedSecret = { label: "Mnemonic", field: "mnemonic", value: storedAccount.secret };
|
|
4560
|
+
} else if (kind === "seed") {
|
|
4561
|
+
revealedSecret = { label: "Seed", field: "seed", value: storedAccount.secret };
|
|
4562
|
+
}
|
|
4563
|
+
}
|
|
4303
4564
|
}
|
|
4304
4565
|
let kindLabel;
|
|
4305
4566
|
let sourceLine;
|
|
@@ -4314,6 +4575,8 @@ async function accountInspect(input, opts) {
|
|
|
4314
4575
|
sourceLine = `parachain ${virtualSource.paraId}`;
|
|
4315
4576
|
} else if (isDev) {
|
|
4316
4577
|
kindLabel = "dev";
|
|
4578
|
+
} else if (isH160Fallback) {
|
|
4579
|
+
kindLabel = "revive H160 fallback";
|
|
4317
4580
|
} else if (storedAccount) {
|
|
4318
4581
|
const k = classifyAccount(storedAccount);
|
|
4319
4582
|
if (k === "pallet" && storedAccount.source?.kind === "pallet") {
|
|
@@ -4335,7 +4598,12 @@ async function accountInspect(input, opts) {
|
|
|
4335
4598
|
}
|
|
4336
4599
|
}
|
|
4337
4600
|
if (isJsonOutput(opts)) {
|
|
4338
|
-
const result = {
|
|
4601
|
+
const result = {
|
|
4602
|
+
publicKey: publicKeyHex,
|
|
4603
|
+
ss58,
|
|
4604
|
+
h160: h160Hex,
|
|
4605
|
+
prefix
|
|
4606
|
+
};
|
|
4339
4607
|
if (name)
|
|
4340
4608
|
result.name = name;
|
|
4341
4609
|
if (kindLabel)
|
|
@@ -4371,6 +4639,8 @@ async function accountInspect(input, opts) {
|
|
|
4371
4639
|
result.env = envLine.replace(/^\$/, "");
|
|
4372
4640
|
if (bandersnatch && Object.keys(bandersnatch).length > 0)
|
|
4373
4641
|
result.bandersnatch = bandersnatch;
|
|
4642
|
+
if (revealedSecret)
|
|
4643
|
+
result[revealedSecret.field] = revealedSecret.value;
|
|
4374
4644
|
if (privateKeyHex)
|
|
4375
4645
|
result.privateKey = privateKeyHex;
|
|
4376
4646
|
console.log(formatJson(result));
|
|
@@ -4382,6 +4652,7 @@ async function accountInspect(input, opts) {
|
|
|
4382
4652
|
console.log(` ${BOLD}Kind:${RESET} ${kindLabel}`);
|
|
4383
4653
|
console.log(` ${BOLD}Public Key:${RESET} ${publicKeyHex}`);
|
|
4384
4654
|
console.log(` ${BOLD}SS58:${RESET} ${ss58}`);
|
|
4655
|
+
console.log(` ${BOLD}H160:${RESET} ${h160Hex}`);
|
|
4385
4656
|
if (sourceLine)
|
|
4386
4657
|
console.log(` ${BOLD}Source:${RESET} ${sourceLine}`);
|
|
4387
4658
|
if (derivationLine)
|
|
@@ -4401,6 +4672,12 @@ async function accountInspect(input, opts) {
|
|
|
4401
4672
|
}
|
|
4402
4673
|
}
|
|
4403
4674
|
console.log(` ${BOLD}Prefix:${RESET} ${prefix}`);
|
|
4675
|
+
if (revealedSecret) {
|
|
4676
|
+
console.log(` ${BOLD}${`${revealedSecret.label}:`.padEnd(13)}${RESET}${revealedSecret.value}`);
|
|
4677
|
+
if (derivationLine) {
|
|
4678
|
+
console.log(` ${YELLOW}(derived with ${derivationLine} — re-import needs --path ${derivationLine})${RESET}`);
|
|
4679
|
+
}
|
|
4680
|
+
}
|
|
4404
4681
|
if (privateKeyHex) {
|
|
4405
4682
|
console.log(` ${BOLD}Private Key:${RESET} ${privateKeyHex}`);
|
|
4406
4683
|
console.log(` ${YELLOW}(sr25519 expanded, 64 bytes — never share)${RESET}`);
|
|
@@ -4655,8 +4932,10 @@ async function handleApis2(target, args, opts) {
|
|
|
4655
4932
|
typeof opts.parsedArgs === "object" ? JSON.stringify(opts.parsedArgs) : String(opts.parsedArgs)
|
|
4656
4933
|
];
|
|
4657
4934
|
const parsedArgs = await parseRuntimeApiArgs2(meta, method, effectiveArgs);
|
|
4935
|
+
const atArg = parseAtForRead(opts.at);
|
|
4936
|
+
const pullOpts = atArg !== undefined ? [{ at: atArg }] : [];
|
|
4658
4937
|
const unsafeApi = clientHandle.client.getUnsafeApi();
|
|
4659
|
-
const result = await unsafeApi.apis[api.name][method.name](...parsedArgs);
|
|
4938
|
+
const result = await withBlockAvailabilityHint(opts.at, () => unsafeApi.apis[api.name][method.name](...parsedArgs, ...pullOpts));
|
|
4660
4939
|
const format = isJsonOutput(opts) ? "json" : opts.output ?? "pretty";
|
|
4661
4940
|
printResult(result, format);
|
|
4662
4941
|
} finally {
|
|
@@ -6826,6 +7105,8 @@ async function handleQuery(target, keys, opts) {
|
|
|
6826
7105
|
typeof opts.parsedArgs === "object" ? JSON.stringify(opts.parsedArgs) : String(opts.parsedArgs)
|
|
6827
7106
|
];
|
|
6828
7107
|
const parsedKeys = await parseStorageKeys(meta, palletInfo.name, storageItem, effectiveKeys);
|
|
7108
|
+
const atArg = parseAtForRead(opts.at);
|
|
7109
|
+
const pullOpts = atArg !== undefined ? [{ at: atArg }] : [];
|
|
6829
7110
|
const format = isJsonOutput(opts) ? "json" : opts.output ?? "pretty";
|
|
6830
7111
|
const expectedLen = storageItem.type === "map" && storageItem.keyTypeId != null ? meta.builder.buildStorage(palletInfo.name, storageItem.name).len : 0;
|
|
6831
7112
|
if (storageItem.type === "map" && parsedKeys.length < expectedLen) {
|
|
@@ -6835,7 +7116,7 @@ async function handleQuery(target, keys, opts) {
|
|
|
6835
7116
|
console.log(`${DIM}Hint: use --dump to fetch all entries${RESET}`);
|
|
6836
7117
|
return;
|
|
6837
7118
|
}
|
|
6838
|
-
const entries = await withStalenessSuggestion(chainName, clientHandle, () => storageApi.getEntries(...parsedKeys));
|
|
7119
|
+
const entries = await withStalenessSuggestion(chainName, clientHandle, () => withBlockAvailabilityHint(opts.at, () => storageApi.getEntries(...parsedKeys, ...pullOpts)));
|
|
6839
7120
|
const rows = entries.map((e) => ({
|
|
6840
7121
|
keys: e.keyArgs,
|
|
6841
7122
|
value: e.value
|
|
@@ -6844,7 +7125,7 @@ async function handleQuery(target, keys, opts) {
|
|
|
6844
7125
|
await writeStdout(`${text}
|
|
6845
7126
|
`);
|
|
6846
7127
|
} else {
|
|
6847
|
-
const result = await withStalenessSuggestion(chainName, clientHandle, () => storageApi.getValue(...parsedKeys));
|
|
7128
|
+
const result = await withStalenessSuggestion(chainName, clientHandle, () => withBlockAvailabilityHint(opts.at, () => storageApi.getValue(...parsedKeys, ...pullOpts)));
|
|
6848
7129
|
const text = format === "json" ? formatJson(result) : formatPretty(result);
|
|
6849
7130
|
await writeStdout(`${text}
|
|
6850
7131
|
`);
|
|
@@ -7468,7 +7749,7 @@ async function handleTx(target, args, opts) {
|
|
|
7468
7749
|
let estimatedFees;
|
|
7469
7750
|
let estimationError;
|
|
7470
7751
|
try {
|
|
7471
|
-
estimatedFees = String(await withStalenessSuggestion(chainName, clientHandle, () => tx.getEstimatedFees(signer?.publicKey, txOptions)));
|
|
7752
|
+
estimatedFees = String(await withStalenessSuggestion(chainName, clientHandle, () => withBlockAvailabilityHint(opts.at, () => tx.getEstimatedFees(signer?.publicKey, txOptions))));
|
|
7472
7753
|
} catch (err) {
|
|
7473
7754
|
estimationError = err instanceof Error ? err.message : String(err);
|
|
7474
7755
|
}
|
|
@@ -7538,7 +7819,7 @@ async function handleTx(target, args, opts) {
|
|
|
7538
7819
|
}
|
|
7539
7820
|
const observable = clientHandle.client.submitAndWatch(generalTx, at);
|
|
7540
7821
|
if (isJsonOutput(opts)) {
|
|
7541
|
-
const result3 = await withStalenessSuggestion(chainName, clientHandle, () => watchTransactionJson(observable, waitLevel, { unsigned: true }));
|
|
7822
|
+
const result3 = await withStalenessSuggestion(chainName, clientHandle, () => withBlockAvailabilityHint(opts.at, () => watchTransactionJson(observable, waitLevel, { unsigned: true })));
|
|
7542
7823
|
const rpcUrl3 = primaryRpc(opts.rpc ?? chainConfig.rpc);
|
|
7543
7824
|
if (result3.type === "broadcasted") {
|
|
7544
7825
|
printJsonLine({ event: "broadcasted", txHash: result3.txHash });
|
|
@@ -7570,7 +7851,7 @@ async function handleTx(target, args, opts) {
|
|
|
7570
7851
|
}
|
|
7571
7852
|
return;
|
|
7572
7853
|
}
|
|
7573
|
-
const result2 = await withStalenessSuggestion(chainName, clientHandle, () => watchTransaction(observable, waitLevel, { unsigned: true }));
|
|
7854
|
+
const result2 = await withStalenessSuggestion(chainName, clientHandle, () => withBlockAvailabilityHint(opts.at, () => watchTransaction(observable, waitLevel, { unsigned: true })));
|
|
7574
7855
|
console.log();
|
|
7575
7856
|
console.log(` ${BOLD}Chain:${RESET} ${chainName}`);
|
|
7576
7857
|
console.log(` ${BOLD}Type:${RESET} unsigned (bare)`);
|
|
@@ -7619,7 +7900,7 @@ async function handleTx(target, args, opts) {
|
|
|
7619
7900
|
return;
|
|
7620
7901
|
}
|
|
7621
7902
|
if (isJsonOutput(opts)) {
|
|
7622
|
-
const result2 = await withStalenessSuggestion(chainName, clientHandle, () => watchTransactionJson(tx.signSubmitAndWatch(signer, txOptions), waitLevel));
|
|
7903
|
+
const result2 = await withStalenessSuggestion(chainName, clientHandle, () => withBlockAvailabilityHint(opts.at, () => watchTransactionJson(tx.signSubmitAndWatch(signer, txOptions), waitLevel)));
|
|
7623
7904
|
const rpcUrl2 = primaryRpc(opts.rpc ?? chainConfig.rpc);
|
|
7624
7905
|
if (result2.type === "broadcasted") {
|
|
7625
7906
|
printJsonLine({ event: "broadcasted", txHash: result2.txHash });
|
|
@@ -7650,7 +7931,7 @@ async function handleTx(target, args, opts) {
|
|
|
7650
7931
|
}
|
|
7651
7932
|
return;
|
|
7652
7933
|
}
|
|
7653
|
-
const result = await withStalenessSuggestion(chainName, clientHandle, () => watchTransaction(tx.signSubmitAndWatch(signer, txOptions), waitLevel));
|
|
7934
|
+
const result = await withStalenessSuggestion(chainName, clientHandle, () => withBlockAvailabilityHint(opts.at, () => watchTransaction(tx.signSubmitAndWatch(signer, txOptions), waitLevel)));
|
|
7654
7935
|
console.log();
|
|
7655
7936
|
console.log(` ${BOLD}Chain:${RESET} ${chainName}`);
|
|
7656
7937
|
console.log(` ${BOLD}Call:${RESET} ${callHex}`);
|
|
@@ -9125,7 +9406,15 @@ if (process.argv[2] === "__complete") {
|
|
|
9125
9406
|
process.exit(0);
|
|
9126
9407
|
})();
|
|
9127
9408
|
} else {
|
|
9128
|
-
let
|
|
9409
|
+
let readAtFromArgv = function(argv) {
|
|
9410
|
+
for (let i = 0;i < argv.length; i++) {
|
|
9411
|
+
if (argv[i] === "--at" && i + 1 < argv.length)
|
|
9412
|
+
return argv[i + 1];
|
|
9413
|
+
if (argv[i].startsWith("--at="))
|
|
9414
|
+
return argv[i].slice(5);
|
|
9415
|
+
}
|
|
9416
|
+
return;
|
|
9417
|
+
}, collectVarFlags = function(argv) {
|
|
9129
9418
|
const vars = [];
|
|
9130
9419
|
for (let i = 0;i < argv.length; i++) {
|
|
9131
9420
|
if (argv[i] === "--var" && i + 1 < argv.length) {
|
|
@@ -9211,11 +9500,12 @@ if (process.argv[2] === "__complete") {
|
|
|
9211
9500
|
registerVerifiableCommands(cli);
|
|
9212
9501
|
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("--to-yaml", "Decode call to YAML file format (for tx)").option("--to-json", "Decode call to JSON file format (for tx)").option("--ext <json>", "Custom signed extension values as JSON (for tx)").option("--asset <json>", "Pay fees in an alternative asset (XCM location JSON, for tx)").option("-w, --wait <level>", "Resolve at: broadcast, best-block (or best), finalized (for tx)", {
|
|
9213
9502
|
default: "finalized"
|
|
9214
|
-
}).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 (
|
|
9503
|
+
}).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 read/validate against (tx, query, apis)').option("--unsigned", "Submit as unsigned/bare transaction (no signer required, for tx)").option("--refresh", "Refresh the cached RPC method list from the node (for rpc)").action(async (dotpath, args, opts) => {
|
|
9215
9504
|
if (!dotpath) {
|
|
9216
9505
|
printHelp();
|
|
9217
9506
|
return;
|
|
9218
9507
|
}
|
|
9508
|
+
const atRaw = readAtFromArgv(process.argv);
|
|
9219
9509
|
if (isFilePath(dotpath)) {
|
|
9220
9510
|
const cliVars = collectVarFlags(process.argv);
|
|
9221
9511
|
const cmd = await loadCommandFile(dotpath, cliVars);
|
|
@@ -9243,7 +9533,7 @@ if (process.argv[2] === "__complete") {
|
|
|
9243
9533
|
nonce: opts.nonce,
|
|
9244
9534
|
tip: opts.tip,
|
|
9245
9535
|
mortality: opts.mortality,
|
|
9246
|
-
at:
|
|
9536
|
+
at: atRaw,
|
|
9247
9537
|
parsedArgs: cmd.args
|
|
9248
9538
|
});
|
|
9249
9539
|
break;
|
|
@@ -9251,6 +9541,7 @@ if (process.argv[2] === "__complete") {
|
|
|
9251
9541
|
await handleQuery(target2, args, {
|
|
9252
9542
|
...handlerOpts2,
|
|
9253
9543
|
dump: opts.dump,
|
|
9544
|
+
at: atRaw,
|
|
9254
9545
|
parsedArgs: cmd.args
|
|
9255
9546
|
});
|
|
9256
9547
|
break;
|
|
@@ -9260,6 +9551,7 @@ if (process.argv[2] === "__complete") {
|
|
|
9260
9551
|
case "apis":
|
|
9261
9552
|
await handleApis2(target2, args, {
|
|
9262
9553
|
...handlerOpts2,
|
|
9554
|
+
at: atRaw,
|
|
9263
9555
|
parsedArgs: cmd.args
|
|
9264
9556
|
});
|
|
9265
9557
|
break;
|
|
@@ -9298,7 +9590,7 @@ if (process.argv[2] === "__complete") {
|
|
|
9298
9590
|
}
|
|
9299
9591
|
switch (parsed.category) {
|
|
9300
9592
|
case "query":
|
|
9301
|
-
await handleQuery(target, args, { ...handlerOpts, dump: opts.dump });
|
|
9593
|
+
await handleQuery(target, args, { ...handlerOpts, dump: opts.dump, at: atRaw });
|
|
9302
9594
|
break;
|
|
9303
9595
|
case "tx": {
|
|
9304
9596
|
const txOpts = {
|
|
@@ -9315,7 +9607,7 @@ if (process.argv[2] === "__complete") {
|
|
|
9315
9607
|
nonce: opts.nonce,
|
|
9316
9608
|
tip: opts.tip,
|
|
9317
9609
|
mortality: opts.mortality,
|
|
9318
|
-
at:
|
|
9610
|
+
at: atRaw
|
|
9319
9611
|
};
|
|
9320
9612
|
if (parsed.pallet && /^0x[0-9a-fA-F]+$/.test(parsed.pallet)) {
|
|
9321
9613
|
await handleTx(parsed.pallet, args, txOpts);
|
|
@@ -9334,7 +9626,7 @@ if (process.argv[2] === "__complete") {
|
|
|
9334
9626
|
await handleErrors2(target, handlerOpts);
|
|
9335
9627
|
break;
|
|
9336
9628
|
case "apis":
|
|
9337
|
-
await handleApis2(target, args, handlerOpts);
|
|
9629
|
+
await handleApis2(target, args, { ...handlerOpts, at: atRaw });
|
|
9338
9630
|
break;
|
|
9339
9631
|
case "extensions": {
|
|
9340
9632
|
if (parsed.item) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polkadot-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.20.0",
|
|
4
4
|
"description": "CLI tool for querying Polkadot-ecosystem on-chain state",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -38,22 +38,22 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@noble/hashes": "^2.0.1",
|
|
41
|
-
"@polkadot-api/metadata-builders": "^0.14.
|
|
42
|
-
"@polkadot-api/substrate-bindings": "^0.20.
|
|
41
|
+
"@polkadot-api/metadata-builders": "^0.14.3",
|
|
42
|
+
"@polkadot-api/substrate-bindings": "^0.20.3",
|
|
43
43
|
"@polkadot-api/substrate-client": "^0.7.0",
|
|
44
|
-
"@polkadot-api/view-builder": "^0.5.
|
|
44
|
+
"@polkadot-api/view-builder": "^0.5.3",
|
|
45
45
|
"@polkadot-labs/hdkd": "^0.0.28",
|
|
46
46
|
"@polkadot-labs/hdkd-helpers": "^0.0.29",
|
|
47
47
|
"@scure/sr25519": "^1.0.0",
|
|
48
48
|
"cac": "^6.7.14",
|
|
49
|
-
"polkadot-api": "^2.
|
|
50
|
-
"verifiablejs": "
|
|
49
|
+
"polkadot-api": "^2.1.4",
|
|
50
|
+
"verifiablejs": "1.3.0",
|
|
51
51
|
"yaml": "^2.8.3"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@biomejs/biome": "^2.4.5",
|
|
55
55
|
"@changesets/cli": "^2.29.4",
|
|
56
|
-
"@polkadot-api/metadata-compatibility": "^0.6.
|
|
56
|
+
"@polkadot-api/metadata-compatibility": "^0.6.3",
|
|
57
57
|
"@types/bun": "^1.3.9",
|
|
58
58
|
"husky": "^9.1.7"
|
|
59
59
|
}
|