@ic-reactor/candid 3.0.13-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/README.md +28 -0
- package/dist/visitor/arguments/helpers.d.ts +5 -5
- package/dist/visitor/arguments/helpers.d.ts.map +1 -1
- package/dist/visitor/arguments/helpers.js.map +1 -1
- package/dist/visitor/arguments/index.d.ts +12 -2
- package/dist/visitor/arguments/index.d.ts.map +1 -1
- package/dist/visitor/arguments/index.js +140 -25
- package/dist/visitor/arguments/index.js.map +1 -1
- package/dist/visitor/arguments/types.d.ts +76 -419
- 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/dist/visitor/returns/types.d.ts +3 -4
- package/dist/visitor/returns/types.d.ts.map +1 -1
- package/dist/visitor/types.d.ts +14 -0
- package/dist/visitor/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/visitor/arguments/helpers.ts +7 -7
- package/src/visitor/arguments/index.test.ts +104 -39
- package/src/visitor/arguments/index.ts +170 -42
- package/src/visitor/arguments/schema.test.ts +114 -4
- package/src/visitor/arguments/types.ts +113 -480
- package/src/visitor/constants.ts +24 -15
- package/src/visitor/returns/index.test.ts +1 -1
- package/src/visitor/returns/types.ts +4 -27
- package/src/visitor/types.ts +45 -0
|
@@ -18,34 +18,36 @@ const TAMESTAMP_KEYS = [
|
|
|
18
18
|
const TAMESTAMP_KEYS_REGEX = new RegExp(TAMESTAMP_KEYS.map((key) => `^[\\w-]*${key}[\\w-]*$`).join("|"), "i");
|
|
19
19
|
const CYCLE_KEYS = ["cycle", "cycles"];
|
|
20
20
|
const CYCLE_KEYS_REGEX = new RegExp(CYCLE_KEYS.map((key) => `^[\\w-]*${key}[\\w-]*$`).join("|"), "i");
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
21
|
+
const ACCOUNT_ID_KEYS_REGEX = /account_identifier|ledger_account|block_hash|transaction_hash|tx_hash/i;
|
|
22
|
+
const tokenize = (label) => {
|
|
23
|
+
const parts = label
|
|
24
|
+
.replace(/_/g, " ")
|
|
25
|
+
.replace(/([a-z])([A-Z])/g, "$1 $2")
|
|
26
|
+
.toLowerCase()
|
|
27
|
+
.split(/[\s-]+/);
|
|
28
|
+
return new Set(parts);
|
|
29
|
+
};
|
|
29
30
|
export const checkTextFormat = (label) => {
|
|
30
31
|
if (!label)
|
|
31
32
|
return "plain";
|
|
32
33
|
if (TAMESTAMP_KEYS_REGEX.test(label))
|
|
33
34
|
return "timestamp";
|
|
34
|
-
if (
|
|
35
|
+
if (ACCOUNT_ID_KEYS_REGEX.test(label))
|
|
36
|
+
return "account-id";
|
|
37
|
+
const tokens = tokenize(label);
|
|
38
|
+
if (tokens.has("email") || tokens.has("mail"))
|
|
35
39
|
return "email";
|
|
36
|
-
if (
|
|
40
|
+
if (tokens.has("phone") || tokens.has("tel") || tokens.has("mobile"))
|
|
37
41
|
return "phone";
|
|
38
|
-
if (
|
|
42
|
+
if (tokens.has("url") || tokens.has("link") || tokens.has("website"))
|
|
39
43
|
return "url";
|
|
40
|
-
if (
|
|
44
|
+
if (tokens.has("uuid") || tokens.has("guid"))
|
|
41
45
|
return "uuid";
|
|
42
|
-
if (
|
|
46
|
+
if (tokens.has("btc") || tokens.has("bitcoin"))
|
|
43
47
|
return "btc";
|
|
44
|
-
if (
|
|
48
|
+
if (tokens.has("eth") || tokens.has("ethereum"))
|
|
45
49
|
return "eth";
|
|
46
|
-
if (
|
|
47
|
-
return "account-id";
|
|
48
|
-
if (PRINCIPAL_KEYS_REGEX.test(label))
|
|
50
|
+
if (tokens.has("principal") || tokens.has("canister"))
|
|
49
51
|
return "principal";
|
|
50
52
|
return "plain";
|
|
51
53
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/visitor/constants.ts"],"names":[],"mappings":"AAEA,MAAM,cAAc,GAAG;IACrB,MAAM;IACN,MAAM;IACN,UAAU;IACV,WAAW;IACX,iBAAiB;IACjB,UAAU;IACV,WAAW;IACX,WAAW;IACX,WAAW;IACX,YAAY;IACZ,WAAW;IACX,YAAY;IACZ,YAAY;IACZ,YAAY;IACZ,aAAa;CACd,CAAA;AAED,MAAM,oBAAoB,GAAG,IAAI,MAAM,CACrC,cAAc,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,WAAW,GAAG,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAC/D,GAAG,CACJ,CAAA;AAED,MAAM,UAAU,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;AAEtC,MAAM,gBAAgB,GAAG,IAAI,MAAM,CACjC,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,WAAW,GAAG,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAC3D,GAAG,CACJ,CAAA;AAED,MAAM,
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/visitor/constants.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { BaseActor, FunctionName, FunctionType, ActorMethodReturnType } from "@ic-reactor/core";
|
|
2
|
-
|
|
2
|
+
import type { VisitorDataType, TextFormat, NumberFormat } from "../types";
|
|
3
|
+
export type { TextFormat, NumberFormat };
|
|
4
|
+
export type NodeType = VisitorDataType;
|
|
3
5
|
export type DisplayType = "string" | "number" | "boolean" | "null" | "object" | "array" | "variant" | "result" | "nullable" | "recursive" | "blob" | "unknown";
|
|
4
|
-
export type NumberFormat = "timestamp" | "cycle" | "value" | "token" | "normal";
|
|
5
|
-
export type TextFormat = "plain" | "timestamp" | "uuid" | "url" | "email" | "phone" | "btc" | "eth" | "account-id" | "principal";
|
|
6
6
|
/**
|
|
7
7
|
* Base properties shared by all result nodes.
|
|
8
8
|
*/
|
|
@@ -99,5 +99,4 @@ export interface ResolvedMethodResult<A = BaseActor> {
|
|
|
99
99
|
export type ServiceMeta<A = BaseActor> = {
|
|
100
100
|
[K in FunctionName<A>]: MethodMeta<A, K>;
|
|
101
101
|
};
|
|
102
|
-
export {};
|
|
103
102
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/visitor/returns/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,qBAAqB,EACtB,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/visitor/returns/types.ts"],"names":[],"mappings":"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"}
|
package/dist/visitor/types.d.ts
CHANGED
|
@@ -2,4 +2,18 @@ export type FieldType = "functionRecord" | "function" | "record" | "variant" | "
|
|
|
2
2
|
export type { Principal } from "@icp-sdk/core/principal";
|
|
3
3
|
import type { IDL } from "@icp-sdk/core/candid";
|
|
4
4
|
export type AllNumberTypes = IDL.NatClass | IDL.IntClass | IDL.FixedNatClass | IDL.FixedIntClass | IDL.FloatClass;
|
|
5
|
+
/**
|
|
6
|
+
* The core Candid type category used across visitors.
|
|
7
|
+
*/
|
|
8
|
+
export type VisitorDataType = "record" | "variant" | "tuple" | "optional" | "vector" | "blob" | "recursive" | "principal" | "number" | "text" | "boolean" | "null" | "unknown";
|
|
9
|
+
/**
|
|
10
|
+
* Detected format for text fields based on label heuristics.
|
|
11
|
+
* Used to provide format-specific validation and display.
|
|
12
|
+
*/
|
|
13
|
+
export type TextFormat = "plain" | "timestamp" | "uuid" | "url" | "email" | "phone" | "btc" | "eth" | "account-id" | "principal" | "cycle";
|
|
14
|
+
/**
|
|
15
|
+
* Detected format for number fields based on label heuristics.
|
|
16
|
+
* Used to provide format-specific validation and display.
|
|
17
|
+
*/
|
|
18
|
+
export type NumberFormat = "timestamp" | "cycle" | "value" | "token" | "normal";
|
|
5
19
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/visitor/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GACjB,gBAAgB,GAChB,UAAU,GACV,QAAQ,GACR,SAAS,GACT,OAAO,GACP,UAAU,GACV,QAAQ,GACR,OAAO,GACP,MAAM,GACN,YAAY,GACZ,WAAW,GACX,SAAS,GACT,MAAM,GACN,QAAQ,GACR,WAAW,GACX,SAAS,GACT,MAAM,CAAA;AAEV,YAAY,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAExD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAC/C,MAAM,MAAM,cAAc,GACtB,GAAG,CAAC,QAAQ,GACZ,GAAG,CAAC,QAAQ,GACZ,GAAG,CAAC,aAAa,GACjB,GAAG,CAAC,aAAa,GACjB,GAAG,CAAC,UAAU,CAAA"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/visitor/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GACjB,gBAAgB,GAChB,UAAU,GACV,QAAQ,GACR,SAAS,GACT,OAAO,GACP,UAAU,GACV,QAAQ,GACR,OAAO,GACP,MAAM,GACN,YAAY,GACZ,WAAW,GACX,SAAS,GACT,MAAM,GACN,QAAQ,GACR,WAAW,GACX,SAAS,GACT,MAAM,CAAA;AAEV,YAAY,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAExD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAC/C,MAAM,MAAM,cAAc,GACtB,GAAG,CAAC,QAAQ,GACZ,GAAG,CAAC,QAAQ,GACZ,GAAG,CAAC,aAAa,GACjB,GAAG,CAAC,aAAa,GACjB,GAAG,CAAC,UAAU,CAAA;AAMlB;;GAEG;AACH,MAAM,MAAM,eAAe,GACvB,QAAQ,GACR,SAAS,GACT,OAAO,GACP,UAAU,GACV,QAAQ,GACR,MAAM,GACN,WAAW,GACX,WAAW,GACX,QAAQ,GACR,MAAM,GACN,SAAS,GACT,MAAM,GACN,SAAS,CAAA;AAEb;;;GAGG;AACH,MAAM,MAAM,UAAU,GAClB,OAAO,GACP,WAAW,GACX,MAAM,GACN,KAAK,GACL,OAAO,GACP,OAAO,GACP,KAAK,GACL,KAAK,GACL,YAAY,GACZ,WAAW,GACX,OAAO,CAAA;AAEX;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ic-reactor/candid",
|
|
3
|
-
"version": "3.0.
|
|
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.
|
|
47
|
+
"@ic-reactor/core": "^3.0.14-beta.1"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"zod": "^4.3.5",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
VisitorDataType,
|
|
3
3
|
CompoundField,
|
|
4
|
-
|
|
4
|
+
FieldNode,
|
|
5
5
|
FieldByType,
|
|
6
6
|
PrimitiveField,
|
|
7
7
|
RecordField,
|
|
@@ -27,15 +27,15 @@ import {
|
|
|
27
27
|
* }
|
|
28
28
|
* ```
|
|
29
29
|
*/
|
|
30
|
-
export function isFieldType<T extends
|
|
31
|
-
field:
|
|
30
|
+
export function isFieldType<T extends VisitorDataType>(
|
|
31
|
+
field: FieldNode,
|
|
32
32
|
type: T
|
|
33
33
|
): field is FieldByType<T> {
|
|
34
34
|
return field.type === type
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
/** Check if a field is a compound type (contains other fields) */
|
|
38
|
-
export function isCompoundField(field:
|
|
38
|
+
export function isCompoundField(field: FieldNode): field is CompoundField {
|
|
39
39
|
return [
|
|
40
40
|
"record",
|
|
41
41
|
"variant",
|
|
@@ -47,13 +47,13 @@ export function isCompoundField(field: Field): field is CompoundField {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
/** Check if a field is a primitive type */
|
|
50
|
-
export function isPrimitiveField(field:
|
|
50
|
+
export function isPrimitiveField(field: FieldNode): field is PrimitiveField {
|
|
51
51
|
return ["principal", "number", "text", "boolean", "null"].includes(field.type)
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
/** Check if a field has children (for iteration) */
|
|
55
55
|
export function hasChildFields(
|
|
56
|
-
field:
|
|
56
|
+
field: FieldNode
|
|
57
57
|
): field is RecordField | VariantField | TupleField {
|
|
58
58
|
return "fields" in field && Array.isArray((field as RecordField).fields)
|
|
59
59
|
}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest"
|
|
2
2
|
import { IDL } from "@icp-sdk/core/candid"
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
FieldVisitor,
|
|
5
|
+
OptionalField,
|
|
6
|
+
RecordField,
|
|
7
|
+
VariantField,
|
|
8
|
+
VectorField,
|
|
9
|
+
} from "./index"
|
|
4
10
|
|
|
5
11
|
describe("ArgumentFieldVisitor", () => {
|
|
6
12
|
const visitor = new FieldVisitor()
|
|
@@ -142,8 +148,8 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
142
148
|
expect(field.type).toBe("record")
|
|
143
149
|
expect(field.label).toBe("person")
|
|
144
150
|
expect(field.fields).toHaveLength(2)
|
|
145
|
-
expect(field.
|
|
146
|
-
expect(field.
|
|
151
|
+
expect(field.fields.some((f) => f.label === "name")).toBe(true)
|
|
152
|
+
expect(field.fields.some((f) => f.label === "age")).toBe(true)
|
|
147
153
|
|
|
148
154
|
const nameField = field.fields.find((f) => f.label === "name")
|
|
149
155
|
if (!nameField || nameField.type !== "text") {
|
|
@@ -186,7 +192,9 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
186
192
|
expect(field.type).toBe("record")
|
|
187
193
|
expect(field.fields).toHaveLength(2)
|
|
188
194
|
|
|
189
|
-
const addressField = field.fields.find(
|
|
195
|
+
const addressField = field.fields.find(
|
|
196
|
+
(f) => f.label === "address"
|
|
197
|
+
) as RecordField
|
|
190
198
|
if (!addressField || addressField.type !== "record") {
|
|
191
199
|
throw new Error("Address field not found or not record")
|
|
192
200
|
}
|
|
@@ -235,7 +243,7 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
235
243
|
expect(field.fields).toHaveLength(5)
|
|
236
244
|
|
|
237
245
|
// Check 'to' field
|
|
238
|
-
const toField = field.fields.find((f) => f.label === "to")
|
|
246
|
+
const toField = field.fields.find((f) => f.label === "to") as RecordField
|
|
239
247
|
if (!toField || toField.type !== "record") {
|
|
240
248
|
throw new Error("To field not found or not record")
|
|
241
249
|
}
|
|
@@ -251,7 +259,9 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
251
259
|
expect(amountField.candidType).toBe("nat")
|
|
252
260
|
|
|
253
261
|
// Check optional 'fee' field
|
|
254
|
-
const feeField = field.fields.find(
|
|
262
|
+
const feeField = field.fields.find(
|
|
263
|
+
(f) => f.label === "fee"
|
|
264
|
+
) as OptionalField
|
|
255
265
|
if (!feeField || feeField.type !== "optional") {
|
|
256
266
|
throw new Error("Fee field not found or not optional")
|
|
257
267
|
}
|
|
@@ -279,18 +289,18 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
279
289
|
|
|
280
290
|
expect(field.type).toBe("variant")
|
|
281
291
|
expect(field.label).toBe("status")
|
|
282
|
-
expect(field.
|
|
292
|
+
expect(field.fields.map((f) => f.label)).toEqual([
|
|
293
|
+
"Inactive",
|
|
294
|
+
"Active",
|
|
295
|
+
"Pending",
|
|
296
|
+
])
|
|
283
297
|
expect(field.defaultOption).toBe("Inactive")
|
|
284
298
|
expect(field.fields).toHaveLength(3)
|
|
285
|
-
expect(field.
|
|
286
|
-
|
|
287
|
-
field.fields.forEach((f) => {
|
|
288
|
-
expect(f.type).toBe("null")
|
|
289
|
-
})
|
|
299
|
+
expect(field.fields.some((f) => f.label === "Active")).toBe(true)
|
|
290
300
|
|
|
291
301
|
// Test getOptionDefault helper
|
|
292
|
-
expect(field.getOptionDefault("Active")).toEqual({
|
|
293
|
-
expect(field.getOptionDefault("Pending")).toEqual({
|
|
302
|
+
expect(field.getOptionDefault("Active")).toEqual({ _type: "Active" })
|
|
303
|
+
expect(field.getOptionDefault("Pending")).toEqual({ _type: "Pending" })
|
|
294
304
|
})
|
|
295
305
|
|
|
296
306
|
it("should handle variant with payloads", () => {
|
|
@@ -328,9 +338,15 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
328
338
|
)
|
|
329
339
|
|
|
330
340
|
expect(field.type).toBe("variant")
|
|
331
|
-
expect(field.
|
|
341
|
+
expect(field.fields.map((f) => f.label)).toEqual([
|
|
342
|
+
"Approve",
|
|
343
|
+
"Burn",
|
|
344
|
+
"Transfer",
|
|
345
|
+
]) // Sorted order
|
|
332
346
|
|
|
333
|
-
const transferField = field.fields.find(
|
|
347
|
+
const transferField = field.fields.find(
|
|
348
|
+
(f) => f.label === "Transfer"
|
|
349
|
+
) as RecordField
|
|
334
350
|
if (!transferField || transferField.type !== "record") {
|
|
335
351
|
throw new Error("Transfer field not found or not record")
|
|
336
352
|
}
|
|
@@ -359,8 +375,8 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
359
375
|
)
|
|
360
376
|
|
|
361
377
|
expect(field.type).toBe("variant")
|
|
362
|
-
expect(field.
|
|
363
|
-
expect(field.
|
|
378
|
+
expect(field.fields.some((f) => f.label === "Ok")).toBe(true)
|
|
379
|
+
expect(field.fields.some((f) => f.label === "Err")).toBe(true)
|
|
364
380
|
|
|
365
381
|
const okField = field.fields.find((f) => f.label === "Ok")
|
|
366
382
|
if (!okField || okField.type !== "text") {
|
|
@@ -429,7 +445,7 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
429
445
|
expect(field.type).toBe("optional")
|
|
430
446
|
expect(field.innerField.type).toBe("record")
|
|
431
447
|
expect(field.innerField.type).toBe("record")
|
|
432
|
-
const inner = field.innerField
|
|
448
|
+
const inner = field.innerField as RecordField
|
|
433
449
|
if (inner.type === "record") {
|
|
434
450
|
expect(inner.fields).toHaveLength(2)
|
|
435
451
|
} else {
|
|
@@ -448,7 +464,7 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
448
464
|
expect(field.type).toBe("optional")
|
|
449
465
|
expect(field.innerField.type).toBe("optional")
|
|
450
466
|
expect(field.innerField.type).toBe("optional")
|
|
451
|
-
const inner = field.innerField
|
|
467
|
+
const inner = field.innerField as OptionalField
|
|
452
468
|
if (inner.type === "optional") {
|
|
453
469
|
expect(inner.innerField.type).toBe("text")
|
|
454
470
|
} else {
|
|
@@ -479,7 +495,7 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
479
495
|
|
|
480
496
|
expect(field.type).toBe("vector")
|
|
481
497
|
expect(field.itemField.type).toBe("record")
|
|
482
|
-
const item = field.itemField
|
|
498
|
+
const item = field.itemField as RecordField
|
|
483
499
|
if (item.type === "record") {
|
|
484
500
|
expect(item.fields).toHaveLength(2)
|
|
485
501
|
} else {
|
|
@@ -509,7 +525,7 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
509
525
|
|
|
510
526
|
expect(field.type).toBe("vector")
|
|
511
527
|
expect(field.itemField.type).toBe("vector")
|
|
512
|
-
const item = field.itemField
|
|
528
|
+
const item = field.itemField as VectorField
|
|
513
529
|
if (item.type === "vector") {
|
|
514
530
|
expect(item.itemField.type).toBe("text")
|
|
515
531
|
} else {
|
|
@@ -550,13 +566,13 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
550
566
|
expect(typeof field.getInnerDefault).toBe("function")
|
|
551
567
|
|
|
552
568
|
// Extract should return a variant
|
|
553
|
-
const extracted = field.extract()
|
|
569
|
+
const extracted = field.extract() as VariantField
|
|
554
570
|
if (extracted.type !== "variant") {
|
|
555
571
|
throw new Error("Extracted field is not variant")
|
|
556
572
|
}
|
|
557
573
|
expect(extracted.type).toBe("variant")
|
|
558
|
-
expect(extracted.
|
|
559
|
-
expect(extracted.
|
|
574
|
+
expect(extracted.fields.some((f) => f.label === "Leaf")).toBe(true)
|
|
575
|
+
expect(extracted.fields.some((f) => f.label === "Node")).toBe(true)
|
|
560
576
|
})
|
|
561
577
|
|
|
562
578
|
it("should handle recursive linked list", () => {
|
|
@@ -585,14 +601,16 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
585
601
|
|
|
586
602
|
expect(field.type).toBe("recursive")
|
|
587
603
|
|
|
588
|
-
const extracted = field.extract()
|
|
604
|
+
const extracted = field.extract() as VariantField
|
|
589
605
|
if (extracted.type !== "variant") {
|
|
590
606
|
throw new Error("Extracted field is not variant")
|
|
591
607
|
}
|
|
592
608
|
expect(extracted.type).toBe("variant")
|
|
593
|
-
expect(extracted.
|
|
609
|
+
expect(extracted.fields.map((f) => f.label)).toEqual(["Nil", "Cons"])
|
|
594
610
|
|
|
595
|
-
const consField = extracted.fields.find(
|
|
611
|
+
const consField = extracted.fields.find(
|
|
612
|
+
(f) => f.label === "Cons"
|
|
613
|
+
) as RecordField
|
|
596
614
|
if (!consField || consField.type !== "record") {
|
|
597
615
|
throw new Error("Cons field not found or not record")
|
|
598
616
|
}
|
|
@@ -642,7 +660,7 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
642
660
|
expect(meta.fields).toHaveLength(1)
|
|
643
661
|
expect(meta.fields[0].type).toBe("record")
|
|
644
662
|
|
|
645
|
-
const recordField = meta.fields[0]
|
|
663
|
+
const recordField = meta.fields[0] as RecordField
|
|
646
664
|
if (recordField.type !== "record") {
|
|
647
665
|
throw new Error("Expected record field")
|
|
648
666
|
}
|
|
@@ -754,13 +772,15 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
754
772
|
)
|
|
755
773
|
const meta = visitor.visitFunc(funcType, "updateUser")
|
|
756
774
|
|
|
757
|
-
const argRecord = meta.fields[0]
|
|
775
|
+
const argRecord = meta.fields[0] as RecordField
|
|
758
776
|
if (argRecord.type !== "record") {
|
|
759
777
|
throw new Error("Expected record field")
|
|
760
778
|
}
|
|
761
779
|
expect(argRecord.name).toBe("[0]")
|
|
762
780
|
|
|
763
|
-
const userRecord = argRecord.fields.find(
|
|
781
|
+
const userRecord = argRecord.fields.find(
|
|
782
|
+
(f) => f.label === "user"
|
|
783
|
+
) as RecordField
|
|
764
784
|
if (!userRecord || userRecord.type !== "record") {
|
|
765
785
|
throw new Error("User record not found or not record")
|
|
766
786
|
}
|
|
@@ -783,7 +803,7 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
783
803
|
const funcType = IDL.Func([IDL.Vec(IDL.Text)], [], [])
|
|
784
804
|
const meta = visitor.visitFunc(funcType, "addTags")
|
|
785
805
|
|
|
786
|
-
const vecField = meta.fields[0]
|
|
806
|
+
const vecField = meta.fields[0] as VectorField
|
|
787
807
|
if (vecField.type !== "vector") {
|
|
788
808
|
throw new Error("Expected vector field")
|
|
789
809
|
}
|
|
@@ -837,7 +857,9 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
837
857
|
expect(field.fields.length).toBeGreaterThan(5)
|
|
838
858
|
|
|
839
859
|
// Check spender field
|
|
840
|
-
const spenderField = field.fields.find(
|
|
860
|
+
const spenderField = field.fields.find(
|
|
861
|
+
(f) => f.label === "spender"
|
|
862
|
+
) as RecordField
|
|
841
863
|
if (!spenderField || spenderField.type !== "record") {
|
|
842
864
|
throw new Error("Spender field not found or not record")
|
|
843
865
|
}
|
|
@@ -901,12 +923,18 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
901
923
|
)
|
|
902
924
|
|
|
903
925
|
expect(field.type).toBe("variant")
|
|
904
|
-
expect(field.
|
|
905
|
-
expect(
|
|
906
|
-
|
|
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)
|
|
907
933
|
|
|
908
934
|
// Check Motion variant
|
|
909
|
-
const motionField = field.fields.find(
|
|
935
|
+
const motionField = field.fields.find(
|
|
936
|
+
(f) => f.label === "Motion"
|
|
937
|
+
) as RecordField
|
|
910
938
|
if (!motionField || motionField.type !== "record") {
|
|
911
939
|
throw new Error("Motion field not found or not record")
|
|
912
940
|
}
|
|
@@ -916,7 +944,7 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
916
944
|
// Check TransferSnsTreasuryFunds variant
|
|
917
945
|
const transferField = field.fields.find(
|
|
918
946
|
(f) => f.label === "TransferSnsTreasuryFunds"
|
|
919
|
-
)
|
|
947
|
+
) as RecordField
|
|
920
948
|
if (!transferField || transferField.type !== "record") {
|
|
921
949
|
throw new Error("Transfer field not found or not record")
|
|
922
950
|
}
|
|
@@ -944,8 +972,9 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
944
972
|
"status"
|
|
945
973
|
)
|
|
946
974
|
|
|
947
|
-
expect(field.getOptionDefault("Active")).toEqual({
|
|
975
|
+
expect(field.getOptionDefault("Active")).toEqual({ _type: "Active" })
|
|
948
976
|
expect(field.getOptionDefault("Pending")).toEqual({
|
|
977
|
+
_type: "Pending",
|
|
949
978
|
Pending: { reason: "" },
|
|
950
979
|
})
|
|
951
980
|
})
|
|
@@ -1371,4 +1400,40 @@ describe("ArgumentFieldVisitor", () => {
|
|
|
1371
1400
|
}
|
|
1372
1401
|
})
|
|
1373
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
|
+
})
|
|
1374
1439
|
})
|