midnight-mcp 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,19 @@
1
1
  /**
2
- * Embedded documentation content for offline access
3
- * Separated from docs.ts for better maintainability
2
+ * Embedded documentation content
3
+ *
4
+ * DESIGN PRINCIPLE: This file contains ONLY curated/unique content that:
5
+ * 1. Doesn't exist in official docs (wallet-integration guide we created)
6
+ * 2. Is a synthesized summary (tokenomics whitepaper)
7
+ * 3. Is a quick reference card (compact-reference, sdk-api)
8
+ * 4. Is from external sources (OpenZeppelin Compact contracts)
9
+ *
10
+ * For official Midnight docs (glossary, Zswap, Kachina concepts),
11
+ * use the search_docs tool which queries the Vector DB.
4
12
  */
5
13
  export const EMBEDDED_DOCS = {
6
- "midnight://docs/compact-reference": `# Compact Language Reference
14
+ "midnight://docs/compact-reference": `# Compact Language Quick Reference
7
15
 
8
- Compact is a TypeScript-inspired language for writing privacy-preserving smart contracts on Midnight.
16
+ A curated syntax reference for Compact - Midnight's smart contract language.
9
17
 
10
18
  ## Basic Structure
11
19
 
@@ -78,810 +86,458 @@ witness getCurrentPrice(): Field {
78
86
  return fetchPrice();
79
87
  }
80
88
 
81
- export circuit swap(amount: Field): Void {
89
+ export circuit buyAtMarketPrice(maxPrice: Field): Void {
82
90
  const price = getCurrentPrice();
83
- // Use price in circuit logic
91
+ assert(price <= maxPrice);
92
+ // ... execute purchase
84
93
  }
85
94
  \`\`\`
86
95
 
87
- ## Built-in Functions
88
-
89
- ### Cryptographic
90
- - \`hash(data)\` - Compute cryptographic hash
91
- - \`commit(value)\` - Create hiding commitment
92
- - \`disclose(private)\` - Reveal private data
93
-
94
- ### State Operations
95
- - \`Counter.increment(n)\` - Add to counter
96
- - \`Counter.decrement(n)\` - Subtract from counter
97
- - \`Counter.value()\` - Read current value
98
- - \`Map.insert(k, v)\` - Add key-value
99
- - \`Map.get(k)\` - Retrieve value
100
- - \`Set.add(v)\` - Add to set
101
- - \`Set.contains(v)\` - Check membership
102
-
103
- ## Privacy Annotations
104
-
105
- \`\`\`compact
106
- ledger {
107
- publicData: Field; // Visible on-chain
108
- @private
109
- privateData: Field; // Only owner sees
110
- }
111
- \`\`\`
112
- `,
113
- "midnight://docs/sdk-api": `# Midnight TypeScript SDK API
114
-
115
- ## Installation
116
-
117
- \`\`\`bash
118
- npm install @midnight-ntwrk/midnight-js-contracts @midnight-ntwrk/midnight-js-types
119
- \`\`\`
120
-
121
- ## Core Packages
122
-
123
- ### @midnight-ntwrk/midnight-js-contracts
124
- Contract interaction layer for deploying and calling Midnight smart contracts.
125
-
126
- \`\`\`typescript
127
- import { Contract, DeployedContract } from '@midnight-ntwrk/midnight-js-contracts';
128
-
129
- // Deploy a contract
130
- const deployed = await Contract.deploy(
131
- wallet,
132
- contractArtifact,
133
- initialState
134
- );
135
-
136
- // Call a circuit
137
- const result = await deployed.call('increment', { amount: 1n });
138
- \`\`\`
139
-
140
- ### @midnight-ntwrk/midnight-js-types
141
- Shared types and interfaces for the SDK.
142
-
143
- \`\`\`typescript
144
- import type {
145
- Address,
146
- Transaction,
147
- Proof,
148
- ContractState
149
- } from '@midnight-ntwrk/midnight-js-types';
150
- \`\`\`
151
-
152
- ### @midnight-ntwrk/wallet-api
153
- Wallet integration interface.
154
-
155
- \`\`\`typescript
156
- import { WalletAPI } from '@midnight-ntwrk/wallet-api';
157
-
158
- const wallet = await WalletAPI.connect();
159
- const address = await wallet.getAddress();
160
- const balance = await wallet.getBalance();
161
- \`\`\`
162
-
163
- ## Common Patterns
164
-
165
- ### Contract Deployment
166
- \`\`\`typescript
167
- import { Contract } from '@midnight-ntwrk/midnight-js-contracts';
168
- import counterContract from './counter.json';
169
-
170
- async function deployCounter() {
171
- const deployed = await Contract.deploy(
172
- wallet,
173
- counterContract,
174
- { counter: 0n }
175
- );
176
-
177
- console.log('Deployed at:', deployed.address);
178
- return deployed;
179
- }
180
- \`\`\`
181
-
182
- ### Calling Circuits
183
- \`\`\`typescript
184
- async function increment(contract: DeployedContract, amount: bigint) {
185
- const tx = await contract.call('increment', { amount });
186
- await tx.wait();
187
-
188
- const newValue = await contract.query('counter');
189
- return newValue;
190
- }
191
- \`\`\`
192
-
193
- ### Querying State
194
- \`\`\`typescript
195
- async function getState(contract: DeployedContract) {
196
- const publicState = await contract.query('publicField');
197
- // Note: Private state requires witness functions
198
- return publicState;
199
- }
200
- \`\`\`
201
- `,
202
- "midnight://docs/concepts/zero-knowledge": `# Zero-Knowledge Proofs in Midnight
203
-
204
- ## What are Zero-Knowledge Proofs?
205
-
206
- Zero-knowledge proofs (ZKPs) allow one party (the prover) to convince another party (the verifier) that a statement is true, without revealing any information beyond the validity of the statement.
207
-
208
- ## How Midnight Uses ZKPs
209
-
210
- In Midnight, every circuit execution generates a zero-knowledge proof:
211
-
212
- 1. **User calls a circuit** with private inputs
213
- 2. **Proof is generated** off-chain
214
- 3. **Only the proof** (not the inputs) is submitted to the blockchain
215
- 4. **Validators verify** the proof without knowing the inputs
216
-
217
- ## Example
218
-
219
- \`\`\`compact
220
- export circuit proveAge(birthYear: Field): Boolean {
221
- const currentYear = 2024;
222
- const age = currentYear - birthYear;
223
-
224
- // Proves user is over 18 without revealing exact age
225
- assert(age >= 18);
226
- return true;
227
- }
228
- \`\`\`
229
-
230
- When this circuit runs:
231
- - Input: \`birthYear = 1990\` (private)
232
- - Output: \`true\` (public)
233
- - Proof: "I know a birthYear that makes age >= 18" (public)
234
-
235
- The verifier learns the user is over 18, but not their actual birth year.
236
-
237
- ## Key Properties
238
-
239
- 1. **Completeness**: Valid proofs always verify
240
- 2. **Soundness**: Invalid proofs cannot be forged
241
- 3. **Zero-knowledge**: Nothing beyond validity is revealed
242
-
243
- ## Privacy Patterns
244
-
245
- ### Selective Disclosure
246
- \`\`\`compact
247
- export circuit verifyCredential(
248
- @private credential: Credential
249
- ): Field {
250
- // Prove credential is valid
251
- assert(credential.isValid());
252
-
253
- // Only reveal specific fields
254
- return disclose(credential.issuer);
255
- }
256
- \`\`\`
257
-
258
- ### Hidden Computation
259
- \`\`\`compact
260
- export circuit secretBid(
261
- @private amount: Field,
262
- commitment: Field
263
- ): Void {
264
- // Prove bid matches commitment without revealing amount
265
- assert(commit(amount) == commitment);
266
- }
267
- \`\`\`
268
- `,
269
- "midnight://docs/concepts/shielded-state": `# Shielded vs Unshielded State
270
-
271
- Midnight supports two types of state: shielded (private) and unshielded (public).
272
-
273
- ## Unshielded State
96
+ ### Key Points:
97
+ - Run locally, not on-chain
98
+ - Can access external APIs, databases
99
+ - Cannot modify ledger state directly
100
+ - Results are private unless disclosed
274
101
 
275
- Public state visible to everyone on the blockchain:
102
+ ## State Management
276
103
 
104
+ ### Public State
277
105
  \`\`\`compact
278
106
  ledger {
279
- totalSupply: Counter; // Public counter
280
- balances: Map<Address, Field>; // Public mapping
107
+ publicCounter: Counter;
108
+ publicMap: Map<Field, Field>;
281
109
  }
282
110
  \`\`\`
283
111
 
284
- **Use for:**
285
- - Token total supply
286
- - Public voting tallies
287
- - Any data that should be transparent
288
-
289
- ## Shielded State
290
-
291
- Private state only visible to the owner:
292
-
112
+ ### Private State
293
113
  \`\`\`compact
294
114
  ledger {
295
115
  @private
296
- secretKey: Bytes<32>;
116
+ secretBalance: Field;
297
117
 
298
118
  @private
299
- privateBalance: Field;
119
+ hiddenVotes: Map<Address, Field>;
300
120
  }
301
121
  \`\`\`
302
122
 
303
- **Use for:**
304
- - User credentials
305
- - Private balances
306
- - Sensitive personal data
307
-
308
- ## Hybrid Approach
309
-
310
- Most contracts use both:
123
+ ## Common Patterns
311
124
 
125
+ ### Access Control
312
126
  \`\`\`compact
313
127
  ledger {
314
- // Public: anyone can see total messages
315
- messageCount: Counter;
316
-
317
- // Private: only owner sees message contents
318
- @private
319
- messages: Map<Field, Opaque<"string">>;
128
+ owner: Opaque<"address">;
320
129
  }
321
130
 
322
- export circuit postMessage(content: Opaque<"string">): Void {
323
- const id = ledger.messageCount.value();
324
-
325
- // Public increment
326
- ledger.messageCount.increment(1);
327
-
328
- // Private storage
329
- ledger.messages.insert(id, content);
131
+ witness getCaller(): Opaque<"address"> {
132
+ return context.caller;
330
133
  }
331
- \`\`\`
332
134
 
333
- ## Transitioning Between States
135
+ export circuit ownerOnly(): Void {
136
+ assert(getCaller() == ledger.owner, "Not owner");
137
+ }
138
+ \`\`\`
334
139
 
335
- ### Disclose: Private → Public
140
+ ### Disclosure
336
141
  \`\`\`compact
337
- export circuit revealBalance(): Field {
338
- // Reveal private balance publicly
339
- return disclose(ledger.privateBalance);
142
+ export circuit revealSecret(): Field {
143
+ const secret = getPrivateData();
144
+ return disclose(secret); // Makes private data public
340
145
  }
341
146
  \`\`\`
342
147
 
343
- ### Commit: Public → Hidden
148
+ ### Assertions
344
149
  \`\`\`compact
345
- export circuit hideValue(value: Field): Field {
346
- // Create commitment (hides value but proves existence)
347
- return commit(value);
348
- }
150
+ assert(condition); // Basic assertion
151
+ assert(condition, "Error message"); // With message
349
152
  \`\`\`
350
153
  `,
351
- "midnight://docs/concepts/witnesses": `# Witness Functions
352
-
353
- Witnesses provide off-chain data to circuits in Midnight.
354
-
355
- ## Why Witnesses?
356
-
357
- Circuits run in a ZK environment with limitations:
358
- - Cannot make network requests
359
- - Cannot access system time
360
- - Cannot read external files
361
- - Must be deterministic
154
+ "midnight://docs/sdk-api": `# Midnight TypeScript SDK Quick Reference
362
155
 
363
- Witnesses bridge this gap by running off-chain.
156
+ ## Installation
364
157
 
365
- ## Basic Witness
158
+ \`\`\`bash
159
+ npm install @midnight-ntwrk/midnight-js-contracts
160
+ \`\`\`
366
161
 
367
- \`\`\`compact
368
- // Runs off-chain, provides data to circuits
369
- witness getTimestamp(): Field {
370
- return getCurrentUnixTime();
371
- }
162
+ ## Core Types
372
163
 
373
- export circuit timedAction(): Void {
374
- const timestamp = getTimestamp();
375
- assert(timestamp > ledger.deadline);
376
- // ... perform action
377
- }
378
- \`\`\`
164
+ ### Contract Deployment
379
165
 
380
- ## Witness with Parameters
166
+ \`\`\`typescript
167
+ import { deployContract, ContractDeployment } from '@midnight-ntwrk/midnight-js-contracts';
381
168
 
382
- \`\`\`compact
383
- witness fetchPrice(asset: Opaque<"string">): Field {
384
- // Off-chain: call price oracle
385
- return callPriceOracle(asset);
386
- }
169
+ const deployment: ContractDeployment = await deployContract({
170
+ contract: compiledContract,
171
+ privateState: initialPrivateState,
172
+ args: constructorArgs,
173
+ });
387
174
 
388
- export circuit swap(asset: Opaque<"string">, amount: Field): Void {
389
- const price = fetchPrice(asset);
390
- const total = amount * price;
391
- // ... execute swap
392
- }
175
+ const { contractAddress, initialState } = deployment;
393
176
  \`\`\`
394
177
 
395
- ## Private Data Access
396
-
397
- Witnesses can access private ledger state:
178
+ ### Contract Interaction
398
179
 
399
- \`\`\`compact
400
- ledger {
401
- @private
402
- secretNonce: Field;
403
- }
180
+ \`\`\`typescript
181
+ import { callContract } from '@midnight-ntwrk/midnight-js-contracts';
404
182
 
405
- witness getNextNonce(): Field {
406
- const current = ledger.secretNonce;
407
- return current + 1;
408
- }
183
+ // Call a circuit
184
+ const result = await callContract({
185
+ contractAddress,
186
+ circuitName: 'increment',
187
+ args: [amount],
188
+ privateState: currentPrivateState,
189
+ });
409
190
 
410
- export circuit signedOperation(data: Field): Field {
411
- const nonce = getNextNonce();
412
- return hash(data, nonce);
413
- }
191
+ // Result contains new state and return value
192
+ const { newPrivateState, returnValue, proof } = result;
414
193
  \`\`\`
415
194
 
416
- ## Best Practices
417
-
418
- 1. **Keep witnesses simple** - Complex logic should be in circuits
419
- 2. **Handle failures gracefully** - Witnesses can fail
420
- 3. **Don't trust witness data blindly** - Validate in circuits
421
- 4. **Cache when possible** - Reduce off-chain calls
195
+ ### Providers
422
196
 
423
- ## Security Considerations
197
+ \`\`\`typescript
198
+ import {
199
+ MidnightProvider,
200
+ createMidnightProvider
201
+ } from '@midnight-ntwrk/midnight-js-contracts';
424
202
 
425
- ⚠️ Witnesses are NOT proven in ZK:
426
- - Circuit verifies witness output is used correctly
427
- - But doesn't verify HOW witness computed the value
428
- - Malicious witnesses can provide false data
203
+ const provider = await createMidnightProvider({
204
+ indexer: 'https://indexer.testnet.midnight.network',
205
+ node: 'https://node.testnet.midnight.network',
206
+ proofServer: 'https://prover.testnet.midnight.network',
207
+ });
208
+ \`\`\`
429
209
 
430
- Always add assertions to validate witness data:
210
+ ## State Management
431
211
 
432
- \`\`\`compact
433
- export circuit usePrice(asset: Opaque<"string">): Void {
434
- const price = fetchPrice(asset);
435
-
436
- // Validate witness data
437
- assert(price > 0);
438
- assert(price < MAX_REASONABLE_PRICE);
439
-
440
- // ... use price
212
+ \`\`\`typescript
213
+ interface ContractState<T> {
214
+ publicState: PublicState;
215
+ privateState: T;
441
216
  }
442
- \`\`\`
443
- `,
444
- "midnight://docs/concepts/kachina": `# Kachina Protocol
445
217
 
446
- Kachina is the cryptographic protocol underlying Midnight's privacy features.
218
+ // Subscribe to state changes
219
+ provider.subscribeToContract(contractAddress, (state) => {
220
+ console.log('New state:', state);
221
+ });
222
+ \`\`\`
447
223
 
448
- ## Overview
224
+ ## Transaction Building
449
225
 
450
- Kachina enables:
451
- - Private smart contracts with public verifiability
452
- - Composable privacy across contracts
453
- - Efficient on-chain verification
226
+ \`\`\`typescript
227
+ import { buildTransaction } from '@midnight-ntwrk/midnight-js-contracts';
454
228
 
455
- ## Architecture
229
+ const tx = await buildTransaction({
230
+ contractAddress,
231
+ circuitName: 'transfer',
232
+ args: [recipient, amount],
233
+ privateState,
234
+ });
456
235
 
457
- \`\`\`
458
- ┌─────────────────┐ ┌─────────────────┐
459
- │ User Wallet │────▶│ Compact Code │
460
- └─────────────────┘ └────────┬────────┘
461
-
462
- ┌────────▼────────┐
463
- │ ZK Circuit │
464
- │ (Prover) │
465
- └────────┬────────┘
466
-
467
- ┌────────▼────────┐
468
- │ Proof │
469
- └────────┬────────┘
470
-
471
- ┌────────▼────────┐
472
- │ Midnight │
473
- │ Validators │
474
- └─────────────────┘
236
+ // Sign and submit
237
+ const signedTx = await wallet.signTransaction(tx);
238
+ const txHash = await provider.submitTransaction(signedTx);
475
239
  \`\`\`
476
240
 
477
- ## Key Concepts
241
+ ## Error Handling
478
242
 
479
- ### State Model
480
- - **Public State**: Stored on-chain, visible to all
481
- - **Private State**: Stored off-chain, encrypted
482
- - **Commitments**: On-chain references to private state
483
-
484
- ### Transaction Flow
485
- 1. User prepares transaction locally
486
- 2. Prover generates ZK proof
487
- 3. Transaction + proof submitted to network
488
- 4. Validators verify proof (not re-execute)
489
- 5. State updates applied
490
-
491
- ### Composability
492
- Contracts can interact while preserving privacy:
493
-
494
- \`\`\`compact
495
- // Contract A
496
- export circuit transferToken(to: Address, amount: Field): Void {
497
- // Private transfer logic
498
- }
243
+ \`\`\`typescript
244
+ import { MidnightError, ContractError } from '@midnight-ntwrk/midnight-js-contracts';
499
245
 
500
- // Contract B can call Contract A
501
- export circuit atomicSwap(
502
- tokenA: Address,
503
- tokenB: Address,
504
- amountA: Field,
505
- amountB: Field
506
- ): Void {
507
- // Both transfers happen atomically
508
- // Privacy preserved for both
246
+ try {
247
+ await callContract({ ... });
248
+ } catch (error) {
249
+ if (error instanceof ContractError) {
250
+ console.error('Contract assertion failed:', error.message);
251
+ } else if (error instanceof MidnightError) {
252
+ console.error('Network error:', error.code);
253
+ }
509
254
  }
510
255
  \`\`\`
511
-
512
- ## Benefits
513
-
514
- 1. **Privacy by Default**: All computation is private unless explicitly disclosed
515
- 2. **Scalability**: Verification is faster than re-execution
516
- 3. **Flexibility**: Developers choose what to reveal
517
- 4. **Interoperability**: Works with existing blockchain infrastructure
518
256
  `,
519
257
  "midnight://docs/openzeppelin": `# OpenZeppelin Contracts for Compact
520
258
 
521
259
  > **Official Documentation**: https://docs.openzeppelin.com/contracts-compact
522
260
  > **GitHub Repository**: https://github.com/OpenZeppelin/compact-contracts
523
261
 
524
- OpenZeppelin Contracts for Compact is the **official and recommended** library for building secure smart contracts on Midnight. This library provides audited, battle-tested modules for common patterns.
262
+ The official OpenZeppelin library for Midnight smart contracts provides battle-tested, audited implementations of common patterns.
525
263
 
526
264
  ## Installation
527
265
 
528
266
  \`\`\`bash
529
- # Create project directory
530
- mkdir my-project && cd my-project
531
-
532
- # Initialize git and add as submodule
533
- git init && git submodule add https://github.com/OpenZeppelin/compact-contracts.git
534
-
535
- # Install dependencies
536
- cd compact-contracts
537
- nvm install && yarn && SKIP_ZK=true yarn compact
267
+ npm install @openzeppelin/compact-contracts
538
268
  \`\`\`
539
269
 
540
270
  ## Available Modules
541
271
 
542
- ### Token
543
- - **FungibleToken**: Standard token implementation with transfer, mint, burn
544
- - Recommended for all token contracts on Midnight
272
+ ### Token Standards
273
+ - **FungibleToken** - Privacy-preserving token with shielded balances
274
+ - **NFT** - Non-fungible tokens with optional privacy
545
275
 
546
276
  ### Access Control
547
- - **Ownable**: Single owner access control
548
- - **AccessControl**: Role-based access control
277
+ - **Ownable** - Single-owner access pattern
278
+ - **Roles** - Role-based access control
279
+ - **AccessControl** - Flexible permission system
549
280
 
550
281
  ### Security
551
- - **Pausable**: Emergency stop mechanism
282
+ - **Pausable** - Emergency stop mechanism
283
+ - **ReentrancyGuard** - Prevent reentrancy attacks
552
284
 
553
285
  ## Usage Example
554
286
 
555
287
  \`\`\`compact
556
- pragma language_version >= 0.16.0;
557
-
558
- import CompactStandardLibrary;
559
- import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/access/Ownable" prefix Ownable_;
560
- import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/security/Pausable" prefix Pausable_;
561
- import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/token/FungibleToken" prefix FungibleToken_;
562
-
563
- constructor(
564
- _name: Opaque<"string">,
565
- _symbol: Opaque<"string">,
566
- _decimals: Uint<8>,
567
- _recipient: Either<ZswapCoinPublicKey, ContractAddress>,
568
- _amount: Uint<128>,
569
- _initOwner: Either<ZswapCoinPublicKey, ContractAddress>,
570
- ) {
571
- Ownable_initialize(_initOwner);
572
- FungibleToken_initialize(_name, _symbol, _decimals);
573
- FungibleToken__mint(_recipient, _amount);
574
- }
575
-
576
- export circuit transfer(
577
- to: Either<ZswapCoinPublicKey, ContractAddress>,
578
- value: Uint<128>,
579
- ): Boolean {
580
- Pausable_assertNotPaused();
581
- return FungibleToken_transfer(to, value);
582
- }
288
+ include "std";
289
+ include "@openzeppelin/compact-contracts/token/FungibleToken.compact";
290
+ include "@openzeppelin/compact-contracts/access/Ownable.compact";
583
291
 
584
- export circuit pause(): [] {
585
- Ownable_assertOnlyOwner();
586
- Pausable__pause();
292
+ ledger {
293
+ // Inherit from OpenZeppelin contracts
294
+ ...FungibleToken.ledger;
295
+ ...Ownable.ledger;
587
296
  }
588
297
 
589
- export circuit unpause(): [] {
590
- Ownable_assertOnlyOwner();
591
- Pausable__unpause();
298
+ export circuit mint(to: Address, amount: Field): Void {
299
+ Ownable.assertOnlyOwner();
300
+ FungibleToken.mint(to, amount);
592
301
  }
593
302
  \`\`\`
594
303
 
595
- ## Compilation
596
-
597
- \`\`\`bash
598
- compact compile MyContract.compact artifacts/MyContract
599
- \`\`\`
600
-
601
- ## Why Use OpenZeppelin?
304
+ ## Best Practices
602
305
 
603
- 1. **Security Audited**: Contracts are professionally audited
604
- 2. **Battle-Tested**: Used in production across the ecosystem
605
- 3. **Official Recommendation**: Midnight's recommended library for tokens
606
- 4. **Modularity**: Use only what you need
607
- 5. **Best Practices**: Follows Compact language best practices
306
+ 1. **Always use audited contracts** - Don't reinvent token standards
307
+ 2. **Combine patterns** - Ownable + FungibleToken + Pausable
308
+ 3. **Check for updates** - Security patches are released regularly
309
+ 4. **Read the docs** - Each module has specific usage patterns
608
310
  `,
609
311
  "midnight://docs/openzeppelin/token": `# OpenZeppelin FungibleToken
610
312
 
611
- > **This is the official and recommended token standard for Midnight.**
612
-
613
- The FungibleToken module provides a complete implementation for fungible tokens on Midnight.
313
+ The recommended standard for privacy-preserving tokens on Midnight.
614
314
 
615
315
  ## Features
616
316
 
617
- - ERC20-compatible interface
618
- - Transfer with balance tracking
619
- - Mint and burn operations
620
- - Approval and transferFrom patterns
621
- - Privacy-preserving by default
317
+ - Shielded balances (private by default)
318
+ - Optional public balance disclosure
319
+ - Transfer with ZK proofs
320
+ - Mint/burn capabilities
622
321
 
623
322
  ## Basic Usage
624
323
 
625
324
  \`\`\`compact
626
- pragma language_version >= 0.16.0;
627
-
628
- import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/token/FungibleToken" prefix FungibleToken_;
629
-
630
- constructor(
631
- _name: Opaque<"string">,
632
- _symbol: Opaque<"string">,
633
- _decimals: Uint<8>,
634
- _recipient: Either<ZswapCoinPublicKey, ContractAddress>,
635
- _initialSupply: Uint<128>,
636
- ) {
637
- FungibleToken_initialize(_name, _symbol, _decimals);
638
- FungibleToken__mint(_recipient, _initialSupply);
325
+ include "std";
326
+ include "@openzeppelin/compact-contracts/token/FungibleToken.compact";
327
+
328
+ ledger {
329
+ ...FungibleToken.ledger;
330
+ name: Opaque<"string">;
331
+ symbol: Opaque<"string">;
332
+ decimals: Uint<8>;
333
+ }
334
+
335
+ export circuit initialize(
336
+ name: Opaque<"string">,
337
+ symbol: Opaque<"string">,
338
+ decimals: Uint<8>,
339
+ initialSupply: Field,
340
+ owner: Address
341
+ ): Void {
342
+ ledger.name = name;
343
+ ledger.symbol = symbol;
344
+ ledger.decimals = decimals;
345
+ FungibleToken.mint(owner, initialSupply);
639
346
  }
640
347
 
641
- // Transfer tokens
642
- export circuit transfer(
643
- to: Either<ZswapCoinPublicKey, ContractAddress>,
644
- value: Uint<128>,
645
- ): Boolean {
646
- return FungibleToken_transfer(to, value);
348
+ // Shielded transfer
349
+ export circuit transfer(to: Address, amount: Field): Void {
350
+ FungibleToken.transfer(to, amount);
647
351
  }
648
352
 
649
- // Check balance (witness function for privacy)
650
- witness balanceOf(
651
- account: Either<ZswapCoinPublicKey, ContractAddress>
652
- ): Uint<128> {
653
- return FungibleToken_balanceOf(account);
353
+ // Check balance (private)
354
+ witness myBalance(): Field {
355
+ return FungibleToken.balanceOf(context.caller);
654
356
  }
655
357
 
656
- // Get total supply
657
- witness totalSupply(): Uint<128> {
658
- return FungibleToken_totalSupply();
358
+ // Reveal balance publicly (optional)
359
+ export circuit revealBalance(): Field {
360
+ return disclose(myBalance());
659
361
  }
660
362
  \`\`\`
661
363
 
662
- ## Advanced: With Approval Pattern
364
+ ## Minting and Burning
663
365
 
664
366
  \`\`\`compact
665
- // Approve spender
666
- export circuit approve(
667
- spender: Either<ZswapCoinPublicKey, ContractAddress>,
668
- value: Uint<128>,
669
- ): Boolean {
670
- return FungibleToken_approve(spender, value);
671
- }
367
+ include "@openzeppelin/compact-contracts/access/Ownable.compact";
672
368
 
673
- // Transfer from approved account
674
- export circuit transferFrom(
675
- from: Either<ZswapCoinPublicKey, ContractAddress>,
676
- to: Either<ZswapCoinPublicKey, ContractAddress>,
677
- value: Uint<128>,
678
- ): Boolean {
679
- return FungibleToken_transferFrom(from, to, value);
369
+ ledger {
370
+ ...FungibleToken.ledger;
371
+ ...Ownable.ledger;
680
372
  }
681
- \`\`\`
682
-
683
- ## Mint and Burn (Owner-Only)
684
373
 
685
- \`\`\`compact
686
- import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/access/Ownable" prefix Ownable_;
687
-
688
- export circuit mint(
689
- to: Either<ZswapCoinPublicKey, ContractAddress>,
690
- amount: Uint<128>,
691
- ): [] {
692
- Ownable_assertOnlyOwner();
693
- FungibleToken__mint(to, amount);
374
+ export circuit mint(to: Address, amount: Field): Void {
375
+ Ownable.assertOnlyOwner();
376
+ FungibleToken.mint(to, amount);
694
377
  }
695
378
 
696
- export circuit burn(
697
- from: Either<ZswapCoinPublicKey, ContractAddress>,
698
- amount: Uint<128>,
699
- ): [] {
700
- Ownable_assertOnlyOwner();
701
- FungibleToken__burn(from, amount);
379
+ export circuit burn(amount: Field): Void {
380
+ FungibleToken.burn(context.caller, amount);
702
381
  }
703
382
  \`\`\`
383
+
384
+ ## Privacy Model
385
+
386
+ | Operation | Privacy |
387
+ |-----------|---------|
388
+ | Balance | Shielded (private) |
389
+ | Transfer amount | Shielded |
390
+ | Sender | Shielded |
391
+ | Recipient | Shielded |
392
+ | Transaction occurred | Public (proof exists) |
393
+
394
+ ## Important Notes
395
+
396
+ 1. **No approval mechanism** - Unlike ERC20, transfers are direct
397
+ 2. **Balances are commitments** - Not stored as plain values
398
+ 3. **Privacy by default** - Explicit disclosure required to reveal
704
399
  `,
705
400
  "midnight://docs/openzeppelin/access": `# OpenZeppelin Access Control
706
401
 
707
- Access control modules for managing permissions in your contracts.
402
+ Patterns for controlling who can call contract functions.
708
403
 
709
404
  ## Ownable
710
405
 
711
406
  Simple single-owner access control.
712
407
 
713
408
  \`\`\`compact
714
- pragma language_version >= 0.16.0;
715
-
716
- import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/access/Ownable" prefix Ownable_;
409
+ include "@openzeppelin/compact-contracts/access/Ownable.compact";
717
410
 
718
- constructor(
719
- _owner: Either<ZswapCoinPublicKey, ContractAddress>,
720
- ) {
721
- Ownable_initialize(_owner);
722
- }
723
-
724
- // Only owner can call this
725
- export circuit adminFunction(): [] {
726
- Ownable_assertOnlyOwner();
727
- // ... admin logic
411
+ ledger {
412
+ ...Ownable.ledger;
728
413
  }
729
414
 
730
- // Transfer ownership
731
- export circuit transferOwnership(
732
- newOwner: Either<ZswapCoinPublicKey, ContractAddress>,
733
- ): [] {
734
- Ownable_assertOnlyOwner();
735
- Ownable_transferOwnership(newOwner);
415
+ export circuit initialize(owner: Address): Void {
416
+ Ownable.initialize(owner);
736
417
  }
737
418
 
738
- // Renounce ownership (irreversible!)
739
- export circuit renounceOwnership(): [] {
740
- Ownable_assertOnlyOwner();
741
- Ownable_renounceOwnership();
419
+ export circuit adminFunction(): Void {
420
+ Ownable.assertOnlyOwner();
421
+ // Only owner can execute this
742
422
  }
743
423
 
744
- // Check current owner
745
- witness owner(): Either<ZswapCoinPublicKey, ContractAddress> {
746
- return Ownable_owner();
424
+ export circuit transferOwnership(newOwner: Address): Void {
425
+ Ownable.assertOnlyOwner();
426
+ Ownable.transferOwnership(newOwner);
747
427
  }
748
428
  \`\`\`
749
429
 
750
- ## AccessControl (Role-Based)
430
+ ## Role-Based Access Control
751
431
 
752
- For contracts needing multiple roles with different permissions.
432
+ For more complex permission systems.
753
433
 
754
434
  \`\`\`compact
755
- import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/access/AccessControl" prefix AC_;
435
+ include "@openzeppelin/compact-contracts/access/AccessControl.compact";
756
436
 
757
- // Define role identifiers
437
+ ledger {
438
+ ...AccessControl.ledger;
439
+ }
440
+
441
+ const ADMIN_ROLE: Bytes<32> = keccak256("ADMIN_ROLE");
758
442
  const MINTER_ROLE: Bytes<32> = keccak256("MINTER_ROLE");
759
- const PAUSER_ROLE: Bytes<32> = keccak256("PAUSER_ROLE");
760
443
 
761
- constructor(_admin: Either<ZswapCoinPublicKey, ContractAddress>) {
762
- AC_initialize(_admin);
763
- AC__grantRole(MINTER_ROLE, _admin);
764
- AC__grantRole(PAUSER_ROLE, _admin);
444
+ export circuit initialize(admin: Address): Void {
445
+ AccessControl.grantRole(ADMIN_ROLE, admin);
446
+ AccessControl.setRoleAdmin(MINTER_ROLE, ADMIN_ROLE);
765
447
  }
766
448
 
767
- // Only minters can call
768
- export circuit mint(to: Address, amount: Uint<128>): [] {
769
- AC_assertOnlyRole(MINTER_ROLE);
770
- // ... mint logic
449
+ export circuit mint(to: Address, amount: Field): Void {
450
+ AccessControl.assertHasRole(MINTER_ROLE);
451
+ // Mint tokens
771
452
  }
772
453
 
773
- // Only pausers can call
774
- export circuit pause(): [] {
775
- AC_assertOnlyRole(PAUSER_ROLE);
776
- // ... pause logic
454
+ export circuit grantMinterRole(account: Address): Void {
455
+ AccessControl.assertHasRole(ADMIN_ROLE);
456
+ AccessControl.grantRole(MINTER_ROLE, account);
777
457
  }
458
+ \`\`\`
778
459
 
779
- // Grant role (admin only)
780
- export circuit grantRole(
781
- role: Bytes<32>,
782
- account: Either<ZswapCoinPublicKey, ContractAddress>,
783
- ): [] {
784
- AC_assertOnlyRole(AC_DEFAULT_ADMIN_ROLE());
785
- AC__grantRole(role, account);
460
+ ## Combining Patterns
461
+
462
+ \`\`\`compact
463
+ include "@openzeppelin/compact-contracts/access/Ownable.compact";
464
+ include "@openzeppelin/compact-contracts/security/Pausable.compact";
465
+
466
+ ledger {
467
+ ...Ownable.ledger;
468
+ ...Pausable.ledger;
469
+ }
470
+
471
+ export circuit criticalFunction(): Void {
472
+ Ownable.assertOnlyOwner();
473
+ Pausable.assertNotPaused();
474
+ // Execute critical logic
475
+ }
476
+
477
+ export circuit pause(): Void {
478
+ Ownable.assertOnlyOwner();
479
+ Pausable.pause();
786
480
  }
787
481
  \`\`\`
788
482
  `,
789
483
  "midnight://docs/openzeppelin/security": `# OpenZeppelin Security Patterns
790
484
 
791
- Security modules for protecting your contracts.
485
+ Security utilities for Compact contracts.
792
486
 
793
487
  ## Pausable
794
488
 
795
- Emergency stop mechanism for your contract.
489
+ Emergency stop mechanism for contracts.
796
490
 
797
491
  \`\`\`compact
798
- pragma language_version >= 0.16.0;
799
-
800
- import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/security/Pausable" prefix Pausable_;
801
- import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/access/Ownable" prefix Ownable_;
802
-
803
- constructor(_owner: Either<ZswapCoinPublicKey, ContractAddress>) {
804
- Ownable_initialize(_owner);
805
- // Contract starts unpaused
806
- }
492
+ include "@openzeppelin/compact-contracts/security/Pausable.compact";
493
+ include "@openzeppelin/compact-contracts/access/Ownable.compact";
807
494
 
808
- // Protected function - won't work when paused
809
- export circuit transfer(
810
- to: Either<ZswapCoinPublicKey, ContractAddress>,
811
- amount: Uint<128>,
812
- ): Boolean {
813
- Pausable_assertNotPaused();
814
- // ... transfer logic
495
+ ledger {
496
+ ...Pausable.ledger;
497
+ ...Ownable.ledger;
815
498
  }
816
499
 
817
- // Owner can pause
818
- export circuit pause(): [] {
819
- Ownable_assertOnlyOwner();
820
- Pausable__pause();
500
+ export circuit transfer(to: Address, amount: Field): Void {
501
+ Pausable.assertNotPaused();
502
+ // Transfer logic
821
503
  }
822
504
 
823
- // Owner can unpause
824
- export circuit unpause(): [] {
825
- Ownable_assertOnlyOwner();
826
- Pausable__unpause();
505
+ export circuit pause(): Void {
506
+ Ownable.assertOnlyOwner();
507
+ Pausable.pause();
827
508
  }
828
509
 
829
- // Check if paused
830
- witness isPaused(): Boolean {
831
- return Pausable_paused();
510
+ export circuit unpause(): Void {
511
+ Ownable.assertOnlyOwner();
512
+ Pausable.unpause();
832
513
  }
833
514
  \`\`\`
834
515
 
835
- ## Combined Example: Secure Token
516
+ ## When to Use Pausable
836
517
 
837
- \`\`\`compact
838
- pragma language_version >= 0.16.0;
839
-
840
- import CompactStandardLibrary;
841
- import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/access/Ownable" prefix Ownable_;
842
- import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/security/Pausable" prefix Pausable_;
843
- import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/token/FungibleToken" prefix FungibleToken_;
844
-
845
- constructor(
846
- _name: Opaque<"string">,
847
- _symbol: Opaque<"string">,
848
- _decimals: Uint<8>,
849
- _initialSupply: Uint<128>,
850
- _owner: Either<ZswapCoinPublicKey, ContractAddress>,
851
- ) {
852
- Ownable_initialize(_owner);
853
- FungibleToken_initialize(_name, _symbol, _decimals);
854
- FungibleToken__mint(_owner, _initialSupply);
855
- }
518
+ - Token contracts handling real value
519
+ - DeFi protocols with liquidity
520
+ - Contracts with upgrade mechanisms
521
+ - Any contract where bugs could cause fund loss
856
522
 
857
- // Pausable transfer
858
- export circuit transfer(
859
- to: Either<ZswapCoinPublicKey, ContractAddress>,
860
- value: Uint<128>,
861
- ): Boolean {
862
- Pausable_assertNotPaused();
863
- return FungibleToken_transfer(to, value);
523
+ ## Implementation Details
524
+
525
+ \`\`\`compact
526
+ // Pausable module internals (simplified)
527
+ ledger {
528
+ paused: Boolean;
864
529
  }
865
530
 
866
- // Owner-only mint
867
- export circuit mint(
868
- to: Either<ZswapCoinPublicKey, ContractAddress>,
869
- amount: Uint<128>,
870
- ): [] {
871
- Ownable_assertOnlyOwner();
872
- Pausable_assertNotPaused();
873
- FungibleToken__mint(to, amount);
531
+ circuit Pausable_assertNotPaused(): Void {
532
+ assert(!ledger.paused, "Contract is paused");
874
533
  }
875
534
 
876
- // Emergency pause
877
- export circuit pause(): [] {
878
- Ownable_assertOnlyOwner();
879
- Pausable__pause();
535
+ circuit Pausable_pause(): Void {
536
+ ledger.paused = true;
880
537
  }
881
538
 
882
- export circuit unpause(): [] {
883
- Ownable_assertOnlyOwner();
884
- Pausable__unpause();
539
+ circuit Pausable_unpause(): Void {
540
+ ledger.paused = false;
885
541
  }
886
542
  \`\`\`
887
543
 
@@ -893,281 +549,184 @@ export circuit unpause(): [] {
893
549
  4. **Document pause conditions** for users
894
550
  5. **Consider timelock** for unpause in high-value contracts
895
551
  `,
896
- "midnight://docs/tokenomics": `# Midnight Tokenomics and Incentives Whitepaper
897
-
898
- ## Overview
899
-
900
- Midnight introduces a novel dual-component tokenomics system with NIGHT (utility token) and DUST (transaction resource), designed for operational predictability, privacy, and cross-chain cooperation.
901
-
902
- ## Core Pillars
903
-
904
- 1. **Operational Predictability**: NIGHT generates DUST continuously, enabling transactions without direct token expenditure
905
- 2. **Rational Privacy**: DUST is shielded - transactions don't leave metadata trails
906
- 3. **Cooperative Tokenomics**: Multi-chain architecture enables cross-chain value creation
907
- 4. **Fair Distribution**: Free, multi-phase token distribution (Glacier Drop)
908
-
909
- ---
910
-
911
- ## The NIGHT Token
912
-
913
- NIGHT is Midnight's native utility token. One NIGHT = 1,000,000 STARs.
914
-
915
- ### Key Properties
916
-
917
- - **Unshielded**: NIGHT transactions are publicly visible on-chain
918
- - **Transferable**: Can be freely transferred, listed on exchanges, bridged across networks
919
- - **Total Supply**: 24 billion NIGHT tokens
920
- - **Non-expendable**: Not consumed to execute transactions
921
- - **Disinflationary**: Circulating supply expansion slows over time
922
- - **Multi-chain Native**: Exists natively on both Cardano (as Native Asset) and Midnight
552
+ "midnight://docs/tokenomics": `# Midnight Tokenomics Summary
923
553
 
924
- ### Stakeholders
554
+ A curated summary of the Midnight Tokenomics Whitepaper (June 2025).
925
555
 
926
- - **NIGHT Token Holders**: Control future network governance
927
- - **Midnight Block Producers (MBPs)**: Validate blocks, receive rewards
928
- - **Midnight Foundation**: Long-term ecosystem development
929
- - **On-chain Treasury**: Protocol-managed fund for ecosystem growth
930
- - **Reserve**: Protocol-managed pool for block production rewards
556
+ ## Dual-Token Model
931
557
 
932
- ### Cross-Chain Token States
558
+ Midnight uses two components: **NIGHT** (token) and **DUST** (resource).
933
559
 
934
- Tokens can be:
935
- - **Protocol-locked**: Cannot move or generate DUST
936
- - **Protocol-unlocked**: Full utility and transferability
560
+ ### NIGHT Token
561
+ - **Supply**: 24 billion (fixed)
562
+ - **Subunit**: 1 NIGHT = 1,000,000 STARs
563
+ - **Visibility**: Unshielded (public)
564
+ - **Function**: Generates DUST, governance, block rewards
565
+ - **Multi-chain**: Native on both Cardano and Midnight
937
566
 
938
- Key invariant: A token unlocked on one chain is locked on the other, ensuring effective supply never exceeds 24 billion.
567
+ ### DUST Resource
568
+ - **Type**: Shielded, non-transferable
569
+ - **Function**: Pay transaction fees
570
+ - **Generation**: Continuously from NIGHT holdings
571
+ - **Decay**: When disassociated from NIGHT
572
+ - **Privacy**: Transactions don't leak metadata
939
573
 
940
- ### Cross-Chain Invariants
574
+ ## Key Insight: NIGHT Generates DUST
941
575
 
942
576
  \`\`\`
943
- C.R + C.L + C.U = M.R + M.L + M.U = S (24 billion)
944
-
945
- Where:
946
- - C = Cardano, M = Midnight
947
- - R = Reserve, L = Locked, U = Unlocked
948
- - S = Total Supply
949
- \`\`\`
950
-
951
- ---
952
-
953
- ## The DUST Resource
954
-
955
- DUST is the shielded, renewable resource for transaction fees.
956
-
957
- ### Key Properties
958
-
959
- - **Shielded**: Transactions don't expose wallet addresses or details
960
- - **Consumable**: Burned when used (not recycled)
961
- - **Renewable**: Continuously generated by NIGHT holdings
962
- - **Decaying**: Balance decays when disassociated from generating NIGHT
963
- - **Non-transferable**: Cannot be bought, sold, or transferred between addresses
964
- - **MEV-resistant**: Shielding prevents attackers from identifying victims
965
-
966
- ### DUST Mechanics
967
-
968
- **Generation**:
969
- 1. NIGHT holder designates a DUST recipient address
970
- 2. DUST accumulates linearly over time up to a cap
971
- 3. Cap is proportional to associated NIGHT balance
972
-
973
- **DUST Cap**: Maximum DUST = f(associated NIGHT balance)
974
-
975
- **Usage**:
976
- - DUST is consumed/burned when used
977
- - No DUST is collected by block producers
978
- - Generation resumes after use if below cap
979
-
980
- **Decay**:
981
- - Severing NIGHT association causes linear decay
982
- - Prevents double-spending through cap enforcement
983
-
984
- ### DUST Beneficiaries
985
-
986
- 1. **NIGHT Holders**: Generate and use their own DUST
987
- 2. **DUST Recipients**: Receive DUST generation from NIGHT holders
988
- 3. **DUST Sponsees**: Transactions paid by a DUST holder (enables tokenless UX)
989
-
990
- ---
991
-
992
- ## Transaction Fees
993
-
994
- ### Components
995
-
996
- \`\`\`
997
- TxFee = CongestionRate × TxWeight + MinFee
998
- \`\`\`
999
-
1000
- - **Minimum Fee**: Fixed fee preventing DDoS attacks
1001
- - **Congestion Rate**: Dynamic multiplier based on network demand
1002
- - **Transaction Weight**: Based on computational resources (initially storage in KB)
1003
-
1004
- ### Block Utilization Target: 50%
1005
-
1006
- - Below 50%: Fees decrease to stimulate activity
1007
- - Above 50%: Fees increase to manage congestion
1008
- - Acts as automatic stabilizer for network efficiency
1009
-
1010
- ---
1011
-
1012
- ## Block Production & Rewards
1013
-
1014
- ### At Launch
1015
-
1016
- - Federated block production by trusted permissioned nodes
1017
- - Initial producers don't receive rewards
1018
- - Progressive decentralization planned
1019
-
1020
- ### Moving to Permissionless
1021
-
1022
- - Cardano SPOs can become Midnight Block Producers
1023
- - Selection proportional to delegated ADA stake
1024
- - Dual-network participation doesn't affect Cardano rewards
1025
-
1026
- ### Block Reward Formula
1027
-
1028
- **Base Distribution Rate (R)**:
1029
- \`\`\`
1030
- R = π(1 - B - T) / (B × γ)
1031
-
1032
- Where:
1033
- - π = Initial annual inflation rate (~3.14%)
1034
- - B = Reserve allocation percentage
1035
- - T = Treasury allocation percentage
1036
- - γ = Blocks per year
1037
- \`\`\`
1038
-
1039
- **Base Reward**:
1040
- \`\`\`
1041
- Nb = Bo × R
1042
-
1043
- Where Bo = Outstanding tokens in Reserve
577
+ Hold NIGHT Generates DUST Pay for transactions
578
+ (continuous) (consumed on use)
1044
579
  \`\`\`
1045
580
 
1046
- ### Reward Split
581
+ This means: **Hold NIGHT, transact "for free"** (no recurring token spend)
1047
582
 
1048
- Rewards divided between block producer and Treasury based on block utilization:
583
+ ## Block Rewards
1049
584
 
585
+ **Formula**:
1050
586
  \`\`\`
1051
- Actual Reward (Na) = Nb × [S + (1 - S) × U]
1052
- Treasury Share (Nt) = Nb - Na
587
+ Actual Reward = Base Reward × [S + (1-S) × U]
1053
588
 
1054
589
  Where:
1055
590
  - S = Subsidy rate (95% at launch)
1056
- - U = Block utilization ratio
591
+ - U = Block utilization (target: 50%)
1057
592
  \`\`\`
1058
593
 
1059
- - **Full block**: Producer gets 100% of base reward
1060
- - **Empty block**: Producer gets only the subsidy (95%)
1061
- - **Partially full**: Linear interpolation between them
1062
-
1063
- ---
594
+ - Full blocks: Producer gets 100% of base reward
595
+ - Empty blocks: Producer gets only subsidy (95%)
596
+ - Remainder goes to Treasury
1064
597
 
1065
598
  ## Token Distribution
1066
599
 
1067
- ### Design Principles
1068
-
1069
- - **Broad**: No single party dominates
1070
- - **Inclusive**: Open to participants beyond crypto
1071
- - **Free**: Allocated at no cost
1072
- - **Transparent**: Open-source audited smart contracts
1073
-
1074
600
  ### Phase 1: Glacier Drop (60 days)
601
+ - Free allocation to crypto holders
602
+ - 50% to Cardano, 20% to Bitcoin, 30% to others
603
+ - Minimum $100 USD equivalent required
1075
604
 
1076
- **Eligible Networks**:
1077
- - Cardano (50% allocation)
1078
- - Bitcoin (20% allocation)
1079
- - Ethereum, Solana, XRPL, BNB Chain, Avalanche, Brave (remaining 30%, proportional)
1080
-
1081
- **Eligibility**:
1082
- - Minimum $100 USD equivalent in native tokens at snapshot
1083
- - Address not on OFAC sanctions list
1084
- - Random historical snapshot to prevent gaming
1085
-
1086
- **Mechanics**:
1087
- 1. Sign message proving address ownership
1088
- 2. Provide unused Cardano address for redemption
1089
- 3. Tokens initially frozen, thaw during redemption period
1090
-
1091
- ### Phase 2: Scavenger Mine (30 days)
1092
-
1093
- - Process unclaimed Glacier Drop tokens
1094
- - Computational puzzles accessible to general public
1095
- - Daily allocation over 30 one-day slots
1096
-
1097
- **Apportionment of Unclaimed Tokens**:
1098
- - ~35% → Midnight Foundation
1099
- - ~30% → Reserve (block rewards)
1100
- - ~10% → Midnight TGE (partnerships/liquidity)
1101
- - ~5% → On-chain Treasury
1102
- - Rest → Scavenger Mine participants + Lost-and-Found
605
+ ### Phase 2: Scavenger Mine (30 days)
606
+ - Computational puzzles (accessible to public)
607
+ - Claims unclaimed Glacier Drop tokens
608
+ - Seeds network constituents
1103
609
 
1104
610
  ### Phase 3: Lost-and-Found (4 years)
611
+ - Second chance for Glacier Drop eligible
612
+ - Fractional allocation
1105
613
 
1106
- - Second chance for eligible non-claimers from Glacier Drop
1107
- - Fractional allocation of original entitlement
1108
- - After 4 years, unclaimed tokens go to Treasury
1109
-
1110
- ### Redemption Period (450 days)
1111
-
1112
- **Thawing Schedule**:
1113
- - Random start day (1-90 days after genesis)
1114
- - 25% unlock at start, then every 90 days
1115
- - Total: 4 unlocks over 360 days
1116
-
1117
- ---
1118
-
1119
- ## Cooperative Tokenomics
614
+ ## Key Differentiators
1120
615
 
1121
- ### Capacity Marketplace
1122
-
1123
- Enables non-NIGHT holders to access Midnight:
1124
-
1125
- **Off-chain Models**:
1126
- - DUST generation leasing
1127
- - Broker-managed leasing
1128
- - Babel Station (DUST filling station using ZSwap)
616
+ 1. **No token spend for transactions** - DUST is renewable
617
+ 2. **MEV resistant** - Shielded transactions
618
+ 3. **Cross-chain native** - Same token on Cardano + Midnight
619
+ 4. **Fair distribution** - Free, multi-phase, broad eligibility
620
+ `,
621
+ "midnight://docs/wallet-integration": `# Midnight Wallet Integration Guide
1129
622
 
1130
- **On-chain Models** (future):
1131
- - Ledger-native capacity leasing
1132
- - On-chain capacity exchange
623
+ A guide for integrating Midnight Lace wallet into your DApp.
1133
624
 
1134
- ### Multi-chain Features
625
+ ## Browser Detection
1135
626
 
1136
- **Cross-chain Observability**: Actions on one chain trigger agents on another
627
+ \`\`\`typescript
628
+ declare global {
629
+ interface Window {
630
+ midnight?: {
631
+ mnLace?: MidnightProvider;
632
+ };
633
+ }
634
+ }
1137
635
 
1138
- **Multichain Signatures**: Treasury can receive fees in other tokens
636
+ function isWalletAvailable(): boolean {
637
+ return typeof window !== 'undefined'
638
+ && window.midnight?.mnLace !== undefined;
639
+ }
640
+ \`\`\`
1139
641
 
1140
- ---
642
+ ## DApp Connector API
1141
643
 
1142
- ## Governance
644
+ \`\`\`typescript
645
+ interface DAppConnectorAPI {
646
+ enable(): Promise<MidnightAPI>;
647
+ isEnabled(): Promise<boolean>;
648
+ apiVersion(): string;
649
+ name(): string;
650
+ icon(): string;
651
+ }
1143
652
 
1144
- ### At Launch: Federated
653
+ async function connectWallet(): Promise<MidnightAPI> {
654
+ if (!window.midnight?.mnLace) {
655
+ throw new Error('Midnight Lace wallet not found');
656
+ }
657
+ return await window.midnight.mnLace.enable();
658
+ }
659
+ \`\`\`
1145
660
 
1146
- - Select committee with equal powers
1147
- - Multisig mechanism for protocol updates
1148
- - Handles: parameter updates, protocol upgrades, hard forks
661
+ ## MidnightAPI Interface
1149
662
 
1150
- ### Future: Decentralized On-chain
663
+ \`\`\`typescript
664
+ interface MidnightAPI {
665
+ getUsedAddresses(): Promise<string[]>;
666
+ getBalance(): Promise<Balance>;
667
+ signTx(tx: Transaction): Promise<SignedTransaction>;
668
+ submitTx(signedTx: SignedTransaction): Promise<TxHash>;
669
+ signData(address: string, payload: string): Promise<Signature>;
670
+ }
671
+ \`\`\`
1151
672
 
1152
- - Community-centric tools and processes
1153
- - Proposal submission and voting
1154
- - Treasury access for approved proposals
1155
- - Automated protocol updates
673
+ ## React Hook
1156
674
 
1157
- ---
675
+ \`\`\`typescript
676
+ export function useWallet() {
677
+ const [state, setState] = useState({
678
+ isConnected: false,
679
+ address: null as string | null,
680
+ isLoading: false,
681
+ error: null as string | null,
682
+ });
683
+
684
+ const connect = useCallback(async () => {
685
+ setState(prev => ({ ...prev, isLoading: true, error: null }));
686
+ try {
687
+ if (!window.midnight?.mnLace) {
688
+ throw new Error('Please install Midnight Lace wallet');
689
+ }
690
+ const api = await window.midnight.mnLace.enable();
691
+ const addresses = await api.getUsedAddresses();
692
+ setState({
693
+ isConnected: true,
694
+ address: addresses[0] || null,
695
+ isLoading: false,
696
+ error: null,
697
+ });
698
+ return api;
699
+ } catch (error) {
700
+ setState(prev => ({
701
+ ...prev,
702
+ isLoading: false,
703
+ error: error instanceof Error ? error.message : 'Failed',
704
+ }));
705
+ throw error;
706
+ }
707
+ }, []);
708
+
709
+ return { ...state, connect };
710
+ }
711
+ \`\`\`
712
+
713
+ ## Connection Flow
714
+
715
+ \`\`\`
716
+ 1. User clicks "Connect Wallet"
717
+ 2. DApp calls window.midnight.mnLace.enable()
718
+ 3. Wallet popup asks user to approve
719
+ 4. User approves → DApp receives MidnightAPI
720
+ 5. DApp can now interact with wallet
721
+ \`\`\`
1158
722
 
1159
- ## Glossary
723
+ ## Best Practices
1160
724
 
1161
- - **NIGHT**: Midnight's native utility token
1162
- - **STAR**: Smallest subunit of NIGHT (1 NIGHT = 1M STARs)
1163
- - **DUST**: Shielded transaction resource
1164
- - **MBP**: Midnight Block Producer
1165
- - **Reserve**: Protocol-managed token pool for block rewards
1166
- - **Treasury**: Protocol-managed fund for ecosystem growth
1167
- - **Glacier Drop**: Initial free token distribution
1168
- - **Scavenger Mine**: Computational task-based distribution
1169
- - **ZSwap**: Atomic asset swap mechanism for privacy
1170
- - **Babel Station**: Service enabling tokenless transactions
725
+ 1. Always check wallet availability first
726
+ 2. Handle user rejection gracefully
727
+ 3. Store connection state in context
728
+ 4. Provide clear loading/error feedback
729
+ 5. Test with Midnight Lace extension
1171
730
  `,
1172
731
  };
1173
732
  //# sourceMappingURL=docs-content.js.map