Hey Midnight community,
I put together a comprehensive step-by-step guide for developers who want to deploy their first Compact contract on Midnight Preprod. I struggled to find a single resource that covered everything end-to-end, so I wrote one.
What the guide covers (15 sections)
1. What Midnight is and how it differs from other chains
2. Prerequisites (Node.js, Docker, Compact compiler)
3. Full project setup, package.json, tsconfig.json, docker-compose.yml
4. Writing a Hello World contract in Compact (line-by-line explanation)
5. Compiling and what the compiler generates
6. Setting up and monitoring the proof server
7. Understanding the 3-wallet model (Shielded / Unshielded / Dust)
8. Writing the full deploy.ts script (section by section)
9. The full deployment walkthrough
10. Writing a CLI to interact with the deployed contract
11. What actually happens under the hood during a circuit call
12. Troubleshooting, every error I hit, with fixes
SDK versions used
- @midnight-ntwrk/ledger-v8: 8.0.3
- @midnight-ntwrk/midnight-js-contracts: 4.0.1
- @midnight-ntwrk/wallet-sdk-facade: 3.0.0
- midnightntwrk/proof-server:8.0.3 (Docker)
- Node.js v20+, TypeScript 5.x
Gotchas I documented so you don’t have to
1. Proof server version must match ledger-v8 version
Using proof-server:7.0.0 with ledger-v8:8.0.3 causes a transport error during proof generation. The server accepts the connection, starts processing, then silently drops it. The fix: make sure the Docker image tag matches your ledger-v8 version exactly.
2. wallet.start() must be called before waiting for sync
WalletFacade.init() creates the wallet but does not begin syncing. You must call await wallet.start(shieldedSecretKeys, dustSecretKey) first. Without it, wallet.state() never emits and your script hangs forever.
3. levelPrivateStateProvider password validation
The storage password requires at least 3 of 4 character classes. A raw hex seed (lowercase + digits = 2 classes) fails validation. Fix: prefix with Aa1! to satisfy the requirement deterministically.
4. First proof server startup requires patience
The container downloads ~30MB of BLS ZK parameters from S3 on first run. Use a named Docker volume to cache them. Watch for the log line starting service: "actix-web-service-0.0.0.0:6300" before attempting deployment.
Full article: https://eightblock.dev/articles/building-and-deploying-your-first-smart-contract-on-midnight-network
Hope this helps developers getting started. Happy to answer any questions, especially around the wallet model and provider setup, which I found the most confusing parts.