codama-renderers-dart 0.4.3 → 0.5.0
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/LICENSE +21 -0
- package/dist/index.browser.cjs +184 -38
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +185 -39
- package/dist/index.browser.js.map +1 -1
- package/dist/index.node.cjs +184 -38
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +185 -39
- package/dist/index.node.js.map +1 -1
- package/dist/index.react-native.js +185 -39
- package/dist/index.react-native.js.map +1 -1
- package/dist/types/fragments/instructionPage.d.ts.map +1 -1
- package/dist/types/fragments/programPage.d.ts +1 -1
- package/dist/types/fragments/programPage.d.ts.map +1 -1
- package/dist/types/utils/importMap.d.ts.map +1 -1
- package/dist/types/utils/nameTransformers.d.ts +1 -1
- package/dist/types/utils/nameTransformers.d.ts.map +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 +11 -6
- package/readme.md +1 -3
- package/src/fragments/instructionPage.ts +15 -4
- package/src/fragments/programPage.ts +165 -6
- package/src/fragments/typePage.ts +4 -3
- package/src/utils/importMap.ts +16 -3
- package/src/utils/nameTransformers.ts +3 -2
- package/src/utils/wellKnownAddresses.ts +4 -4
- package/src/visitors/getTypeManifestVisitor.ts +35 -22
- package/src/visitors/renderVisitor.ts +7 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ifiok Jr.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.browser.cjs
CHANGED
|
@@ -50,7 +50,7 @@ function createDartNameApi() {
|
|
|
50
50
|
errorConstant: (programName, errorName) => `${camelCase(programName)}Error${pascalCase(errorName)}`,
|
|
51
51
|
errorMessageFunction: (name) => `get${pascalCase(name)}ErrorMessage`,
|
|
52
52
|
enumVariant: (name) => camelCase(name),
|
|
53
|
-
sealedClassVariant: (
|
|
53
|
+
sealedClassVariant: (parentName, variantName) => `${pascalCase(parentName)}${pascalCase(variantName)}`,
|
|
54
54
|
isTypeFunction: (name) => `is${pascalCase(name)}`,
|
|
55
55
|
fileName: (name) => snakeCase(name),
|
|
56
56
|
discriminatorConstant: (name) => `${camelCase(name)}Discriminator`
|
|
@@ -124,11 +124,16 @@ var DartImportMap = class {
|
|
|
124
124
|
const uris = /* @__PURE__ */ new Set();
|
|
125
125
|
for (const module of this._imports) {
|
|
126
126
|
if (module in internalMap) {
|
|
127
|
-
|
|
127
|
+
const uri = internalMap[module];
|
|
128
|
+
if (uri) {
|
|
129
|
+
uris.add(uri);
|
|
130
|
+
}
|
|
128
131
|
} else if (module in DART_EXTERNAL_PACKAGE_MAP) {
|
|
129
132
|
uris.add(DART_EXTERNAL_PACKAGE_MAP[module]);
|
|
130
|
-
} else {
|
|
133
|
+
} else if (isRawDartImportUri(module)) {
|
|
131
134
|
uris.add(module);
|
|
135
|
+
} else {
|
|
136
|
+
throw new Error(`Unresolved Dart import module "${module}"`);
|
|
132
137
|
}
|
|
133
138
|
}
|
|
134
139
|
return [...uris].sort((a, b) => {
|
|
@@ -157,6 +162,9 @@ var DartImportMap = class {
|
|
|
157
162
|
return lines.join("\n");
|
|
158
163
|
}
|
|
159
164
|
};
|
|
165
|
+
function isRawDartImportUri(module) {
|
|
166
|
+
return module.startsWith("dart:") || module.startsWith("package:") || module.endsWith(".dart") && !module.includes(":");
|
|
167
|
+
}
|
|
160
168
|
|
|
161
169
|
// src/utils/fragment.ts
|
|
162
170
|
function fragment(strings, ...values) {
|
|
@@ -248,10 +256,10 @@ var WELL_KNOWN_ADDRESSES = /* @__PURE__ */ new Map([
|
|
|
248
256
|
["Sysvar1111111111111111111111111111111111111", "sysvarOwnerAddress"],
|
|
249
257
|
// SPL programs
|
|
250
258
|
["TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "tokenProgramAddress"],
|
|
251
|
-
["
|
|
252
|
-
["
|
|
253
|
-
["
|
|
254
|
-
["
|
|
259
|
+
["TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", "token2022ProgramAddress"],
|
|
260
|
+
["ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", "associatedTokenProgramAddress"],
|
|
261
|
+
["MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr", "memoProgramAddress"],
|
|
262
|
+
["Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo", "memoLegacyProgramAddress"],
|
|
255
263
|
// Metaplex programs
|
|
256
264
|
["metaqbxxU9qX8rZXkmUJ7haCrXXz2W1PSUq1Rn3E1od", "tokenMetadataProgramAddress"],
|
|
257
265
|
["BGUMAp9V1mQ2KV8t34L5u3gZsXYZaYDBdKkc1xYk1qA1", "mplBubblegumProgramAddress"],
|
|
@@ -406,17 +414,18 @@ function getTypeManifestVisitor(input) {
|
|
|
406
414
|
},
|
|
407
415
|
visitArrayType(node, { self }) {
|
|
408
416
|
const itemManifest = visitorsCore.visit(node.item, self);
|
|
409
|
-
const
|
|
417
|
+
const encoderSizeExpr = getArraySizeExpression(node, "Encoder");
|
|
418
|
+
const decoderSizeExpr = getArraySizeExpression(node, "Decoder");
|
|
410
419
|
return {
|
|
411
420
|
type: fragment`List<${itemManifest.type}>`,
|
|
412
421
|
encoder: fragment`${use(
|
|
413
422
|
"getArrayEncoder",
|
|
414
423
|
"solanaCodecsDataStructures"
|
|
415
|
-
)}(${itemManifest.encoder}${
|
|
424
|
+
)}(${itemManifest.encoder}${encoderSizeExpr})`,
|
|
416
425
|
decoder: fragment`${use(
|
|
417
426
|
"getArrayDecoder",
|
|
418
427
|
"solanaCodecsDataStructures"
|
|
419
|
-
)}(${itemManifest.decoder}${
|
|
428
|
+
)}(${itemManifest.decoder}${decoderSizeExpr})`,
|
|
420
429
|
value: emptyTypeManifest().value,
|
|
421
430
|
isEnum: false
|
|
422
431
|
};
|
|
@@ -424,34 +433,36 @@ function getTypeManifestVisitor(input) {
|
|
|
424
433
|
visitMapType(node, { self }) {
|
|
425
434
|
const keyManifest = visitorsCore.visit(node.key, self);
|
|
426
435
|
const valueManifest = visitorsCore.visit(node.value, self);
|
|
427
|
-
const
|
|
436
|
+
const encoderSizeExpr = getMapSizeExpression(node, "Encoder");
|
|
437
|
+
const decoderSizeExpr = getMapSizeExpression(node, "Decoder");
|
|
428
438
|
return {
|
|
429
439
|
type: fragment`Map<${keyManifest.type}, ${valueManifest.type}>`,
|
|
430
440
|
encoder: fragment`${use(
|
|
431
441
|
"getMapEncoder",
|
|
432
442
|
"solanaCodecsDataStructures"
|
|
433
|
-
)}(${keyManifest.encoder}, ${valueManifest.encoder}${
|
|
443
|
+
)}(${keyManifest.encoder}, ${valueManifest.encoder}${encoderSizeExpr})`,
|
|
434
444
|
decoder: fragment`${use(
|
|
435
445
|
"getMapDecoder",
|
|
436
446
|
"solanaCodecsDataStructures"
|
|
437
|
-
)}(${keyManifest.decoder}, ${valueManifest.decoder}${
|
|
447
|
+
)}(${keyManifest.decoder}, ${valueManifest.decoder}${decoderSizeExpr})`,
|
|
438
448
|
value: emptyTypeManifest().value,
|
|
439
449
|
isEnum: false
|
|
440
450
|
};
|
|
441
451
|
},
|
|
442
452
|
visitSetType(node, { self }) {
|
|
443
453
|
const itemManifest = visitorsCore.visit(node.item, self);
|
|
444
|
-
const
|
|
454
|
+
const encoderSizeExpr = getSetSizeExpression(node, "Encoder");
|
|
455
|
+
const decoderSizeExpr = getSetSizeExpression(node, "Decoder");
|
|
445
456
|
return {
|
|
446
457
|
type: fragment`Set<${itemManifest.type}>`,
|
|
447
458
|
encoder: fragment`${use(
|
|
448
459
|
"getSetEncoder",
|
|
449
460
|
"solanaCodecsDataStructures"
|
|
450
|
-
)}(${itemManifest.encoder}${
|
|
461
|
+
)}(${itemManifest.encoder}${encoderSizeExpr})`,
|
|
451
462
|
decoder: fragment`${use(
|
|
452
463
|
"getSetDecoder",
|
|
453
464
|
"solanaCodecsDataStructures"
|
|
454
|
-
)}(${itemManifest.decoder}${
|
|
465
|
+
)}(${itemManifest.decoder}${decoderSizeExpr})`,
|
|
455
466
|
value: emptyTypeManifest().value,
|
|
456
467
|
isEnum: false
|
|
457
468
|
};
|
|
@@ -627,9 +638,10 @@ function getTypeManifestVisitor(input) {
|
|
|
627
638
|
const bigIntFormats = /* @__PURE__ */ new Set(["u64", "u128", "i64", "i128"]);
|
|
628
639
|
let prefixManifest;
|
|
629
640
|
if (node.prefix.kind === "numberTypeNode" && bigIntFormats.has(node.prefix.format)) {
|
|
641
|
+
const codecName = getNumberCodecName(node.prefix.format);
|
|
630
642
|
prefixManifest = {
|
|
631
|
-
encoder: fragment
|
|
632
|
-
decoder: fragment
|
|
643
|
+
encoder: fragment`transformEncoder(${use(`get${codecName}Encoder`, "solanaCodecsNumbers")}(), (size) => BigInt.from(size))`,
|
|
644
|
+
decoder: fragment`transformDecoder(${use(`get${codecName}Decoder`, "solanaCodecsNumbers")}(), (size, _, __) => size.toInt())`
|
|
633
645
|
};
|
|
634
646
|
} else {
|
|
635
647
|
prefixManifest = visitorsCore.visit(node.prefix, self);
|
|
@@ -816,7 +828,7 @@ function getNumberCodecExpression(format, codecType) {
|
|
|
816
828
|
const name = getNumberCodecName(format);
|
|
817
829
|
return `get${name}${codecType}()`;
|
|
818
830
|
}
|
|
819
|
-
function getArraySizeExpression(node) {
|
|
831
|
+
function getArraySizeExpression(node, codecType) {
|
|
820
832
|
if (!("count" in node) || !node.count) return "";
|
|
821
833
|
const count = node.count;
|
|
822
834
|
switch (count.kind) {
|
|
@@ -829,13 +841,13 @@ function getArraySizeExpression(node) {
|
|
|
829
841
|
if (resolvedPrefix.format === "u32" && (!resolvedPrefix.endian || resolvedPrefix.endian === "le")) {
|
|
830
842
|
return "";
|
|
831
843
|
}
|
|
832
|
-
return `, size: PrefixedArraySize(
|
|
844
|
+
return `, size: PrefixedArraySize(${getNumberCodecExpression(resolvedPrefix.format, codecType)})`;
|
|
833
845
|
}
|
|
834
846
|
default:
|
|
835
847
|
return "";
|
|
836
848
|
}
|
|
837
849
|
}
|
|
838
|
-
function getMapSizeExpression(node) {
|
|
850
|
+
function getMapSizeExpression(node, codecType) {
|
|
839
851
|
if (!("count" in node) || !node.count) return "";
|
|
840
852
|
const count = node.count;
|
|
841
853
|
switch (count.kind) {
|
|
@@ -848,13 +860,13 @@ function getMapSizeExpression(node) {
|
|
|
848
860
|
if (resolvedPrefix.format === "u32" && (!resolvedPrefix.endian || resolvedPrefix.endian === "le")) {
|
|
849
861
|
return "";
|
|
850
862
|
}
|
|
851
|
-
return `, size: PrefixedArraySize(
|
|
863
|
+
return `, size: PrefixedArraySize(${getNumberCodecExpression(resolvedPrefix.format, codecType)})`;
|
|
852
864
|
}
|
|
853
865
|
default:
|
|
854
866
|
return "";
|
|
855
867
|
}
|
|
856
868
|
}
|
|
857
|
-
function getSetSizeExpression(node) {
|
|
869
|
+
function getSetSizeExpression(node, codecType) {
|
|
858
870
|
if (!("count" in node) || !node.count) return "";
|
|
859
871
|
const count = node.count;
|
|
860
872
|
switch (count.kind) {
|
|
@@ -867,7 +879,7 @@ function getSetSizeExpression(node) {
|
|
|
867
879
|
if (resolvedPrefix.format === "u32" && (!resolvedPrefix.endian || resolvedPrefix.endian === "le")) {
|
|
868
880
|
return "";
|
|
869
881
|
}
|
|
870
|
-
return `, size: PrefixedArraySize(
|
|
882
|
+
return `, size: PrefixedArraySize(${getNumberCodecExpression(resolvedPrefix.format, codecType)})`;
|
|
871
883
|
}
|
|
872
884
|
default:
|
|
873
885
|
return "";
|
|
@@ -1238,7 +1250,7 @@ function getInstructionPageFragment(node, scope) {
|
|
|
1238
1250
|
const manifest = argManifestMap.get(arg);
|
|
1239
1251
|
const fieldName = camelCase(arg.name);
|
|
1240
1252
|
const typeStr = manifest.type.content;
|
|
1241
|
-
const hasDefault = arg.defaultValue != null;
|
|
1253
|
+
const hasDefault = arg.defaultValue != null && arg.defaultValue.kind !== "accountBumpValueNode";
|
|
1242
1254
|
if (hasDefault) {
|
|
1243
1255
|
const nullableType = typeStr.endsWith("?") ? typeStr : `${typeStr}?`;
|
|
1244
1256
|
return ` ${nullableType} ${fieldName},`;
|
|
@@ -1259,7 +1271,9 @@ function getInstructionPageFragment(node, scope) {
|
|
|
1259
1271
|
if (isDiscriminatorArg(arg, node)) {
|
|
1260
1272
|
return "";
|
|
1261
1273
|
}
|
|
1262
|
-
|
|
1274
|
+
const typeStr2 = argManifestMap.get(arg)?.type.content;
|
|
1275
|
+
const skipDefault = arg.defaultValue?.kind === "accountBumpValueNode";
|
|
1276
|
+
return ` ${fieldName}: ${fieldName}${arg.defaultValue != null && !skipDefault ? ` ?? ${getDefaultValue(arg, typeStr2)}` : ""},`;
|
|
1263
1277
|
}).filter(Boolean).join("\n");
|
|
1264
1278
|
const discFragment = getDiscriminatorConstantsFragment(node, scope);
|
|
1265
1279
|
const parts = [
|
|
@@ -1393,12 +1407,13 @@ function isConstDefaultValue(defaultValue) {
|
|
|
1393
1407
|
return false;
|
|
1394
1408
|
}
|
|
1395
1409
|
}
|
|
1396
|
-
function getDefaultValue(arg) {
|
|
1410
|
+
function getDefaultValue(arg, typeStr) {
|
|
1397
1411
|
if (!arg.defaultValue) return "null";
|
|
1412
|
+
const isBigInt = typeStr === "BigInt";
|
|
1398
1413
|
const dv = arg.defaultValue;
|
|
1399
1414
|
switch (dv.kind) {
|
|
1400
1415
|
case "numberValueNode":
|
|
1401
|
-
return String(dv.number);
|
|
1416
|
+
return isBigInt ? `BigInt.from(${dv.number})` : String(dv.number);
|
|
1402
1417
|
case "booleanValueNode":
|
|
1403
1418
|
return String(dv.boolean);
|
|
1404
1419
|
case "stringValueNode":
|
|
@@ -1538,8 +1553,6 @@ function bytesValueToDart(hex) {
|
|
|
1538
1553
|
}
|
|
1539
1554
|
return `[${pairs.join(", ")}]`;
|
|
1540
1555
|
}
|
|
1541
|
-
|
|
1542
|
-
// src/fragments/programPage.ts
|
|
1543
1556
|
function getProgramPageFragment(node, scope) {
|
|
1544
1557
|
const name = node.name;
|
|
1545
1558
|
const addressConstName = scope.nameApi.programAddressConstant(name);
|
|
@@ -1571,17 +1584,146 @@ enum ${fragmentFromString(pascalCase(name))}Account {
|
|
|
1571
1584
|
${fragmentFromString(accountVariants)}
|
|
1572
1585
|
}`);
|
|
1573
1586
|
}
|
|
1574
|
-
const instructions = node
|
|
1587
|
+
const instructions = nodes.getAllInstructionsWithSubs(node);
|
|
1575
1588
|
if (instructions.length > 0) {
|
|
1589
|
+
const programName = pascalCase(name);
|
|
1590
|
+
const instructionEnum = `${programName}Instruction`;
|
|
1576
1591
|
const instrVariants = instructions.map((instr) => ` ${camelCase(instr.name)},`).join("\n");
|
|
1577
1592
|
parts.push(fragment`
|
|
1578
|
-
/// Known instructions for the ${fragmentFromString(
|
|
1579
|
-
enum ${fragmentFromString(
|
|
1593
|
+
/// Known instructions for the ${fragmentFromString(programName)} program.
|
|
1594
|
+
enum ${fragmentFromString(instructionEnum)} {
|
|
1580
1595
|
${fragmentFromString(instrVariants)}
|
|
1581
1596
|
}`);
|
|
1597
|
+
const identifiableInstructions = instructions.map((instruction) => ({
|
|
1598
|
+
instruction,
|
|
1599
|
+
condition: getInstructionDiscriminatorCondition(instruction, scope)
|
|
1600
|
+
})).filter(({ condition }) => condition !== null);
|
|
1601
|
+
if (identifiableInstructions.length > 0) {
|
|
1602
|
+
const identifyBranches = identifiableInstructions.map(
|
|
1603
|
+
({ instruction, condition }) => fragment` if (${condition}) {
|
|
1604
|
+
return ${fragmentFromString(instructionEnum)}.${fragmentFromString(camelCase(instruction.name))};
|
|
1605
|
+
}`
|
|
1606
|
+
);
|
|
1607
|
+
const parsedBase = `Parsed${programName}Instruction`;
|
|
1608
|
+
const parsedClasses = instructions.map((instruction) => {
|
|
1609
|
+
const instructionName = pascalCase(instruction.name);
|
|
1610
|
+
const variant = camelCase(instruction.name);
|
|
1611
|
+
const parsedClass = `Parsed${instructionName}`;
|
|
1612
|
+
const dataClass = `${instructionName}InstructionData`;
|
|
1613
|
+
return fragment`/// A parsed ${fragmentFromString(instructionName)} instruction.
|
|
1614
|
+
final class ${fragmentFromString(parsedClass)} extends ${fragmentFromString(parsedBase)} {
|
|
1615
|
+
const ${fragmentFromString(parsedClass)}({required this.data})
|
|
1616
|
+
: super(${fragmentFromString(instructionEnum)}.${fragmentFromString(variant)});
|
|
1617
|
+
|
|
1618
|
+
final ${use(dataClass, "../instructions/instructions.dart")} data;
|
|
1619
|
+
}`;
|
|
1620
|
+
});
|
|
1621
|
+
const parseBranches = instructions.map((instruction) => {
|
|
1622
|
+
const instructionName = pascalCase(instruction.name);
|
|
1623
|
+
const variant = camelCase(instruction.name);
|
|
1624
|
+
const parsedClass = `Parsed${instructionName}`;
|
|
1625
|
+
const parseFunction = scope.nameApi.instructionParseFunction(
|
|
1626
|
+
instruction.name
|
|
1627
|
+
);
|
|
1628
|
+
return fragment` ${fragmentFromString(instructionEnum)}.${fragmentFromString(variant)} => ${fragmentFromString(parsedClass)}(
|
|
1629
|
+
data: ${use(parseFunction, "../instructions/instructions.dart")}(instruction),
|
|
1630
|
+
),`;
|
|
1631
|
+
});
|
|
1632
|
+
parts.push(fragment`
|
|
1633
|
+
/// Identifies the type of a ${fragmentFromString(programName)} instruction.
|
|
1634
|
+
${fragmentFromString(instructionEnum)} identify${fragmentFromString(programName)}Instruction(
|
|
1635
|
+
${use("Uint8List", "dartTypedData")} data,
|
|
1636
|
+
) {
|
|
1637
|
+
${mergeFragments(identifyBranches, (cs) => cs.join("\n"))}
|
|
1638
|
+
|
|
1639
|
+
throw ${use("SolanaError", "solanaErrors")}(
|
|
1640
|
+
${use("SolanaErrorCode", "solanaErrors")}.programClientsFailedToIdentifyInstruction,
|
|
1641
|
+
{
|
|
1642
|
+
'instructionData': data,
|
|
1643
|
+
'programName': '${fragmentFromString(name)}',
|
|
1644
|
+
},
|
|
1645
|
+
);
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1648
|
+
/// A parsed instruction from the ${fragmentFromString(programName)} program.
|
|
1649
|
+
sealed class ${fragmentFromString(parsedBase)} {
|
|
1650
|
+
const ${fragmentFromString(parsedBase)}(this.instructionType);
|
|
1651
|
+
|
|
1652
|
+
final ${fragmentFromString(instructionEnum)} instructionType;
|
|
1653
|
+
}
|
|
1654
|
+
|
|
1655
|
+
${mergeFragments(parsedClasses, (cs) => cs.join("\n\n"))}
|
|
1656
|
+
|
|
1657
|
+
/// Parses a ${fragmentFromString(programName)} instruction.
|
|
1658
|
+
${fragmentFromString(parsedBase)} parse${fragmentFromString(programName)}Instruction(
|
|
1659
|
+
${use("Instruction", "solanaInstructions")} instruction,
|
|
1660
|
+
) {
|
|
1661
|
+
return switch (identify${fragmentFromString(programName)}Instruction(
|
|
1662
|
+
instruction.data ?? Uint8List(0),
|
|
1663
|
+
)) {
|
|
1664
|
+
${mergeFragments(parseBranches, (cs) => cs.join("\n"))}
|
|
1665
|
+
};
|
|
1666
|
+
}`);
|
|
1667
|
+
}
|
|
1582
1668
|
}
|
|
1583
1669
|
return mergeFragments(parts, (cs) => cs.join("\n"));
|
|
1584
1670
|
}
|
|
1671
|
+
function getInstructionDiscriminatorCondition(instruction, scope) {
|
|
1672
|
+
const discriminators = instruction.discriminators ?? [];
|
|
1673
|
+
if (discriminators.length === 0) return null;
|
|
1674
|
+
const conditions = discriminators.map((discriminator) => {
|
|
1675
|
+
switch (discriminator.kind) {
|
|
1676
|
+
case "sizeDiscriminatorNode":
|
|
1677
|
+
return fragment`data.length == ${discriminator.size}`;
|
|
1678
|
+
case "constantDiscriminatorNode": {
|
|
1679
|
+
const manifest = visitorsCore.visit(
|
|
1680
|
+
discriminator.constant.type,
|
|
1681
|
+
scope.typeManifestVisitor
|
|
1682
|
+
);
|
|
1683
|
+
const value = getValueFragment(
|
|
1684
|
+
discriminator.constant.value,
|
|
1685
|
+
manifest.type.content
|
|
1686
|
+
);
|
|
1687
|
+
if (value === null) return null;
|
|
1688
|
+
return fragment`${use("containsBytes", "solanaCodecsCore")}(data, ${manifest.encoder}.encode(${value}), ${discriminator.offset})`;
|
|
1689
|
+
}
|
|
1690
|
+
case "fieldDiscriminatorNode": {
|
|
1691
|
+
const argument = (instruction.arguments ?? []).find(
|
|
1692
|
+
(candidate) => candidate.name === discriminator.name
|
|
1693
|
+
);
|
|
1694
|
+
if (argument?.defaultValue == null) return null;
|
|
1695
|
+
const manifest = visitorsCore.visit(argument.type, scope.typeManifestVisitor);
|
|
1696
|
+
const value = getValueFragment(
|
|
1697
|
+
argument.defaultValue,
|
|
1698
|
+
manifest.type.content
|
|
1699
|
+
);
|
|
1700
|
+
if (value === null) return null;
|
|
1701
|
+
return fragment`${use("containsBytes", "solanaCodecsCore")}(data, ${manifest.encoder}.encode(${value}), ${discriminator.offset})`;
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
});
|
|
1705
|
+
if (conditions.some((condition) => condition === null)) return null;
|
|
1706
|
+
return mergeFragments(conditions, (cs) => cs.join(" && "));
|
|
1707
|
+
}
|
|
1708
|
+
function getValueFragment(value, dartType) {
|
|
1709
|
+
switch (value.kind) {
|
|
1710
|
+
case "numberValueNode":
|
|
1711
|
+
return fragmentFromString(
|
|
1712
|
+
dartType === "BigInt" ? `BigInt.from(${value.number})` : String(value.number)
|
|
1713
|
+
);
|
|
1714
|
+
case "booleanValueNode":
|
|
1715
|
+
return fragmentFromString(String(value.boolean));
|
|
1716
|
+
case "stringValueNode":
|
|
1717
|
+
return fragmentFromString(`'${value.string.replaceAll("'", "\\'")}'`);
|
|
1718
|
+
case "bytesValueNode": {
|
|
1719
|
+
const clean = value.data.replace(/^0x/, "");
|
|
1720
|
+
const bytes = clean.match(/.{1,2}/g)?.map((byte) => parseInt(byte, 16)) ?? [];
|
|
1721
|
+
return fragment`${use("Uint8List", "dartTypedData")}.fromList([${fragmentFromString(bytes.join(", "))}])`;
|
|
1722
|
+
}
|
|
1723
|
+
default:
|
|
1724
|
+
return null;
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1585
1727
|
function getTypePageFragment(node, scope) {
|
|
1586
1728
|
const name = node.name;
|
|
1587
1729
|
scope.nameApi.dataType(name);
|
|
@@ -1664,6 +1806,7 @@ function getDataEnumPageFragment(node, scope) {
|
|
|
1664
1806
|
const allVariantManifests = [];
|
|
1665
1807
|
for (let i = 0; i < enumNode.variants.length; i++) {
|
|
1666
1808
|
const variant = enumNode.variants[i];
|
|
1809
|
+
const variantName = pascalCase(variant.name);
|
|
1667
1810
|
const variantClassName = scope.nameApi.sealedClassVariant(
|
|
1668
1811
|
name,
|
|
1669
1812
|
variant.name
|
|
@@ -1680,7 +1823,7 @@ function getDataEnumPageFragment(node, scope) {
|
|
|
1680
1823
|
int get hashCode => runtimeType.hashCode;
|
|
1681
1824
|
|
|
1682
1825
|
@override
|
|
1683
|
-
String toString() => '${typeName}.${
|
|
1826
|
+
String toString() => '${typeName}.${variantName}()';
|
|
1684
1827
|
}`);
|
|
1685
1828
|
encoderVariants.push(
|
|
1686
1829
|
`(${i}, getStructEncoder(<(String, Encoder<Object?>)>[]))`
|
|
@@ -1727,7 +1870,7 @@ ${fieldDecls}
|
|
|
1727
1870
|
int get hashCode => ${hashExpression};
|
|
1728
1871
|
|
|
1729
1872
|
@override
|
|
1730
|
-
String toString() => '${typeName}.${
|
|
1873
|
+
String toString() => '${typeName}.${variantName}(${toStringFields})';
|
|
1731
1874
|
}`);
|
|
1732
1875
|
const encFields = fieldManifests.map(({ field: f, manifest }) => {
|
|
1733
1876
|
return `('${f.name}', ${manifest.encoder.content})`;
|
|
@@ -1776,7 +1919,7 @@ ${fieldDecls}
|
|
|
1776
1919
|
int get hashCode => value.hashCode;
|
|
1777
1920
|
|
|
1778
1921
|
@override
|
|
1779
|
-
String toString() => '${typeName}.${
|
|
1922
|
+
String toString() => '${typeName}.${variantName}($value)';
|
|
1780
1923
|
}`);
|
|
1781
1924
|
encoderVariants.push(
|
|
1782
1925
|
`(${i}, transformEncoder<${manifest.type.content}, Map<String, Object?>>(${manifest.encoder.content}, (Map<String, Object?> map) => map['value']! as ${manifest.type.content}))`
|
|
@@ -2220,7 +2363,7 @@ function renderVisitor(outputDir, options = {}) {
|
|
|
2220
2363
|
);
|
|
2221
2364
|
const typePathMap = {};
|
|
2222
2365
|
for (const renderPath of renderMap.keys()) {
|
|
2223
|
-
const match = renderPath.match(/^(?:.*\/)?types\/([a-
|
|
2366
|
+
const match = renderPath.match(/^(?:.*\/)?types\/([a-z0-9_]+)\.dart$/);
|
|
2224
2367
|
if (match) {
|
|
2225
2368
|
typePathMap[`definedType:${match[1]}`] = renderPath;
|
|
2226
2369
|
}
|
|
@@ -2234,7 +2377,10 @@ function renderVisitor(outputDir, options = {}) {
|
|
|
2234
2377
|
const fileDir = path.dirname(filePath);
|
|
2235
2378
|
const internalMap = {};
|
|
2236
2379
|
for (const [key, typePath] of Object.entries(typePathMap)) {
|
|
2237
|
-
if (typePath === filePath)
|
|
2380
|
+
if (typePath === filePath) {
|
|
2381
|
+
internalMap[key] = "";
|
|
2382
|
+
continue;
|
|
2383
|
+
}
|
|
2238
2384
|
let rel = path.posix.relative(fileDir, typePath);
|
|
2239
2385
|
if (!rel.startsWith(".")) {
|
|
2240
2386
|
rel = `./${rel}`;
|