Skip to content

Releases: paritytech/polkadot-cli

v1.25.1

Choose a tag to compare

@github-actions github-actions released this 23 Oct 08:38
d2a06d5

What's Changed

  • chore: refresh built-in RPC endpoints by @peetzweg in #318
  • chore: version packages by @github-actions[bot] in #319

Full Changelog: v1.25.0...v1.25.1

v1.25.0

Choose a tag to compare

@github-actions github-actions released this 07 Oct 09:26
4a2c38c

What's Changed

  • chore: refresh built-in RPC endpoints, drop decommissioned IBP by @peetzweg in #288
  • chore(deps): safe in-range bumps + ws security override by @peetzweg in #291
  • feat: negotiate the highest supported metadata version instead of pinning v15 by @peetzweg in #298
  • fix: let --ext override builtin extensions, error on unknown names by @peetzweg in #297
  • feat: select the transaction-extension version from metadata by @peetzweg in #299
  • docs: showcase tapes for the README and docs site by @peetzweg in #302
  • docs: record the remaining showcase tapes by @peetzweg in #304
  • Rename --unsigned to --general (deprecated alias kept) by @peetzweg in #307
  • Upgrade polkadot-api to 3.0 by @peetzweg in #308
  • fix: unknown command crashed with 'Bun is not defined' under node by @peetzweg in #309
  • chore(deps): upgrade verifiablejs 1.4.0 -> 1.6.0 by @peetzweg in #311
  • fix: output errors as JSON when --json is passed by @CiprianPotor in #312
  • feat: every error honours --json; add DOT_OUTPUT env var by @peetzweg in #313
  • chore: version packages by @github-actions[bot] in #290

New Contributors

Full Changelog: v1.24.0...v1.25.0

v1.24.0

Choose a tag to compare

@github-actions github-actions released this 03 Aug 18:17
a672112

What's Changed

  • chore: update repository references from peetzweg to paritytech by @peetzweg in #281
  • Surface the active config root in chain commands by @peetzweg in #280
  • feat(skill): first-class Codex support via dot skill by @peetzweg in #282
  • chore: version packages by @github-actions[bot] in #283

Full Changelog: v1.23.0...v1.24.0

v1.22.0

Choose a tag to compare

@github-actions github-actions released this 29 Jun 08:54
10a6ce4

What's Changed

  • feat(account): add rm alias for account delete/remove by @peetzweg in #242
  • fix(cli): stop dropping --help for nested subcommands (#238) by @peetzweg in #244
  • fix(cli): make nested --help survive the production bundle (#238) by @peetzweg in #248
  • feat: global DOT_DRY_RUN flag to force dry-run on all extrinsics by @peetzweg in #243
  • chore(deps): upgrade polkadot-api to 2.1.7 by @peetzweg in #256
  • chore(deps): upgrade verifiablejs to 1.4.0 by @peetzweg in #257
  • docs: document {relay}-{parachain} chain naming convention by @peetzweg in #262
  • ci: publish via paritytech/npm_publish_automation by @peetzweg in #266
  • chore(deps): upgrade cac from 6 to 7 by @peetzweg in #268
  • chore: version packages by @github-actions[bot] in #245

Full Changelog: v1.21.0...v1.22.0

v1.21.0

Choose a tag to compare

@github-actions github-actions released this 12 Jun 07:36
4bb1acd

Minor Changes

  • 5ac2b5e: Add directory-local workspaces: dot init creates a .polkadot/ workspace in the current directory, discovered git-style (cwd and parents, stopping at $HOME) and fully isolating accounts, custom chains, and metadata cache from the global ~/.polkadot. New dot which shows the active config root and how it was chosen. Precedence: DOT_HOME → local workspace → global. Account and chain resolution errors now name the config root that was searched.

  • a33128e: feat(verifiable): ring-VRF proof, signing, verification and members primitives

    Adds composable dot verifiable subcommands over verifiablejs:

    • verifiable sign / verify-sig — standalone Bandersnatch signatures.
    • verifiable alias — derive the alias for a 32-byte ring context.
    • verifiable prove / verify — ring-VRF proofs (one_shot) and local
      verification against a members set or a 768-byte ring root.
    • verifiable members — SCALE-encode member keys as Vec<[u8;32]>.

    The command is scoped to raw verifiable crypto only — bytes in, bytes out, with
    no chain/pallet knowledge and no automated fetching or selection (the same way
    dot sign is just sr25519). Supply the members/context/message yourself (e.g.
    read from chain with dot first) and use the resulting signature/proof however
    you need — in a dot extrinsic or signed extension, or elsewhere.

    All actions accept hex / --file / --stdin input and --output json, and a
    new src/features/verifiable/lib.ts exposes the underlying primitives for reuse.

    Breaking: the entropy-derivation key is now --entropy-key (was --context
    on dot verifiable), and --context now means the 32-byte ring/proof namespace
    — aligning with the runtime (type Context = [u8;32]) and the iOS/Android
    clients. The old --context <key> form still works on the member command for one
    release with a deprecation warning; switch to --entropy-key.

Patch Changes

  • 09aab3e: fix(tx): show stale-metadata hint on BadProof / AncientBirthBlock

    withStalenessSuggestion already wraps every signSubmitAndWatch call
    and, on error, compares cached (specVersion, transactionVersion, codeHash) against the live runtime — if they diverge it appends the
    ⚠ Local metadata for "<chain>" is out of date … Run: dot chain update <chain> hint. But the gating regex only matched wasm-trap / codec /
    decode symptoms, not Invalid::BadProof or Invalid::AncientBirthBlock.

    After a chain runtime upgrade the signer used the cached spec/tx
    version, the runtime reconstructed a different payload, the signature
    didn't verify and the tx was rejected with a bare BadProof — leaving
    the user guessing. The fingerprint mismatch was right there but the
    regex skipped over it.

    CheckSpecVersion / CheckTxVersion / CheckGenesis /
    CheckMortality are all in the signed payload, so BadProof and
    AncientBirthBlock are exactly the variants that smell like stale
    metadata. Adding them to the pattern list lets the existing fingerprint
    gate run; if cached matches live (genuine bad key / wrong chain) the
    raw error still passes through unchanged.

    Nonce-mismatch variants (Future, Stale) are deliberately excluded —
    those are account-state issues, not metadata.

  • c1ed560: fix(completions): only print setup instructions when stdout is a TTY

    dot completions <shell> wrote its setup hint to stderr on every invocation.
    Inside eval "$(dot completions zsh)" in ~/.zshrc, stderr bypasses the
    command substitution and reaches the terminal, so every new shell printed the
    # Add this to your ~/.zshrc block. The hint is now only printed when stdout
    is a TTY — i.e. when a human runs the command to look at the script — and
    stays silent when the output is captured by eval or redirected to a file.

  • d9a27d7: fix(test): make polkadot-api module mocks ordering-safe across test files

    No runtime behavior change — this fixes the flaky CI failures where
    createChainClient tests failed depending on test-file scheduling order.
    bun's mock.module() is global to the test process and not restored between
    files, so client.test.ts and load-meta.test.ts clobbered each other's
    mocks. Both now share a fixture that spreads the real module exports into
    the mocks and captures the real createChainClient before any file can stub
    the client.ts module.

v1.20.0

Choose a tag to compare

@github-actions github-actions released this 11 Jun 10:20
c94e91a

Minor Changes

  • 5920098: feat(account): reveal mnemonic with --show-secret and import raw private keys

    dot account inspect <name> --show-secret now also reveals the stored
    mnemonic
    (or 32-byte hex seed) alongside the 64-byte sr25519 expanded private
    key, in both text and --json output. Env-backed secrets stay redacted — only
    the $VAR reference is shown.

    dot account add <name> --secret 0x<128 hex> now imports an account directly
    from a 64-byte sr25519 expanded secret — the exact value --show-secret
    prints — making it round-trippable. Imported expanded-secret accounts sign and
    resolve addresses like any other signer. A derivation path cannot be applied to
    an expanded secret, so --path is rejected for this format.

    Fixes a related bug: --secret 0x... was previously corrupted by cac's
    numeric coercion, so 32-byte hex seed import never worked from the command
    line
    . The raw argv value is now read directly, so both hex seeds and raw
    private keys import correctly. The misleading "hex seed not supported" help text
    has been corrected.

Patch Changes

  • 0dd979c: chore(deps): upgrade polkadot-api to 2.1.4 and sibling @polkadot-api/* packages

    Bumps polkadot-api (2.0.1 → 2.1.4), @polkadot-api/metadata-builders
    (0.14.1 → 0.14.3), @polkadot-api/substrate-bindings (0.20.1 → 0.20.3),
    @polkadot-api/view-builder (0.5.1 → 0.5.3), and
    @polkadot-api/metadata-compatibility (0.6.1 → 0.6.3, dev).
    Minor/patch bumps with no API surface change in the parts consumed by the CLI.

  • 6535199: chore(deps): upgrade verifiablejs to 1.3.0

    Bumps verifiablejs from 1.3.0-beta.2 to the stable 1.3.0 release. The JS
    API consumed by the CLI (member_from_entropy) is unchanged, but the release
    bumps the underlying verifiable crate to v0.5.0 (ThinVRF, new ring proofs),
    so derived Bandersnatch member keys are wire-incompatible with beta.2 —
    this is the intended alignment with the verifiable crate used on-chain by
    individuality. Updated the documented example keys (README, docs) and added a
    regression test pinning alice's derived member keys to the 1.3.0 wire format.

v1.19.0

Choose a tag to compare

@github-actions github-actions released this 15 May 06:22
0d4be40

Minor Changes

  • 64bc0b5: fix(query, apis): honor --at <block> for historical reads

    --at was declared on the global command but only ever wired into tx
    submission. query.* and apis.* accepted the flag silently and read
    current head anyway, making historical state reads and per-block runtime
    API replays impossible from the high-level wrappers.

    papi v2 supports historical reads natively via the trailing PullOptions
    argument on storage and runtime calls ({ at: "best" | "finalized" | <hash> }). The fix threads the flag through.

    • dot polkadot.query.System.Number --at best

    • dot polkadot.query.System.Number --at finalized

    • dot polkadot.query.System.Number --at 0x<hash>

    • dot polkadot.apis.Core.version --at 0x<hash>

      Behavior matrix:

      Command --at best --at finalized --at 0x<hash>
      query.* ✓ ✓ ✓
      apis.* ✓ ✓ ✓
      tx.* rejected (papi v2 constraint) ✓ ✓

      Also fixes a pre-existing CAC/mri argv-parsing bug where 0x-hex block
      hashes passed to --at were silently coerced to JS Numbers, losing
      precision. --at is now read from raw argv to keep the original string
      intact.

      papi v2's chainHead_v1_* JSON-RPC only serves pinned (recent) blocks.
      For deep historical reads, point --rpc at an archive endpoint.

  • debed0d: feat(account): show pallet-revive H160 in dot account inspect

    Every Substrate account now also shows its pallet-revive 20-byte H160
    address (EIP-55 checksummed) on the H160: line, so developers working
    across SS58 and EVM tooling on Polkadot Hub / Asset Hub can see both
    representations side by side. The same H160 appears under the h160
    field of --output json.

    The mapping is offline and matches current polkadot-sdk master:

    • 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.
    • H160 → AccountId32: deterministic fallback H160 || 0xEE * 12.
      The full mapping after pallet_revive.map_account lives in on-chain
      AddressSuffix storage and is not recoverable offline.

    dot account inspect accepts a 20-byte H160 hex value as a new input
    form. It resolves to the fallback AccountId32 and reports
    Kind: revive H160 fallback.

    dot account inspect alice
    #   H160:        0x9621DDe636dE098B43Efb0fA9b61fAcFE328F99D
    
    dot account inspect 0x9621DDe636dE098B43Efb0fA9b61fAcFE328F99D
    #   Kind:        revive H160 fallback
    #   Public Key:  0x9621dde636de098b43efb0fa9b61facfe328f99deeeeeeeeeeeeeeeeeeeeeeee
    
    dot account inspect alice --json | jq -r .h160
    # 0x9621DDe636dE098B43Efb0fA9b61fAcFE328F99D

    Older stable2412 runtimes used plain accountId32[..20] truncation
    instead of the keccak fallback for the forward direction. A
    --revive-truncate flag for those is not implemented; this release
    ships only the canonical current-master mapping.

  • ecd453b: feat(hash): add twox64, twox128, twox256 algorithms

    Substrate uses XXH64-based twox* hashes throughout — pallet/storage prefixes
    are twox128(palletName) ++ twox128(itemName), and Twox64Concat is a common
    storage-map hasher. Previously dot hash only supported the BLAKE2b, Keccak,
    and SHA-2 families, so constructing a raw storage key required an external
    tool.

    The three new algorithms are pure-TypeScript (no wasm, no native deps) and
    verified against canonical XXH64 vectors and Substrate prefixes:

    • dot hash twox128 System → 0x26aa394eea5630e07c48ae0c9558cef7
    • dot hash twox128 Balances → 0xc2261276cc9d1f8598ea4b6a74b15c2f
    • dot hash twox64 <key> / dot hash twox256 <key> for the other variants

    Combined with dot [chain.]rpc.state_getStorage 0x<key>, this is enough to
    read any raw storage value, including the well-known keys (:code,
    :heappages) that live outside metadata.

Patch Changes

  • 47992bf: fix(errors): friendlier message when --at <block> is not available

    When --at points at a block the connected RPC can't serve — most often
    an old hash against a non-archive node — papi raises
    BlockHashNotFoundError / StorageError: UnknownBlock / "is not pinned"
    rejections. These now get caught at the query.* / apis.* / tx.*
    call sites and re-surfaced as a clean CliError with a copy-pasteable
    hint:

    Error: Block 0x… is not pinned (storage)
    
    ⚠ 0x… is not available on the current RPC endpoint.
       Public nodes serve only recent (pinned) blocks via chainHead_v1_*.
       For deep historical reads, point --rpc at an archive endpoint, e.g.:
         dot ... --at 0x… --rpc wss://<archive-endpoint>
    

    Note: papi's substrate-client may still emit its own internal stack
    trace ahead of the clean message; suppressing that is a separate
    follow-up.

  • a801337: chore(deps): upgrade verifiablejs to 1.3.0-beta.2

    Tracks the upstream beta. The CLI only consumes member_from_entropy,
    whose signature is unchanged, so dot verifiable output is byte-identical.

v1.18.0

Choose a tag to compare

@github-actions github-actions released this 07 May 15:41
dd82993

Minor Changes

  • 0a4c5f3: feat(rpc): add dot [chain.]rpc.<method> for raw JSON-RPC calls

    Closes #196.

    Substrate nodes expose a JSON-RPC surface (system_*, chain_*, state_*,
    author_*, payment_*, consensus and dev families, plus the new spec
    chainSpec_v1_* / archive_v1_* / rpc_methods) that is separate from
    runtime metadata and was previously unreachable from this CLI.

    The new rpc category mirrors the other dotpath commands: methods are
    discovered per-chain via rpc_methods, cached at
    ~/.polkadot/chains/<chain>/rpc-methods.json, and tab-completed.

    • dot polkadot.rpc — list methods grouped by family
    • dot polkadot.rpc.system_health — call a method
    • dot polkadot.rpc.chain_getBlock 0x<hash> — positional args
    • dot polkadot.rpc.<method> --help — curated description and arg names
      for ~50 well-known methods; raw passthrough for the rest
    • dot polkadot.rpc --refresh — re-discover methods on a node upgrade

    Subscription methods (*_subscribe*, chainHead_v1_follow, transaction_v1_*)
    appear in completion but error out as one-shots with a helpful message.

    dot chain add and dot chain update now also fetch and cache the method
    list, and dot chain info shows a per-family breakdown.

  • 3180e75: Add derivation flags to dot account add that store sovereign addresses as named watch-only accounts. One command lets you turn a parachain ID or a pallet PalletId into a stored account that's reusable in --from, in tx args, and in dot account list.

    # Pallet sovereign (Treasury / Bounties / Crowdloan / NominationPools / …)
    dot account add Treasury --pallet-id py/trsry
    dot account add Bounties --pallet-id 0x70792f626f756e74
    
    # Parachain sovereign — type is required (child = address on the relay,
    # sibling = address from another parachain's POV)
    dot account add People --parachain 1004 --parachain-type child
    dot account add People-Sibling --parachain 1004 --parachain-type sibling

    Derivation (matches Substrate's AccountIdConversion::into_account_truncating):

    • Pallet: b"modl" (4 bytes) + palletId (8 bytes) + 20 zero bytes
    • Parachain: b"para" (child) or b"sibl" (sibling) + paraId LE u32 (4 bytes) + 24 zero bytes

    PalletId input is either 8 ASCII chars (py/trsry) or 0x-prefixed hex with exactly 16 hex chars (0x70792f7472737279). Per-chain PalletIds can be discovered via the existing const category:

    dot account add Treasury --pallet-id "$(dot polkadot.const.Treasury.PalletId | tr -d '"')"

    Constraints: --parachain requires --parachain-type child|sibling (no implicit default); --parachain and --pallet-id are mutually exclusive; derivation flags cannot be combined with a positional address or with --secret/--env.

    JSON output (--json) includes a derivation object describing the source — { "kind": "pallet", "palletId": "py/trsry", "palletIdHex": "0x..." } or { "kind": "parachain", "paraId": 1004, "type": "child" } — for round-trippable record-keeping.

    dot account list is restructured to make kinds obvious and SS58s easier to copy-paste. Stored accounts are now bucketed into Signers, Watch-only, Pallet Sovereigns, and Parachain Sovereigns sections (empty sections omitted). The first line of each entry is just name ss58; extra attributes render on tree-style continuation lines (├─ / └─, mirroring dot chains). Attribute labels are aligned with the --flag that sets each value (path:, env:, pallet-id:, parachain:, parachain-type:) so the listing reads back as a recipe. Multiple attributes per account (e.g. --path + --env) each get their own branch:

    Signers
      ci-signer  5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy
         ├─ path: //ci
         └─ env:  $CI_SECRET
    
    Pallet Sovereigns
      Treasury   5EYCAe5ijiYfyeZ2JJCGq56LmPyNRAKzpG4QkoQkkQNB5e6Z
         └─ pallet-id: py/trsry (0x70792f7472737279)
    
    Parachain Sovereigns
      People     5Ec4AhPaYcfBz8fMoPd4EfnAgwbzRS7np3APZUnnFo12qEYk
         ├─ parachain:      1004
         └─ parachain-type: child
    

    --json adds a kind discriminator on every entry plus a source object on derived sovereigns.

    dot account inspect now surfaces the derivation source. The output gains a Kind: line (dev / signer / watch-only / pallet sovereign / parachain sovereign (child|sibling)) and, for derived sovereigns, a Source: line (PalletId py/trsry (0x70792f7472737279) or parachain 1004). For env-backed signers there's an Env: line; derived child keys show their Derivation: path.

    Storage-format change: StoredAccount gains an optional source field that records how a watch-only account was derived. Existing accounts without this field continue to work — they're classified as plain signer or watch-only based on the presence of a secret.

    dot account inspect accepts the same derivation flags for stateless lookup. When you just need the SS58 in a script and don't want a stored entry, run dot account inspect --pallet-id <id> or dot account inspect --parachain <id> --parachain-type <child|sibling> — same output shape (Kind / Source / SS58 / public key, plus a structured source object on --json), no name, nothing written to ~/.polkadot/accounts.json.

    SS58=$(dot account inspect --pallet-id py/trsry --prefix 0 --json | jq -r .ss58)

    Use account add to persist (named, reusable as --from / tx arg / in account list); use account inspect to derive ad-hoc.

Patch Changes

  • 34044e8: Preserve the standalone dot parachain <paraId> command as a deprecated alias.

    The same release that introduced sovereign-account derivation flags on dot account (--parachain / --parachain-type / --pallet-id) had also deleted the older standalone dot parachain command. To avoid breaking production scripts that pin the prior CLI surface, the command is restored verbatim — same arguments, same exit codes, same byte-identical stdout for --json and pretty output. It now prints a one-line deprecation warning to stderr only, so pipes into jq / awk / file redirects keep working unchanged.

    Migrate at your convenience:

    # Before
    dot parachain 1000 --type child --json
    
    # After (same SS58 / public key, structured `source` field on JSON output)
    dot account inspect --parachain 1000 --parachain-type child --json

    Tracked for removal in a future release: #208.

v1.17.0

Choose a tag to compare

@github-actions github-actions released this 30 Apr 12:10
ab8a6a9

Minor Changes

  • fd6cf14: Clean up dot chains output and add dot chain info <name> for per-chain detail.

    dot chains is now scannable

    The default dot chains (and dot chain list) output no longer prints RPC URLs inline. The list view becomes a compact tree of names + relay structure + parachain IDs:

    Configured Chains
    
      polkadot
      ├─ polkadot-asset-hub [1000]
      ├─ polkadot-bridge-hub [1002]
      ├─ polkadot-collectives [1001]
      ├─ polkadot-coretime [1005]
      └─ polkadot-people [1004]
    
      paseo
      ├─ paseo-asset-hub [1000]
      └─ paseo-people [1004]
    

    Pass -v / --verbose (à la git remote -v) to keep the previous behavior with RPC endpoints inline:

    dot chains -v
    dot chain list --verbose

    dot chain info <name>

    A new info action prints full per-chain detail in one block — RPC endpoints, relay/parachain id, child parachains (when the target is a relay), and metadata cache status:

    dot chain info polkadot
    
    # polkadot
    #
    #   rpc:
    #     wss://polkadot.ibp.network
    #     wss://rpc.polkadot.io
    #     ...
    #   parachains:
    #     polkadot-asset-hub [1000]
    #     polkadot-bridge-hub [1002]
    #     ...
    #   metadata:
    #     polkadot v1003000 (cached 2026-04-29T12:34:56.000Z)

    dot chain <name> is a bare-noun shortcut that falls through to chain info <name> — like gh repo view. The dispatcher still pattern-matches known action verbs first (add, remove, update, list, export, import), so existing usage is unchanged.

    --json emits a structured object with name, rpc[], optional relay / parachainId, optional parachains[], and a metadata block (or null when no fingerprint is cached). Names resolve case-insensitively, matching findChainName semantics used elsewhere.

    When metadata has never been fetched for the chain, the metadata row prints not cached — run \dot chain update `` so it's clear how to populate it.

  • ede4b8c: Width-aware multi-line pretty-printing for type signatures, call arguments, and decoded calls.

    dot inspect, the focused listings (dot <chain>.tx.<Pallet>, .query.<Pallet>, .events.<Pallet>, .extensions), and --dry-run output now render structured types across multiple lines when they don't fit, with syntactic ANSI coloring (field names cyan, primitives yellow, container keywords magenta, enum variants green). Short signatures stay compact.

    Before

      Args: (proposal_origin: system | Origins | ParachainsOrigin | XcmPallet, proposal: Legacy | Inline | Lookup, enactment_moment: At | After)
    

    After

      Args: (
        proposal_origin : system | Origins | ParachainsOrigin | XcmPallet,
        proposal        : Legacy | Inline | Lookup,
        enactment_moment: At | After,
      )
    

    Storage detail now shows Type:, Key:, and Value: on separate lines (no → arrow), with composite values expanded:

    Assets.Metadata (Storage)
    
      Type:  map
      Key:   u32
      Value: {
        deposit  : u128,
        name     : Vec<u8>,
        symbol   : Vec<u8>,
        decimals : u8,
        is_frozen: bool,
      }
    

    Dry-run Decode: is now JSON-styled, suitable for very complex calls:

      Decode: System.remark
        {
          "remark": "0x68656c6c6f20776f726c64"
        }
    

    Enum variant visibility — the enum(N variants) summary threshold was raised from 4 to 24, so most enums (e.g. Option<AsPersonalAliasWithAccount | AsPersonalAliasWithProof | ...>) now show variant names instead of being collapsed.

    Width detection uses process.stdout.columns (falls back to 80). Output is automatically uncolored when stdout isn't a TTY, so piped --json and shell-redirected output stay clean.

    JSON output (--json) is unchanged — type strings continue to be emitted as compact single-line values for scripting.

Patch Changes

  • 3a12d97: Fix dot query <Pallet.Item> --dump --json | jq failing with
    jq: parse error: Unfinished JSON term at EOF on populated storage maps
    (reported against polkadot-asset-hub query.Revive.AccountInfoOf).

    # Now works (previously truncated past ~64 KiB of output):
    dot --chain polkadot-asset-hub query.Revive.AccountInfoOf --dump --json | jq

    Bun's console.log writes to process.stdout are async, and the CLI returns
    before the userspace stdout buffer drains into the OS pipe; on Linux
    (~64 KiB pipe buffer) anything past that threshold gets dropped. PR #194
    fixed this for dot metadata with a local awaitable-write helper. This
    extracts that helper into src/core/output.ts as a shared writeStdout
    primitive and routes dot query's five output sites through it (the
    --dump map-entries path that triggers the user's bug, the single-value
    fetch, and the three pallet/storage listing paths). dot metadata now
    imports the shared helper instead of carrying its own copy.

    Issue #198 stays open as the forward-looking sweep — inspect, const,
    apis, etc. still emit via console.log, but their payloads don't
    realistically cross the pipe-buffer threshold today, so they're left for
    when (or if) one of them grows.

v1.16.0

Choose a tag to compare

@github-actions github-actions released this 28 Apr 13:34
c4a8ac9

Minor Changes

  • e4ee0dc: Add dot metadata <chain> command and detect stale local metadata after a failed call.

    dot metadata <chain>

    A new top-level command that fetches a chain's runtime metadata and prints it as a single JSON blob with everything needed to drive the chain — pallets (with calls, events, errors, storage, constants), runtime APIs, transaction extensions, and a runtime fingerprint header (specVersion, transactionVersion, codeHash, etc.). Closes #170.

    dot metadata polkadot                  # decoded JSON, fetched fresh from the chain
    dot metadata polkadot --raw            # SCALE-encoded metadata bytes as a single 0x… hex line
    dot metadata polkadot --cached         # use locally cached metadata, skip the network round-trip
    dot metadata polkadot --rpc wss://…    # override the RPC endpoint

    Stale-metadata suggestion

    When dot tx, --dry-run, or dot query fails with an error that smells like stale metadata (a runtime wasm trap, codec/decode failure, or fee-estimation panic), the CLI now compares your local metadata's runtime fingerprint against the live chain. If it has changed, the original error is wrapped with a one-line suggestion telling you exactly which command to run:

    Error: The runtime rejected this transaction in the runtime's validate_transaction step.
      Cause: a runtime invariant failed — typically the call's arguments are out of range, …
    
    ⚠ Local metadata for "paseo-people-next" is out of date (spec 1018 → 1020).
       Run: dot chain update paseo-people-next
    

    The fingerprint includes the runtime code hash (from state_getStorageHash(":code:")) — so the check also catches local-node restarts where the runtime wasm changed but specVersion was kept the same. No automatic refetch happens; the suggestion is shown once and the original error still propagates with the non-zero exit code.

    The check only fires on suspected-stale errors, so the happy path pays no extra RPC. Set DOT_TRUST_CACHED_METADATA=1 to skip the check entirely (e.g. for CI or scripted loops where you've just refreshed manually).

    Companion improvements

    • formatRuntimeError now translates raw polkadot-api wasm-trap stack traces into a friendly "the runtime rejected this transaction" message with a hint pointing at --dry-run.
    • dot tx --dry-run now surfaces the underlying reason when fee estimation fails (previously the error message was silently dropped, leaving only "unable to estimate").
    • A global unhandledRejection filter swallows benign late-timer rejections from @polkadot-api/observable-client (Not connected, DisjointError) that previously crashed dot chain update --all after the actual work had completed.

Patch Changes

  • e4ee0dc: Friendlier error output when the runtime panics or papi cleanup races leak.

    Runtime wasm traps

    Errors from inside validate_transaction (wasm unreachable instruction / Execution aborted due to trap) used to be printed as a verbatim wasm backtrace from polkadot-api. They now render as a one-paragraph "the runtime rejected this transaction" message that names the failing entrypoint where possible (e.g. the runtime's validate_transaction step) and points at --dry-run for the next step.

    --dry-run no longer hides the reason fee estimation failed

    Previously dot tx … --dry-run swallowed any exception from getEstimatedFees and printed only Estimated fees: unable to estimate. The error reason is now captured and displayed alongside the estimate (and included in the JSON output as estimationError), so users see why estimation failed before deciding to submit.

    dot chain update --all no longer crashes on cleanup races

    @polkadot-api/observable-client schedules timers inside its chain-head follow stream that can fire after client.destroy() has cleared the connection, rejecting with Error: Not connected or DisjointError. Previously these unhandled rejections killed the process after the actual update work had completed. A process.on('unhandledRejection') filter at the CLI entry point now swallows that specific class of teardown noise (matched by name) and lets unrelated rejections through with the new friendlier formatting.