@codama/renderers-js 1.3.4 → 1.4.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 +1 -1
- package/dist/index.browser.cjs +3247 -0
- package/dist/index.browser.cjs.map +1 -0
- package/dist/index.browser.mjs +3300 -0
- package/dist/index.browser.mjs.map +1 -0
- package/dist/index.node.cjs +2081 -1718
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.mjs +2015 -1657
- package/dist/index.node.mjs.map +1 -1
- package/dist/index.react-native.mjs +3300 -0
- package/dist/index.react-native.mjs.map +1 -0
- package/dist/types/fragments/accountFetchHelpers.d.ts +2 -4
- package/dist/types/fragments/accountFetchHelpers.d.ts.map +1 -1
- package/dist/types/fragments/accountPage.d.ts +8 -0
- package/dist/types/fragments/accountPage.d.ts.map +1 -0
- package/dist/types/fragments/accountPdaHelpers.d.ts +3 -5
- package/dist/types/fragments/accountPdaHelpers.d.ts.map +1 -1
- package/dist/types/fragments/accountSizeHelpers.d.ts +3 -4
- package/dist/types/fragments/accountSizeHelpers.d.ts.map +1 -1
- package/dist/types/fragments/accountType.d.ts +3 -5
- package/dist/types/fragments/accountType.d.ts.map +1 -1
- package/dist/types/fragments/discriminatorCondition.d.ts +2 -3
- package/dist/types/fragments/discriminatorCondition.d.ts.map +1 -1
- package/dist/types/fragments/discriminatorConstants.d.ts +5 -6
- package/dist/types/fragments/discriminatorConstants.d.ts.map +1 -1
- package/dist/types/fragments/errorPage.d.ts +6 -0
- package/dist/types/fragments/errorPage.d.ts.map +1 -0
- package/dist/types/fragments/index.d.ts +11 -4
- package/dist/types/fragments/index.d.ts.map +1 -1
- package/dist/types/fragments/indexPage.d.ts +6 -0
- package/dist/types/fragments/indexPage.d.ts.map +1 -0
- package/dist/types/fragments/instructionAccountMeta.d.ts +1 -1
- package/dist/types/fragments/instructionAccountMeta.d.ts.map +1 -1
- package/dist/types/fragments/instructionAccountTypeParam.d.ts +2 -3
- package/dist/types/fragments/instructionAccountTypeParam.d.ts.map +1 -1
- package/dist/types/fragments/instructionByteDelta.d.ts +3 -4
- package/dist/types/fragments/instructionByteDelta.d.ts.map +1 -1
- package/dist/types/fragments/instructionData.d.ts +3 -5
- package/dist/types/fragments/instructionData.d.ts.map +1 -1
- package/dist/types/fragments/instructionExtraArgs.d.ts +3 -5
- package/dist/types/fragments/instructionExtraArgs.d.ts.map +1 -1
- package/dist/types/fragments/instructionFunction.d.ts +3 -5
- package/dist/types/fragments/instructionFunction.d.ts.map +1 -1
- package/dist/types/fragments/instructionInputDefault.d.ts +2 -3
- package/dist/types/fragments/instructionInputDefault.d.ts.map +1 -1
- package/dist/types/fragments/instructionInputResolved.d.ts +2 -3
- package/dist/types/fragments/instructionInputResolved.d.ts.map +1 -1
- package/dist/types/fragments/instructionInputType.d.ts +2 -4
- package/dist/types/fragments/instructionInputType.d.ts.map +1 -1
- package/dist/types/fragments/instructionPage.d.ts +9 -0
- package/dist/types/fragments/instructionPage.d.ts.map +1 -0
- package/dist/types/fragments/instructionParseFunction.d.ts +2 -4
- package/dist/types/fragments/instructionParseFunction.d.ts.map +1 -1
- package/dist/types/fragments/instructionRemainingAccounts.d.ts +3 -4
- package/dist/types/fragments/instructionRemainingAccounts.d.ts.map +1 -1
- package/dist/types/fragments/instructionType.d.ts +2 -3
- package/dist/types/fragments/instructionType.d.ts.map +1 -1
- package/dist/types/fragments/pdaFunction.d.ts +2 -3
- package/dist/types/fragments/pdaFunction.d.ts.map +1 -1
- package/dist/types/fragments/pdaPage.d.ts +7 -0
- package/dist/types/fragments/pdaPage.d.ts.map +1 -0
- package/dist/types/fragments/programAccounts.d.ts +3 -4
- package/dist/types/fragments/programAccounts.d.ts.map +1 -1
- package/dist/types/fragments/programConstant.d.ts +6 -0
- package/dist/types/fragments/programConstant.d.ts.map +1 -0
- package/dist/types/fragments/programInstructions.d.ts +3 -4
- package/dist/types/fragments/programInstructions.d.ts.map +1 -1
- package/dist/types/fragments/programPage.d.ts +6 -0
- package/dist/types/fragments/programPage.d.ts.map +1 -0
- package/dist/types/fragments/rootIndexPage.d.ts +10 -0
- package/dist/types/fragments/rootIndexPage.d.ts.map +1 -0
- package/dist/types/fragments/sharedPage.d.ts +3 -0
- package/dist/types/fragments/sharedPage.d.ts.map +1 -0
- package/dist/types/fragments/type.d.ts +2 -4
- package/dist/types/fragments/type.d.ts.map +1 -1
- package/dist/types/fragments/typeCodec.d.ts +2 -4
- package/dist/types/fragments/typeCodec.d.ts.map +1 -1
- package/dist/types/fragments/typeDecoder.d.ts +2 -4
- package/dist/types/fragments/typeDecoder.d.ts.map +1 -1
- package/dist/types/fragments/typeDiscriminatedUnionHelpers.d.ts +3 -4
- package/dist/types/fragments/typeDiscriminatedUnionHelpers.d.ts.map +1 -1
- package/dist/types/fragments/typeEncoder.d.ts +2 -4
- package/dist/types/fragments/typeEncoder.d.ts.map +1 -1
- package/dist/types/fragments/typePage.d.ts +7 -0
- package/dist/types/fragments/typePage.d.ts.map +1 -0
- package/dist/types/fragments/typeWithCodec.d.ts +2 -4
- package/dist/types/fragments/typeWithCodec.d.ts.map +1 -1
- package/dist/types/index.d.ts +5 -7
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/utils/fragment.d.ts +24 -0
- package/dist/types/utils/fragment.d.ts.map +1 -0
- package/dist/types/utils/importMap.d.ts +17 -0
- package/dist/types/utils/importMap.d.ts.map +1 -0
- package/dist/types/utils/index.d.ts +5 -1
- package/dist/types/utils/index.d.ts.map +1 -1
- package/dist/types/utils/nameTransformers.d.ts.map +1 -0
- package/dist/types/utils/options.d.ts +40 -0
- package/dist/types/utils/options.d.ts.map +1 -0
- package/dist/types/{TypeManifest.d.ts → utils/typeManifest.d.ts} +6 -6
- package/dist/types/utils/typeManifest.d.ts.map +1 -0
- package/dist/types/visitors/getRenderMapVisitor.d.ts +3 -0
- package/dist/types/visitors/getRenderMapVisitor.d.ts.map +1 -0
- package/dist/types/visitors/getTypeManifestVisitor.d.ts +21 -0
- package/dist/types/visitors/getTypeManifestVisitor.d.ts.map +1 -0
- package/dist/types/visitors/index.d.ts +4 -0
- package/dist/types/visitors/index.d.ts.map +1 -0
- package/dist/types/visitors/renderVisitor.d.ts +3 -0
- package/dist/types/visitors/renderVisitor.d.ts.map +1 -0
- package/package.json +22 -13
- package/dist/templates/fragments/accountFetchHelpers.njk +0 -43
- package/dist/templates/fragments/accountPdaHelpers.njk +0 -25
- package/dist/templates/fragments/accountSizeHelpers.njk +0 -3
- package/dist/templates/fragments/instructionExtraArgs.njk +0 -4
- package/dist/templates/fragments/instructionFunction.njk +0 -62
- package/dist/templates/fragments/instructionInputType.njk +0 -16
- package/dist/templates/fragments/instructionParseFunction.njk +0 -81
- package/dist/templates/fragments/instructionType.njk +0 -18
- package/dist/templates/fragments/pdaFunction.njk +0 -33
- package/dist/templates/fragments/program.njk +0 -3
- package/dist/templates/fragments/programErrors.njk +0 -36
- package/dist/templates/fragments/type.njk +0 -12
- package/dist/templates/fragments/typeCodec.njk +0 -6
- package/dist/templates/fragments/typeDecoder.njk +0 -6
- package/dist/templates/fragments/typeDiscriminatedUnionHelpers.njk +0 -23
- package/dist/templates/fragments/typeEncoder.njk +0 -6
- package/dist/templates/layout.njk +0 -9
- package/dist/templates/macros.njk +0 -12
- package/dist/templates/pages/accountsIndex.njk +0 -9
- package/dist/templates/pages/accountsPage.njk +0 -12
- package/dist/templates/pages/definedTypesIndex.njk +0 -9
- package/dist/templates/pages/definedTypesPage.njk +0 -9
- package/dist/templates/pages/errorsIndex.njk +0 -9
- package/dist/templates/pages/errorsPage.njk +0 -8
- package/dist/templates/pages/instructionsIndex.njk +0 -9
- package/dist/templates/pages/instructionsPage.njk +0 -14
- package/dist/templates/pages/pdasIndex.njk +0 -9
- package/dist/templates/pages/pdasPage.njk +0 -8
- package/dist/templates/pages/programsIndex.njk +0 -9
- package/dist/templates/pages/programsPage.njk +0 -10
- package/dist/templates/pages/rootIndex.njk +0 -26
- package/dist/templates/pages/sharedPage.njk +0 -106
- package/dist/types/ImportMap.d.ts +0 -15
- package/dist/types/ImportMap.d.ts.map +0 -1
- package/dist/types/TypeManifest.d.ts.map +0 -1
- package/dist/types/fragments/common.d.ts +0 -25
- package/dist/types/fragments/common.d.ts.map +0 -1
- package/dist/types/fragments/program.d.ts +0 -7
- package/dist/types/fragments/program.d.ts.map +0 -1
- package/dist/types/fragments/programErrors.d.ts +0 -7
- package/dist/types/fragments/programErrors.d.ts.map +0 -1
- package/dist/types/getRenderMapVisitor.d.ts +0 -31
- package/dist/types/getRenderMapVisitor.d.ts.map +0 -1
- package/dist/types/getTypeManifestVisitor.d.ts +0 -16
- package/dist/types/getTypeManifestVisitor.d.ts.map +0 -1
- package/dist/types/nameTransformers.d.ts.map +0 -1
- package/dist/types/renderVisitor.d.ts +0 -11
- package/dist/types/renderVisitor.d.ts.map +0 -1
- package/dist/types/utils/render.d.ts +0 -4
- package/dist/types/utils/render.d.ts.map +0 -1
- /package/dist/types/{nameTransformers.d.ts → utils/nameTransformers.d.ts} +0 -0
|
@@ -0,0 +1,3300 @@
|
|
|
1
|
+
// src/utils/importMap.ts
|
|
2
|
+
var DEFAULT_EXTERNAL_MODULE_MAP = {
|
|
3
|
+
solanaAccounts: "@solana/kit",
|
|
4
|
+
solanaAddresses: "@solana/kit",
|
|
5
|
+
solanaCodecsCore: "@solana/kit",
|
|
6
|
+
solanaCodecsDataStructures: "@solana/kit",
|
|
7
|
+
solanaCodecsNumbers: "@solana/kit",
|
|
8
|
+
solanaCodecsStrings: "@solana/kit",
|
|
9
|
+
solanaErrors: "@solana/kit",
|
|
10
|
+
solanaInstructions: "@solana/kit",
|
|
11
|
+
solanaOptions: "@solana/kit",
|
|
12
|
+
solanaPrograms: "@solana/kit",
|
|
13
|
+
solanaRpcTypes: "@solana/kit",
|
|
14
|
+
solanaSigners: "@solana/kit"
|
|
15
|
+
};
|
|
16
|
+
var DEFAULT_GRANULAR_EXTERNAL_MODULE_MAP = {
|
|
17
|
+
solanaAccounts: "@solana/accounts",
|
|
18
|
+
solanaAddresses: "@solana/addresses",
|
|
19
|
+
solanaCodecsCore: "@solana/codecs",
|
|
20
|
+
solanaCodecsDataStructures: "@solana/codecs",
|
|
21
|
+
solanaCodecsNumbers: "@solana/codecs",
|
|
22
|
+
solanaCodecsStrings: "@solana/codecs",
|
|
23
|
+
solanaErrors: "@solana/errors",
|
|
24
|
+
solanaInstructions: "@solana/instructions",
|
|
25
|
+
solanaOptions: "@solana/codecs",
|
|
26
|
+
solanaPrograms: "@solana/programs",
|
|
27
|
+
solanaRpcTypes: "@solana/rpc-types",
|
|
28
|
+
solanaSigners: "@solana/signers"
|
|
29
|
+
};
|
|
30
|
+
var DEFAULT_INTERNAL_MODULE_MAP = {
|
|
31
|
+
errors: "../errors",
|
|
32
|
+
generated: "..",
|
|
33
|
+
generatedAccounts: "../accounts",
|
|
34
|
+
generatedErrors: "../errors",
|
|
35
|
+
generatedInstructions: "../instructions",
|
|
36
|
+
generatedPdas: "../pdas",
|
|
37
|
+
generatedPrograms: "../programs",
|
|
38
|
+
generatedTypes: "../types",
|
|
39
|
+
hooked: "../../hooked",
|
|
40
|
+
shared: "../shared",
|
|
41
|
+
types: "../types"
|
|
42
|
+
};
|
|
43
|
+
function createImportMap() {
|
|
44
|
+
return Object.freeze(/* @__PURE__ */ new Map());
|
|
45
|
+
}
|
|
46
|
+
function parseImportInput(input) {
|
|
47
|
+
const matches = input.match(/^(type )?([^ ]+)(?: as (.+))?$/);
|
|
48
|
+
if (!matches) return Object.freeze({ importedIdentifier: input, isType: false, usedIdentifier: input });
|
|
49
|
+
const [_, isType, name, alias] = matches;
|
|
50
|
+
return Object.freeze({
|
|
51
|
+
importedIdentifier: name,
|
|
52
|
+
isType: !!isType,
|
|
53
|
+
usedIdentifier: alias ?? name
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
function addToImportMap(importMap, module, imports) {
|
|
57
|
+
const parsedImports = imports.map(parseImportInput).map((i) => [i.usedIdentifier, i]);
|
|
58
|
+
return mergeImportMaps([importMap, /* @__PURE__ */ new Map([[module, new Map(parsedImports)]])]);
|
|
59
|
+
}
|
|
60
|
+
function removeFromImportMap(importMap, module, usedIdentifiers) {
|
|
61
|
+
const newMap = new Map(importMap);
|
|
62
|
+
const newModuleMap = new Map(newMap.get(module));
|
|
63
|
+
usedIdentifiers.forEach((usedIdentifier) => {
|
|
64
|
+
newModuleMap.delete(usedIdentifier);
|
|
65
|
+
});
|
|
66
|
+
if (newModuleMap.size === 0) {
|
|
67
|
+
newMap.delete(module);
|
|
68
|
+
} else {
|
|
69
|
+
newMap.set(module, newModuleMap);
|
|
70
|
+
}
|
|
71
|
+
return Object.freeze(newMap);
|
|
72
|
+
}
|
|
73
|
+
function mergeImportMaps(importMaps) {
|
|
74
|
+
if (importMaps.length === 0) return createImportMap();
|
|
75
|
+
if (importMaps.length === 1) return importMaps[0];
|
|
76
|
+
const mergedMap = new Map(importMaps[0]);
|
|
77
|
+
for (const map of importMaps.slice(1)) {
|
|
78
|
+
for (const [module, imports] of map) {
|
|
79
|
+
const mergedModuleMap = mergedMap.get(module) ?? /* @__PURE__ */ new Map();
|
|
80
|
+
for (const [usedIdentifier, importInfo] of imports) {
|
|
81
|
+
const existingImportInfo = mergedModuleMap.get(usedIdentifier);
|
|
82
|
+
const shouldOverwriteTypeOnly = existingImportInfo && existingImportInfo.importedIdentifier === importInfo.importedIdentifier && existingImportInfo.isType && !importInfo.isType;
|
|
83
|
+
if (!existingImportInfo || shouldOverwriteTypeOnly) {
|
|
84
|
+
mergedModuleMap.set(usedIdentifier, importInfo);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
mergedMap.set(module, mergedModuleMap);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return Object.freeze(mergedMap);
|
|
91
|
+
}
|
|
92
|
+
function importMapToString(importMap, dependencyMap = {}, useGranularImports = false) {
|
|
93
|
+
const resolvedMap = resolveImportMapModules(importMap, dependencyMap, useGranularImports);
|
|
94
|
+
return [...resolvedMap.entries()].sort(([a], [b]) => {
|
|
95
|
+
const relative = Number(a.startsWith(".")) - Number(b.startsWith("."));
|
|
96
|
+
if (relative !== 0) return relative;
|
|
97
|
+
return a.localeCompare(b);
|
|
98
|
+
}).map(([module, imports]) => {
|
|
99
|
+
const innerImports = [...imports.values()].map(importInfoToString).sort((a, b) => a.localeCompare(b)).join(", ");
|
|
100
|
+
return `import { ${innerImports} } from '${module}';`;
|
|
101
|
+
}).join("\n");
|
|
102
|
+
}
|
|
103
|
+
function resolveImportMapModules(importMap, dependencyMap, useGranularImports) {
|
|
104
|
+
const dependencyMapWithDefaults = {
|
|
105
|
+
...useGranularImports ? DEFAULT_GRANULAR_EXTERNAL_MODULE_MAP : DEFAULT_EXTERNAL_MODULE_MAP,
|
|
106
|
+
...DEFAULT_INTERNAL_MODULE_MAP,
|
|
107
|
+
...dependencyMap
|
|
108
|
+
};
|
|
109
|
+
return mergeImportMaps(
|
|
110
|
+
[...importMap.entries()].map(([module, imports]) => {
|
|
111
|
+
const resolvedModule = dependencyMapWithDefaults[module] ?? module;
|
|
112
|
+
return /* @__PURE__ */ new Map([[resolvedModule, imports]]);
|
|
113
|
+
})
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
function importInfoToString({ importedIdentifier, isType, usedIdentifier }) {
|
|
117
|
+
const alias = importedIdentifier !== usedIdentifier ? ` as ${usedIdentifier}` : "";
|
|
118
|
+
return `${isType ? "type " : ""}${importedIdentifier}${alias}`;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// src/utils/nameTransformers.ts
|
|
122
|
+
import { camelCase, capitalize, kebabCase, pascalCase, snakeCase, titleCase } from "@codama/nodes";
|
|
123
|
+
function getNameApi(transformers) {
|
|
124
|
+
const helpers = {
|
|
125
|
+
camelCase,
|
|
126
|
+
capitalize,
|
|
127
|
+
kebabCase,
|
|
128
|
+
pascalCase,
|
|
129
|
+
snakeCase,
|
|
130
|
+
titleCase
|
|
131
|
+
};
|
|
132
|
+
return Object.fromEntries(
|
|
133
|
+
Object.entries(transformers).map(([key, transformer]) => [key, (name) => transformer(name, helpers)])
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
var DEFAULT_NAME_TRANSFORMERS = {
|
|
137
|
+
accountDecodeFunction: (name) => `decode${pascalCase(name)}`,
|
|
138
|
+
accountFetchAllFunction: (name) => `fetchAll${pascalCase(name)}`,
|
|
139
|
+
accountFetchAllMaybeFunction: (name) => `fetchAllMaybe${pascalCase(name)}`,
|
|
140
|
+
accountFetchFromSeedsFunction: (name) => `fetch${pascalCase(name)}FromSeeds`,
|
|
141
|
+
accountFetchFunction: (name) => `fetch${pascalCase(name)}`,
|
|
142
|
+
accountFetchMaybeFromSeedsFunction: (name) => `fetchMaybe${pascalCase(name)}FromSeeds`,
|
|
143
|
+
accountFetchMaybeFunction: (name) => `fetchMaybe${pascalCase(name)}`,
|
|
144
|
+
accountGetSizeFunction: (name) => `get${pascalCase(name)}Size`,
|
|
145
|
+
codecFunction: (name) => `get${pascalCase(name)}Codec`,
|
|
146
|
+
constant: (name) => snakeCase(name).toUpperCase(),
|
|
147
|
+
constantFunction: (name) => `get${pascalCase(name)}Bytes`,
|
|
148
|
+
dataArgsType: (name) => `${pascalCase(name)}Args`,
|
|
149
|
+
dataType: (name) => `${pascalCase(name)}`,
|
|
150
|
+
decoderFunction: (name) => `get${pascalCase(name)}Decoder`,
|
|
151
|
+
discriminatedUnionDiscriminator: () => "__kind",
|
|
152
|
+
discriminatedUnionFunction: (name) => `${camelCase(name)}`,
|
|
153
|
+
discriminatedUnionVariant: (name) => `${pascalCase(name)}`,
|
|
154
|
+
encoderFunction: (name) => `get${pascalCase(name)}Encoder`,
|
|
155
|
+
enumVariant: (name) => `${pascalCase(name)}`,
|
|
156
|
+
instructionAsyncFunction: (name) => `get${pascalCase(name)}InstructionAsync`,
|
|
157
|
+
instructionAsyncInputType: (name) => `${pascalCase(name)}AsyncInput`,
|
|
158
|
+
instructionDataType: (name) => `${pascalCase(name)}InstructionData`,
|
|
159
|
+
instructionExtraType: (name) => `${pascalCase(name)}InstructionExtra`,
|
|
160
|
+
instructionParseFunction: (name) => `parse${pascalCase(name)}Instruction`,
|
|
161
|
+
instructionParsedType: (name) => `Parsed${pascalCase(name)}Instruction`,
|
|
162
|
+
instructionSyncFunction: (name) => `get${pascalCase(name)}Instruction`,
|
|
163
|
+
instructionSyncInputType: (name) => `${pascalCase(name)}Input`,
|
|
164
|
+
instructionType: (name) => `${pascalCase(name)}Instruction`,
|
|
165
|
+
isDiscriminatedUnionFunction: (name) => `is${pascalCase(name)}`,
|
|
166
|
+
pdaFindFunction: (name) => `find${pascalCase(name)}Pda`,
|
|
167
|
+
pdaSeedsType: (name) => `${pascalCase(name)}Seeds`,
|
|
168
|
+
programAccountsEnum: (name) => `${pascalCase(name)}Account`,
|
|
169
|
+
programAccountsEnumVariant: (name) => `${pascalCase(name)}`,
|
|
170
|
+
programAccountsIdentifierFunction: (name) => `identify${pascalCase(name)}Account`,
|
|
171
|
+
programAddressConstant: (name) => `${snakeCase(name).toUpperCase()}_PROGRAM_ADDRESS`,
|
|
172
|
+
programErrorConstant: (name) => snakeCase(name).toUpperCase(),
|
|
173
|
+
programErrorConstantPrefix: (name) => `${snakeCase(name).toUpperCase()}_ERROR__`,
|
|
174
|
+
programErrorMessagesMap: (name) => `${camelCase(name)}ErrorMessages`,
|
|
175
|
+
programErrorUnion: (name) => `${pascalCase(name)}Error`,
|
|
176
|
+
programGetErrorMessageFunction: (name) => `get${pascalCase(name)}ErrorMessage`,
|
|
177
|
+
programInstructionsEnum: (name) => `${pascalCase(name)}Instruction`,
|
|
178
|
+
programInstructionsEnumVariant: (name) => `${pascalCase(name)}`,
|
|
179
|
+
programInstructionsIdentifierFunction: (name) => `identify${pascalCase(name)}Instruction`,
|
|
180
|
+
programInstructionsParsedUnionType: (name) => `Parsed${pascalCase(name)}Instruction`,
|
|
181
|
+
programIsErrorFunction: (name) => `is${pascalCase(name)}Error`,
|
|
182
|
+
resolverFunction: (name) => `${camelCase(name)}`
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
// src/utils/fragment.ts
|
|
186
|
+
import { createFragmentTemplate } from "@codama/renderers-core";
|
|
187
|
+
function createFragment(content) {
|
|
188
|
+
return Object.freeze({ content, features: /* @__PURE__ */ new Set(), imports: createImportMap() });
|
|
189
|
+
}
|
|
190
|
+
function isFragment(value) {
|
|
191
|
+
return typeof value === "object" && value !== null && "content" in value;
|
|
192
|
+
}
|
|
193
|
+
function fragment(template, ...items) {
|
|
194
|
+
return createFragmentTemplate(template, items, isFragment, mergeFragments);
|
|
195
|
+
}
|
|
196
|
+
function mergeFragments(fragments, mergeContent) {
|
|
197
|
+
const filteredFragments = fragments.filter((f) => f !== void 0);
|
|
198
|
+
return Object.freeze({
|
|
199
|
+
content: mergeContent(filteredFragments.map((fragment2) => fragment2.content)),
|
|
200
|
+
features: new Set(filteredFragments.flatMap((f) => [...f.features])),
|
|
201
|
+
imports: mergeImportMaps(filteredFragments.map((f) => f.imports))
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
function use(importInput, module) {
|
|
205
|
+
const importInfo = parseImportInput(importInput);
|
|
206
|
+
return addFragmentImports(createFragment(importInfo.usedIdentifier), module, [importInput]);
|
|
207
|
+
}
|
|
208
|
+
function mergeFragmentImports(fragment2, importMaps) {
|
|
209
|
+
return Object.freeze({ ...fragment2, imports: mergeImportMaps([fragment2.imports, ...importMaps]) });
|
|
210
|
+
}
|
|
211
|
+
function addFragmentImports(fragment2, module, importInputs) {
|
|
212
|
+
return Object.freeze({ ...fragment2, imports: addToImportMap(fragment2.imports, module, importInputs) });
|
|
213
|
+
}
|
|
214
|
+
function removeFragmentImports(fragment2, module, usedIdentifiers) {
|
|
215
|
+
return Object.freeze({ ...fragment2, imports: removeFromImportMap(fragment2.imports, module, usedIdentifiers) });
|
|
216
|
+
}
|
|
217
|
+
function addFragmentFeatures(fragment2, features) {
|
|
218
|
+
return Object.freeze({ ...fragment2, features: /* @__PURE__ */ new Set([...fragment2.features, ...features]) });
|
|
219
|
+
}
|
|
220
|
+
function getExportAllFragment(module) {
|
|
221
|
+
return fragment`export * from '${module}';`;
|
|
222
|
+
}
|
|
223
|
+
function getDocblockFragment(lines, withLineJump = false) {
|
|
224
|
+
const lineJump = withLineJump ? "\n" : "";
|
|
225
|
+
if (lines.length === 0) return;
|
|
226
|
+
if (lines.length === 1) return fragment`/** ${lines[0]} */${lineJump}`;
|
|
227
|
+
const prefixedLines = lines.map((line) => line ? ` * ${line}` : " *");
|
|
228
|
+
return fragment`/**\n${prefixedLines.join("\n")}\n */${lineJump}`;
|
|
229
|
+
}
|
|
230
|
+
function getPageFragment(page, scope) {
|
|
231
|
+
const header = getDocblockFragment([
|
|
232
|
+
"This code was AUTOGENERATED using the Codama library.",
|
|
233
|
+
"Please DO NOT EDIT THIS FILE, instead use visitors",
|
|
234
|
+
"to add features, then rerun Codama to update it.",
|
|
235
|
+
"",
|
|
236
|
+
"@see https://github.com/codama-idl/codama"
|
|
237
|
+
]);
|
|
238
|
+
const imports = page.imports.size === 0 ? void 0 : fragment`${importMapToString(page.imports, scope.dependencyMap, scope.useGranularImports)}`;
|
|
239
|
+
return mergeFragments([header, imports, page], (cs) => cs.join("\n\n"));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// src/utils/typeManifest.ts
|
|
243
|
+
function typeManifest(input = {}) {
|
|
244
|
+
return Object.freeze({
|
|
245
|
+
decoder: fragment``,
|
|
246
|
+
encoder: fragment``,
|
|
247
|
+
isEnum: false,
|
|
248
|
+
looseType: fragment``,
|
|
249
|
+
strictType: fragment``,
|
|
250
|
+
value: fragment``,
|
|
251
|
+
...input
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
function mergeTypeManifests(manifests, options = {}) {
|
|
255
|
+
const { mergeTypes, mergeCodecs, mergeValues } = options;
|
|
256
|
+
const merge = (fragmentFn, mergeFn) => mergeFn ? mergeFragments(manifests.map(fragmentFn), mergeFn) : fragment``;
|
|
257
|
+
return Object.freeze({
|
|
258
|
+
decoder: merge((m) => m.decoder, mergeCodecs),
|
|
259
|
+
encoder: merge((m) => m.encoder, mergeCodecs),
|
|
260
|
+
isEnum: false,
|
|
261
|
+
looseType: merge((m) => m.looseType, mergeTypes),
|
|
262
|
+
strictType: merge((m) => m.strictType, mergeTypes),
|
|
263
|
+
value: merge((m) => m.value, mergeValues)
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// src/visitors/getRenderMapVisitor.ts
|
|
268
|
+
import {
|
|
269
|
+
camelCase as camelCase14,
|
|
270
|
+
getAllAccounts,
|
|
271
|
+
getAllDefinedTypes,
|
|
272
|
+
getAllInstructionsWithSubs as getAllInstructionsWithSubs2,
|
|
273
|
+
getAllPdas,
|
|
274
|
+
getAllPrograms
|
|
275
|
+
} from "@codama/nodes";
|
|
276
|
+
import { createRenderMap, mergeRenderMaps } from "@codama/renderers-core";
|
|
277
|
+
import {
|
|
278
|
+
extendVisitor as extendVisitor2,
|
|
279
|
+
getByteSizeVisitor,
|
|
280
|
+
getResolvedInstructionInputsVisitor,
|
|
281
|
+
LinkableDictionary as LinkableDictionary3,
|
|
282
|
+
NodeStack as NodeStack2,
|
|
283
|
+
pipe as pipe16,
|
|
284
|
+
recordLinkablesOnFirstVisitVisitor,
|
|
285
|
+
recordNodeStackVisitor as recordNodeStackVisitor2,
|
|
286
|
+
staticVisitor as staticVisitor2,
|
|
287
|
+
visit as visit9
|
|
288
|
+
} from "@codama/visitors-core";
|
|
289
|
+
|
|
290
|
+
// src/fragments/accountFetchHelpers.ts
|
|
291
|
+
import { getLastNodeFromPath, pipe } from "@codama/visitors-core";
|
|
292
|
+
|
|
293
|
+
// src/utils/async.ts
|
|
294
|
+
import {
|
|
295
|
+
accountValueNode,
|
|
296
|
+
argumentValueNode,
|
|
297
|
+
isNode
|
|
298
|
+
} from "@codama/nodes";
|
|
299
|
+
import { deduplicateInstructionDependencies } from "@codama/visitors-core";
|
|
300
|
+
function hasAsyncFunction(instructionNode, resolvedInputs, asyncResolvers) {
|
|
301
|
+
const hasByteDeltasAsync = (instructionNode.byteDeltas ?? []).some(
|
|
302
|
+
({ value }) => isNode(value, "resolverValueNode") && asyncResolvers.includes(value.name)
|
|
303
|
+
);
|
|
304
|
+
const hasRemainingAccountsAsync = (instructionNode.remainingAccounts ?? []).some(
|
|
305
|
+
({ value }) => isNode(value, "resolverValueNode") && asyncResolvers.includes(value.name)
|
|
306
|
+
);
|
|
307
|
+
return hasAsyncDefaultValues(resolvedInputs, asyncResolvers) || hasByteDeltasAsync || hasRemainingAccountsAsync;
|
|
308
|
+
}
|
|
309
|
+
function hasAsyncDefaultValues(resolvedInputs, asyncResolvers) {
|
|
310
|
+
return resolvedInputs.some(
|
|
311
|
+
(input) => !!input.defaultValue && isAsyncDefaultValue(input.defaultValue, asyncResolvers)
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
function isAsyncDefaultValue(defaultValue, asyncResolvers) {
|
|
315
|
+
switch (defaultValue.kind) {
|
|
316
|
+
case "pdaValueNode":
|
|
317
|
+
return true;
|
|
318
|
+
case "resolverValueNode":
|
|
319
|
+
return asyncResolvers.includes(defaultValue.name);
|
|
320
|
+
case "conditionalValueNode":
|
|
321
|
+
return isAsyncDefaultValue(defaultValue.condition, asyncResolvers) || (defaultValue.ifFalse == null ? false : isAsyncDefaultValue(defaultValue.ifFalse, asyncResolvers)) || (defaultValue.ifTrue == null ? false : isAsyncDefaultValue(defaultValue.ifTrue, asyncResolvers));
|
|
322
|
+
default:
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
function getInstructionDependencies(input, asyncResolvers, useAsync) {
|
|
327
|
+
if (isNode(input, "instructionNode")) {
|
|
328
|
+
return deduplicateInstructionDependencies([
|
|
329
|
+
...input.accounts.flatMap((x) => getInstructionDependencies(x, asyncResolvers, useAsync)),
|
|
330
|
+
...input.arguments.flatMap((x) => getInstructionDependencies(x, asyncResolvers, useAsync)),
|
|
331
|
+
...(input.extraArguments ?? []).flatMap((x) => getInstructionDependencies(x, asyncResolvers, useAsync))
|
|
332
|
+
]);
|
|
333
|
+
}
|
|
334
|
+
if (!input.defaultValue) return [];
|
|
335
|
+
const getNestedDependencies = (defaultValue) => {
|
|
336
|
+
if (!defaultValue) return [];
|
|
337
|
+
return getInstructionDependencies({ ...input, defaultValue }, asyncResolvers, useAsync);
|
|
338
|
+
};
|
|
339
|
+
if (isNode(input.defaultValue, ["accountValueNode", "accountBumpValueNode"])) {
|
|
340
|
+
return [accountValueNode(input.defaultValue.name)];
|
|
341
|
+
}
|
|
342
|
+
if (isNode(input.defaultValue, ["argumentValueNode"])) {
|
|
343
|
+
return [argumentValueNode(input.defaultValue.name)];
|
|
344
|
+
}
|
|
345
|
+
if (isNode(input.defaultValue, "pdaValueNode")) {
|
|
346
|
+
const dependencies = /* @__PURE__ */ new Map();
|
|
347
|
+
input.defaultValue.seeds.forEach((seed) => {
|
|
348
|
+
if (isNode(seed.value, ["accountValueNode", "argumentValueNode"])) {
|
|
349
|
+
dependencies.set(seed.value.name, { ...seed.value });
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
return [...dependencies.values()];
|
|
353
|
+
}
|
|
354
|
+
if (isNode(input.defaultValue, "resolverValueNode")) {
|
|
355
|
+
const isSynchronousResolver = !asyncResolvers.includes(input.defaultValue.name);
|
|
356
|
+
if (useAsync || isSynchronousResolver) {
|
|
357
|
+
return input.defaultValue.dependsOn ?? [];
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (isNode(input.defaultValue, "conditionalValueNode")) {
|
|
361
|
+
return deduplicateInstructionDependencies([
|
|
362
|
+
...getNestedDependencies(input.defaultValue.condition),
|
|
363
|
+
...getNestedDependencies(input.defaultValue.ifTrue),
|
|
364
|
+
...getNestedDependencies(input.defaultValue.ifFalse)
|
|
365
|
+
]);
|
|
366
|
+
}
|
|
367
|
+
return [];
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// src/utils/codecs.ts
|
|
371
|
+
import { getBase16Encoder, getBase58Encoder, getBase64Encoder, getUtf8Encoder } from "@solana/codecs-strings";
|
|
372
|
+
function getBytesFromBytesValueNode(node) {
|
|
373
|
+
switch (node.encoding) {
|
|
374
|
+
case "utf8":
|
|
375
|
+
return getUtf8Encoder().encode(node.data);
|
|
376
|
+
case "base16":
|
|
377
|
+
return getBase16Encoder().encode(node.data);
|
|
378
|
+
case "base58":
|
|
379
|
+
return getBase58Encoder().encode(node.data);
|
|
380
|
+
case "base64":
|
|
381
|
+
default:
|
|
382
|
+
return getBase64Encoder().encode(node.data);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// src/utils/customData.ts
|
|
387
|
+
import {
|
|
388
|
+
camelCase as camelCase2,
|
|
389
|
+
definedTypeLinkNode,
|
|
390
|
+
definedTypeNode,
|
|
391
|
+
isNode as isNode2,
|
|
392
|
+
structTypeNodeFromInstructionArgumentNodes
|
|
393
|
+
} from "@codama/nodes";
|
|
394
|
+
var parseCustomDataOptions = (customDataOptions, defaultSuffix) => new Map(
|
|
395
|
+
customDataOptions.map((o) => {
|
|
396
|
+
const options = typeof o === "string" ? { name: o } : o;
|
|
397
|
+
const importAs = camelCase2(options.importAs ?? `${options.name}${defaultSuffix}`);
|
|
398
|
+
const importFrom = options.importFrom ?? "hooked";
|
|
399
|
+
return [
|
|
400
|
+
camelCase2(options.name),
|
|
401
|
+
{
|
|
402
|
+
extract: options.extract ?? false,
|
|
403
|
+
extractAs: options.extractAs ? camelCase2(options.extractAs) : importAs,
|
|
404
|
+
importAs,
|
|
405
|
+
importFrom,
|
|
406
|
+
linkNode: definedTypeLinkNode(importAs)
|
|
407
|
+
}
|
|
408
|
+
];
|
|
409
|
+
})
|
|
410
|
+
);
|
|
411
|
+
var getDefinedTypeNodesToExtract = (nodes, parsedCustomDataOptions) => nodes.flatMap((node) => {
|
|
412
|
+
const options = parsedCustomDataOptions.get(node.name);
|
|
413
|
+
if (!options || !options.extract) return [];
|
|
414
|
+
if (isNode2(node, "accountNode")) {
|
|
415
|
+
return [definedTypeNode({ name: options.extractAs, type: { ...node.data } })];
|
|
416
|
+
}
|
|
417
|
+
return [
|
|
418
|
+
definedTypeNode({
|
|
419
|
+
name: options.extractAs,
|
|
420
|
+
type: structTypeNodeFromInstructionArgumentNodes(node.arguments)
|
|
421
|
+
})
|
|
422
|
+
];
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
// src/utils/linkOverrides.ts
|
|
426
|
+
import { CODAMA_ERROR__UNEXPECTED_NODE_KIND, CodamaError } from "@codama/errors";
|
|
427
|
+
function getImportFromFactory(overrides, customAccountData, customInstructionData) {
|
|
428
|
+
const customDataOverrides = Object.fromEntries(
|
|
429
|
+
[...customAccountData.values(), ...customInstructionData.values()].map(({ importFrom, importAs }) => [
|
|
430
|
+
importAs,
|
|
431
|
+
importFrom
|
|
432
|
+
])
|
|
433
|
+
);
|
|
434
|
+
const linkOverrides = {
|
|
435
|
+
accounts: overrides.accounts ?? {},
|
|
436
|
+
definedTypes: { ...customDataOverrides, ...overrides.definedTypes },
|
|
437
|
+
instructions: overrides.instructions ?? {},
|
|
438
|
+
pdas: overrides.pdas ?? {},
|
|
439
|
+
programs: overrides.programs ?? {},
|
|
440
|
+
resolvers: overrides.resolvers ?? {}
|
|
441
|
+
};
|
|
442
|
+
return (node) => {
|
|
443
|
+
const kind = node.kind;
|
|
444
|
+
switch (kind) {
|
|
445
|
+
case "accountLinkNode":
|
|
446
|
+
return linkOverrides.accounts[node.name] ?? "generatedAccounts";
|
|
447
|
+
case "definedTypeLinkNode":
|
|
448
|
+
return linkOverrides.definedTypes[node.name] ?? "generatedTypes";
|
|
449
|
+
case "instructionLinkNode":
|
|
450
|
+
return linkOverrides.instructions[node.name] ?? "generatedInstructions";
|
|
451
|
+
case "pdaLinkNode":
|
|
452
|
+
return linkOverrides.pdas[node.name] ?? "generatedPdas";
|
|
453
|
+
case "programLinkNode":
|
|
454
|
+
return linkOverrides.programs[node.name] ?? "generatedPrograms";
|
|
455
|
+
case "resolverValueNode":
|
|
456
|
+
return linkOverrides.resolvers[node.name] ?? "hooked";
|
|
457
|
+
default:
|
|
458
|
+
throw new CodamaError(CODAMA_ERROR__UNEXPECTED_NODE_KIND, {
|
|
459
|
+
expectedKinds: [
|
|
460
|
+
"AccountLinkNode",
|
|
461
|
+
"DefinedTypeLinkNode",
|
|
462
|
+
"InstructionLinkNode",
|
|
463
|
+
"PdaLinkNode",
|
|
464
|
+
"ProgramLinkNode",
|
|
465
|
+
"resolverValueNode"
|
|
466
|
+
],
|
|
467
|
+
kind,
|
|
468
|
+
node
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// src/fragments/accountFetchHelpers.ts
|
|
475
|
+
function getAccountFetchHelpersFragment(scope) {
|
|
476
|
+
const { accountPath, typeManifest: typeManifest2, nameApi, customAccountData } = scope;
|
|
477
|
+
const accountNode = getLastNodeFromPath(accountPath);
|
|
478
|
+
const decodeFunction = nameApi.accountDecodeFunction(accountNode.name);
|
|
479
|
+
const fetchAllFunction = nameApi.accountFetchAllFunction(accountNode.name);
|
|
480
|
+
const fetchAllMaybeFunction = nameApi.accountFetchAllMaybeFunction(accountNode.name);
|
|
481
|
+
const fetchFunction = nameApi.accountFetchFunction(accountNode.name);
|
|
482
|
+
const fetchMaybeFunction = nameApi.accountFetchMaybeFunction(accountNode.name);
|
|
483
|
+
const hasCustomData = customAccountData.has(accountNode.name);
|
|
484
|
+
const accountType = hasCustomData ? typeManifest2.strictType : nameApi.dataType(accountNode.name);
|
|
485
|
+
const decoderFunction = hasCustomData ? typeManifest2.decoder : `${nameApi.decoderFunction(accountNode.name)}()`;
|
|
486
|
+
return pipe(
|
|
487
|
+
fragment`export function ${decodeFunction}<TAddress extends string = string>(encodedAccount: EncodedAccount<TAddress>): Account<${accountType}, TAddress>;
|
|
488
|
+
export function ${decodeFunction}<TAddress extends string = string>(encodedAccount: MaybeEncodedAccount<TAddress>): MaybeAccount<${accountType}, TAddress>;
|
|
489
|
+
export function ${decodeFunction}<TAddress extends string = string>(encodedAccount: EncodedAccount<TAddress> | MaybeEncodedAccount<TAddress>): Account<${accountType}, TAddress> | MaybeAccount<${accountType}, TAddress> {
|
|
490
|
+
return decodeAccount(encodedAccount as MaybeEncodedAccount<TAddress>, ${decoderFunction});
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
export async function ${fetchFunction}<TAddress extends string = string>(
|
|
494
|
+
rpc: Parameters<typeof fetchEncodedAccount>[0],
|
|
495
|
+
address: Address<TAddress>,
|
|
496
|
+
config?: FetchAccountConfig,
|
|
497
|
+
): Promise<Account<${accountType}, TAddress>> {
|
|
498
|
+
const maybeAccount = await ${fetchMaybeFunction}(rpc, address, config);
|
|
499
|
+
assertAccountExists(maybeAccount);
|
|
500
|
+
return maybeAccount;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
export async function ${fetchMaybeFunction}<TAddress extends string = string>(
|
|
504
|
+
rpc: Parameters<typeof fetchEncodedAccount>[0],
|
|
505
|
+
address: Address<TAddress>,
|
|
506
|
+
config?: FetchAccountConfig,
|
|
507
|
+
): Promise<MaybeAccount<${accountType}, TAddress>> {
|
|
508
|
+
const maybeAccount = await fetchEncodedAccount(rpc, address, config);
|
|
509
|
+
return ${decodeFunction}(maybeAccount);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
export async function ${fetchAllFunction}(
|
|
513
|
+
rpc: Parameters<typeof fetchEncodedAccounts>[0],
|
|
514
|
+
addresses: Array<Address>,
|
|
515
|
+
config?: FetchAccountsConfig,
|
|
516
|
+
): Promise<Account<${accountType}>[]> {
|
|
517
|
+
const maybeAccounts = await ${fetchAllMaybeFunction}(rpc, addresses, config);
|
|
518
|
+
assertAccountsExist(maybeAccounts);
|
|
519
|
+
return maybeAccounts;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
export async function ${fetchAllMaybeFunction}(
|
|
523
|
+
rpc: Parameters<typeof fetchEncodedAccounts>[0],
|
|
524
|
+
addresses: Array<Address>,
|
|
525
|
+
config?: FetchAccountsConfig,
|
|
526
|
+
): Promise<MaybeAccount<${accountType}>[]> {
|
|
527
|
+
const maybeAccounts = await fetchEncodedAccounts(rpc, addresses, config);
|
|
528
|
+
return maybeAccounts.map((maybeAccount) => ${decodeFunction}(maybeAccount));
|
|
529
|
+
}`,
|
|
530
|
+
(f) => addFragmentImports(f, "solanaAddresses", ["type Address"]),
|
|
531
|
+
(f) => addFragmentImports(f, "solanaAccounts", [
|
|
532
|
+
"type Account",
|
|
533
|
+
"assertAccountExists",
|
|
534
|
+
"assertAccountsExist",
|
|
535
|
+
"decodeAccount",
|
|
536
|
+
"type EncodedAccount",
|
|
537
|
+
"fetchEncodedAccount",
|
|
538
|
+
"fetchEncodedAccounts",
|
|
539
|
+
"type FetchAccountConfig",
|
|
540
|
+
"type FetchAccountsConfig",
|
|
541
|
+
"type MaybeAccount",
|
|
542
|
+
"type MaybeEncodedAccount"
|
|
543
|
+
])
|
|
544
|
+
);
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// src/fragments/accountPage.ts
|
|
548
|
+
import { resolveNestedTypeNode as resolveNestedTypeNode2 } from "@codama/nodes";
|
|
549
|
+
import { findProgramNodeFromPath, getLastNodeFromPath as getLastNodeFromPath5, visit as visit2 } from "@codama/visitors-core";
|
|
550
|
+
|
|
551
|
+
// src/fragments/accountPdaHelpers.ts
|
|
552
|
+
import { isNodeFilter } from "@codama/nodes";
|
|
553
|
+
import { getLastNodeFromPath as getLastNodeFromPath2, pipe as pipe2 } from "@codama/visitors-core";
|
|
554
|
+
function getAccountPdaHelpersFragment(scope) {
|
|
555
|
+
const { accountPath, nameApi, linkables, customAccountData, typeManifest: typeManifest2 } = scope;
|
|
556
|
+
const accountNode = getLastNodeFromPath2(accountPath);
|
|
557
|
+
const pdaNode = accountNode.pda ? linkables.get([...accountPath, accountNode.pda]) : void 0;
|
|
558
|
+
if (!pdaNode) return;
|
|
559
|
+
const accountType = customAccountData.has(accountNode.name) ? typeManifest2.strictType : nameApi.dataType(accountNode.name);
|
|
560
|
+
const importFrom = "generatedPdas";
|
|
561
|
+
const pdaSeedsType = nameApi.pdaSeedsType(pdaNode.name);
|
|
562
|
+
const findPdaFunction = nameApi.pdaFindFunction(pdaNode.name);
|
|
563
|
+
const hasVariableSeeds = pdaNode.seeds.filter(isNodeFilter("variablePdaSeedNode")).length > 0;
|
|
564
|
+
const fetchFromSeedsFunction = nameApi.accountFetchFromSeedsFunction(accountNode.name);
|
|
565
|
+
const fetchMaybeFromSeedsFunction = nameApi.accountFetchMaybeFromSeedsFunction(accountNode.name);
|
|
566
|
+
const fetchMaybeFunction = nameApi.accountFetchMaybeFunction(accountNode.name);
|
|
567
|
+
return pipe2(
|
|
568
|
+
fragment`export async function ${fetchFromSeedsFunction}(
|
|
569
|
+
rpc: Parameters<typeof fetchEncodedAccount>[0],
|
|
570
|
+
${hasVariableSeeds ? `seeds: ${pdaSeedsType},` : ""}
|
|
571
|
+
config: FetchAccountConfig & { programAddress?: Address } = {},
|
|
572
|
+
): Promise<Account<${accountType}>> {
|
|
573
|
+
const maybeAccount = await ${fetchMaybeFromSeedsFunction}(rpc, ${hasVariableSeeds ? "seeds, " : ""}config);
|
|
574
|
+
assertAccountExists(maybeAccount);
|
|
575
|
+
return maybeAccount;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
export async function ${fetchMaybeFromSeedsFunction}(
|
|
579
|
+
rpc: Parameters<typeof fetchEncodedAccount>[0],
|
|
580
|
+
${hasVariableSeeds ? `seeds: ${pdaSeedsType},` : ""}
|
|
581
|
+
config: FetchAccountConfig & { programAddress?: Address } = {},
|
|
582
|
+
): Promise<MaybeAccount<${accountType}>> {
|
|
583
|
+
const { programAddress, ...fetchConfig } = config;
|
|
584
|
+
const [address] = await ${findPdaFunction}(${hasVariableSeeds ? "seeds, " : ""}{ programAddress });
|
|
585
|
+
return await ${fetchMaybeFunction}(rpc, address, fetchConfig);
|
|
586
|
+
}`,
|
|
587
|
+
(f) => addFragmentImports(f, importFrom, hasVariableSeeds ? [pdaSeedsType, findPdaFunction] : [findPdaFunction]),
|
|
588
|
+
(f) => addFragmentImports(f, "solanaAddresses", ["type Address"]),
|
|
589
|
+
(f) => addFragmentImports(f, "solanaAccounts", [
|
|
590
|
+
"type Account",
|
|
591
|
+
"assertAccountExists",
|
|
592
|
+
"type FetchAccountConfig",
|
|
593
|
+
"type MaybeAccount"
|
|
594
|
+
])
|
|
595
|
+
);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// src/fragments/accountSizeHelpers.ts
|
|
599
|
+
import { getLastNodeFromPath as getLastNodeFromPath3 } from "@codama/visitors-core";
|
|
600
|
+
function getAccountSizeHelpersFragment(scope) {
|
|
601
|
+
const { accountPath, nameApi } = scope;
|
|
602
|
+
const accountNode = getLastNodeFromPath3(accountPath);
|
|
603
|
+
if (accountNode.size == null) return;
|
|
604
|
+
const getSizeFunction = nameApi.accountGetSizeFunction(accountNode.name);
|
|
605
|
+
return fragment`export function ${getSizeFunction}(): number {
|
|
606
|
+
return ${accountNode.size};
|
|
607
|
+
}`;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// src/fragments/accountType.ts
|
|
611
|
+
import { resolveNestedTypeNode } from "@codama/nodes";
|
|
612
|
+
import { getLastNodeFromPath as getLastNodeFromPath4 } from "@codama/visitors-core";
|
|
613
|
+
|
|
614
|
+
// src/fragments/type.ts
|
|
615
|
+
function getTypeFragment(scope) {
|
|
616
|
+
const { name, manifest, nameApi, docs = [] } = scope;
|
|
617
|
+
const docblock = getDocblockFragment(docs, true);
|
|
618
|
+
const strictName = nameApi.dataType(name);
|
|
619
|
+
const looseName = nameApi.dataArgsType(name);
|
|
620
|
+
const aliasedLooseName = `export type ${looseName} = ${strictName};`;
|
|
621
|
+
if (manifest.isEnum) {
|
|
622
|
+
return fragment`${docblock}export enum ${strictName} ${manifest.strictType};\n\n${aliasedLooseName}`;
|
|
623
|
+
}
|
|
624
|
+
const looseExport = manifest.strictType.content === manifest.looseType.content ? aliasedLooseName : fragment`export type ${looseName} = ${manifest.looseType};`;
|
|
625
|
+
return fragment`${docblock}export type ${strictName} = ${manifest.strictType};\n\n${looseExport}`;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// src/fragments/typeDecoder.ts
|
|
629
|
+
import { isDataEnum, isNode as isNode3 } from "@codama/nodes";
|
|
630
|
+
function getTypeDecoderFragment(scope) {
|
|
631
|
+
const { name, node, manifest, nameApi, docs = [] } = scope;
|
|
632
|
+
const decoderFunction = nameApi.decoderFunction(name);
|
|
633
|
+
const strictName = nameApi.dataType(name);
|
|
634
|
+
const docblock = getDocblockFragment(docs, true);
|
|
635
|
+
const decoderType = use(
|
|
636
|
+
typeof scope.size === "number" ? "type FixedSizeDecoder" : "type Decoder",
|
|
637
|
+
"solanaCodecsCore"
|
|
638
|
+
);
|
|
639
|
+
const useTypeCast = isNode3(node, "enumTypeNode") && isDataEnum(node) && typeof scope.size === "number";
|
|
640
|
+
const typeCast = useTypeCast ? fragment` as ${decoderType}<${strictName}>` : "";
|
|
641
|
+
return fragment`${docblock}export function ${decoderFunction}(): ${decoderType}<${strictName}> {
|
|
642
|
+
return ${manifest.decoder}${typeCast};
|
|
643
|
+
}`;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// src/fragments/typeEncoder.ts
|
|
647
|
+
import { isDataEnum as isDataEnum2, isNode as isNode4 } from "@codama/nodes";
|
|
648
|
+
function getTypeEncoderFragment(scope) {
|
|
649
|
+
const { name, node, manifest, nameApi, docs = [] } = scope;
|
|
650
|
+
const encoderFunction = nameApi.encoderFunction(name);
|
|
651
|
+
const looseName = nameApi.dataArgsType(name);
|
|
652
|
+
const docblock = getDocblockFragment(docs, true);
|
|
653
|
+
const encoderType = use(
|
|
654
|
+
typeof scope.size === "number" ? "type FixedSizeEncoder" : "type Encoder",
|
|
655
|
+
"solanaCodecsCore"
|
|
656
|
+
);
|
|
657
|
+
const useTypeCast = isNode4(node, "enumTypeNode") && isDataEnum2(node) && typeof scope.size === "number";
|
|
658
|
+
const typeCast = useTypeCast ? fragment` as ${encoderType}<${looseName}>` : "";
|
|
659
|
+
return fragment`${docblock}export function ${encoderFunction}(): ${encoderType}<${looseName}> {
|
|
660
|
+
return ${manifest.encoder}${typeCast};
|
|
661
|
+
}`;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
// src/fragments/typeCodec.ts
|
|
665
|
+
function getTypeCodecFragment(scope) {
|
|
666
|
+
const { codecDocs = [], name, nameApi } = scope;
|
|
667
|
+
const codecFunction = nameApi.codecFunction(name);
|
|
668
|
+
const decoderFunction = nameApi.decoderFunction(name);
|
|
669
|
+
const encoderFunction = nameApi.encoderFunction(name);
|
|
670
|
+
const looseName = nameApi.dataArgsType(name);
|
|
671
|
+
const strictName = nameApi.dataType(name);
|
|
672
|
+
const docblock = getDocblockFragment(codecDocs, true);
|
|
673
|
+
const codecType = use(typeof scope.size === "number" ? "type FixedSizeCodec" : "type Codec", "solanaCodecsCore");
|
|
674
|
+
return mergeFragments(
|
|
675
|
+
[
|
|
676
|
+
getTypeEncoderFragment({ ...scope, docs: scope.encoderDocs }),
|
|
677
|
+
getTypeDecoderFragment({ ...scope, docs: scope.decoderDocs }),
|
|
678
|
+
fragment`${docblock}export function ${codecFunction}(): ${codecType}<${looseName}, ${strictName}> {
|
|
679
|
+
return ${use("combineCodec", "solanaCodecsCore")}(${encoderFunction}(), ${decoderFunction}());
|
|
680
|
+
}`
|
|
681
|
+
],
|
|
682
|
+
(renders) => renders.join("\n\n")
|
|
683
|
+
);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
// src/fragments/typeWithCodec.ts
|
|
687
|
+
function getTypeWithCodecFragment(scope) {
|
|
688
|
+
return mergeFragments(
|
|
689
|
+
[getTypeFragment({ ...scope, docs: scope.typeDocs }), getTypeCodecFragment(scope)],
|
|
690
|
+
(renders) => renders.join("\n\n")
|
|
691
|
+
);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// src/fragments/accountType.ts
|
|
695
|
+
function getAccountTypeFragment(scope) {
|
|
696
|
+
const { accountPath, typeManifest: typeManifest2, nameApi, customAccountData } = scope;
|
|
697
|
+
const accountNode = getLastNodeFromPath4(accountPath);
|
|
698
|
+
if (customAccountData.has(accountNode.name)) return;
|
|
699
|
+
return getTypeWithCodecFragment({
|
|
700
|
+
manifest: typeManifest2,
|
|
701
|
+
name: accountNode.name,
|
|
702
|
+
nameApi,
|
|
703
|
+
node: resolveNestedTypeNode(accountNode.data),
|
|
704
|
+
size: scope.size
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
// src/fragments/discriminatorConstants.ts
|
|
709
|
+
import {
|
|
710
|
+
camelCase as camelCase3,
|
|
711
|
+
isNode as isNode5,
|
|
712
|
+
isNodeFilter as isNodeFilter2,
|
|
713
|
+
VALUE_NODES
|
|
714
|
+
} from "@codama/nodes";
|
|
715
|
+
import { visit } from "@codama/visitors-core";
|
|
716
|
+
function getDiscriminatorConstantsFragment(scope) {
|
|
717
|
+
const fragments = scope.discriminatorNodes.map((node) => getDiscriminatorConstantFragment(node, scope)).filter(Boolean);
|
|
718
|
+
return mergeFragments(fragments, (c) => c.join("\n\n"));
|
|
719
|
+
}
|
|
720
|
+
function getDiscriminatorConstantFragment(discriminatorNode, scope) {
|
|
721
|
+
switch (discriminatorNode.kind) {
|
|
722
|
+
case "constantDiscriminatorNode":
|
|
723
|
+
return getConstantDiscriminatorConstantFragment(discriminatorNode, scope);
|
|
724
|
+
case "fieldDiscriminatorNode":
|
|
725
|
+
return getFieldDiscriminatorConstantFragment(discriminatorNode, scope);
|
|
726
|
+
default:
|
|
727
|
+
return null;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
function getConstantDiscriminatorConstantFragment(discriminatorNode, scope) {
|
|
731
|
+
const { discriminatorNodes, typeManifestVisitor, prefix } = scope;
|
|
732
|
+
const index = discriminatorNodes.filter(isNodeFilter2("constantDiscriminatorNode")).indexOf(discriminatorNode);
|
|
733
|
+
const suffix = index <= 0 ? "" : `_${index + 1}`;
|
|
734
|
+
const name = camelCase3(`${prefix}_discriminator${suffix}`);
|
|
735
|
+
const encoder = visit(discriminatorNode.constant.type, typeManifestVisitor).encoder;
|
|
736
|
+
const value = visit(discriminatorNode.constant.value, typeManifestVisitor).value;
|
|
737
|
+
return getConstantFragment({ ...scope, encoder, name, value });
|
|
738
|
+
}
|
|
739
|
+
function getFieldDiscriminatorConstantFragment(discriminatorNode, scope) {
|
|
740
|
+
const { fields, prefix, typeManifestVisitor } = scope;
|
|
741
|
+
const field = fields.find((f) => f.name === discriminatorNode.name);
|
|
742
|
+
if (!field || !field.defaultValue || !isNode5(field.defaultValue, VALUE_NODES)) {
|
|
743
|
+
return null;
|
|
744
|
+
}
|
|
745
|
+
const name = camelCase3(`${prefix}_${discriminatorNode.name}`);
|
|
746
|
+
const encoder = visit(field.type, typeManifestVisitor).encoder;
|
|
747
|
+
const value = visit(field.defaultValue, typeManifestVisitor).value;
|
|
748
|
+
return getConstantFragment({ ...scope, encoder, name, value });
|
|
749
|
+
}
|
|
750
|
+
function getConstantFragment(scope) {
|
|
751
|
+
const { encoder, name, nameApi, value } = scope;
|
|
752
|
+
const constantName = nameApi.constant(name);
|
|
753
|
+
const constantFunction = nameApi.constantFunction(name);
|
|
754
|
+
return fragment`export const ${constantName} = ${value};\n\nexport function ${constantFunction}() { return ${encoder}.encode(${constantName}); }`;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
// src/fragments/accountPage.ts
|
|
758
|
+
function getAccountPageFragment(scope) {
|
|
759
|
+
const node = getLastNodeFromPath5(scope.accountPath);
|
|
760
|
+
if (!findProgramNodeFromPath(scope.accountPath)) {
|
|
761
|
+
throw new Error("Account must be visited inside a program.");
|
|
762
|
+
}
|
|
763
|
+
const typeManifest2 = visit2(node, scope.typeManifestVisitor);
|
|
764
|
+
const fields = resolveNestedTypeNode2(node.data).fields;
|
|
765
|
+
return mergeFragments(
|
|
766
|
+
[
|
|
767
|
+
getDiscriminatorConstantsFragment({
|
|
768
|
+
...scope,
|
|
769
|
+
discriminatorNodes: node.discriminators ?? [],
|
|
770
|
+
fields,
|
|
771
|
+
prefix: node.name
|
|
772
|
+
}),
|
|
773
|
+
getAccountTypeFragment({ ...scope, typeManifest: typeManifest2 }),
|
|
774
|
+
getAccountFetchHelpersFragment({ ...scope, typeManifest: typeManifest2 }),
|
|
775
|
+
getAccountSizeHelpersFragment(scope),
|
|
776
|
+
getAccountPdaHelpersFragment({ ...scope, typeManifest: typeManifest2 })
|
|
777
|
+
],
|
|
778
|
+
(cs) => cs.join("\n\n")
|
|
779
|
+
);
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
// src/fragments/discriminatorCondition.ts
|
|
783
|
+
import {
|
|
784
|
+
constantDiscriminatorNode,
|
|
785
|
+
constantValueNode,
|
|
786
|
+
constantValueNodeFromBytes,
|
|
787
|
+
isNode as isNode6,
|
|
788
|
+
isNodeFilter as isNodeFilter3
|
|
789
|
+
} from "@codama/nodes";
|
|
790
|
+
import { mapFragmentContent } from "@codama/renderers-core";
|
|
791
|
+
import { pipe as pipe3, visit as visit3 } from "@codama/visitors-core";
|
|
792
|
+
import { getBase64Decoder } from "@solana/codecs-strings";
|
|
793
|
+
function getDiscriminatorConditionFragment(scope) {
|
|
794
|
+
return pipe3(
|
|
795
|
+
mergeFragments(
|
|
796
|
+
scope.discriminators.flatMap((discriminator) => {
|
|
797
|
+
if (isNode6(discriminator, "sizeDiscriminatorNode")) {
|
|
798
|
+
return [getSizeConditionFragment(discriminator, scope)];
|
|
799
|
+
}
|
|
800
|
+
if (isNode6(discriminator, "constantDiscriminatorNode")) {
|
|
801
|
+
return [getByteConditionFragment(discriminator, scope)];
|
|
802
|
+
}
|
|
803
|
+
if (isNode6(discriminator, "fieldDiscriminatorNode")) {
|
|
804
|
+
return [getFieldConditionFragment(discriminator, scope)];
|
|
805
|
+
}
|
|
806
|
+
return [];
|
|
807
|
+
}),
|
|
808
|
+
(c) => c.join(" && ")
|
|
809
|
+
),
|
|
810
|
+
(f) => mapFragmentContent(f, (c) => `if (${c}) { ${scope.ifTrue}; }`)
|
|
811
|
+
);
|
|
812
|
+
}
|
|
813
|
+
function getSizeConditionFragment(discriminator, scope) {
|
|
814
|
+
const { dataName } = scope;
|
|
815
|
+
return fragment`${dataName}.length === ${discriminator.size}`;
|
|
816
|
+
}
|
|
817
|
+
function getByteConditionFragment(discriminator, scope) {
|
|
818
|
+
const { dataName, typeManifestVisitor } = scope;
|
|
819
|
+
const constant = visit3(discriminator.constant, typeManifestVisitor).value;
|
|
820
|
+
return fragment`${use("containsBytes", "solanaCodecsCore")}(${dataName}, ${constant}, ${discriminator.offset})`;
|
|
821
|
+
}
|
|
822
|
+
function getFieldConditionFragment(discriminator, scope) {
|
|
823
|
+
const field = scope.struct.fields.find((f) => f.name === discriminator.name);
|
|
824
|
+
if (!field || !field.defaultValue) {
|
|
825
|
+
throw new Error(
|
|
826
|
+
`Field discriminator "${discriminator.name}" does not have a matching argument with default value.`
|
|
827
|
+
);
|
|
828
|
+
}
|
|
829
|
+
if (isNode6(field.type, "arrayTypeNode") && isNode6(field.type.item, "numberTypeNode") && field.type.item.format === "u8" && isNode6(field.type.count, "fixedCountNode") && isNode6(field.defaultValue, "arrayValueNode") && field.defaultValue.items.every(isNodeFilter3("numberValueNode"))) {
|
|
830
|
+
const base64Bytes = getBase64Decoder().decode(
|
|
831
|
+
new Uint8Array(field.defaultValue.items.map((node) => node.number))
|
|
832
|
+
);
|
|
833
|
+
return getByteConditionFragment(
|
|
834
|
+
constantDiscriminatorNode(constantValueNodeFromBytes("base64", base64Bytes), discriminator.offset),
|
|
835
|
+
scope
|
|
836
|
+
);
|
|
837
|
+
}
|
|
838
|
+
return getByteConditionFragment(
|
|
839
|
+
constantDiscriminatorNode(constantValueNode(field.type, field.defaultValue), discriminator.offset),
|
|
840
|
+
scope
|
|
841
|
+
);
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// src/fragments/errorPage.ts
|
|
845
|
+
function getErrorPageFragment(scope) {
|
|
846
|
+
return mergeFragments(
|
|
847
|
+
[
|
|
848
|
+
getConstantsFragment(scope),
|
|
849
|
+
getConstantUnionTypeFragment(scope),
|
|
850
|
+
getErrorMessagesFragment(scope),
|
|
851
|
+
getErrorMessageFunctionFragment(scope),
|
|
852
|
+
getIsErrorFunctionFragment(scope)
|
|
853
|
+
],
|
|
854
|
+
(cs) => cs.join("\n\n")
|
|
855
|
+
);
|
|
856
|
+
}
|
|
857
|
+
function getConstantsFragment(scope) {
|
|
858
|
+
const constantPrefix = scope.nameApi.programErrorConstantPrefix(scope.programNode.name);
|
|
859
|
+
return mergeFragments(
|
|
860
|
+
[...scope.programNode.errors].sort((a, b) => a.code - b.code).map((error) => {
|
|
861
|
+
const docs = getDocblockFragment(error.docs ?? [], true);
|
|
862
|
+
const name = constantPrefix + scope.nameApi.programErrorConstant(error.name);
|
|
863
|
+
return fragment`${docs}export const ${name} = 0x${error.code.toString(16)}; // ${error.code}`;
|
|
864
|
+
}),
|
|
865
|
+
(cs) => cs.join("\n")
|
|
866
|
+
);
|
|
867
|
+
}
|
|
868
|
+
function getConstantUnionTypeFragment(scope) {
|
|
869
|
+
const constantPrefix = scope.nameApi.programErrorConstantPrefix(scope.programNode.name);
|
|
870
|
+
const typeName = scope.nameApi.programErrorUnion(scope.programNode.name);
|
|
871
|
+
const errorTypes = mergeFragments(
|
|
872
|
+
[...scope.programNode.errors].sort((a, b) => a.name.localeCompare(b.name)).map((error) => fragment`typeof ${constantPrefix + scope.nameApi.programErrorConstant(error.name)}`),
|
|
873
|
+
(cs) => cs.join(" | ")
|
|
874
|
+
);
|
|
875
|
+
return fragment`export type ${typeName} = ${errorTypes};`;
|
|
876
|
+
}
|
|
877
|
+
function getErrorMessagesFragment(scope) {
|
|
878
|
+
const mapName = scope.nameApi.programErrorMessagesMap(scope.programNode.name);
|
|
879
|
+
const errorUnionType = scope.nameApi.programErrorUnion(scope.programNode.name);
|
|
880
|
+
const constantPrefix = scope.nameApi.programErrorConstantPrefix(scope.programNode.name);
|
|
881
|
+
const messageEntries = mergeFragments(
|
|
882
|
+
[...scope.programNode.errors].sort((a, b) => a.name.localeCompare(b.name)).map((error) => {
|
|
883
|
+
const constantName = constantPrefix + scope.nameApi.programErrorConstant(error.name);
|
|
884
|
+
const escapedMessage = error.message.replace(/`/g, "\\`");
|
|
885
|
+
return fragment`[${constantName}]: \`${escapedMessage}\``;
|
|
886
|
+
}),
|
|
887
|
+
(cs) => cs.join(", ")
|
|
888
|
+
);
|
|
889
|
+
return fragment`let ${mapName}: Record<${errorUnionType}, string> | undefined;
|
|
890
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
891
|
+
${mapName} = { ${messageEntries} };
|
|
892
|
+
}`;
|
|
893
|
+
}
|
|
894
|
+
function getErrorMessageFunctionFragment(scope) {
|
|
895
|
+
const functionName = scope.nameApi.programGetErrorMessageFunction(scope.programNode.name);
|
|
896
|
+
const errorUnionType = scope.nameApi.programErrorUnion(scope.programNode.name);
|
|
897
|
+
const messageMapName = scope.nameApi.programErrorMessagesMap(scope.programNode.name);
|
|
898
|
+
return fragment`export function ${functionName}(code: ${errorUnionType}): string {
|
|
899
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
900
|
+
return (${messageMapName} as Record<${errorUnionType}, string>)[code];
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
return 'Error message not available in production bundles.';
|
|
904
|
+
}`;
|
|
905
|
+
}
|
|
906
|
+
function getIsErrorFunctionFragment(scope) {
|
|
907
|
+
const { programNode, nameApi } = scope;
|
|
908
|
+
const programAddressConstant = use(nameApi.programAddressConstant(programNode.name), "generatedPrograms");
|
|
909
|
+
const functionName = nameApi.programIsErrorFunction(programNode.name);
|
|
910
|
+
const programErrorUnion = nameApi.programErrorUnion(programNode.name);
|
|
911
|
+
return fragment`export function ${functionName}<TProgramErrorCode extends ${programErrorUnion}>(
|
|
912
|
+
error: unknown,
|
|
913
|
+
transactionMessage: { instructions: Record<number, { programAddress: ${use("type Address", "solanaAddresses")} }> },
|
|
914
|
+
code?: TProgramErrorCode,
|
|
915
|
+
): error is ${use("type SolanaError", "solanaErrors")}<typeof ${use("type SOLANA_ERROR__INSTRUCTION_ERROR__CUSTOM", "solanaErrors")}> & Readonly<{ context: Readonly<{ code: TProgramErrorCode }> }> {
|
|
916
|
+
return ${use("isProgramError", "solanaPrograms")}<TProgramErrorCode>(error, transactionMessage, ${programAddressConstant}, code);
|
|
917
|
+
}`;
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
// src/fragments/indexPage.ts
|
|
921
|
+
function getIndexPageFragment(items) {
|
|
922
|
+
if (items.length === 0) return;
|
|
923
|
+
const names = items.map((item) => item.name).sort((a, b) => a.localeCompare(b)).map((name) => getExportAllFragment(`./${name}`));
|
|
924
|
+
return mergeFragments(names, (cs) => cs.join("\n"));
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
// src/fragments/instructionAccountMeta.ts
|
|
928
|
+
import { pascalCase as pascalCase2 } from "@codama/nodes";
|
|
929
|
+
function getInstructionAccountMetaFragment(instructionAccountNode) {
|
|
930
|
+
const typeParam = `TAccount${pascalCase2(instructionAccountNode.name)}`;
|
|
931
|
+
if (instructionAccountNode.isSigner === true && instructionAccountNode.isWritable) {
|
|
932
|
+
return fragment`${use("type WritableSignerAccount", "solanaInstructions")}<${typeParam}> & ${use("type AccountSignerMeta", "solanaSigners")}<${typeParam}>`;
|
|
933
|
+
}
|
|
934
|
+
if (instructionAccountNode.isSigner === true) {
|
|
935
|
+
return fragment`${use("type ReadonlySignerAccount", "solanaInstructions")}<${typeParam}> & ${use("type AccountSignerMeta", "solanaSigners")}<${typeParam}>`;
|
|
936
|
+
}
|
|
937
|
+
if (instructionAccountNode.isWritable) {
|
|
938
|
+
return fragment`${use("type WritableAccount", "solanaInstructions")}<${typeParam}>`;
|
|
939
|
+
}
|
|
940
|
+
return fragment`${use("type ReadonlyAccount", "solanaInstructions")}<${typeParam}>`;
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
// src/fragments/instructionAccountTypeParam.ts
|
|
944
|
+
import { pascalCase as pascalCase3 } from "@codama/nodes";
|
|
945
|
+
import {
|
|
946
|
+
findInstructionNodeFromPath,
|
|
947
|
+
findProgramNodeFromPath as findProgramNodeFromPath2,
|
|
948
|
+
getLastNodeFromPath as getLastNodeFromPath6
|
|
949
|
+
} from "@codama/visitors-core";
|
|
950
|
+
function getInstructionAccountTypeParamFragment(scope) {
|
|
951
|
+
const { instructionAccountPath, allowAccountMeta, linkables } = scope;
|
|
952
|
+
const instructionAccountNode = getLastNodeFromPath6(instructionAccountPath);
|
|
953
|
+
const instructionNode = findInstructionNodeFromPath(instructionAccountPath);
|
|
954
|
+
const programNode = findProgramNodeFromPath2(instructionAccountPath);
|
|
955
|
+
const typeParam = `TAccount${pascalCase3(instructionAccountNode.name)}`;
|
|
956
|
+
const accountMeta = allowAccountMeta ? fragment` | ${use("type AccountMeta", "solanaInstructions")}<string>` : void 0;
|
|
957
|
+
if (instructionNode.optionalAccountStrategy === "omitted" && instructionAccountNode.isOptional) {
|
|
958
|
+
return fragment`${typeParam} extends string${accountMeta} | undefined = undefined`;
|
|
959
|
+
}
|
|
960
|
+
const defaultAddress = getDefaultAddress(instructionAccountNode.defaultValue, programNode.publicKey, linkables);
|
|
961
|
+
return fragment`${typeParam} extends string${accountMeta} = ${defaultAddress}`;
|
|
962
|
+
}
|
|
963
|
+
function getDefaultAddress(defaultValue, programId, linkables) {
|
|
964
|
+
switch (defaultValue?.kind) {
|
|
965
|
+
case "publicKeyValueNode":
|
|
966
|
+
return `"${defaultValue.publicKey}"`;
|
|
967
|
+
case "programLinkNode":
|
|
968
|
+
const programNode = linkables.get([defaultValue]);
|
|
969
|
+
return programNode ? `"${programNode.publicKey}"` : "string";
|
|
970
|
+
case "programIdValueNode":
|
|
971
|
+
return `"${programId}"`;
|
|
972
|
+
default:
|
|
973
|
+
return "string";
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
// src/fragments/instructionByteDelta.ts
|
|
978
|
+
import { assertIsNode, camelCase as camelCase4, isNode as isNode7 } from "@codama/nodes";
|
|
979
|
+
import { mapFragmentContent as mapFragmentContent2 } from "@codama/renderers-core";
|
|
980
|
+
import { getLastNodeFromPath as getLastNodeFromPath7, pipe as pipe4 } from "@codama/visitors-core";
|
|
981
|
+
function getInstructionByteDeltaFragment(scope) {
|
|
982
|
+
const { byteDeltas } = getLastNodeFromPath7(scope.instructionPath);
|
|
983
|
+
const fragments = (byteDeltas ?? []).flatMap((c) => getByteDeltaFragment(c, scope));
|
|
984
|
+
if (fragments.length === 0) return;
|
|
985
|
+
return mergeFragments(
|
|
986
|
+
fragments,
|
|
987
|
+
(c) => `// Bytes created or reallocated by the instruction.
|
|
988
|
+
const byteDelta: number = [${c.join(",")}].reduce((a, b) => a + b, 0);`
|
|
989
|
+
);
|
|
990
|
+
}
|
|
991
|
+
function getByteDeltaFragment(byteDelta, scope) {
|
|
992
|
+
let bytesFragment = (() => {
|
|
993
|
+
if (isNode7(byteDelta.value, "numberValueNode")) {
|
|
994
|
+
return getNumberValueNodeFragment(byteDelta);
|
|
995
|
+
}
|
|
996
|
+
if (isNode7(byteDelta.value, "argumentValueNode")) {
|
|
997
|
+
return getArgumentValueNodeFragment(byteDelta);
|
|
998
|
+
}
|
|
999
|
+
if (isNode7(byteDelta.value, "accountLinkNode")) {
|
|
1000
|
+
return getAccountLinkNodeFragment(byteDelta, scope);
|
|
1001
|
+
}
|
|
1002
|
+
if (isNode7(byteDelta.value, "resolverValueNode")) {
|
|
1003
|
+
return getResolverValueNodeFragment(byteDelta, scope);
|
|
1004
|
+
}
|
|
1005
|
+
return null;
|
|
1006
|
+
})();
|
|
1007
|
+
if (bytesFragment === null) return [];
|
|
1008
|
+
if (byteDelta.withHeader) {
|
|
1009
|
+
bytesFragment = fragment`${bytesFragment} + ${use("BASE_ACCOUNT_SIZE", "solanaAccounts")}`;
|
|
1010
|
+
}
|
|
1011
|
+
if (byteDelta.subtract) {
|
|
1012
|
+
bytesFragment = pipe4(bytesFragment, (f) => mapFragmentContent2(f, (c) => `- (${c})`));
|
|
1013
|
+
}
|
|
1014
|
+
return [bytesFragment];
|
|
1015
|
+
}
|
|
1016
|
+
function getNumberValueNodeFragment(byteDelta) {
|
|
1017
|
+
assertIsNode(byteDelta.value, "numberValueNode");
|
|
1018
|
+
return fragment`${byteDelta.value.number}`;
|
|
1019
|
+
}
|
|
1020
|
+
function getArgumentValueNodeFragment(byteDelta) {
|
|
1021
|
+
assertIsNode(byteDelta.value, "argumentValueNode");
|
|
1022
|
+
const argumentName = camelCase4(byteDelta.value.name);
|
|
1023
|
+
return fragment`Number(args.${argumentName})`;
|
|
1024
|
+
}
|
|
1025
|
+
function getAccountLinkNodeFragment(byteDelta, scope) {
|
|
1026
|
+
assertIsNode(byteDelta.value, "accountLinkNode");
|
|
1027
|
+
const functionName = use(
|
|
1028
|
+
scope.nameApi.accountGetSizeFunction(byteDelta.value.name),
|
|
1029
|
+
scope.getImportFrom(byteDelta.value)
|
|
1030
|
+
);
|
|
1031
|
+
return fragment`${functionName}()`;
|
|
1032
|
+
}
|
|
1033
|
+
function getResolverValueNodeFragment(byteDelta, scope) {
|
|
1034
|
+
assertIsNode(byteDelta.value, "resolverValueNode");
|
|
1035
|
+
const isAsync = scope.asyncResolvers.includes(byteDelta.value.name);
|
|
1036
|
+
if (!scope.useAsync && isAsync) return null;
|
|
1037
|
+
const awaitKeyword = scope.useAsync && isAsync ? "await " : "";
|
|
1038
|
+
const functionName = use(
|
|
1039
|
+
scope.nameApi.resolverFunction(byteDelta.value.name),
|
|
1040
|
+
scope.getImportFrom(byteDelta.value)
|
|
1041
|
+
);
|
|
1042
|
+
return pipe4(
|
|
1043
|
+
fragment`${awaitKeyword}${functionName}(resolverScope)`,
|
|
1044
|
+
(f) => addFragmentFeatures(f, ["instruction:resolverScopeVariable"])
|
|
1045
|
+
);
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
// src/fragments/instructionData.ts
|
|
1049
|
+
import { structTypeNodeFromInstructionArgumentNodes as structTypeNodeFromInstructionArgumentNodes2 } from "@codama/nodes";
|
|
1050
|
+
import { getLastNodeFromPath as getLastNodeFromPath8 } from "@codama/visitors-core";
|
|
1051
|
+
function getInstructionDataFragment(scope) {
|
|
1052
|
+
const { instructionPath, dataArgsManifest, nameApi, customInstructionData } = scope;
|
|
1053
|
+
const instructionNode = getLastNodeFromPath8(instructionPath);
|
|
1054
|
+
if (instructionNode.arguments.length === 0 || customInstructionData.has(instructionNode.name)) return;
|
|
1055
|
+
const instructionDataName = nameApi.instructionDataType(instructionNode.name);
|
|
1056
|
+
return getTypeWithCodecFragment({
|
|
1057
|
+
manifest: dataArgsManifest,
|
|
1058
|
+
name: instructionDataName,
|
|
1059
|
+
nameApi,
|
|
1060
|
+
node: structTypeNodeFromInstructionArgumentNodes2(instructionNode.arguments),
|
|
1061
|
+
size: scope.size
|
|
1062
|
+
});
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
// src/fragments/instructionExtraArgs.ts
|
|
1066
|
+
import { mapFragmentContent as mapFragmentContent3 } from "@codama/renderers-core";
|
|
1067
|
+
import { getLastNodeFromPath as getLastNodeFromPath9 } from "@codama/visitors-core";
|
|
1068
|
+
function getInstructionExtraArgsFragment(scope) {
|
|
1069
|
+
const { instructionPath, extraArgsManifest, nameApi } = scope;
|
|
1070
|
+
const instructionNode = getLastNodeFromPath9(instructionPath);
|
|
1071
|
+
if ((instructionNode.extraArguments ?? []).length === 0) return;
|
|
1072
|
+
const instructionExtraName = nameApi.instructionExtraType(instructionNode.name);
|
|
1073
|
+
const looseName = nameApi.dataArgsType(instructionExtraName);
|
|
1074
|
+
return mapFragmentContent3(extraArgsManifest.looseType, (c) => `export type ${looseName} = ${c};`);
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
// src/fragments/instructionFunction.ts
|
|
1078
|
+
import { camelCase as camelCase9, isNode as isNode12, isNodeFilter as isNodeFilter4, pascalCase as pascalCase5 } from "@codama/nodes";
|
|
1079
|
+
import { mapFragmentContent as mapFragmentContent7 } from "@codama/renderers-core";
|
|
1080
|
+
import {
|
|
1081
|
+
findProgramNodeFromPath as findProgramNodeFromPath3,
|
|
1082
|
+
getLastNodeFromPath as getLastNodeFromPath13,
|
|
1083
|
+
pipe as pipe8
|
|
1084
|
+
} from "@codama/visitors-core";
|
|
1085
|
+
|
|
1086
|
+
// src/fragments/instructionInputResolved.ts
|
|
1087
|
+
import { camelCase as camelCase6, isNode as isNode9, parseOptionalAccountStrategy } from "@codama/nodes";
|
|
1088
|
+
import { mapFragmentContent as mapFragmentContent5 } from "@codama/renderers-core";
|
|
1089
|
+
import { getLastNodeFromPath as getLastNodeFromPath10 } from "@codama/visitors-core";
|
|
1090
|
+
|
|
1091
|
+
// src/fragments/instructionInputDefault.ts
|
|
1092
|
+
import { camelCase as camelCase5, isNode as isNode8 } from "@codama/nodes";
|
|
1093
|
+
import { mapFragmentContent as mapFragmentContent4, setFragmentContent } from "@codama/renderers-core";
|
|
1094
|
+
import { pipe as pipe5, visit as visit4 } from "@codama/visitors-core";
|
|
1095
|
+
function getInstructionInputDefaultFragment(scope) {
|
|
1096
|
+
const { input, optionalAccountStrategy, asyncResolvers, useAsync, nameApi, typeManifestVisitor, getImportFrom } = scope;
|
|
1097
|
+
if (!input.defaultValue) {
|
|
1098
|
+
return fragment``;
|
|
1099
|
+
}
|
|
1100
|
+
if (!useAsync && isAsyncDefaultValue(input.defaultValue, asyncResolvers)) {
|
|
1101
|
+
return fragment``;
|
|
1102
|
+
}
|
|
1103
|
+
const { defaultValue } = input;
|
|
1104
|
+
const defaultFragment = (renderedValue, isWritable) => {
|
|
1105
|
+
const inputName = camelCase5(input.name);
|
|
1106
|
+
if (input.kind === "instructionAccountNode" && isNode8(defaultValue, "resolverValueNode")) {
|
|
1107
|
+
return fragment`accounts.${inputName} = { ...accounts.${inputName}, ...${renderedValue} };`;
|
|
1108
|
+
}
|
|
1109
|
+
if (input.kind === "instructionAccountNode" && isWritable === void 0) {
|
|
1110
|
+
return fragment`accounts.${inputName}.value = ${renderedValue};`;
|
|
1111
|
+
}
|
|
1112
|
+
if (input.kind === "instructionAccountNode") {
|
|
1113
|
+
return fragment`accounts.${inputName}.value = ${renderedValue};\naccounts.${inputName}.isWritable = ${isWritable ? "true" : "false"}`;
|
|
1114
|
+
}
|
|
1115
|
+
return fragment`args.${inputName} = ${renderedValue};`;
|
|
1116
|
+
};
|
|
1117
|
+
switch (defaultValue.kind) {
|
|
1118
|
+
case "accountValueNode":
|
|
1119
|
+
const name = camelCase5(defaultValue.name);
|
|
1120
|
+
if (input.kind === "instructionAccountNode" && input.resolvedIsSigner && !input.isSigner) {
|
|
1121
|
+
return pipe5(
|
|
1122
|
+
defaultFragment(`expectTransactionSigner(accounts.${name}.value).address`),
|
|
1123
|
+
(f) => addFragmentImports(f, "shared", ["expectTransactionSigner"])
|
|
1124
|
+
);
|
|
1125
|
+
}
|
|
1126
|
+
if (input.kind === "instructionAccountNode") {
|
|
1127
|
+
return pipe5(
|
|
1128
|
+
defaultFragment(`expectSome(accounts.${name}.value)`),
|
|
1129
|
+
(f) => addFragmentImports(f, "shared", ["expectSome"])
|
|
1130
|
+
);
|
|
1131
|
+
}
|
|
1132
|
+
return pipe5(
|
|
1133
|
+
defaultFragment(`expectAddress(accounts.${name}.value)`),
|
|
1134
|
+
(f) => addFragmentImports(f, "shared", ["expectAddress"])
|
|
1135
|
+
);
|
|
1136
|
+
case "pdaValueNode":
|
|
1137
|
+
if (isNode8(defaultValue.pda, "pdaNode")) {
|
|
1138
|
+
const pdaProgram = defaultValue.pda.programId ? pipe5(
|
|
1139
|
+
fragment`'${defaultValue.pda.programId}' as Address<'${defaultValue.pda.programId}'>`,
|
|
1140
|
+
(f) => addFragmentImports(f, "solanaAddresses", ["type Address"])
|
|
1141
|
+
) : fragment`programAddress`;
|
|
1142
|
+
const pdaSeeds2 = defaultValue.pda.seeds.flatMap((seed) => {
|
|
1143
|
+
if (isNode8(seed, "constantPdaSeedNode") && isNode8(seed.value, "programIdValueNode")) {
|
|
1144
|
+
return [
|
|
1145
|
+
pipe5(
|
|
1146
|
+
fragment`getAddressEncoder().encode(${pdaProgram})`,
|
|
1147
|
+
(f) => addFragmentImports(f, "solanaAddresses", ["getAddressEncoder"])
|
|
1148
|
+
)
|
|
1149
|
+
];
|
|
1150
|
+
}
|
|
1151
|
+
if (isNode8(seed, "constantPdaSeedNode") && !isNode8(seed.value, "programIdValueNode")) {
|
|
1152
|
+
const typeManifest2 = visit4(seed.type, typeManifestVisitor);
|
|
1153
|
+
const valueManifest2 = visit4(seed.value, typeManifestVisitor);
|
|
1154
|
+
return [fragment`${typeManifest2.encoder}.encode(${valueManifest2.value})`];
|
|
1155
|
+
}
|
|
1156
|
+
if (isNode8(seed, "variablePdaSeedNode")) {
|
|
1157
|
+
const typeManifest2 = visit4(seed.type, typeManifestVisitor);
|
|
1158
|
+
const valueSeed = defaultValue.seeds.find((s) => s.name === seed.name)?.value;
|
|
1159
|
+
if (!valueSeed) return [];
|
|
1160
|
+
if (isNode8(valueSeed, "accountValueNode")) {
|
|
1161
|
+
return [
|
|
1162
|
+
pipe5(
|
|
1163
|
+
fragment`${typeManifest2.encoder}.encode(expectAddress(accounts.${camelCase5(valueSeed.name)}.value))`,
|
|
1164
|
+
(f) => addFragmentImports(f, "shared", ["expectAddress"])
|
|
1165
|
+
)
|
|
1166
|
+
];
|
|
1167
|
+
}
|
|
1168
|
+
if (isNode8(valueSeed, "argumentValueNode")) {
|
|
1169
|
+
return [
|
|
1170
|
+
pipe5(
|
|
1171
|
+
fragment`${typeManifest2.encoder}.encode(expectSome(args.${camelCase5(valueSeed.name)}))`,
|
|
1172
|
+
(f) => addFragmentImports(f, "shared", ["expectSome"])
|
|
1173
|
+
)
|
|
1174
|
+
];
|
|
1175
|
+
}
|
|
1176
|
+
const valueManifest2 = visit4(valueSeed, typeManifestVisitor);
|
|
1177
|
+
return [fragment`${typeManifest2.encoder}.encode(${valueManifest2.value})`];
|
|
1178
|
+
}
|
|
1179
|
+
return [];
|
|
1180
|
+
});
|
|
1181
|
+
return pipe5(
|
|
1182
|
+
mergeFragments([pdaProgram, ...pdaSeeds2], ([p, ...s]) => {
|
|
1183
|
+
const programAddress2 = p === "programAddress" ? p : `programAddress: ${p}`;
|
|
1184
|
+
return `await getProgramDerivedAddress({ ${programAddress2}, seeds: [${s.join(", ")}] })`;
|
|
1185
|
+
}),
|
|
1186
|
+
(f) => addFragmentImports(f, "solanaAddresses", ["getProgramDerivedAddress"]),
|
|
1187
|
+
(f) => mapFragmentContent4(f, (c) => defaultFragment(c).content)
|
|
1188
|
+
);
|
|
1189
|
+
}
|
|
1190
|
+
const pdaFunction = nameApi.pdaFindFunction(defaultValue.pda.name);
|
|
1191
|
+
const pdaArgs = [];
|
|
1192
|
+
const pdaSeeds = defaultValue.seeds.map((seed) => {
|
|
1193
|
+
if (isNode8(seed.value, "accountValueNode")) {
|
|
1194
|
+
return pipe5(
|
|
1195
|
+
fragment`${seed.name}: expectAddress(accounts.${camelCase5(seed.value.name)}.value)`,
|
|
1196
|
+
(f) => addFragmentImports(f, "shared", ["expectAddress"])
|
|
1197
|
+
);
|
|
1198
|
+
}
|
|
1199
|
+
if (isNode8(seed.value, "argumentValueNode")) {
|
|
1200
|
+
return pipe5(
|
|
1201
|
+
fragment`${seed.name}: expectSome(args.${camelCase5(seed.value.name)})`,
|
|
1202
|
+
(f) => addFragmentImports(f, "shared", ["expectSome"])
|
|
1203
|
+
);
|
|
1204
|
+
}
|
|
1205
|
+
return pipe5(
|
|
1206
|
+
visit4(seed.value, typeManifestVisitor).value,
|
|
1207
|
+
(f) => mapFragmentContent4(f, (c) => `${seed.name}: ${c}`)
|
|
1208
|
+
);
|
|
1209
|
+
});
|
|
1210
|
+
const pdaSeedsFragment = pipe5(
|
|
1211
|
+
mergeFragments(pdaSeeds, (renders) => renders.join(", ")),
|
|
1212
|
+
(f) => mapFragmentContent4(f, (c) => `{ ${c} }`)
|
|
1213
|
+
);
|
|
1214
|
+
if (pdaSeeds.length > 0) {
|
|
1215
|
+
pdaArgs.push(pdaSeedsFragment.content);
|
|
1216
|
+
}
|
|
1217
|
+
const module = getImportFrom(defaultValue.pda);
|
|
1218
|
+
return pipe5(
|
|
1219
|
+
defaultFragment(`await ${pdaFunction}(${pdaArgs.join(", ")})`),
|
|
1220
|
+
(f) => mergeFragmentImports(f, [pdaSeedsFragment.imports]),
|
|
1221
|
+
(f) => addFragmentImports(f, module, [pdaFunction])
|
|
1222
|
+
);
|
|
1223
|
+
case "publicKeyValueNode":
|
|
1224
|
+
return pipe5(
|
|
1225
|
+
defaultFragment(`'${defaultValue.publicKey}' as Address<'${defaultValue.publicKey}'>`),
|
|
1226
|
+
(f) => addFragmentImports(f, "solanaAddresses", ["type Address"])
|
|
1227
|
+
);
|
|
1228
|
+
case "programLinkNode":
|
|
1229
|
+
const programAddress = nameApi.programAddressConstant(defaultValue.name);
|
|
1230
|
+
return pipe5(
|
|
1231
|
+
defaultFragment(programAddress, false),
|
|
1232
|
+
(f) => addFragmentImports(f, getImportFrom(defaultValue), [programAddress])
|
|
1233
|
+
);
|
|
1234
|
+
case "programIdValueNode":
|
|
1235
|
+
if (optionalAccountStrategy === "programId" && input.kind === "instructionAccountNode" && input.isOptional) {
|
|
1236
|
+
return fragment``;
|
|
1237
|
+
}
|
|
1238
|
+
return defaultFragment("programAddress", false);
|
|
1239
|
+
case "identityValueNode":
|
|
1240
|
+
case "payerValueNode":
|
|
1241
|
+
return fragment``;
|
|
1242
|
+
case "accountBumpValueNode":
|
|
1243
|
+
return pipe5(
|
|
1244
|
+
defaultFragment(`expectProgramDerivedAddress(accounts.${camelCase5(defaultValue.name)}.value)[1]`),
|
|
1245
|
+
(f) => addFragmentImports(f, "shared", ["expectProgramDerivedAddress"])
|
|
1246
|
+
);
|
|
1247
|
+
case "argumentValueNode":
|
|
1248
|
+
return pipe5(
|
|
1249
|
+
defaultFragment(`expectSome(args.${camelCase5(defaultValue.name)})`),
|
|
1250
|
+
(f) => addFragmentImports(f, "shared", ["expectSome"])
|
|
1251
|
+
);
|
|
1252
|
+
case "resolverValueNode":
|
|
1253
|
+
const resolverFunction = nameApi.resolverFunction(defaultValue.name);
|
|
1254
|
+
const resolverAwait = useAsync && asyncResolvers.includes(defaultValue.name) ? "await " : "";
|
|
1255
|
+
return pipe5(
|
|
1256
|
+
defaultFragment(`${resolverAwait}${resolverFunction}(resolverScope)`),
|
|
1257
|
+
(f) => addFragmentImports(f, getImportFrom(defaultValue), [resolverFunction]),
|
|
1258
|
+
(f) => addFragmentFeatures(f, ["instruction:resolverScopeVariable"])
|
|
1259
|
+
);
|
|
1260
|
+
case "conditionalValueNode":
|
|
1261
|
+
const ifTrueRenderer = renderNestedInstructionDefault({
|
|
1262
|
+
...scope,
|
|
1263
|
+
defaultValue: defaultValue.ifTrue
|
|
1264
|
+
});
|
|
1265
|
+
const ifFalseRenderer = renderNestedInstructionDefault({
|
|
1266
|
+
...scope,
|
|
1267
|
+
defaultValue: defaultValue.ifFalse
|
|
1268
|
+
});
|
|
1269
|
+
if (!ifTrueRenderer && !ifFalseRenderer) {
|
|
1270
|
+
return fragment``;
|
|
1271
|
+
}
|
|
1272
|
+
let conditionalFragment = fragment``;
|
|
1273
|
+
if (ifTrueRenderer) {
|
|
1274
|
+
conditionalFragment = mergeFragments([conditionalFragment, ifTrueRenderer], (c) => c[0]);
|
|
1275
|
+
}
|
|
1276
|
+
if (ifFalseRenderer) {
|
|
1277
|
+
conditionalFragment = mergeFragments([conditionalFragment, ifFalseRenderer], (c) => c[0]);
|
|
1278
|
+
}
|
|
1279
|
+
const negatedCondition = !ifTrueRenderer;
|
|
1280
|
+
let condition = "true";
|
|
1281
|
+
if (isNode8(defaultValue.condition, "resolverValueNode")) {
|
|
1282
|
+
const conditionalResolverFunction = nameApi.resolverFunction(defaultValue.condition.name);
|
|
1283
|
+
const module2 = getImportFrom(defaultValue.condition);
|
|
1284
|
+
conditionalFragment = pipe5(
|
|
1285
|
+
conditionalFragment,
|
|
1286
|
+
(f) => addFragmentImports(f, module2, [conditionalResolverFunction]),
|
|
1287
|
+
(f) => addFragmentFeatures(f, ["instruction:resolverScopeVariable"])
|
|
1288
|
+
);
|
|
1289
|
+
const conditionalResolverAwait = useAsync && asyncResolvers.includes(defaultValue.condition.name) ? "await " : "";
|
|
1290
|
+
condition = `${conditionalResolverAwait}${conditionalResolverFunction}(resolverScope)`;
|
|
1291
|
+
condition = negatedCondition ? `!${condition}` : condition;
|
|
1292
|
+
} else {
|
|
1293
|
+
const comparedInputName = isNode8(defaultValue.condition, "accountValueNode") ? `accounts.${camelCase5(defaultValue.condition.name)}.value` : `args.${camelCase5(defaultValue.condition.name)}`;
|
|
1294
|
+
if (defaultValue.value) {
|
|
1295
|
+
const comparedValue = visit4(defaultValue.value, typeManifestVisitor).value;
|
|
1296
|
+
conditionalFragment = mergeFragments([conditionalFragment, comparedValue], (c) => c[0]);
|
|
1297
|
+
const operator = negatedCondition ? "!==" : "===";
|
|
1298
|
+
condition = `${comparedInputName} ${operator} ${comparedValue.content}`;
|
|
1299
|
+
} else {
|
|
1300
|
+
condition = negatedCondition ? `!${comparedInputName}` : comparedInputName;
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
if (ifTrueRenderer && ifFalseRenderer) {
|
|
1304
|
+
return setFragmentContent(
|
|
1305
|
+
conditionalFragment,
|
|
1306
|
+
`if (${condition}) {
|
|
1307
|
+
${ifTrueRenderer.content}
|
|
1308
|
+
} else {
|
|
1309
|
+
${ifFalseRenderer.content}
|
|
1310
|
+
}`
|
|
1311
|
+
);
|
|
1312
|
+
}
|
|
1313
|
+
return setFragmentContent(
|
|
1314
|
+
conditionalFragment,
|
|
1315
|
+
`if (${condition}) {
|
|
1316
|
+
${ifTrueRenderer ? ifTrueRenderer.content : ifFalseRenderer?.content}
|
|
1317
|
+
}`
|
|
1318
|
+
);
|
|
1319
|
+
default:
|
|
1320
|
+
const valueManifest = visit4(defaultValue, typeManifestVisitor).value;
|
|
1321
|
+
return pipe5(valueManifest, (f) => mapFragmentContent4(f, (c) => defaultFragment(c).content));
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
function renderNestedInstructionDefault(scope) {
|
|
1325
|
+
const { input, defaultValue } = scope;
|
|
1326
|
+
if (!defaultValue) return void 0;
|
|
1327
|
+
return getInstructionInputDefaultFragment({
|
|
1328
|
+
...scope,
|
|
1329
|
+
input: { ...input, defaultValue }
|
|
1330
|
+
});
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
// src/fragments/instructionInputResolved.ts
|
|
1334
|
+
function getInstructionInputResolvedFragment(scope) {
|
|
1335
|
+
const instructionNode = getLastNodeFromPath10(scope.instructionPath);
|
|
1336
|
+
const resolvedInputFragments = scope.resolvedInputs.flatMap((input) => {
|
|
1337
|
+
const inputFragment = getInstructionInputDefaultFragment({
|
|
1338
|
+
...scope,
|
|
1339
|
+
input,
|
|
1340
|
+
optionalAccountStrategy: parseOptionalAccountStrategy(instructionNode.optionalAccountStrategy)
|
|
1341
|
+
});
|
|
1342
|
+
if (!inputFragment.content) return [];
|
|
1343
|
+
const camelName = camelCase6(input.name);
|
|
1344
|
+
return [
|
|
1345
|
+
mapFragmentContent5(
|
|
1346
|
+
inputFragment,
|
|
1347
|
+
(c) => isNode9(input, "instructionArgumentNode") ? `if (!args.${camelName}) {
|
|
1348
|
+
${c}
|
|
1349
|
+
}` : `if (!accounts.${camelName}.value) {
|
|
1350
|
+
${c}
|
|
1351
|
+
}`
|
|
1352
|
+
)
|
|
1353
|
+
];
|
|
1354
|
+
});
|
|
1355
|
+
if (resolvedInputFragments.length === 0) {
|
|
1356
|
+
return fragment``;
|
|
1357
|
+
}
|
|
1358
|
+
return mergeFragments([fragment`// Resolve default values.`, ...resolvedInputFragments], (c) => c.join("\n"));
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
// src/fragments/instructionInputType.ts
|
|
1362
|
+
import {
|
|
1363
|
+
camelCase as camelCase7,
|
|
1364
|
+
getAllInstructionArguments,
|
|
1365
|
+
isNode as isNode10,
|
|
1366
|
+
pascalCase as pascalCase4
|
|
1367
|
+
} from "@codama/nodes";
|
|
1368
|
+
import { mapFragmentContent as mapFragmentContent6 } from "@codama/renderers-core";
|
|
1369
|
+
import {
|
|
1370
|
+
getLastNodeFromPath as getLastNodeFromPath11,
|
|
1371
|
+
pipe as pipe6
|
|
1372
|
+
} from "@codama/visitors-core";
|
|
1373
|
+
function getInstructionInputTypeFragment(scope) {
|
|
1374
|
+
const { instructionPath, useAsync, nameApi } = scope;
|
|
1375
|
+
const instructionNode = getLastNodeFromPath11(instructionPath);
|
|
1376
|
+
const instructionInputType = useAsync ? nameApi.instructionAsyncInputType(instructionNode.name) : nameApi.instructionSyncInputType(instructionNode.name);
|
|
1377
|
+
const [dataArgumentsFragment, customDataArgumentsFragment] = getDataArgumentsFragments(scope);
|
|
1378
|
+
let accountTypeParams = "";
|
|
1379
|
+
if (instructionNode.accounts.length > 0) {
|
|
1380
|
+
accountTypeParams = instructionNode.accounts.map((account) => `TAccount${pascalCase4(account.name)} extends string = string`).join(", ");
|
|
1381
|
+
accountTypeParams = `<${accountTypeParams}>`;
|
|
1382
|
+
}
|
|
1383
|
+
const typeBodyFragment = mergeFragments(
|
|
1384
|
+
[
|
|
1385
|
+
getAccountsFragment(scope),
|
|
1386
|
+
dataArgumentsFragment,
|
|
1387
|
+
getExtraArgumentsFragment(scope),
|
|
1388
|
+
getRemainingAccountsFragment(instructionNode)
|
|
1389
|
+
],
|
|
1390
|
+
(c) => c.join("\n")
|
|
1391
|
+
);
|
|
1392
|
+
return fragment`export type ${instructionInputType}${accountTypeParams} = ${customDataArgumentsFragment} {
|
|
1393
|
+
${typeBodyFragment}
|
|
1394
|
+
}`;
|
|
1395
|
+
}
|
|
1396
|
+
function getAccountsFragment(scope) {
|
|
1397
|
+
const { instructionPath, resolvedInputs, useAsync, asyncResolvers } = scope;
|
|
1398
|
+
const instructionNode = getLastNodeFromPath11(instructionPath);
|
|
1399
|
+
const fragments = instructionNode.accounts.map((account) => {
|
|
1400
|
+
const resolvedAccount = resolvedInputs.find(
|
|
1401
|
+
(input) => input.kind === "instructionAccountNode" && input.name === account.name
|
|
1402
|
+
);
|
|
1403
|
+
const hasDefaultValue = !!resolvedAccount.defaultValue && !isNode10(resolvedAccount.defaultValue, ["identityValueNode", "payerValueNode"]) && (useAsync || !isAsyncDefaultValue(resolvedAccount.defaultValue, asyncResolvers));
|
|
1404
|
+
const docs = getDocblockFragment(account.docs ?? [], true);
|
|
1405
|
+
const optionalSign = hasDefaultValue || resolvedAccount.isOptional ? "?" : "";
|
|
1406
|
+
return fragment`${docs}${camelCase7(account.name)}${optionalSign}: ${getAccountTypeFragment2(resolvedAccount)};`;
|
|
1407
|
+
});
|
|
1408
|
+
return mergeFragments(fragments, (c) => c.join("\n"));
|
|
1409
|
+
}
|
|
1410
|
+
function getAccountTypeFragment2(account) {
|
|
1411
|
+
const typeParam = `TAccount${pascalCase4(account.name)}`;
|
|
1412
|
+
const address = use("type Address", "solanaAddresses");
|
|
1413
|
+
const signer = use("type TransactionSigner", "solanaSigners");
|
|
1414
|
+
const pda = use("type ProgramDerivedAddress", "solanaAddresses");
|
|
1415
|
+
if (account.isPda && account.isSigner === false) return fragment`${pda}<${typeParam}>`;
|
|
1416
|
+
if (account.isPda && account.isSigner === "either") return fragment`${pda}<${typeParam}> | ${signer}<${typeParam}>`;
|
|
1417
|
+
if (account.isSigner === "either") return fragment`${address}<${typeParam}> | ${signer}<${typeParam}>`;
|
|
1418
|
+
if (account.isSigner) return fragment`${signer}<${typeParam}>`;
|
|
1419
|
+
return fragment`${address}<${typeParam}>`;
|
|
1420
|
+
}
|
|
1421
|
+
function getDataArgumentsFragments(scope) {
|
|
1422
|
+
const { instructionPath, nameApi } = scope;
|
|
1423
|
+
const instructionNode = getLastNodeFromPath11(instructionPath);
|
|
1424
|
+
const customData = scope.customInstructionData.get(instructionNode.name);
|
|
1425
|
+
if (customData) {
|
|
1426
|
+
return [
|
|
1427
|
+
void 0,
|
|
1428
|
+
pipe6(
|
|
1429
|
+
fragment`${nameApi.dataArgsType(customData.importAs)}`,
|
|
1430
|
+
(f) => mergeFragmentImports(f, [scope.dataArgsManifest.looseType.imports]),
|
|
1431
|
+
(f) => mapFragmentContent6(f, (c) => `${c} & `)
|
|
1432
|
+
)
|
|
1433
|
+
];
|
|
1434
|
+
}
|
|
1435
|
+
const instructionDataName = nameApi.instructionDataType(instructionNode.name);
|
|
1436
|
+
const dataArgsType = nameApi.dataArgsType(instructionDataName);
|
|
1437
|
+
const fragments = instructionNode.arguments.flatMap((arg) => {
|
|
1438
|
+
const argFragment = getArgumentFragment(arg, dataArgsType, scope.resolvedInputs, scope.renamedArgs);
|
|
1439
|
+
return argFragment ? [argFragment] : [];
|
|
1440
|
+
});
|
|
1441
|
+
return [fragments.length === 0 ? void 0 : mergeFragments(fragments, (c) => c.join("\n")), fragment``];
|
|
1442
|
+
}
|
|
1443
|
+
function getExtraArgumentsFragment(scope) {
|
|
1444
|
+
const { instructionPath, nameApi } = scope;
|
|
1445
|
+
const instructionNode = getLastNodeFromPath11(instructionPath);
|
|
1446
|
+
const instructionExtraName = nameApi.instructionExtraType(instructionNode.name);
|
|
1447
|
+
const extraArgsType = nameApi.dataArgsType(instructionExtraName);
|
|
1448
|
+
const fragments = (instructionNode.extraArguments ?? []).flatMap((arg) => {
|
|
1449
|
+
const argFragment = getArgumentFragment(arg, extraArgsType, scope.resolvedInputs, scope.renamedArgs);
|
|
1450
|
+
return argFragment ? [argFragment] : [];
|
|
1451
|
+
});
|
|
1452
|
+
if (fragments.length === 0) return;
|
|
1453
|
+
return mergeFragments(fragments, (c) => c.join("\n"));
|
|
1454
|
+
}
|
|
1455
|
+
function getArgumentFragment(arg, argsType, resolvedInputs, renamedArgs) {
|
|
1456
|
+
const resolvedArg = resolvedInputs.find(
|
|
1457
|
+
(input) => isNode10(input, "instructionArgumentNode") && input.name === arg.name
|
|
1458
|
+
);
|
|
1459
|
+
if (arg.defaultValue && arg.defaultValueStrategy === "omitted") return null;
|
|
1460
|
+
const renamedName = renamedArgs.get(arg.name) ?? arg.name;
|
|
1461
|
+
const optionalSign = arg.defaultValue || resolvedArg?.defaultValue ? "?" : "";
|
|
1462
|
+
return fragment`${camelCase7(renamedName)}${optionalSign}: ${argsType}["${camelCase7(arg.name)}"];`;
|
|
1463
|
+
}
|
|
1464
|
+
function getRemainingAccountsFragment(instructionNode) {
|
|
1465
|
+
const fragments = (instructionNode.remainingAccounts ?? []).flatMap((remainingAccountsNode) => {
|
|
1466
|
+
if (isNode10(remainingAccountsNode.value, "resolverValueNode")) return [];
|
|
1467
|
+
const { name } = remainingAccountsNode.value;
|
|
1468
|
+
const allArguments = getAllInstructionArguments(instructionNode);
|
|
1469
|
+
const argumentExists = allArguments.some((arg) => arg.name === name);
|
|
1470
|
+
if (argumentExists) return [];
|
|
1471
|
+
const isSigner = remainingAccountsNode.isSigner ?? false;
|
|
1472
|
+
const optionalSign = remainingAccountsNode.isOptional ?? false ? "?" : "";
|
|
1473
|
+
const signerFragment = use("type TransactionSigner", "solanaSigners");
|
|
1474
|
+
const addressFragment = use("type Address", "solanaAddresses");
|
|
1475
|
+
const typeFragment = (() => {
|
|
1476
|
+
if (isSigner === "either") return fragment`${signerFragment} | ${addressFragment}`;
|
|
1477
|
+
return isSigner ? signerFragment : addressFragment;
|
|
1478
|
+
})();
|
|
1479
|
+
return fragment`${camelCase7(name)}${optionalSign}: Array<${typeFragment}>;`;
|
|
1480
|
+
});
|
|
1481
|
+
if (fragments.length === 0) return;
|
|
1482
|
+
return mergeFragments(fragments, (c) => c.join("\n"));
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
// src/fragments/instructionRemainingAccounts.ts
|
|
1486
|
+
import {
|
|
1487
|
+
assertIsNode as assertIsNode2,
|
|
1488
|
+
camelCase as camelCase8,
|
|
1489
|
+
getAllInstructionArguments as getAllInstructionArguments2,
|
|
1490
|
+
isNode as isNode11
|
|
1491
|
+
} from "@codama/nodes";
|
|
1492
|
+
import { getLastNodeFromPath as getLastNodeFromPath12, pipe as pipe7 } from "@codama/visitors-core";
|
|
1493
|
+
function getInstructionRemainingAccountsFragment(scope) {
|
|
1494
|
+
const { remainingAccounts } = getLastNodeFromPath12(scope.instructionPath);
|
|
1495
|
+
const fragments = (remainingAccounts ?? []).flatMap((a) => getRemainingAccountsFragment2(a, scope));
|
|
1496
|
+
if (fragments.length === 0) return;
|
|
1497
|
+
return pipe7(
|
|
1498
|
+
mergeFragments(
|
|
1499
|
+
fragments,
|
|
1500
|
+
(c) => `// Remaining accounts.
|
|
1501
|
+
const remainingAccounts: AccountMeta[] = ${c.length === 1 ? c[0] : `[...${c.join(", ...")}]`}`
|
|
1502
|
+
),
|
|
1503
|
+
(f) => addFragmentImports(f, "solanaInstructions", ["type AccountMeta"])
|
|
1504
|
+
);
|
|
1505
|
+
}
|
|
1506
|
+
function getRemainingAccountsFragment2(remainingAccounts, scope) {
|
|
1507
|
+
const remainingAccountsFragment = (() => {
|
|
1508
|
+
if (isNode11(remainingAccounts.value, "argumentValueNode")) {
|
|
1509
|
+
return getArgumentValueNodeFragment2(remainingAccounts, scope);
|
|
1510
|
+
}
|
|
1511
|
+
if (isNode11(remainingAccounts.value, "resolverValueNode")) {
|
|
1512
|
+
return getResolverValueNodeFragment2(remainingAccounts, scope);
|
|
1513
|
+
}
|
|
1514
|
+
return null;
|
|
1515
|
+
})();
|
|
1516
|
+
if (remainingAccountsFragment === null) return [];
|
|
1517
|
+
return [remainingAccountsFragment];
|
|
1518
|
+
}
|
|
1519
|
+
function getArgumentValueNodeFragment2(remainingAccounts, scope) {
|
|
1520
|
+
const instructionNode = getLastNodeFromPath12(scope.instructionPath);
|
|
1521
|
+
assertIsNode2(remainingAccounts.value, "argumentValueNode");
|
|
1522
|
+
const argumentName = camelCase8(remainingAccounts.value.name);
|
|
1523
|
+
const isOptional = remainingAccounts.isOptional ?? false;
|
|
1524
|
+
const isSigner = remainingAccounts.isSigner ?? false;
|
|
1525
|
+
const isWritable = remainingAccounts.isWritable ?? false;
|
|
1526
|
+
const accountRole = use("AccountRole", "solanaInstructions");
|
|
1527
|
+
const nonSignerRole = isWritable ? fragment`${accountRole}.WRITABLE` : fragment`${accountRole}.READONLY`;
|
|
1528
|
+
const signerRole = isWritable ? fragment`${accountRole}.WRITABLE_SIGNER` : fragment`${accountRole}.READONLY_SIGNER`;
|
|
1529
|
+
const role = isSigner === true ? signerRole : nonSignerRole;
|
|
1530
|
+
const argumentArray = isOptional ? `(args.${argumentName} ?? [])` : `args.${argumentName}`;
|
|
1531
|
+
const allArguments = getAllInstructionArguments2(instructionNode);
|
|
1532
|
+
const argumentExists = allArguments.some((arg) => arg.name === remainingAccounts.value.name);
|
|
1533
|
+
if (argumentExists || isSigner === false) {
|
|
1534
|
+
return fragment`${argumentArray}.map((address) => ({ address, role: ${role} }))`;
|
|
1535
|
+
}
|
|
1536
|
+
if (isSigner === "either") {
|
|
1537
|
+
return fragment`${argumentArray}.map((addressOrSigner) => (${use("isTransactionSigner", "shared")}(addressOrSigner) ? { address: addressOrSigner.address, role: ${role}, signer: addressOrSigner } : { address: addressOrSigner, role: ${role} }))`;
|
|
1538
|
+
}
|
|
1539
|
+
return fragment`${argumentArray}.map((signer) => ({ address: signer.address, role: ${signerRole}, signer }))`;
|
|
1540
|
+
}
|
|
1541
|
+
function getResolverValueNodeFragment2(remainingAccounts, scope) {
|
|
1542
|
+
assertIsNode2(remainingAccounts.value, "resolverValueNode");
|
|
1543
|
+
const isAsync = scope.asyncResolvers.includes(remainingAccounts.value.name);
|
|
1544
|
+
if (!scope.useAsync && isAsync) return null;
|
|
1545
|
+
const awaitKeyword = scope.useAsync && isAsync ? "await " : "";
|
|
1546
|
+
const functionName = use(
|
|
1547
|
+
scope.nameApi.resolverFunction(remainingAccounts.value.name),
|
|
1548
|
+
scope.getImportFrom(remainingAccounts.value)
|
|
1549
|
+
);
|
|
1550
|
+
return pipe7(
|
|
1551
|
+
fragment`${awaitKeyword}${functionName}(resolverScope)`,
|
|
1552
|
+
(f) => addFragmentFeatures(f, ["instruction:resolverScopeVariable"])
|
|
1553
|
+
);
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
// src/fragments/instructionFunction.ts
|
|
1557
|
+
function getInstructionFunctionFragment(scope) {
|
|
1558
|
+
const { useAsync, instructionPath, resolvedInputs, renamedArgs, asyncResolvers, nameApi, customInstructionData } = scope;
|
|
1559
|
+
const instructionNode = getLastNodeFromPath13(instructionPath);
|
|
1560
|
+
const programNode = findProgramNodeFromPath3(instructionPath);
|
|
1561
|
+
if (useAsync && !hasAsyncFunction(instructionNode, resolvedInputs, asyncResolvers)) return;
|
|
1562
|
+
const customData = customInstructionData.get(instructionNode.name);
|
|
1563
|
+
const hasAccounts = instructionNode.accounts.length > 0;
|
|
1564
|
+
const instructionDependencies = getInstructionDependencies(instructionNode, asyncResolvers, useAsync);
|
|
1565
|
+
const argDependencies = instructionDependencies.filter(isNodeFilter4("argumentValueNode")).map((node) => node.name);
|
|
1566
|
+
const hasData = !!customData || instructionNode.arguments.length > 0;
|
|
1567
|
+
const argIsNotOmitted = (arg) => !(arg.defaultValue && arg.defaultValueStrategy === "omitted");
|
|
1568
|
+
const argIsDependent = (arg) => argDependencies.includes(arg.name);
|
|
1569
|
+
const argHasDefaultValue = (arg) => {
|
|
1570
|
+
if (!arg.defaultValue) return false;
|
|
1571
|
+
if (useAsync) return true;
|
|
1572
|
+
return !isAsyncDefaultValue(arg.defaultValue, asyncResolvers);
|
|
1573
|
+
};
|
|
1574
|
+
const hasDataArgs = !!customData || instructionNode.arguments.filter(argIsNotOmitted).length > 0;
|
|
1575
|
+
const hasExtraArgs = (instructionNode.extraArguments ?? []).filter(
|
|
1576
|
+
(field) => argIsNotOmitted(field) && (argIsDependent(field) || argHasDefaultValue(field))
|
|
1577
|
+
).length > 0;
|
|
1578
|
+
const hasRemainingAccountArgs = (instructionNode.remainingAccounts ?? []).filter(({ value }) => isNode12(value, "argumentValueNode")).length > 0;
|
|
1579
|
+
const hasAnyArgs = hasDataArgs || hasExtraArgs || hasRemainingAccountArgs;
|
|
1580
|
+
const hasInput = hasAccounts || hasAnyArgs;
|
|
1581
|
+
const programAddressConstant = use(nameApi.programAddressConstant(programNode.name), "generatedPrograms");
|
|
1582
|
+
const functionName = useAsync ? nameApi.instructionAsyncFunction(instructionNode.name) : nameApi.instructionSyncFunction(instructionNode.name);
|
|
1583
|
+
const resolvedInputsFragment = getInstructionInputResolvedFragment(scope);
|
|
1584
|
+
const remainingAccountsFragment = getInstructionRemainingAccountsFragment(scope);
|
|
1585
|
+
const byteDeltaFragment = getInstructionByteDeltaFragment(scope);
|
|
1586
|
+
const resolvedInputFragment = mergeFragments(
|
|
1587
|
+
[resolvedInputsFragment, remainingAccountsFragment, byteDeltaFragment],
|
|
1588
|
+
(content) => content.join("\n\n")
|
|
1589
|
+
);
|
|
1590
|
+
const hasRemainingAccounts = !!remainingAccountsFragment;
|
|
1591
|
+
const hasByteDeltas = !!byteDeltaFragment;
|
|
1592
|
+
const hasResolver = resolvedInputFragment.features.has("instruction:resolverScopeVariable");
|
|
1593
|
+
const instructionTypeFragment = getInstructionTypeFragment(scope);
|
|
1594
|
+
const typeParams = getTypeParamsFragment(instructionNode, programAddressConstant);
|
|
1595
|
+
const returnType = getReturnTypeFragment(instructionTypeFragment, hasByteDeltas, useAsync);
|
|
1596
|
+
const inputType = getInstructionInputTypeFragment(scope);
|
|
1597
|
+
const inputArg = mapFragmentContent7(getInputTypeCallFragment(scope), (c) => hasInput ? `input: ${c}, ` : "");
|
|
1598
|
+
const functionBody = mergeFragments(
|
|
1599
|
+
[
|
|
1600
|
+
getProgramAddressInitializationFragment(programAddressConstant),
|
|
1601
|
+
getAccountsInitializationFragment(instructionNode),
|
|
1602
|
+
getArgumentsInitializationFragment(hasAnyArgs, renamedArgs),
|
|
1603
|
+
getResolverScopeInitializationFragment(hasResolver, hasAccounts, hasAnyArgs),
|
|
1604
|
+
resolvedInputFragment,
|
|
1605
|
+
getReturnStatementFragment({
|
|
1606
|
+
...scope,
|
|
1607
|
+
hasByteDeltas,
|
|
1608
|
+
hasData,
|
|
1609
|
+
hasDataArgs,
|
|
1610
|
+
hasRemainingAccounts,
|
|
1611
|
+
instructionNode,
|
|
1612
|
+
syncReturnTypeFragment: getReturnTypeFragment(instructionTypeFragment, hasByteDeltas, false)
|
|
1613
|
+
})
|
|
1614
|
+
],
|
|
1615
|
+
(cs) => cs.join("\n\n")
|
|
1616
|
+
);
|
|
1617
|
+
return fragment`${inputType}\n\nexport ${useAsync ? "async " : ""}function ${functionName}${typeParams}(${inputArg}config?: { programAddress?: TProgramAddress } ): ${returnType} {
|
|
1618
|
+
${functionBody}
|
|
1619
|
+
}`;
|
|
1620
|
+
}
|
|
1621
|
+
function getProgramAddressInitializationFragment(programAddressConstant) {
|
|
1622
|
+
return fragment`// Program address.
|
|
1623
|
+
const programAddress = config?.programAddress ?? ${programAddressConstant};`;
|
|
1624
|
+
}
|
|
1625
|
+
function getAccountsInitializationFragment(instructionNode) {
|
|
1626
|
+
if (instructionNode.accounts.length === 0) return;
|
|
1627
|
+
const accounts = mergeFragments(
|
|
1628
|
+
instructionNode.accounts.map((account) => {
|
|
1629
|
+
const name = camelCase9(account.name);
|
|
1630
|
+
const isWritable = account.isWritable ? "true" : "false";
|
|
1631
|
+
return fragment`${name}: { value: input.${name} ?? null, isWritable: ${isWritable} }`;
|
|
1632
|
+
}),
|
|
1633
|
+
(cs) => cs.join(", ")
|
|
1634
|
+
);
|
|
1635
|
+
return fragment` // Original accounts.
|
|
1636
|
+
const originalAccounts = { ${accounts} }
|
|
1637
|
+
const accounts = originalAccounts as Record<keyof typeof originalAccounts, ${use("type ResolvedAccount", "shared")}>;
|
|
1638
|
+
`;
|
|
1639
|
+
}
|
|
1640
|
+
function getArgumentsInitializationFragment(hasAnyArgs, renamedArgs) {
|
|
1641
|
+
if (!hasAnyArgs) return;
|
|
1642
|
+
const renamedArgsText = [...renamedArgs.entries()].map(([k, v]) => `${k}: input.${v}`).join(", ");
|
|
1643
|
+
return fragment`// Original args.
|
|
1644
|
+
const args = { ...input, ${renamedArgsText} };
|
|
1645
|
+
`;
|
|
1646
|
+
}
|
|
1647
|
+
function getResolverScopeInitializationFragment(hasResolver, hasAccounts, hasAnyArgs) {
|
|
1648
|
+
if (!hasResolver) return;
|
|
1649
|
+
const resolverAttributes = [
|
|
1650
|
+
"programAddress",
|
|
1651
|
+
...hasAccounts ? ["accounts"] : [],
|
|
1652
|
+
...hasAnyArgs ? ["args"] : []
|
|
1653
|
+
].join(", ");
|
|
1654
|
+
return fragment`// Resolver scope.
|
|
1655
|
+
const resolverScope = { ${resolverAttributes} };`;
|
|
1656
|
+
}
|
|
1657
|
+
function getReturnStatementFragment(scope) {
|
|
1658
|
+
const { instructionNode, hasByteDeltas, hasData, hasDataArgs, hasRemainingAccounts, nameApi } = scope;
|
|
1659
|
+
const optionalAccountStrategy = instructionNode.optionalAccountStrategy ?? "programId";
|
|
1660
|
+
const hasAccounts = instructionNode.accounts.length > 0;
|
|
1661
|
+
const hasLegacyOptionalAccounts = instructionNode.optionalAccountStrategy === "omitted" && instructionNode.accounts.some((account) => account.isOptional);
|
|
1662
|
+
const getAccountMeta = hasAccounts ? fragment`const getAccountMeta = ${use("getAccountMetaFactory", "shared")}(programAddress, '${optionalAccountStrategy}');` : "";
|
|
1663
|
+
const accountItems = [
|
|
1664
|
+
...instructionNode.accounts.map((account) => `getAccountMeta(accounts.${camelCase9(account.name)})`),
|
|
1665
|
+
...hasRemainingAccounts ? ["...remainingAccounts"] : []
|
|
1666
|
+
].join(", ");
|
|
1667
|
+
let accounts;
|
|
1668
|
+
if (hasAccounts && hasLegacyOptionalAccounts) {
|
|
1669
|
+
accounts = fragment`accounts: [${accountItems}].filter(<T>(x: T | undefined): x is T => x !== undefined)`;
|
|
1670
|
+
} else if (hasAccounts) {
|
|
1671
|
+
accounts = fragment`accounts: [${accountItems}]`;
|
|
1672
|
+
} else if (hasRemainingAccounts) {
|
|
1673
|
+
accounts = fragment`accounts: remainingAccounts`;
|
|
1674
|
+
}
|
|
1675
|
+
const customData = scope.customInstructionData.get(instructionNode.name);
|
|
1676
|
+
const instructionDataName = nameApi.instructionDataType(instructionNode.name);
|
|
1677
|
+
const encoderFunctionFragment = customData ? scope.dataArgsManifest.encoder : `${nameApi.encoderFunction(instructionDataName)}()`;
|
|
1678
|
+
const argsTypeFragment = customData ? scope.dataArgsManifest.looseType : nameApi.dataArgsType(instructionDataName);
|
|
1679
|
+
let data;
|
|
1680
|
+
if (hasDataArgs) {
|
|
1681
|
+
data = fragment`data: ${encoderFunctionFragment}.encode(args as ${argsTypeFragment})`;
|
|
1682
|
+
} else if (hasData) {
|
|
1683
|
+
data = fragment`data: ${encoderFunctionFragment}.encode({})`;
|
|
1684
|
+
}
|
|
1685
|
+
const instructionAttributes = pipe8(
|
|
1686
|
+
[accounts, hasByteDeltas ? fragment`byteDelta` : void 0, data, fragment`programAddress`],
|
|
1687
|
+
(fs) => mergeFragments(fs, (cs) => cs.join(", "))
|
|
1688
|
+
);
|
|
1689
|
+
return fragment`${getAccountMeta}\nreturn Object.freeze({ ${instructionAttributes} } as ${scope.syncReturnTypeFragment});`;
|
|
1690
|
+
}
|
|
1691
|
+
function getReturnTypeFragment(instructionTypeFragment, hasByteDeltas, useAsync) {
|
|
1692
|
+
return pipe8(
|
|
1693
|
+
instructionTypeFragment,
|
|
1694
|
+
(f) => hasByteDeltas ? fragment`${f} & ${use("type InstructionWithByteDelta", "shared")}` : f,
|
|
1695
|
+
(f) => useAsync ? fragment`Promise<${f}>` : f
|
|
1696
|
+
);
|
|
1697
|
+
}
|
|
1698
|
+
function getTypeParamsFragment(instructionNode, programAddressConstant) {
|
|
1699
|
+
return mergeFragments(
|
|
1700
|
+
[
|
|
1701
|
+
...instructionNode.accounts.map((account) => fragment`TAccount${pascalCase5(account.name)} extends string`),
|
|
1702
|
+
fragment`TProgramAddress extends ${use("type Address", "solanaAddresses")} = typeof ${programAddressConstant}`
|
|
1703
|
+
],
|
|
1704
|
+
(cs) => `<${cs.join(", ")}>`
|
|
1705
|
+
);
|
|
1706
|
+
}
|
|
1707
|
+
function getInstructionTypeFragment(scope) {
|
|
1708
|
+
const { instructionPath, nameApi } = scope;
|
|
1709
|
+
const instructionNode = getLastNodeFromPath13(instructionPath);
|
|
1710
|
+
const instructionTypeName = nameApi.instructionType(instructionNode.name);
|
|
1711
|
+
const accountTypeParamsFragments = instructionNode.accounts.map((account) => {
|
|
1712
|
+
const typeParam = fragment`TAccount${pascalCase5(account.name)}`;
|
|
1713
|
+
const camelName = camelCase9(account.name);
|
|
1714
|
+
if (account.isSigner === "either") {
|
|
1715
|
+
const signerRole = use(
|
|
1716
|
+
account.isWritable ? "type WritableSignerAccount" : "type ReadonlySignerAccount",
|
|
1717
|
+
"solanaInstructions"
|
|
1718
|
+
);
|
|
1719
|
+
return pipe8(
|
|
1720
|
+
fragment`typeof input["${camelName}"] extends TransactionSigner<${typeParam}> ? ${signerRole}<${typeParam}> & AccountSignerMeta<${typeParam}> : ${typeParam}`,
|
|
1721
|
+
(f) => addFragmentImports(f, "solanaSigners", ["type AccountSignerMeta", "type TransactionSigner"])
|
|
1722
|
+
);
|
|
1723
|
+
}
|
|
1724
|
+
return typeParam;
|
|
1725
|
+
});
|
|
1726
|
+
return pipe8(
|
|
1727
|
+
mergeFragments([fragment`TProgramAddress`, ...accountTypeParamsFragments], (c) => c.join(", ")),
|
|
1728
|
+
(f) => mapFragmentContent7(f, (c) => `${instructionTypeName}<${c}>`)
|
|
1729
|
+
);
|
|
1730
|
+
}
|
|
1731
|
+
function getInputTypeCallFragment(scope) {
|
|
1732
|
+
const { instructionPath, useAsync, nameApi } = scope;
|
|
1733
|
+
const instructionNode = getLastNodeFromPath13(instructionPath);
|
|
1734
|
+
const inputTypeName = useAsync ? nameApi.instructionAsyncInputType(instructionNode.name) : nameApi.instructionSyncInputType(instructionNode.name);
|
|
1735
|
+
if (instructionNode.accounts.length === 0) return fragment`${inputTypeName}`;
|
|
1736
|
+
const accountTypeParams = instructionNode.accounts.map((account) => `TAccount${pascalCase5(account.name)}`).join(", ");
|
|
1737
|
+
return fragment`${inputTypeName}<${accountTypeParams}>`;
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
// src/fragments/instructionPage.ts
|
|
1741
|
+
import { logWarn } from "@codama/errors";
|
|
1742
|
+
import { camelCase as camelCase11, definedTypeNode as definedTypeNode2, structTypeNodeFromInstructionArgumentNodes as structTypeNodeFromInstructionArgumentNodes3 } from "@codama/nodes";
|
|
1743
|
+
import {
|
|
1744
|
+
findProgramNodeFromPath as findProgramNodeFromPath6,
|
|
1745
|
+
getLastNodeFromPath as getLastNodeFromPath16,
|
|
1746
|
+
visit as visit5
|
|
1747
|
+
} from "@codama/visitors-core";
|
|
1748
|
+
|
|
1749
|
+
// src/fragments/instructionParseFunction.ts
|
|
1750
|
+
import { camelCase as camelCase10 } from "@codama/nodes";
|
|
1751
|
+
import { findProgramNodeFromPath as findProgramNodeFromPath4, getLastNodeFromPath as getLastNodeFromPath14, pipe as pipe9 } from "@codama/visitors-core";
|
|
1752
|
+
function getInstructionParseFunctionFragment(scope) {
|
|
1753
|
+
const instructionNode = getLastNodeFromPath14(scope.instructionPath);
|
|
1754
|
+
const programNode = findProgramNodeFromPath4(scope.instructionPath);
|
|
1755
|
+
const programAddressConstant = use(scope.nameApi.programAddressConstant(programNode.name), "generatedPrograms");
|
|
1756
|
+
const childScope = { ...scope, instructionNode, programAddressConstant };
|
|
1757
|
+
return mergeFragments([getTypeFragment2(childScope), getFunctionFragment(childScope)], (cs) => cs.join("\n\n"));
|
|
1758
|
+
}
|
|
1759
|
+
function getTypeFragment2(scope) {
|
|
1760
|
+
const customData = scope.customInstructionData.get(scope.instructionNode.name);
|
|
1761
|
+
const instructionParsedType = scope.nameApi.instructionParsedType(scope.instructionNode.name);
|
|
1762
|
+
const instructionDataName = scope.nameApi.instructionDataType(scope.instructionNode.name);
|
|
1763
|
+
const hasData = !!customData || scope.instructionNode.arguments.length > 0;
|
|
1764
|
+
const hasAccounts = scope.instructionNode.accounts.length > 0;
|
|
1765
|
+
const typeParamDeclarations = mergeFragments(
|
|
1766
|
+
[
|
|
1767
|
+
fragment`TProgram extends string = typeof ${scope.programAddressConstant}`,
|
|
1768
|
+
hasAccounts ? fragment`TAccountMetas extends readonly ${use("type AccountMeta", "solanaInstructions")}[] = readonly AccountMeta[]` : void 0
|
|
1769
|
+
],
|
|
1770
|
+
(cs) => cs.join(", ")
|
|
1771
|
+
);
|
|
1772
|
+
const accounts = mergeFragments(
|
|
1773
|
+
scope.instructionNode.accounts.map((account, i) => {
|
|
1774
|
+
const docs = getDocblockFragment(account.docs ?? [], true);
|
|
1775
|
+
const name = camelCase10(account.name);
|
|
1776
|
+
return fragment`${docs}${name}${account.isOptional ? "?" : ""}: TAccountMetas[${i}]${account.isOptional ? " | undefined" : ""};`;
|
|
1777
|
+
}),
|
|
1778
|
+
(cs) => hasAccounts ? `
|
|
1779
|
+
accounts: {
|
|
1780
|
+
${cs.join("\n")}
|
|
1781
|
+
};` : ""
|
|
1782
|
+
);
|
|
1783
|
+
const dataTypeFragment = customData ? scope.dataArgsManifest.strictType : fragment`${scope.nameApi.dataType(instructionDataName)}`;
|
|
1784
|
+
const data = hasData ? fragment`\ndata: ${dataTypeFragment};` : fragment``;
|
|
1785
|
+
return fragment`export type ${instructionParsedType}<${typeParamDeclarations}> = { programAddress: ${use("type Address", "solanaAddresses")}<TProgram>;${accounts}${data} };`;
|
|
1786
|
+
}
|
|
1787
|
+
function getFunctionFragment(scope) {
|
|
1788
|
+
const customData = scope.customInstructionData.get(scope.instructionNode.name);
|
|
1789
|
+
const instructionParsedType = scope.nameApi.instructionParsedType(scope.instructionNode.name);
|
|
1790
|
+
const instructionParseFunction = scope.nameApi.instructionParseFunction(scope.instructionNode.name);
|
|
1791
|
+
const instructionDataName = scope.nameApi.instructionDataType(scope.instructionNode.name);
|
|
1792
|
+
const decoderFunction = customData ? scope.dataArgsManifest.decoder : fragment`${scope.nameApi.decoderFunction(instructionDataName)}()`;
|
|
1793
|
+
const hasData = !!customData || scope.instructionNode.arguments.length > 0;
|
|
1794
|
+
const hasAccounts = scope.instructionNode.accounts.length > 0;
|
|
1795
|
+
const hasOptionalAccounts = scope.instructionNode.accounts.some((account) => account.isOptional);
|
|
1796
|
+
const minimumNumberOfAccounts = scope.instructionNode.optionalAccountStrategy === "omitted" ? scope.instructionNode.accounts.filter((account) => !account.isOptional).length : scope.instructionNode.accounts.length;
|
|
1797
|
+
const typeParams = ["TProgram", hasAccounts ? "TAccountMetas" : void 0].filter(Boolean).join(", ");
|
|
1798
|
+
const typeParamDeclarations = mergeFragments(
|
|
1799
|
+
[
|
|
1800
|
+
fragment`TProgram extends string`,
|
|
1801
|
+
hasAccounts ? fragment`TAccountMetas extends readonly ${use("type AccountMeta", "solanaInstructions")}[]` : void 0
|
|
1802
|
+
],
|
|
1803
|
+
(cs) => cs.join(", ")
|
|
1804
|
+
);
|
|
1805
|
+
const instructionType = mergeFragments(
|
|
1806
|
+
[
|
|
1807
|
+
fragment`${use("type Instruction", "solanaInstructions")}<TProgram>`,
|
|
1808
|
+
hasAccounts ? fragment`${use("type InstructionWithAccounts", "solanaInstructions")}<TAccountMetas>` : void 0,
|
|
1809
|
+
hasData ? pipe9(
|
|
1810
|
+
fragment`InstructionWithData<ReadonlyUint8Array>`,
|
|
1811
|
+
(f) => addFragmentImports(f, "solanaInstructions", ["type InstructionWithData"]),
|
|
1812
|
+
(f) => addFragmentImports(f, "solanaCodecsCore", ["type ReadonlyUint8Array"])
|
|
1813
|
+
) : void 0
|
|
1814
|
+
],
|
|
1815
|
+
(cs) => cs.join(" & ")
|
|
1816
|
+
);
|
|
1817
|
+
let accountHelpers;
|
|
1818
|
+
if (hasAccounts) {
|
|
1819
|
+
accountHelpers = fragment`if (instruction.accounts.length < ${minimumNumberOfAccounts}) {
|
|
1820
|
+
// TODO: Coded error.
|
|
1821
|
+
throw new Error('Not enough accounts');
|
|
1822
|
+
}
|
|
1823
|
+
let accountIndex = 0;
|
|
1824
|
+
const getNextAccount = () => {
|
|
1825
|
+
const accountMeta = (instruction.accounts as TAccountMetas)[accountIndex]!;
|
|
1826
|
+
accountIndex += 1;
|
|
1827
|
+
return accountMeta;
|
|
1828
|
+
}`;
|
|
1829
|
+
}
|
|
1830
|
+
if (hasOptionalAccounts && scope.instructionNode.optionalAccountStrategy === "omitted") {
|
|
1831
|
+
accountHelpers = fragment`${accountHelpers}
|
|
1832
|
+
let optionalAccountsRemaining = instruction.accounts.length - ${minimumNumberOfAccounts};
|
|
1833
|
+
const getNextOptionalAccount = () => {
|
|
1834
|
+
if (optionalAccountsRemaining === 0) return undefined;
|
|
1835
|
+
optionalAccountsRemaining -= 1;
|
|
1836
|
+
return getNextAccount();
|
|
1837
|
+
};`;
|
|
1838
|
+
} else if (hasOptionalAccounts) {
|
|
1839
|
+
accountHelpers = fragment`${accountHelpers}
|
|
1840
|
+
const getNextOptionalAccount = () => {
|
|
1841
|
+
const accountMeta = getNextAccount();
|
|
1842
|
+
return accountMeta.address === ${scope.programAddressConstant} ? undefined : accountMeta;
|
|
1843
|
+
};`;
|
|
1844
|
+
}
|
|
1845
|
+
const accounts = mergeFragments(
|
|
1846
|
+
scope.instructionNode.accounts.map(
|
|
1847
|
+
(account) => account.isOptional ? fragment`${camelCase10(account.name)}: getNextOptionalAccount()` : fragment`${camelCase10(account.name)}: getNextAccount()`
|
|
1848
|
+
),
|
|
1849
|
+
(cs) => hasAccounts ? `, accounts: { ${cs.join(", ")} }` : ""
|
|
1850
|
+
);
|
|
1851
|
+
const data = hasData ? fragment`, data: ${decoderFunction}.decode(instruction.data)` : fragment``;
|
|
1852
|
+
return fragment`export function ${instructionParseFunction}<${typeParamDeclarations}>(instruction: ${instructionType}): ${instructionParsedType}<${typeParams}> {
|
|
1853
|
+
${accountHelpers}
|
|
1854
|
+
return { programAddress: instruction.programAddress${accounts}${data} };
|
|
1855
|
+
}`;
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
// src/fragments/instructionType.ts
|
|
1859
|
+
import { pascalCase as pascalCase6 } from "@codama/nodes";
|
|
1860
|
+
import { mapFragmentContent as mapFragmentContent8 } from "@codama/renderers-core";
|
|
1861
|
+
import { findProgramNodeFromPath as findProgramNodeFromPath5, getLastNodeFromPath as getLastNodeFromPath15 } from "@codama/visitors-core";
|
|
1862
|
+
function getInstructionTypeFragment2(scope) {
|
|
1863
|
+
const { instructionPath, nameApi, customInstructionData } = scope;
|
|
1864
|
+
const instructionNode = getLastNodeFromPath15(instructionPath);
|
|
1865
|
+
const programNode = findProgramNodeFromPath5(instructionPath);
|
|
1866
|
+
const hasAccounts = instructionNode.accounts.length > 0;
|
|
1867
|
+
const customData = customInstructionData.get(instructionNode.name);
|
|
1868
|
+
const hasData = !!customData || instructionNode.arguments.length > 0;
|
|
1869
|
+
const instructionType = nameApi.instructionType(instructionNode.name);
|
|
1870
|
+
const programAddressConstant = use(nameApi.programAddressConstant(programNode.name), "generatedPrograms");
|
|
1871
|
+
const accountTypeParams = mergeFragments(
|
|
1872
|
+
instructionNode.accounts.map(
|
|
1873
|
+
(account) => getInstructionAccountTypeParamFragment({
|
|
1874
|
+
...scope,
|
|
1875
|
+
allowAccountMeta: true,
|
|
1876
|
+
instructionAccountPath: [...instructionPath, account]
|
|
1877
|
+
})
|
|
1878
|
+
),
|
|
1879
|
+
(cs) => cs.length > 0 ? `${cs.join(", ")}, ` : ""
|
|
1880
|
+
);
|
|
1881
|
+
const data = hasData ? fragment` & ${use("type InstructionWithData", "solanaInstructions")}<${use("type ReadonlyUint8Array", "solanaCodecsCore")}>` : void 0;
|
|
1882
|
+
const usesLegacyOptionalAccounts = instructionNode.optionalAccountStrategy === "omitted";
|
|
1883
|
+
const accountMetasFragment = mergeFragments(
|
|
1884
|
+
instructionNode.accounts.map(
|
|
1885
|
+
(account) => mapFragmentContent8(getInstructionAccountMetaFragment(account), (c) => {
|
|
1886
|
+
const typeParam = `TAccount${pascalCase6(account.name)}`;
|
|
1887
|
+
const isLegacyOptional = account.isOptional && usesLegacyOptionalAccounts;
|
|
1888
|
+
const type = `${typeParam} extends string ? ${c} : ${typeParam}`;
|
|
1889
|
+
if (!isLegacyOptional) return type;
|
|
1890
|
+
return `...(${typeParam} extends undefined ? [] : [${type}])`;
|
|
1891
|
+
})
|
|
1892
|
+
),
|
|
1893
|
+
(c) => c.join(", ")
|
|
1894
|
+
);
|
|
1895
|
+
const instructionWithAccounts = use("type InstructionWithAccounts", "solanaInstructions");
|
|
1896
|
+
const accounts = hasAccounts ? fragment` & ${instructionWithAccounts}<[${accountMetasFragment}, ...TRemainingAccounts]>` : fragment` & ${instructionWithAccounts}<TRemainingAccounts>`;
|
|
1897
|
+
return fragment`export type ${instructionType}<TProgram extends string = typeof ${programAddressConstant}, ${accountTypeParams}TRemainingAccounts extends readonly ${use("type AccountMeta", "solanaInstructions")}<string>[] = []> =
|
|
1898
|
+
${use("type Instruction", "solanaInstructions")}<TProgram>${data}${accounts};`;
|
|
1899
|
+
}
|
|
1900
|
+
|
|
1901
|
+
// src/fragments/instructionPage.ts
|
|
1902
|
+
function getInstructionPageFragment(scope) {
|
|
1903
|
+
const node = getLastNodeFromPath16(scope.instructionPath);
|
|
1904
|
+
if (!findProgramNodeFromPath6(scope.instructionPath)) {
|
|
1905
|
+
throw new Error("Instruction must be visited inside a program.");
|
|
1906
|
+
}
|
|
1907
|
+
const childScope = {
|
|
1908
|
+
...scope,
|
|
1909
|
+
dataArgsManifest: visit5(node, scope.typeManifestVisitor),
|
|
1910
|
+
extraArgsManifest: visit5(
|
|
1911
|
+
definedTypeNode2({
|
|
1912
|
+
name: scope.nameApi.instructionExtraType(node.name),
|
|
1913
|
+
type: structTypeNodeFromInstructionArgumentNodes3(node.extraArguments ?? [])
|
|
1914
|
+
}),
|
|
1915
|
+
scope.typeManifestVisitor
|
|
1916
|
+
),
|
|
1917
|
+
renamedArgs: getRenamedArgsMap(node)
|
|
1918
|
+
};
|
|
1919
|
+
return mergeFragments(
|
|
1920
|
+
[
|
|
1921
|
+
getDiscriminatorConstantsFragment({
|
|
1922
|
+
...childScope,
|
|
1923
|
+
discriminatorNodes: node.discriminators ?? [],
|
|
1924
|
+
fields: node.arguments,
|
|
1925
|
+
prefix: node.name
|
|
1926
|
+
}),
|
|
1927
|
+
getInstructionTypeFragment2(childScope),
|
|
1928
|
+
getInstructionDataFragment(childScope),
|
|
1929
|
+
getInstructionExtraArgsFragment(childScope),
|
|
1930
|
+
getInstructionFunctionFragment({ ...childScope, useAsync: true }),
|
|
1931
|
+
getInstructionFunctionFragment({ ...childScope, useAsync: false }),
|
|
1932
|
+
getInstructionParseFunctionFragment(childScope)
|
|
1933
|
+
],
|
|
1934
|
+
(cs) => cs.join("\n\n")
|
|
1935
|
+
);
|
|
1936
|
+
}
|
|
1937
|
+
function getRenamedArgsMap(instruction) {
|
|
1938
|
+
const argNames = [
|
|
1939
|
+
...instruction.arguments.map((a) => a.name),
|
|
1940
|
+
...(instruction.extraArguments ?? []).map((a) => a.name)
|
|
1941
|
+
];
|
|
1942
|
+
const duplicateArgs = argNames.filter((e, i, a) => a.indexOf(e) !== i);
|
|
1943
|
+
if (duplicateArgs.length > 0) {
|
|
1944
|
+
throw new Error(`Duplicate args found: [${duplicateArgs.join(", ")}] in instruction [${instruction.name}].`);
|
|
1945
|
+
}
|
|
1946
|
+
const allNames = [...instruction.accounts.map((account) => account.name), ...argNames];
|
|
1947
|
+
const duplicates = allNames.filter((e, i, a) => a.indexOf(e) !== i);
|
|
1948
|
+
if (duplicates.length === 0) return /* @__PURE__ */ new Map();
|
|
1949
|
+
logWarn(
|
|
1950
|
+
`[JavaScript] Accounts and args of instruction [${instruction.name}] have the following conflicting attributes [${duplicates.join(", ")}]. Thus, the arguments have been renamed to avoid conflicts in the input type.`
|
|
1951
|
+
);
|
|
1952
|
+
return new Map(duplicates.map((name) => [camelCase11(name), camelCase11(`${name}Arg`)]));
|
|
1953
|
+
}
|
|
1954
|
+
|
|
1955
|
+
// src/fragments/pdaFunction.ts
|
|
1956
|
+
import { camelCase as camelCase12, isNode as isNode13, isNodeFilter as isNodeFilter5 } from "@codama/nodes";
|
|
1957
|
+
import { findProgramNodeFromPath as findProgramNodeFromPath7, getLastNodeFromPath as getLastNodeFromPath17, visit as visit6 } from "@codama/visitors-core";
|
|
1958
|
+
function getPdaFunctionFragment(scope) {
|
|
1959
|
+
const pdaNode = getLastNodeFromPath17(scope.pdaPath);
|
|
1960
|
+
const seeds = parsePdaSeedNodes(pdaNode.seeds, scope);
|
|
1961
|
+
return mergeFragments(
|
|
1962
|
+
[getSeedInputTypeFragment(seeds, scope), getFunctionFragment2(seeds, scope)],
|
|
1963
|
+
(cs) => cs.join("\n\n")
|
|
1964
|
+
);
|
|
1965
|
+
}
|
|
1966
|
+
function getSeedInputTypeFragment(seeds, scope) {
|
|
1967
|
+
const variableSeeds = seeds.filter(isNodeFilter5("variablePdaSeedNode"));
|
|
1968
|
+
if (variableSeeds.length === 0) return;
|
|
1969
|
+
const pdaNode = getLastNodeFromPath17(scope.pdaPath);
|
|
1970
|
+
const seedTypeName = scope.nameApi.pdaSeedsType(pdaNode.name);
|
|
1971
|
+
const seedAttributes = mergeFragments(
|
|
1972
|
+
variableSeeds.map((seed) => seed.inputAttribute),
|
|
1973
|
+
(cs) => cs.join("\n")
|
|
1974
|
+
);
|
|
1975
|
+
return fragment`export type ${seedTypeName} = {\n${seedAttributes}\n};`;
|
|
1976
|
+
}
|
|
1977
|
+
function getFunctionFragment2(seeds, scope) {
|
|
1978
|
+
const pdaNode = getLastNodeFromPath17(scope.pdaPath);
|
|
1979
|
+
const programNode = findProgramNodeFromPath7(scope.pdaPath);
|
|
1980
|
+
const addressType = use("type Address", "solanaAddresses");
|
|
1981
|
+
const pdaType = use("type ProgramDerivedAddress", "solanaAddresses");
|
|
1982
|
+
const getPdaFunction = use("getProgramDerivedAddress", "solanaAddresses");
|
|
1983
|
+
const seedTypeName = scope.nameApi.pdaSeedsType(pdaNode.name);
|
|
1984
|
+
const findPdaFunction = scope.nameApi.pdaFindFunction(pdaNode.name);
|
|
1985
|
+
const docs = getDocblockFragment(pdaNode.docs ?? [], true);
|
|
1986
|
+
const hasVariableSeeds = seeds.filter(isNodeFilter5("variablePdaSeedNode")).length > 0;
|
|
1987
|
+
const seedArgument = hasVariableSeeds ? `seeds: ${seedTypeName}, ` : "";
|
|
1988
|
+
const programAddress = pdaNode.programId ?? programNode.publicKey;
|
|
1989
|
+
const encodedSeeds = mergeFragments(
|
|
1990
|
+
seeds.map((s) => s.encodedValue),
|
|
1991
|
+
(cs) => cs.join(", ")
|
|
1992
|
+
);
|
|
1993
|
+
return fragment`${docs}export async function ${findPdaFunction}(${seedArgument}config: { programAddress?: ${addressType} | undefined } = {}): Promise<${pdaType}> {
|
|
1994
|
+
const { programAddress = '${programAddress}' as ${addressType}<'${programAddress}'> } = config;
|
|
1995
|
+
return await ${getPdaFunction}({ programAddress, seeds: [${encodedSeeds}]});
|
|
1996
|
+
}`;
|
|
1997
|
+
}
|
|
1998
|
+
function parsePdaSeedNodes(seeds, scope) {
|
|
1999
|
+
return seeds.map((seed) => {
|
|
2000
|
+
if (isNode13(seed, "variablePdaSeedNode")) {
|
|
2001
|
+
const name = camelCase12(seed.name);
|
|
2002
|
+
const docs = getDocblockFragment(seed.docs ?? [], true);
|
|
2003
|
+
const { encoder: encoder2, looseType } = visit6(seed.type, scope.typeManifestVisitor);
|
|
2004
|
+
return {
|
|
2005
|
+
...seed,
|
|
2006
|
+
encodedValue: fragment`${encoder2}.encode(seeds.${name})`,
|
|
2007
|
+
inputAttribute: fragment`${docs}${name}: ${looseType};`
|
|
2008
|
+
};
|
|
2009
|
+
}
|
|
2010
|
+
if (isNode13(seed.value, "programIdValueNode")) {
|
|
2011
|
+
const addressEncoder = use("getAddressEncoder", "solanaAddresses");
|
|
2012
|
+
return { ...seed, encodedValue: fragment`${addressEncoder}().encode(programAddress)` };
|
|
2013
|
+
}
|
|
2014
|
+
const { encoder } = visit6(seed.type, scope.typeManifestVisitor);
|
|
2015
|
+
const { value } = visit6(seed.value, scope.typeManifestVisitor);
|
|
2016
|
+
return { ...seed, encodedValue: fragment`${encoder}.encode(${value})` };
|
|
2017
|
+
});
|
|
2018
|
+
}
|
|
2019
|
+
|
|
2020
|
+
// src/fragments/pdaPage.ts
|
|
2021
|
+
import { findProgramNodeFromPath as findProgramNodeFromPath8 } from "@codama/visitors-core";
|
|
2022
|
+
function getPdaPageFragment(scope) {
|
|
2023
|
+
if (!findProgramNodeFromPath8(scope.pdaPath)) {
|
|
2024
|
+
throw new Error("PDA must be visited inside a program.");
|
|
2025
|
+
}
|
|
2026
|
+
return getPdaFunctionFragment(scope);
|
|
2027
|
+
}
|
|
2028
|
+
|
|
2029
|
+
// src/fragments/programAccounts.ts
|
|
2030
|
+
import { resolveNestedTypeNode as resolveNestedTypeNode3 } from "@codama/nodes";
|
|
2031
|
+
import { mapFragmentContent as mapFragmentContent9 } from "@codama/renderers-core";
|
|
2032
|
+
import { pipe as pipe10 } from "@codama/visitors-core";
|
|
2033
|
+
function getProgramAccountsFragment(scope) {
|
|
2034
|
+
if (scope.programNode.accounts.length === 0) return;
|
|
2035
|
+
return mergeFragments(
|
|
2036
|
+
[getProgramAccountsEnumFragment(scope), getProgramAccountsIdentifierFunctionFragment(scope)],
|
|
2037
|
+
(c) => c.join("\n\n")
|
|
2038
|
+
);
|
|
2039
|
+
}
|
|
2040
|
+
function getProgramAccountsEnumFragment(scope) {
|
|
2041
|
+
const { programNode, nameApi } = scope;
|
|
2042
|
+
const programAccountsEnum = nameApi.programAccountsEnum(programNode.name);
|
|
2043
|
+
const programAccountsEnumVariants = programNode.accounts.map(
|
|
2044
|
+
(account) => nameApi.programAccountsEnumVariant(account.name)
|
|
2045
|
+
);
|
|
2046
|
+
return fragment`export enum ${programAccountsEnum} { ${programAccountsEnumVariants.join(", ")} }`;
|
|
2047
|
+
}
|
|
2048
|
+
function getProgramAccountsIdentifierFunctionFragment(scope) {
|
|
2049
|
+
const { programNode, nameApi } = scope;
|
|
2050
|
+
const accountsWithDiscriminators = programNode.accounts.filter(
|
|
2051
|
+
(account) => (account.discriminators ?? []).length > 0
|
|
2052
|
+
);
|
|
2053
|
+
const hasAccountDiscriminators = accountsWithDiscriminators.length > 0;
|
|
2054
|
+
if (!hasAccountDiscriminators) return;
|
|
2055
|
+
const programAccountsEnum = nameApi.programAccountsEnum(programNode.name);
|
|
2056
|
+
const programAccountsIdentifierFunction = nameApi.programAccountsIdentifierFunction(programNode.name);
|
|
2057
|
+
return pipe10(
|
|
2058
|
+
mergeFragments(
|
|
2059
|
+
accountsWithDiscriminators.map((account) => {
|
|
2060
|
+
const variant = nameApi.programAccountsEnumVariant(account.name);
|
|
2061
|
+
return getDiscriminatorConditionFragment({
|
|
2062
|
+
...scope,
|
|
2063
|
+
dataName: "data",
|
|
2064
|
+
discriminators: account.discriminators ?? [],
|
|
2065
|
+
ifTrue: `return ${programAccountsEnum}.${variant};`,
|
|
2066
|
+
struct: resolveNestedTypeNode3(account.data)
|
|
2067
|
+
});
|
|
2068
|
+
}),
|
|
2069
|
+
(c) => c.join("\n")
|
|
2070
|
+
),
|
|
2071
|
+
(f) => mapFragmentContent9(
|
|
2072
|
+
f,
|
|
2073
|
+
(discriminators) => `export function ${programAccountsIdentifierFunction}(account: { data: ReadonlyUint8Array } | ReadonlyUint8Array): ${programAccountsEnum} {
|
|
2074
|
+
const data = 'data' in account ? account.data : account;
|
|
2075
|
+
${discriminators}
|
|
2076
|
+
throw new Error("The provided account could not be identified as a ${programNode.name} account.")
|
|
2077
|
+
}`
|
|
2078
|
+
),
|
|
2079
|
+
(f) => addFragmentImports(f, "solanaCodecsCore", ["type ReadonlyUint8Array"])
|
|
2080
|
+
);
|
|
2081
|
+
}
|
|
2082
|
+
|
|
2083
|
+
// src/fragments/programConstant.ts
|
|
2084
|
+
import { pipe as pipe11 } from "@codama/visitors-core";
|
|
2085
|
+
function getProgramConstantFragment(scope) {
|
|
2086
|
+
const { programNode, nameApi } = scope;
|
|
2087
|
+
const programAddressConstant = nameApi.programAddressConstant(programNode.name);
|
|
2088
|
+
return pipe11(
|
|
2089
|
+
fragment`export const ${programAddressConstant} = '${programNode.publicKey}' as Address<'${programNode.publicKey}'>;`,
|
|
2090
|
+
(f) => addFragmentImports(f, "solanaAddresses", ["type Address"])
|
|
2091
|
+
);
|
|
2092
|
+
}
|
|
2093
|
+
|
|
2094
|
+
// src/fragments/programInstructions.ts
|
|
2095
|
+
import {
|
|
2096
|
+
getAllInstructionsWithSubs,
|
|
2097
|
+
structTypeNodeFromInstructionArgumentNodes as structTypeNodeFromInstructionArgumentNodes4
|
|
2098
|
+
} from "@codama/nodes";
|
|
2099
|
+
import { mapFragmentContent as mapFragmentContent10 } from "@codama/renderers-core";
|
|
2100
|
+
import { pipe as pipe12 } from "@codama/visitors-core";
|
|
2101
|
+
function getProgramInstructionsFragment(scope) {
|
|
2102
|
+
if (scope.programNode.instructions.length === 0) return;
|
|
2103
|
+
const allInstructions = getAllInstructionsWithSubs(scope.programNode, {
|
|
2104
|
+
leavesOnly: !scope.renderParentInstructions,
|
|
2105
|
+
subInstructionsFirst: true
|
|
2106
|
+
});
|
|
2107
|
+
const scopeWithInstructions = { ...scope, allInstructions };
|
|
2108
|
+
return mergeFragments(
|
|
2109
|
+
[
|
|
2110
|
+
getProgramInstructionsEnumFragment(scopeWithInstructions),
|
|
2111
|
+
getProgramInstructionsIdentifierFunctionFragment(scopeWithInstructions),
|
|
2112
|
+
getProgramInstructionsParsedUnionTypeFragment(scopeWithInstructions)
|
|
2113
|
+
],
|
|
2114
|
+
(c) => c.join("\n\n")
|
|
2115
|
+
);
|
|
2116
|
+
}
|
|
2117
|
+
function getProgramInstructionsEnumFragment(scope) {
|
|
2118
|
+
const { programNode, allInstructions, nameApi } = scope;
|
|
2119
|
+
const programInstructionsEnum = nameApi.programInstructionsEnum(programNode.name);
|
|
2120
|
+
const programInstructionsEnumVariants = allInstructions.map(
|
|
2121
|
+
(instruction) => nameApi.programInstructionsEnumVariant(instruction.name)
|
|
2122
|
+
);
|
|
2123
|
+
return fragment`export enum ${programInstructionsEnum} { ${programInstructionsEnumVariants.join(", ")} }`;
|
|
2124
|
+
}
|
|
2125
|
+
function getProgramInstructionsIdentifierFunctionFragment(scope) {
|
|
2126
|
+
const { programNode, nameApi, allInstructions } = scope;
|
|
2127
|
+
const instructionsWithDiscriminators = allInstructions.filter(
|
|
2128
|
+
(instruction) => (instruction.discriminators ?? []).length > 0
|
|
2129
|
+
);
|
|
2130
|
+
const hasInstructionDiscriminators = instructionsWithDiscriminators.length > 0;
|
|
2131
|
+
if (!hasInstructionDiscriminators) return;
|
|
2132
|
+
const programInstructionsEnum = nameApi.programInstructionsEnum(programNode.name);
|
|
2133
|
+
const programInstructionsIdentifierFunction = nameApi.programInstructionsIdentifierFunction(programNode.name);
|
|
2134
|
+
const discriminatorsFragment = mergeFragments(
|
|
2135
|
+
instructionsWithDiscriminators.map((instruction) => {
|
|
2136
|
+
const variant = nameApi.programInstructionsEnumVariant(instruction.name);
|
|
2137
|
+
return getDiscriminatorConditionFragment({
|
|
2138
|
+
...scope,
|
|
2139
|
+
dataName: "data",
|
|
2140
|
+
discriminators: instruction.discriminators ?? [],
|
|
2141
|
+
ifTrue: `return ${programInstructionsEnum}.${variant};`,
|
|
2142
|
+
struct: structTypeNodeFromInstructionArgumentNodes4(instruction.arguments)
|
|
2143
|
+
});
|
|
2144
|
+
}),
|
|
2145
|
+
(c) => c.join("\n")
|
|
2146
|
+
);
|
|
2147
|
+
return pipe12(
|
|
2148
|
+
discriminatorsFragment,
|
|
2149
|
+
(f) => mapFragmentContent10(
|
|
2150
|
+
f,
|
|
2151
|
+
(discriminators) => `export function ${programInstructionsIdentifierFunction}(instruction: { data: ReadonlyUint8Array } | ReadonlyUint8Array): ${programInstructionsEnum} {
|
|
2152
|
+
const data = 'data' in instruction ? instruction.data : instruction;
|
|
2153
|
+
${discriminators}
|
|
2154
|
+
throw new Error("The provided instruction could not be identified as a ${programNode.name} instruction.")
|
|
2155
|
+
}`
|
|
2156
|
+
),
|
|
2157
|
+
(f) => addFragmentImports(f, "solanaCodecsCore", ["type ReadonlyUint8Array"])
|
|
2158
|
+
);
|
|
2159
|
+
}
|
|
2160
|
+
function getProgramInstructionsParsedUnionTypeFragment(scope) {
|
|
2161
|
+
const { programNode, allInstructions, nameApi } = scope;
|
|
2162
|
+
const programAddress = programNode.publicKey;
|
|
2163
|
+
const programInstructionsType = nameApi.programInstructionsParsedUnionType(programNode.name);
|
|
2164
|
+
const programInstructionsEnum = nameApi.programInstructionsEnum(programNode.name);
|
|
2165
|
+
const typeVariants = allInstructions.map((instruction) => {
|
|
2166
|
+
const instructionEnumVariant = nameApi.programInstructionsEnumVariant(instruction.name);
|
|
2167
|
+
const parsedInstructionType = use(
|
|
2168
|
+
`type ${nameApi.instructionParsedType(instruction.name)}`,
|
|
2169
|
+
"generatedInstructions"
|
|
2170
|
+
);
|
|
2171
|
+
return fragment`| { instructionType: ${programInstructionsEnum}.${instructionEnumVariant} } & ${parsedInstructionType}<TProgram>`;
|
|
2172
|
+
});
|
|
2173
|
+
return mergeFragments(
|
|
2174
|
+
[
|
|
2175
|
+
fragment`export type ${programInstructionsType}<TProgram extends string = '${programAddress}'> =`,
|
|
2176
|
+
...typeVariants
|
|
2177
|
+
],
|
|
2178
|
+
(c) => c.join("\n")
|
|
2179
|
+
);
|
|
2180
|
+
}
|
|
2181
|
+
|
|
2182
|
+
// src/fragments/programPage.ts
|
|
2183
|
+
function getProgramPageFragment(scope) {
|
|
2184
|
+
return mergeFragments(
|
|
2185
|
+
[getProgramConstantFragment(scope), getProgramAccountsFragment(scope), getProgramInstructionsFragment(scope)],
|
|
2186
|
+
(cs) => cs.join("\n\n")
|
|
2187
|
+
);
|
|
2188
|
+
}
|
|
2189
|
+
|
|
2190
|
+
// src/fragments/rootIndexPage.ts
|
|
2191
|
+
function getRootIndexPageFragment(scope) {
|
|
2192
|
+
const hasAnythingToExport = scope.programsToExport.length > 0 || scope.accountsToExport.length > 0 || scope.instructionsToExport.length > 0 || scope.definedTypesToExport.length > 0;
|
|
2193
|
+
if (!hasAnythingToExport) {
|
|
2194
|
+
return fragment`export default {};`;
|
|
2195
|
+
}
|
|
2196
|
+
const programsWithErrorsToExport = scope.programsToExport.filter((p) => p.errors.length > 0);
|
|
2197
|
+
return mergeFragments(
|
|
2198
|
+
[
|
|
2199
|
+
scope.accountsToExport.length > 0 ? getExportAllFragment("./accounts") : void 0,
|
|
2200
|
+
programsWithErrorsToExport.length > 0 ? getExportAllFragment("./errors") : void 0,
|
|
2201
|
+
scope.instructionsToExport.length > 0 ? getExportAllFragment("./instructions") : void 0,
|
|
2202
|
+
scope.pdasToExport.length > 0 ? getExportAllFragment("./pdas") : void 0,
|
|
2203
|
+
scope.programsToExport.length > 0 ? getExportAllFragment("./programs") : void 0,
|
|
2204
|
+
scope.definedTypesToExport.length > 0 ? getExportAllFragment("./types") : void 0
|
|
2205
|
+
],
|
|
2206
|
+
(cs) => cs.join("\n")
|
|
2207
|
+
);
|
|
2208
|
+
}
|
|
2209
|
+
|
|
2210
|
+
// src/fragments/sharedPage.ts
|
|
2211
|
+
import { pipe as pipe13 } from "@codama/visitors-core";
|
|
2212
|
+
function getSharedPageFragment() {
|
|
2213
|
+
const sharedPage = fragment`/**
|
|
2214
|
+
* Asserts that the given value is not null or undefined.
|
|
2215
|
+
* @internal
|
|
2216
|
+
*/
|
|
2217
|
+
export function expectSome<T>(value: T | null | undefined): T {
|
|
2218
|
+
if (value === null || value === undefined) {
|
|
2219
|
+
throw new Error('Expected a value but received null or undefined.');
|
|
2220
|
+
}
|
|
2221
|
+
return value;
|
|
2222
|
+
}
|
|
2223
|
+
|
|
2224
|
+
/**
|
|
2225
|
+
* Asserts that the given value is a PublicKey.
|
|
2226
|
+
* @internal
|
|
2227
|
+
*/
|
|
2228
|
+
export function expectAddress<T extends string = string>(
|
|
2229
|
+
value: Address<T> | ProgramDerivedAddress<T> | TransactionSigner<T> | null | undefined
|
|
2230
|
+
): Address<T> {
|
|
2231
|
+
if (!value) {
|
|
2232
|
+
throw new Error('Expected a Address.');
|
|
2233
|
+
}
|
|
2234
|
+
if (typeof value === 'object' && "address" in value) {
|
|
2235
|
+
return value.address;
|
|
2236
|
+
}
|
|
2237
|
+
if (Array.isArray(value)) {
|
|
2238
|
+
return value[0] as Address<T>;
|
|
2239
|
+
}
|
|
2240
|
+
return value as Address<T>;
|
|
2241
|
+
}
|
|
2242
|
+
|
|
2243
|
+
/**
|
|
2244
|
+
* Asserts that the given value is a PDA.
|
|
2245
|
+
* @internal
|
|
2246
|
+
*/
|
|
2247
|
+
export function expectProgramDerivedAddress<T extends string = string>(
|
|
2248
|
+
value: Address<T> | ProgramDerivedAddress<T> | TransactionSigner<T> | null | undefined
|
|
2249
|
+
): ProgramDerivedAddress<T> {
|
|
2250
|
+
if (!value || !Array.isArray(value) || !isProgramDerivedAddress(value)) {
|
|
2251
|
+
throw new Error('Expected a ProgramDerivedAddress.');
|
|
2252
|
+
}
|
|
2253
|
+
return value;
|
|
2254
|
+
}
|
|
2255
|
+
|
|
2256
|
+
/**
|
|
2257
|
+
* Asserts that the given value is a TransactionSigner.
|
|
2258
|
+
* @internal
|
|
2259
|
+
*/
|
|
2260
|
+
export function expectTransactionSigner<T extends string = string>(
|
|
2261
|
+
value: Address<T> | ProgramDerivedAddress<T> | TransactionSigner<T> | null | undefined
|
|
2262
|
+
): TransactionSigner<T> {
|
|
2263
|
+
if (!value || !isTransactionSigner(value)) {
|
|
2264
|
+
throw new Error('Expected a TransactionSigner.');
|
|
2265
|
+
}
|
|
2266
|
+
return value;
|
|
2267
|
+
}
|
|
2268
|
+
|
|
2269
|
+
/**
|
|
2270
|
+
* Defines an instruction account to resolve.
|
|
2271
|
+
* @internal
|
|
2272
|
+
*/
|
|
2273
|
+
export type ResolvedAccount<T extends string = string, U extends Address<T> | ProgramDerivedAddress<T> | TransactionSigner<T> | null = Address<T> | ProgramDerivedAddress<T> | TransactionSigner<T> | null> = {
|
|
2274
|
+
isWritable: boolean;
|
|
2275
|
+
value: U;
|
|
2276
|
+
};
|
|
2277
|
+
|
|
2278
|
+
/**
|
|
2279
|
+
* Defines an instruction that stores additional bytes on-chain.
|
|
2280
|
+
* @internal
|
|
2281
|
+
*/
|
|
2282
|
+
export type InstructionWithByteDelta = {
|
|
2283
|
+
byteDelta: number;
|
|
2284
|
+
};
|
|
2285
|
+
|
|
2286
|
+
/**
|
|
2287
|
+
* Get account metas and signers from resolved accounts.
|
|
2288
|
+
* @internal
|
|
2289
|
+
*/
|
|
2290
|
+
export function getAccountMetaFactory(
|
|
2291
|
+
programAddress: Address,
|
|
2292
|
+
optionalAccountStrategy: 'omitted' | 'programId',
|
|
2293
|
+
) {
|
|
2294
|
+
return (account: ResolvedAccount): AccountMeta | AccountSignerMeta | undefined => {
|
|
2295
|
+
if (!account.value) {
|
|
2296
|
+
if (optionalAccountStrategy === 'omitted') return;
|
|
2297
|
+
return Object.freeze({ address: programAddress, role: AccountRole.READONLY });
|
|
2298
|
+
}
|
|
2299
|
+
|
|
2300
|
+
const writableRole = account.isWritable ? AccountRole.WRITABLE : AccountRole.READONLY;
|
|
2301
|
+
return Object.freeze({
|
|
2302
|
+
address: expectAddress(account.value),
|
|
2303
|
+
role: isTransactionSigner(account.value) ? upgradeRoleToSigner(writableRole) : writableRole,
|
|
2304
|
+
...(isTransactionSigner(account.value) ? { signer: account.value } : {})
|
|
2305
|
+
});
|
|
2306
|
+
};
|
|
2307
|
+
}
|
|
2308
|
+
|
|
2309
|
+
export function isTransactionSigner<TAddress extends string = string>(value: Address<TAddress> | ProgramDerivedAddress<TAddress> | TransactionSigner<TAddress>): value is TransactionSigner<TAddress> {
|
|
2310
|
+
return !!value && typeof value === 'object' && 'address' in value && kitIsTransactionSigner(value);
|
|
2311
|
+
}`;
|
|
2312
|
+
return pipe13(
|
|
2313
|
+
sharedPage,
|
|
2314
|
+
(f) => addFragmentImports(f, "solanaAddresses", [
|
|
2315
|
+
"type Address",
|
|
2316
|
+
"isProgramDerivedAddress",
|
|
2317
|
+
"type ProgramDerivedAddress"
|
|
2318
|
+
]),
|
|
2319
|
+
(f) => addFragmentImports(f, "solanaInstructions", ["AccountRole", "type AccountMeta", "upgradeRoleToSigner"]),
|
|
2320
|
+
(f) => addFragmentImports(f, "solanaSigners", [
|
|
2321
|
+
"type AccountSignerMeta",
|
|
2322
|
+
"isTransactionSigner as kitIsTransactionSigner",
|
|
2323
|
+
"type TransactionSigner"
|
|
2324
|
+
])
|
|
2325
|
+
);
|
|
2326
|
+
}
|
|
2327
|
+
|
|
2328
|
+
// src/fragments/typeDiscriminatedUnionHelpers.ts
|
|
2329
|
+
import { isDataEnum as isDataEnum3, isNode as isNode14 } from "@codama/nodes";
|
|
2330
|
+
function getTypeDiscriminatedUnionHelpersFragment(scope) {
|
|
2331
|
+
const { name, typeNode, nameApi } = scope;
|
|
2332
|
+
const isDiscriminatedUnion = isNode14(typeNode, "enumTypeNode") && isDataEnum3(typeNode);
|
|
2333
|
+
if (!isDiscriminatedUnion) return;
|
|
2334
|
+
const functionName = nameApi.discriminatedUnionFunction(name);
|
|
2335
|
+
const isDiscriminatedUnionFunctionName = nameApi.isDiscriminatedUnionFunction(name);
|
|
2336
|
+
const discriminatorName = nameApi.discriminatedUnionDiscriminator(name);
|
|
2337
|
+
const strictName = nameApi.dataType(name);
|
|
2338
|
+
const looseName = nameApi.dataArgsType(name);
|
|
2339
|
+
const getVariantContentType = use("type GetDiscriminatedUnionVariantContent", "solanaCodecsDataStructures");
|
|
2340
|
+
const getVariantType = use("type GetDiscriminatedUnionVariant", "solanaCodecsDataStructures");
|
|
2341
|
+
const variantSignatures = mergeFragments(
|
|
2342
|
+
typeNode.variants.map((variant) => {
|
|
2343
|
+
const variantName = nameApi.discriminatedUnionVariant(variant.name);
|
|
2344
|
+
if (isNode14(variant, "enumStructVariantTypeNode")) {
|
|
2345
|
+
return fragment`export function ${functionName}(kind: '${variantName}', data: ${getVariantContentType}<${looseName}, '${discriminatorName}', '${variantName}'>): ${getVariantType}<${looseName}, '${discriminatorName}', '${variantName}'>;`;
|
|
2346
|
+
}
|
|
2347
|
+
if (isNode14(variant, "enumTupleVariantTypeNode")) {
|
|
2348
|
+
return fragment`export function ${functionName}(kind: '${variantName}', data: ${getVariantContentType}<${looseName}, '${discriminatorName}', '${variantName}'>['fields']): ${getVariantType}<${looseName}, '${discriminatorName}', '${variantName}'>;`;
|
|
2349
|
+
}
|
|
2350
|
+
return fragment`export function ${functionName}(kind: '${variantName}'): ${getVariantType}<${looseName}, '${discriminatorName}', '${variantName}'>;`;
|
|
2351
|
+
}),
|
|
2352
|
+
(cs) => cs.length > 0 ? `${cs.join("\n")}
|
|
2353
|
+
` : ""
|
|
2354
|
+
);
|
|
2355
|
+
return fragment`// Data Enum Helpers.
|
|
2356
|
+
${variantSignatures}export function ${functionName}<K extends ${looseName}['${discriminatorName}'], Data>(kind: K, data?: Data) {
|
|
2357
|
+
return Array.isArray(data) ? { ${discriminatorName}: kind, fields: data } : { ${discriminatorName}: kind, ...(data ?? {}) };
|
|
2358
|
+
}
|
|
2359
|
+
|
|
2360
|
+
export function ${isDiscriminatedUnionFunctionName}<K extends ${strictName}['${discriminatorName}']>(kind: K, value: ${strictName}): value is ${strictName} & { ${discriminatorName}: K } {
|
|
2361
|
+
return value.${discriminatorName} === kind;
|
|
2362
|
+
};
|
|
2363
|
+
`;
|
|
2364
|
+
}
|
|
2365
|
+
|
|
2366
|
+
// src/fragments/typePage.ts
|
|
2367
|
+
import { pipe as pipe14, visit as visit7 } from "@codama/visitors-core";
|
|
2368
|
+
function getTypePageFragment(scope) {
|
|
2369
|
+
const node = scope.node;
|
|
2370
|
+
const manifest = visit7(node, scope.typeManifestVisitor);
|
|
2371
|
+
return pipe14(
|
|
2372
|
+
mergeFragments(
|
|
2373
|
+
[
|
|
2374
|
+
getTypeWithCodecFragment({ ...scope, manifest, name: node.name, node: node.type, typeDocs: node.docs }),
|
|
2375
|
+
getTypeDiscriminatedUnionHelpersFragment({ ...scope, name: node.name, typeNode: node.type })
|
|
2376
|
+
],
|
|
2377
|
+
(cs) => cs.join("\n\n")
|
|
2378
|
+
),
|
|
2379
|
+
(f) => removeFragmentImports(f, "generatedTypes", [
|
|
2380
|
+
scope.nameApi.dataType(node.name),
|
|
2381
|
+
scope.nameApi.dataArgsType(node.name),
|
|
2382
|
+
scope.nameApi.encoderFunction(node.name),
|
|
2383
|
+
scope.nameApi.decoderFunction(node.name),
|
|
2384
|
+
scope.nameApi.codecFunction(node.name)
|
|
2385
|
+
])
|
|
2386
|
+
);
|
|
2387
|
+
}
|
|
2388
|
+
|
|
2389
|
+
// src/visitors/getTypeManifestVisitor.ts
|
|
2390
|
+
import {
|
|
2391
|
+
camelCase as camelCase13,
|
|
2392
|
+
isNode as isNode15,
|
|
2393
|
+
isNodeFilter as isNodeFilter6,
|
|
2394
|
+
isScalarEnum,
|
|
2395
|
+
REGISTERED_TYPE_NODE_KINDS,
|
|
2396
|
+
REGISTERED_VALUE_NODE_KINDS,
|
|
2397
|
+
resolveNestedTypeNode as resolveNestedTypeNode4,
|
|
2398
|
+
structFieldTypeNode,
|
|
2399
|
+
structTypeNode,
|
|
2400
|
+
structTypeNodeFromInstructionArgumentNodes as structTypeNodeFromInstructionArgumentNodes5
|
|
2401
|
+
} from "@codama/nodes";
|
|
2402
|
+
import { mapFragmentContent as mapFragmentContent11, setFragmentContent as setFragmentContent2 } from "@codama/renderers-core";
|
|
2403
|
+
import {
|
|
2404
|
+
extendVisitor,
|
|
2405
|
+
findLastNodeFromPath,
|
|
2406
|
+
NodeStack,
|
|
2407
|
+
pipe as pipe15,
|
|
2408
|
+
recordNodeStackVisitor,
|
|
2409
|
+
staticVisitor,
|
|
2410
|
+
visit as visit8
|
|
2411
|
+
} from "@codama/visitors-core";
|
|
2412
|
+
function getTypeManifestVisitor(input) {
|
|
2413
|
+
const { nameApi, linkables, nonScalarEnums, customAccountData, customInstructionData, getImportFrom } = input;
|
|
2414
|
+
const stack = input.stack ?? new NodeStack();
|
|
2415
|
+
let parentName = null;
|
|
2416
|
+
return pipe15(
|
|
2417
|
+
staticVisitor(() => typeManifest(), {
|
|
2418
|
+
keys: [
|
|
2419
|
+
...REGISTERED_TYPE_NODE_KINDS,
|
|
2420
|
+
...REGISTERED_VALUE_NODE_KINDS,
|
|
2421
|
+
"definedTypeLinkNode",
|
|
2422
|
+
"definedTypeNode",
|
|
2423
|
+
"accountNode",
|
|
2424
|
+
"instructionNode"
|
|
2425
|
+
]
|
|
2426
|
+
}),
|
|
2427
|
+
(visitor) => extendVisitor(visitor, {
|
|
2428
|
+
visitAccount(account, { self }) {
|
|
2429
|
+
parentName = {
|
|
2430
|
+
loose: nameApi.dataArgsType(account.name),
|
|
2431
|
+
strict: nameApi.dataType(account.name)
|
|
2432
|
+
};
|
|
2433
|
+
const link = customAccountData.get(account.name)?.linkNode;
|
|
2434
|
+
const manifest = link ? visit8(link, self) : visit8(account.data, self);
|
|
2435
|
+
parentName = null;
|
|
2436
|
+
return manifest;
|
|
2437
|
+
},
|
|
2438
|
+
visitAmountType(amountType, { self }) {
|
|
2439
|
+
return visit8(amountType.number, self);
|
|
2440
|
+
},
|
|
2441
|
+
visitArrayType(arrayType, { self }) {
|
|
2442
|
+
const childManifest = visit8(arrayType.item, self);
|
|
2443
|
+
const sizeManifest = getArrayLikeSizeOption(arrayType.count, self);
|
|
2444
|
+
const encoderOptions = sizeManifest.encoder ? fragment`, { ${sizeManifest.encoder} }` : "";
|
|
2445
|
+
const decoderOptions = sizeManifest.decoder ? fragment`, { ${sizeManifest.decoder} }` : "";
|
|
2446
|
+
return typeManifest({
|
|
2447
|
+
...childManifest,
|
|
2448
|
+
decoder: fragment`${use("getArrayDecoder", "solanaCodecsDataStructures")}(${childManifest.decoder}${decoderOptions})`,
|
|
2449
|
+
encoder: fragment`${use("getArrayEncoder", "solanaCodecsDataStructures")}(${childManifest.encoder}${encoderOptions})`,
|
|
2450
|
+
looseType: fragment`Array<${childManifest.looseType}>`,
|
|
2451
|
+
strictType: fragment`Array<${childManifest.strictType}>`
|
|
2452
|
+
});
|
|
2453
|
+
},
|
|
2454
|
+
visitArrayValue(node, { self }) {
|
|
2455
|
+
return mergeTypeManifests(
|
|
2456
|
+
node.items.map((v) => visit8(v, self)),
|
|
2457
|
+
{ mergeValues: (renders) => `[${renders.join(", ")}]` }
|
|
2458
|
+
);
|
|
2459
|
+
},
|
|
2460
|
+
visitBooleanType(booleanType, { self }) {
|
|
2461
|
+
let sizeEncoder = fragment``;
|
|
2462
|
+
let sizeDecoder = fragment``;
|
|
2463
|
+
const resolvedSize = resolveNestedTypeNode4(booleanType.size);
|
|
2464
|
+
if (resolvedSize.format !== "u8" || resolvedSize.endian !== "le") {
|
|
2465
|
+
const size = visit8(booleanType.size, self);
|
|
2466
|
+
sizeEncoder = fragment`{ size: ${size.encoder} }`;
|
|
2467
|
+
sizeDecoder = fragment`{ size: ${size.decoder} }`;
|
|
2468
|
+
}
|
|
2469
|
+
return typeManifest({
|
|
2470
|
+
decoder: fragment`${use("getBooleanDecoder", "solanaCodecsDataStructures")}(${sizeDecoder})`,
|
|
2471
|
+
encoder: fragment`${use("getBooleanEncoder", "solanaCodecsDataStructures")}(${sizeEncoder})`,
|
|
2472
|
+
looseType: fragment`boolean`,
|
|
2473
|
+
strictType: fragment`boolean`
|
|
2474
|
+
});
|
|
2475
|
+
},
|
|
2476
|
+
visitBooleanValue(node) {
|
|
2477
|
+
return typeManifest({ value: fragment`${JSON.stringify(node.boolean)}` });
|
|
2478
|
+
},
|
|
2479
|
+
visitBytesType() {
|
|
2480
|
+
const readonlyUint8Array = use("type ReadonlyUint8Array", "solanaCodecsCore");
|
|
2481
|
+
return typeManifest({
|
|
2482
|
+
decoder: fragment`${use("getBytesDecoder", "solanaCodecsDataStructures")}()`,
|
|
2483
|
+
encoder: fragment`${use("getBytesEncoder", "solanaCodecsDataStructures")}()`,
|
|
2484
|
+
looseType: readonlyUint8Array,
|
|
2485
|
+
strictType: readonlyUint8Array
|
|
2486
|
+
});
|
|
2487
|
+
},
|
|
2488
|
+
visitBytesValue(node) {
|
|
2489
|
+
const bytes = getBytesFromBytesValueNode(node);
|
|
2490
|
+
return typeManifest({ value: fragment`new Uint8Array([${Array.from(bytes).join(", ")}])` });
|
|
2491
|
+
},
|
|
2492
|
+
visitConstantValue(node, { self }) {
|
|
2493
|
+
if (isNode15(node.type, "bytesTypeNode") && isNode15(node.value, "bytesValueNode")) {
|
|
2494
|
+
return visit8(node.value, self);
|
|
2495
|
+
}
|
|
2496
|
+
return typeManifest({
|
|
2497
|
+
value: fragment`${visit8(node.type, self).encoder}.encode(${visit8(node.value, self).value})`
|
|
2498
|
+
});
|
|
2499
|
+
},
|
|
2500
|
+
visitDateTimeType(dateTimeType, { self }) {
|
|
2501
|
+
return visit8(dateTimeType.number, self);
|
|
2502
|
+
},
|
|
2503
|
+
visitDefinedType(definedType, { self }) {
|
|
2504
|
+
parentName = {
|
|
2505
|
+
loose: nameApi.dataArgsType(definedType.name),
|
|
2506
|
+
strict: nameApi.dataType(definedType.name)
|
|
2507
|
+
};
|
|
2508
|
+
const manifest = visit8(definedType.type, self);
|
|
2509
|
+
parentName = null;
|
|
2510
|
+
return manifest;
|
|
2511
|
+
},
|
|
2512
|
+
visitDefinedTypeLink(node) {
|
|
2513
|
+
const strictName = nameApi.dataType(node.name);
|
|
2514
|
+
const looseName = nameApi.dataArgsType(node.name);
|
|
2515
|
+
const encoderFunction = nameApi.encoderFunction(node.name);
|
|
2516
|
+
const decoderFunction = nameApi.decoderFunction(node.name);
|
|
2517
|
+
const importFrom = getImportFrom(node);
|
|
2518
|
+
return typeManifest({
|
|
2519
|
+
decoder: fragment`${use(decoderFunction, importFrom)}()`,
|
|
2520
|
+
encoder: fragment`${use(encoderFunction, importFrom)}()`,
|
|
2521
|
+
looseType: use(`type ${looseName}`, importFrom),
|
|
2522
|
+
strictType: use(`type ${strictName}`, importFrom)
|
|
2523
|
+
});
|
|
2524
|
+
},
|
|
2525
|
+
visitEnumEmptyVariantType(enumEmptyVariantType) {
|
|
2526
|
+
const discriminator = nameApi.discriminatedUnionDiscriminator(camelCase13(parentName?.strict ?? ""));
|
|
2527
|
+
const name = nameApi.discriminatedUnionVariant(enumEmptyVariantType.name);
|
|
2528
|
+
const kindAttribute = `${discriminator}: "${name}"`;
|
|
2529
|
+
return typeManifest({
|
|
2530
|
+
decoder: fragment`['${name}', ${use("getUnitDecoder", "solanaCodecsDataStructures")}()]`,
|
|
2531
|
+
encoder: fragment`['${name}', ${use("getUnitEncoder", "solanaCodecsDataStructures")}()]`,
|
|
2532
|
+
looseType: fragment`{ ${kindAttribute} }`,
|
|
2533
|
+
strictType: fragment`{ ${kindAttribute} }`
|
|
2534
|
+
});
|
|
2535
|
+
},
|
|
2536
|
+
visitEnumStructVariantType(enumStructVariantType, { self }) {
|
|
2537
|
+
const currentParentName = parentName;
|
|
2538
|
+
const discriminator = nameApi.discriminatedUnionDiscriminator(
|
|
2539
|
+
camelCase13(currentParentName?.strict ?? "")
|
|
2540
|
+
);
|
|
2541
|
+
const name = nameApi.discriminatedUnionVariant(enumStructVariantType.name);
|
|
2542
|
+
const kindAttribute = `${discriminator}: "${name}"`;
|
|
2543
|
+
parentName = null;
|
|
2544
|
+
const structManifest = visit8(enumStructVariantType.struct, self);
|
|
2545
|
+
parentName = currentParentName;
|
|
2546
|
+
return typeManifest({
|
|
2547
|
+
...structManifest,
|
|
2548
|
+
decoder: fragment`['${name}', ${structManifest.decoder}]`,
|
|
2549
|
+
encoder: fragment`['${name}', ${structManifest.encoder}]`,
|
|
2550
|
+
looseType: pipe15(
|
|
2551
|
+
structManifest.looseType,
|
|
2552
|
+
(f) => mapFragmentContent11(f, (c) => `{ ${kindAttribute},${c.slice(1, -1)}}`)
|
|
2553
|
+
),
|
|
2554
|
+
strictType: pipe15(
|
|
2555
|
+
structManifest.strictType,
|
|
2556
|
+
(f) => mapFragmentContent11(f, (c) => `{ ${kindAttribute},${c.slice(1, -1)}}`)
|
|
2557
|
+
)
|
|
2558
|
+
});
|
|
2559
|
+
},
|
|
2560
|
+
visitEnumTupleVariantType(enumTupleVariantType, { self }) {
|
|
2561
|
+
const currentParentName = parentName;
|
|
2562
|
+
const discriminator = nameApi.discriminatedUnionDiscriminator(
|
|
2563
|
+
camelCase13(currentParentName?.strict ?? "")
|
|
2564
|
+
);
|
|
2565
|
+
const name = nameApi.discriminatedUnionVariant(enumTupleVariantType.name);
|
|
2566
|
+
const kindAttribute = `${discriminator}: "${name}"`;
|
|
2567
|
+
const struct = structTypeNode([
|
|
2568
|
+
structFieldTypeNode({
|
|
2569
|
+
name: "fields",
|
|
2570
|
+
type: enumTupleVariantType.tuple
|
|
2571
|
+
})
|
|
2572
|
+
]);
|
|
2573
|
+
parentName = null;
|
|
2574
|
+
const structManifest = visit8(struct, self);
|
|
2575
|
+
parentName = currentParentName;
|
|
2576
|
+
return typeManifest({
|
|
2577
|
+
...structManifest,
|
|
2578
|
+
decoder: fragment`['${name}', ${structManifest.decoder}]`,
|
|
2579
|
+
encoder: fragment`['${name}', ${structManifest.encoder}]`,
|
|
2580
|
+
looseType: pipe15(
|
|
2581
|
+
structManifest.looseType,
|
|
2582
|
+
(f) => mapFragmentContent11(f, (c) => `{ ${kindAttribute},${c.slice(1, -1)}}`)
|
|
2583
|
+
),
|
|
2584
|
+
strictType: pipe15(
|
|
2585
|
+
structManifest.strictType,
|
|
2586
|
+
(f) => mapFragmentContent11(f, (c) => `{ ${kindAttribute},${c.slice(1, -1)}}`)
|
|
2587
|
+
)
|
|
2588
|
+
});
|
|
2589
|
+
},
|
|
2590
|
+
visitEnumType(enumType, { self }) {
|
|
2591
|
+
const currentParentName = parentName;
|
|
2592
|
+
const encoderOptions = [];
|
|
2593
|
+
const decoderOptions = [];
|
|
2594
|
+
const enumSize = resolveNestedTypeNode4(enumType.size);
|
|
2595
|
+
if (enumSize.format !== "u8" || enumSize.endian !== "le") {
|
|
2596
|
+
const sizeManifest = visit8(enumType.size, self);
|
|
2597
|
+
encoderOptions.push(fragment`size: ${sizeManifest.encoder}`);
|
|
2598
|
+
decoderOptions.push(fragment`size: ${sizeManifest.decoder}`);
|
|
2599
|
+
}
|
|
2600
|
+
const discriminator = nameApi.discriminatedUnionDiscriminator(
|
|
2601
|
+
camelCase13(currentParentName?.strict ?? "")
|
|
2602
|
+
);
|
|
2603
|
+
if (!isScalarEnum(enumType) && discriminator !== "__kind") {
|
|
2604
|
+
encoderOptions.push(fragment`discriminator: '${discriminator}'`);
|
|
2605
|
+
decoderOptions.push(fragment`discriminator: '${discriminator}'`);
|
|
2606
|
+
}
|
|
2607
|
+
const encoderOptionsFragment = mergeFragments(
|
|
2608
|
+
encoderOptions,
|
|
2609
|
+
(cs) => cs.length > 0 ? `, { ${cs.join(", ")} }` : ""
|
|
2610
|
+
);
|
|
2611
|
+
const decoderOptionsFragment = mergeFragments(
|
|
2612
|
+
decoderOptions,
|
|
2613
|
+
(cs) => cs.length > 0 ? `, { ${cs.join(", ")} }` : ""
|
|
2614
|
+
);
|
|
2615
|
+
if (isScalarEnum(enumType)) {
|
|
2616
|
+
if (currentParentName === null) {
|
|
2617
|
+
throw new Error(
|
|
2618
|
+
"Scalar enums cannot be inlined and must be introduced via a defined type. Ensure you are not inlining a defined type that is a scalar enum through a visitor."
|
|
2619
|
+
);
|
|
2620
|
+
}
|
|
2621
|
+
const variantNames = enumType.variants.map(({ name }) => nameApi.enumVariant(name));
|
|
2622
|
+
return typeManifest({
|
|
2623
|
+
decoder: fragment`${use("getEnumDecoder", "solanaCodecsDataStructures")}(${currentParentName.strict}${decoderOptionsFragment})`,
|
|
2624
|
+
encoder: fragment`${use("getEnumEncoder", "solanaCodecsDataStructures")}(${currentParentName.strict}${encoderOptionsFragment})`,
|
|
2625
|
+
isEnum: true,
|
|
2626
|
+
looseType: fragment`{ ${variantNames.join(", ")} }`,
|
|
2627
|
+
strictType: fragment`{ ${variantNames.join(", ")} }`
|
|
2628
|
+
});
|
|
2629
|
+
}
|
|
2630
|
+
const mergedManifest = mergeTypeManifests(
|
|
2631
|
+
enumType.variants.map((variant) => visit8(variant, self)),
|
|
2632
|
+
{
|
|
2633
|
+
mergeCodecs: (renders) => renders.join(", "),
|
|
2634
|
+
mergeTypes: (renders) => renders.join(" | ")
|
|
2635
|
+
}
|
|
2636
|
+
);
|
|
2637
|
+
return typeManifest({
|
|
2638
|
+
...mergedManifest,
|
|
2639
|
+
decoder: fragment`${use("getDiscriminatedUnionDecoder", "solanaCodecsDataStructures")}([${mergedManifest.decoder}]${decoderOptionsFragment})`,
|
|
2640
|
+
encoder: fragment`${use("getDiscriminatedUnionEncoder", "solanaCodecsDataStructures")}([${mergedManifest.encoder}]${encoderOptionsFragment})`
|
|
2641
|
+
});
|
|
2642
|
+
},
|
|
2643
|
+
visitEnumValue(node, { self }) {
|
|
2644
|
+
const manifest = typeManifest();
|
|
2645
|
+
const enumName = nameApi.dataType(node.enum.name);
|
|
2646
|
+
const enumFunction = nameApi.discriminatedUnionFunction(node.enum.name);
|
|
2647
|
+
const importFrom = getImportFrom(node.enum);
|
|
2648
|
+
const enumNode = linkables.get([...stack.getPath(), node.enum])?.type;
|
|
2649
|
+
const isScalar = enumNode && isNode15(enumNode, "enumTypeNode") ? isScalarEnum(enumNode) : !nonScalarEnums.includes(node.enum.name);
|
|
2650
|
+
if (!node.value && isScalar) {
|
|
2651
|
+
const variantName2 = nameApi.enumVariant(node.variant);
|
|
2652
|
+
return typeManifest({
|
|
2653
|
+
...manifest,
|
|
2654
|
+
value: pipe15(
|
|
2655
|
+
manifest.value,
|
|
2656
|
+
(f) => setFragmentContent2(f, `${enumName}.${variantName2}`),
|
|
2657
|
+
(f) => addFragmentImports(f, importFrom, [enumName])
|
|
2658
|
+
)
|
|
2659
|
+
});
|
|
2660
|
+
}
|
|
2661
|
+
const variantName = nameApi.discriminatedUnionVariant(node.variant);
|
|
2662
|
+
if (!node.value) {
|
|
2663
|
+
return typeManifest({
|
|
2664
|
+
...manifest,
|
|
2665
|
+
value: pipe15(
|
|
2666
|
+
manifest.value,
|
|
2667
|
+
(f) => setFragmentContent2(f, `${enumFunction}('${variantName}')`),
|
|
2668
|
+
(f) => addFragmentImports(f, importFrom, [enumFunction])
|
|
2669
|
+
)
|
|
2670
|
+
});
|
|
2671
|
+
}
|
|
2672
|
+
return typeManifest({
|
|
2673
|
+
...manifest,
|
|
2674
|
+
value: pipe15(
|
|
2675
|
+
visit8(node.value, self).value,
|
|
2676
|
+
(f) => mapFragmentContent11(f, (c) => `${enumFunction}('${variantName}', ${c})`),
|
|
2677
|
+
(f) => addFragmentImports(f, importFrom, [enumFunction])
|
|
2678
|
+
)
|
|
2679
|
+
});
|
|
2680
|
+
},
|
|
2681
|
+
visitFixedSizeType(node, { self }) {
|
|
2682
|
+
const manifest = visit8(node.type, self);
|
|
2683
|
+
return typeManifest({
|
|
2684
|
+
...manifest,
|
|
2685
|
+
decoder: fragment`${use("fixDecoderSize", "solanaCodecsCore")}(${manifest.decoder}, ${node.size})`,
|
|
2686
|
+
encoder: fragment`${use("fixEncoderSize", "solanaCodecsCore")}(${manifest.encoder}, ${node.size})`
|
|
2687
|
+
});
|
|
2688
|
+
},
|
|
2689
|
+
visitHiddenPrefixType(node, { self }) {
|
|
2690
|
+
const manifest = visit8(node.type, self);
|
|
2691
|
+
const prefixes = node.prefix.map((c) => visit8(c, self).value);
|
|
2692
|
+
const prefixEncoders = pipe15(
|
|
2693
|
+
mergeFragments(prefixes, (cs) => cs.map((c) => `getConstantEncoder(${c})`).join(", ")),
|
|
2694
|
+
(f) => addFragmentImports(f, "solanaCodecsCore", ["getConstantEncoder"])
|
|
2695
|
+
);
|
|
2696
|
+
const prefixDecoders = pipe15(
|
|
2697
|
+
mergeFragments(prefixes, (cs) => cs.map((c) => `getConstantDecoder(${c})`).join(", ")),
|
|
2698
|
+
(f) => addFragmentImports(f, "solanaCodecsCore", ["getConstantDecoder"])
|
|
2699
|
+
);
|
|
2700
|
+
return typeManifest({
|
|
2701
|
+
...manifest,
|
|
2702
|
+
decoder: fragment`${use("getHiddenPrefixDecoder", "solanaCodecsDataStructures")}(${manifest.decoder}, [${prefixDecoders}])`,
|
|
2703
|
+
encoder: fragment`${use("getHiddenPrefixEncoder", "solanaCodecsDataStructures")}(${manifest.encoder}, [${prefixEncoders}])`
|
|
2704
|
+
});
|
|
2705
|
+
},
|
|
2706
|
+
visitHiddenSuffixType(node, { self }) {
|
|
2707
|
+
const manifest = visit8(node.type, self);
|
|
2708
|
+
const suffixes = node.suffix.map((c) => visit8(c, self).value);
|
|
2709
|
+
const suffixEncoders = pipe15(
|
|
2710
|
+
mergeFragments(suffixes, (cs) => cs.map((c) => `getConstantEncoder(${c})`).join(", ")),
|
|
2711
|
+
(f) => addFragmentImports(f, "solanaCodecsCore", ["getConstantEncoder"])
|
|
2712
|
+
);
|
|
2713
|
+
const suffixDecoders = pipe15(
|
|
2714
|
+
mergeFragments(suffixes, (cs) => cs.map((c) => `getConstantDecoder(${c})`).join(", ")),
|
|
2715
|
+
(f) => addFragmentImports(f, "solanaCodecsCore", ["getConstantDecoder"])
|
|
2716
|
+
);
|
|
2717
|
+
return typeManifest({
|
|
2718
|
+
...manifest,
|
|
2719
|
+
decoder: fragment`${use("getHiddenSuffixDecoder", "solanaCodecsDataStructures")}(${manifest.decoder}, [${suffixDecoders}])`,
|
|
2720
|
+
encoder: fragment`${use("getHiddenSuffixEncoder", "solanaCodecsDataStructures")}(${manifest.encoder}, [${suffixEncoders}])`
|
|
2721
|
+
});
|
|
2722
|
+
},
|
|
2723
|
+
visitInstruction(instruction, { self }) {
|
|
2724
|
+
const instructionDataName = nameApi.instructionDataType(instruction.name);
|
|
2725
|
+
parentName = {
|
|
2726
|
+
loose: nameApi.dataArgsType(instructionDataName),
|
|
2727
|
+
strict: nameApi.dataType(instructionDataName)
|
|
2728
|
+
};
|
|
2729
|
+
const link = customInstructionData.get(instruction.name)?.linkNode;
|
|
2730
|
+
const struct = structTypeNodeFromInstructionArgumentNodes5(instruction.arguments);
|
|
2731
|
+
const manifest = link ? visit8(link, self) : visit8(struct, self);
|
|
2732
|
+
parentName = null;
|
|
2733
|
+
return manifest;
|
|
2734
|
+
},
|
|
2735
|
+
visitMapEntryValue(node, { self }) {
|
|
2736
|
+
return mergeTypeManifests([visit8(node.key, self), visit8(node.value, self)], {
|
|
2737
|
+
mergeValues: (renders) => `[${renders.join(", ")}]`
|
|
2738
|
+
});
|
|
2739
|
+
},
|
|
2740
|
+
visitMapType(mapType, { self }) {
|
|
2741
|
+
const key = visit8(mapType.key, self);
|
|
2742
|
+
const value = visit8(mapType.value, self);
|
|
2743
|
+
const mergedManifest = mergeTypeManifests([key, value], {
|
|
2744
|
+
mergeCodecs: ([k, v]) => `${k}, ${v}`,
|
|
2745
|
+
mergeTypes: ([k, v]) => `Map<${k}, ${v}>`
|
|
2746
|
+
});
|
|
2747
|
+
const sizeManifest = getArrayLikeSizeOption(mapType.count, self);
|
|
2748
|
+
const encoderOptions = sizeManifest.encoder ? fragment`, { ${sizeManifest.encoder} }` : "";
|
|
2749
|
+
const decoderOptions = sizeManifest.decoder ? fragment`, { ${sizeManifest.decoder} }` : "";
|
|
2750
|
+
return typeManifest({
|
|
2751
|
+
...mergedManifest,
|
|
2752
|
+
decoder: fragment`${use("getMapDecoder", "solanaCodecsDataStructures")}(${mergedManifest.decoder}${decoderOptions})`,
|
|
2753
|
+
encoder: fragment`${use("getMapEncoder", "solanaCodecsDataStructures")}(${mergedManifest.encoder}${encoderOptions})`
|
|
2754
|
+
});
|
|
2755
|
+
},
|
|
2756
|
+
visitMapValue(node, { self }) {
|
|
2757
|
+
const entryFragments = node.entries.map((entry) => visit8(entry, self));
|
|
2758
|
+
return mergeTypeManifests(entryFragments, {
|
|
2759
|
+
mergeValues: (renders) => `new Map([${renders.join(", ")}])`
|
|
2760
|
+
});
|
|
2761
|
+
},
|
|
2762
|
+
visitNoneValue() {
|
|
2763
|
+
return typeManifest({
|
|
2764
|
+
value: fragment`${use("none", "solanaOptions")}()`
|
|
2765
|
+
});
|
|
2766
|
+
},
|
|
2767
|
+
visitNumberType(numberType) {
|
|
2768
|
+
const encoderFunction = use(nameApi.encoderFunction(numberType.format), "solanaCodecsNumbers");
|
|
2769
|
+
const decoderFunction = use(nameApi.decoderFunction(numberType.format), "solanaCodecsNumbers");
|
|
2770
|
+
const isBigNumber = ["u64", "u128", "i64", "i128"].includes(numberType.format);
|
|
2771
|
+
const endianness = numberType.endian === "be" ? fragment`{ endian: ${use("Endian", "solanaCodecsNumbers")}.Big }` : "";
|
|
2772
|
+
return typeManifest({
|
|
2773
|
+
decoder: fragment`${decoderFunction}(${endianness})`,
|
|
2774
|
+
encoder: fragment`${encoderFunction}(${endianness})`,
|
|
2775
|
+
looseType: fragment`${isBigNumber ? "number | bigint" : "number"}`,
|
|
2776
|
+
strictType: fragment`${isBigNumber ? "bigint" : "number"}`
|
|
2777
|
+
});
|
|
2778
|
+
},
|
|
2779
|
+
visitNumberValue(node) {
|
|
2780
|
+
return typeManifest({ value: fragment`${JSON.stringify(node.number)}` });
|
|
2781
|
+
},
|
|
2782
|
+
visitOptionType(optionType, { self }) {
|
|
2783
|
+
const childManifest = visit8(optionType.item, self);
|
|
2784
|
+
const encoderOptions = [];
|
|
2785
|
+
const decoderOptions = [];
|
|
2786
|
+
const optionPrefix = resolveNestedTypeNode4(optionType.prefix);
|
|
2787
|
+
if (optionPrefix.format !== "u8" || optionPrefix.endian !== "le") {
|
|
2788
|
+
const prefixManifest = visit8(optionType.prefix, self);
|
|
2789
|
+
encoderOptions.push(fragment`prefix: ${prefixManifest.encoder}`);
|
|
2790
|
+
decoderOptions.push(fragment`prefix: ${prefixManifest.decoder}`);
|
|
2791
|
+
}
|
|
2792
|
+
if (optionType.fixed) {
|
|
2793
|
+
encoderOptions.push(fragment`noneValue: "zeroes"`);
|
|
2794
|
+
decoderOptions.push(fragment`noneValue: "zeroes"`);
|
|
2795
|
+
}
|
|
2796
|
+
const encoderOptionsFragment = mergeFragments(
|
|
2797
|
+
encoderOptions,
|
|
2798
|
+
(cs) => cs.length > 0 ? `, { ${cs.join(", ")} }` : ""
|
|
2799
|
+
);
|
|
2800
|
+
const decoderOptionsFragment = mergeFragments(
|
|
2801
|
+
decoderOptions,
|
|
2802
|
+
(cs) => cs.length > 0 ? `, { ${cs.join(", ")} }` : ""
|
|
2803
|
+
);
|
|
2804
|
+
return typeManifest({
|
|
2805
|
+
...childManifest,
|
|
2806
|
+
decoder: fragment`${use("getOptionDecoder", "solanaOptions")}(${childManifest.decoder}${decoderOptionsFragment})`,
|
|
2807
|
+
encoder: fragment`${use("getOptionEncoder", "solanaOptions")}(${childManifest.encoder}${encoderOptionsFragment})`,
|
|
2808
|
+
looseType: fragment`${use("type OptionOrNullable", "solanaOptions")}<${childManifest.looseType}>`,
|
|
2809
|
+
strictType: fragment`${use("type Option", "solanaOptions")}<${childManifest.strictType}>`
|
|
2810
|
+
});
|
|
2811
|
+
},
|
|
2812
|
+
visitPostOffsetType(node, { self }) {
|
|
2813
|
+
const manifest = visit8(node.type, self);
|
|
2814
|
+
if (node.strategy === "padded") {
|
|
2815
|
+
return typeManifest({
|
|
2816
|
+
...manifest,
|
|
2817
|
+
decoder: fragment`${use("padRightDecoder", "solanaCodecsCore")}(${manifest.decoder}, ${node.offset})`,
|
|
2818
|
+
encoder: fragment`${use("padRightEncoder", "solanaCodecsCore")}(${manifest.encoder}, ${node.offset})`
|
|
2819
|
+
});
|
|
2820
|
+
}
|
|
2821
|
+
const fn = (() => {
|
|
2822
|
+
switch (node.strategy) {
|
|
2823
|
+
case "absolute":
|
|
2824
|
+
return node.offset < 0 ? `({ wrapBytes }) => wrapBytes(${node.offset})` : `() => ${node.offset}`;
|
|
2825
|
+
case "preOffset":
|
|
2826
|
+
return node.offset < 0 ? `({ preOffset }) => preOffset ${node.offset}` : `({ preOffset }) => preOffset + ${node.offset}`;
|
|
2827
|
+
case "relative":
|
|
2828
|
+
default:
|
|
2829
|
+
return node.offset < 0 ? `({ postOffset }) => postOffset ${node.offset}` : `({ postOffset }) => postOffset + ${node.offset}`;
|
|
2830
|
+
}
|
|
2831
|
+
})();
|
|
2832
|
+
return typeManifest({
|
|
2833
|
+
...manifest,
|
|
2834
|
+
decoder: fragment`${use("offsetDecoder", "solanaCodecsCore")}(${manifest.decoder}, { postOffset: ${fn} })`,
|
|
2835
|
+
encoder: fragment`${use("offsetEncoder", "solanaCodecsCore")}(${manifest.encoder}, { postOffset: ${fn} })`
|
|
2836
|
+
});
|
|
2837
|
+
},
|
|
2838
|
+
visitPreOffsetType(node, { self }) {
|
|
2839
|
+
const manifest = visit8(node.type, self);
|
|
2840
|
+
if (node.strategy === "padded") {
|
|
2841
|
+
return typeManifest({
|
|
2842
|
+
...manifest,
|
|
2843
|
+
decoder: fragment`${use("padLeftDecoder", "solanaCodecsCore")}(${manifest.decoder}, ${node.offset})`,
|
|
2844
|
+
encoder: fragment`${use("padLeftEncoder", "solanaCodecsCore")}(${manifest.encoder}, ${node.offset})`
|
|
2845
|
+
});
|
|
2846
|
+
}
|
|
2847
|
+
const fn = (() => {
|
|
2848
|
+
switch (node.strategy) {
|
|
2849
|
+
case "absolute":
|
|
2850
|
+
return node.offset < 0 ? `({ wrapBytes }) => wrapBytes(${node.offset})` : `() => ${node.offset}`;
|
|
2851
|
+
case "relative":
|
|
2852
|
+
default:
|
|
2853
|
+
return node.offset < 0 ? `({ preOffset }) => preOffset ${node.offset}` : `({ preOffset }) => preOffset + ${node.offset}`;
|
|
2854
|
+
}
|
|
2855
|
+
})();
|
|
2856
|
+
return typeManifest({
|
|
2857
|
+
...manifest,
|
|
2858
|
+
decoder: fragment`${use("offsetDecoder", "solanaCodecsCore")}(${manifest.decoder}, { preOffset: ${fn} })`,
|
|
2859
|
+
encoder: fragment`${use("offsetEncoder", "solanaCodecsCore")}(${manifest.encoder}, { preOffset: ${fn} })`
|
|
2860
|
+
});
|
|
2861
|
+
},
|
|
2862
|
+
visitPublicKeyType() {
|
|
2863
|
+
return typeManifest({
|
|
2864
|
+
decoder: fragment`${use("getAddressDecoder", "solanaAddresses")}()`,
|
|
2865
|
+
encoder: fragment`${use("getAddressEncoder", "solanaAddresses")}()`,
|
|
2866
|
+
looseType: use("type Address", "solanaAddresses"),
|
|
2867
|
+
strictType: use("type Address", "solanaAddresses")
|
|
2868
|
+
});
|
|
2869
|
+
},
|
|
2870
|
+
visitPublicKeyValue(node) {
|
|
2871
|
+
return typeManifest({
|
|
2872
|
+
value: fragment`${use("address", "solanaAddresses")}("${node.publicKey}")`
|
|
2873
|
+
});
|
|
2874
|
+
},
|
|
2875
|
+
visitRemainderOptionType(node, { self }) {
|
|
2876
|
+
const childManifest = visit8(node.item, self);
|
|
2877
|
+
const encoderOptions = ["prefix: null"];
|
|
2878
|
+
const decoderOptions = ["prefix: null"];
|
|
2879
|
+
const encoderOptionsAsString = encoderOptions.length > 0 ? `, { ${encoderOptions.join(", ")} }` : "";
|
|
2880
|
+
const decoderOptionsAsString = decoderOptions.length > 0 ? `, { ${decoderOptions.join(", ")} }` : "";
|
|
2881
|
+
return typeManifest({
|
|
2882
|
+
...childManifest,
|
|
2883
|
+
decoder: fragment`${use("getOptionDecoder", "solanaOptions")}(${childManifest.decoder}${decoderOptionsAsString})`,
|
|
2884
|
+
encoder: fragment`${use("getOptionEncoder", "solanaOptions")}(${childManifest.encoder}${encoderOptionsAsString})`,
|
|
2885
|
+
looseType: fragment`${use("type OptionOrNullable", "solanaOptions")}<${childManifest.looseType}>`,
|
|
2886
|
+
strictType: fragment`${use("type Option", "solanaOptions")}<${childManifest.strictType}>`
|
|
2887
|
+
});
|
|
2888
|
+
},
|
|
2889
|
+
visitSentinelType(node, { self }) {
|
|
2890
|
+
const manifest = visit8(node.type, self);
|
|
2891
|
+
const sentinel = visit8(node.sentinel, self).value;
|
|
2892
|
+
return typeManifest({
|
|
2893
|
+
...manifest,
|
|
2894
|
+
decoder: fragment`${use("addDecoderSentinel", "solanaCodecsCore")}(${manifest.decoder}, ${sentinel})`,
|
|
2895
|
+
encoder: fragment`${use("addEncoderSentinel", "solanaCodecsCore")}(${manifest.encoder}, ${sentinel})`
|
|
2896
|
+
});
|
|
2897
|
+
},
|
|
2898
|
+
visitSetType(setType, { self }) {
|
|
2899
|
+
const childManifest = visit8(setType.item, self);
|
|
2900
|
+
const sizeManifest = getArrayLikeSizeOption(setType.count, self);
|
|
2901
|
+
const encoderOptions = sizeManifest.encoder ? fragment`, { ${sizeManifest.encoder} }` : "";
|
|
2902
|
+
const decoderOptions = sizeManifest.decoder ? fragment`, { ${sizeManifest.decoder} }` : "";
|
|
2903
|
+
return typeManifest({
|
|
2904
|
+
...childManifest,
|
|
2905
|
+
decoder: fragment`${use("getSetDecoder", "solanaCodecsDataStructures")}(${childManifest.decoder}${decoderOptions})`,
|
|
2906
|
+
encoder: fragment`${use("getSetEncoder", "solanaCodecsDataStructures")}(${childManifest.encoder}${encoderOptions})`,
|
|
2907
|
+
looseType: fragment`Set<${childManifest.looseType}>`,
|
|
2908
|
+
strictType: fragment`Set<${childManifest.strictType}>`
|
|
2909
|
+
});
|
|
2910
|
+
},
|
|
2911
|
+
visitSetValue(node, { self }) {
|
|
2912
|
+
return mergeTypeManifests(
|
|
2913
|
+
node.items.map((v) => visit8(v, self)),
|
|
2914
|
+
{ mergeValues: (renders) => `new Set([${renders.join(", ")}])` }
|
|
2915
|
+
);
|
|
2916
|
+
},
|
|
2917
|
+
visitSizePrefixType(node, { self }) {
|
|
2918
|
+
const manifest = visit8(node.type, self);
|
|
2919
|
+
const prefix = visit8(node.prefix, self);
|
|
2920
|
+
return typeManifest({
|
|
2921
|
+
...manifest,
|
|
2922
|
+
decoder: fragment`${use("addDecoderSizePrefix", "solanaCodecsCore")}(${manifest.decoder}, ${prefix.decoder})`,
|
|
2923
|
+
encoder: fragment`${use("addEncoderSizePrefix", "solanaCodecsCore")}(${manifest.encoder}, ${prefix.encoder})`
|
|
2924
|
+
});
|
|
2925
|
+
},
|
|
2926
|
+
visitSolAmountType({ number }, { self }) {
|
|
2927
|
+
const numberManifest = visit8(number, self);
|
|
2928
|
+
return typeManifest({
|
|
2929
|
+
...numberManifest,
|
|
2930
|
+
decoder: fragment`${use("getLamportsDecoder", "solanaRpcTypes")}(${numberManifest.decoder})`,
|
|
2931
|
+
encoder: fragment`${use("getLamportsEncoder", "solanaRpcTypes")}(${numberManifest.encoder})`,
|
|
2932
|
+
looseType: use("type Lamports", "solanaRpcTypes"),
|
|
2933
|
+
strictType: use("type Lamports", "solanaRpcTypes")
|
|
2934
|
+
});
|
|
2935
|
+
},
|
|
2936
|
+
visitSomeValue(node, { self }) {
|
|
2937
|
+
const innerValue = visit8(node.value, self).value;
|
|
2938
|
+
return typeManifest({
|
|
2939
|
+
value: fragment`${use("some", "solanaOptions")}(${innerValue})`
|
|
2940
|
+
});
|
|
2941
|
+
},
|
|
2942
|
+
visitStringType(stringType) {
|
|
2943
|
+
const [encoder, decoder] = (() => {
|
|
2944
|
+
switch (stringType.encoding) {
|
|
2945
|
+
case "base16":
|
|
2946
|
+
return ["getBase16Encoder", "getBase16Decoder"];
|
|
2947
|
+
case "base58":
|
|
2948
|
+
return ["getBase58Encoder", "getBase58Decoder"];
|
|
2949
|
+
case "base64":
|
|
2950
|
+
return ["getBase64Encoder", "getBase64Decoder"];
|
|
2951
|
+
case "utf8":
|
|
2952
|
+
return ["getUtf8Encoder", "getUtf8Decoder"];
|
|
2953
|
+
default:
|
|
2954
|
+
throw new Error(`Unsupported string encoding: ${stringType.encoding}`);
|
|
2955
|
+
}
|
|
2956
|
+
})();
|
|
2957
|
+
return typeManifest({
|
|
2958
|
+
decoder: fragment`${use(decoder, "solanaCodecsStrings")}()`,
|
|
2959
|
+
encoder: fragment`${use(encoder, "solanaCodecsStrings")}()`,
|
|
2960
|
+
looseType: fragment`string`,
|
|
2961
|
+
strictType: fragment`string`
|
|
2962
|
+
});
|
|
2963
|
+
},
|
|
2964
|
+
visitStringValue(node) {
|
|
2965
|
+
return typeManifest({
|
|
2966
|
+
value: fragment`${JSON.stringify(node.string)}`
|
|
2967
|
+
});
|
|
2968
|
+
},
|
|
2969
|
+
visitStructFieldType(structFieldType, { self }) {
|
|
2970
|
+
const name = camelCase13(structFieldType.name);
|
|
2971
|
+
const originalChildManifest = visit8(structFieldType.type, self);
|
|
2972
|
+
let docs = getDocblockFragment(structFieldType.docs ?? [], true);
|
|
2973
|
+
docs = docs ? fragment`\n${docs}` : docs;
|
|
2974
|
+
const childManifest = typeManifest({
|
|
2975
|
+
...originalChildManifest,
|
|
2976
|
+
decoder: fragment`['${name}', ${originalChildManifest.decoder}]`,
|
|
2977
|
+
encoder: fragment`['${name}', ${originalChildManifest.encoder}]`,
|
|
2978
|
+
looseType: fragment`${docs}${name}: ${originalChildManifest.looseType}; `,
|
|
2979
|
+
strictType: fragment`${docs}${name}: ${originalChildManifest.strictType}; `
|
|
2980
|
+
});
|
|
2981
|
+
if (!structFieldType.defaultValue) {
|
|
2982
|
+
return childManifest;
|
|
2983
|
+
}
|
|
2984
|
+
if (structFieldType.defaultValueStrategy !== "omitted") {
|
|
2985
|
+
return typeManifest({
|
|
2986
|
+
...childManifest,
|
|
2987
|
+
looseType: fragment`${docs}${name}?: ${originalChildManifest.looseType}; `
|
|
2988
|
+
});
|
|
2989
|
+
}
|
|
2990
|
+
return typeManifest({ ...childManifest, looseType: fragment`` });
|
|
2991
|
+
},
|
|
2992
|
+
visitStructFieldValue(node, { self }) {
|
|
2993
|
+
const innerValue = visit8(node.value, self).value;
|
|
2994
|
+
return typeManifest({
|
|
2995
|
+
value: fragment`${node.name}: ${innerValue}`
|
|
2996
|
+
});
|
|
2997
|
+
},
|
|
2998
|
+
visitStructType(structType, { self }) {
|
|
2999
|
+
const optionalFields = structType.fields.filter((f) => !!f.defaultValue);
|
|
3000
|
+
const mergedManifest = pipe15(
|
|
3001
|
+
mergeTypeManifests(
|
|
3002
|
+
structType.fields.map((field) => visit8(field, self)),
|
|
3003
|
+
{
|
|
3004
|
+
mergeCodecs: (renders) => `([${renders.join(", ")}])`,
|
|
3005
|
+
mergeTypes: (renders) => `{ ${renders.join("")} }`
|
|
3006
|
+
}
|
|
3007
|
+
),
|
|
3008
|
+
(manifest) => typeManifest({
|
|
3009
|
+
...manifest,
|
|
3010
|
+
decoder: fragment`${use("getStructDecoder", "solanaCodecsDataStructures")}${manifest.decoder}`,
|
|
3011
|
+
encoder: fragment`${use("getStructEncoder", "solanaCodecsDataStructures")}${manifest.encoder}`
|
|
3012
|
+
})
|
|
3013
|
+
);
|
|
3014
|
+
if (optionalFields.length === 0) {
|
|
3015
|
+
return mergedManifest;
|
|
3016
|
+
}
|
|
3017
|
+
const parentPath = stack.getPath();
|
|
3018
|
+
const instructionNode = findLastNodeFromPath(parentPath, "instructionNode");
|
|
3019
|
+
const accountNode = findLastNodeFromPath(parentPath, "accountNode");
|
|
3020
|
+
const discriminatorPrefix = instructionNode ? instructionNode.name : accountNode?.name;
|
|
3021
|
+
const discriminators = (instructionNode ? instructionNode.discriminators : accountNode?.discriminators) ?? [];
|
|
3022
|
+
const fieldDiscriminators = discriminators.filter(isNodeFilter6("fieldDiscriminatorNode"));
|
|
3023
|
+
const defaultValues = mergeFragments(
|
|
3024
|
+
optionalFields.map((f) => {
|
|
3025
|
+
const key = camelCase13(f.name);
|
|
3026
|
+
if (fieldDiscriminators.some((d) => d.name === f.name)) {
|
|
3027
|
+
const constantName = nameApi.constant(camelCase13(`${discriminatorPrefix}_${f.name}`));
|
|
3028
|
+
return f.defaultValueStrategy === "omitted" ? fragment`${key}: ${constantName}` : fragment`${key}: value.${key} ?? ${constantName}`;
|
|
3029
|
+
}
|
|
3030
|
+
const defaultValue = f.defaultValue;
|
|
3031
|
+
const value = visit8(defaultValue, self).value;
|
|
3032
|
+
return f.defaultValueStrategy === "omitted" ? fragment`${key}: ${value}` : fragment`${key}: value.${key} ?? ${value}`;
|
|
3033
|
+
}),
|
|
3034
|
+
(cs) => cs.join(", ")
|
|
3035
|
+
);
|
|
3036
|
+
return typeManifest({
|
|
3037
|
+
...mergedManifest,
|
|
3038
|
+
encoder: fragment`${use("transformEncoder", "solanaCodecsCore")}(${mergedManifest.encoder}, (value) => ({ ...value, ${defaultValues} }))`
|
|
3039
|
+
});
|
|
3040
|
+
},
|
|
3041
|
+
visitStructValue(node, { self }) {
|
|
3042
|
+
return mergeTypeManifests(
|
|
3043
|
+
node.fields.map((field) => visit8(field, self)),
|
|
3044
|
+
{ mergeValues: (renders) => `{ ${renders.join(", ")} }` }
|
|
3045
|
+
);
|
|
3046
|
+
},
|
|
3047
|
+
visitTupleType(tupleType, { self }) {
|
|
3048
|
+
const items = tupleType.items.map((item) => visit8(item, self));
|
|
3049
|
+
const mergedManifest = mergeTypeManifests(items, {
|
|
3050
|
+
mergeCodecs: (codecs) => `[${codecs.join(", ")}]`,
|
|
3051
|
+
mergeTypes: (types) => `readonly [${types.join(", ")}]`
|
|
3052
|
+
});
|
|
3053
|
+
return typeManifest({
|
|
3054
|
+
...mergedManifest,
|
|
3055
|
+
decoder: fragment`${use("getTupleDecoder", "solanaCodecsDataStructures")}(${mergedManifest.decoder})`,
|
|
3056
|
+
encoder: fragment`${use("getTupleEncoder", "solanaCodecsDataStructures")}(${mergedManifest.encoder})`
|
|
3057
|
+
});
|
|
3058
|
+
},
|
|
3059
|
+
visitTupleValue(node, { self }) {
|
|
3060
|
+
return mergeTypeManifests(
|
|
3061
|
+
node.items.map((v) => visit8(v, self)),
|
|
3062
|
+
{ mergeValues: (renders) => `[${renders.join(", ")}]` }
|
|
3063
|
+
);
|
|
3064
|
+
},
|
|
3065
|
+
visitZeroableOptionType(node, { self }) {
|
|
3066
|
+
const childManifest = visit8(node.item, self);
|
|
3067
|
+
const encoderOptions = [fragment`prefix: null`];
|
|
3068
|
+
const decoderOptions = [fragment`prefix: null`];
|
|
3069
|
+
if (node.zeroValue) {
|
|
3070
|
+
const zeroValueManifest = visit8(node.zeroValue, self);
|
|
3071
|
+
encoderOptions.push(fragment`noneValue: ${zeroValueManifest.value}`);
|
|
3072
|
+
decoderOptions.push(fragment`noneValue: ${zeroValueManifest.value}`);
|
|
3073
|
+
} else {
|
|
3074
|
+
encoderOptions.push(fragment`noneValue: "zeroes"`);
|
|
3075
|
+
decoderOptions.push(fragment`noneValue: "zeroes"`);
|
|
3076
|
+
}
|
|
3077
|
+
const encoderOptionsFragment = mergeFragments(
|
|
3078
|
+
encoderOptions,
|
|
3079
|
+
(cs) => cs.length > 0 ? `, { ${cs.join(", ")} }` : ""
|
|
3080
|
+
);
|
|
3081
|
+
const decoderOptionsFragment = mergeFragments(
|
|
3082
|
+
decoderOptions,
|
|
3083
|
+
(cs) => cs.length > 0 ? `, { ${cs.join(", ")} }` : ""
|
|
3084
|
+
);
|
|
3085
|
+
return typeManifest({
|
|
3086
|
+
...childManifest,
|
|
3087
|
+
decoder: fragment`${use("getOptionDecoder", "solanaOptions")}(${childManifest.decoder}${decoderOptionsFragment})`,
|
|
3088
|
+
encoder: fragment`${use("getOptionEncoder", "solanaOptions")}(${childManifest.encoder}${encoderOptionsFragment})`,
|
|
3089
|
+
looseType: fragment`${use("type OptionOrNullable", "solanaOptions")}<${childManifest.looseType}>`,
|
|
3090
|
+
strictType: fragment`${use("type Option", "solanaOptions")}<${childManifest.strictType}>`
|
|
3091
|
+
});
|
|
3092
|
+
}
|
|
3093
|
+
}),
|
|
3094
|
+
(visitor) => recordNodeStackVisitor(visitor, stack)
|
|
3095
|
+
);
|
|
3096
|
+
}
|
|
3097
|
+
function getArrayLikeSizeOption(count, visitor) {
|
|
3098
|
+
if (isNode15(count, "fixedCountNode")) {
|
|
3099
|
+
return {
|
|
3100
|
+
decoder: fragment`size: ${count.value}`,
|
|
3101
|
+
encoder: fragment`size: ${count.value}`
|
|
3102
|
+
};
|
|
3103
|
+
}
|
|
3104
|
+
if (isNode15(count, "remainderCountNode")) {
|
|
3105
|
+
return {
|
|
3106
|
+
decoder: fragment`size: 'remainder'`,
|
|
3107
|
+
encoder: fragment`size: 'remainder'`
|
|
3108
|
+
};
|
|
3109
|
+
}
|
|
3110
|
+
const prefix = resolveNestedTypeNode4(count.prefix);
|
|
3111
|
+
if (prefix.format === "u32" && prefix.endian === "le") {
|
|
3112
|
+
return { decoder: void 0, encoder: void 0 };
|
|
3113
|
+
}
|
|
3114
|
+
const prefixManifest = visit8(count.prefix, visitor);
|
|
3115
|
+
return {
|
|
3116
|
+
decoder: pipe15(prefixManifest.decoder, (f) => mapFragmentContent11(f, (c) => `size: ${c}`)),
|
|
3117
|
+
encoder: pipe15(prefixManifest.encoder, (f) => mapFragmentContent11(f, (c) => `size: ${c}`))
|
|
3118
|
+
};
|
|
3119
|
+
}
|
|
3120
|
+
|
|
3121
|
+
// src/visitors/getRenderMapVisitor.ts
|
|
3122
|
+
function getRenderMapVisitor(options = {}) {
|
|
3123
|
+
const linkables = new LinkableDictionary3();
|
|
3124
|
+
const stack = new NodeStack2();
|
|
3125
|
+
const customAccountData = parseCustomDataOptions(options.customAccountData ?? [], "AccountData");
|
|
3126
|
+
const customInstructionData = parseCustomDataOptions(options.customInstructionData ?? [], "InstructionData");
|
|
3127
|
+
const renderScopeWithTypeManifestVisitor = {
|
|
3128
|
+
asyncResolvers: (options.asyncResolvers ?? []).map(camelCase14),
|
|
3129
|
+
customAccountData,
|
|
3130
|
+
customInstructionData,
|
|
3131
|
+
dependencyMap: options.dependencyMap ?? {},
|
|
3132
|
+
getImportFrom: getImportFromFactory(options.linkOverrides ?? {}, customAccountData, customInstructionData),
|
|
3133
|
+
linkables,
|
|
3134
|
+
nameApi: getNameApi({ ...DEFAULT_NAME_TRANSFORMERS, ...options.nameTransformers }),
|
|
3135
|
+
nonScalarEnums: (options.nonScalarEnums ?? []).map(camelCase14),
|
|
3136
|
+
renderParentInstructions: options.renderParentInstructions ?? false,
|
|
3137
|
+
useGranularImports: options.useGranularImports ?? false
|
|
3138
|
+
};
|
|
3139
|
+
const typeManifestVisitor = getTypeManifestVisitor({ ...renderScopeWithTypeManifestVisitor, stack });
|
|
3140
|
+
const renderScope = { ...renderScopeWithTypeManifestVisitor, typeManifestVisitor };
|
|
3141
|
+
const internalNodes = (options.internalNodes ?? []).map(camelCase14);
|
|
3142
|
+
const resolvedInstructionInputVisitor = getResolvedInstructionInputsVisitor();
|
|
3143
|
+
const byteSizeVisitor = getByteSizeVisitor(linkables, { stack });
|
|
3144
|
+
const asPage = (fragment2, dependencyMap = {}) => {
|
|
3145
|
+
if (!fragment2) return void 0;
|
|
3146
|
+
return getPageFragment(fragment2, {
|
|
3147
|
+
...renderScope,
|
|
3148
|
+
dependencyMap: { ...renderScope.dependencyMap, ...dependencyMap }
|
|
3149
|
+
});
|
|
3150
|
+
};
|
|
3151
|
+
return pipe16(
|
|
3152
|
+
staticVisitor2(() => createRenderMap(), {
|
|
3153
|
+
keys: ["rootNode", "programNode", "pdaNode", "accountNode", "definedTypeNode", "instructionNode"]
|
|
3154
|
+
}),
|
|
3155
|
+
(v) => extendVisitor2(v, {
|
|
3156
|
+
visitAccount(node) {
|
|
3157
|
+
return createRenderMap(
|
|
3158
|
+
`accounts/${camelCase14(node.name)}.ts`,
|
|
3159
|
+
asPage(
|
|
3160
|
+
getAccountPageFragment({
|
|
3161
|
+
...renderScope,
|
|
3162
|
+
accountPath: stack.getPath("accountNode"),
|
|
3163
|
+
size: visit9(node, byteSizeVisitor)
|
|
3164
|
+
})
|
|
3165
|
+
)
|
|
3166
|
+
);
|
|
3167
|
+
},
|
|
3168
|
+
visitDefinedType(node) {
|
|
3169
|
+
return createRenderMap(
|
|
3170
|
+
`types/${camelCase14(node.name)}.ts`,
|
|
3171
|
+
asPage(getTypePageFragment({ ...renderScope, node, size: visit9(node, byteSizeVisitor) }), {
|
|
3172
|
+
generatedTypes: "."
|
|
3173
|
+
})
|
|
3174
|
+
);
|
|
3175
|
+
},
|
|
3176
|
+
visitInstruction(node) {
|
|
3177
|
+
return createRenderMap(
|
|
3178
|
+
`instructions/${camelCase14(node.name)}.ts`,
|
|
3179
|
+
asPage(
|
|
3180
|
+
getInstructionPageFragment({
|
|
3181
|
+
...renderScope,
|
|
3182
|
+
instructionPath: stack.getPath("instructionNode"),
|
|
3183
|
+
resolvedInputs: visit9(node, resolvedInstructionInputVisitor),
|
|
3184
|
+
size: visit9(node, byteSizeVisitor)
|
|
3185
|
+
})
|
|
3186
|
+
)
|
|
3187
|
+
);
|
|
3188
|
+
},
|
|
3189
|
+
visitPda(node) {
|
|
3190
|
+
return createRenderMap(
|
|
3191
|
+
`pdas/${camelCase14(node.name)}.ts`,
|
|
3192
|
+
asPage(getPdaPageFragment({ ...renderScope, pdaPath: stack.getPath("pdaNode") }))
|
|
3193
|
+
);
|
|
3194
|
+
},
|
|
3195
|
+
visitProgram(node, { self }) {
|
|
3196
|
+
const customDataDefinedType = [
|
|
3197
|
+
...getDefinedTypeNodesToExtract(node.accounts, customAccountData),
|
|
3198
|
+
...getDefinedTypeNodesToExtract(node.instructions, customInstructionData)
|
|
3199
|
+
];
|
|
3200
|
+
const scope = { ...renderScope, programNode: node };
|
|
3201
|
+
return mergeRenderMaps([
|
|
3202
|
+
createRenderMap({
|
|
3203
|
+
[`programs/${camelCase14(node.name)}.ts`]: asPage(getProgramPageFragment(scope)),
|
|
3204
|
+
[`errors/${camelCase14(node.name)}.ts`]: node.errors.length > 0 ? asPage(getErrorPageFragment(scope)) : void 0
|
|
3205
|
+
}),
|
|
3206
|
+
...node.pdas.map((p) => visit9(p, self)),
|
|
3207
|
+
...node.accounts.map((a) => visit9(a, self)),
|
|
3208
|
+
...node.definedTypes.map((t) => visit9(t, self)),
|
|
3209
|
+
...customDataDefinedType.map((t) => visit9(t, self)),
|
|
3210
|
+
...getAllInstructionsWithSubs2(node, { leavesOnly: !renderScope.renderParentInstructions }).map(
|
|
3211
|
+
(i) => visit9(i, self)
|
|
3212
|
+
)
|
|
3213
|
+
]);
|
|
3214
|
+
},
|
|
3215
|
+
visitRoot(node, { self }) {
|
|
3216
|
+
const isNotInternal = (n) => !internalNodes.includes(n.name);
|
|
3217
|
+
const programsToExport = getAllPrograms(node).filter(isNotInternal);
|
|
3218
|
+
const programsWithErrorsToExport = programsToExport.filter((p) => p.errors.length > 0);
|
|
3219
|
+
const pdasToExport = getAllPdas(node);
|
|
3220
|
+
const accountsToExport = getAllAccounts(node).filter(isNotInternal);
|
|
3221
|
+
const instructionsToExport = getAllInstructionsWithSubs2(node, {
|
|
3222
|
+
leavesOnly: !renderScope.renderParentInstructions
|
|
3223
|
+
}).filter(isNotInternal);
|
|
3224
|
+
const definedTypesToExport = getAllDefinedTypes(node).filter(isNotInternal);
|
|
3225
|
+
const hasAnythingToExport = programsToExport.length > 0 || accountsToExport.length > 0 || instructionsToExport.length > 0 || definedTypesToExport.length > 0;
|
|
3226
|
+
const scope = {
|
|
3227
|
+
...renderScope,
|
|
3228
|
+
accountsToExport,
|
|
3229
|
+
definedTypesToExport,
|
|
3230
|
+
instructionsToExport,
|
|
3231
|
+
pdasToExport,
|
|
3232
|
+
programsToExport
|
|
3233
|
+
};
|
|
3234
|
+
return mergeRenderMaps([
|
|
3235
|
+
createRenderMap({
|
|
3236
|
+
["accounts/index.ts"]: asPage(getIndexPageFragment(accountsToExport)),
|
|
3237
|
+
["errors/index.ts"]: asPage(getIndexPageFragment(programsWithErrorsToExport)),
|
|
3238
|
+
["index.ts"]: asPage(getRootIndexPageFragment(scope)),
|
|
3239
|
+
["instructions/index.ts"]: asPage(getIndexPageFragment(instructionsToExport)),
|
|
3240
|
+
["pdas/index.ts"]: asPage(getIndexPageFragment(pdasToExport)),
|
|
3241
|
+
["programs/index.ts"]: asPage(getIndexPageFragment(programsToExport)),
|
|
3242
|
+
["shared/index.ts"]: hasAnythingToExport ? asPage(getSharedPageFragment()) : void 0,
|
|
3243
|
+
["types/index.ts"]: asPage(getIndexPageFragment(definedTypesToExport))
|
|
3244
|
+
}),
|
|
3245
|
+
...getAllPrograms(node).map((p) => visit9(p, self))
|
|
3246
|
+
]);
|
|
3247
|
+
}
|
|
3248
|
+
}),
|
|
3249
|
+
(v) => recordNodeStackVisitor2(v, stack),
|
|
3250
|
+
(v) => recordLinkablesOnFirstVisitVisitor(v, linkables)
|
|
3251
|
+
);
|
|
3252
|
+
}
|
|
3253
|
+
|
|
3254
|
+
// src/visitors/renderVisitor.ts
|
|
3255
|
+
import { deleteDirectory, mapRenderMapContentAsync, writeRenderMap } from "@codama/renderers-core";
|
|
3256
|
+
import { rootNodeVisitor, visit as visit10 } from "@codama/visitors-core";
|
|
3257
|
+
import * as estreePlugin from "prettier/plugins/estree";
|
|
3258
|
+
import * as typeScriptPlugin from "prettier/plugins/typescript";
|
|
3259
|
+
import { format } from "prettier/standalone";
|
|
3260
|
+
var DEFAULT_PRETTIER_OPTIONS = {
|
|
3261
|
+
arrowParens: "always",
|
|
3262
|
+
parser: "typescript",
|
|
3263
|
+
plugins: [estreePlugin, typeScriptPlugin],
|
|
3264
|
+
printWidth: 80,
|
|
3265
|
+
semi: true,
|
|
3266
|
+
singleQuote: true,
|
|
3267
|
+
tabWidth: 2,
|
|
3268
|
+
trailingComma: "es5",
|
|
3269
|
+
useTabs: false
|
|
3270
|
+
};
|
|
3271
|
+
function renderVisitor(path, options = {}) {
|
|
3272
|
+
return rootNodeVisitor(async (root) => {
|
|
3273
|
+
if (options.deleteFolderBeforeRendering ?? true) {
|
|
3274
|
+
deleteDirectory(path);
|
|
3275
|
+
}
|
|
3276
|
+
let renderMap = visit10(root, getRenderMapVisitor(options));
|
|
3277
|
+
if (options.formatCode ?? true) {
|
|
3278
|
+
const prettierOptions = { ...DEFAULT_PRETTIER_OPTIONS, ...options.prettierOptions };
|
|
3279
|
+
renderMap = await mapRenderMapContentAsync(renderMap, (code) => format(code, prettierOptions));
|
|
3280
|
+
}
|
|
3281
|
+
writeRenderMap(renderMap, path);
|
|
3282
|
+
});
|
|
3283
|
+
}
|
|
3284
|
+
export {
|
|
3285
|
+
DEFAULT_NAME_TRANSFORMERS,
|
|
3286
|
+
addToImportMap,
|
|
3287
|
+
createImportMap,
|
|
3288
|
+
renderVisitor as default,
|
|
3289
|
+
getNameApi,
|
|
3290
|
+
getRenderMapVisitor,
|
|
3291
|
+
getTypeManifestVisitor,
|
|
3292
|
+
importMapToString,
|
|
3293
|
+
mergeImportMaps,
|
|
3294
|
+
mergeTypeManifests,
|
|
3295
|
+
parseImportInput,
|
|
3296
|
+
removeFromImportMap,
|
|
3297
|
+
renderVisitor,
|
|
3298
|
+
typeManifest
|
|
3299
|
+
};
|
|
3300
|
+
//# sourceMappingURL=index.browser.mjs.map
|