@parity/ppn
v0.6.0
Published
Spin up a local Polkadot ecosystem: fetch, generate, fork and run a network
Maintainers
Keywords
Readme
@parity/ppn
Spawn a local Polkadot ecosystem, a relay chain and its parachains, either from genesis or forked from a live network's state, and drive everything around it: fetching binaries and runtimes, generating chain specs, running the services a network needs, and upgrading a running chain.
npm install -g @parity/ppn # puts `ppn` on your PATH
ppn start # fetch what is missing, then spawnRequires Node.js 24+. Nothing else to configure: the packaged networks come with it, previewnet
by default, and ppn networks lists the rest. ppn kill stops everything.
Point it at your own network
What to run is a descriptor: networks/<name>.json, stating which binary every chain runs,
which release it comes from, which runtime it starts from, and what services and tools it needs.
Bring your own set and ppn runs those instead, against your sources rather than these.
ppn picks a workspace in this order:
$PPN_HOME, if set: a directory containing anetworks/folder;- otherwise the nearest ancestor of your working directory that has one;
- otherwise
~/.ppn, created on first use.
That same directory holds the state: bin/ for downloaded binaries (~500 MB), data/ for chain
state, fork-bundle*/ for bitten networks.
export PPN_HOME=~/my-network # contains networks/my-net.json
ppn show # what resolves: binaries, runtimes, releases, services
ppn start # fetch what is missing, build specs, spawn
ppn kill # stop it, including the auxiliary servicesCommands
| | |
| --- | --- |
| ppn show [network] [--json] | everything a network resolves to; --json is the machine-readable form |
| ppn fetch [--if-needed] | download exactly the binaries and runtimes the descriptor names |
| ppn generate | build the chain specs a genesis network starts from |
| ppn start [--fork] [--clean] | spawn, fetching and generating whatever is missing |
| ppn kill | stop the network and free its ports |
| ppn bite / ppn fork … | capture a live network's state, and spawn from that capture |
| ppn upgrade <chain> <wasm> | authorize and apply a runtime upgrade on a running chain |
| ppn service <name> | the processes the spawner starts alongside the nodes |
Overriding versions
Any release or binary can be repointed without editing a descriptor, which is what makes this useful in a release gate. Run the same network against a candidate build:
ppn fetch --binary polkadot-omni-node=paritytech/release-automation@polkadot-weekly2026w37-rc1
ppn fetch --release polkadot-sdk=paritytech/polkadot-sdk@polkadot-stable2609-rc1
ppn fetch --binary polkadot-omni-node=file:/path/to/your/build
# or through the environment, for anything that cannot take flags
PPN_BINARIES="polkadot-omni-node=paritytech/release-automation@latest" ppn startOverrides are applied inside the loader, so fetch, generate, bite and show cannot disagree
about what is running. An unknown binary or release name is refused rather than ignored, and
ppn show --json marks every overridden slot, so a gate can report what actually executed instead
of what it asked for.
Authentication
ppn fetch reads GitHub releases. The packaged networks name only public ones, so a token is
about rate limits rather than access: a fetch pulls a lot of assets, and anonymous requests are
throttled hard. It uses GITHUB_TOKEN if set, otherwise the credentials gh auth login writes
for git. Your own descriptors may of course name private releases, and when a token cannot see
one the fetch fails naming the artifact and the repository rather than leaving bin/
half-populated.
Reading a network from code
@parity/ppn-network-config exposes the same descriptor loading as a library, for tools that want
the facts without shelling out:
import { loadNetwork, networkChains, networkBinaries } from '@parity/ppn-network-config';
const net = loadNetwork('my-net');
networkChains(net).map((c) => [c.key, c.binary.name]);