Back to Learn
Advanced20 min read

Midnight DApp Architecture

Building a DApp on Midnight is fundamentally different from building on Cardano or Ethereum. Midnight's privacy model requires a new mental framework: on-chain state is divided into public and shielded compartments, computation proofs are generated client-side, and the Compact language handles ZK circuit definition. This article explains how it all fits together.

The Midnight programming model

Every Midnight DApp consists of two components: on-chain logic written in Compact (Midnight's ZK circuit definition language), and off-chain logic written in TypeScript. This mirrors Cardano's architecture (Aiken on-chain, MeshJS off-chain) but with the crucial addition that on-chain Compact code generates zero-knowledge proofs during execution.

The TypeScript off-chain layer uses the Midnight SDK to interact with the network, manage private state, generate proofs, and submit transactions. The SDK is the primary developer-facing library and handles the cryptographic complexity behind a clean API.

Compact: defining ZK circuits

Compact is a typed language designed specifically for writing Midnight smart contracts. It looks somewhat like TypeScript but with domain-specific constructs for ZK circuits. A Compact contract defines both a public ledger state (visible to all) and a private witness state (known only to the user).

When a user interacts with a Midnight contract, they provide a witness — private data that satisfies the contract's constraints. The Compact compiler generates the ZK proof circuit, and the Midnight SDK generates a proof that the witness satisfies the constraints, without revealing the witness itself. The proof is attached to the transaction and verified by Midnight nodes.

Shielded vs. public state

Every Midnight contract has two state domains. Public state is written to the Midnight blockchain and is visible to all network participants — equivalent to storage variables in an Ethereum contract. Shielded state exists only in the user's local Midnight wallet; it is never revealed to the network.

The privacy magic happens at the boundary: a Midnight transaction can update public state based on computations performed on shielded state, with a ZK proof guaranteeing the computation was performed correctly. For example, a DApp can update a public 'verified users' mapping based on a user's private KYC credential, without revealing the credential contents.

The witness model

When a user calls a Midnight contract, they provide a witness — the private inputs to the computation. The SDK generates a ZK proof from this witness and the contract's circuit. The proof is submitted to the network along with any public state updates.

Managing witness state is one of the unique challenges of Midnight development. The Midnight SDK provides a local encrypted state store (called the witness store) that persists shielded data between sessions. DApp developers need to design their witness state carefully — what must be private, what can be public, and how state transitions are authorized.

Interaction with Cardano mainchain

Midnight is not isolated from Cardano — the two chains are designed to interoperate. Value can move between Cardano and Midnight through bridging mechanisms. In the Kukolu mainnet phase, interoperability features are being progressively enabled as they are audited and battle-tested.

One key interoperability feature is the ability to prove Cardano-side conditions in Midnight proofs — for example, proving ownership of a Cardano NFT as a credential in a Midnight DApp. This cross-chain composability opens up powerful use cases that leverage both ecosystems.

Development workflow with the Midnight SDK

Setting up a Midnight development environment involves installing the Midnight SDK via npm, installing the Compact compiler, and connecting to either the Midnight devnet or testnet. The official Midnight documentation at docs.midnight.network provides quickstart guides and a counter DApp example as a reference implementation.

A typical development workflow: write Compact contract → compile with `compactc` → generate TypeScript bindings → write TypeScript off-chain logic using the SDK → deploy to testnet → test with the Midnight Lace wallet. The Midnight Lace wallet is a fork of Lace with support for Midnight's shielded state and proof generation.

Key Takeaways

  • Midnight DApps have two layers: Compact (on-chain ZK circuits) and TypeScript with the Midnight SDK (off-chain logic and proof generation).
  • Compact defines both public ledger state and private witness state; ZK proofs allow the public state to be updated based on private computations.
  • The witness model requires careful design of what is shielded vs. public; the Midnight SDK manages the local encrypted witness store.
  • Midnight and Cardano are interoperable — value and credentials can flow between chains through bridging mechanisms.
  • The Midnight Lace wallet is the reference wallet for testing Midnight DApps on devnet and testnet.