midnight-mcp 0.1.34 → 0.1.36

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.
@@ -65,4 +65,107 @@ export declare function getVersionInfo(): string;
65
65
  * Check if a version is within supported range
66
66
  */
67
67
  export declare function isVersionSupported(version: string): boolean;
68
+ /**
69
+ * Built-in functions vs patterns you must implement yourself
70
+ * CRITICAL: These are the actual stdlib functions available in Compact
71
+ */
72
+ export declare const BUILTIN_FUNCTIONS: {
73
+ /** Actually built into the language/stdlib */
74
+ stdlib: {
75
+ name: string;
76
+ signature: string;
77
+ description: string;
78
+ }[];
79
+ /** NOT built-in - you must implement these patterns yourself */
80
+ notBuiltIn: {
81
+ name: string;
82
+ wrongUsage: string;
83
+ correctPattern: string;
84
+ description: string;
85
+ }[];
86
+ };
87
+ /**
88
+ * Type compatibility rules - what types can be compared/operated together
89
+ */
90
+ export declare const TYPE_COMPATIBILITY: {
91
+ comparisons: ({
92
+ types: string;
93
+ works: boolean;
94
+ note: string;
95
+ fix?: undefined;
96
+ } | {
97
+ types: string;
98
+ works: boolean;
99
+ fix: string;
100
+ note?: undefined;
101
+ })[];
102
+ arithmetic: ({
103
+ types: string;
104
+ works: boolean;
105
+ note: string;
106
+ fix?: undefined;
107
+ } | {
108
+ types: string;
109
+ works: boolean;
110
+ fix: string;
111
+ note?: undefined;
112
+ })[];
113
+ assignments: {
114
+ types: string;
115
+ works: boolean;
116
+ fix: string;
117
+ }[];
118
+ tips: string[];
119
+ };
120
+ /**
121
+ * Ledger type limitations - what works in circuits vs TypeScript
122
+ */
123
+ export declare const LEDGER_TYPE_LIMITS: {
124
+ Counter: {
125
+ circuitOperations: {
126
+ method: string;
127
+ works: boolean;
128
+ note: string;
129
+ }[];
130
+ typescriptAccess: string;
131
+ reason: string;
132
+ };
133
+ Map: {
134
+ circuitOperations: {
135
+ method: string;
136
+ works: boolean;
137
+ note: string;
138
+ }[];
139
+ typescriptAccess: string;
140
+ reason: string;
141
+ pattern: string;
142
+ };
143
+ Set: {
144
+ circuitOperations: {
145
+ method: string;
146
+ works: boolean;
147
+ note: string;
148
+ }[];
149
+ typescriptAccess: string;
150
+ reason: string;
151
+ };
152
+ MerkleTree: {
153
+ circuitOperations: {
154
+ method: string;
155
+ works: boolean;
156
+ note: string;
157
+ }[];
158
+ typescriptAccess: string;
159
+ pattern: string;
160
+ };
161
+ };
162
+ /**
163
+ * Common compilation errors with their fixes
164
+ * Maps actual compiler error messages to solutions
165
+ */
166
+ export declare const COMMON_ERRORS: {
167
+ error: string;
168
+ cause: string;
169
+ fix: string;
170
+ }[];
68
171
  //# sourceMappingURL=compact-version.d.ts.map
@@ -92,4 +92,271 @@ export function isVersionSupported(version) {
92
92
  const maxNum = maxMajor * 100 + maxMinor;
93
93
  return versionNum >= minNum && versionNum <= maxNum;
94
94
  }
95
+ /**
96
+ * Built-in functions vs patterns you must implement yourself
97
+ * CRITICAL: These are the actual stdlib functions available in Compact
98
+ */
99
+ export const BUILTIN_FUNCTIONS = {
100
+ /** Actually built into the language/stdlib */
101
+ stdlib: [
102
+ {
103
+ name: "persistentHash",
104
+ signature: "persistentHash<T>(value: T): Bytes<32>",
105
+ description: "Poseidon hash that produces consistent results across calls",
106
+ },
107
+ {
108
+ name: "persistentCommit",
109
+ signature: "persistentCommit<T>(value: T): Bytes<32>",
110
+ description: "Creates a hiding commitment to a value",
111
+ },
112
+ {
113
+ name: "pad",
114
+ signature: "pad(length: number, value: string): Bytes<N>",
115
+ description: "Pads a string to fixed-length bytes",
116
+ },
117
+ {
118
+ name: "disclose",
119
+ signature: "disclose(value: T): T",
120
+ description: "Explicitly reveals a witness value (required in conditionals)",
121
+ },
122
+ {
123
+ name: "assert",
124
+ signature: "assert(condition: Boolean, message?: string): []",
125
+ description: "Fails circuit if condition is false",
126
+ },
127
+ {
128
+ name: "default",
129
+ signature: "default<T>(): T",
130
+ description: "Returns default value for a type (0 for numbers, empty for collections)",
131
+ },
132
+ ],
133
+ /** NOT built-in - you must implement these patterns yourself */
134
+ notBuiltIn: [
135
+ {
136
+ name: "public_key",
137
+ wrongUsage: "public_key(sk) // ERROR: unbound identifier",
138
+ correctPattern: `// Derive public key using persistentHash
139
+ const pk = persistentHash<Vector<2, Bytes<32>>>([
140
+ pad(32, "midnight:pk:"),
141
+ sk
142
+ ]);`,
143
+ description: "Public key derivation is NOT a builtin - use persistentHash pattern",
144
+ },
145
+ {
146
+ name: "verify_signature",
147
+ wrongUsage: "verify_signature(msg, sig, pk) // Does not exist",
148
+ correctPattern: `// Signature verification must be done via witnesses
149
+ // The prover verifies off-chain, then provides the boolean result
150
+ witness signature_valid(): Boolean;`,
151
+ description: "Signature verification is done off-chain in the prover",
152
+ },
153
+ {
154
+ name: "random",
155
+ wrongUsage: "random() // Does not exist in ZK circuits",
156
+ correctPattern: `// Randomness must come from witnesses (prover-provided)
157
+ witness get_random_value(): Field;`,
158
+ description: "ZK circuits are deterministic - randomness must come from witnesses",
159
+ },
160
+ ],
161
+ };
162
+ /**
163
+ * Type compatibility rules - what types can be compared/operated together
164
+ */
165
+ export const TYPE_COMPATIBILITY = {
166
+ comparisons: [
167
+ { types: "Field == Field", works: true, note: "Direct comparison" },
168
+ {
169
+ types: "Field == Uint<N>",
170
+ works: false,
171
+ fix: "Cast with `value as Field`",
172
+ },
173
+ {
174
+ types: "Field >= 0",
175
+ works: false,
176
+ fix: "Use bounded Uint<0..N> parameter instead",
177
+ },
178
+ { types: "Uint<N> == Uint<N>", works: true, note: "Same-width comparison" },
179
+ {
180
+ types: "Uint<0..2> == Uint<0..2>",
181
+ works: true,
182
+ note: "Bounded integers",
183
+ },
184
+ { types: "Bytes<32> == Bytes<32>", works: true, note: "Direct comparison" },
185
+ { types: "Boolean == Boolean", works: true, note: "Direct comparison" },
186
+ ],
187
+ arithmetic: [
188
+ { types: "Field + Field", works: true, note: "Field arithmetic" },
189
+ { types: "Field + Uint<N>", works: false, fix: "Cast Uint to Field first" },
190
+ {
191
+ types: "Uint<N> + Uint<N>",
192
+ works: true,
193
+ note: "Must fit in result width",
194
+ },
195
+ ],
196
+ assignments: [
197
+ {
198
+ types: "Field = Uint<N>",
199
+ works: false,
200
+ fix: "Cast with `value as Field`",
201
+ },
202
+ {
203
+ types: "Uint<N> = Field",
204
+ works: false,
205
+ fix: "Use bounded param or explicit cast",
206
+ },
207
+ ],
208
+ tips: [
209
+ "Use Uint<0..N> for circuit parameters that need range validation",
210
+ "Field is unbounded - use for hashes, commitments, general computation",
211
+ "Uint<N> is bounded - use when you need range checks",
212
+ "Casting with `as Field` is safe but loses range information",
213
+ ],
214
+ };
215
+ /**
216
+ * Ledger type limitations - what works in circuits vs TypeScript
217
+ */
218
+ export const LEDGER_TYPE_LIMITS = {
219
+ Counter: {
220
+ circuitOperations: [
221
+ { method: ".increment(n)", works: true, note: "Adds n to counter" },
222
+ {
223
+ method: ".decrement(n)",
224
+ works: true,
225
+ note: "Subtracts n from counter",
226
+ },
227
+ { method: ".resetToDefault()", works: true, note: "Resets to 0" },
228
+ { method: ".value()", works: false, note: "NOT available in circuits" },
229
+ ],
230
+ typescriptAccess: "Access counter value via `ledgerState.counter` in TypeScript SDK",
231
+ reason: "ZK circuits cannot read current ledger state - only modify it",
232
+ },
233
+ Map: {
234
+ circuitOperations: [
235
+ {
236
+ method: ".insert(key, value)",
237
+ works: true,
238
+ note: "Adds/updates entry",
239
+ },
240
+ { method: ".remove(key)", works: true, note: "Removes entry" },
241
+ {
242
+ method: ".lookup(key)",
243
+ works: false,
244
+ note: "NOT available in circuits",
245
+ },
246
+ {
247
+ method: ".member(key)",
248
+ works: false,
249
+ note: "NOT available in circuits",
250
+ },
251
+ ],
252
+ typescriptAccess: "Query map via `contractState.data.get(key)` in TypeScript SDK",
253
+ reason: "ZK circuits prove transitions, not current state. Use witnesses for reads.",
254
+ pattern: `// To read a map value in a circuit, use a witness:
255
+ witness get_stored_value(key: Bytes<32>): Field;
256
+
257
+ export circuit update_if_exists(key: Bytes<32>, new_value: Field): [] {
258
+ const current = get_stored_value(key); // Prover fetches from ledger
259
+ // ... use current value
260
+ data.insert(key, new_value); // Update is allowed
261
+ }`,
262
+ },
263
+ Set: {
264
+ circuitOperations: [
265
+ { method: ".insert(value)", works: true, note: "Adds to set" },
266
+ { method: ".remove(value)", works: true, note: "Removes from set" },
267
+ {
268
+ method: ".member(value)",
269
+ works: false,
270
+ note: "NOT available in circuits",
271
+ },
272
+ ],
273
+ typescriptAccess: "Check membership via `contractState.set.has(value)` in TypeScript SDK",
274
+ reason: "Same as Map - use witnesses for membership checks",
275
+ },
276
+ MerkleTree: {
277
+ circuitOperations: [
278
+ { method: ".insert(leaf)", works: true, note: "Adds leaf to tree" },
279
+ { method: ".root()", works: false, note: "NOT available in circuits" },
280
+ ],
281
+ typescriptAccess: "Get root via `contractState.tree.root` in TypeScript SDK",
282
+ pattern: `// To verify a merkle proof in circuit:
283
+ witness get_merkle_root(): Bytes<32>;
284
+ witness get_merkle_proof(leaf: Bytes<32>): Vector<32, Bytes<32>>;
285
+
286
+ // Verify proof using persistentHash to compute expected root`,
287
+ },
288
+ };
289
+ /**
290
+ * Common compilation errors with their fixes
291
+ * Maps actual compiler error messages to solutions
292
+ */
293
+ export const COMMON_ERRORS = [
294
+ {
295
+ error: 'unbound identifier "public_key"',
296
+ cause: "Trying to use public_key() as if it's a builtin function",
297
+ fix: `Use persistentHash pattern instead:
298
+ const pk = persistentHash<Vector<2, Bytes<32>>>([pad(32, "midnight:pk:"), sk]);`,
299
+ },
300
+ {
301
+ error: "incompatible combination of types Field and Uint",
302
+ cause: "Comparing or operating on Field with Uint without casting",
303
+ fix: `Cast Uint to Field: (myUint as Field)
304
+ Or use bounded Uint<0..N> for parameters that need constraints`,
305
+ },
306
+ {
307
+ error: 'operation "value" undefined for ledger field type Counter',
308
+ cause: "Trying to read Counter.value() inside a circuit",
309
+ fix: `Counter values cannot be read in circuits. Options:
310
+ 1. Use a witness: witness get_counter_value(): Uint<64>;
311
+ 2. Read from TypeScript SDK: ledgerState.counter
312
+ 3. Track the value in a separate Field ledger variable`,
313
+ },
314
+ {
315
+ error: "implicit disclosure of witness value",
316
+ cause: "Using witness value in conditional without disclose()",
317
+ fix: `Wrap witness comparisons in disclose():
318
+ if (disclose(witness_value == expected)) { ... }`,
319
+ },
320
+ {
321
+ error: 'parse error: found "{" looking for an identifier',
322
+ cause: "Using old ledger { } block syntax",
323
+ fix: `Use individual exports instead:
324
+ export ledger field1: Type1;
325
+ export ledger field2: Type2;`,
326
+ },
327
+ {
328
+ error: 'parse error: found "{" looking for ";"',
329
+ cause: "Using Void as return type (doesn't exist)",
330
+ fix: `Use empty tuple [] for no return value:
331
+ export circuit myCircuit(): [] { ... }`,
332
+ },
333
+ {
334
+ error: 'unbound identifier "Cell"',
335
+ cause: "Using deprecated Cell<T> wrapper (removed in 0.15)",
336
+ fix: `Remove Cell wrapper, just use the type directly:
337
+ export ledger myField: Field; // Not Cell<Field>`,
338
+ },
339
+ {
340
+ error: "member access requires struct type",
341
+ cause: "Trying to use .member() or .lookup() on Map/Set in circuit",
342
+ fix: `Map/Set queries are not available in circuits.
343
+ Use a witness to fetch the value from the prover:
344
+ witness lookup_value(key: Bytes<32>): Field;`,
345
+ },
346
+ {
347
+ error: "cannot prove assertion",
348
+ cause: "Assert condition cannot be proven true",
349
+ fix: `Check your logic. Common causes:
350
+ 1. Witness returns unexpected value
351
+ 2. Range check fails (use bounded Uint)
352
+ 3. Logic error in circuit`,
353
+ },
354
+ {
355
+ error: 'parse error: found ":" looking for ")"',
356
+ cause: "Using Rust-style :: for enum variant access",
357
+ fix: `Use dot notation for enum variants:
358
+ WRONG: Choice::rock, GameState::waiting
359
+ CORRECT: Choice.rock, GameState.waiting`,
360
+ },
361
+ ];
95
362
  //# sourceMappingURL=compact-version.js.map
@@ -133,6 +133,16 @@ export enum GameState { waiting, playing, finished }
133
133
  export enum Choice { rock, paper, scissors }
134
134
  \`\`\`
135
135
 
136
+ **Enum Access Syntax** - use DOT notation (not Rust-style ::):
137
+ \`\`\`compact
138
+ // CORRECT - dot notation
139
+ if (choice == Choice.rock) { ... }
140
+ game_state = GameState.waiting;
141
+
142
+ // WRONG - Rust-style double colon
143
+ if (choice == Choice::rock) { ... } // ❌ Parse error: found ":" looking for ")"
144
+ \`\`\`
145
+
136
146
  **Structs**:
137
147
  \`\`\`compact
138
148
  export struct PlayerConfig {
@@ -225,6 +235,7 @@ constructor(initNonce: Bytes<32>) {
225
235
  \`\`\`compact
226
236
  witness local_secret_key(): Bytes<32>;
227
237
 
238
+ // IMPORTANT: public_key() is NOT a builtin - use this pattern
228
239
  circuit get_public_key(sk: Bytes<32>): Bytes<32> {
229
240
  return persistentHash<Vector<2, Bytes<32>>>([pad(32, "myapp:pk:"), sk]);
230
241
  }
@@ -237,32 +248,47 @@ export circuit authenticated_action(): [] {
237
248
  }
238
249
  \`\`\`
239
250
 
240
- ### Commit-Reveal Pattern
251
+ ### Commit-Reveal Pattern (COMPLETE, VALIDATED)
241
252
  \`\`\`compact
253
+ pragma language_version >= 0.16 && <= 0.18;
254
+
255
+ import CompactStandardLibrary;
256
+
257
+ // Ledger state
242
258
  export ledger commitment: Bytes<32>;
243
- export ledger revealed: Boolean;
259
+ export ledger revealed_value: Field;
260
+ export ledger is_revealed: Boolean;
244
261
 
245
- witness get_stored_value(): Field;
246
- witness store_value(v: Field): [];
262
+ // Witnesses for off-chain storage
263
+ witness local_secret_key(): Bytes<32>;
264
+ witness store_secret_value(v: Field): [];
265
+ witness get_secret_value(): Field;
266
+
267
+ // Helper: compute commitment hash
268
+ circuit compute_commitment(value: Field, salt: Bytes<32>): Bytes<32> {
269
+ // Convert Field to Bytes for hashing
270
+ const value_bytes = value as Bytes<32>;
271
+ return persistentHash<Vector<2, Bytes<32>>>([value_bytes, salt]);
272
+ }
247
273
 
274
+ // Commit phase: store hash on-chain, value off-chain
248
275
  export circuit commit(value: Field): [] {
249
- const sk = local_secret_key();
250
- store_value(value);
251
- commitment = disclose(persistentHash<Vector<2, Bytes<32>>>([
252
- value as Bytes<32>,
253
- sk
254
- ]));
276
+ const salt = local_secret_key();
277
+ store_secret_value(value);
278
+ commitment = disclose(compute_commitment(value, salt));
279
+ is_revealed = false;
255
280
  }
256
281
 
282
+ // Reveal phase: verify stored value matches commitment
257
283
  export circuit reveal(): Field {
258
- const sk = local_secret_key();
259
- const value = get_stored_value();
260
- const expected = persistentHash<Vector<2, Bytes<32>>>([
261
- value as Bytes<32>,
262
- sk
263
- ]);
264
- assert(disclose(expected == commitment), "Mismatch");
265
- revealed = true;
284
+ const salt = local_secret_key();
285
+ const value = get_secret_value();
286
+ const expected = compute_commitment(value, salt);
287
+ assert(disclose(expected == commitment), "Value doesn't match commitment");
288
+ assert(disclose(!is_revealed), "Already revealed");
289
+
290
+ revealed_value = disclose(value);
291
+ is_revealed = true;
266
292
  return disclose(value);
267
293
  }
268
294
  \`\`\`
@@ -296,22 +322,39 @@ export circuit check_broken(guess: Field): Boolean {
296
322
 
297
323
  ### Counter Operations
298
324
  \`\`\`compact
325
+ // These work in circuits:
299
326
  counter.increment(1);
300
327
  counter.decrement(1);
301
- const val = counter.value(); // Note: returns as Field
328
+ counter.resetToDefault();
329
+
330
+ // ⚠️ DOES NOT WORK IN CIRCUITS:
331
+ // const val = counter.value(); // ERROR: operation undefined
332
+ // Instead, read counter value in TypeScript SDK: ledgerState.counter
302
333
  \`\`\`
303
334
 
304
335
  ### Map Operations
305
336
  \`\`\`compact
337
+ // These work in circuits:
306
338
  balances.insert(address, 100);
307
- const balance = balances.lookup(address);
308
- const exists = balances.member(address);
339
+ balances.remove(address);
340
+
341
+ // ⚠️ DOES NOT WORK IN CIRCUITS:
342
+ // const balance = balances.lookup(address); // ERROR
343
+ // const exists = balances.member(address); // ERROR
344
+ // Instead, use witnesses to read values:
345
+ witness get_balance(addr: Bytes<32>): Uint<64>;
309
346
  \`\`\`
310
347
 
311
348
  ### Set Operations
312
349
  \`\`\`compact
350
+ // These work in circuits:
313
351
  members.insert(address);
314
- const isMember = members.member(address);
352
+ members.remove(address);
353
+
354
+ // ⚠️ DOES NOT WORK IN CIRCUITS:
355
+ // const isMember = members.member(address); // ERROR
356
+ // Use witness instead:
357
+ witness is_member(addr: Bytes<32>): Boolean;
315
358
  \`\`\`
316
359
 
317
360
  ### Maybe Operations
@@ -326,9 +369,9 @@ if (opt.is_some) {
326
369
 
327
370
  ### Type Casting
328
371
  \`\`\`compact
329
- const f: Field = counter.value(); // Counter to Field
330
- const bytes: Bytes<32> = f as Bytes<32>; // Field to Bytes
331
- const num: Uint<64> = f as Uint<64>; // Field to Uint
372
+ const bytes: Bytes<32> = myField as Bytes<32>; // Field to Bytes
373
+ const num: Uint<64> = myField as Uint<64>; // Field to Uint (bounds not checked!)
374
+ const field: Field = myUint as Field; // Uint to Field (safe)
332
375
  \`\`\`
333
376
 
334
377
  ### Hashing
@@ -336,8 +379,8 @@ const num: Uint<64> = f as Uint<64>; // Field to Uint
336
379
  // Persistent hash (same input = same output across calls)
337
380
  const hash = persistentHash<Vector<2, Bytes<32>>>([data1, data2]);
338
381
 
339
- // Transient hash (includes randomness)
340
- const commit = transientCommit<Field>(value, randomness);
382
+ // Persistent commit (hiding commitment)
383
+ const commit = persistentCommit<Field>(value);
341
384
  \`\`\`
342
385
 
343
386
  ---
@@ -159,6 +159,93 @@ export declare function compareSyntax(input: CompareSyntaxInput): Promise<{
159
159
  */
160
160
  export declare function getLatestSyntax(input: GetLatestSyntaxInput): Promise<{
161
161
  quickStartTemplate: string;
162
+ builtinFunctions: {
163
+ stdlib: {
164
+ name: string;
165
+ signature: string;
166
+ description: string;
167
+ }[];
168
+ notBuiltIn: {
169
+ name: string;
170
+ wrongUsage: string;
171
+ correctPattern: string;
172
+ description: string;
173
+ }[];
174
+ };
175
+ typeCompatibility: {
176
+ comparisons: ({
177
+ types: string;
178
+ works: boolean;
179
+ note: string;
180
+ fix?: undefined;
181
+ } | {
182
+ types: string;
183
+ works: boolean;
184
+ fix: string;
185
+ note?: undefined;
186
+ })[];
187
+ arithmetic: ({
188
+ types: string;
189
+ works: boolean;
190
+ note: string;
191
+ fix?: undefined;
192
+ } | {
193
+ types: string;
194
+ works: boolean;
195
+ fix: string;
196
+ note?: undefined;
197
+ })[];
198
+ assignments: {
199
+ types: string;
200
+ works: boolean;
201
+ fix: string;
202
+ }[];
203
+ tips: string[];
204
+ };
205
+ ledgerTypeLimits: {
206
+ Counter: {
207
+ circuitOperations: {
208
+ method: string;
209
+ works: boolean;
210
+ note: string;
211
+ }[];
212
+ typescriptAccess: string;
213
+ reason: string;
214
+ };
215
+ Map: {
216
+ circuitOperations: {
217
+ method: string;
218
+ works: boolean;
219
+ note: string;
220
+ }[];
221
+ typescriptAccess: string;
222
+ reason: string;
223
+ pattern: string;
224
+ };
225
+ Set: {
226
+ circuitOperations: {
227
+ method: string;
228
+ works: boolean;
229
+ note: string;
230
+ }[];
231
+ typescriptAccess: string;
232
+ reason: string;
233
+ };
234
+ MerkleTree: {
235
+ circuitOperations: {
236
+ method: string;
237
+ works: boolean;
238
+ note: string;
239
+ }[];
240
+ typescriptAccess: string;
241
+ pattern: string;
242
+ };
243
+ };
244
+ commonErrors: {
245
+ error: string;
246
+ cause: string;
247
+ fix: string;
248
+ }[];
162
249
  commonMistakes: {
163
250
  wrong: string;
164
251
  correct: string;
@@ -8,7 +8,7 @@ import { logger, DEFAULT_REPOSITORIES, SelfCorrectionHints, } from "../../utils/
8
8
  import { sendProgressNotification } from "../../server.js";
9
9
  import { REPO_ALIASES, EXAMPLES } from "./constants.js";
10
10
  import { EMBEDDED_DOCS } from "../../resources/content/docs-content.js";
11
- import { COMPACT_VERSION, RECOMMENDED_PRAGMA, REFERENCE_CONTRACTS, } from "../../config/compact-version.js";
11
+ import { COMPACT_VERSION, RECOMMENDED_PRAGMA, REFERENCE_CONTRACTS, BUILTIN_FUNCTIONS, TYPE_COMPATIBILITY, LEDGER_TYPE_LIMITS, COMMON_ERRORS, } from "../../config/compact-version.js";
12
12
  // Re-export validation handlers from validation.ts
13
13
  export { extractContractStructure } from "./validation.js";
14
14
  /**
@@ -356,6 +356,14 @@ witness local_secret_key(): Bytes<32>;
356
356
  export circuit increment(): [] {
357
357
  counter.increment(1);
358
358
  }`,
359
+ // Built-in functions vs patterns (CRITICAL knowledge)
360
+ builtinFunctions: BUILTIN_FUNCTIONS,
361
+ // Type compatibility rules
362
+ typeCompatibility: TYPE_COMPATIBILITY,
363
+ // Ledger type limitations in circuits
364
+ ledgerTypeLimits: LEDGER_TYPE_LIMITS,
365
+ // Common compilation errors with fixes
366
+ commonErrors: COMMON_ERRORS,
359
367
  // Common mistakes that cause compilation failures
360
368
  commonMistakes: [
361
369
  {
@@ -388,6 +396,26 @@ export circuit increment(): [] {
388
396
  correct: "Field",
389
397
  error: "unbound identifier Cell (deprecated)",
390
398
  },
399
+ {
400
+ wrong: "public_key(sk)",
401
+ correct: 'persistentHash<Vector<2, Bytes<32>>>([pad(32, "midnight:pk:"), sk])',
402
+ error: 'unbound identifier "public_key"',
403
+ },
404
+ {
405
+ wrong: "counter.value()",
406
+ correct: "// Read via witness or TypeScript SDK",
407
+ error: 'operation "value" undefined for Counter',
408
+ },
409
+ {
410
+ wrong: "data.lookup(key)",
411
+ correct: "// Use witness: witness get_value(key): Type;",
412
+ error: "member access requires struct type",
413
+ },
414
+ {
415
+ wrong: "Choice::rock (Rust-style)",
416
+ correct: "Choice.rock (dot notation)",
417
+ error: 'parse error: found ":" looking for ")"',
418
+ },
391
419
  ],
392
420
  syntaxReference: compactReference,
393
421
  sections: [
@@ -396,6 +424,9 @@ export circuit increment(): [] {
396
424
  "Imports",
397
425
  "Ledger Declarations",
398
426
  "Data Types",
427
+ "Built-in Functions",
428
+ "Type Compatibility",
429
+ "Ledger Type Limits",
399
430
  "Circuits",
400
431
  "Witnesses",
401
432
  "Constructor",
@@ -403,6 +434,7 @@ export circuit increment(): [] {
403
434
  "Common Operations",
404
435
  "Assertions",
405
436
  "Common Mistakes to Avoid",
437
+ "Common Errors & Fixes",
406
438
  "Exports for TypeScript",
407
439
  "Reference Contracts",
408
440
  ],
@@ -411,7 +443,13 @@ export circuit increment(): [] {
411
443
  repo: rc.repo,
412
444
  description: rc.description,
413
445
  })),
414
- note: `CRITICAL: Use quickStartTemplate as your base. Check commonMistakes before submitting code. This reference is for Compact ${COMPACT_VERSION.min}-${COMPACT_VERSION.max} (last updated: ${COMPACT_VERSION.lastUpdated}).`,
446
+ note: `CRITICAL: Use quickStartTemplate as your base. Check commonMistakes and commonErrors before submitting code.
447
+ KEY GOTCHAS:
448
+ 1. public_key() is NOT a builtin - use persistentHash pattern
449
+ 2. Counter.value() NOT available in circuits - use witnesses
450
+ 3. Map.lookup()/Set.member() NOT available in circuits - use witnesses
451
+ 4. Field vs Uint comparison requires casting
452
+ This reference is for Compact ${COMPACT_VERSION.min}-${COMPACT_VERSION.max} (last updated: ${COMPACT_VERSION.lastUpdated}).`,
415
453
  };
416
454
  }
417
455
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "midnight-mcp",
3
- "version": "0.1.34",
3
+ "version": "0.1.36",
4
4
  "description": "Model Context Protocol Server for Midnight Blockchain Development",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",