---
title: Metadata and SDK generation
description: EmpoorioChain has no IDL — clients are generated from the runtime metadata, which changes at every upgrade.
---

# Metadata and SDK generation

Substrate chains describe themselves through **runtime metadata**, not an IDL. Every pallet, storage item, extrinsic, event and type is in `state_getMetadata` of the live node.

## Rules learned the hard way

1. **The metadata changes at every runtime upgrade** — the `spec_version` lives inside it. Runtime 208 → 220 in two weeks meant ten regenerations. Regenerate after each upgrade; pin the spec version you generated against.
2. **Compare at startup.** The Dart SDK bakes `System::Version` at generation time and Eoonia compares it with the chain's on connect; a mismatch fails loudly instead of decoding garbage.
3. **Never enumerate calls by position.** Call indices are explicit (`set_manufacturer` is index 90 while listed first). Read the index from the metadata.
4. **Hardcoded envelopes break.** The signed extra carries `CheckPqcPolicy` (2 bytes, first) and `CheckDormantAccount` (zero-size). A library that does not build the envelope from metadata produces signatures the node rejects.

## Generators

- TypeScript: `@polkadot/api` + `@polkadot/typegen` against `wss://rpc.testnet.empooriochain.org`
- Dart: `polkadart_cli` → `empoorio_chain_sdk` (the wallet's SDK; metadata byte-identical to the live node)
- Rust: `subxt codegen --url wss://rpc.testnet.empooriochain.org`

## EVM side

Solidity ABIs work as usual on chain id 2026; `eth_getCode("latest")` is unreliable (see the EVM note).
