midnight-mcp 0.1.14 → 0.1.16
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.
|
@@ -15,9 +15,13 @@ export const EMBEDDED_DOCS = {
|
|
|
15
15
|
|
|
16
16
|
A curated syntax reference for Compact - Midnight's smart contract language.
|
|
17
17
|
|
|
18
|
+
> **Version Note**: This reference is for Compact 0.16+ (current). Some older examples may use deprecated syntax like \`Cell<T>\` wrappers - see "Common Pitfalls" section below.
|
|
19
|
+
|
|
18
20
|
## Basic Structure
|
|
19
21
|
|
|
20
22
|
\`\`\`compact
|
|
23
|
+
pragma language_version >= 0.14.0;
|
|
24
|
+
|
|
21
25
|
include "std";
|
|
22
26
|
|
|
23
27
|
ledger {
|
|
@@ -145,11 +149,124 @@ export circuit revealSecret(): Field {
|
|
|
145
149
|
}
|
|
146
150
|
\`\`\`
|
|
147
151
|
|
|
152
|
+
### Disclosure in Conditionals (IMPORTANT)
|
|
153
|
+
When using witness values in if/else conditions, you MUST explicitly disclose the comparison result:
|
|
154
|
+
|
|
155
|
+
\`\`\`compact
|
|
156
|
+
// ❌ WRONG - compiler error: "potential witness-value disclosure must be declared"
|
|
157
|
+
witness getSecret(): Field { return 42; }
|
|
158
|
+
export circuit checkValue(guess: Field): Boolean {
|
|
159
|
+
const secret = getSecret();
|
|
160
|
+
if (guess == secret) { // ERROR: implicit disclosure
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// ✅ CORRECT - wrap comparison in disclose()
|
|
167
|
+
export circuit checkValue(guess: Field): Boolean {
|
|
168
|
+
const secret = getSecret();
|
|
169
|
+
if (disclose(guess == secret)) { // Explicitly acknowledge disclosure
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// ✅ Multiple comparisons
|
|
176
|
+
export circuit giveHint(guess: Field): Hint {
|
|
177
|
+
const secret = getSecret();
|
|
178
|
+
if (disclose(guess == secret)) {
|
|
179
|
+
return Hint.correct;
|
|
180
|
+
} else if (disclose(guess > secret)) {
|
|
181
|
+
return Hint.too_high;
|
|
182
|
+
} else {
|
|
183
|
+
return Hint.too_low;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
\`\`\`
|
|
187
|
+
|
|
188
|
+
**Why?** When you branch on a comparison involving private (witness) values, the boolean result becomes observable on-chain. Compact requires explicit acknowledgment via \`disclose()\` to prevent accidental privacy leaks.
|
|
189
|
+
|
|
148
190
|
### Assertions
|
|
149
191
|
\`\`\`compact
|
|
150
192
|
assert(condition); // Basic assertion
|
|
151
193
|
assert(condition, "Error message"); // With message
|
|
152
194
|
\`\`\`
|
|
195
|
+
|
|
196
|
+
## Common Pitfalls & Solutions
|
|
197
|
+
|
|
198
|
+
### 1. Cell<T> Wrapper (Deprecated)
|
|
199
|
+
\`\`\`compact
|
|
200
|
+
// ❌ OLD SYNTAX (pre-0.15) - causes "unbound identifier Cell"
|
|
201
|
+
export ledger myValue: Cell<Field>;
|
|
202
|
+
myValue.write(42);
|
|
203
|
+
const x = myValue.read();
|
|
204
|
+
|
|
205
|
+
// ✅ CURRENT SYNTAX (0.16+) - direct declaration
|
|
206
|
+
export ledger myValue: Field;
|
|
207
|
+
myValue = 42;
|
|
208
|
+
const x = myValue;
|
|
209
|
+
\`\`\`
|
|
210
|
+
|
|
211
|
+
### 2. Opaque String Assignment
|
|
212
|
+
\`\`\`compact
|
|
213
|
+
// ❌ WRONG - cannot assign string literals to Opaque
|
|
214
|
+
export ledger message: Opaque<"string">;
|
|
215
|
+
export circuit setMessage(): Void {
|
|
216
|
+
message = "hello"; // ERROR!
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// ✅ CORRECT - use enum for fixed values
|
|
220
|
+
export enum Status { pending, approved, rejected }
|
|
221
|
+
export ledger status: Status;
|
|
222
|
+
export circuit setStatus(): Void {
|
|
223
|
+
status = Status.approved; // Works!
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// ✅ Or receive Opaque from parameter/witness
|
|
227
|
+
export circuit setMessage(msg: Opaque<"string">): Void {
|
|
228
|
+
message = msg; // msg comes from TypeScript
|
|
229
|
+
}
|
|
230
|
+
\`\`\`
|
|
231
|
+
|
|
232
|
+
### 3. Counter vs Field
|
|
233
|
+
\`\`\`compact
|
|
234
|
+
// Counter has special methods
|
|
235
|
+
export ledger count: Counter;
|
|
236
|
+
count.increment(1);
|
|
237
|
+
count.decrement(1);
|
|
238
|
+
const val = count.value();
|
|
239
|
+
|
|
240
|
+
// Field uses direct assignment
|
|
241
|
+
export ledger amount: Field;
|
|
242
|
+
amount = amount + 1;
|
|
243
|
+
const val = amount;
|
|
244
|
+
\`\`\`
|
|
245
|
+
|
|
246
|
+
### 4. Map Initialization
|
|
247
|
+
\`\`\`compact
|
|
248
|
+
// Maps don't need initialization
|
|
249
|
+
export ledger balances: Map<Bytes<32>, Field>;
|
|
250
|
+
|
|
251
|
+
// Access with .member()
|
|
252
|
+
const balance = balances.member(address);
|
|
253
|
+
balances.insert(address, 100);
|
|
254
|
+
\`\`\`
|
|
255
|
+
|
|
256
|
+
### 5. Boolean Returns with Witnesses
|
|
257
|
+
\`\`\`compact
|
|
258
|
+
// ❌ WRONG - returns private boolean without disclosure
|
|
259
|
+
export circuit isOwner(): Boolean {
|
|
260
|
+
const caller = getCaller(); // witness
|
|
261
|
+
return caller == owner; // ERROR: undisclosed
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// ✅ CORRECT - disclose the result
|
|
265
|
+
export circuit isOwner(): Boolean {
|
|
266
|
+
const caller = getCaller();
|
|
267
|
+
return disclose(caller == owner);
|
|
268
|
+
}
|
|
269
|
+
\`\`\`
|
|
153
270
|
`,
|
|
154
271
|
"midnight://docs/sdk-api": `# Midnight TypeScript SDK Quick Reference
|
|
155
272
|
|
|
@@ -157,11 +157,24 @@ export declare function compareSyntax(input: CompareSyntaxInput): Promise<{
|
|
|
157
157
|
* This is the source of truth for writing valid, compilable contracts
|
|
158
158
|
*/
|
|
159
159
|
export declare function getLatestSyntax(input: GetLatestSyntaxInput): Promise<{
|
|
160
|
+
repository: string;
|
|
161
|
+
version: string;
|
|
162
|
+
syntaxReference: string;
|
|
163
|
+
sections: string[];
|
|
164
|
+
pitfalls: string[];
|
|
165
|
+
note: string;
|
|
166
|
+
warning?: undefined;
|
|
167
|
+
syntaxFiles?: undefined;
|
|
168
|
+
examplePaths?: undefined;
|
|
169
|
+
} | {
|
|
160
170
|
repository: string;
|
|
161
171
|
version: string;
|
|
162
172
|
warning: string;
|
|
163
173
|
syntaxFiles: never[];
|
|
164
174
|
examplePaths: string[];
|
|
175
|
+
syntaxReference?: undefined;
|
|
176
|
+
sections?: undefined;
|
|
177
|
+
pitfalls?: undefined;
|
|
165
178
|
note?: undefined;
|
|
166
179
|
} | {
|
|
167
180
|
repository: string;
|
|
@@ -171,6 +184,9 @@ export declare function getLatestSyntax(input: GetLatestSyntaxInput): Promise<{
|
|
|
171
184
|
content: string;
|
|
172
185
|
}[];
|
|
173
186
|
note: string;
|
|
187
|
+
syntaxReference?: undefined;
|
|
188
|
+
sections?: undefined;
|
|
189
|
+
pitfalls?: undefined;
|
|
174
190
|
warning?: undefined;
|
|
175
191
|
examplePaths?: undefined;
|
|
176
192
|
}>;
|
|
@@ -6,6 +6,7 @@ import { githubClient } from "../../pipeline/index.js";
|
|
|
6
6
|
import { releaseTracker } from "../../pipeline/releases.js";
|
|
7
7
|
import { logger, DEFAULT_REPOSITORIES, SelfCorrectionHints, } from "../../utils/index.js";
|
|
8
8
|
import { REPO_ALIASES, EXAMPLES } from "./constants.js";
|
|
9
|
+
import { EMBEDDED_DOCS } from "../../resources/content/docs-content.js";
|
|
9
10
|
/**
|
|
10
11
|
* Resolve repository name alias to owner/repo
|
|
11
12
|
*/
|
|
@@ -301,6 +302,36 @@ export async function getLatestSyntax(input) {
|
|
|
301
302
|
// Ensure repo defaults to compact if undefined/empty
|
|
302
303
|
const repoName = input?.repo || "compact";
|
|
303
304
|
logger.debug("Getting latest syntax reference", { repo: repoName });
|
|
305
|
+
// For Compact language, always return our curated reference first
|
|
306
|
+
// This is more reliable than fetching from GitHub and includes pitfalls/patterns
|
|
307
|
+
if (repoName === "compact" || repoName === "midnight-compact") {
|
|
308
|
+
const compactReference = EMBEDDED_DOCS["midnight://docs/compact-reference"];
|
|
309
|
+
if (compactReference) {
|
|
310
|
+
return {
|
|
311
|
+
repository: "midnightntwrk/compact",
|
|
312
|
+
version: "0.16+ (current)",
|
|
313
|
+
syntaxReference: compactReference,
|
|
314
|
+
sections: [
|
|
315
|
+
"Basic Structure",
|
|
316
|
+
"Data Types",
|
|
317
|
+
"Circuits",
|
|
318
|
+
"Witnesses",
|
|
319
|
+
"State Management",
|
|
320
|
+
"Common Patterns",
|
|
321
|
+
"Disclosure in Conditionals (IMPORTANT)",
|
|
322
|
+
"Common Pitfalls & Solutions",
|
|
323
|
+
],
|
|
324
|
+
pitfalls: [
|
|
325
|
+
"Cell<T> wrapper deprecated in 0.15+ - use direct type",
|
|
326
|
+
'Cannot assign string literals to Opaque<"string"> - use enum or parameters',
|
|
327
|
+
"Must disclose() comparisons used in if/else conditions",
|
|
328
|
+
"Counter uses .increment()/.value(), Field uses direct assignment",
|
|
329
|
+
"Boolean returns from witnesses need disclose()",
|
|
330
|
+
],
|
|
331
|
+
note: "This is the curated syntax reference for Compact 0.16+. Includes common pitfalls and correct patterns.",
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
}
|
|
304
335
|
const resolved = resolveRepo(repoName);
|
|
305
336
|
if (!resolved) {
|
|
306
337
|
throw new Error(`Unknown repository: ${repoName}. Available: ${Object.keys(REPO_ALIASES).join(", ")}`);
|