paritytech / paritytech/polkadot-cli
Investigate chain spec / chain properties support
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 10
- Forks
- 2
- Avg merge
- 12h 35m
- Merged PRs (30d)
- 4
Description
Background
Substrate chains carry a chain spec — a JSON blob produced at genesis — that holds:
- Identity: `name`, `id`, `chainType`
- Networking: `bootNodes`, `telemetryEndpoints`, `protocolId`
- `properties`: `{ tokenDecimals, tokenSymbol, ss58Format }`
- `forkBlocks`, `badBlocks`, `codeSubstitutes`, `lightSyncState`
- `genesis` (initial state + runtime wasm)
The `properties` block in particular is information `dot` currently does not surface — and not having it leads users (and the dot-cli skill) to hardcode token decimals per chain. That's the same antipattern that bit the in-tree `scripting-patterns.md` example: `NATIVE_DECIMALS=12` for the preview environment, `NATIVE_DECIMALS=10` for paseo-people-next, baked into config files. A faucet built on top of those numbers silently goes wrong when run against the wrong network. The chain knows the answer; we should ask it instead of guessing.
This issue is to investigate whether and how `polkadot-cli` should consume chain-spec data, and what the trade-offs look like.
What's in scope
Two distinct slices:
- Chain properties (cheap, RPC-served): `tokenDecimals`, `tokenSymbol`, `ss58Format`. Available on every Substrate node via `system_properties` (legacy) or `chainSpec_v1_properties` (modern chainHead family).
- Full chain spec (heavy, mostly out-of-band): the whole JSON, including genesis state and embedded wasm. Multi-MB. Source of truth is the node binary (` build-spec --chain `) or published files (e.g. `paritytech/polkadot-sdk`'s `cumulus/parachains/chain-specs/*.json`, `paritytech/chainspecs`, smoldot's `well-known-chains`).
These are very different shapes of feature. We should be deliberate about which one(s) to support.
Possible benefits
- Replaces hardcoded decimals everywhere. The faucet incident, the `scripting-patterns.md` config files, and any agent-generated script that needs to reason about balances all benefit. One `dot` call replaces a per-environment branch.
- Nicer balance rendering. `dot polkadot.query.System.Account alice` could show `1.234 DOT` alongside the raw plancks once we know the decimals + symbol.
- Better address output. `dot account inspect` already accepts `--prefix`; with `ss58Format` known per chain, it could default to the right prefix automatically (Polkadot 0, Kusama 2, Substrate 42).
- Smoother `dot chain add` UX. `dot chain add my-chain --rpc ` could pre-fill name / decimals / symbol / ss58 from the chain itself, no manual flags. Even better: `dot chain add --from-spec ` for full bootstrap from a published chain-spec JSON.
- Foundation for a future light-client mode. If `dot` ever wants to use smoldot, we'd need real chain-spec ingestion. Building the import path now means the work isn't wasted later.
- Clearer "what is this chain" introspection. Could feed the `dot metadata` JSON dump (#170, PR #194) so the runtime fingerprint header includes `tokenDecimals` / `tokenSymbol`.
Possible drawbacks / open questions
- Two RPC families. `system_properties` is the legacy method but universally implemented; `chainSpec_v1_properties` is the modern chainHead variant. Some endpoints expose only one. Pick one, fall back to the other, or document both?
- Multi-token edge case. Some chains return `tokenDecimals` and `tokenSymbol` as arrays instead of scalars (chains intentionally listing multiple native-ish tokens). How do we expose that? Pick the first? Surface the array? Refuse and tell the user?
- Empty-properties endpoints. Some custom / minimal chains return `{}` — no decimals at all. Need a graceful fallback.
- Caching policy. Properties are effectively immutable per genesis, so caching forever is fine. But if a chain operator restarts with a new spec at the same RPC URL, the cache is stale. Tie cache invalidation to the runtime fingerprint we're already storing for stale-metadata detection (PR #194)?
- Full-spec ingestion is a different beast. Mostly a multi-MB JSON parse plus genesis-state validation logic. Not justified by the faucet use case alone — only worth it if we're also pursuing light-client or chain-bootstrap features.
- Source-of-truth divergence. The properties block on a running node can in principle drift from what's in the binary's embedded spec (operator config errors). RPC is what users will hit, so trust the RPC.
- Privacy / signal. Calling `system_properties` adds one round-trip per command if we fetch live each time. Cache once on `dot chain add` and on `dot chain update` to avoid that cost.
Possible implementation directions
In order of increasing scope:
- `dot chain properties ` command. Thin wrapper around `system_properties` / `chainSpec_v1_properties`. ~30 lines. Returns `{ tokenDecimals, tokenSymbol, ss58Format }` as JSON. Lets scripts replace `NATIVE_DECIMALS=12` with `NATIVE_DECIMALS=$(dot chain properties polkadot --json | jq .tokenDecimals)`. Self-contained; doesn't touch any other code.
- Persist properties in `config.json`. On `dot chain add` and `dot chain update`, fetch properties once and save them in the chain's config entry. `dot chain list` shows them. `dot account inspect` defaults `--prefix` from there. Existing chain entries get a backfill on next update.
- Use them for balance rendering. `dot query` and `dot tx` output starts showing `1.234 DOT` next to raw plancks when the storage value is a known balance type and we have decimals/symbol cached.
- `dot chain add --from-spec `. Parse a published chain-spec JSON (Substrate `build-spec` output) and prefill the chain entry with name, decimals, symbol, ss58, and bootnodes if available. No genesis-state ingestion; just the metadata fields.
- Full chain-spec import / light-client mode. Out of scope here — track separately if pursued.
(1) clearly pays for itself for the faucet / hardcoded-decimals problem alone. (2)+(3) build on it. (4) is a separable nice-to-have. (5) is a different feature.
Related
- #170 / PR #194 — `dot metadata ` already prints a runtime fingerprint header; chain properties would slot in alongside it.
- #196 — Expose known RPC methods. `system_properties` is one such method; the work here may overlap.
- #197 — Enable calling custom RPC methods. A generic `dot rpc ` would let advanced users hit `system_properties` directly even before we add a dedicated command. Could be a stepping stone.
Decision needed
- Which of the implementation slices (1–5) are worth pursuing?
- Prefer `system_properties` or `chainSpec_v1_properties` as the source? (Probably both, with a fallback chain.)
- How to handle multi-token / array-typed responses?
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the existing dot chain add and dot chain update entry points, then review #196, #197, and PR #194 for RPC and metadata patterns. Compare system_properties with chainSpec_v1_properties, including array and empty responses; done means a documented recommendation for the supported slice, fallback behavior, caching, and scope boundaries.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, cli
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100