- Overview
- Architecture
- Technology Stack
- Project Structure
- Smart Contract Details
- API Layer
- User Interfaces
- Installation Guide
- Development Workflow
- Testing
- Deployment
- Network Configuration
- Security Considerations
- Troubleshooting
- Contributing
This project implements a Know Your Customer (KYC) attestation system on the Midnight Network blockchain. It's a privacy-preserving DApp that verifies user eligibility based on age and country requirements without revealing the actual personal data on-chain.
- Privacy-First: Uses zero-knowledge proofs to verify eligibility without exposing sensitive data
- Flexible Policies: Configurable age and country requirements
- Admin Controls: Owner-managed attestation system with governance capabilities
- Multi-Interface: Supports both CLI and web browser interactions
- Testnet Ready: Fully integrated with Midnight Network testnet
- Age verification for regulated services
- Country-based access control
- Compliance with KYC/AML regulations
- Privacy-preserving identity verification
graph TB
subgraph "User Interfaces"
UI[Web UI<br/>React + Material-UI]
CLI[CLI Application<br/>Node.js]
end
subgraph "API Layer"
API[BBoardAPI<br/>TypeScript]
TYPES[Common Types]
end
subgraph "Smart Contract"
CONTRACT[bboard.compact<br/>Compact 0.17]
WITNESSES[Witness Functions<br/>TypeScript]
end
subgraph "Midnight Network"
BLOCKCHAIN[Midnight Blockchain]
INDEXER[Indexer Service]
PROOF[Proof Server]
end
subgraph "Storage"
PRIVATE[Private State<br/>LevelDB]
PUBLIC[Public Ledger]
end
UI --> API
CLI --> API
API --> CONTRACT
API --> WITNESSES
CONTRACT --> BLOCKCHAIN
WITNESSES --> PRIVATE
BLOCKCHAIN --> PUBLIC
BLOCKCHAIN --> INDEXER
API --> PROOF
- User Layer: Web UI or CLI interface for user interactions
- API Layer: Abstracts contract complexity and manages state
- Contract Layer: Compact smart contract with witness functions
- Network Layer: Midnight blockchain and supporting services
- Storage Layer: Private state (local) and public ledger (on-chain)
- Blockchain: Midnight Network (privacy-focused blockchain)
- Smart Contract Language: Compact v0.17
- Runtime: Node.js v18+ / TypeScript 5.8.3
- Frontend Framework: React 19
- UI Components: Material-UI v5
- Build Tool: Vite 7.0.0
- Package Manager: npm (with workspaces)
{
"@midnight-ntwrk/compact-runtime": "^0.8.1",
"@midnight-ntwrk/midnight-js-contracts": "^2.0.2",
"@midnight-ntwrk/wallet": "^5.0.0",
"rxjs": "^7.8.2",
"fp-ts": "^2.16.10",
"pino": "^9.7.0"
}repoMidNight/
├── 📁 api/ # Shared API and types
│ ├── src/
│ │ ├── index.ts # Main API implementation
│ │ └── common-types.ts # Shared type definitions
│ ├── package.json
│ └── tsconfig.json
│
├── 📁 contract/ # Smart contract
│ ├── src/
│ │ ├── bboard.compact # Main KYC contract (Compact)
│ │ ├── witnesses.ts # Witness functions
│ │ ├── index.ts # Contract exports
│ │ └── managed/ # Compiled artifacts
│ │ └── bboard/
│ │ └── contract/
│ ├── package.json
│ └── tsconfig.json
│
├── 📁 bboard-cli/ # CLI application
│ ├── src/
│ │ ├── index.ts # CLI entry point
│ │ ├── config.ts # Network configurations
│ │ └── logger-utils.ts # Logging utilities
│ ├── package.json
│ └── README.md
│
├── 📁 bboard-ui/ # Web interface
│ ├── src/
│ │ ├── App.tsx # Main React component
│ │ ├── main.tsx # Application entry
│ │ ├── components/ # UI components
│ │ ├── contexts/ # React contexts
│ │ └── hooks/ # Custom React hooks
│ ├── package.json
│ └── vite.config.ts
│
├── 📁 .github/ # GitHub templates
│ ├── ISSUE_TEMPLATE/
│ └── PULL_REQUEST_TEMPLATE/
│
├── 📄 package.json # Root workspace config
├── 📄 WARP.md # AI assistant guide
├── 📄 README.md # Basic readme
├── 📄 CHANGELOG.md # Version history
├── 📄 CONTRIBUTING.md # Contribution guidelines
└── 📄 SECURITY.md # Security policies
The KYC attestation contract implements a privacy-preserving identity verification system.
struct Attestation {
epoch: Uint<64>; // Policy version when issued
adult: Uint<1>; // 1 if meets age requirement
inCountry: Uint<1>; // 1 if in allowed country
}
ledger epoch: Counter; // Policy version counter
ledger instance: Counter; // Contract instance ID
ledger attest: Map<Bytes<32>, Attestation>; // User attestations
ledger allowedCountry: Bytes<2>; // ISO country code
ledger allowedMinAge: Uint<8>; // Minimum age requirement
bumpEpoch(): Increment policy versionrevokeUpk(uPk): Remove user attestationsetAdultFlag(uPk, v): Manually set adult statussetCountryFlag(uPk, v): Manually set country statussetAllowedMinAge(age): Update age requirementsetAllowedCountry(country): Update country requirement
enrollOnce(ageBytes, country): Initial KYC enrollmentselfUpgradeToAdult(ageBytes): Age-based status upgradeselfRefreshCountry(country): Update country status
checkAdultByUpk(uPk): Check if user is adultcheckCountryByUpk(uPk): Check if user in allowed countrycheckEligibleByUpk(uPk): Check full eligibilitycheckAdultSelf(): Self-check adult statuscheckCountrySelf(): Self-check country statuscheckEligibleSelf(): Self-check eligibility
Located in contract/src/witnesses.ts, these functions manage private state:
export const witnesses = {
localSecretKey: privateStateKey('localSecretKey')
};The witness system ensures that sensitive data (secret keys, age, country) never appear on-chain.
The main API class (api/src/index.ts) provides:
class BBoardAPI {
// Deployment and joining
static async deploy(providers, logger): Promise<BBoardAPI>
static async join(providers, contractAddress, logger): Promise<BBoardAPI>
// State management
ledgerState$: Observable<BBoardDerivedState>
// Transaction submission
async enrollOnce(age: number, country: string): Promise<TransactionId>
async selfUpgradeToAdult(age: number): Promise<TransactionId>
async selfRefreshCountry(country: string): Promise<TransactionId>
// Admin functions
async setAllowedMinAge(age: number): Promise<TransactionId>
async setAllowedCountry(country: string): Promise<TransactionId>
async revokeUpk(userPublicKey: Bytes<32>): Promise<TransactionId>
}The system requires multiple providers:
interface BBoardProviders {
privateStateProvider: PrivateStateProvider; // Local state
zkConfigProvider: ZkConfigProvider; // ZK circuits
proofProvider: ProofProvider; // Proof generation
publicDataProvider: PublicDataProvider; // Blockchain queries
walletProvider: WalletProvider; // Transaction signing
midnightProvider: MidnightProvider; // Network submission
}The browser interface provides:
- Contract deployment wizard
- User enrollment form
- Attestation status viewer
- Admin control panel
- Wallet integration (Midnight Lace)
Key Components:
App.tsx: Main application componentBoard.tsx: Contract interaction boardDeployedBoardProvider: Context for contract stateBrowserDeployedBoardManager: Wallet integration
Interactive command-line interface offering:
- Contract deployment/joining
- Message posting/removal
- State inspection (ledger, private, derived)
- Network configuration options
Menu Options:
1. Deploy a new bulletin board contract
2. Join an existing bulletin board contract
3. Post a message
4. Take down your message
5. Display current states
6. Exit
- Node.js v18+ and npm v8+
- Git
- Midnight Lace wallet (for browser UI)
- Access to Midnight testnet
# 1. Clone repository
git clone https://github.com/your-repo/repoMidNight.git
cd repoMidNight
# 2. Install root dependencies
npm install --legacy-peer-deps
# 3. Build API package
cd api
npm install
npm run build
cd ..
# 4. Build contract
cd contract
npm install
npm run compact # Compile Compact contract
npm run build # Build TypeScript
cd ..
# 5. Setup CLI (optional)
cd bboard-cli
npm install
npm run build
cd ..
# 6. Setup Web UI (optional)
cd bboard-ui
npm install
npm run build
cd ..cd contract
# Edit contract
vim src/bboard.compact
# Compile contract
npm run compact
# Run tests
npm run test
# Build TypeScript
npm run buildcd api
# Edit API
vim src/index.ts
# Build
npm run build
# Type check
npm run typecheck
# Lint
npm run lintcd bboard-ui
# Start dev server with hot reload
npm run dev
# Build for production
npm run build
# Start production server
npm run build:startcd bboard-cli
# Build CLI
npm run build
# Run against testnet
npm run testnet-remote
# Run locally
npm run testnet-localcd contract
npm run testTests use Vitest framework and cover:
- Enrollment scenarios
- Policy updates
- Attestation queries
- Access control
# Run full stack test
cd bboard-cli
npm run test:integration- Deploy contract via CLI
- Set policies (age, country)
- Enroll test user
- Verify attestation
- Test admin functions
cd bboard-cli
# Configure testnet
export MIDNIGHT_NETWORK=testnet
export PROOF_SERVER_URL=https://proof.testnet.midnight.network
# Deploy contract
npm run testnet-remote
# Select "1" to deploy new contract
# Note the contract address- Update network configuration in
config.ts - Set production proof server URL
- Deploy via secure environment
- Transfer ownership to multisig/DAO
# Build Docker image
docker build -t midnight-kyc .
# Run container
docker run -p 3000:3000 midnight-kyc{
indexer: "https://indexer.testnet.midnight.network",
proofServer: "https://proof.testnet.midnight.network",
node: "wss://node.testnet.midnight.network"
}{
indexer: "http://localhost:8080",
proofServer: "http://localhost:3000",
node: "ws://localhost:9944"
}{
indexer: "http://localhost:8080",
proofServer: "http://localhost:3000",
node: "ws://localhost:9944"
}bboard-cli/src/config.ts: Network endpointsbboard-ui/src/globals.ts: Browser configuration.env: Environment variables (create from.env.example)
- Secret keys stored locally via LevelDB
- Never transmitted or stored on-chain
- Derived public keys used for identification
- Age/country verified without revealing values
- Proofs generated locally or via secure server
- Circuit integrity verified on-chain
- Owner-only admin functions
- Ownable pattern implementation
- Ownership transfer capability
- Never share private keys
- Verify contract addresses
- Use hardware wallets in production
- Audit policy changes
- Monitor attestation updates
# Use legacy peer deps flag
npm install --legacy-peer-deps// Add WebSocket polyfill
globalThis.WebSocket = WebSocket;# Clean and rebuild
rm -rf node_modules package-lock.json
npm install --legacy-peer-deps
npm run clean && npm run build- Check firewall settings
- Verify network URLs
- Ensure wallet is connected
- Check wallet balance
- Verify gas fees
- Review transaction logs
# Enable debug logging
export DEBUG=midnight:*
npm run dev- Fork the repository
- Create feature branch (
git checkout -b feature/amazing) - Commit changes (
git commit -m 'Add feature') - Push branch (
git push origin feature/amazing) - Open Pull Request
- TypeScript strict mode enabled
- ESLint + Prettier formatting
- 100% test coverage for contracts
- Documentation for public APIs
type(scope): description
[optional body]
[optional footer]
Types: feat, fix, docs, style, refactor, test, chore
- Automated CI/CD checks
- Code review by maintainers
- Security audit for contract changes
- Documentation updates required
MIT License - See LICENSE file for details
- Midnight Foundation for blockchain infrastructure
- IOG for Compact language development
- Community contributors and testers
📝 Note: This documentation reflects the current state of the project. For the latest updates, check the CHANGELOG and GitHub releases.