@seljs/env 1.0.0 → 1.0.1-beta.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/builder.cjs +220 -0
- package/dist/builder.d.cts +39 -0
- package/dist/builder.d.mts +39 -0
- package/dist/builder.mjs +219 -0
- package/dist/builtins.cjs +373 -0
- package/dist/{builtins.d.ts → builtins.d.cts} +8 -5
- package/dist/builtins.d.mts +20 -0
- package/dist/builtins.mjs +371 -0
- package/dist/index.cjs +8 -0
- package/dist/index.d.cts +3 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +3 -0
- package/package.json +18 -11
- package/dist/builder.d.ts +0 -36
- package/dist/builder.d.ts.map +0 -1
- package/dist/builder.js +0 -223
- package/dist/builder.spec.d.ts +0 -2
- package/dist/builder.spec.d.ts.map +0 -1
- package/dist/builder.spec.js +0 -428
- package/dist/builtins.d.ts.map +0 -1
- package/dist/builtins.js +0 -307
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -2
package/dist/builder.cjs
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
const require_builtins = require("./builtins.cjs");
|
|
2
|
+
let _seljs_common = require("@seljs/common");
|
|
3
|
+
let _seljs_types = require("@seljs/types");
|
|
4
|
+
//#region src/builder.ts
|
|
5
|
+
/**
|
|
6
|
+
* Checks if the given ABI parameter is a tuple type with components, indicating that it represents a struct in Solidity.
|
|
7
|
+
* @param param
|
|
8
|
+
*/
|
|
9
|
+
const isTupleParam = (param) => param.type === "tuple" && "components" in param;
|
|
10
|
+
/**
|
|
11
|
+
* Checks if the given ABI parameter is an array of tuples with components, indicating that it represents an array of structs in Solidity.
|
|
12
|
+
* @param param
|
|
13
|
+
*/
|
|
14
|
+
const isTupleArrayParam = (param) => param.type === "tuple[]" && "components" in param;
|
|
15
|
+
/**
|
|
16
|
+
* Checks if the given ABI parameter is either a tuple or an array of tuples, both of which indicate the presence of components and thus represent struct types in Solidity.
|
|
17
|
+
*
|
|
18
|
+
* @param param
|
|
19
|
+
*/
|
|
20
|
+
const isAnyTupleParam = (param) => isTupleParam(param) || isTupleArrayParam(param);
|
|
21
|
+
/**
|
|
22
|
+
* Generates a unique type name for a nested struct based on the parent type name and the field name, used for naming struct types in the SEL schema.
|
|
23
|
+
*
|
|
24
|
+
* @param parentTypeName Name of the parent type (e.g., contract name or parent struct name) to which the field belongs, used as a prefix for the nested struct type name.
|
|
25
|
+
* @param fieldName Name of the field for which to generate the nested struct type name, used as a suffix in the nested struct type name.
|
|
26
|
+
*/
|
|
27
|
+
const nestedTypeName = (parentTypeName, fieldName) => `${parentTypeName}__${fieldName}`;
|
|
28
|
+
/**
|
|
29
|
+
* Recursively builds struct field definitions.
|
|
30
|
+
*
|
|
31
|
+
* @param components Array of ABI parameters representing the components of a tuple type.
|
|
32
|
+
* @param parentTypeName Name to use for the struct type representing the current level of nesting.
|
|
33
|
+
*/
|
|
34
|
+
const buildStructFields = (components, parentTypeName) => {
|
|
35
|
+
const fields = {};
|
|
36
|
+
const nestedTypes = [];
|
|
37
|
+
for (const component of components) {
|
|
38
|
+
const fieldName = component.name ?? "arg0";
|
|
39
|
+
if (isTupleParam(component) && component.components.length > 0) {
|
|
40
|
+
const childTypeName = nestedTypeName(parentTypeName, fieldName);
|
|
41
|
+
const child = buildStructFields(component.components, childTypeName);
|
|
42
|
+
nestedTypes.push(...child.nestedTypes);
|
|
43
|
+
nestedTypes.push({
|
|
44
|
+
typeName: childTypeName,
|
|
45
|
+
fields: child.fields
|
|
46
|
+
});
|
|
47
|
+
fields[fieldName] = childTypeName;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (isTupleArrayParam(component) && component.components.length > 0) {
|
|
51
|
+
const childTypeName = nestedTypeName(parentTypeName, fieldName);
|
|
52
|
+
const child = buildStructFields(component.components, childTypeName);
|
|
53
|
+
nestedTypes.push(...child.nestedTypes);
|
|
54
|
+
nestedTypes.push({
|
|
55
|
+
typeName: childTypeName,
|
|
56
|
+
fields: child.fields
|
|
57
|
+
});
|
|
58
|
+
fields[fieldName] = `list<${childTypeName}>`;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
fields[fieldName] = (0, _seljs_types.mapSolidityTypeToCEL)(component.type) ?? "dyn";
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
fields,
|
|
65
|
+
nestedTypes
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Builds method parameters for a given array of ABI parameters.
|
|
70
|
+
*
|
|
71
|
+
* @param inputs Array of ABI parameters representing the inputs of a function.
|
|
72
|
+
*/
|
|
73
|
+
const buildMethodParams = (inputs) => {
|
|
74
|
+
return inputs.map((param, index) => ({
|
|
75
|
+
name: param.name || `arg${String(index)}`,
|
|
76
|
+
type: (0, _seljs_types.mapSolidityTypeToCEL)(param.type) ?? "dyn"
|
|
77
|
+
}));
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Builds the return type resolution for a method based on its ABI components, handling nested structs as needed.
|
|
81
|
+
*
|
|
82
|
+
* @param components Array of ABI parameters representing the components of a tuple return type.
|
|
83
|
+
* @param typeName Name to use for the struct type representing the return value, used for naming nested struct types as well.
|
|
84
|
+
*/
|
|
85
|
+
const buildStructReturn = (components, typeName) => {
|
|
86
|
+
const result = buildStructFields(components, typeName);
|
|
87
|
+
const structTypes = [];
|
|
88
|
+
for (const nested of result.nestedTypes) structTypes.push({
|
|
89
|
+
name: nested.typeName,
|
|
90
|
+
kind: "struct",
|
|
91
|
+
fields: Object.entries(nested.fields).map(([name, type]) => ({
|
|
92
|
+
name,
|
|
93
|
+
type
|
|
94
|
+
}))
|
|
95
|
+
});
|
|
96
|
+
structTypes.push({
|
|
97
|
+
name: typeName,
|
|
98
|
+
kind: "struct",
|
|
99
|
+
fields: Object.entries(result.fields).map(([name, type]) => ({
|
|
100
|
+
name,
|
|
101
|
+
type
|
|
102
|
+
}))
|
|
103
|
+
});
|
|
104
|
+
return {
|
|
105
|
+
returns: typeName,
|
|
106
|
+
structTypes
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Resolves the return type of method based on its ABI function definition.
|
|
111
|
+
*
|
|
112
|
+
* @param fn ABI function for which to resolve the return type.
|
|
113
|
+
* @param contractName Name of the contract to which the function belongs, used for naming nested struct types.
|
|
114
|
+
*/
|
|
115
|
+
const resolveMethodReturnType = (fn, contractName) => {
|
|
116
|
+
const firstOutput = fn.outputs[0];
|
|
117
|
+
if (!firstOutput) return {
|
|
118
|
+
returns: "dyn",
|
|
119
|
+
structTypes: []
|
|
120
|
+
};
|
|
121
|
+
if (fn.outputs.length === 1 && !isAnyTupleParam(firstOutput)) return {
|
|
122
|
+
returns: (0, _seljs_types.mapSolidityTypeToCEL)(firstOutput.type) ?? "dyn",
|
|
123
|
+
structTypes: []
|
|
124
|
+
};
|
|
125
|
+
const typeName = (0, _seljs_common.structTypeName)(contractName, fn.name);
|
|
126
|
+
const isSingleOutput = fn.outputs.length === 1;
|
|
127
|
+
const isSingleTupleArray = isSingleOutput && isTupleArrayParam(firstOutput);
|
|
128
|
+
const isSingleTuple = isSingleOutput && isTupleParam(firstOutput);
|
|
129
|
+
let components;
|
|
130
|
+
if (isSingleTuple || isSingleTupleArray) components = firstOutput.components;
|
|
131
|
+
else components = fn.outputs.map((o, i) => ({
|
|
132
|
+
...o,
|
|
133
|
+
name: o.name ?? `arg${String(i)}`
|
|
134
|
+
}));
|
|
135
|
+
const resolution = buildStructReturn(components, typeName);
|
|
136
|
+
if (isSingleTupleArray) return {
|
|
137
|
+
returns: `list<${typeName}>`,
|
|
138
|
+
structTypes: resolution.structTypes
|
|
139
|
+
};
|
|
140
|
+
else return resolution;
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Builds a MethodSchema for a given ABI function.
|
|
144
|
+
*
|
|
145
|
+
* @param fn ABI function for which to build the MethodSchema.
|
|
146
|
+
* @param contractName Name of the contract to which the function belongs, used for naming nested struct types.
|
|
147
|
+
* @param acc Accumulator to keep track of seen struct types and collect unique TypeSchemas for nested structs.
|
|
148
|
+
*/
|
|
149
|
+
const buildMethodSchema = (fn, contractName, acc) => {
|
|
150
|
+
const params = buildMethodParams(fn.inputs);
|
|
151
|
+
const resolution = resolveMethodReturnType(fn, contractName);
|
|
152
|
+
for (const st of resolution.structTypes) if (!acc.seen.has(st.name)) {
|
|
153
|
+
acc.types.push(st);
|
|
154
|
+
acc.seen.add(st.name);
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
name: fn.name,
|
|
158
|
+
params,
|
|
159
|
+
returns: resolution.returns,
|
|
160
|
+
abi: fn
|
|
161
|
+
};
|
|
162
|
+
};
|
|
163
|
+
/**
|
|
164
|
+
* Builds a ContractSchema for a given contract by processing its ABI and extracting view/pure functions as methods.
|
|
165
|
+
*
|
|
166
|
+
* @param contractName Name of the contract for which to build the schema.
|
|
167
|
+
* @param input ContractInput containing the ABI and other relevant information for the contract.
|
|
168
|
+
* @param acc Accumulator to keep track of seen struct types and collect unique TypeSchemas for nested structs.
|
|
169
|
+
*/
|
|
170
|
+
const buildContractSchema = (contractName, input, acc) => {
|
|
171
|
+
const methods = input.abi.filter((item) => item.type === "function" && (item.stateMutability === "view" || item.stateMutability === "pure")).map((fn) => buildMethodSchema(fn, contractName, acc));
|
|
172
|
+
return {
|
|
173
|
+
name: contractName,
|
|
174
|
+
address: input.address,
|
|
175
|
+
description: input.description,
|
|
176
|
+
methods
|
|
177
|
+
};
|
|
178
|
+
};
|
|
179
|
+
/**
|
|
180
|
+
* Resolves a ContextFieldDefinition to its CEL type string.
|
|
181
|
+
*/
|
|
182
|
+
const resolveFieldType = (field) => typeof field === "string" ? field : field.type;
|
|
183
|
+
/**
|
|
184
|
+
* Resolves the optional description from a ContextFieldDefinition.
|
|
185
|
+
*/
|
|
186
|
+
const resolveFieldDescription = (field) => typeof field === "string" ? void 0 : field.description;
|
|
187
|
+
/**
|
|
188
|
+
* Extracts variables from the provided context definition and builds an array of VariableSchema objects.
|
|
189
|
+
*/
|
|
190
|
+
const buildVariablesFromContext = (config) => {
|
|
191
|
+
if (!config.context) return [];
|
|
192
|
+
return Object.entries(config.context).map(([name, field]) => ({
|
|
193
|
+
name,
|
|
194
|
+
type: resolveFieldType(field),
|
|
195
|
+
description: resolveFieldDescription(field)
|
|
196
|
+
}));
|
|
197
|
+
};
|
|
198
|
+
/**
|
|
199
|
+
* Builds a SELSchema based on the provided configuration, which includes contract definitions and an optional context for variables.
|
|
200
|
+
*
|
|
201
|
+
* @param config Configuration object containing contract definitions and an optional context for variables.
|
|
202
|
+
* @returns A SELSchema object representing the schema for the SEL environment.
|
|
203
|
+
*/
|
|
204
|
+
const buildSchema = (config) => {
|
|
205
|
+
const acc = {
|
|
206
|
+
seen: /* @__PURE__ */ new Set(),
|
|
207
|
+
types: []
|
|
208
|
+
};
|
|
209
|
+
return {
|
|
210
|
+
version: "1.0.0",
|
|
211
|
+
contracts: Object.entries(config.contracts ?? {}).map(([name, input]) => buildContractSchema(name, input, acc)),
|
|
212
|
+
variables: buildVariablesFromContext(config),
|
|
213
|
+
types: [...require_builtins.SOLIDITY_PRIMITIVE_TYPES, ...acc.types],
|
|
214
|
+
functions: require_builtins.CEL_BUILTIN_FUNCTIONS,
|
|
215
|
+
macros: require_builtins.CEL_BUILTIN_MACROS
|
|
216
|
+
};
|
|
217
|
+
};
|
|
218
|
+
//#endregion
|
|
219
|
+
exports.buildSchema = buildSchema;
|
|
220
|
+
exports.buildStructFields = buildStructFields;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { SELSchema } from "@seljs/schema";
|
|
2
|
+
import { ContextDefinition } from "@seljs/types";
|
|
3
|
+
import { AbiParameter } from "abitype";
|
|
4
|
+
import { Abi, Address } from "viem";
|
|
5
|
+
|
|
6
|
+
//#region src/builder.d.ts
|
|
7
|
+
interface StructTypeDefinition {
|
|
8
|
+
typeName: string;
|
|
9
|
+
fields: Record<string, string>;
|
|
10
|
+
}
|
|
11
|
+
interface BuildStructFieldsResult {
|
|
12
|
+
fields: Record<string, string>;
|
|
13
|
+
nestedTypes: StructTypeDefinition[];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Recursively builds struct field definitions.
|
|
17
|
+
*
|
|
18
|
+
* @param components Array of ABI parameters representing the components of a tuple type.
|
|
19
|
+
* @param parentTypeName Name to use for the struct type representing the current level of nesting.
|
|
20
|
+
*/
|
|
21
|
+
declare const buildStructFields: (components: readonly AbiParameter[], parentTypeName: string) => BuildStructFieldsResult;
|
|
22
|
+
interface ContractInput {
|
|
23
|
+
address: Address;
|
|
24
|
+
abi: Abi;
|
|
25
|
+
description?: string;
|
|
26
|
+
}
|
|
27
|
+
interface SchemaBuilderConfig {
|
|
28
|
+
contracts?: Record<string, ContractInput>;
|
|
29
|
+
context?: ContextDefinition;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Builds a SELSchema based on the provided configuration, which includes contract definitions and an optional context for variables.
|
|
33
|
+
*
|
|
34
|
+
* @param config Configuration object containing contract definitions and an optional context for variables.
|
|
35
|
+
* @returns A SELSchema object representing the schema for the SEL environment.
|
|
36
|
+
*/
|
|
37
|
+
declare const buildSchema: (config: SchemaBuilderConfig) => SELSchema;
|
|
38
|
+
//#endregion
|
|
39
|
+
export { BuildStructFieldsResult, ContractInput, SchemaBuilderConfig, StructTypeDefinition, buildSchema, buildStructFields };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ContextDefinition } from "@seljs/types";
|
|
2
|
+
import { SELSchema } from "@seljs/schema";
|
|
3
|
+
import { AbiParameter } from "abitype";
|
|
4
|
+
import { Abi, Address } from "viem";
|
|
5
|
+
|
|
6
|
+
//#region src/builder.d.ts
|
|
7
|
+
interface StructTypeDefinition {
|
|
8
|
+
typeName: string;
|
|
9
|
+
fields: Record<string, string>;
|
|
10
|
+
}
|
|
11
|
+
interface BuildStructFieldsResult {
|
|
12
|
+
fields: Record<string, string>;
|
|
13
|
+
nestedTypes: StructTypeDefinition[];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Recursively builds struct field definitions.
|
|
17
|
+
*
|
|
18
|
+
* @param components Array of ABI parameters representing the components of a tuple type.
|
|
19
|
+
* @param parentTypeName Name to use for the struct type representing the current level of nesting.
|
|
20
|
+
*/
|
|
21
|
+
declare const buildStructFields: (components: readonly AbiParameter[], parentTypeName: string) => BuildStructFieldsResult;
|
|
22
|
+
interface ContractInput {
|
|
23
|
+
address: Address;
|
|
24
|
+
abi: Abi;
|
|
25
|
+
description?: string;
|
|
26
|
+
}
|
|
27
|
+
interface SchemaBuilderConfig {
|
|
28
|
+
contracts?: Record<string, ContractInput>;
|
|
29
|
+
context?: ContextDefinition;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Builds a SELSchema based on the provided configuration, which includes contract definitions and an optional context for variables.
|
|
33
|
+
*
|
|
34
|
+
* @param config Configuration object containing contract definitions and an optional context for variables.
|
|
35
|
+
* @returns A SELSchema object representing the schema for the SEL environment.
|
|
36
|
+
*/
|
|
37
|
+
declare const buildSchema: (config: SchemaBuilderConfig) => SELSchema;
|
|
38
|
+
//#endregion
|
|
39
|
+
export { BuildStructFieldsResult, ContractInput, SchemaBuilderConfig, StructTypeDefinition, buildSchema, buildStructFields };
|
package/dist/builder.mjs
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { CEL_BUILTIN_FUNCTIONS, CEL_BUILTIN_MACROS, SOLIDITY_PRIMITIVE_TYPES } from "./builtins.mjs";
|
|
2
|
+
import { structTypeName } from "@seljs/common";
|
|
3
|
+
import { mapSolidityTypeToCEL } from "@seljs/types";
|
|
4
|
+
//#region src/builder.ts
|
|
5
|
+
/**
|
|
6
|
+
* Checks if the given ABI parameter is a tuple type with components, indicating that it represents a struct in Solidity.
|
|
7
|
+
* @param param
|
|
8
|
+
*/
|
|
9
|
+
const isTupleParam = (param) => param.type === "tuple" && "components" in param;
|
|
10
|
+
/**
|
|
11
|
+
* Checks if the given ABI parameter is an array of tuples with components, indicating that it represents an array of structs in Solidity.
|
|
12
|
+
* @param param
|
|
13
|
+
*/
|
|
14
|
+
const isTupleArrayParam = (param) => param.type === "tuple[]" && "components" in param;
|
|
15
|
+
/**
|
|
16
|
+
* Checks if the given ABI parameter is either a tuple or an array of tuples, both of which indicate the presence of components and thus represent struct types in Solidity.
|
|
17
|
+
*
|
|
18
|
+
* @param param
|
|
19
|
+
*/
|
|
20
|
+
const isAnyTupleParam = (param) => isTupleParam(param) || isTupleArrayParam(param);
|
|
21
|
+
/**
|
|
22
|
+
* Generates a unique type name for a nested struct based on the parent type name and the field name, used for naming struct types in the SEL schema.
|
|
23
|
+
*
|
|
24
|
+
* @param parentTypeName Name of the parent type (e.g., contract name or parent struct name) to which the field belongs, used as a prefix for the nested struct type name.
|
|
25
|
+
* @param fieldName Name of the field for which to generate the nested struct type name, used as a suffix in the nested struct type name.
|
|
26
|
+
*/
|
|
27
|
+
const nestedTypeName = (parentTypeName, fieldName) => `${parentTypeName}__${fieldName}`;
|
|
28
|
+
/**
|
|
29
|
+
* Recursively builds struct field definitions.
|
|
30
|
+
*
|
|
31
|
+
* @param components Array of ABI parameters representing the components of a tuple type.
|
|
32
|
+
* @param parentTypeName Name to use for the struct type representing the current level of nesting.
|
|
33
|
+
*/
|
|
34
|
+
const buildStructFields = (components, parentTypeName) => {
|
|
35
|
+
const fields = {};
|
|
36
|
+
const nestedTypes = [];
|
|
37
|
+
for (const component of components) {
|
|
38
|
+
const fieldName = component.name ?? "arg0";
|
|
39
|
+
if (isTupleParam(component) && component.components.length > 0) {
|
|
40
|
+
const childTypeName = nestedTypeName(parentTypeName, fieldName);
|
|
41
|
+
const child = buildStructFields(component.components, childTypeName);
|
|
42
|
+
nestedTypes.push(...child.nestedTypes);
|
|
43
|
+
nestedTypes.push({
|
|
44
|
+
typeName: childTypeName,
|
|
45
|
+
fields: child.fields
|
|
46
|
+
});
|
|
47
|
+
fields[fieldName] = childTypeName;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (isTupleArrayParam(component) && component.components.length > 0) {
|
|
51
|
+
const childTypeName = nestedTypeName(parentTypeName, fieldName);
|
|
52
|
+
const child = buildStructFields(component.components, childTypeName);
|
|
53
|
+
nestedTypes.push(...child.nestedTypes);
|
|
54
|
+
nestedTypes.push({
|
|
55
|
+
typeName: childTypeName,
|
|
56
|
+
fields: child.fields
|
|
57
|
+
});
|
|
58
|
+
fields[fieldName] = `list<${childTypeName}>`;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
fields[fieldName] = mapSolidityTypeToCEL(component.type) ?? "dyn";
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
fields,
|
|
65
|
+
nestedTypes
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Builds method parameters for a given array of ABI parameters.
|
|
70
|
+
*
|
|
71
|
+
* @param inputs Array of ABI parameters representing the inputs of a function.
|
|
72
|
+
*/
|
|
73
|
+
const buildMethodParams = (inputs) => {
|
|
74
|
+
return inputs.map((param, index) => ({
|
|
75
|
+
name: param.name || `arg${String(index)}`,
|
|
76
|
+
type: mapSolidityTypeToCEL(param.type) ?? "dyn"
|
|
77
|
+
}));
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Builds the return type resolution for a method based on its ABI components, handling nested structs as needed.
|
|
81
|
+
*
|
|
82
|
+
* @param components Array of ABI parameters representing the components of a tuple return type.
|
|
83
|
+
* @param typeName Name to use for the struct type representing the return value, used for naming nested struct types as well.
|
|
84
|
+
*/
|
|
85
|
+
const buildStructReturn = (components, typeName) => {
|
|
86
|
+
const result = buildStructFields(components, typeName);
|
|
87
|
+
const structTypes = [];
|
|
88
|
+
for (const nested of result.nestedTypes) structTypes.push({
|
|
89
|
+
name: nested.typeName,
|
|
90
|
+
kind: "struct",
|
|
91
|
+
fields: Object.entries(nested.fields).map(([name, type]) => ({
|
|
92
|
+
name,
|
|
93
|
+
type
|
|
94
|
+
}))
|
|
95
|
+
});
|
|
96
|
+
structTypes.push({
|
|
97
|
+
name: typeName,
|
|
98
|
+
kind: "struct",
|
|
99
|
+
fields: Object.entries(result.fields).map(([name, type]) => ({
|
|
100
|
+
name,
|
|
101
|
+
type
|
|
102
|
+
}))
|
|
103
|
+
});
|
|
104
|
+
return {
|
|
105
|
+
returns: typeName,
|
|
106
|
+
structTypes
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Resolves the return type of method based on its ABI function definition.
|
|
111
|
+
*
|
|
112
|
+
* @param fn ABI function for which to resolve the return type.
|
|
113
|
+
* @param contractName Name of the contract to which the function belongs, used for naming nested struct types.
|
|
114
|
+
*/
|
|
115
|
+
const resolveMethodReturnType = (fn, contractName) => {
|
|
116
|
+
const firstOutput = fn.outputs[0];
|
|
117
|
+
if (!firstOutput) return {
|
|
118
|
+
returns: "dyn",
|
|
119
|
+
structTypes: []
|
|
120
|
+
};
|
|
121
|
+
if (fn.outputs.length === 1 && !isAnyTupleParam(firstOutput)) return {
|
|
122
|
+
returns: mapSolidityTypeToCEL(firstOutput.type) ?? "dyn",
|
|
123
|
+
structTypes: []
|
|
124
|
+
};
|
|
125
|
+
const typeName = structTypeName(contractName, fn.name);
|
|
126
|
+
const isSingleOutput = fn.outputs.length === 1;
|
|
127
|
+
const isSingleTupleArray = isSingleOutput && isTupleArrayParam(firstOutput);
|
|
128
|
+
const isSingleTuple = isSingleOutput && isTupleParam(firstOutput);
|
|
129
|
+
let components;
|
|
130
|
+
if (isSingleTuple || isSingleTupleArray) components = firstOutput.components;
|
|
131
|
+
else components = fn.outputs.map((o, i) => ({
|
|
132
|
+
...o,
|
|
133
|
+
name: o.name ?? `arg${String(i)}`
|
|
134
|
+
}));
|
|
135
|
+
const resolution = buildStructReturn(components, typeName);
|
|
136
|
+
if (isSingleTupleArray) return {
|
|
137
|
+
returns: `list<${typeName}>`,
|
|
138
|
+
structTypes: resolution.structTypes
|
|
139
|
+
};
|
|
140
|
+
else return resolution;
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Builds a MethodSchema for a given ABI function.
|
|
144
|
+
*
|
|
145
|
+
* @param fn ABI function for which to build the MethodSchema.
|
|
146
|
+
* @param contractName Name of the contract to which the function belongs, used for naming nested struct types.
|
|
147
|
+
* @param acc Accumulator to keep track of seen struct types and collect unique TypeSchemas for nested structs.
|
|
148
|
+
*/
|
|
149
|
+
const buildMethodSchema = (fn, contractName, acc) => {
|
|
150
|
+
const params = buildMethodParams(fn.inputs);
|
|
151
|
+
const resolution = resolveMethodReturnType(fn, contractName);
|
|
152
|
+
for (const st of resolution.structTypes) if (!acc.seen.has(st.name)) {
|
|
153
|
+
acc.types.push(st);
|
|
154
|
+
acc.seen.add(st.name);
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
name: fn.name,
|
|
158
|
+
params,
|
|
159
|
+
returns: resolution.returns,
|
|
160
|
+
abi: fn
|
|
161
|
+
};
|
|
162
|
+
};
|
|
163
|
+
/**
|
|
164
|
+
* Builds a ContractSchema for a given contract by processing its ABI and extracting view/pure functions as methods.
|
|
165
|
+
*
|
|
166
|
+
* @param contractName Name of the contract for which to build the schema.
|
|
167
|
+
* @param input ContractInput containing the ABI and other relevant information for the contract.
|
|
168
|
+
* @param acc Accumulator to keep track of seen struct types and collect unique TypeSchemas for nested structs.
|
|
169
|
+
*/
|
|
170
|
+
const buildContractSchema = (contractName, input, acc) => {
|
|
171
|
+
const methods = input.abi.filter((item) => item.type === "function" && (item.stateMutability === "view" || item.stateMutability === "pure")).map((fn) => buildMethodSchema(fn, contractName, acc));
|
|
172
|
+
return {
|
|
173
|
+
name: contractName,
|
|
174
|
+
address: input.address,
|
|
175
|
+
description: input.description,
|
|
176
|
+
methods
|
|
177
|
+
};
|
|
178
|
+
};
|
|
179
|
+
/**
|
|
180
|
+
* Resolves a ContextFieldDefinition to its CEL type string.
|
|
181
|
+
*/
|
|
182
|
+
const resolveFieldType = (field) => typeof field === "string" ? field : field.type;
|
|
183
|
+
/**
|
|
184
|
+
* Resolves the optional description from a ContextFieldDefinition.
|
|
185
|
+
*/
|
|
186
|
+
const resolveFieldDescription = (field) => typeof field === "string" ? void 0 : field.description;
|
|
187
|
+
/**
|
|
188
|
+
* Extracts variables from the provided context definition and builds an array of VariableSchema objects.
|
|
189
|
+
*/
|
|
190
|
+
const buildVariablesFromContext = (config) => {
|
|
191
|
+
if (!config.context) return [];
|
|
192
|
+
return Object.entries(config.context).map(([name, field]) => ({
|
|
193
|
+
name,
|
|
194
|
+
type: resolveFieldType(field),
|
|
195
|
+
description: resolveFieldDescription(field)
|
|
196
|
+
}));
|
|
197
|
+
};
|
|
198
|
+
/**
|
|
199
|
+
* Builds a SELSchema based on the provided configuration, which includes contract definitions and an optional context for variables.
|
|
200
|
+
*
|
|
201
|
+
* @param config Configuration object containing contract definitions and an optional context for variables.
|
|
202
|
+
* @returns A SELSchema object representing the schema for the SEL environment.
|
|
203
|
+
*/
|
|
204
|
+
const buildSchema = (config) => {
|
|
205
|
+
const acc = {
|
|
206
|
+
seen: /* @__PURE__ */ new Set(),
|
|
207
|
+
types: []
|
|
208
|
+
};
|
|
209
|
+
return {
|
|
210
|
+
version: "1.0.0",
|
|
211
|
+
contracts: Object.entries(config.contracts ?? {}).map(([name, input]) => buildContractSchema(name, input, acc)),
|
|
212
|
+
variables: buildVariablesFromContext(config),
|
|
213
|
+
types: [...SOLIDITY_PRIMITIVE_TYPES, ...acc.types],
|
|
214
|
+
functions: CEL_BUILTIN_FUNCTIONS,
|
|
215
|
+
macros: CEL_BUILTIN_MACROS
|
|
216
|
+
};
|
|
217
|
+
};
|
|
218
|
+
//#endregion
|
|
219
|
+
export { buildSchema, buildStructFields };
|