midnight-mcp 0.0.1
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.
- package/LICENSE +21 -0
- package/README.md +136 -0
- package/dist/db/index.d.ts +3 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +2 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/vectorStore.d.ts +66 -0
- package/dist/db/vectorStore.d.ts.map +1 -0
- package/dist/db/vectorStore.js +196 -0
- package/dist/db/vectorStore.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/pipeline/embeddings.d.ts +25 -0
- package/dist/pipeline/embeddings.d.ts.map +1 -0
- package/dist/pipeline/embeddings.js +103 -0
- package/dist/pipeline/embeddings.js.map +1 -0
- package/dist/pipeline/github.d.ts +67 -0
- package/dist/pipeline/github.d.ts.map +1 -0
- package/dist/pipeline/github.js +287 -0
- package/dist/pipeline/github.js.map +1 -0
- package/dist/pipeline/index.d.ts +11 -0
- package/dist/pipeline/index.d.ts.map +1 -0
- package/dist/pipeline/index.js +6 -0
- package/dist/pipeline/index.js.map +1 -0
- package/dist/pipeline/indexer.d.ts +38 -0
- package/dist/pipeline/indexer.d.ts.map +1 -0
- package/dist/pipeline/indexer.js +222 -0
- package/dist/pipeline/indexer.js.map +1 -0
- package/dist/pipeline/parser.d.ts +46 -0
- package/dist/pipeline/parser.d.ts.map +1 -0
- package/dist/pipeline/parser.js +436 -0
- package/dist/pipeline/parser.js.map +1 -0
- package/dist/pipeline/releases.d.ts +112 -0
- package/dist/pipeline/releases.d.ts.map +1 -0
- package/dist/pipeline/releases.js +298 -0
- package/dist/pipeline/releases.js.map +1 -0
- package/dist/pipeline/repository.d.ts +372 -0
- package/dist/pipeline/repository.d.ts.map +1 -0
- package/dist/pipeline/repository.js +517 -0
- package/dist/pipeline/repository.js.map +1 -0
- package/dist/prompts/index.d.ts +3 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +2 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/templates.d.ts +26 -0
- package/dist/prompts/templates.d.ts.map +1 -0
- package/dist/prompts/templates.js +353 -0
- package/dist/prompts/templates.js.map +1 -0
- package/dist/resources/code.d.ts +16 -0
- package/dist/resources/code.d.ts.map +1 -0
- package/dist/resources/code.js +630 -0
- package/dist/resources/code.js.map +1 -0
- package/dist/resources/docs.d.ts +16 -0
- package/dist/resources/docs.d.ts.map +1 -0
- package/dist/resources/docs.js +989 -0
- package/dist/resources/docs.js.map +1 -0
- package/dist/resources/index.d.ts +6 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +13 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/schemas.d.ts +16 -0
- package/dist/resources/schemas.d.ts.map +1 -0
- package/dist/resources/schemas.js +407 -0
- package/dist/resources/schemas.js.map +1 -0
- package/dist/scripts/index-repos.d.ts +12 -0
- package/dist/scripts/index-repos.d.ts.map +1 -0
- package/dist/scripts/index-repos.js +53 -0
- package/dist/scripts/index-repos.js.map +1 -0
- package/dist/server.d.ts +14 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +231 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/analyze.d.ts +140 -0
- package/dist/tools/analyze.d.ts.map +1 -0
- package/dist/tools/analyze.js +270 -0
- package/dist/tools/analyze.js.map +1 -0
- package/dist/tools/index.d.ts +392 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +9 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/repository.d.ts +537 -0
- package/dist/tools/repository.d.ts.map +1 -0
- package/dist/tools/repository.js +654 -0
- package/dist/tools/repository.js.map +1 -0
- package/dist/tools/search.d.ts +204 -0
- package/dist/tools/search.d.ts.map +1 -0
- package/dist/tools/search.js +210 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/utils/config.d.ts +66 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +161 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +14 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +43 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,989 @@
|
|
|
1
|
+
import { githubClient } from "../pipeline/index.js";
|
|
2
|
+
import { logger } from "../utils/index.js";
|
|
3
|
+
// Documentation resource URIs
|
|
4
|
+
export const documentationResources = [
|
|
5
|
+
{
|
|
6
|
+
uri: "midnight://docs/compact-reference",
|
|
7
|
+
name: "Compact Language Reference",
|
|
8
|
+
description: "Complete Compact language reference including syntax, types, built-in functions, and circuit definitions",
|
|
9
|
+
mimeType: "text/markdown",
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
uri: "midnight://docs/sdk-api",
|
|
13
|
+
name: "TypeScript SDK API",
|
|
14
|
+
description: "TypeScript SDK API documentation with type signatures and usage examples",
|
|
15
|
+
mimeType: "text/markdown",
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
uri: "midnight://docs/concepts/zero-knowledge",
|
|
19
|
+
name: "Zero-Knowledge Proofs",
|
|
20
|
+
description: "Conceptual documentation about zero-knowledge proofs in Midnight",
|
|
21
|
+
mimeType: "text/markdown",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
uri: "midnight://docs/concepts/shielded-state",
|
|
25
|
+
name: "Shielded State",
|
|
26
|
+
description: "Understanding shielded (private) vs unshielded (public) state in Midnight",
|
|
27
|
+
mimeType: "text/markdown",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
uri: "midnight://docs/concepts/witnesses",
|
|
31
|
+
name: "Witness Functions",
|
|
32
|
+
description: "How witness functions work in Midnight for off-chain computation",
|
|
33
|
+
mimeType: "text/markdown",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
uri: "midnight://docs/concepts/kachina",
|
|
37
|
+
name: "Kachina Protocol",
|
|
38
|
+
description: "The Kachina protocol underlying Midnight's privacy features",
|
|
39
|
+
mimeType: "text/markdown",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
uri: "midnight://docs/openzeppelin",
|
|
43
|
+
name: "OpenZeppelin Contracts for Compact",
|
|
44
|
+
description: "Official OpenZeppelin library documentation - the recommended source for token contracts, access control, and security patterns",
|
|
45
|
+
mimeType: "text/markdown",
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
uri: "midnight://docs/openzeppelin/token",
|
|
49
|
+
name: "OpenZeppelin FungibleToken",
|
|
50
|
+
description: "Official token contract implementation - the recommended standard for tokens on Midnight",
|
|
51
|
+
mimeType: "text/markdown",
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
uri: "midnight://docs/openzeppelin/access",
|
|
55
|
+
name: "OpenZeppelin Access Control",
|
|
56
|
+
description: "Ownable, roles, and access control patterns from OpenZeppelin",
|
|
57
|
+
mimeType: "text/markdown",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
uri: "midnight://docs/openzeppelin/security",
|
|
61
|
+
name: "OpenZeppelin Security",
|
|
62
|
+
description: "Pausable and other security patterns from OpenZeppelin",
|
|
63
|
+
mimeType: "text/markdown",
|
|
64
|
+
},
|
|
65
|
+
];
|
|
66
|
+
// Static documentation content (embedded for offline access)
|
|
67
|
+
const EMBEDDED_DOCS = {
|
|
68
|
+
"midnight://docs/compact-reference": `# Compact Language Reference
|
|
69
|
+
|
|
70
|
+
Compact is a TypeScript-inspired language for writing privacy-preserving smart contracts on Midnight.
|
|
71
|
+
|
|
72
|
+
## Basic Structure
|
|
73
|
+
|
|
74
|
+
\`\`\`compact
|
|
75
|
+
include "std";
|
|
76
|
+
|
|
77
|
+
ledger {
|
|
78
|
+
// Public state (on-chain, visible to everyone)
|
|
79
|
+
counter: Counter;
|
|
80
|
+
|
|
81
|
+
// Private state (off-chain, only owner can see)
|
|
82
|
+
@private
|
|
83
|
+
secretValue: Field;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Circuit - generates ZK proof
|
|
87
|
+
export circuit increment(amount: Field): Void {
|
|
88
|
+
assert(amount > 0);
|
|
89
|
+
ledger.counter.increment(amount);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Witness - off-chain computation
|
|
93
|
+
witness getSecret(): Field {
|
|
94
|
+
return ledger.secretValue;
|
|
95
|
+
}
|
|
96
|
+
\`\`\`
|
|
97
|
+
|
|
98
|
+
## Data Types
|
|
99
|
+
|
|
100
|
+
### Primitive Types
|
|
101
|
+
- \`Field\` - Finite field element (basic numeric type)
|
|
102
|
+
- \`Boolean\` - True or false
|
|
103
|
+
- \`Bytes<N>\` - Fixed-size byte array
|
|
104
|
+
- \`Uint<N>\` - Unsigned integer (N = 8, 16, 32, 64, 128, 256)
|
|
105
|
+
|
|
106
|
+
### Collection Types
|
|
107
|
+
- \`Counter\` - Incrementable/decrementable counter
|
|
108
|
+
- \`Map<K, V>\` - Key-value mapping
|
|
109
|
+
- \`Set<T>\` - Collection of unique values
|
|
110
|
+
- \`Opaque<T>\` - Type-safe wrapper for arbitrary data
|
|
111
|
+
|
|
112
|
+
## Circuits
|
|
113
|
+
|
|
114
|
+
Circuits are functions that generate zero-knowledge proofs:
|
|
115
|
+
|
|
116
|
+
\`\`\`compact
|
|
117
|
+
export circuit transfer(to: Address, amount: Field): Void {
|
|
118
|
+
// Assertions create ZK constraints
|
|
119
|
+
assert(amount > 0);
|
|
120
|
+
assert(ledger.balance.value() >= amount);
|
|
121
|
+
|
|
122
|
+
// State modifications
|
|
123
|
+
ledger.balance.decrement(amount);
|
|
124
|
+
}
|
|
125
|
+
\`\`\`
|
|
126
|
+
|
|
127
|
+
### Key Points:
|
|
128
|
+
- \`export\` makes circuit callable from outside
|
|
129
|
+
- Must be deterministic (same inputs = same outputs)
|
|
130
|
+
- Cannot access external data directly (use witnesses)
|
|
131
|
+
- Assertions become ZK constraints
|
|
132
|
+
|
|
133
|
+
## Witnesses
|
|
134
|
+
|
|
135
|
+
Witnesses provide off-chain data to circuits:
|
|
136
|
+
|
|
137
|
+
\`\`\`compact
|
|
138
|
+
witness getCurrentPrice(): Field {
|
|
139
|
+
// This runs off-chain
|
|
140
|
+
return fetchPrice();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export circuit swap(amount: Field): Void {
|
|
144
|
+
const price = getCurrentPrice();
|
|
145
|
+
// Use price in circuit logic
|
|
146
|
+
}
|
|
147
|
+
\`\`\`
|
|
148
|
+
|
|
149
|
+
## Built-in Functions
|
|
150
|
+
|
|
151
|
+
### Cryptographic
|
|
152
|
+
- \`hash(data)\` - Compute cryptographic hash
|
|
153
|
+
- \`commit(value)\` - Create hiding commitment
|
|
154
|
+
- \`disclose(private)\` - Reveal private data
|
|
155
|
+
|
|
156
|
+
### State Operations
|
|
157
|
+
- \`Counter.increment(n)\` - Add to counter
|
|
158
|
+
- \`Counter.decrement(n)\` - Subtract from counter
|
|
159
|
+
- \`Counter.value()\` - Read current value
|
|
160
|
+
- \`Map.insert(k, v)\` - Add key-value
|
|
161
|
+
- \`Map.get(k)\` - Retrieve value
|
|
162
|
+
- \`Set.add(v)\` - Add to set
|
|
163
|
+
- \`Set.contains(v)\` - Check membership
|
|
164
|
+
|
|
165
|
+
## Privacy Annotations
|
|
166
|
+
|
|
167
|
+
\`\`\`compact
|
|
168
|
+
ledger {
|
|
169
|
+
publicData: Field; // Visible on-chain
|
|
170
|
+
@private
|
|
171
|
+
privateData: Field; // Only owner sees
|
|
172
|
+
}
|
|
173
|
+
\`\`\`
|
|
174
|
+
`,
|
|
175
|
+
"midnight://docs/sdk-api": `# Midnight TypeScript SDK API
|
|
176
|
+
|
|
177
|
+
## Installation
|
|
178
|
+
|
|
179
|
+
\`\`\`bash
|
|
180
|
+
npm install @midnight-ntwrk/midnight-js-contracts @midnight-ntwrk/midnight-js-types
|
|
181
|
+
\`\`\`
|
|
182
|
+
|
|
183
|
+
## Core Packages
|
|
184
|
+
|
|
185
|
+
### @midnight-ntwrk/midnight-js-contracts
|
|
186
|
+
Contract interaction layer for deploying and calling Midnight smart contracts.
|
|
187
|
+
|
|
188
|
+
\`\`\`typescript
|
|
189
|
+
import { Contract, DeployedContract } from '@midnight-ntwrk/midnight-js-contracts';
|
|
190
|
+
|
|
191
|
+
// Deploy a contract
|
|
192
|
+
const deployed = await Contract.deploy(
|
|
193
|
+
wallet,
|
|
194
|
+
contractArtifact,
|
|
195
|
+
initialState
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
// Call a circuit
|
|
199
|
+
const result = await deployed.call('increment', { amount: 1n });
|
|
200
|
+
\`\`\`
|
|
201
|
+
|
|
202
|
+
### @midnight-ntwrk/midnight-js-types
|
|
203
|
+
Shared types and interfaces for the SDK.
|
|
204
|
+
|
|
205
|
+
\`\`\`typescript
|
|
206
|
+
import type {
|
|
207
|
+
Address,
|
|
208
|
+
Transaction,
|
|
209
|
+
Proof,
|
|
210
|
+
ContractState
|
|
211
|
+
} from '@midnight-ntwrk/midnight-js-types';
|
|
212
|
+
\`\`\`
|
|
213
|
+
|
|
214
|
+
### @midnight-ntwrk/wallet-api
|
|
215
|
+
Wallet integration interface.
|
|
216
|
+
|
|
217
|
+
\`\`\`typescript
|
|
218
|
+
import { WalletAPI } from '@midnight-ntwrk/wallet-api';
|
|
219
|
+
|
|
220
|
+
const wallet = await WalletAPI.connect();
|
|
221
|
+
const address = await wallet.getAddress();
|
|
222
|
+
const balance = await wallet.getBalance();
|
|
223
|
+
\`\`\`
|
|
224
|
+
|
|
225
|
+
## Common Patterns
|
|
226
|
+
|
|
227
|
+
### Contract Deployment
|
|
228
|
+
\`\`\`typescript
|
|
229
|
+
import { Contract } from '@midnight-ntwrk/midnight-js-contracts';
|
|
230
|
+
import counterContract from './counter.json';
|
|
231
|
+
|
|
232
|
+
async function deployCounter() {
|
|
233
|
+
const deployed = await Contract.deploy(
|
|
234
|
+
wallet,
|
|
235
|
+
counterContract,
|
|
236
|
+
{ counter: 0n }
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
console.log('Deployed at:', deployed.address);
|
|
240
|
+
return deployed;
|
|
241
|
+
}
|
|
242
|
+
\`\`\`
|
|
243
|
+
|
|
244
|
+
### Calling Circuits
|
|
245
|
+
\`\`\`typescript
|
|
246
|
+
async function increment(contract: DeployedContract, amount: bigint) {
|
|
247
|
+
const tx = await contract.call('increment', { amount });
|
|
248
|
+
await tx.wait();
|
|
249
|
+
|
|
250
|
+
const newValue = await contract.query('counter');
|
|
251
|
+
return newValue;
|
|
252
|
+
}
|
|
253
|
+
\`\`\`
|
|
254
|
+
|
|
255
|
+
### Querying State
|
|
256
|
+
\`\`\`typescript
|
|
257
|
+
async function getState(contract: DeployedContract) {
|
|
258
|
+
const publicState = await contract.query('publicField');
|
|
259
|
+
// Note: Private state requires witness functions
|
|
260
|
+
return publicState;
|
|
261
|
+
}
|
|
262
|
+
\`\`\`
|
|
263
|
+
`,
|
|
264
|
+
"midnight://docs/concepts/zero-knowledge": `# Zero-Knowledge Proofs in Midnight
|
|
265
|
+
|
|
266
|
+
## What are Zero-Knowledge Proofs?
|
|
267
|
+
|
|
268
|
+
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.
|
|
269
|
+
|
|
270
|
+
## How Midnight Uses ZKPs
|
|
271
|
+
|
|
272
|
+
In Midnight, every circuit execution generates a zero-knowledge proof:
|
|
273
|
+
|
|
274
|
+
1. **User calls a circuit** with private inputs
|
|
275
|
+
2. **Proof is generated** off-chain
|
|
276
|
+
3. **Only the proof** (not the inputs) is submitted to the blockchain
|
|
277
|
+
4. **Validators verify** the proof without knowing the inputs
|
|
278
|
+
|
|
279
|
+
## Example
|
|
280
|
+
|
|
281
|
+
\`\`\`compact
|
|
282
|
+
export circuit proveAge(birthYear: Field): Boolean {
|
|
283
|
+
const currentYear = 2024;
|
|
284
|
+
const age = currentYear - birthYear;
|
|
285
|
+
|
|
286
|
+
// Proves user is over 18 without revealing exact age
|
|
287
|
+
assert(age >= 18);
|
|
288
|
+
return true;
|
|
289
|
+
}
|
|
290
|
+
\`\`\`
|
|
291
|
+
|
|
292
|
+
When this circuit runs:
|
|
293
|
+
- Input: \`birthYear = 1990\` (private)
|
|
294
|
+
- Output: \`true\` (public)
|
|
295
|
+
- Proof: "I know a birthYear that makes age >= 18" (public)
|
|
296
|
+
|
|
297
|
+
The verifier learns the user is over 18, but not their actual birth year.
|
|
298
|
+
|
|
299
|
+
## Key Properties
|
|
300
|
+
|
|
301
|
+
1. **Completeness**: Valid proofs always verify
|
|
302
|
+
2. **Soundness**: Invalid proofs cannot be forged
|
|
303
|
+
3. **Zero-knowledge**: Nothing beyond validity is revealed
|
|
304
|
+
|
|
305
|
+
## Privacy Patterns
|
|
306
|
+
|
|
307
|
+
### Selective Disclosure
|
|
308
|
+
\`\`\`compact
|
|
309
|
+
export circuit verifyCredential(
|
|
310
|
+
@private credential: Credential
|
|
311
|
+
): Field {
|
|
312
|
+
// Prove credential is valid
|
|
313
|
+
assert(credential.isValid());
|
|
314
|
+
|
|
315
|
+
// Only reveal specific fields
|
|
316
|
+
return disclose(credential.issuer);
|
|
317
|
+
}
|
|
318
|
+
\`\`\`
|
|
319
|
+
|
|
320
|
+
### Hidden Computation
|
|
321
|
+
\`\`\`compact
|
|
322
|
+
export circuit secretBid(
|
|
323
|
+
@private amount: Field,
|
|
324
|
+
commitment: Field
|
|
325
|
+
): Void {
|
|
326
|
+
// Prove bid matches commitment without revealing amount
|
|
327
|
+
assert(commit(amount) == commitment);
|
|
328
|
+
}
|
|
329
|
+
\`\`\`
|
|
330
|
+
`,
|
|
331
|
+
"midnight://docs/concepts/shielded-state": `# Shielded vs Unshielded State
|
|
332
|
+
|
|
333
|
+
Midnight supports two types of state: shielded (private) and unshielded (public).
|
|
334
|
+
|
|
335
|
+
## Unshielded State
|
|
336
|
+
|
|
337
|
+
Public state visible to everyone on the blockchain:
|
|
338
|
+
|
|
339
|
+
\`\`\`compact
|
|
340
|
+
ledger {
|
|
341
|
+
totalSupply: Counter; // Public counter
|
|
342
|
+
balances: Map<Address, Field>; // Public mapping
|
|
343
|
+
}
|
|
344
|
+
\`\`\`
|
|
345
|
+
|
|
346
|
+
**Use for:**
|
|
347
|
+
- Token total supply
|
|
348
|
+
- Public voting tallies
|
|
349
|
+
- Any data that should be transparent
|
|
350
|
+
|
|
351
|
+
## Shielded State
|
|
352
|
+
|
|
353
|
+
Private state only visible to the owner:
|
|
354
|
+
|
|
355
|
+
\`\`\`compact
|
|
356
|
+
ledger {
|
|
357
|
+
@private
|
|
358
|
+
secretKey: Bytes<32>;
|
|
359
|
+
|
|
360
|
+
@private
|
|
361
|
+
privateBalance: Field;
|
|
362
|
+
}
|
|
363
|
+
\`\`\`
|
|
364
|
+
|
|
365
|
+
**Use for:**
|
|
366
|
+
- User credentials
|
|
367
|
+
- Private balances
|
|
368
|
+
- Sensitive personal data
|
|
369
|
+
|
|
370
|
+
## Hybrid Approach
|
|
371
|
+
|
|
372
|
+
Most contracts use both:
|
|
373
|
+
|
|
374
|
+
\`\`\`compact
|
|
375
|
+
ledger {
|
|
376
|
+
// Public: anyone can see total messages
|
|
377
|
+
messageCount: Counter;
|
|
378
|
+
|
|
379
|
+
// Private: only owner sees message contents
|
|
380
|
+
@private
|
|
381
|
+
messages: Map<Field, Opaque<"string">>;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
export circuit postMessage(content: Opaque<"string">): Void {
|
|
385
|
+
const id = ledger.messageCount.value();
|
|
386
|
+
|
|
387
|
+
// Public increment
|
|
388
|
+
ledger.messageCount.increment(1);
|
|
389
|
+
|
|
390
|
+
// Private storage
|
|
391
|
+
ledger.messages.insert(id, content);
|
|
392
|
+
}
|
|
393
|
+
\`\`\`
|
|
394
|
+
|
|
395
|
+
## Transitioning Between States
|
|
396
|
+
|
|
397
|
+
### Disclose: Private → Public
|
|
398
|
+
\`\`\`compact
|
|
399
|
+
export circuit revealBalance(): Field {
|
|
400
|
+
// Reveal private balance publicly
|
|
401
|
+
return disclose(ledger.privateBalance);
|
|
402
|
+
}
|
|
403
|
+
\`\`\`
|
|
404
|
+
|
|
405
|
+
### Commit: Public → Hidden
|
|
406
|
+
\`\`\`compact
|
|
407
|
+
export circuit hideValue(value: Field): Field {
|
|
408
|
+
// Create commitment (hides value but proves existence)
|
|
409
|
+
return commit(value);
|
|
410
|
+
}
|
|
411
|
+
\`\`\`
|
|
412
|
+
`,
|
|
413
|
+
"midnight://docs/concepts/witnesses": `# Witness Functions
|
|
414
|
+
|
|
415
|
+
Witnesses provide off-chain data to circuits in Midnight.
|
|
416
|
+
|
|
417
|
+
## Why Witnesses?
|
|
418
|
+
|
|
419
|
+
Circuits run in a ZK environment with limitations:
|
|
420
|
+
- Cannot make network requests
|
|
421
|
+
- Cannot access system time
|
|
422
|
+
- Cannot read external files
|
|
423
|
+
- Must be deterministic
|
|
424
|
+
|
|
425
|
+
Witnesses bridge this gap by running off-chain.
|
|
426
|
+
|
|
427
|
+
## Basic Witness
|
|
428
|
+
|
|
429
|
+
\`\`\`compact
|
|
430
|
+
// Runs off-chain, provides data to circuits
|
|
431
|
+
witness getTimestamp(): Field {
|
|
432
|
+
return getCurrentUnixTime();
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
export circuit timedAction(): Void {
|
|
436
|
+
const timestamp = getTimestamp();
|
|
437
|
+
assert(timestamp > ledger.deadline);
|
|
438
|
+
// ... perform action
|
|
439
|
+
}
|
|
440
|
+
\`\`\`
|
|
441
|
+
|
|
442
|
+
## Witness with Parameters
|
|
443
|
+
|
|
444
|
+
\`\`\`compact
|
|
445
|
+
witness fetchPrice(asset: Opaque<"string">): Field {
|
|
446
|
+
// Off-chain: call price oracle
|
|
447
|
+
return callPriceOracle(asset);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
export circuit swap(asset: Opaque<"string">, amount: Field): Void {
|
|
451
|
+
const price = fetchPrice(asset);
|
|
452
|
+
const total = amount * price;
|
|
453
|
+
// ... execute swap
|
|
454
|
+
}
|
|
455
|
+
\`\`\`
|
|
456
|
+
|
|
457
|
+
## Private Data Access
|
|
458
|
+
|
|
459
|
+
Witnesses can access private ledger state:
|
|
460
|
+
|
|
461
|
+
\`\`\`compact
|
|
462
|
+
ledger {
|
|
463
|
+
@private
|
|
464
|
+
secretNonce: Field;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
witness getNextNonce(): Field {
|
|
468
|
+
const current = ledger.secretNonce;
|
|
469
|
+
return current + 1;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
export circuit signedOperation(data: Field): Field {
|
|
473
|
+
const nonce = getNextNonce();
|
|
474
|
+
return hash(data, nonce);
|
|
475
|
+
}
|
|
476
|
+
\`\`\`
|
|
477
|
+
|
|
478
|
+
## Best Practices
|
|
479
|
+
|
|
480
|
+
1. **Keep witnesses simple** - Complex logic should be in circuits
|
|
481
|
+
2. **Handle failures gracefully** - Witnesses can fail
|
|
482
|
+
3. **Don't trust witness data blindly** - Validate in circuits
|
|
483
|
+
4. **Cache when possible** - Reduce off-chain calls
|
|
484
|
+
|
|
485
|
+
## Security Considerations
|
|
486
|
+
|
|
487
|
+
⚠️ Witnesses are NOT proven in ZK:
|
|
488
|
+
- Circuit verifies witness output is used correctly
|
|
489
|
+
- But doesn't verify HOW witness computed the value
|
|
490
|
+
- Malicious witnesses can provide false data
|
|
491
|
+
|
|
492
|
+
Always add assertions to validate witness data:
|
|
493
|
+
|
|
494
|
+
\`\`\`compact
|
|
495
|
+
export circuit usePrice(asset: Opaque<"string">): Void {
|
|
496
|
+
const price = fetchPrice(asset);
|
|
497
|
+
|
|
498
|
+
// Validate witness data
|
|
499
|
+
assert(price > 0);
|
|
500
|
+
assert(price < MAX_REASONABLE_PRICE);
|
|
501
|
+
|
|
502
|
+
// ... use price
|
|
503
|
+
}
|
|
504
|
+
\`\`\`
|
|
505
|
+
`,
|
|
506
|
+
"midnight://docs/concepts/kachina": `# Kachina Protocol
|
|
507
|
+
|
|
508
|
+
Kachina is the cryptographic protocol underlying Midnight's privacy features.
|
|
509
|
+
|
|
510
|
+
## Overview
|
|
511
|
+
|
|
512
|
+
Kachina enables:
|
|
513
|
+
- Private smart contracts with public verifiability
|
|
514
|
+
- Composable privacy across contracts
|
|
515
|
+
- Efficient on-chain verification
|
|
516
|
+
|
|
517
|
+
## Architecture
|
|
518
|
+
|
|
519
|
+
\`\`\`
|
|
520
|
+
┌─────────────────┐ ┌─────────────────┐
|
|
521
|
+
│ User Wallet │────▶│ Compact Code │
|
|
522
|
+
└─────────────────┘ └────────┬────────┘
|
|
523
|
+
│
|
|
524
|
+
┌────────▼────────┐
|
|
525
|
+
│ ZK Circuit │
|
|
526
|
+
│ (Prover) │
|
|
527
|
+
└────────┬────────┘
|
|
528
|
+
│
|
|
529
|
+
┌────────▼────────┐
|
|
530
|
+
│ Proof │
|
|
531
|
+
└────────┬────────┘
|
|
532
|
+
│
|
|
533
|
+
┌────────▼────────┐
|
|
534
|
+
│ Midnight │
|
|
535
|
+
│ Validators │
|
|
536
|
+
└─────────────────┘
|
|
537
|
+
\`\`\`
|
|
538
|
+
|
|
539
|
+
## Key Concepts
|
|
540
|
+
|
|
541
|
+
### State Model
|
|
542
|
+
- **Public State**: Stored on-chain, visible to all
|
|
543
|
+
- **Private State**: Stored off-chain, encrypted
|
|
544
|
+
- **Commitments**: On-chain references to private state
|
|
545
|
+
|
|
546
|
+
### Transaction Flow
|
|
547
|
+
1. User prepares transaction locally
|
|
548
|
+
2. Prover generates ZK proof
|
|
549
|
+
3. Transaction + proof submitted to network
|
|
550
|
+
4. Validators verify proof (not re-execute)
|
|
551
|
+
5. State updates applied
|
|
552
|
+
|
|
553
|
+
### Composability
|
|
554
|
+
Contracts can interact while preserving privacy:
|
|
555
|
+
|
|
556
|
+
\`\`\`compact
|
|
557
|
+
// Contract A
|
|
558
|
+
export circuit transferToken(to: Address, amount: Field): Void {
|
|
559
|
+
// Private transfer logic
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
// Contract B can call Contract A
|
|
563
|
+
export circuit atomicSwap(
|
|
564
|
+
tokenA: Address,
|
|
565
|
+
tokenB: Address,
|
|
566
|
+
amountA: Field,
|
|
567
|
+
amountB: Field
|
|
568
|
+
): Void {
|
|
569
|
+
// Both transfers happen atomically
|
|
570
|
+
// Privacy preserved for both
|
|
571
|
+
}
|
|
572
|
+
\`\`\`
|
|
573
|
+
|
|
574
|
+
## Benefits
|
|
575
|
+
|
|
576
|
+
1. **Privacy by Default**: All computation is private unless explicitly disclosed
|
|
577
|
+
2. **Scalability**: Verification is faster than re-execution
|
|
578
|
+
3. **Flexibility**: Developers choose what to reveal
|
|
579
|
+
4. **Interoperability**: Works with existing blockchain infrastructure
|
|
580
|
+
`,
|
|
581
|
+
"midnight://docs/openzeppelin": `# OpenZeppelin Contracts for Compact
|
|
582
|
+
|
|
583
|
+
> **Official Documentation**: https://docs.openzeppelin.com/contracts-compact
|
|
584
|
+
> **GitHub Repository**: https://github.com/OpenZeppelin/compact-contracts
|
|
585
|
+
|
|
586
|
+
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.
|
|
587
|
+
|
|
588
|
+
## Installation
|
|
589
|
+
|
|
590
|
+
\`\`\`bash
|
|
591
|
+
# Create project directory
|
|
592
|
+
mkdir my-project && cd my-project
|
|
593
|
+
|
|
594
|
+
# Initialize git and add as submodule
|
|
595
|
+
git init && git submodule add https://github.com/OpenZeppelin/compact-contracts.git
|
|
596
|
+
|
|
597
|
+
# Install dependencies
|
|
598
|
+
cd compact-contracts
|
|
599
|
+
nvm install && yarn && SKIP_ZK=true yarn compact
|
|
600
|
+
\`\`\`
|
|
601
|
+
|
|
602
|
+
## Available Modules
|
|
603
|
+
|
|
604
|
+
### Token
|
|
605
|
+
- **FungibleToken**: Standard token implementation with transfer, mint, burn
|
|
606
|
+
- Recommended for all token contracts on Midnight
|
|
607
|
+
|
|
608
|
+
### Access Control
|
|
609
|
+
- **Ownable**: Single owner access control
|
|
610
|
+
- **AccessControl**: Role-based access control
|
|
611
|
+
|
|
612
|
+
### Security
|
|
613
|
+
- **Pausable**: Emergency stop mechanism
|
|
614
|
+
|
|
615
|
+
## Usage Example
|
|
616
|
+
|
|
617
|
+
\`\`\`compact
|
|
618
|
+
pragma language_version >= 0.16.0;
|
|
619
|
+
|
|
620
|
+
import CompactStandardLibrary;
|
|
621
|
+
import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/access/Ownable" prefix Ownable_;
|
|
622
|
+
import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/security/Pausable" prefix Pausable_;
|
|
623
|
+
import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/token/FungibleToken" prefix FungibleToken_;
|
|
624
|
+
|
|
625
|
+
constructor(
|
|
626
|
+
_name: Opaque<"string">,
|
|
627
|
+
_symbol: Opaque<"string">,
|
|
628
|
+
_decimals: Uint<8>,
|
|
629
|
+
_recipient: Either<ZswapCoinPublicKey, ContractAddress>,
|
|
630
|
+
_amount: Uint<128>,
|
|
631
|
+
_initOwner: Either<ZswapCoinPublicKey, ContractAddress>,
|
|
632
|
+
) {
|
|
633
|
+
Ownable_initialize(_initOwner);
|
|
634
|
+
FungibleToken_initialize(_name, _symbol, _decimals);
|
|
635
|
+
FungibleToken__mint(_recipient, _amount);
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
export circuit transfer(
|
|
639
|
+
to: Either<ZswapCoinPublicKey, ContractAddress>,
|
|
640
|
+
value: Uint<128>,
|
|
641
|
+
): Boolean {
|
|
642
|
+
Pausable_assertNotPaused();
|
|
643
|
+
return FungibleToken_transfer(to, value);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
export circuit pause(): [] {
|
|
647
|
+
Ownable_assertOnlyOwner();
|
|
648
|
+
Pausable__pause();
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
export circuit unpause(): [] {
|
|
652
|
+
Ownable_assertOnlyOwner();
|
|
653
|
+
Pausable__unpause();
|
|
654
|
+
}
|
|
655
|
+
\`\`\`
|
|
656
|
+
|
|
657
|
+
## Compilation
|
|
658
|
+
|
|
659
|
+
\`\`\`bash
|
|
660
|
+
compact compile MyContract.compact artifacts/MyContract
|
|
661
|
+
\`\`\`
|
|
662
|
+
|
|
663
|
+
## Why Use OpenZeppelin?
|
|
664
|
+
|
|
665
|
+
1. **Security Audited**: Contracts are professionally audited
|
|
666
|
+
2. **Battle-Tested**: Used in production across the ecosystem
|
|
667
|
+
3. **Official Recommendation**: Midnight's recommended library for tokens
|
|
668
|
+
4. **Modularity**: Use only what you need
|
|
669
|
+
5. **Best Practices**: Follows Compact language best practices
|
|
670
|
+
`,
|
|
671
|
+
"midnight://docs/openzeppelin/token": `# OpenZeppelin FungibleToken
|
|
672
|
+
|
|
673
|
+
> **This is the official and recommended token standard for Midnight.**
|
|
674
|
+
|
|
675
|
+
The FungibleToken module provides a complete implementation for fungible tokens on Midnight.
|
|
676
|
+
|
|
677
|
+
## Features
|
|
678
|
+
|
|
679
|
+
- ERC20-compatible interface
|
|
680
|
+
- Transfer with balance tracking
|
|
681
|
+
- Mint and burn operations
|
|
682
|
+
- Approval and transferFrom patterns
|
|
683
|
+
- Privacy-preserving by default
|
|
684
|
+
|
|
685
|
+
## Basic Usage
|
|
686
|
+
|
|
687
|
+
\`\`\`compact
|
|
688
|
+
pragma language_version >= 0.16.0;
|
|
689
|
+
|
|
690
|
+
import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/token/FungibleToken" prefix FungibleToken_;
|
|
691
|
+
|
|
692
|
+
constructor(
|
|
693
|
+
_name: Opaque<"string">,
|
|
694
|
+
_symbol: Opaque<"string">,
|
|
695
|
+
_decimals: Uint<8>,
|
|
696
|
+
_recipient: Either<ZswapCoinPublicKey, ContractAddress>,
|
|
697
|
+
_initialSupply: Uint<128>,
|
|
698
|
+
) {
|
|
699
|
+
FungibleToken_initialize(_name, _symbol, _decimals);
|
|
700
|
+
FungibleToken__mint(_recipient, _initialSupply);
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// Transfer tokens
|
|
704
|
+
export circuit transfer(
|
|
705
|
+
to: Either<ZswapCoinPublicKey, ContractAddress>,
|
|
706
|
+
value: Uint<128>,
|
|
707
|
+
): Boolean {
|
|
708
|
+
return FungibleToken_transfer(to, value);
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
// Check balance (witness function for privacy)
|
|
712
|
+
witness balanceOf(
|
|
713
|
+
account: Either<ZswapCoinPublicKey, ContractAddress>
|
|
714
|
+
): Uint<128> {
|
|
715
|
+
return FungibleToken_balanceOf(account);
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// Get total supply
|
|
719
|
+
witness totalSupply(): Uint<128> {
|
|
720
|
+
return FungibleToken_totalSupply();
|
|
721
|
+
}
|
|
722
|
+
\`\`\`
|
|
723
|
+
|
|
724
|
+
## Advanced: With Approval Pattern
|
|
725
|
+
|
|
726
|
+
\`\`\`compact
|
|
727
|
+
// Approve spender
|
|
728
|
+
export circuit approve(
|
|
729
|
+
spender: Either<ZswapCoinPublicKey, ContractAddress>,
|
|
730
|
+
value: Uint<128>,
|
|
731
|
+
): Boolean {
|
|
732
|
+
return FungibleToken_approve(spender, value);
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
// Transfer from approved account
|
|
736
|
+
export circuit transferFrom(
|
|
737
|
+
from: Either<ZswapCoinPublicKey, ContractAddress>,
|
|
738
|
+
to: Either<ZswapCoinPublicKey, ContractAddress>,
|
|
739
|
+
value: Uint<128>,
|
|
740
|
+
): Boolean {
|
|
741
|
+
return FungibleToken_transferFrom(from, to, value);
|
|
742
|
+
}
|
|
743
|
+
\`\`\`
|
|
744
|
+
|
|
745
|
+
## Mint and Burn (Owner-Only)
|
|
746
|
+
|
|
747
|
+
\`\`\`compact
|
|
748
|
+
import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/access/Ownable" prefix Ownable_;
|
|
749
|
+
|
|
750
|
+
export circuit mint(
|
|
751
|
+
to: Either<ZswapCoinPublicKey, ContractAddress>,
|
|
752
|
+
amount: Uint<128>,
|
|
753
|
+
): [] {
|
|
754
|
+
Ownable_assertOnlyOwner();
|
|
755
|
+
FungibleToken__mint(to, amount);
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
export circuit burn(
|
|
759
|
+
from: Either<ZswapCoinPublicKey, ContractAddress>,
|
|
760
|
+
amount: Uint<128>,
|
|
761
|
+
): [] {
|
|
762
|
+
Ownable_assertOnlyOwner();
|
|
763
|
+
FungibleToken__burn(from, amount);
|
|
764
|
+
}
|
|
765
|
+
\`\`\`
|
|
766
|
+
`,
|
|
767
|
+
"midnight://docs/openzeppelin/access": `# OpenZeppelin Access Control
|
|
768
|
+
|
|
769
|
+
Access control modules for managing permissions in your contracts.
|
|
770
|
+
|
|
771
|
+
## Ownable
|
|
772
|
+
|
|
773
|
+
Simple single-owner access control.
|
|
774
|
+
|
|
775
|
+
\`\`\`compact
|
|
776
|
+
pragma language_version >= 0.16.0;
|
|
777
|
+
|
|
778
|
+
import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/access/Ownable" prefix Ownable_;
|
|
779
|
+
|
|
780
|
+
constructor(
|
|
781
|
+
_owner: Either<ZswapCoinPublicKey, ContractAddress>,
|
|
782
|
+
) {
|
|
783
|
+
Ownable_initialize(_owner);
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
// Only owner can call this
|
|
787
|
+
export circuit adminFunction(): [] {
|
|
788
|
+
Ownable_assertOnlyOwner();
|
|
789
|
+
// ... admin logic
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
// Transfer ownership
|
|
793
|
+
export circuit transferOwnership(
|
|
794
|
+
newOwner: Either<ZswapCoinPublicKey, ContractAddress>,
|
|
795
|
+
): [] {
|
|
796
|
+
Ownable_assertOnlyOwner();
|
|
797
|
+
Ownable_transferOwnership(newOwner);
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
// Renounce ownership (irreversible!)
|
|
801
|
+
export circuit renounceOwnership(): [] {
|
|
802
|
+
Ownable_assertOnlyOwner();
|
|
803
|
+
Ownable_renounceOwnership();
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
// Check current owner
|
|
807
|
+
witness owner(): Either<ZswapCoinPublicKey, ContractAddress> {
|
|
808
|
+
return Ownable_owner();
|
|
809
|
+
}
|
|
810
|
+
\`\`\`
|
|
811
|
+
|
|
812
|
+
## AccessControl (Role-Based)
|
|
813
|
+
|
|
814
|
+
For contracts needing multiple roles with different permissions.
|
|
815
|
+
|
|
816
|
+
\`\`\`compact
|
|
817
|
+
import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/access/AccessControl" prefix AC_;
|
|
818
|
+
|
|
819
|
+
// Define role identifiers
|
|
820
|
+
const MINTER_ROLE: Bytes<32> = keccak256("MINTER_ROLE");
|
|
821
|
+
const PAUSER_ROLE: Bytes<32> = keccak256("PAUSER_ROLE");
|
|
822
|
+
|
|
823
|
+
constructor(_admin: Either<ZswapCoinPublicKey, ContractAddress>) {
|
|
824
|
+
AC_initialize(_admin);
|
|
825
|
+
AC__grantRole(MINTER_ROLE, _admin);
|
|
826
|
+
AC__grantRole(PAUSER_ROLE, _admin);
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
// Only minters can call
|
|
830
|
+
export circuit mint(to: Address, amount: Uint<128>): [] {
|
|
831
|
+
AC_assertOnlyRole(MINTER_ROLE);
|
|
832
|
+
// ... mint logic
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
// Only pausers can call
|
|
836
|
+
export circuit pause(): [] {
|
|
837
|
+
AC_assertOnlyRole(PAUSER_ROLE);
|
|
838
|
+
// ... pause logic
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
// Grant role (admin only)
|
|
842
|
+
export circuit grantRole(
|
|
843
|
+
role: Bytes<32>,
|
|
844
|
+
account: Either<ZswapCoinPublicKey, ContractAddress>,
|
|
845
|
+
): [] {
|
|
846
|
+
AC_assertOnlyRole(AC_DEFAULT_ADMIN_ROLE());
|
|
847
|
+
AC__grantRole(role, account);
|
|
848
|
+
}
|
|
849
|
+
\`\`\`
|
|
850
|
+
`,
|
|
851
|
+
"midnight://docs/openzeppelin/security": `# OpenZeppelin Security Patterns
|
|
852
|
+
|
|
853
|
+
Security modules for protecting your contracts.
|
|
854
|
+
|
|
855
|
+
## Pausable
|
|
856
|
+
|
|
857
|
+
Emergency stop mechanism for your contract.
|
|
858
|
+
|
|
859
|
+
\`\`\`compact
|
|
860
|
+
pragma language_version >= 0.16.0;
|
|
861
|
+
|
|
862
|
+
import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/security/Pausable" prefix Pausable_;
|
|
863
|
+
import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/access/Ownable" prefix Ownable_;
|
|
864
|
+
|
|
865
|
+
constructor(_owner: Either<ZswapCoinPublicKey, ContractAddress>) {
|
|
866
|
+
Ownable_initialize(_owner);
|
|
867
|
+
// Contract starts unpaused
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
// Protected function - won't work when paused
|
|
871
|
+
export circuit transfer(
|
|
872
|
+
to: Either<ZswapCoinPublicKey, ContractAddress>,
|
|
873
|
+
amount: Uint<128>,
|
|
874
|
+
): Boolean {
|
|
875
|
+
Pausable_assertNotPaused();
|
|
876
|
+
// ... transfer logic
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
// Owner can pause
|
|
880
|
+
export circuit pause(): [] {
|
|
881
|
+
Ownable_assertOnlyOwner();
|
|
882
|
+
Pausable__pause();
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
// Owner can unpause
|
|
886
|
+
export circuit unpause(): [] {
|
|
887
|
+
Ownable_assertOnlyOwner();
|
|
888
|
+
Pausable__unpause();
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
// Check if paused
|
|
892
|
+
witness isPaused(): Boolean {
|
|
893
|
+
return Pausable_paused();
|
|
894
|
+
}
|
|
895
|
+
\`\`\`
|
|
896
|
+
|
|
897
|
+
## Combined Example: Secure Token
|
|
898
|
+
|
|
899
|
+
\`\`\`compact
|
|
900
|
+
pragma language_version >= 0.16.0;
|
|
901
|
+
|
|
902
|
+
import CompactStandardLibrary;
|
|
903
|
+
import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/access/Ownable" prefix Ownable_;
|
|
904
|
+
import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/security/Pausable" prefix Pausable_;
|
|
905
|
+
import "./compact-contracts/node_modules/@openzeppelin-compact/contracts/src/token/FungibleToken" prefix FungibleToken_;
|
|
906
|
+
|
|
907
|
+
constructor(
|
|
908
|
+
_name: Opaque<"string">,
|
|
909
|
+
_symbol: Opaque<"string">,
|
|
910
|
+
_decimals: Uint<8>,
|
|
911
|
+
_initialSupply: Uint<128>,
|
|
912
|
+
_owner: Either<ZswapCoinPublicKey, ContractAddress>,
|
|
913
|
+
) {
|
|
914
|
+
Ownable_initialize(_owner);
|
|
915
|
+
FungibleToken_initialize(_name, _symbol, _decimals);
|
|
916
|
+
FungibleToken__mint(_owner, _initialSupply);
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
// Pausable transfer
|
|
920
|
+
export circuit transfer(
|
|
921
|
+
to: Either<ZswapCoinPublicKey, ContractAddress>,
|
|
922
|
+
value: Uint<128>,
|
|
923
|
+
): Boolean {
|
|
924
|
+
Pausable_assertNotPaused();
|
|
925
|
+
return FungibleToken_transfer(to, value);
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
// Owner-only mint
|
|
929
|
+
export circuit mint(
|
|
930
|
+
to: Either<ZswapCoinPublicKey, ContractAddress>,
|
|
931
|
+
amount: Uint<128>,
|
|
932
|
+
): [] {
|
|
933
|
+
Ownable_assertOnlyOwner();
|
|
934
|
+
Pausable_assertNotPaused();
|
|
935
|
+
FungibleToken__mint(to, amount);
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
// Emergency pause
|
|
939
|
+
export circuit pause(): [] {
|
|
940
|
+
Ownable_assertOnlyOwner();
|
|
941
|
+
Pausable__pause();
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
export circuit unpause(): [] {
|
|
945
|
+
Ownable_assertOnlyOwner();
|
|
946
|
+
Pausable__unpause();
|
|
947
|
+
}
|
|
948
|
+
\`\`\`
|
|
949
|
+
|
|
950
|
+
## Best Practices
|
|
951
|
+
|
|
952
|
+
1. **Always use Pausable** for contracts handling value
|
|
953
|
+
2. **Combine with Ownable** for admin-only pause control
|
|
954
|
+
3. **Test pause scenarios** thoroughly
|
|
955
|
+
4. **Document pause conditions** for users
|
|
956
|
+
5. **Consider timelock** for unpause in high-value contracts
|
|
957
|
+
`,
|
|
958
|
+
};
|
|
959
|
+
/**
|
|
960
|
+
* Get documentation content by URI
|
|
961
|
+
*/
|
|
962
|
+
export async function getDocumentation(uri) {
|
|
963
|
+
// Check embedded docs first
|
|
964
|
+
if (EMBEDDED_DOCS[uri]) {
|
|
965
|
+
return EMBEDDED_DOCS[uri];
|
|
966
|
+
}
|
|
967
|
+
// Try to fetch from GitHub if it's a doc path
|
|
968
|
+
if (uri.startsWith("midnight://docs/")) {
|
|
969
|
+
const docPath = uri.replace("midnight://docs/", "");
|
|
970
|
+
try {
|
|
971
|
+
// Try to fetch from midnight-docs repo
|
|
972
|
+
const file = await githubClient.getFileContent("midnightntwrk", "midnight-docs", `docs/${docPath}.md`);
|
|
973
|
+
if (file) {
|
|
974
|
+
return file.content;
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
catch (error) {
|
|
978
|
+
logger.warn(`Could not fetch doc from GitHub: ${uri}`);
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
return null;
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* List all available documentation resources
|
|
985
|
+
*/
|
|
986
|
+
export function listDocumentationResources() {
|
|
987
|
+
return documentationResources;
|
|
988
|
+
}
|
|
989
|
+
//# sourceMappingURL=docs.js.map
|