Ga naar hoofdinhoud

Local Development Network

Run a single-node local Monolythium chain for development and testing. A local devnet provides instant block times, zero gas costs, and full control over chain state.


Prerequisites

  • monod binary installed (Installation Guide)
  • Go 1.21+ (if building from source)
  • Node.js 18+ (for Hardhat/Foundry frontend tests)

Initialize the Node

# Remove any existing state
rm -rf ~/.mono

# Initialize a fresh local chain
monod init localtest --chain-id mono-local-1

# Create a test key (no password prompt with test backend)
monod keys add devkey --keyring-backend test

Save the mnemonic output from keys add -- you will need it to connect wallets.


Configure Genesis

Fund your development account and tune the chain for fast iteration.

Fund Accounts

# Get your address
DEV_ADDR=$(monod keys show devkey -a --keyring-backend test)

# Add genesis account with 1 billion LYTH
monod genesis add-genesis-account $DEV_ADDR 1000000000000000000000000000alyth

# Create gentx (self-delegate as validator)
monod genesis gentx devkey 100000000000000000000000alyth \
--chain-id mono-local-1 \
--keyring-backend test

# Collect genesis transactions
monod genesis collect-gentxs

Fast Block Configuration

Edit ~/.mono/config/config.toml for near-instant blocks:

[consensus]
timeout_propose = "200ms"
timeout_prevote = "100ms"
timeout_precommit = "100ms"
timeout_commit = "500ms"

Low Gas Prices

Edit ~/.mono/config/app.toml:

# Accept zero-fee transactions for development
minimum-gas-prices = "0alyth"

[json-rpc]
enable = true
address = "0.0.0.0:8545"
ws-address = "0.0.0.0:8546"
api = "eth,net,web3,txpool,debug,personal"

Enable CORS (for Browser dApps)

In ~/.mono/config/config.toml:

[rpc]
cors_allowed_origins = ["*"]

In ~/.mono/config/app.toml:

[api]
enable = true
address = "tcp://0.0.0.0:1317"
enabled-unsafe-cors = true

[grpc]
enable = true
address = "0.0.0.0:9090"

Start the Node

monod start

You should see blocks produced every ~500ms. The following endpoints become available:

ServiceURL
EVM JSON-RPChttp://localhost:8545
EVM WebSocketws://localhost:8546
Cosmos RPChttp://localhost:26657
REST APIhttp://localhost:1317
gRPClocalhost:9090
Background Mode

Run in the background with output to a log file:

monod start > ~/.mono/devnet.log 2>&1 &

Connecting Hardhat

// hardhat.config.js
require("@nomicfoundation/hardhat-toolbox");

module.exports = {
solidity: "0.8.24",
networks: {
local: {
url: "http://localhost:8545",
chainId: 262146, // mono-local-1 EVM chain ID (derived from chain-id)
accounts: {
mnemonic: "your devkey mnemonic here",
},
gas: "auto",
gasPrice: "auto",
},
},
};

Deploy contracts:

npx hardhat run scripts/deploy.js --network local
EVM Version

Monolythium targets the paris EVM version. Set this in your Hardhat config:

solidity: {
version: "0.8.24",
settings: { evmVersion: "paris" },
},

Connecting Foundry

# Deploy with Foundry
forge create src/MyContract.sol:MyContract \
--rpc-url http://localhost:8545 \
--private-key $DEVKEY_PRIVATE_KEY \
--legacy \
--gas-limit 3000000

# Run tests against local node
forge test --fork-url http://localhost:8545

Add to foundry.toml:

[profile.default]
evm_version = "paris"

[rpc_endpoints]
local = "http://localhost:8545"
Legacy Transactions

Use the --legacy flag with Foundry. Monolythium uses the feemarket module but local devnets may not have a populated base fee history.


Connecting CosmJS

import { SigningStargateClient, GasPrice } from "@cosmjs/stargate";
import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";

const wallet = await DirectSecp256k1HdWallet.fromMnemonic(
"your devkey mnemonic here",
{ prefix: "mono" }
);

const client = await SigningStargateClient.connectWithSigner(
"http://localhost:26657",
wallet,
{ gasPrice: GasPrice.fromString("0alyth") }
);

const [account] = await wallet.getAccounts();
const balance = await client.getBalance(account.address, "alyth");
console.log("Balance:", balance);

Docker (Optional)

If you prefer containerized development, use a single-node Docker setup:

docker run -d \
--name mono-local \
-p 8545:8545 \
-p 8546:8546 \
-p 26657:26657 \
-p 1317:1317 \
-p 9090:9090 \
-e CHAIN_ID=mono-local-1 \
-e MINIMUM_GAS_PRICES=0alyth \
ghcr.io/mono-labs-org/monod:latest \
monod start
info

The Docker image includes a pre-initialized genesis with a funded account. Check the image documentation for the default mnemonic and addresses.


Reset Chain State

To wipe all state and start fresh:

# Stop the node first
monod tendermint unsafe-reset-all

Or remove everything and re-initialize:

rm -rf ~/.mono
# Re-run the initialization steps above

Faucet for Local Development

For local testing, you already have a fully funded genesis account. To fund additional addresses:

monod tx bank send devkey mono1newaddress... 1000000000000000000000alyth \
--chain-id mono-local-1 \
--keyring-backend test \
--gas auto \
--gas-adjustment 1.5 \
--yes

Troubleshooting

Node won't start after genesis changes

Reset state with monod tendermint unsafe-reset-all and reinitialize.

EVM transactions fail with "invalid chain ID"

The EVM chain ID is derived from the Cosmos chain ID. For mono-local-1, use the numeric chain ID returned by eth_chainId.

Blocks aren't being produced

Ensure the gentx was collected (monod genesis collect-gentxs) and the validator has sufficient self-delegation.

MetaMask can't connect

Verify CORS is enabled and the JSON-RPC address binds to 0.0.0.0 (not 127.0.0.1).