Minimal React/Vite dApp showing how to integrate the 1AM browser extension with Midnight contracts.
- 1AM Chrome extension (or Chromium-based browser with 1AM installed)
- Node.js 20+ and npm
- Compact compiler (install guide: https://docs.midnight.network/getting-started/installation) - only required if you modify/recompile contracts
- Docker + Docker Compose (optional, only for the containerized run)
- Detect and connect
window.midnight['1am'] - Build Midnight deploy/call transactions in the dApp
- Prove, balance, and submit those transactions through 1AM
- Read task state from indexer-backed public data provider
- Support unshielded and shielded task workflows
- Optional payload encryption using a wallet-signature-derived key
npm install
npm run devOpen http://localhost:5173.
Copy .env.example to .env and adjust values for your setup.
VITE_1AM_NETWORK: wallet network for 1AM (previeworpreprod)VITE_ZK_TODO_ASSET_BASE_PATH: unshielded TODO contract ZK asset pathVITE_ZK_SHIELDED_TODO_ASSET_BASE_PATH: shielded TODO contract ZK asset pathDEV_ALLOWED_HOSTS: comma-separated hostnames allowed by Vite dev server
docker compose build uses the same VITE_* values as build args.
The dApp should use 1AM as the wallet/relayer boundary, not as a replacement for the Midnight SDK.
- Detect
window.midnight?.['1am']and connect with the configured network. - Read
api.getConfiguration()and pass the returned indexer URLs to Midnight providers. - Host the compiled contract assets under
public/zk/.... - Create a
FetchZkConfigProviderfor each contract asset base path. - Pass
zkConfigProvider.asKeyMaterialProvider()toapi.getProvingProvider(...). - Route
walletProvider.balanceTx(...)throughapi.balanceUnsealedTransaction(txHex). - Route
midnightProvider.submitTx(...)throughapi.submitTransaction(txHex).
Important API details:
submitTransaction(txHex)resolves when the wallet has accepted/submitted the finalized transaction; it does not return a transaction id. Derive the id from the finalizedTransaction.identifiers()value before submitting.signData(data, { encoding, keyType: 'unshielded' })returns{ data, signature, verifyingKey }. Use thesignaturefield, not the whole response, when deriving local encryption keys.- The dApp hosts only its contract ZK artifacts:
keys/{circuit}.prover,keys/{circuit}.verifier, andzkir/{circuit}.bzkir. It should not copy Midnight system keys or requireMIDNIGHT_SYSTEM_KEYS_DIR; 1AM/ProofStation handles system proving and dust sponsorship.
See 1am.md for a more detailed integration reference.
- Connect wallet on your configured
VITE_1AM_NETWORK - Deploy task contract
- Refresh indexed state
- Edit tasks locally
- Save local edits on-chain
src/midnight.ts: 1AM session/provider wiring and indexer patch behaviorsrc/confidentialTodo.ts: optional payload encryption/decryptionsrc/features/tasks/hooks/useTaskBoard.ts: app functionality and state orchestrationsrc/features/tasks/domain/*: pure task serialization/parsing logicsrc/features/tasks/data/*: storage helperssrc/features/tasks/ui/*: frontend rendering components
The frontend exists to exercise the integration flow; this repo is primarily a reference for 1AM + Midnight functionality.
npm run buildThe checked-in contracts already include compiled artifacts. If you change a Compact contract, run:
npm run prepare:todoThis recompiles both TODO contracts and syncs the generated keys/ and zkir/ directories into public/zk/... so the browser can fetch them.