|
| 1 | +# @polkadot-api/check-runtime |
| 2 | + |
| 3 | +Detect common pitfalls when preparing or rolling out **runtime upgrades** on PolkadotSDK-based chains. |
| 4 | + |
| 5 | +- **Two ways to use it** |
| 6 | + - **Library**: one function, `getProblems(uri, options)`, returns a list of problems detected. |
| 7 | + - **CLI**: `check-runtime problems <uri>` for fast local checks and CI. |
| 8 | + |
| 9 | +> ✅ Designed to be **simple**, **deterministic**, and **automation‑friendly**. |
| 10 | +
|
| 11 | +--- |
| 12 | + |
| 13 | +## Table of contents |
| 14 | + |
| 15 | +- [Installation](#installation) |
| 16 | +- [Requirements](#requirements) |
| 17 | +- [CLI Usage](#cli-usage) |
| 18 | + - [Examples](#examples) |
| 19 | + - [Exit codes](#exit-codes) |
| 20 | + - [CI integration](#ci-integration) |
| 21 | + |
| 22 | +- [Programmatic API](#programmatic-api) |
| 23 | + - [Signature](#signature) |
| 24 | + - [Parameters](#parameters) |
| 25 | + - [Return value](#return-value) |
| 26 | + - [Usage examples](#usage-examples) |
| 27 | + |
| 28 | +- [Problem reference](#problem-reference) |
| 29 | +- [Notes & limitations](#notes--limitations) |
| 30 | + |
| 31 | +--- |
| 32 | + |
| 33 | +## Installation |
| 34 | + |
| 35 | +**Using npm** |
| 36 | + |
| 37 | +```bash |
| 38 | +npm i @polkadot-api/check-runtime |
| 39 | +``` |
| 40 | + |
| 41 | +Or run the CLI without installing globally: |
| 42 | + |
| 43 | +```bash |
| 44 | +npx @polkadot-api/check-runtime@latest problems wss://your.chain.rpc |
| 45 | +``` |
| 46 | + |
| 47 | +--- |
| 48 | + |
| 49 | +## Requirements |
| 50 | + |
| 51 | +- **Node.js 22+** |
| 52 | +- A **WebSocket RPC URI** for your chain (e.g. `wss://...`). |
| 53 | + |
| 54 | +--- |
| 55 | + |
| 56 | +## CLI Usage |
| 57 | + |
| 58 | +The CLI exposes a single subcommand (for now), `problems`, that inspects a live chain and/or a provided WASM artifact (that's applied at a certain state of the chain) and prints any detected issues. |
| 59 | + |
| 60 | +``` |
| 61 | +check-runtime problems <uri> [options] |
| 62 | +``` |
| 63 | + |
| 64 | +- `<uri>`: WebSocket RPC endpoint of the chain, e.g. `wss://rpc.ibp.network/polkadot`. |
| 65 | + |
| 66 | +**Options** |
| 67 | + |
| 68 | +| Option | Description | |
| 69 | +| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
| 70 | +| `--wasm <filenameOrUrl>` | A path to a local runtime WASM file **or** a direct URL to download it. When provided, checks are performed against this WASM at the target height (see `--at`). | |
| 71 | +| `--at <block>` | The height **or** block hash at which to check and/or apply the WASM. If omitted, the node’s latest state is used. | |
| 72 | +| `--symbol <symbol>` | The native token symbol. If omitted, it is read from the RPC chainspec. | |
| 73 | +| `--decimals <decimals>` | The native token decimals. If omitted, it is read from the RPC chainspec. | |
| 74 | + |
| 75 | +### Examples |
| 76 | + |
| 77 | +Check a live chain at head: |
| 78 | + |
| 79 | +```bash |
| 80 | +npx @polkadot-api/check-runtime problems wss://sys.ibp.network/statemine |
| 81 | +``` |
| 82 | + |
| 83 | +Check a specific block: |
| 84 | + |
| 85 | +```bash |
| 86 | +npx @polkadot-api/check-runtime problems wss://sys.ibp.network/statemine --at 0xe67351e56ddd9f12f4e67b98c709a58a170b0eb71d168ad0b5bb17fa45becff8 |
| 87 | +``` |
| 88 | + |
| 89 | +Check using a locally built WASM: |
| 90 | + |
| 91 | +```bash |
| 92 | +npx @polkadot-api/check-runtime problems wss://sys.ibp.network/statemine \ |
| 93 | + --wasm ./artifacts/runtime.compact.compressed.wasm |
| 94 | +``` |
| 95 | + |
| 96 | +Check against a WASM downloaded from a URL: |
| 97 | + |
| 98 | +```bash |
| 99 | +npx @polkadot-api/check-runtime problems wss://sys.ibp.network/statemine \ |
| 100 | + --wasm https://github.com/polkadot-fellows/runtimes/releases/download/v1.7.1/asset-hub-kusama_runtime-v1007001.compact.compressed.wasm |
| 101 | + --at 0xe67351e56ddd9f12f4e67b98c709a58a170b0eb71d168ad0b5bb17fa45becff8 |
| 102 | +``` |
| 103 | + |
| 104 | +### Exit codes |
| 105 | + |
| 106 | +- `0`: No problems found: “Everything looks great!” |
| 107 | +- `1`: One or more problems detected (messages printed to stderr). This makes the command **CI‑friendly**. |
| 108 | + |
| 109 | +### CI integration |
| 110 | + |
| 111 | +**GitHub Actions** (minimal): |
| 112 | + |
| 113 | +```yaml |
| 114 | +name: Runtime checks |
| 115 | +on: [push, pull_request] |
| 116 | +jobs: |
| 117 | + check-runtime: |
| 118 | + runs-on: ubuntu-latest |
| 119 | + steps: |
| 120 | + - uses: actions/checkout@v4 |
| 121 | + - uses: actions/setup-node@v4 |
| 122 | + with: |
| 123 | + node-version: 22 |
| 124 | + - run: npx @polkadot-api/check-runtime problems ${{ RPC_URI }} --wasm ${{ TARGET_WASM_FILE }} |
| 125 | +``` |
| 126 | +
|
| 127 | +--- |
| 128 | +
|
| 129 | +## Programmatic API |
| 130 | +
|
| 131 | +### Signature |
| 132 | +
|
| 133 | +```ts |
| 134 | +import { HexString } from "polkadot-api" |
| 135 | + |
| 136 | +declare const Problem: { |
| 137 | + readonly ANCIENT_METADATA: "ANCIENT_METADATA" |
| 138 | + readonly MISSING_MODERN_METADATA: "MISSING_MODERN_METADATA" |
| 139 | + readonly MISSING_RUNTIME_APIS: "MISSING_RUNTIME_APIS" |
| 140 | + readonly DEV_APIS_PRESENT: "DEV_APIS_PRESENT" |
| 141 | + readonly MISSING_CHECK_METADATA_HASH_EXTENSION: "MISSING_CHECK_METADATA_HASH_EXTENSION" |
| 142 | + readonly DIFFERENT_METADATA_HASHES: "DIFFERENT_METADATA_HASHES" |
| 143 | + readonly WRONG_OR_MISSING_METADATA_HASH: "WRONG_OR_MISSING_METADATA_HASH" |
| 144 | +} |
| 145 | + |
| 146 | +type Problem = (typeof Problem)[keyof typeof Problem] |
| 147 | + |
| 148 | +declare function getProblems( |
| 149 | + uri: string, |
| 150 | + options?: Partial<{ |
| 151 | + wasm: HexString |
| 152 | + block: HexString | number |
| 153 | + token: Partial<{ symbol: string; decimals: number }> |
| 154 | + }>, |
| 155 | +): Promise<Array<Problem>> |
| 156 | +``` |
| 157 | +
|
| 158 | +### Parameters |
| 159 | +
|
| 160 | +- `uri` **(string, required)**: WebSocket RPC URI to the target chain. |
| 161 | +- `options` **(optional)** |
| 162 | + - `wasm` **(HexString)**: The runtime code to check, as a hex string. When present, checks are performed against this code (at `block`, if provided). |
| 163 | + - `block` **(number | HexString)**: Height (number) or block hash (hex) at which to evaluate the runtime and metadata. |
| 164 | + - `token` **(Partial<{ symbol: string; decimals: number }> )**: The native token information. If omitted, values are read from the chain’s spec via RPC. |
| 165 | + |
| 166 | +### Return value |
| 167 | + |
| 168 | +A `Promise<Array<Problem>>` with zero or more problem identifiers. See [Problem reference](#problem-reference) for details. |
| 169 | + |
| 170 | +### Usage examples |
| 171 | + |
| 172 | +**Check a live chain at head** |
| 173 | + |
| 174 | +```ts |
| 175 | +import { getProblems } from "@polkadot-api/check-runtime" |
| 176 | +
|
| 177 | +const problems = await getProblems("wss://your.chain.rpc") |
| 178 | +if (problems.length) { |
| 179 | + console.error("Issues detected:", problems) |
| 180 | +} else { |
| 181 | + console.log("Looks great!") |
| 182 | +} |
| 183 | +``` |
| 184 | + |
| 185 | +**Check a specific WASM at a height** |
| 186 | + |
| 187 | +```ts |
| 188 | +import { readFile } from "node:fs/promises" |
| 189 | +import { toHex } from "polkadot-api/utils" |
| 190 | +import { getProblems } from "@polkadot-api/check-runtime" |
| 191 | +
|
| 192 | +const WASM_URI = |
| 193 | + "https://github.com/polkadot-fellows/runtimes/releases/download/v1.7.1/asset-hub-kusama_runtime-v1007001.compact.compressed.wasm" |
| 194 | +const wasm = toHex(await (await fetch(WASM_URI)).bytes()) |
| 195 | +
|
| 196 | +const problems = await getProblems("wss://rpc.my-chain.io", { |
| 197 | + wasm, |
| 198 | + block: 123_456, |
| 199 | +}) |
| 200 | +
|
| 201 | +if (problems.length) { |
| 202 | + console.error("Issues detected:", problems) |
| 203 | +} else { |
| 204 | + console.log("Looks great!") |
| 205 | +} |
| 206 | +``` |
| 207 | + |
| 208 | +--- |
| 209 | + |
| 210 | +## Problem reference |
| 211 | + |
| 212 | +Below are the possible Problems. For each, you’ll see what it means at a high level and why it matters. |
| 213 | + |
| 214 | +| Problem | What it means | Why it matters | |
| 215 | +| --------------------------------------- | --------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | |
| 216 | +| `ANCIENT_METADATA` | The runtime **does not expose modern metadata ≥ v14**. | Tooling that relies on modern metadata (including many SDKs and wallets) will not function correctly. Upgrade the runtime to at least metadata v14. | |
| 217 | +| `MISSING_MODERN_METADATA` | The runtime **only exposes metadata v14**, not newer formats (v15/v16). | Some clients expect v15+ for enhanced correctness and hashing; remaining on v14 can limit compatibility and safety checks. Plan to migrate to v15 or v16. | |
| 218 | +| `MISSING_RUNTIME_APIS` | The **Runtime APIs** required by modern tooling are missing. | Without them, metadata‑driven tools cannot interact reliably. See guidance linked in the CLI output. | |
| 219 | +| `DEV_APIS_PRESENT` | The runtime contains \*\*Development only Runtime APIs. | These APIs are meant for development and should not be present in a production build. | |
| 220 | +| `MISSING_CHECK_METADATA_HASH_EXTENSION` | The **CheckMetadataHash** extension is not supported by this runtime's extrinsic. | Some popular **offline** signers may be able to create transactions for this chain. | |
| 221 | +| `WRONG_OR_MISSING_METADATA_HASH` | The runtime was **compiled without the correct metadata hash** embedded. | Transactions that correctly use `CheckMetadataHash` will be deemed invalid. | |
| 222 | +| `DIFFERENT_METADATA_HASHES` | The **metadata hash differs** between metadata v15 and v16. | Indicates an inconsistency between versions; clients may behave unpredictably. | |
| 223 | + |
| 224 | +> The CLI provides short, actionable messages for each problem and exits with code `1` if any are found. |
| 225 | + |
| 226 | +--- |
| 227 | + |
| 228 | +## Notes & limitations |
| 229 | + |
| 230 | +- The tool **does not submit extrinsics** and does not mutate on‑chain state; it uses Chopsticks behind the scenes. |
| 231 | +- `--at` / `block` accepts **either** a height (number) **or** a block hash (hex string). |
| 232 | +- When `--wasm`/`wasm` is provided **together** with `--at`/`block`, the height is used as the context at which to **check and/or apply** that specific code. |
| 233 | +- If `symbol`/`decimals` are not provided, they are read from the chain-spec via RPC. Keep in mind that's not "on-chain" data, ie: it's safer to provide these values. |
0 commit comments