A Midnight smart contract example demonstrating counter functionality with zero-knowledge proofs on testnet.
example-counter/
├── contract/ # Smart contract in Compact language
│ ├── src/counter.compact # The actual smart contract
│ └── src/test/ # Contract unit tests
└── counter-cli/ # Command-line interface
└── src/ # CLI implementation
You need NodeJS version 22.15 or greater:
node --versionExpected output: v22.15.0 or higher.
If you get a lower version: Install Node.js 22+.
The proof server runs in Docker, so you need Docker Desktop:
docker --versionExpected output: Docker version X.X.X.
If Docker is not found: Install Docker Desktop. Make sure Docker Desktop is running (not just installed).
The Compact compiler converts smart contracts written in the Compact language into executable circuits for zero-knowledge proof generation.
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/midnightntwrk/compact/releases/latest/download/compact-installer.sh | shsource $HOME/.local/bin/env # bash/zsh/sh
source $HOME/.local/bin/env.fish # fishcompact update 0.25.0
compact compile --versionExpected output: 0.25.0.
If command not found: Restart your terminal and try the
sourcecommand again.
npm installThe Compact compiler generates TypeScript bindings and zero-knowledge circuits from the smart contract source code. Navigate to contract directory and compile the smart contract:
cd contract && npm run compactExpected output:
Compiling 1 circuits:
circuit "increment" (k=10, rows=29)
Note: First time may download zero-knowledge parameters (~500MB). This is normal and happens once.
Build TypeScript files and run tests:
npm run build && npm run testNavigate to CLI directory and build the project:
cd ../counter-cli && npm run buildThe proof server generates zero-knowledge proofs for transactions locally to protect private data. It must be running before you can deploy or interact with contracts.
Pull the Docker image:
docker pull midnightnetwork/proof-server:latestThen start the proof server (keep this terminal open):
docker run -p 6300:6300 midnightnetwork/proof-server -- 'midnight-proof-server --network testnet'Expected output:
INFO midnight_proof_server: This proof server processes transactions for TestNet.
INFO actix_server::server: starting service: "actix-web-service-0.0.0.0:6300"
Keep this terminal running! The proof server must stay active while using the DApp.
This should start proof server automatically, but may fail if Docker isn't properly configured:
npm run testnet-remote-psIf this fails with "Could not find a working container runtime strategy", use Option A instead.
Open a new terminal (keep proof server running in the first one).
cd counter-cli && npm run start-testnet-remoteThe CLI uses a headless wallet (separate from browser wallets like Lace) that can be called through library functions.
- Choose option
1to build a fresh wallet - The system will generate a wallet address and seed
- Save both the address and seed - you'll need them later
Expected output:
Your wallet seed is: [64-character hex string]
Your wallet address is: mn_shield-addr_test1...
Your wallet balance is: 0
Before deploying contracts, you need testnet tokens.
- Copy your wallet address from the output above
- Visit the testnet faucet
- Paste your address and request funds
- Wait for the CLI to detect the funds (takes 2-3 minutes)
Expected output:
Your wallet balance is: 1000000000
- Choose option
1to deploy a new counter contract - Wait for deployment (takes ~30 seconds)
- Save the contract address for future use
Expected output:
Deployed contract at address: [contract address]
You can now:
- Increment the counter (submits a transaction to testnet)
- Display current counter value (queries the blockchain)
- Exit when done
Each increment creates a real transaction on Midnight Testnet.
Next time you run the DApp:
- Choose option
2to build wallet from seed - Enter your saved seed
- Choose option
2to join existing contract - Enter your saved contract address
- Testnet Faucet - Get testnet funds
- Midnight Documentation - Complete developer guide
- Compact Language Guide - Smart contract language reference
| Issue | Solution |
|---|---|
compact: command not found |
Run source $HOME/.local/bin/env then compact compile --version |
connect ECONNREFUSED 127.0.0.1:6300 |
Start proof server: docker run -p 6300:6300 midnightnetwork/proof-server -- 'midnight-proof-server --network testnet' |
| Could not find a working container runtime strategy | Docker isn't running properly. Restart Docker Desktop and try again |
| Tests fail with "Cannot find module" | Compile contract first: cd contract && npm run compact && npm run build && npm run test |
| Wallet seed validation errors | Enter complete 64-character hex string without extra spaces |
| Node.js warnings about experimental features | Normal warnings - don't affect functionality |