To connect to a blockchain network like Polkadot, the fundamental requirement is a provider, which acts as a bridge between your application and the chain. Providers typically connect to an RPC (Remote Procedure Call) endpoint, which allows your app to retrieve data like blocks and events. However, simply connecting to the chain doesn’t enable full interaction.
To interact with the chain — whether by querying storage, making transactions, or calling runtime methods — you also need to understand what data is available and how to format it. This is where metadata becomes crucial. The chain's metadata contains a detailed description of all the storage items, runtime functions, and transactions available on that network, as well as their data types.
Here’s how the process works:
During runtime, PAPI can automatically request the metadata from the chain you're connected to. From this metadata, it generates codecs (serialization and deserialization tools) to communicate with the chain's functions and storage. Before development, however, you need to have this information ready, in order to make your life easier on knowing how to communicate with the chain.
PAPI simplifies this with its CLI (Command Line Interface), which allows you to download the chain’s metadata ahead of time. This metadata is then used to generate all the necessary type descriptors, so you don’t have to manually figure out the structure of every interaction.
In practice, using the CLI to download metadata ensures that your app stays in sync with the specific network you're developing for, especially if that chain undergoes runtime upgrades or type changes.
That CLI's syntax is:
$ npx papi add --helpUsage: polkadot-api add [options] <key>Add a new chain spec to the listArguments:key Key identifier for the chain specOptions:--config <filename> Source for the config file-f, --file <filename> Source from metadata encoded file-w, --wsUrl <URL> Source from websocket URL-c, --chainSpec <filename> Source from chain spec file-n, --name <name> Source from a well-known chain (choices: "ksmcc3", "paseo","polkadot", "polkadot_collectives", "rococo_v2_2", "westend2", [...]")--wasm <filename> Source from runtime wasm file--no-persist Do not persist the metadata as a file--skip-codegen Skip running codegen after adding-h, --help display help for command
The papi add
command is used to register a new chain in your Polkadot project. When running this command, you need to provide a key — a unique identifier that will be used as a constant name when generating code for the chain. Additionally, you specify a source for the chain’s metadata using one of the following flags:
-f
, -w
, -c
, -n
, or --wasm
, depending on whether the metadata comes from a file, websocket, chain, or other source.The command then downloads the latest metadata for the chain and stores it in a .papi folder. This folder contains:
polkadot-api.json
, which holds the setup information for the chain.${key}.scale
, which contains the chain's specific metadata for later use.This structure ensures that all the necessary metadata for interacting with the chain is preloaded and organized, streamlining your development process.
Now that the CLI is understood, let's get going with this and run:
$ bunx papi add dot -n polkadot
Note: bunx is the equivelent package runner for bun (as npx is for npm). You can read more here.
What happened here?
Using bunx
we asked (politely) from Polkadot API to fetch for you, in a dot
"variable", the metadata from (the well-known-chain) polkadot
.
The outcome of the command should be the following:
$ bunx papi add dot -n polkadot✔ Metadata saved as .papi/metadata/dot.scaleSaved new spec "dot"Reading metadataCLI Building entry: .papi/descriptors/src/index.tsCLI Using tsconfig: tsconfig.jsonCLI tsup v8.3.0CLI Target: esnextCJS Build startESM Build startESM .papi/descriptors/dist/index.mjs 9.88 KBESM .papi/descriptors/dist/metadataTypes-FYTIEX4M.mjs 146.06 KBESM .papi/descriptors/dist/descriptors-BGFWDDEF.mjs 25.73 KBESM ⚡️ Build success in 20msCJS .papi/descriptors/dist/index.js 190.36 KBCJS ⚡️ Build success in 20msCompilation startedCompilation successfulbun installbun install v1.1.7 (b0b7db5c)+ @polkadot-api/descriptors@.papi/descriptors1 package installed [19.00ms]
So what PAPI did for you, behind the scenes?
.papi
and under it in the dir metadata
saved all the latest metadata for polkadot
;package.json
file added a dependency link to the descriptors that are created: "@polkadot-api/descriptors": "file:.papi/descriptors",
..papi
directory, created a PAPI configuration file called polkadot-api.json
that looks like this:{"version": 0,"descriptorPath": ".papi/descriptors","entries": {"dot": {"chain": "polkadot","metadata": ".papi/metadata/dot.scale"}}}
and contains in entries
the "variable" dot
, linked to the respective chain and metadata;
Note: the command
bunx papi add dot -n polkadot
is "same" if we used an RPC endpoint with the flag -w. "Same" should not be lightly taken into account. This is not entiredly correct. If the PAPI's entries are used instead of an RPC endpoint, then the metadata are downloaded in a more decentralized manner - instead of being downladed from 1 specific url.
$ bunx papi add -w wss://polkadot-collectives-rpc.polkadot.io dot
but since
polkadot
is a known chain, the first command will suffice
In just few words - configured all the paths and needed dependencies with just 1 command.
Let's run the commands for the rest of the chains we need:
$ bunx papi add people -n polkadot_people
and
$ bunx papi add collectives -n polkadot_collectives
Configuration is now finished! All the necessary chains are set up in your project, and the metadata is neatly organized in a structured directory.
Note: It’s a great idea to add PAPI to the "postinstall" script in your package.json to automate the generation of types after installation. (see
package.json
file for how that looks.)