Skip to main content

Local development with gnodev

gnodev is a local Gno.land node bundled with gnoweb, designed for a fast edit → save → reload loop. Use it instead of deploying to a network while you're still iterating on code.

For a first-realm walkthrough, see Getting started.

gnodev ships with the Gno toolchain. If gnodev --help fails, install it from the installation guide.

Quick start

Run gnodev from a package directory that has a gnomod.toml. The gnomod.toml declares the path the package deploys under:

module = "gno.land/r/dev/counter"
gno = "0.9"

Then start the node:

gnodev .

You should see output along these lines:

Loader      ┃ I workspace detected root={your_pwd}
Accounts ┃ I default address imported name=devtest addr=g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5
Proxy ┃ I lazy loading is enabled. packages will be loaded only upon a request via a query or transaction. loader=native
Node ┃ I packages paths=[gno.land/r/dev/counter]
GnoWeb ┃ I gnoweb started lisn=http://127.0.0.1:8888
--- READY ┃ I for commands and help, press `h` took=1.4s

Open http://localhost:8888 to browse your realm via the built-in gnoweb (change the address with -web-listener). The devtest account is preloaded with funds, so no faucet is needed. Press h at any time for the in-terminal help menu (see Interactive controls).

Modes

gnodev runs in one of two modes, picked by subcommand:

  • gnodev local is the default when you run gnodev with no subcommand. It is tuned for iterating locally: interactive controls, the unsafe /reset and /reload endpoints, and console logs. The workspace and every -extra-root load up front; examples/ packages resolve on demand the first time they're referenced.
  • gnodev staging is tuned for server use: no interactive mode, no unsafe API, and JSON logs. On top of the workspace and -extra-root, all of examples/ is eager-loaded at startup (use -no-examples to skip it).

Features

Automatic deployment

gnodev deploys the working directory's package to the built-in node automatically, with no addpkg step. Pass several directories (gnodev ./realmA ./realmB) to deploy and hot-reload them together. Packages and realms in the monorepo's examples/ folder are resolved on demand, the first time a query or transaction references them, so they're importable without deploying them yourself.

To make packages outside the working directory and examples/ resolvable, add their root with -extra-root <dir> (repeatable). Every package under an extra root is loaded, so they're available without deploying them by hand.

Package path resolution:

  • If a gnomod.toml is present, the path inside is used.
  • Otherwise, gnodev derives the path from the directory name and deploys under gno.land/r/dev/<dirname>, where <dirname> is sanitized to a valid path segment: lowercased, non-alphanumerics collapsed to underscores. A name with no letters falls back to app, and a leading digit is prefixed with d (the path must start with a letter).

See Configuring Gno projects for gnomod.toml details. The default deployer is devtest1; override with -deploy-key.

The devtest account is automatically imported and pre-funded with locally usable GNOT. It is available for immediate use in development and testing.

Premining

Every key in your local gnokey keybase is prefunded on the built-in node. Press A while gnodev is running to list balances:

Accounts    ┃ I (2) known keys
┃ │ KeyName Address Balance
┃ │ devtest g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5 10000000000000ugnot
┃ │ MyKey g1q4q3uegdnq9rsvf3xgxydr3yqd2v6w2tww5920 10000000000000ugnot

This is local-only; on remote networks you still need the faucet.

To fund an address you don't hold a key for, or to set a specific balance, use -add-account <name|addr>[=<amount>] (repeatable), or seed many at once from a file with -balance-file <file>. Replay a set of genesis transactions at startup with -txs-file <file>; its signers are auto-premined and the packages it references are auto-loaded. The -balance-file and -txs-file flags cannot be combined with -genesis.

The -balance-file format is one <address>=<amount>ugnot entry per line, with # comments allowed:

g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5=10000000000000ugnot # test1
g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj=10000000000000ugnot # test2

The -txs-file format is one JSON transaction per line, each wrapped in a tx field. Build the inner transaction with the first steps of making an airgapped transaction:

{"tx": {"msg":[{"@type":"/vm.m_call","caller":"g1us8428u2a5satrlxzagqqa5m6vmuze025anjlj","send":"","pkg_path":"gno.land/r/demo/counter","func":"Increment","args":[]}],"fee":{"gas_wanted":"2000000","gas_fee":"1000000ugnot"},"signatures":[{"pub_key":{"@type":"/tm.PubKeySecp256k1","value":"AmG6kzznyo1uNqWPAYU6wDpsmzQKDaEOrVRaZ08vOyX0"},"signature":""}],"memo":""}}

Hot reload

gnodev watches the working directory and reloads the node on every .gno save, replaying prior transactions to preserve state across reloads.

Genesis and node tuning

gnodev can also load a genesis file with -genesis <file> to seed the built-in node with a custom state, and exposes flags to tune node behavior (RPC listener, web listener, chain ID, …). See gnodev --help for the full list.

Calling your realm

Once gnodev is running, you can drive your realm from another terminal using gnokey against the local node. The defaults are -remote 127.0.0.1:26657 and -chainid dev:

gnokey maketx call \
-pkgpath "gno.land/r/dev/counter" \
-func "Increment" \
-gas-fee 1000000ugnot -gas-wanted 20000000 \
-broadcast \
-chainid dev -remote 127.0.0.1:26657 \
devtest

Response (Increment takes no argument and returns the new count):

(1 int)
OK!
GAS WANTED: 20000000
GAS USED: 126933
HEIGHT: 203
EVENTS: []
INFO:
TX HASH: k+WuKgPpoAg+EcR2EnzqxeWqUXB4KhOhg3l6zthSy0I=

Refresh http://localhost:8888 to see the updated Render() output. The devtest key works out of the box because it's premined (see above); swap it for any other key in your keybase.

If you start gnodev on a non-default RPC port, point -remote at the same address. For example, started with:

gnodev -node-rpc-listener 127.0.0.1:36657

the call above must use -remote 127.0.0.1:36657.

Interactive controls

These keys work while gnodev is running in interactive mode (case-insensitive). Interactive mode is on by default in gnodev local when standard output is a terminal; it turns off when output is piped or redirected, and in gnodev staging. Pass -interactive to force it:

KeyAction
HShow the in-terminal help menu
AList known accounts and balances
RReload all packages
N / PStep to the next / previous transaction
EExport the current state as a genesis doc
Ctrl+SSave the current state
Ctrl+RReset to the initial or last-saved state
Ctrl+CExit

Useful flags

FlagPurpose
-deploy-key <name>Override the default deployer (devtest)
-extra-root <dir>Add another directory tree whose packages are resolvable, alongside the working directory and examples/ (repeatable)
-remote <domain>=<rpc>Fetch missing packages for a chain domain from its RPC, as <domain>=<rpc> (e.g. gno.land=https://rpc.staging.gno.land:443). Only domains given an entry are fetched; with no -remote, gnodev never reaches the network for packages
-paths <paths>Preload extra package paths, comma-separated (e.g. gno.land/r/my/realm)
-no-examplesSkip loading $GNOROOT/examples entirely
-add-account <name|addr>[=<amount>]Premine or set the balance of an account (repeatable)
-balance-file <file>Seed account balances from a file (cannot be combined with -genesis)
-txs-file <file>Replay genesis transactions at startup; signers are auto-premined and referenced packages auto-loaded (cannot be combined with -genesis)
-genesis <file>Load a custom genesis file at startup
-node-rpc-listener <addr>Node RPC listen address (default 127.0.0.1:26657); gnokey -remote must match it
-web-listener <addr>gnoweb listen address (default 127.0.0.1:8888)
-no-webRun without gnoweb
-unsafe-apiExpose the /reset and /reload HTTP endpoints (on in local, off in staging)
-interactiveForce interactive controls when stdout is not a terminal (on by default in local at a terminal, off in staging)
-no-watchDisable file watching
-no-replaySkip transaction replay across reloads

Run gnodev --help for the full flag list.

See also

Footnotes

  1. devtest corresponds to address g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5. Its mnemonic is publicly known. Never use it on production networks or for real funds.