codama-renderers-dart 0.5.0 → 0.5.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/index.browser.cjs +456 -127
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +456 -128
- package/dist/index.browser.js.map +1 -1
- package/dist/index.node.cjs +456 -127
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +456 -128
- package/dist/index.node.js.map +1 -1
- package/dist/index.react-native.js +456 -128
- package/dist/index.react-native.js.map +1 -1
- package/dist/types/fragments/accountPage.d.ts.map +1 -1
- package/dist/types/fragments/instructionPage.d.ts.map +1 -1
- package/dist/types/fragments/typePage.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/utils/discriminators.d.ts +10 -0
- package/dist/types/utils/discriminators.d.ts.map +1 -0
- package/dist/types/utils/exactDecoder.d.ts +17 -0
- package/dist/types/utils/exactDecoder.d.ts.map +1 -0
- package/dist/types/utils/formatCode.d.ts +1 -1
- package/dist/types/utils/formatCode.d.ts.map +1 -1
- package/dist/types/utils/index.d.ts +4 -0
- package/dist/types/utils/index.d.ts.map +1 -1
- package/dist/types/utils/normalizeRootNode.d.ts +11 -0
- package/dist/types/utils/normalizeRootNode.d.ts.map +1 -0
- package/dist/types/utils/valueNodes.d.ts +16 -0
- package/dist/types/utils/valueNodes.d.ts.map +1 -0
- package/dist/types/visitors/getTypeManifestVisitor.d.ts +1 -1
- package/dist/types/visitors/getTypeManifestVisitor.d.ts.map +1 -1
- package/dist/types/visitors/renderVisitor.d.ts.map +1 -1
- package/package.json +21 -18
- package/readme.md +29 -0
- package/src/fragments/accountPage.ts +90 -17
- package/src/fragments/instructionPage.ts +103 -77
- package/src/fragments/typePage.ts +32 -12
- package/src/index.ts +1 -0
- package/src/utils/discriminators.ts +121 -0
- package/src/utils/exactDecoder.ts +82 -0
- package/src/utils/formatCode.ts +7 -11
- package/src/utils/index.ts +4 -0
- package/src/utils/normalizeRootNode.ts +76 -0
- package/src/utils/valueNodes.ts +87 -0
- package/src/visitors/getRenderMapVisitor.ts +1 -1
- package/src/visitors/getTypeManifestVisitor.ts +14 -8
- package/src/visitors/renderVisitor.ts +4 -1
package/dist/index.browser.js
CHANGED
|
@@ -8,13 +8,71 @@ import { CodamaError, CODAMA_ERROR__UNEXPECTED_NODE_KIND } from '@codama/errors'
|
|
|
8
8
|
|
|
9
9
|
// src/visitors/renderVisitor.ts
|
|
10
10
|
function formatDartDirectory(dir) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
execSync(`dart format "${dir}"`, {
|
|
12
|
+
encoding: "utf-8",
|
|
13
|
+
timeout: 6e4,
|
|
14
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// src/utils/normalizeRootNode.ts
|
|
19
|
+
function normalizeRootNode(root) {
|
|
20
|
+
return normalizeNode(root);
|
|
21
|
+
}
|
|
22
|
+
function normalizeNode(value) {
|
|
23
|
+
if (Array.isArray(value)) {
|
|
24
|
+
return value.map(normalizeNode);
|
|
25
|
+
}
|
|
26
|
+
if (!isRecord(value)) {
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
const normalized = Object.fromEntries(
|
|
30
|
+
Object.entries(value).map(([key, child]) => [key, normalizeNode(child)])
|
|
31
|
+
);
|
|
32
|
+
switch (normalized.kind) {
|
|
33
|
+
case "rootNode":
|
|
34
|
+
setEmptyCollection(normalized, "additionalPrograms");
|
|
35
|
+
break;
|
|
36
|
+
case "programNode":
|
|
37
|
+
setEmptyCollection(normalized, "accounts");
|
|
38
|
+
setEmptyCollection(normalized, "constants");
|
|
39
|
+
setEmptyCollection(normalized, "definedTypes");
|
|
40
|
+
setEmptyCollection(normalized, "errors");
|
|
41
|
+
setEmptyCollection(normalized, "events");
|
|
42
|
+
setEmptyCollection(normalized, "instructions");
|
|
43
|
+
setEmptyCollection(normalized, "pdas");
|
|
44
|
+
break;
|
|
45
|
+
case "instructionNode":
|
|
46
|
+
setEmptyCollection(normalized, "accounts");
|
|
47
|
+
setEmptyCollection(normalized, "arguments");
|
|
48
|
+
break;
|
|
49
|
+
case "pdaNode":
|
|
50
|
+
setEmptyCollection(normalized, "seeds");
|
|
51
|
+
break;
|
|
52
|
+
case "structTypeNode":
|
|
53
|
+
setEmptyCollection(normalized, "fields");
|
|
54
|
+
break;
|
|
55
|
+
case "enumTypeNode":
|
|
56
|
+
setEmptyCollection(normalized, "variants");
|
|
57
|
+
break;
|
|
58
|
+
case "tupleTypeNode":
|
|
59
|
+
setEmptyCollection(normalized, "items");
|
|
60
|
+
break;
|
|
61
|
+
case "hiddenPrefixTypeNode":
|
|
62
|
+
setEmptyCollection(normalized, "prefix");
|
|
63
|
+
break;
|
|
64
|
+
case "hiddenSuffixTypeNode":
|
|
65
|
+
setEmptyCollection(normalized, "suffix");
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
return normalized;
|
|
69
|
+
}
|
|
70
|
+
function isRecord(value) {
|
|
71
|
+
return typeof value === "object" && value !== null;
|
|
72
|
+
}
|
|
73
|
+
function setEmptyCollection(record, key) {
|
|
74
|
+
if (record[key] === void 0) {
|
|
75
|
+
record[key] = [];
|
|
18
76
|
}
|
|
19
77
|
}
|
|
20
78
|
|
|
@@ -204,17 +262,6 @@ function use(typeName, module) {
|
|
|
204
262
|
return { content: typeName, imports };
|
|
205
263
|
}
|
|
206
264
|
|
|
207
|
-
// src/utils/typeManifest.ts
|
|
208
|
-
function emptyTypeManifest() {
|
|
209
|
-
return {
|
|
210
|
-
type: emptyFragment(),
|
|
211
|
-
encoder: emptyFragment(),
|
|
212
|
-
decoder: emptyFragment(),
|
|
213
|
-
value: emptyFragment(),
|
|
214
|
-
isEnum: false
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
|
|
218
265
|
// src/utils/wellKnownAddresses.ts
|
|
219
266
|
var WELL_KNOWN_ADDRESSES = /* @__PURE__ */ new Map([
|
|
220
267
|
// Agave / Solana native programs
|
|
@@ -269,6 +316,207 @@ var WELL_KNOWN_ADDRESSES = /* @__PURE__ */ new Map([
|
|
|
269
316
|
["Es9vMFrzaCERm6YKXx6bqKr1Rmd9b5v3J8rM5e4rfF4", "usdtAddress"]
|
|
270
317
|
]);
|
|
271
318
|
|
|
319
|
+
// src/utils/valueNodes.ts
|
|
320
|
+
function getDartValueFragment(value, dartType) {
|
|
321
|
+
switch (value.kind) {
|
|
322
|
+
case "numberValueNode":
|
|
323
|
+
return fragmentFromString(
|
|
324
|
+
dartType === "BigInt" ? `BigInt.from(${value.number})` : String(value.number)
|
|
325
|
+
);
|
|
326
|
+
case "booleanValueNode":
|
|
327
|
+
return fragmentFromString(String(value.boolean));
|
|
328
|
+
case "stringValueNode":
|
|
329
|
+
return fragmentFromString(toDartStringLiteral(value.string));
|
|
330
|
+
case "noneValueNode":
|
|
331
|
+
return fragmentFromString("null");
|
|
332
|
+
case "bytesValueNode": {
|
|
333
|
+
if (value.encoding !== "base16") {
|
|
334
|
+
throw new Error(
|
|
335
|
+
`Unsupported deterministic bytes encoding: ${value.encoding}`
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
const clean = value.data.replace(/^0x/, "");
|
|
339
|
+
if (clean.length % 2 !== 0 || !/^[0-9a-f]*$/i.test(clean)) {
|
|
340
|
+
throw new Error(`Invalid hexadecimal bytes value: ${value.data}`);
|
|
341
|
+
}
|
|
342
|
+
const bytes = clean.match(/.{2}/g)?.map((byte) => `0x${byte}`) ?? [];
|
|
343
|
+
return fragment`${use("Uint8List", "dartTypedData")}.fromList([${fragmentFromString(bytes.join(", "))}])`;
|
|
344
|
+
}
|
|
345
|
+
case "publicKeyValueNode": {
|
|
346
|
+
const wellKnownName = WELL_KNOWN_ADDRESSES.get(value.publicKey);
|
|
347
|
+
return wellKnownName ? fragment`${use(wellKnownName, "solanaAddresses")}` : fragment`${use("Address", "solanaAddresses")}(${fragmentFromString(toDartStringLiteral(value.publicKey))})`;
|
|
348
|
+
}
|
|
349
|
+
default:
|
|
350
|
+
throw new Error(
|
|
351
|
+
`Unsupported deterministic Dart value node: ${value.kind}`
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
function isConstDartValueNode(value) {
|
|
356
|
+
switch (value.kind) {
|
|
357
|
+
case "numberValueNode":
|
|
358
|
+
case "booleanValueNode":
|
|
359
|
+
case "stringValueNode":
|
|
360
|
+
case "noneValueNode":
|
|
361
|
+
case "publicKeyValueNode":
|
|
362
|
+
return true;
|
|
363
|
+
default:
|
|
364
|
+
return false;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
function toDartStringLiteral(value) {
|
|
368
|
+
return `'${value.replaceAll("\\", "\\\\").replaceAll("\n", "\\n").replaceAll("\r", "\\r").replaceAll(" ", "\\t").replaceAll("\b", "\\b").replaceAll("\f", "\\f").replaceAll("$", "\\$").replaceAll("'", "\\'")}'`;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// src/utils/discriminators.ts
|
|
372
|
+
function getDiscriminatorValidationFragment(node, scope) {
|
|
373
|
+
const discriminators = node.discriminators ?? [];
|
|
374
|
+
if (discriminators.length === 0) return emptyFragment();
|
|
375
|
+
const fields = getDiscriminatorFields(node);
|
|
376
|
+
const fragments = discriminators.map((discriminator) => {
|
|
377
|
+
switch (discriminator.kind) {
|
|
378
|
+
case "constantDiscriminatorNode":
|
|
379
|
+
return getConstantValidationFragment(
|
|
380
|
+
discriminator.constant,
|
|
381
|
+
discriminator.offset,
|
|
382
|
+
scope
|
|
383
|
+
);
|
|
384
|
+
case "fieldDiscriminatorNode": {
|
|
385
|
+
const field = fields.find(
|
|
386
|
+
(candidate) => candidate.name === discriminator.name
|
|
387
|
+
);
|
|
388
|
+
if (field?.defaultValue == null) {
|
|
389
|
+
throw new Error(
|
|
390
|
+
`Field discriminator "${discriminator.name}" on ${node.kind} "${node.name}" must reference a field with a default value.`
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
return getConstantValidationFragment(
|
|
394
|
+
{
|
|
395
|
+
type: field.type,
|
|
396
|
+
value: field.defaultValue
|
|
397
|
+
},
|
|
398
|
+
discriminator.offset,
|
|
399
|
+
scope
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
case "sizeDiscriminatorNode": {
|
|
403
|
+
if (!Number.isSafeInteger(discriminator.size) || discriminator.size < 0) {
|
|
404
|
+
throw new Error(
|
|
405
|
+
`Discriminator size must be a non-negative safe integer, got ${discriminator.size}.`
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
return fragment`if (bytes.length - offset != ${fragmentFromString(String(discriminator.size))}) {
|
|
409
|
+
throw ${use("SolanaError", "solanaErrors")}(
|
|
410
|
+
${use("SolanaErrorCode", "solanaErrors")}.codecsInvalidByteLength,
|
|
411
|
+
{
|
|
412
|
+
'codecDescription': '${fragmentFromString(node.name)} discriminator',
|
|
413
|
+
'expected': ${fragmentFromString(String(discriminator.size))},
|
|
414
|
+
'bytesLength': bytes.length - offset,
|
|
415
|
+
},
|
|
416
|
+
);
|
|
417
|
+
}`;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
return mergeFragments(fragments, (contents) => contents.join("\n"));
|
|
422
|
+
}
|
|
423
|
+
function getConstantValidationFragment(constant, discriminatorOffset, scope) {
|
|
424
|
+
if (!Number.isSafeInteger(discriminatorOffset) || discriminatorOffset < 0) {
|
|
425
|
+
throw new Error(
|
|
426
|
+
`Discriminator offset must be a non-negative safe integer, got ${discriminatorOffset}.`
|
|
427
|
+
);
|
|
428
|
+
}
|
|
429
|
+
const manifest = visit(constant.type, scope.typeManifestVisitor);
|
|
430
|
+
const value = getDartValueFragment(
|
|
431
|
+
constant.value,
|
|
432
|
+
manifest.type.content
|
|
433
|
+
);
|
|
434
|
+
return fragment`${use("getConstantDecoder", "solanaCodecsDataStructures")}(
|
|
435
|
+
${manifest.encoder}.encode(${value}),
|
|
436
|
+
).read(bytes, offset + ${fragmentFromString(String(discriminatorOffset))});`;
|
|
437
|
+
}
|
|
438
|
+
function getDiscriminatorFields(node) {
|
|
439
|
+
if (node.kind === "accountNode") {
|
|
440
|
+
return resolveNestedTypeNode(node.data).fields ?? [];
|
|
441
|
+
}
|
|
442
|
+
return (node.arguments ?? []).map(
|
|
443
|
+
(argument) => ({
|
|
444
|
+
...argument,
|
|
445
|
+
kind: "structFieldTypeNode"
|
|
446
|
+
})
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// src/utils/exactDecoder.ts
|
|
451
|
+
function getTopLevelDecoderFragment({
|
|
452
|
+
typeName,
|
|
453
|
+
description,
|
|
454
|
+
discriminatorValidation,
|
|
455
|
+
fromMapFields,
|
|
456
|
+
requireExactConsumption
|
|
457
|
+
}) {
|
|
458
|
+
const validation = discriminatorValidation.content ? ` ${discriminatorValidation.content.replaceAll("\n", "\n ")}
|
|
459
|
+
` : "";
|
|
460
|
+
const consumptionCheck = requireExactConsumption ? ` if (newOffset != bytes.length) {
|
|
461
|
+
throwInvalidByteLength(newOffset - offset, bytes.length - offset);
|
|
462
|
+
}
|
|
463
|
+
` : "";
|
|
464
|
+
const fixedSizeCheck = requireExactConsumption ? "bytesLength != structDecoder.fixedSize" : "bytesLength < structDecoder.fixedSize";
|
|
465
|
+
const result = fragment` Never throwInvalidByteLength(int expected, int bytesLength) {
|
|
466
|
+
throw ${use("SolanaError", "solanaErrors")}(
|
|
467
|
+
${use("SolanaErrorCode", "solanaErrors")}.codecsInvalidByteLength,
|
|
468
|
+
{
|
|
469
|
+
'codecDescription': '${fragmentFromString(description)}',
|
|
470
|
+
'expected': expected,
|
|
471
|
+
'bytesLength': bytesLength,
|
|
472
|
+
},
|
|
473
|
+
);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
(${fragmentFromString(typeName)}, int) readTopLevel(Uint8List bytes, int offset) {
|
|
477
|
+
${fragmentFromString(validation)} final (map, newOffset) = structDecoder.read(bytes, offset);
|
|
478
|
+
${fragmentFromString(consumptionCheck)}
|
|
479
|
+
return (
|
|
480
|
+
${fragmentFromString(typeName)}(
|
|
481
|
+
${fragmentFromString(fromMapFields)}
|
|
482
|
+
),
|
|
483
|
+
newOffset,
|
|
484
|
+
);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
return switch (structDecoder) {
|
|
488
|
+
${use("FixedSizeDecoder", "solanaCodecsCore")}<Map<String, Object?>>() =>
|
|
489
|
+
${use("FixedSizeDecoder", "solanaCodecsCore")}<${fragmentFromString(typeName)}>(
|
|
490
|
+
fixedSize: structDecoder.fixedSize,
|
|
491
|
+
read: (bytes, offset) {
|
|
492
|
+
final bytesLength = bytes.length - offset;
|
|
493
|
+
if (${fragmentFromString(fixedSizeCheck)}) {
|
|
494
|
+
throwInvalidByteLength(structDecoder.fixedSize, bytesLength);
|
|
495
|
+
}
|
|
496
|
+
return readTopLevel(bytes, offset);
|
|
497
|
+
},
|
|
498
|
+
),
|
|
499
|
+
${use("VariableSizeDecoder", "solanaCodecsCore")}<Map<String, Object?>>() =>
|
|
500
|
+
${use("VariableSizeDecoder", "solanaCodecsCore")}<${fragmentFromString(typeName)}>(
|
|
501
|
+
read: readTopLevel,
|
|
502
|
+
maxSize: structDecoder.maxSize,
|
|
503
|
+
),
|
|
504
|
+
};`;
|
|
505
|
+
result.imports.mergeWith(discriminatorValidation.imports);
|
|
506
|
+
return result;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// src/utils/typeManifest.ts
|
|
510
|
+
function emptyTypeManifest() {
|
|
511
|
+
return {
|
|
512
|
+
type: emptyFragment(),
|
|
513
|
+
encoder: emptyFragment(),
|
|
514
|
+
decoder: emptyFragment(),
|
|
515
|
+
value: emptyFragment(),
|
|
516
|
+
isEnum: false
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
|
|
272
520
|
// src/visitors/getTypeManifestVisitor.ts
|
|
273
521
|
function getTypeManifestVisitor(input) {
|
|
274
522
|
const { nameApi, linkables, nonScalarEnums = [] } = input;
|
|
@@ -412,12 +660,17 @@ function getTypeManifestVisitor(input) {
|
|
|
412
660
|
const itemManifest = visit(node.item, self);
|
|
413
661
|
const encoderSizeExpr = getArraySizeExpression(node, "Encoder");
|
|
414
662
|
const decoderSizeExpr = getArraySizeExpression(node, "Decoder");
|
|
663
|
+
const itemType = fragmentFromString(itemManifest.type.content);
|
|
664
|
+
const itemEncoder = fragment`${use(
|
|
665
|
+
"transformEncoder",
|
|
666
|
+
"solanaCodecsCore"
|
|
667
|
+
)}(${itemManifest.encoder}, (${itemType} value) => value)`;
|
|
415
668
|
return {
|
|
416
669
|
type: fragment`List<${itemManifest.type}>`,
|
|
417
670
|
encoder: fragment`${use(
|
|
418
671
|
"getArrayEncoder",
|
|
419
672
|
"solanaCodecsDataStructures"
|
|
420
|
-
)}(${
|
|
673
|
+
)}<${itemType}>(${itemEncoder}${encoderSizeExpr})`,
|
|
421
674
|
decoder: fragment`${use(
|
|
422
675
|
"getArrayDecoder",
|
|
423
676
|
"solanaCodecsDataStructures"
|
|
@@ -464,7 +717,7 @@ function getTypeManifestVisitor(input) {
|
|
|
464
717
|
};
|
|
465
718
|
},
|
|
466
719
|
visitTupleType(node, { self }) {
|
|
467
|
-
const itemManifests = node.items.map((item) => visit(item, self));
|
|
720
|
+
const itemManifests = (node.items ?? []).map((item) => visit(item, self));
|
|
468
721
|
const typeList = itemManifests.map((m) => m.type.content).join(", ");
|
|
469
722
|
const encoderList = itemManifests.map((m) => m.encoder);
|
|
470
723
|
const decoderList = itemManifests.map((m) => m.decoder);
|
|
@@ -497,8 +750,9 @@ function getTypeManifestVisitor(input) {
|
|
|
497
750
|
};
|
|
498
751
|
},
|
|
499
752
|
visitStructType(node, { self }) {
|
|
500
|
-
const
|
|
501
|
-
const
|
|
753
|
+
const nodeFields = node.fields ?? [];
|
|
754
|
+
const fields = nodeFields.map((f) => visit(f, self));
|
|
755
|
+
const fieldNames = nodeFields.map((f) => f.name);
|
|
502
756
|
const typeStr = "Map<String, Object?>";
|
|
503
757
|
const encoderFields = fields.map((f, i) => `('${fieldNames[i]}', ${f.encoder.content})`).join(", ");
|
|
504
758
|
const encoderFrag = fragment`${use(
|
|
@@ -528,7 +782,7 @@ function getTypeManifestVisitor(input) {
|
|
|
528
782
|
return visit(node.type, self);
|
|
529
783
|
},
|
|
530
784
|
visitEnumType(node, { self }) {
|
|
531
|
-
const isScalar = node.variants.every(
|
|
785
|
+
const isScalar = (node.variants ?? []).every(
|
|
532
786
|
(v) => v.kind === "enumEmptyVariantTypeNode"
|
|
533
787
|
);
|
|
534
788
|
if (isScalar) {
|
|
@@ -620,7 +874,7 @@ function getTypeManifestVisitor(input) {
|
|
|
620
874
|
encoder: fragment`${use(
|
|
621
875
|
"fixEncoderSize",
|
|
622
876
|
"solanaCodecsCore"
|
|
623
|
-
)}(${innerManifest.encoder}, ${fragmentFromString(String(node.size))})`,
|
|
877
|
+
)}(${innerManifest.encoder}, ${fragmentFromString(String(node.size))}, allowTruncation: false)`,
|
|
624
878
|
decoder: fragment`${use(
|
|
625
879
|
"fixDecoderSize",
|
|
626
880
|
"solanaCodecsCore"
|
|
@@ -658,7 +912,7 @@ function getTypeManifestVisitor(input) {
|
|
|
658
912
|
},
|
|
659
913
|
visitHiddenPrefixType(node, { self }) {
|
|
660
914
|
const innerManifest = visit(node.type, self);
|
|
661
|
-
const prefixes = node.prefix.map((p) => getHiddenAffixManifest(p, self));
|
|
915
|
+
const prefixes = (node.prefix ?? []).map((p) => getHiddenAffixManifest(p, self));
|
|
662
916
|
const prefixEncoders = prefixes.map((p) => p.encoder.content).join(", ");
|
|
663
917
|
const prefixDecoders = prefixes.map((p) => p.decoder.content).join(", ");
|
|
664
918
|
const encoderFrag = fragment`${use(
|
|
@@ -685,7 +939,7 @@ function getTypeManifestVisitor(input) {
|
|
|
685
939
|
},
|
|
686
940
|
visitHiddenSuffixType(node, { self }) {
|
|
687
941
|
const innerManifest = visit(node.type, self);
|
|
688
|
-
const suffixes = node.suffix.map((s) => getHiddenAffixManifest(s, self));
|
|
942
|
+
const suffixes = (node.suffix ?? []).map((s) => getHiddenAffixManifest(s, self));
|
|
689
943
|
const suffixEncoders = suffixes.map((s) => s.encoder.content).join(", ");
|
|
690
944
|
const suffixDecoders = suffixes.map((s) => s.decoder.content).join(", ");
|
|
691
945
|
const encoderFrag = fragment`${use(
|
|
@@ -972,19 +1226,52 @@ function hexToBytes(hex) {
|
|
|
972
1226
|
function getAccountPageFragment(node, scope) {
|
|
973
1227
|
const name = node.name;
|
|
974
1228
|
const typeName = scope.nameApi.dataType(name);
|
|
975
|
-
const
|
|
976
|
-
const fields = dataNode.fields;
|
|
1229
|
+
const fields = resolveNestedTypeNode(node.data).fields ?? [];
|
|
977
1230
|
const fieldManifests = fields.map((f) => ({
|
|
978
1231
|
field: f,
|
|
979
1232
|
manifest: visit(f.type, scope.typeManifestVisitor)
|
|
980
1233
|
}));
|
|
1234
|
+
const omittedFields = fields.filter(isOmittedDefaultField);
|
|
1235
|
+
const constructorFields = fields.filter(
|
|
1236
|
+
(field) => !isOmittedDefaultField(field)
|
|
1237
|
+
);
|
|
1238
|
+
const forcedFields = /* @__PURE__ */ new Set([
|
|
1239
|
+
...omittedFields,
|
|
1240
|
+
...fields.filter((field) => isFieldDiscriminator(field, node))
|
|
1241
|
+
]);
|
|
1242
|
+
const fieldDefaults = new Map(
|
|
1243
|
+
fieldManifests.flatMap(({ field, manifest }) => {
|
|
1244
|
+
if (!forcedFields.has(field) || field.defaultValue == null) return [];
|
|
1245
|
+
return [
|
|
1246
|
+
[
|
|
1247
|
+
field,
|
|
1248
|
+
getDartValueFragment(field.defaultValue, manifest.type.content)
|
|
1249
|
+
]
|
|
1250
|
+
];
|
|
1251
|
+
})
|
|
1252
|
+
);
|
|
1253
|
+
for (const field of forcedFields) {
|
|
1254
|
+
if (!fieldDefaults.has(field)) {
|
|
1255
|
+
throw new Error(
|
|
1256
|
+
`Forced field "${field.name}" on account "${node.name}" must have a deterministic default value.`
|
|
1257
|
+
);
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
981
1260
|
const fieldDecls = fieldManifests.map(({ field: f, manifest }) => {
|
|
982
1261
|
return ` final ${manifest.type.content} ${camelCase(f.name)};`;
|
|
983
1262
|
}).join("\n");
|
|
984
|
-
const ctorParams =
|
|
985
|
-
const
|
|
1263
|
+
const ctorParams = constructorFields.map((f) => ` required this.${camelCase(f.name)},`).join("\n");
|
|
1264
|
+
const ctorInitializers = omittedFields.map((field) => {
|
|
1265
|
+
const fieldName = camelCase(field.name);
|
|
1266
|
+
return `${fieldName} = ${fieldDefaults.get(field).content}`;
|
|
1267
|
+
}).join(",\n ");
|
|
1268
|
+
const ctorKeyword = omittedFields.every(
|
|
1269
|
+
(field) => isConstDartValueNode(field.defaultValue)
|
|
1270
|
+
) ? "const " : "";
|
|
1271
|
+
const ctorSignature = constructorFields.length === 0 ? `${ctorKeyword}${typeName}()${ctorInitializers ? ` : ${ctorInitializers}` : ""};` : `${ctorKeyword}${typeName}({
|
|
986
1272
|
${ctorParams}
|
|
987
|
-
})
|
|
1273
|
+
})${ctorInitializers ? ` :
|
|
1274
|
+
${ctorInitializers}` : ""};`;
|
|
988
1275
|
const eqChecks = fields.length === 0 ? "true" : fields.map(
|
|
989
1276
|
(f) => `${camelCase(f.name)} == other.${camelCase(f.name)}`
|
|
990
1277
|
).join(" &&\n ");
|
|
@@ -999,10 +1286,11 @@ ${ctorParams}
|
|
|
999
1286
|
const decFields = fieldManifests.map(({ field: f, manifest }) => {
|
|
1000
1287
|
return ` ('${f.name}', ${manifest.decoder.content}),`;
|
|
1001
1288
|
}).join("\n");
|
|
1002
|
-
const toMapFields = fields.map(
|
|
1003
|
-
(f)
|
|
1004
|
-
|
|
1005
|
-
|
|
1289
|
+
const toMapFields = fields.map((f) => {
|
|
1290
|
+
const value = forcedFields.has(f) ? fieldDefaults.get(f).content : `value.${camelCase(f.name)}`;
|
|
1291
|
+
return ` '${f.name}': ${value},`;
|
|
1292
|
+
}).join("\n");
|
|
1293
|
+
const fromMapFields = fieldManifests.filter(({ field }) => !isOmittedDefaultField(field)).map(({ field: f, manifest }) => {
|
|
1006
1294
|
const typeStr = manifest.type.content;
|
|
1007
1295
|
const isNullable = typeStr.endsWith("?");
|
|
1008
1296
|
const accessor = isNullable ? `map['${f.name}']` : `map['${f.name}']!`;
|
|
@@ -1016,6 +1304,19 @@ ${ctorParams}
|
|
|
1016
1304
|
/// The size of the [${fragmentFromString(typeName)}] account data in bytes.
|
|
1017
1305
|
const int ${fragmentFromString(scope.nameApi.accountSizeConstant(name))} = ${fragmentFromString(String(node.size))};` : emptyFragment();
|
|
1018
1306
|
const discFragment = getDiscriminatorConstantsFragment(node, scope);
|
|
1307
|
+
const discriminatorValidation = getDiscriminatorValidationFragment(
|
|
1308
|
+
node,
|
|
1309
|
+
scope
|
|
1310
|
+
);
|
|
1311
|
+
const topLevelDecoder = getTopLevelDecoderFragment({
|
|
1312
|
+
typeName,
|
|
1313
|
+
description: `${name} account decoder`,
|
|
1314
|
+
discriminatorValidation,
|
|
1315
|
+
fromMapFields,
|
|
1316
|
+
requireExactConsumption: (node.discriminators ?? []).some(
|
|
1317
|
+
(discriminator) => discriminator.kind === "sizeDiscriminatorNode"
|
|
1318
|
+
)
|
|
1319
|
+
});
|
|
1019
1320
|
const parts = [
|
|
1020
1321
|
fragment`// Auto-generated. Do not edit.
|
|
1021
1322
|
// ignore_for_file: type=lint
|
|
@@ -1075,12 +1376,7 @@ Decoder<${fragmentFromString(typeName)}> ${fragmentFromString(decoderName)}() {
|
|
|
1075
1376
|
${fragmentFromString(decFields)}
|
|
1076
1377
|
]);
|
|
1077
1378
|
|
|
1078
|
-
|
|
1079
|
-
structDecoder,
|
|
1080
|
-
(Map<String, Object?> map, Uint8List bytes, int offset) => ${fragmentFromString(typeName)}(
|
|
1081
|
-
${fragmentFromString(fromMapFields)}
|
|
1082
|
-
),
|
|
1083
|
-
);
|
|
1379
|
+
${topLevelDecoder}
|
|
1084
1380
|
}
|
|
1085
1381
|
|
|
1086
1382
|
Codec<${fragmentFromString(typeName)}, ${fragmentFromString(typeName)}> ${fragmentFromString(codecName)}() {
|
|
@@ -1096,8 +1392,19 @@ Account<${fragmentFromString(typeName)}> ${fragmentFromString(decodeFnName)}(Enc
|
|
|
1096
1392
|
result.imports.mergeWith(manifest.decoder.imports);
|
|
1097
1393
|
result.imports.mergeWith(manifest.type.imports);
|
|
1098
1394
|
}
|
|
1395
|
+
for (const defaultValue of fieldDefaults.values()) {
|
|
1396
|
+
result.imports.mergeWith(defaultValue.imports);
|
|
1397
|
+
}
|
|
1099
1398
|
return result;
|
|
1100
1399
|
}
|
|
1400
|
+
function isOmittedDefaultField(field) {
|
|
1401
|
+
return field.defaultValue != null && field.defaultValueStrategy === "omitted";
|
|
1402
|
+
}
|
|
1403
|
+
function isFieldDiscriminator(field, node) {
|
|
1404
|
+
return (node.discriminators ?? []).some(
|
|
1405
|
+
(discriminator) => discriminator.kind === "fieldDiscriminatorNode" && discriminator.name === field.name
|
|
1406
|
+
);
|
|
1407
|
+
}
|
|
1101
1408
|
|
|
1102
1409
|
// src/fragments/errorPage.ts
|
|
1103
1410
|
function getErrorPageFragment(programNode, scope) {
|
|
@@ -1158,7 +1465,7 @@ function getIndexPageFragment(fileNames, relativePath = "") {
|
|
|
1158
1465
|
"// Auto-generated. Do not edit.\n// ignore_for_file: type=lint\n"
|
|
1159
1466
|
);
|
|
1160
1467
|
}
|
|
1161
|
-
const exports
|
|
1468
|
+
const exports = fileNames.sort().map((f) => {
|
|
1162
1469
|
const path = relativePath ? `${relativePath}/${f}` : f;
|
|
1163
1470
|
return `export '${path}';`;
|
|
1164
1471
|
}).join("\n");
|
|
@@ -1166,17 +1473,17 @@ function getIndexPageFragment(fileNames, relativePath = "") {
|
|
|
1166
1473
|
`// Auto-generated. Do not edit.
|
|
1167
1474
|
// ignore_for_file: type=lint
|
|
1168
1475
|
|
|
1169
|
-
${exports
|
|
1476
|
+
${exports}
|
|
1170
1477
|
`
|
|
1171
1478
|
);
|
|
1172
1479
|
}
|
|
1173
1480
|
function getRootIndexPageFragment(categories) {
|
|
1174
|
-
const exports
|
|
1481
|
+
const exports = categories.sort().map((cat) => `export '${cat}/${cat}.dart';`).join("\n");
|
|
1175
1482
|
return fragmentFromString(
|
|
1176
1483
|
`// Auto-generated. Do not edit.
|
|
1177
1484
|
// ignore_for_file: type=lint
|
|
1178
1485
|
|
|
1179
|
-
${exports
|
|
1486
|
+
${exports}
|
|
1180
1487
|
`
|
|
1181
1488
|
);
|
|
1182
1489
|
}
|
|
@@ -1186,30 +1493,62 @@ function getInstructionPageFragment(node, scope) {
|
|
|
1186
1493
|
const instrFnName = scope.nameApi.instructionFunction(name);
|
|
1187
1494
|
const parseFnName = scope.nameApi.instructionParseFunction(name);
|
|
1188
1495
|
const accounts = node.accounts ?? [];
|
|
1189
|
-
const args = (node.arguments ?? []).filter(
|
|
1190
|
-
(arg) => !isDiscriminatorArg(arg, node)
|
|
1191
|
-
);
|
|
1192
1496
|
const allArgs = node.arguments ?? [];
|
|
1497
|
+
const optionalAccountStrategy = node.optionalAccountStrategy ?? "programId";
|
|
1498
|
+
if (optionalAccountStrategy !== "programId" && optionalAccountStrategy !== "omitted") {
|
|
1499
|
+
throw new Error(
|
|
1500
|
+
`Unsupported optional account strategy on instruction "${node.name}": ${optionalAccountStrategy}`
|
|
1501
|
+
);
|
|
1502
|
+
}
|
|
1503
|
+
const args = allArgs.filter(
|
|
1504
|
+
(arg) => !isDiscriminatorArg(arg, node) && !isOmittedDefaultArgument(arg)
|
|
1505
|
+
);
|
|
1193
1506
|
const dataClassName = `${typeName}InstructionData`;
|
|
1194
|
-
const allArgManifests =
|
|
1507
|
+
const allArgManifests = (node.arguments ?? []).map((arg) => ({
|
|
1195
1508
|
arg,
|
|
1196
1509
|
manifest: visit(arg.type, scope.typeManifestVisitor)
|
|
1197
1510
|
}));
|
|
1511
|
+
const argDefaultValues = new Map(
|
|
1512
|
+
allArgManifests.flatMap(({ arg, manifest }) => {
|
|
1513
|
+
if (arg.defaultValue == null) return [];
|
|
1514
|
+
const needsRenderedDefault = isOmittedDefaultArgument(arg) || isDiscriminatorArg(arg, node) || arg.defaultValue.kind !== "accountBumpValueNode";
|
|
1515
|
+
if (!needsRenderedDefault) return [];
|
|
1516
|
+
return [
|
|
1517
|
+
[
|
|
1518
|
+
arg,
|
|
1519
|
+
getDartValueFragment(arg.defaultValue, manifest.type.content)
|
|
1520
|
+
]
|
|
1521
|
+
];
|
|
1522
|
+
})
|
|
1523
|
+
);
|
|
1524
|
+
for (const arg of allArgs.filter(
|
|
1525
|
+
(candidate) => isDiscriminatorArg(candidate, node)
|
|
1526
|
+
)) {
|
|
1527
|
+
if (!argDefaultValues.has(arg)) {
|
|
1528
|
+
throw new Error(
|
|
1529
|
+
`Field discriminator "${arg.name}" on instruction "${node.name}" must reference a field with a default value.`
|
|
1530
|
+
);
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1198
1533
|
const dataFieldDecls = allArgManifests.map(({ arg, manifest }) => {
|
|
1199
1534
|
const fieldName = camelCase(arg.name);
|
|
1200
1535
|
return ` final ${manifest.type.content} ${fieldName};`;
|
|
1201
1536
|
}).join("\n");
|
|
1202
1537
|
const dataCtorParams = allArgManifests.map(({ arg, manifest }) => {
|
|
1203
1538
|
const fieldName = camelCase(arg.name);
|
|
1539
|
+
if (isOmittedDefaultArgument(arg)) return "";
|
|
1204
1540
|
if (isDiscriminatorArg(arg, node)) {
|
|
1205
|
-
return isConstDefaultValue(arg.defaultValue) ? ` this.${fieldName} = ${
|
|
1541
|
+
return isConstDefaultValue(arg.defaultValue) ? ` this.${fieldName} = ${argDefaultValues.get(arg).content},` : ` ${manifest.type.content}? ${fieldName},`;
|
|
1206
1542
|
}
|
|
1207
1543
|
return ` required this.${fieldName},`;
|
|
1208
|
-
}).join("\n");
|
|
1544
|
+
}).filter(Boolean).join("\n");
|
|
1209
1545
|
const dataCtorInitializers = allArgManifests.map(({ arg }) => {
|
|
1210
1546
|
const fieldName = camelCase(arg.name);
|
|
1547
|
+
if (isOmittedDefaultArgument(arg)) {
|
|
1548
|
+
return ` ${fieldName} = ${argDefaultValues.get(arg).content}`;
|
|
1549
|
+
}
|
|
1211
1550
|
if (isDiscriminatorArg(arg, node) && !isConstDefaultValue(arg.defaultValue)) {
|
|
1212
|
-
return ` ${fieldName} = ${fieldName} ?? ${
|
|
1551
|
+
return ` ${fieldName} = ${fieldName} ?? ${argDefaultValues.get(arg).content}`;
|
|
1213
1552
|
}
|
|
1214
1553
|
return null;
|
|
1215
1554
|
}).filter((value) => value !== null).join(",\n");
|
|
@@ -1219,16 +1558,26 @@ function getInstructionPageFragment(node, scope) {
|
|
|
1219
1558
|
const decFields = allArgManifests.map(({ arg, manifest }) => {
|
|
1220
1559
|
return ` ('${arg.name}', ${manifest.decoder.content}),`;
|
|
1221
1560
|
}).join("\n");
|
|
1222
|
-
const toMapFields = allArgs.map(
|
|
1223
|
-
(arg)
|
|
1224
|
-
|
|
1225
|
-
|
|
1561
|
+
const toMapFields = allArgs.map((arg) => {
|
|
1562
|
+
const value = isOmittedDefaultArgument(arg) || isDiscriminatorArg(arg, node) ? argDefaultValues.get(arg).content : `value.${camelCase(arg.name)}`;
|
|
1563
|
+
return ` '${arg.name}': ${value},`;
|
|
1564
|
+
}).join("\n");
|
|
1565
|
+
const fromMapFields = allArgManifests.filter(({ arg }) => !isOmittedDefaultArgument(arg)).map(({ arg, manifest }) => {
|
|
1226
1566
|
const typeStr = manifest.type.content;
|
|
1227
1567
|
const isNullable = typeStr.endsWith("?");
|
|
1228
1568
|
const accessor = isNullable ? `map['${arg.name}']` : `map['${arg.name}']!`;
|
|
1229
1569
|
return ` ${camelCase(arg.name)}: ${accessor} as ${typeStr},`;
|
|
1230
1570
|
}).join("\n");
|
|
1231
|
-
const dataCtorKeyword =
|
|
1571
|
+
const dataCtorKeyword = allArgs.every(
|
|
1572
|
+
(arg) => !isOmittedDefaultArgument(arg) || isConstDartValueNode(arg.defaultValue)
|
|
1573
|
+
) && allArgs.every(
|
|
1574
|
+
(arg) => !isDiscriminatorArg(arg, node) || isConstDefaultValue(arg.defaultValue)
|
|
1575
|
+
) ? "const " : "";
|
|
1576
|
+
const dataCtorSignature = dataCtorParams ? `${dataCtorKeyword}${dataClassName}({
|
|
1577
|
+
${dataCtorParams}
|
|
1578
|
+
})${dataCtorInitializers ? ` :
|
|
1579
|
+
${dataCtorInitializers}` : ""};` : `${dataCtorKeyword}${dataClassName}()${dataCtorInitializers ? ` :
|
|
1580
|
+
${dataCtorInitializers}` : ""};`;
|
|
1232
1581
|
const dataEncoderName = `get${typeName}InstructionDataEncoder`;
|
|
1233
1582
|
const dataDecoderName = `get${typeName}InstructionDataDecoder`;
|
|
1234
1583
|
const dataCodecName = `get${typeName}InstructionDataCodec`;
|
|
@@ -1258,20 +1607,33 @@ function getInstructionPageFragment(node, scope) {
|
|
|
1258
1607
|
const role = getAccountRole(acc);
|
|
1259
1608
|
const isOptional = acc.isOptional ?? false;
|
|
1260
1609
|
if (isOptional) {
|
|
1261
|
-
|
|
1610
|
+
if (optionalAccountStrategy === "omitted") {
|
|
1611
|
+
return ` if (${fieldName} != null) AccountMeta(address: ${fieldName}, role: ${role}),`;
|
|
1612
|
+
}
|
|
1613
|
+
return ` if (${fieldName} != null) AccountMeta(address: ${fieldName}, role: ${role}) else AccountMeta(address: ${instrProgramParam}, role: AccountRole.readonly),`;
|
|
1262
1614
|
}
|
|
1263
1615
|
return ` AccountMeta(address: ${fieldName}, role: ${role}),`;
|
|
1264
1616
|
}).join("\n");
|
|
1265
1617
|
const dataConstruction = allArgs.map((arg) => {
|
|
1266
1618
|
const fieldName = camelCase(arg.name);
|
|
1267
|
-
if (isDiscriminatorArg(arg, node)) {
|
|
1619
|
+
if (isOmittedDefaultArgument(arg) || isDiscriminatorArg(arg, node)) {
|
|
1268
1620
|
return "";
|
|
1269
1621
|
}
|
|
1270
|
-
const typeStr2 = argManifestMap.get(arg)?.type.content;
|
|
1271
1622
|
const skipDefault = arg.defaultValue?.kind === "accountBumpValueNode";
|
|
1272
|
-
return ` ${fieldName}: ${fieldName}${arg.defaultValue != null && !skipDefault ? ` ?? ${
|
|
1623
|
+
return ` ${fieldName}: ${fieldName}${arg.defaultValue != null && !skipDefault ? ` ?? ${argDefaultValues.get(arg).content}` : ""},`;
|
|
1273
1624
|
}).filter(Boolean).join("\n");
|
|
1274
1625
|
const discFragment = getDiscriminatorConstantsFragment(node, scope);
|
|
1626
|
+
const discriminatorValidation = getDiscriminatorValidationFragment(
|
|
1627
|
+
node,
|
|
1628
|
+
scope
|
|
1629
|
+
);
|
|
1630
|
+
const topLevelDecoder = getTopLevelDecoderFragment({
|
|
1631
|
+
typeName: dataClassName,
|
|
1632
|
+
description: `${name} instruction decoder`,
|
|
1633
|
+
discriminatorValidation,
|
|
1634
|
+
fromMapFields,
|
|
1635
|
+
requireExactConsumption: true
|
|
1636
|
+
});
|
|
1275
1637
|
const parts = [
|
|
1276
1638
|
fragment`// Auto-generated. Do not edit.
|
|
1277
1639
|
// ignore_for_file: type=lint
|
|
@@ -1295,10 +1657,7 @@ ${use("AccountRole", "solanaInstructions")}`
|
|
|
1295
1657
|
parts.push(fragment`
|
|
1296
1658
|
@immutable
|
|
1297
1659
|
class ${fragmentFromString(dataClassName)} {
|
|
1298
|
-
${fragmentFromString(
|
|
1299
|
-
${fragmentFromString(dataCtorParams)}
|
|
1300
|
-
})${fragmentFromString(dataCtorInitializers ? ` :
|
|
1301
|
-
${dataCtorInitializers}` : "")};
|
|
1660
|
+
${fragmentFromString(dataCtorSignature)}
|
|
1302
1661
|
|
|
1303
1662
|
${fragmentFromString(dataFieldDecls)}
|
|
1304
1663
|
}`);
|
|
@@ -1321,12 +1680,7 @@ Decoder<${fragmentFromString(dataClassName)}> ${fragmentFromString(dataDecoderNa
|
|
|
1321
1680
|
${fragmentFromString(decFields)}
|
|
1322
1681
|
]);
|
|
1323
1682
|
|
|
1324
|
-
|
|
1325
|
-
structDecoder,
|
|
1326
|
-
(Map<String, Object?> map, Uint8List bytes, int offset) => ${fragmentFromString(dataClassName)}(
|
|
1327
|
-
${fragmentFromString(fromMapFields)}
|
|
1328
|
-
),
|
|
1329
|
-
);
|
|
1683
|
+
${topLevelDecoder}
|
|
1330
1684
|
}
|
|
1331
1685
|
|
|
1332
1686
|
Codec<${fragmentFromString(dataClassName)}, ${fragmentFromString(dataClassName)}> ${fragmentFromString(dataCodecName)}() {
|
|
@@ -1362,6 +1716,9 @@ ${fragmentFromString(dataClassName)} ${fragmentFromString(parseFnName)}(Instruct
|
|
|
1362
1716
|
result.imports.mergeWith(manifest.decoder.imports);
|
|
1363
1717
|
result.imports.mergeWith(manifest.type.imports);
|
|
1364
1718
|
}
|
|
1719
|
+
for (const defaultValue of argDefaultValues.values()) {
|
|
1720
|
+
result.imports.mergeWith(defaultValue.imports);
|
|
1721
|
+
}
|
|
1365
1722
|
return result;
|
|
1366
1723
|
}
|
|
1367
1724
|
function getAccountRole(acc) {
|
|
@@ -1378,19 +1735,6 @@ function isDiscriminatorArg(arg, node) {
|
|
|
1378
1735
|
(d) => d.kind === "fieldDiscriminatorNode" && d.name === arg.name
|
|
1379
1736
|
);
|
|
1380
1737
|
}
|
|
1381
|
-
function getDiscriminatorDefault(arg, _node) {
|
|
1382
|
-
if (arg.defaultValue) {
|
|
1383
|
-
if (arg.defaultValue.kind === "numberValueNode") {
|
|
1384
|
-
return String(arg.defaultValue.number);
|
|
1385
|
-
}
|
|
1386
|
-
if (arg.defaultValue.kind === "bytesValueNode") {
|
|
1387
|
-
const data = arg.defaultValue.data;
|
|
1388
|
-
const bytes = data.match(/.{1,2}/g)?.map((b) => parseInt(b, 16)) ?? [];
|
|
1389
|
-
return `Uint8List.fromList([${bytes.join(", ")}])`;
|
|
1390
|
-
}
|
|
1391
|
-
}
|
|
1392
|
-
return "0";
|
|
1393
|
-
}
|
|
1394
1738
|
function isConstDefaultValue(defaultValue) {
|
|
1395
1739
|
if (!defaultValue) return false;
|
|
1396
1740
|
switch (defaultValue.kind) {
|
|
@@ -1403,34 +1747,8 @@ function isConstDefaultValue(defaultValue) {
|
|
|
1403
1747
|
return false;
|
|
1404
1748
|
}
|
|
1405
1749
|
}
|
|
1406
|
-
function
|
|
1407
|
-
|
|
1408
|
-
const isBigInt = typeStr === "BigInt";
|
|
1409
|
-
const dv = arg.defaultValue;
|
|
1410
|
-
switch (dv.kind) {
|
|
1411
|
-
case "numberValueNode":
|
|
1412
|
-
return isBigInt ? `BigInt.from(${dv.number})` : String(dv.number);
|
|
1413
|
-
case "booleanValueNode":
|
|
1414
|
-
return String(dv.boolean);
|
|
1415
|
-
case "stringValueNode":
|
|
1416
|
-
return `'${dv.string}'`;
|
|
1417
|
-
case "publicKeyValueNode": {
|
|
1418
|
-
const wellKnownName = WELL_KNOWN_ADDRESSES.get(dv.publicKey);
|
|
1419
|
-
if (wellKnownName) {
|
|
1420
|
-
use(wellKnownName, "solanaAddresses");
|
|
1421
|
-
return wellKnownName;
|
|
1422
|
-
}
|
|
1423
|
-
return `Address('${dv.publicKey}')`;
|
|
1424
|
-
}
|
|
1425
|
-
case "noneValueNode":
|
|
1426
|
-
return "null";
|
|
1427
|
-
case "bytesValueNode": {
|
|
1428
|
-
const bytes = dv.data.match(/.{1,2}/g)?.map((b) => parseInt(b, 16)) ?? [];
|
|
1429
|
-
return `Uint8List.fromList([${bytes.join(", ")}])`;
|
|
1430
|
-
}
|
|
1431
|
-
default:
|
|
1432
|
-
return "null";
|
|
1433
|
-
}
|
|
1750
|
+
function isOmittedDefaultArgument(arg) {
|
|
1751
|
+
return arg.defaultValue != null && arg.defaultValueStrategy === "omitted";
|
|
1434
1752
|
}
|
|
1435
1753
|
function getPdaPageFragment(node, scope) {
|
|
1436
1754
|
const name = node.name;
|
|
@@ -1725,25 +2043,26 @@ function getTypePageFragment(node, scope) {
|
|
|
1725
2043
|
scope.nameApi.dataType(name);
|
|
1726
2044
|
const typeNode = node.type;
|
|
1727
2045
|
if (typeNode.kind === "enumTypeNode") {
|
|
1728
|
-
const
|
|
2046
|
+
const variants = typeNode.variants ?? [];
|
|
2047
|
+
const isScalar = variants.every(
|
|
1729
2048
|
(v) => v.kind === "enumEmptyVariantTypeNode"
|
|
1730
2049
|
);
|
|
1731
2050
|
if (isScalar) {
|
|
1732
|
-
return getScalarEnumPageFragment(node, scope);
|
|
2051
|
+
return getScalarEnumPageFragment(node, variants, scope);
|
|
1733
2052
|
}
|
|
1734
|
-
return getDataEnumPageFragment(node, scope);
|
|
2053
|
+
return getDataEnumPageFragment(node, variants, scope);
|
|
1735
2054
|
}
|
|
1736
2055
|
if (typeNode.kind === "structTypeNode") {
|
|
1737
2056
|
return getStructPageFragment(node, scope);
|
|
1738
2057
|
}
|
|
1739
2058
|
return getTypeAliasPageFragment(node, scope);
|
|
1740
2059
|
}
|
|
1741
|
-
function getScalarEnumPageFragment(node, scope) {
|
|
2060
|
+
function getScalarEnumPageFragment(node, enumVariants, scope) {
|
|
1742
2061
|
const name = node.name;
|
|
1743
2062
|
const typeName = scope.nameApi.dataType(name);
|
|
1744
2063
|
const enumNode = node.type;
|
|
1745
2064
|
if (enumNode.kind !== "enumTypeNode") return emptyFragment();
|
|
1746
|
-
const variants =
|
|
2065
|
+
const variants = enumVariants.map((v) => {
|
|
1747
2066
|
const variantName = scope.nameApi.enumVariant(v.name);
|
|
1748
2067
|
return variantName;
|
|
1749
2068
|
});
|
|
@@ -1754,6 +2073,14 @@ function getScalarEnumPageFragment(node, scope) {
|
|
|
1754
2073
|
const resolvedSize = resolveNestedTypeNode(enumNode.size);
|
|
1755
2074
|
const sizeType = resolvedSize.format ?? "u8";
|
|
1756
2075
|
const sizeCodecName = getNumberCodecName2(sizeType);
|
|
2076
|
+
const isU64 = sizeType === "u64";
|
|
2077
|
+
const encodedVariantIndex = isU64 ? "BigInt.from(value.index)" : "value.index";
|
|
2078
|
+
const decodedVariant = isU64 ? `(BigInt value, Uint8List bytes, int offset) {
|
|
2079
|
+
if (value.isNegative || value >= BigInt.from(${typeName}.values.length)) {
|
|
2080
|
+
throw RangeError('Invalid ${typeName} discriminator: ' + value.toString());
|
|
2081
|
+
}
|
|
2082
|
+
return ${typeName}.values[value.toInt()];
|
|
2083
|
+
}` : `(int value, Uint8List bytes, int offset) => ${typeName}.values[value]`;
|
|
1757
2084
|
return fragment`// Auto-generated. Do not edit.
|
|
1758
2085
|
// ignore_for_file: type=lint
|
|
1759
2086
|
|
|
@@ -1774,14 +2101,14 @@ ${fragmentFromString(variantLines)}
|
|
|
1774
2101
|
Encoder<${fragmentFromString(typeName)}> ${fragmentFromString(encoderName)}() {
|
|
1775
2102
|
return transformEncoder(
|
|
1776
2103
|
get${fragmentFromString(sizeCodecName)}Encoder(),
|
|
1777
|
-
(${fragmentFromString(typeName)} value) =>
|
|
2104
|
+
(${fragmentFromString(typeName)} value) => ${fragmentFromString(encodedVariantIndex)},
|
|
1778
2105
|
);
|
|
1779
2106
|
}
|
|
1780
2107
|
|
|
1781
2108
|
Decoder<${fragmentFromString(typeName)}> ${fragmentFromString(decoderName)}() {
|
|
1782
2109
|
return transformDecoder(
|
|
1783
2110
|
get${fragmentFromString(sizeCodecName)}Decoder(),
|
|
1784
|
-
|
|
2111
|
+
${fragmentFromString(decodedVariant)},
|
|
1785
2112
|
);
|
|
1786
2113
|
}
|
|
1787
2114
|
|
|
@@ -1789,7 +2116,7 @@ Codec<${fragmentFromString(typeName)}, ${fragmentFromString(typeName)}> ${fragme
|
|
|
1789
2116
|
return combineCodec(${fragmentFromString(encoderName)}(), ${fragmentFromString(decoderName)}());
|
|
1790
2117
|
}`;
|
|
1791
2118
|
}
|
|
1792
|
-
function getDataEnumPageFragment(node, scope) {
|
|
2119
|
+
function getDataEnumPageFragment(node, variants, scope) {
|
|
1793
2120
|
const name = node.name;
|
|
1794
2121
|
const typeName = scope.nameApi.dataType(name);
|
|
1795
2122
|
const enumNode = node.type;
|
|
@@ -1800,8 +2127,8 @@ function getDataEnumPageFragment(node, scope) {
|
|
|
1800
2127
|
const encodeCases = [];
|
|
1801
2128
|
const decodeCases = [];
|
|
1802
2129
|
const allVariantManifests = [];
|
|
1803
|
-
for (let i = 0; i <
|
|
1804
|
-
const variant =
|
|
2130
|
+
for (let i = 0; i < variants.length; i++) {
|
|
2131
|
+
const variant = variants[i];
|
|
1805
2132
|
const variantName = pascalCase(variant.name);
|
|
1806
2133
|
const variantClassName = scope.nameApi.sealedClassVariant(
|
|
1807
2134
|
name,
|
|
@@ -1831,7 +2158,7 @@ function getDataEnumPageFragment(node, scope) {
|
|
|
1831
2158
|
decodeCases.push(`case ${i}: return const ${variantClassName}();`);
|
|
1832
2159
|
} else if (variant.kind === "enumStructVariantTypeNode") {
|
|
1833
2160
|
const resolvedStruct = resolveNestedTypeNode(variant.struct);
|
|
1834
|
-
const fields = resolvedStruct.fields;
|
|
2161
|
+
const fields = resolvedStruct.fields ?? [];
|
|
1835
2162
|
const fieldManifests = fields.map((f) => ({
|
|
1836
2163
|
field: f,
|
|
1837
2164
|
manifest: visit(f.type, scope.typeManifestVisitor)
|
|
@@ -1897,7 +2224,7 @@ ${fieldDecls}
|
|
|
1897
2224
|
decodeCases.push(`case ${i}: return ${variantClassName}(${fromMapFields.replace(/\n/g, " ").replace(/,$/, "")});`);
|
|
1898
2225
|
} else if (variant.kind === "enumTupleVariantTypeNode") {
|
|
1899
2226
|
const resolvedTuple = resolveNestedTypeNode(variant.tuple);
|
|
1900
|
-
const items = resolvedTuple.items;
|
|
2227
|
+
const items = resolvedTuple.items ?? [];
|
|
1901
2228
|
if (items.length === 1) {
|
|
1902
2229
|
const manifest = visit(items[0], scope.typeManifestVisitor);
|
|
1903
2230
|
allVariantManifests.push(manifest);
|
|
@@ -1997,7 +2324,7 @@ function getStructPageFragment(node, scope) {
|
|
|
1997
2324
|
const typeName = scope.nameApi.dataType(name);
|
|
1998
2325
|
const structNode = node.type;
|
|
1999
2326
|
if (structNode.kind !== "structTypeNode") return emptyFragment();
|
|
2000
|
-
const fields = structNode.fields;
|
|
2327
|
+
const fields = structNode.fields ?? [];
|
|
2001
2328
|
const fieldManifests = fields.map((f) => ({
|
|
2002
2329
|
field: f,
|
|
2003
2330
|
manifest: visit(f.type, scope.typeManifestVisitor)
|
|
@@ -2204,7 +2531,7 @@ function getRenderMapVisitor(options = {}) {
|
|
|
2204
2531
|
visitRoot(node, { self }) {
|
|
2205
2532
|
const programMaps = [
|
|
2206
2533
|
visit(node.program, self),
|
|
2207
|
-
...node.additionalPrograms.map((p) => visit(p, self))
|
|
2534
|
+
...(node.additionalPrograms ?? []).map((p) => visit(p, self))
|
|
2208
2535
|
];
|
|
2209
2536
|
const mergedProgramMap = mergeRenderMaps(programMaps);
|
|
2210
2537
|
const categoryMaps = getSharedCategoryIndexMaps(mergedProgramMap);
|
|
@@ -2350,11 +2677,12 @@ function renderVisitor(outputDir, options = {}) {
|
|
|
2350
2677
|
dependencyMap
|
|
2351
2678
|
} = options;
|
|
2352
2679
|
return rootNodeVisitor((root) => {
|
|
2680
|
+
const normalizedRoot = normalizeRootNode(root);
|
|
2353
2681
|
if (deleteFolderBeforeRendering && existsSync(outputDir)) {
|
|
2354
2682
|
deleteDirectory(outputDir);
|
|
2355
2683
|
}
|
|
2356
2684
|
const renderMap = visit(
|
|
2357
|
-
|
|
2685
|
+
normalizedRoot,
|
|
2358
2686
|
getRenderMapVisitor({ nameApi, dependencyMap })
|
|
2359
2687
|
);
|
|
2360
2688
|
const typePathMap = {};
|
|
@@ -2436,6 +2764,6 @@ function cleanFragmentContent(content) {
|
|
|
2436
2764
|
// src/index.ts
|
|
2437
2765
|
var src_default = renderVisitor;
|
|
2438
2766
|
|
|
2439
|
-
export { DART_EXTERNAL_PACKAGE_MAP, DartImportMap, createDartNameApi, src_default as default, getRenderMapVisitor, getTypeManifestVisitor, renderVisitor };
|
|
2767
|
+
export { DART_EXTERNAL_PACKAGE_MAP, DartImportMap, createDartNameApi, src_default as default, getRenderMapVisitor, getTypeManifestVisitor, normalizeRootNode, renderVisitor };
|
|
2440
2768
|
//# sourceMappingURL=index.browser.js.map
|
|
2441
2769
|
//# sourceMappingURL=index.browser.js.map
|