@ic-reactor/candid 3.0.14-beta.0 → 3.0.14-beta.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/dist/visitor/arguments/helpers.d.ts +2 -2
- package/dist/visitor/arguments/helpers.d.ts.map +1 -1
- package/dist/visitor/arguments/index.d.ts.map +1 -1
- package/dist/visitor/arguments/index.js +4 -13
- package/dist/visitor/arguments/index.js.map +1 -1
- package/dist/visitor/arguments/types.d.ts +32 -128
- package/dist/visitor/arguments/types.d.ts.map +1 -1
- package/dist/visitor/constants.d.ts.map +1 -1
- package/dist/visitor/constants.js +19 -17
- package/dist/visitor/constants.js.map +1 -1
- package/package.json +2 -2
- package/src/visitor/arguments/helpers.ts +2 -2
- package/src/visitor/arguments/index.test.ts +61 -17
- package/src/visitor/arguments/index.ts +7 -14
- package/src/visitor/arguments/types.ts +113 -214
- package/src/visitor/constants.ts +24 -15
- package/src/visitor/returns/index.test.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ic-reactor/candid",
|
|
3
|
-
"version": "3.0.14-beta.
|
|
3
|
+
"version": "3.0.14-beta.1",
|
|
4
4
|
"description": "IC Reactor Candid Adapter - Fetch and parse Candid definitions from Internet Computer canisters",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@noble/hashes": "^2.0.1",
|
|
46
46
|
"zod": "^4.3.5",
|
|
47
|
-
"@ic-reactor/core": "^3.0.14-beta.
|
|
47
|
+
"@ic-reactor/core": "^3.0.14-beta.1"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"zod": "^4.3.5",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
VisitorDataType,
|
|
3
3
|
CompoundField,
|
|
4
4
|
FieldNode,
|
|
5
5
|
FieldByType,
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
* }
|
|
28
28
|
* ```
|
|
29
29
|
*/
|
|
30
|
-
export function isFieldType<T extends
|
|
30
|
+
export function isFieldType<T extends VisitorDataType>(
|
|
31
31
|
field: FieldNode,
|
|
32
32
|
type: T
|
|
33
33
|
): field is FieldByType<T> {
|
|
@@ -148,8 +148,8 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
148
148
|
expect(field.type).toBe("record")
|
|
149
149
|
expect(field.label).toBe("person")
|
|
150
150
|
expect(field.fields).toHaveLength(2)
|
|
151
|
-
expect(field.
|
|
152
|
-
expect(field.
|
|
151
|
+
expect(field.fields.some((f) => f.label === "name")).toBe(true)
|
|
152
|
+
expect(field.fields.some((f) => f.label === "age")).toBe(true)
|
|
153
153
|
|
|
154
154
|
const nameField = field.fields.find((f) => f.label === "name")
|
|
155
155
|
if (!nameField || nameField.type !== "text") {
|
|
@@ -289,14 +289,14 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
289
289
|
|
|
290
290
|
expect(field.type).toBe("variant")
|
|
291
291
|
expect(field.label).toBe("status")
|
|
292
|
-
expect(field.
|
|
292
|
+
expect(field.fields.map((f) => f.label)).toEqual([
|
|
293
|
+
"Inactive",
|
|
294
|
+
"Active",
|
|
295
|
+
"Pending",
|
|
296
|
+
])
|
|
293
297
|
expect(field.defaultOption).toBe("Inactive")
|
|
294
298
|
expect(field.fields).toHaveLength(3)
|
|
295
|
-
expect(field.
|
|
296
|
-
|
|
297
|
-
field.fields.forEach((f) => {
|
|
298
|
-
expect(f.type).toBe("null")
|
|
299
|
-
})
|
|
299
|
+
expect(field.fields.some((f) => f.label === "Active")).toBe(true)
|
|
300
300
|
|
|
301
301
|
// Test getOptionDefault helper
|
|
302
302
|
expect(field.getOptionDefault("Active")).toEqual({ _type: "Active" })
|
|
@@ -338,7 +338,11 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
338
338
|
)
|
|
339
339
|
|
|
340
340
|
expect(field.type).toBe("variant")
|
|
341
|
-
expect(field.
|
|
341
|
+
expect(field.fields.map((f) => f.label)).toEqual([
|
|
342
|
+
"Approve",
|
|
343
|
+
"Burn",
|
|
344
|
+
"Transfer",
|
|
345
|
+
]) // Sorted order
|
|
342
346
|
|
|
343
347
|
const transferField = field.fields.find(
|
|
344
348
|
(f) => f.label === "Transfer"
|
|
@@ -371,8 +375,8 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
371
375
|
)
|
|
372
376
|
|
|
373
377
|
expect(field.type).toBe("variant")
|
|
374
|
-
expect(field.
|
|
375
|
-
expect(field.
|
|
378
|
+
expect(field.fields.some((f) => f.label === "Ok")).toBe(true)
|
|
379
|
+
expect(field.fields.some((f) => f.label === "Err")).toBe(true)
|
|
376
380
|
|
|
377
381
|
const okField = field.fields.find((f) => f.label === "Ok")
|
|
378
382
|
if (!okField || okField.type !== "text") {
|
|
@@ -567,8 +571,8 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
567
571
|
throw new Error("Extracted field is not variant")
|
|
568
572
|
}
|
|
569
573
|
expect(extracted.type).toBe("variant")
|
|
570
|
-
expect(extracted.
|
|
571
|
-
expect(extracted.
|
|
574
|
+
expect(extracted.fields.some((f) => f.label === "Leaf")).toBe(true)
|
|
575
|
+
expect(extracted.fields.some((f) => f.label === "Node")).toBe(true)
|
|
572
576
|
})
|
|
573
577
|
|
|
574
578
|
it("should handle recursive linked list", () => {
|
|
@@ -602,7 +606,7 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
602
606
|
throw new Error("Extracted field is not variant")
|
|
603
607
|
}
|
|
604
608
|
expect(extracted.type).toBe("variant")
|
|
605
|
-
expect(extracted.
|
|
609
|
+
expect(extracted.fields.map((f) => f.label)).toEqual(["Nil", "Cons"])
|
|
606
610
|
|
|
607
611
|
const consField = extracted.fields.find(
|
|
608
612
|
(f) => f.label === "Cons"
|
|
@@ -919,9 +923,13 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
919
923
|
)
|
|
920
924
|
|
|
921
925
|
expect(field.type).toBe("variant")
|
|
922
|
-
expect(field.
|
|
923
|
-
expect(
|
|
924
|
-
|
|
926
|
+
expect(field.fields.some((f) => f.label === "Motion")).toBe(true)
|
|
927
|
+
expect(
|
|
928
|
+
field.fields.some((f) => f.label === "TransferSnsTreasuryFunds")
|
|
929
|
+
).toBe(true)
|
|
930
|
+
expect(
|
|
931
|
+
field.fields.some((f) => f.label === "UpgradeSnsControlledCanister")
|
|
932
|
+
).toBe(true)
|
|
925
933
|
|
|
926
934
|
// Check Motion variant
|
|
927
935
|
const motionField = field.fields.find(
|
|
@@ -1392,4 +1400,40 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
1392
1400
|
}
|
|
1393
1401
|
})
|
|
1394
1402
|
})
|
|
1403
|
+
|
|
1404
|
+
// ════════════════════════════════════════════════════════════════════════
|
|
1405
|
+
// Format Detection
|
|
1406
|
+
// ════════════════════════════════════════════════════════════════════════
|
|
1407
|
+
|
|
1408
|
+
describe("Format Detection", () => {
|
|
1409
|
+
it("should NOT detect eth format for method_name", () => {
|
|
1410
|
+
const field = visitor.visitText(IDL.Text, "method_name")
|
|
1411
|
+
expect(field.format).toBe("plain")
|
|
1412
|
+
})
|
|
1413
|
+
|
|
1414
|
+
it("should detect eth format for my_eth_address", () => {
|
|
1415
|
+
const field = visitor.visitText(IDL.Text, "my_eth_address")
|
|
1416
|
+
expect(field.format).toBe("eth")
|
|
1417
|
+
})
|
|
1418
|
+
|
|
1419
|
+
it("should detect eth format for myEthAddress", () => {
|
|
1420
|
+
const field = visitor.visitText(IDL.Text, "myEthAddress")
|
|
1421
|
+
expect(field.format).toBe("eth")
|
|
1422
|
+
})
|
|
1423
|
+
|
|
1424
|
+
it("should detect eth format for ethereum", () => {
|
|
1425
|
+
const field = visitor.visitText(IDL.Text, "ethereum")
|
|
1426
|
+
expect(field.format).toBe("eth")
|
|
1427
|
+
})
|
|
1428
|
+
|
|
1429
|
+
it("should detect btc format for bitcoin_address", () => {
|
|
1430
|
+
const field = visitor.visitText(IDL.Text, "bitcoin_address")
|
|
1431
|
+
expect(field.format).toBe("btc")
|
|
1432
|
+
})
|
|
1433
|
+
|
|
1434
|
+
it("should NOT detect btc format for debt", () => {
|
|
1435
|
+
const field = visitor.visitText(IDL.Text, "debt")
|
|
1436
|
+
expect(field.format).toBe("plain")
|
|
1437
|
+
})
|
|
1438
|
+
})
|
|
1395
1439
|
})
|
|
@@ -278,7 +278,6 @@ export class FieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
278
278
|
): RecordField {
|
|
279
279
|
const name = this.currentName()
|
|
280
280
|
const fields: FieldNode[] = []
|
|
281
|
-
const fieldMap = new Map<string, FieldNode>()
|
|
282
281
|
const defaultValue: Record<string, unknown> = {}
|
|
283
282
|
const schemaShape: Record<string, z.ZodTypeAny> = {}
|
|
284
283
|
|
|
@@ -288,7 +287,6 @@ export class FieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
288
287
|
) as FieldNode
|
|
289
288
|
|
|
290
289
|
fields.push(field)
|
|
291
|
-
fieldMap.set(key, field)
|
|
292
290
|
defaultValue[key] = field.defaultValue
|
|
293
291
|
schemaShape[key] = field.schema
|
|
294
292
|
}
|
|
@@ -303,7 +301,6 @@ export class FieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
303
301
|
component: "record-container",
|
|
304
302
|
renderHint: COMPOUND_RENDER_HINT,
|
|
305
303
|
fields,
|
|
306
|
-
fieldMap,
|
|
307
304
|
defaultValue,
|
|
308
305
|
schema,
|
|
309
306
|
candidType: "record",
|
|
@@ -317,8 +314,6 @@ export class FieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
317
314
|
): VariantField {
|
|
318
315
|
const name = this.currentName()
|
|
319
316
|
const fields: FieldNode[] = []
|
|
320
|
-
const options: string[] = []
|
|
321
|
-
const optionMap = new Map<string, FieldNode>()
|
|
322
317
|
const variantSchemas: z.ZodTypeAny[] = []
|
|
323
318
|
|
|
324
319
|
for (const [key, type] of fields_) {
|
|
@@ -327,8 +322,6 @@ export class FieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
327
322
|
) as FieldNode
|
|
328
323
|
|
|
329
324
|
fields.push(field)
|
|
330
|
-
options.push(key)
|
|
331
|
-
optionMap.set(key, field)
|
|
332
325
|
|
|
333
326
|
if (field.type === "null") {
|
|
334
327
|
variantSchemas.push(z.object({ _type: z.literal(key) }))
|
|
@@ -342,8 +335,8 @@ export class FieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
342
335
|
}
|
|
343
336
|
}
|
|
344
337
|
|
|
345
|
-
const defaultOption = options[0]
|
|
346
338
|
const firstField = fields[0]
|
|
339
|
+
const defaultOption = firstField.label
|
|
347
340
|
|
|
348
341
|
const defaultValue =
|
|
349
342
|
firstField.type === "null"
|
|
@@ -353,11 +346,11 @@ export class FieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
353
346
|
[defaultOption]: firstField.defaultValue,
|
|
354
347
|
}
|
|
355
348
|
|
|
356
|
-
const schema = z.union(variantSchemas)
|
|
349
|
+
const schema = z.union(variantSchemas as [z.ZodTypeAny, ...z.ZodTypeAny[]])
|
|
357
350
|
|
|
358
351
|
// Helper to get default value for any option
|
|
359
352
|
const getOptionDefault = (option: string): Record<string, unknown> => {
|
|
360
|
-
const optField =
|
|
353
|
+
const optField = fields.find((f) => f.label === option)
|
|
361
354
|
if (!optField) {
|
|
362
355
|
throw new Error(`Unknown variant option: ${option}`)
|
|
363
356
|
}
|
|
@@ -368,7 +361,7 @@ export class FieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
368
361
|
|
|
369
362
|
// Helper to get field for a specific option
|
|
370
363
|
const getField = (option: string): FieldNode => {
|
|
371
|
-
const optField =
|
|
364
|
+
const optField = fields.find((f) => f.label === option)
|
|
372
365
|
if (!optField) {
|
|
373
366
|
throw new Error(`Unknown variant option: ${option}`)
|
|
374
367
|
}
|
|
@@ -380,7 +373,9 @@ export class FieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
380
373
|
if (value._type && typeof value._type === "string") {
|
|
381
374
|
return value._type
|
|
382
375
|
}
|
|
383
|
-
const validKeys = Object.keys(value).filter((k) =>
|
|
376
|
+
const validKeys = Object.keys(value).filter((k) =>
|
|
377
|
+
fields.some((f) => f.label === k)
|
|
378
|
+
)
|
|
384
379
|
return validKeys[0] ?? defaultOption
|
|
385
380
|
}
|
|
386
381
|
|
|
@@ -398,9 +393,7 @@ export class FieldVisitor<A = BaseActor> extends IDL.Visitor<
|
|
|
398
393
|
component: "variant-select",
|
|
399
394
|
renderHint: COMPOUND_RENDER_HINT,
|
|
400
395
|
fields,
|
|
401
|
-
options,
|
|
402
396
|
defaultOption,
|
|
403
|
-
optionMap,
|
|
404
397
|
defaultValue,
|
|
405
398
|
schema,
|
|
406
399
|
getOptionDefault,
|