@seljs/checker 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/_virtual/_rolldown/runtime.cjs +23 -0
- package/dist/checker/checker.cjs +482 -0
- package/dist/checker/checker.d.cts +176 -0
- package/dist/checker/checker.d.mts +176 -0
- package/dist/checker/checker.mjs +481 -0
- package/dist/checker/diagnostics.cjs +66 -0
- package/dist/checker/diagnostics.mjs +66 -0
- package/dist/checker/index.cjs +2 -0
- package/dist/checker/index.d.mts +2 -0
- package/dist/checker/index.mjs +3 -0
- package/dist/checker/type-compatibility.cjs +70 -0
- package/dist/checker/type-compatibility.d.cts +8 -0
- package/dist/checker/type-compatibility.d.mts +8 -0
- package/dist/checker/type-compatibility.mjs +69 -0
- package/dist/constants.cjs +14 -0
- package/dist/constants.d.cts +7 -0
- package/dist/constants.d.mts +7 -0
- package/dist/constants.mjs +13 -0
- package/dist/debug.cjs +7 -0
- package/dist/debug.mjs +5 -0
- package/dist/environment/codec-registry.cjs +109 -0
- package/dist/environment/codec-registry.d.cts +45 -0
- package/dist/environment/codec-registry.d.mts +45 -0
- package/dist/environment/codec-registry.mjs +108 -0
- package/dist/environment/hydrate.cjs +163 -0
- package/dist/environment/hydrate.d.cts +52 -0
- package/dist/environment/hydrate.d.mts +52 -0
- package/dist/environment/hydrate.mjs +160 -0
- package/dist/environment/index.cjs +4 -0
- package/dist/environment/index.d.mts +4 -0
- package/dist/environment/index.mjs +5 -0
- package/dist/environment/register-types.cjs +107 -0
- package/dist/environment/register-types.d.cts +15 -0
- package/dist/environment/register-types.d.mts +15 -0
- package/dist/environment/register-types.mjs +106 -0
- package/dist/environment/value-wrappers.cjs +44 -0
- package/dist/environment/value-wrappers.d.cts +20 -0
- package/dist/environment/value-wrappers.d.mts +20 -0
- package/dist/environment/value-wrappers.mjs +41 -0
- package/dist/index.cjs +27 -0
- package/dist/index.d.cts +11 -0
- package/dist/index.d.mts +11 -0
- package/dist/index.mjs +13 -0
- package/dist/rules/defaults/deferred-call.cjs +107 -0
- package/dist/rules/defaults/deferred-call.mjs +106 -0
- package/dist/rules/defaults/index.cjs +6 -0
- package/dist/rules/defaults/index.mjs +7 -0
- package/dist/rules/defaults/no-constant-condition.cjs +31 -0
- package/dist/rules/defaults/no-constant-condition.mjs +31 -0
- package/dist/rules/defaults/no-mixed-operators.cjs +39 -0
- package/dist/rules/defaults/no-mixed-operators.mjs +39 -0
- package/dist/rules/defaults/no-redundant-bool.cjs +26 -0
- package/dist/rules/defaults/no-redundant-bool.mjs +26 -0
- package/dist/rules/defaults/no-self-comparison.cjs +44 -0
- package/dist/rules/defaults/no-self-comparison.mjs +43 -0
- package/dist/rules/defaults/require-type.cjs +18 -0
- package/dist/rules/defaults/require-type.mjs +18 -0
- package/dist/rules/facade.cjs +31 -0
- package/dist/rules/facade.d.cts +20 -0
- package/dist/rules/facade.d.mts +20 -0
- package/dist/rules/facade.mjs +31 -0
- package/dist/rules/index.cjs +2 -0
- package/dist/rules/index.d.mts +3 -0
- package/dist/rules/index.mjs +3 -0
- package/dist/rules/runner.cjs +40 -0
- package/dist/rules/runner.d.cts +27 -0
- package/dist/rules/runner.d.mts +27 -0
- package/dist/rules/runner.mjs +40 -0
- package/dist/rules/types.d.cts +77 -0
- package/dist/rules/types.d.mts +77 -0
- package/dist/utils/ast-utils.cjs +164 -0
- package/dist/utils/ast-utils.mjs +162 -0
- package/package.json +24 -17
- package/dist/checker/checker.d.ts +0 -173
- package/dist/checker/checker.js +0 -567
- package/dist/checker/diagnostics.d.ts +0 -10
- package/dist/checker/diagnostics.js +0 -80
- package/dist/checker/index.d.ts +0 -2
- package/dist/checker/index.js +0 -2
- package/dist/checker/type-compatibility.d.ts +0 -16
- package/dist/checker/type-compatibility.js +0 -59
- package/dist/constants.d.ts +0 -4
- package/dist/constants.js +0 -10
- package/dist/debug.d.ts +0 -2
- package/dist/debug.js +0 -2
- package/dist/environment/codec-registry.d.ts +0 -42
- package/dist/environment/codec-registry.js +0 -146
- package/dist/environment/hydrate.d.ts +0 -48
- package/dist/environment/hydrate.js +0 -198
- package/dist/environment/index.d.ts +0 -4
- package/dist/environment/index.js +0 -4
- package/dist/environment/register-types.d.ts +0 -14
- package/dist/environment/register-types.js +0 -154
- package/dist/environment/value-wrappers.d.ts +0 -17
- package/dist/environment/value-wrappers.js +0 -65
- package/dist/index.d.ts +0 -4
- package/dist/index.js +0 -4
- package/dist/rules/defaults/deferred-call.d.ts +0 -13
- package/dist/rules/defaults/deferred-call.js +0 -162
- package/dist/rules/defaults/index.d.ts +0 -6
- package/dist/rules/defaults/index.js +0 -6
- package/dist/rules/defaults/no-constant-condition.d.ts +0 -7
- package/dist/rules/defaults/no-constant-condition.js +0 -36
- package/dist/rules/defaults/no-mixed-operators.d.ts +0 -9
- package/dist/rules/defaults/no-mixed-operators.js +0 -44
- package/dist/rules/defaults/no-redundant-bool.d.ts +0 -5
- package/dist/rules/defaults/no-redundant-bool.js +0 -27
- package/dist/rules/defaults/no-self-comparison.d.ts +0 -9
- package/dist/rules/defaults/no-self-comparison.js +0 -31
- package/dist/rules/defaults/require-type.d.ts +0 -7
- package/dist/rules/defaults/require-type.js +0 -19
- package/dist/rules/facade.d.ts +0 -22
- package/dist/rules/facade.js +0 -29
- package/dist/rules/index.d.ts +0 -3
- package/dist/rules/index.js +0 -3
- package/dist/rules/runner.d.ts +0 -16
- package/dist/rules/runner.js +0 -30
- package/dist/rules/types.d.ts +0 -73
- package/dist/rules/types.js +0 -1
- package/dist/utils/ast-utils.d.ts +0 -55
- package/dist/utils/ast-utils.js +0 -255
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/index.js +0 -1
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
require("../_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
const require_debug = require("../debug.cjs");
|
|
3
|
+
const require_codec_registry = require("./codec-registry.cjs");
|
|
4
|
+
const require_register_types = require("./register-types.cjs");
|
|
5
|
+
const require_value_wrappers = require("./value-wrappers.cjs");
|
|
6
|
+
let _seljs_common = require("@seljs/common");
|
|
7
|
+
let _marcbachmann_cel_js = require("@marcbachmann/cel-js");
|
|
8
|
+
//#region src/environment/hydrate.ts
|
|
9
|
+
const debug = require_debug.createLogger("hydrate");
|
|
10
|
+
const hydrateEnvironment = (env, schema, handler) => {
|
|
11
|
+
const contractBindings = {};
|
|
12
|
+
const structRegistry = /* @__PURE__ */ new Map();
|
|
13
|
+
for (const type of schema.types) if (type.kind === "struct" && type.fields) {
|
|
14
|
+
const fields = {};
|
|
15
|
+
for (const field of type.fields) fields[field.name] = field.type;
|
|
16
|
+
try {
|
|
17
|
+
if (handler !== void 0) {
|
|
18
|
+
const StructCtor = class {};
|
|
19
|
+
env.registerType(type.name, {
|
|
20
|
+
ctor: StructCtor,
|
|
21
|
+
fields
|
|
22
|
+
});
|
|
23
|
+
structRegistry.set(type.name, {
|
|
24
|
+
ctor: StructCtor,
|
|
25
|
+
fieldNames: Object.keys(fields),
|
|
26
|
+
fieldTypes: fields
|
|
27
|
+
});
|
|
28
|
+
} else env.registerType(type.name, { fields });
|
|
29
|
+
} catch (err) {
|
|
30
|
+
debug("skipped type %s: %O", type.name, err);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const codecRegistry = handler !== void 0 ? new require_codec_registry.CelCodecRegistry({ structs: Array.from(structRegistry.entries()).map(([name, info]) => ({
|
|
34
|
+
name,
|
|
35
|
+
...info
|
|
36
|
+
})) }) : void 0;
|
|
37
|
+
for (const contract of schema.contracts) {
|
|
38
|
+
const typeName = (0, _seljs_common.contractTypeName)(contract.name);
|
|
39
|
+
class ContractType {
|
|
40
|
+
constructor(name) {
|
|
41
|
+
this.name = name;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
env.registerType(typeName, {
|
|
45
|
+
ctor: ContractType,
|
|
46
|
+
fields: {}
|
|
47
|
+
}).registerVariable(contract.name, typeName);
|
|
48
|
+
contractBindings[contract.name] = new ContractType(contract.name);
|
|
49
|
+
for (const method of contract.methods) {
|
|
50
|
+
const returnType = method.returns || "dyn";
|
|
51
|
+
const methodHandler = handler !== void 0 ? async (...args) => {
|
|
52
|
+
const raw = await handler(contract.name, method.name, args.slice(1));
|
|
53
|
+
if (!codecRegistry) throw new Error("codecRegistry is required when handler is provided");
|
|
54
|
+
return codecRegistry.resolve(returnType).parse(raw);
|
|
55
|
+
} : () => void 0;
|
|
56
|
+
try {
|
|
57
|
+
env.registerFunction({
|
|
58
|
+
name: method.name,
|
|
59
|
+
receiverType: typeName,
|
|
60
|
+
returnType,
|
|
61
|
+
handler: methodHandler,
|
|
62
|
+
params: method.params.map((param) => ({
|
|
63
|
+
name: param.name,
|
|
64
|
+
type: param.type
|
|
65
|
+
}))
|
|
66
|
+
}, void 0);
|
|
67
|
+
} catch (err) {
|
|
68
|
+
debug("skipped method %s.%s: %O", contract.name, method.name, err);
|
|
69
|
+
}
|
|
70
|
+
if (method.params.some((p) => require_value_wrappers.toCelLiteralType(p.type) !== null)) try {
|
|
71
|
+
env.registerFunction({
|
|
72
|
+
name: method.name,
|
|
73
|
+
receiverType: typeName,
|
|
74
|
+
returnType,
|
|
75
|
+
handler: methodHandler,
|
|
76
|
+
params: method.params.map((param) => ({
|
|
77
|
+
name: param.name,
|
|
78
|
+
type: require_value_wrappers.toCelLiteralType(param.type) ?? param.type
|
|
79
|
+
}))
|
|
80
|
+
}, void 0);
|
|
81
|
+
} catch (err) {
|
|
82
|
+
debug("skipped literal overload %s.%s: %O", contract.name, method.name, err);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
for (const variable of schema.variables) try {
|
|
87
|
+
env.registerVariable(variable.name, variable.type);
|
|
88
|
+
} catch (err) {
|
|
89
|
+
debug("variable %s: fallback to dyn: %O", variable.name, err);
|
|
90
|
+
env.registerVariable(variable.name, "dyn");
|
|
91
|
+
}
|
|
92
|
+
for (const fn of schema.functions) {
|
|
93
|
+
if (!fn.receiverType) continue;
|
|
94
|
+
try {
|
|
95
|
+
env.registerFunction({
|
|
96
|
+
name: fn.name,
|
|
97
|
+
receiverType: fn.receiverType,
|
|
98
|
+
returnType: fn.returns,
|
|
99
|
+
handler: () => void 0,
|
|
100
|
+
params: fn.params.map((param) => ({
|
|
101
|
+
name: param.name,
|
|
102
|
+
type: param.type
|
|
103
|
+
}))
|
|
104
|
+
}, void 0);
|
|
105
|
+
} catch (err) {
|
|
106
|
+
if (!(err instanceof Error) || !err.message.includes("overlaps with existing overload")) throw err;
|
|
107
|
+
debug("skipped overlapping overload: %O", err);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
contractBindings,
|
|
112
|
+
codecRegistry
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* Create a base CEL environment with Solidity types registered.
|
|
117
|
+
* No contracts, no variables — just the type system.
|
|
118
|
+
*
|
|
119
|
+
* Use this when you need to register contracts and variables yourself
|
|
120
|
+
* (e.g., runtime evaluation with real async handlers).
|
|
121
|
+
*/
|
|
122
|
+
const createBaseEnvironment = (options) => {
|
|
123
|
+
const env = new _marcbachmann_cel_js.Environment({
|
|
124
|
+
unlistedVariablesAreDyn: false,
|
|
125
|
+
...options?.limits ? { limits: options.limits } : {}
|
|
126
|
+
});
|
|
127
|
+
require_register_types.registerSolidityTypes(env);
|
|
128
|
+
return env;
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* Create a fully hydrated checker environment from a SELSchema.
|
|
132
|
+
*
|
|
133
|
+
* Registers Solidity primitive types, contract types with their methods
|
|
134
|
+
* (using no-op handlers since the checker only needs type information),
|
|
135
|
+
* schema variables, and built-in functions.
|
|
136
|
+
*/
|
|
137
|
+
const createCheckerEnvironment = (schema) => {
|
|
138
|
+
const env = createBaseEnvironment();
|
|
139
|
+
hydrateEnvironment(env, schema);
|
|
140
|
+
return env;
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Create a fully hydrated runtime environment from a SELSchema with a
|
|
144
|
+
* real async handler for contract method calls.
|
|
145
|
+
*/
|
|
146
|
+
const createRuntimeEnvironment = (schema, handler, options) => {
|
|
147
|
+
const env = new _marcbachmann_cel_js.Environment({
|
|
148
|
+
unlistedVariablesAreDyn: options?.unlistedVariablesAreDyn ?? false,
|
|
149
|
+
...options?.limits ? { limits: options.limits } : {}
|
|
150
|
+
});
|
|
151
|
+
require_register_types.registerSolidityTypes(env);
|
|
152
|
+
const result = hydrateEnvironment(env, schema, handler);
|
|
153
|
+
if (!result.codecRegistry) throw new Error("codecRegistry is required when handler is provided");
|
|
154
|
+
return {
|
|
155
|
+
env,
|
|
156
|
+
contractBindings: result.contractBindings,
|
|
157
|
+
codecRegistry: result.codecRegistry
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
//#endregion
|
|
161
|
+
exports.createBaseEnvironment = createBaseEnvironment;
|
|
162
|
+
exports.createCheckerEnvironment = createCheckerEnvironment;
|
|
163
|
+
exports.createRuntimeEnvironment = createRuntimeEnvironment;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { CelCodecRegistry } from "./codec-registry.cjs";
|
|
2
|
+
import { Environment } from "@marcbachmann/cel-js";
|
|
3
|
+
import { SELSchema } from "@seljs/schema";
|
|
4
|
+
|
|
5
|
+
//#region src/environment/hydrate.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* CEL environment limits configuration.
|
|
8
|
+
*/
|
|
9
|
+
interface CelLimits {
|
|
10
|
+
maxAstNodes?: number;
|
|
11
|
+
maxDepth?: number;
|
|
12
|
+
maxListElements?: number;
|
|
13
|
+
maxMapEntries?: number;
|
|
14
|
+
maxCallArguments?: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Handler called when a contract method is invoked at runtime.
|
|
18
|
+
*/
|
|
19
|
+
type ContractCallHandler = (contractName: string, methodName: string, args: unknown[]) => unknown;
|
|
20
|
+
/**
|
|
21
|
+
* Create a base CEL environment with Solidity types registered.
|
|
22
|
+
* No contracts, no variables — just the type system.
|
|
23
|
+
*
|
|
24
|
+
* Use this when you need to register contracts and variables yourself
|
|
25
|
+
* (e.g., runtime evaluation with real async handlers).
|
|
26
|
+
*/
|
|
27
|
+
declare const createBaseEnvironment: (options?: {
|
|
28
|
+
limits?: CelLimits;
|
|
29
|
+
}) => Environment;
|
|
30
|
+
/**
|
|
31
|
+
* Create a fully hydrated checker environment from a SELSchema.
|
|
32
|
+
*
|
|
33
|
+
* Registers Solidity primitive types, contract types with their methods
|
|
34
|
+
* (using no-op handlers since the checker only needs type information),
|
|
35
|
+
* schema variables, and built-in functions.
|
|
36
|
+
*/
|
|
37
|
+
declare const createCheckerEnvironment: (schema: SELSchema) => Environment;
|
|
38
|
+
interface RuntimeEnvironmentResult {
|
|
39
|
+
env: Environment;
|
|
40
|
+
contractBindings: Record<string, unknown>;
|
|
41
|
+
codecRegistry: CelCodecRegistry;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Create a fully hydrated runtime environment from a SELSchema with a
|
|
45
|
+
* real async handler for contract method calls.
|
|
46
|
+
*/
|
|
47
|
+
declare const createRuntimeEnvironment: (schema: SELSchema, handler: ContractCallHandler, options?: {
|
|
48
|
+
limits?: CelLimits;
|
|
49
|
+
unlistedVariablesAreDyn?: boolean;
|
|
50
|
+
}) => RuntimeEnvironmentResult;
|
|
51
|
+
//#endregion
|
|
52
|
+
export { CelLimits, ContractCallHandler, RuntimeEnvironmentResult, createBaseEnvironment, createCheckerEnvironment, createRuntimeEnvironment };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { CelCodecRegistry } from "./codec-registry.mjs";
|
|
2
|
+
import { Environment } from "@marcbachmann/cel-js";
|
|
3
|
+
import { SELSchema } from "@seljs/schema";
|
|
4
|
+
|
|
5
|
+
//#region src/environment/hydrate.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* CEL environment limits configuration.
|
|
8
|
+
*/
|
|
9
|
+
interface CelLimits {
|
|
10
|
+
maxAstNodes?: number;
|
|
11
|
+
maxDepth?: number;
|
|
12
|
+
maxListElements?: number;
|
|
13
|
+
maxMapEntries?: number;
|
|
14
|
+
maxCallArguments?: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Handler called when a contract method is invoked at runtime.
|
|
18
|
+
*/
|
|
19
|
+
type ContractCallHandler = (contractName: string, methodName: string, args: unknown[]) => unknown;
|
|
20
|
+
/**
|
|
21
|
+
* Create a base CEL environment with Solidity types registered.
|
|
22
|
+
* No contracts, no variables — just the type system.
|
|
23
|
+
*
|
|
24
|
+
* Use this when you need to register contracts and variables yourself
|
|
25
|
+
* (e.g., runtime evaluation with real async handlers).
|
|
26
|
+
*/
|
|
27
|
+
declare const createBaseEnvironment: (options?: {
|
|
28
|
+
limits?: CelLimits;
|
|
29
|
+
}) => Environment;
|
|
30
|
+
/**
|
|
31
|
+
* Create a fully hydrated checker environment from a SELSchema.
|
|
32
|
+
*
|
|
33
|
+
* Registers Solidity primitive types, contract types with their methods
|
|
34
|
+
* (using no-op handlers since the checker only needs type information),
|
|
35
|
+
* schema variables, and built-in functions.
|
|
36
|
+
*/
|
|
37
|
+
declare const createCheckerEnvironment: (schema: SELSchema) => Environment;
|
|
38
|
+
interface RuntimeEnvironmentResult {
|
|
39
|
+
env: Environment;
|
|
40
|
+
contractBindings: Record<string, unknown>;
|
|
41
|
+
codecRegistry: CelCodecRegistry;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Create a fully hydrated runtime environment from a SELSchema with a
|
|
45
|
+
* real async handler for contract method calls.
|
|
46
|
+
*/
|
|
47
|
+
declare const createRuntimeEnvironment: (schema: SELSchema, handler: ContractCallHandler, options?: {
|
|
48
|
+
limits?: CelLimits;
|
|
49
|
+
unlistedVariablesAreDyn?: boolean;
|
|
50
|
+
}) => RuntimeEnvironmentResult;
|
|
51
|
+
//#endregion
|
|
52
|
+
export { CelLimits, ContractCallHandler, RuntimeEnvironmentResult, createBaseEnvironment, createCheckerEnvironment, createRuntimeEnvironment };
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { createLogger } from "../debug.mjs";
|
|
2
|
+
import { CelCodecRegistry } from "./codec-registry.mjs";
|
|
3
|
+
import { registerSolidityTypes } from "./register-types.mjs";
|
|
4
|
+
import { toCelLiteralType } from "./value-wrappers.mjs";
|
|
5
|
+
import { contractTypeName } from "@seljs/common";
|
|
6
|
+
import { Environment } from "@marcbachmann/cel-js";
|
|
7
|
+
//#region src/environment/hydrate.ts
|
|
8
|
+
const debug = createLogger("hydrate");
|
|
9
|
+
const hydrateEnvironment = (env, schema, handler) => {
|
|
10
|
+
const contractBindings = {};
|
|
11
|
+
const structRegistry = /* @__PURE__ */ new Map();
|
|
12
|
+
for (const type of schema.types) if (type.kind === "struct" && type.fields) {
|
|
13
|
+
const fields = {};
|
|
14
|
+
for (const field of type.fields) fields[field.name] = field.type;
|
|
15
|
+
try {
|
|
16
|
+
if (handler !== void 0) {
|
|
17
|
+
const StructCtor = class {};
|
|
18
|
+
env.registerType(type.name, {
|
|
19
|
+
ctor: StructCtor,
|
|
20
|
+
fields
|
|
21
|
+
});
|
|
22
|
+
structRegistry.set(type.name, {
|
|
23
|
+
ctor: StructCtor,
|
|
24
|
+
fieldNames: Object.keys(fields),
|
|
25
|
+
fieldTypes: fields
|
|
26
|
+
});
|
|
27
|
+
} else env.registerType(type.name, { fields });
|
|
28
|
+
} catch (err) {
|
|
29
|
+
debug("skipped type %s: %O", type.name, err);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const codecRegistry = handler !== void 0 ? new CelCodecRegistry({ structs: Array.from(structRegistry.entries()).map(([name, info]) => ({
|
|
33
|
+
name,
|
|
34
|
+
...info
|
|
35
|
+
})) }) : void 0;
|
|
36
|
+
for (const contract of schema.contracts) {
|
|
37
|
+
const typeName = contractTypeName(contract.name);
|
|
38
|
+
class ContractType {
|
|
39
|
+
constructor(name) {
|
|
40
|
+
this.name = name;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
env.registerType(typeName, {
|
|
44
|
+
ctor: ContractType,
|
|
45
|
+
fields: {}
|
|
46
|
+
}).registerVariable(contract.name, typeName);
|
|
47
|
+
contractBindings[contract.name] = new ContractType(contract.name);
|
|
48
|
+
for (const method of contract.methods) {
|
|
49
|
+
const returnType = method.returns || "dyn";
|
|
50
|
+
const methodHandler = handler !== void 0 ? async (...args) => {
|
|
51
|
+
const raw = await handler(contract.name, method.name, args.slice(1));
|
|
52
|
+
if (!codecRegistry) throw new Error("codecRegistry is required when handler is provided");
|
|
53
|
+
return codecRegistry.resolve(returnType).parse(raw);
|
|
54
|
+
} : () => void 0;
|
|
55
|
+
try {
|
|
56
|
+
env.registerFunction({
|
|
57
|
+
name: method.name,
|
|
58
|
+
receiverType: typeName,
|
|
59
|
+
returnType,
|
|
60
|
+
handler: methodHandler,
|
|
61
|
+
params: method.params.map((param) => ({
|
|
62
|
+
name: param.name,
|
|
63
|
+
type: param.type
|
|
64
|
+
}))
|
|
65
|
+
}, void 0);
|
|
66
|
+
} catch (err) {
|
|
67
|
+
debug("skipped method %s.%s: %O", contract.name, method.name, err);
|
|
68
|
+
}
|
|
69
|
+
if (method.params.some((p) => toCelLiteralType(p.type) !== null)) try {
|
|
70
|
+
env.registerFunction({
|
|
71
|
+
name: method.name,
|
|
72
|
+
receiverType: typeName,
|
|
73
|
+
returnType,
|
|
74
|
+
handler: methodHandler,
|
|
75
|
+
params: method.params.map((param) => ({
|
|
76
|
+
name: param.name,
|
|
77
|
+
type: toCelLiteralType(param.type) ?? param.type
|
|
78
|
+
}))
|
|
79
|
+
}, void 0);
|
|
80
|
+
} catch (err) {
|
|
81
|
+
debug("skipped literal overload %s.%s: %O", contract.name, method.name, err);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
for (const variable of schema.variables) try {
|
|
86
|
+
env.registerVariable(variable.name, variable.type);
|
|
87
|
+
} catch (err) {
|
|
88
|
+
debug("variable %s: fallback to dyn: %O", variable.name, err);
|
|
89
|
+
env.registerVariable(variable.name, "dyn");
|
|
90
|
+
}
|
|
91
|
+
for (const fn of schema.functions) {
|
|
92
|
+
if (!fn.receiverType) continue;
|
|
93
|
+
try {
|
|
94
|
+
env.registerFunction({
|
|
95
|
+
name: fn.name,
|
|
96
|
+
receiverType: fn.receiverType,
|
|
97
|
+
returnType: fn.returns,
|
|
98
|
+
handler: () => void 0,
|
|
99
|
+
params: fn.params.map((param) => ({
|
|
100
|
+
name: param.name,
|
|
101
|
+
type: param.type
|
|
102
|
+
}))
|
|
103
|
+
}, void 0);
|
|
104
|
+
} catch (err) {
|
|
105
|
+
if (!(err instanceof Error) || !err.message.includes("overlaps with existing overload")) throw err;
|
|
106
|
+
debug("skipped overlapping overload: %O", err);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
contractBindings,
|
|
111
|
+
codecRegistry
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Create a base CEL environment with Solidity types registered.
|
|
116
|
+
* No contracts, no variables — just the type system.
|
|
117
|
+
*
|
|
118
|
+
* Use this when you need to register contracts and variables yourself
|
|
119
|
+
* (e.g., runtime evaluation with real async handlers).
|
|
120
|
+
*/
|
|
121
|
+
const createBaseEnvironment = (options) => {
|
|
122
|
+
const env = new Environment({
|
|
123
|
+
unlistedVariablesAreDyn: false,
|
|
124
|
+
...options?.limits ? { limits: options.limits } : {}
|
|
125
|
+
});
|
|
126
|
+
registerSolidityTypes(env);
|
|
127
|
+
return env;
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Create a fully hydrated checker environment from a SELSchema.
|
|
131
|
+
*
|
|
132
|
+
* Registers Solidity primitive types, contract types with their methods
|
|
133
|
+
* (using no-op handlers since the checker only needs type information),
|
|
134
|
+
* schema variables, and built-in functions.
|
|
135
|
+
*/
|
|
136
|
+
const createCheckerEnvironment = (schema) => {
|
|
137
|
+
const env = createBaseEnvironment();
|
|
138
|
+
hydrateEnvironment(env, schema);
|
|
139
|
+
return env;
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* Create a fully hydrated runtime environment from a SELSchema with a
|
|
143
|
+
* real async handler for contract method calls.
|
|
144
|
+
*/
|
|
145
|
+
const createRuntimeEnvironment = (schema, handler, options) => {
|
|
146
|
+
const env = new Environment({
|
|
147
|
+
unlistedVariablesAreDyn: options?.unlistedVariablesAreDyn ?? false,
|
|
148
|
+
...options?.limits ? { limits: options.limits } : {}
|
|
149
|
+
});
|
|
150
|
+
registerSolidityTypes(env);
|
|
151
|
+
const result = hydrateEnvironment(env, schema, handler);
|
|
152
|
+
if (!result.codecRegistry) throw new Error("codecRegistry is required when handler is provided");
|
|
153
|
+
return {
|
|
154
|
+
env,
|
|
155
|
+
contractBindings: result.contractBindings,
|
|
156
|
+
codecRegistry: result.codecRegistry
|
|
157
|
+
};
|
|
158
|
+
};
|
|
159
|
+
//#endregion
|
|
160
|
+
export { createBaseEnvironment, createCheckerEnvironment, createRuntimeEnvironment };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { CelCodecRegistry, CelCodecRegistryOptions, StructCodecDescriptor } from "./codec-registry.mjs";
|
|
2
|
+
import { CelLimits, ContractCallHandler, RuntimeEnvironmentResult, createBaseEnvironment, createCheckerEnvironment, createRuntimeEnvironment } from "./hydrate.mjs";
|
|
3
|
+
import { registerSolidityTypes } from "./register-types.mjs";
|
|
4
|
+
import { StructInfo, toCelLiteralType, wrapStructValue, wrapValueForSel } from "./value-wrappers.mjs";
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
require("../_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
let _seljs_types = require("@seljs/types");
|
|
3
|
+
//#region src/environment/register-types.ts
|
|
4
|
+
/**
|
|
5
|
+
* Try to register an operator, silently ignoring "already registered" errors.
|
|
6
|
+
* cel-js auto-derives some cross-type operators (e.g., registering
|
|
7
|
+
* `sol_int == int` also creates `int == sol_int`).
|
|
8
|
+
*/
|
|
9
|
+
const tryRegisterOperator = (env, signature, handler) => {
|
|
10
|
+
try {
|
|
11
|
+
env.registerOperator(signature, handler);
|
|
12
|
+
} catch (error) {
|
|
13
|
+
if (!(error instanceof Error) || !error.message.includes("already registered")) throw error;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
const registerAddressOperators = (env) => {
|
|
17
|
+
env.registerOperator("sol_address == sol_address", (left, right) => (0, _seljs_types.toAddress)(left) === (0, _seljs_types.toAddress)(right));
|
|
18
|
+
env.registerOperator("sol_address < sol_address", (left, right) => (0, _seljs_types.toAddress)(left) < (0, _seljs_types.toAddress)(right));
|
|
19
|
+
env.registerOperator("sol_address <= sol_address", (left, right) => (0, _seljs_types.toAddress)(left) <= (0, _seljs_types.toAddress)(right));
|
|
20
|
+
env.registerOperator("sol_address > sol_address", (left, right) => (0, _seljs_types.toAddress)(left) > (0, _seljs_types.toAddress)(right));
|
|
21
|
+
env.registerOperator("sol_address >= sol_address", (left, right) => (0, _seljs_types.toAddress)(left) >= (0, _seljs_types.toAddress)(right));
|
|
22
|
+
};
|
|
23
|
+
const toSolInt = (value) => new _seljs_types.SolidityIntTypeWrapper(value);
|
|
24
|
+
const registerIntegerOperators = (env) => {
|
|
25
|
+
env.registerOperator("sol_int + sol_int", (a, b) => toSolInt((0, _seljs_types.toBigInt)(a) + (0, _seljs_types.toBigInt)(b)));
|
|
26
|
+
env.registerOperator("sol_int - sol_int", (a, b) => toSolInt((0, _seljs_types.toBigInt)(a) - (0, _seljs_types.toBigInt)(b)));
|
|
27
|
+
env.registerOperator("sol_int * sol_int", (a, b) => toSolInt((0, _seljs_types.toBigInt)(a) * (0, _seljs_types.toBigInt)(b)));
|
|
28
|
+
env.registerOperator("sol_int / sol_int", (a, b) => {
|
|
29
|
+
const divisor = (0, _seljs_types.toBigInt)(b);
|
|
30
|
+
if (divisor === 0n) throw new Error("division by zero");
|
|
31
|
+
return toSolInt((0, _seljs_types.toBigInt)(a) / divisor);
|
|
32
|
+
});
|
|
33
|
+
env.registerOperator("sol_int % sol_int", (a, b) => {
|
|
34
|
+
const divisor = (0, _seljs_types.toBigInt)(b);
|
|
35
|
+
if (divisor === 0n) throw new Error("modulo by zero");
|
|
36
|
+
return toSolInt((0, _seljs_types.toBigInt)(a) % divisor);
|
|
37
|
+
});
|
|
38
|
+
env.registerOperator("-sol_int", (a) => toSolInt(-(0, _seljs_types.toBigInt)(a)));
|
|
39
|
+
env.registerOperator("sol_int == sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) === (0, _seljs_types.toBigInt)(b));
|
|
40
|
+
env.registerOperator("sol_int < sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) < (0, _seljs_types.toBigInt)(b));
|
|
41
|
+
env.registerOperator("sol_int <= sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) <= (0, _seljs_types.toBigInt)(b));
|
|
42
|
+
env.registerOperator("sol_int > sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) > (0, _seljs_types.toBigInt)(b));
|
|
43
|
+
env.registerOperator("sol_int >= sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) >= (0, _seljs_types.toBigInt)(b));
|
|
44
|
+
tryRegisterOperator(env, "sol_int + int", (a, b) => toSolInt((0, _seljs_types.toBigInt)(a) + (0, _seljs_types.toBigInt)(b)));
|
|
45
|
+
tryRegisterOperator(env, "sol_int - int", (a, b) => toSolInt((0, _seljs_types.toBigInt)(a) - (0, _seljs_types.toBigInt)(b)));
|
|
46
|
+
tryRegisterOperator(env, "sol_int * int", (a, b) => toSolInt((0, _seljs_types.toBigInt)(a) * (0, _seljs_types.toBigInt)(b)));
|
|
47
|
+
tryRegisterOperator(env, "sol_int / int", (a, b) => {
|
|
48
|
+
const divisor = (0, _seljs_types.toBigInt)(b);
|
|
49
|
+
if (divisor === 0n) throw new Error("division by zero");
|
|
50
|
+
return toSolInt((0, _seljs_types.toBigInt)(a) / divisor);
|
|
51
|
+
});
|
|
52
|
+
tryRegisterOperator(env, "sol_int % int", (a, b) => {
|
|
53
|
+
const divisor = (0, _seljs_types.toBigInt)(b);
|
|
54
|
+
if (divisor === 0n) throw new Error("modulo by zero");
|
|
55
|
+
return toSolInt((0, _seljs_types.toBigInt)(a) % divisor);
|
|
56
|
+
});
|
|
57
|
+
tryRegisterOperator(env, "sol_int == int", (a, b) => (0, _seljs_types.toBigInt)(a) === (0, _seljs_types.toBigInt)(b));
|
|
58
|
+
tryRegisterOperator(env, "int == sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) === (0, _seljs_types.toBigInt)(b));
|
|
59
|
+
tryRegisterOperator(env, "sol_int < int", (a, b) => (0, _seljs_types.toBigInt)(a) < (0, _seljs_types.toBigInt)(b));
|
|
60
|
+
tryRegisterOperator(env, "int < sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) < (0, _seljs_types.toBigInt)(b));
|
|
61
|
+
tryRegisterOperator(env, "sol_int <= int", (a, b) => (0, _seljs_types.toBigInt)(a) <= (0, _seljs_types.toBigInt)(b));
|
|
62
|
+
tryRegisterOperator(env, "int <= sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) <= (0, _seljs_types.toBigInt)(b));
|
|
63
|
+
tryRegisterOperator(env, "sol_int > int", (a, b) => (0, _seljs_types.toBigInt)(a) > (0, _seljs_types.toBigInt)(b));
|
|
64
|
+
tryRegisterOperator(env, "int > sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) > (0, _seljs_types.toBigInt)(b));
|
|
65
|
+
tryRegisterOperator(env, "sol_int >= int", (a, b) => (0, _seljs_types.toBigInt)(a) >= (0, _seljs_types.toBigInt)(b));
|
|
66
|
+
tryRegisterOperator(env, "int >= sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) >= (0, _seljs_types.toBigInt)(b));
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Register all Solidity primitive types on a CEL Environment.
|
|
70
|
+
*/
|
|
71
|
+
const registerSolidityTypes = (env) => {
|
|
72
|
+
for (const entry of _seljs_types.SOLIDITY_TYPES) {
|
|
73
|
+
if (entry.type === "builtin") continue;
|
|
74
|
+
env.registerType(entry.name, entry.wrapperClass);
|
|
75
|
+
if (entry.name === "sol_address") registerAddressOperators(env);
|
|
76
|
+
if (entry.name === "sol_int") registerIntegerOperators(env);
|
|
77
|
+
const Ctor = entry.wrapperClass;
|
|
78
|
+
for (const sig of entry.castSignatures) env.registerFunction(sig, (value) => new Ctor(value));
|
|
79
|
+
}
|
|
80
|
+
env.registerFunction("parseUnits(string, int): sol_int", (value, decimals) => (0, _seljs_types.parseUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
|
|
81
|
+
env.registerFunction("parseUnits(int, int): sol_int", (value, decimals) => (0, _seljs_types.parseUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
|
|
82
|
+
env.registerFunction("parseUnits(double, int): sol_int", (value, decimals) => (0, _seljs_types.parseUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
|
|
83
|
+
env.registerFunction("parseUnits(sol_int, int): sol_int", (value, decimals) => (0, _seljs_types.parseUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
|
|
84
|
+
env.registerFunction("formatUnits(sol_int, int): double", (value, decimals) => (0, _seljs_types.formatUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
|
|
85
|
+
env.registerFunction("formatUnits(int, int): double", (value, decimals) => (0, _seljs_types.formatUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
|
|
86
|
+
env.registerFunction("min(sol_int, sol_int): sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) <= (0, _seljs_types.toBigInt)(b) ? toSolInt(a) : toSolInt(b));
|
|
87
|
+
env.registerFunction("min(sol_int, int): sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) <= (0, _seljs_types.toBigInt)(b) ? toSolInt(a) : toSolInt(b));
|
|
88
|
+
env.registerFunction("min(int, sol_int): sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) <= (0, _seljs_types.toBigInt)(b) ? toSolInt(a) : toSolInt(b));
|
|
89
|
+
env.registerFunction("min(int, int): sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) <= (0, _seljs_types.toBigInt)(b) ? toSolInt(a) : toSolInt(b));
|
|
90
|
+
env.registerFunction("max(sol_int, sol_int): sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) >= (0, _seljs_types.toBigInt)(b) ? toSolInt(a) : toSolInt(b));
|
|
91
|
+
env.registerFunction("max(sol_int, int): sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) >= (0, _seljs_types.toBigInt)(b) ? toSolInt(a) : toSolInt(b));
|
|
92
|
+
env.registerFunction("max(int, sol_int): sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) >= (0, _seljs_types.toBigInt)(b) ? toSolInt(a) : toSolInt(b));
|
|
93
|
+
env.registerFunction("max(int, int): sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) >= (0, _seljs_types.toBigInt)(b) ? toSolInt(a) : toSolInt(b));
|
|
94
|
+
env.registerFunction("abs(sol_int): sol_int", (a) => {
|
|
95
|
+
const v = (0, _seljs_types.toBigInt)(a);
|
|
96
|
+
return toSolInt(v < 0n ? -v : v);
|
|
97
|
+
});
|
|
98
|
+
env.registerFunction("abs(int): sol_int", (a) => {
|
|
99
|
+
const v = (0, _seljs_types.toBigInt)(a);
|
|
100
|
+
return toSolInt(v < 0n ? -v : v);
|
|
101
|
+
});
|
|
102
|
+
const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
103
|
+
env.registerFunction("isZeroAddress(sol_address): bool", (addr) => (0, _seljs_types.toAddress)(addr) === ZERO_ADDRESS);
|
|
104
|
+
env.registerFunction("isZeroAddress(string): bool", (addr) => (0, _seljs_types.toAddress)(addr) === ZERO_ADDRESS);
|
|
105
|
+
};
|
|
106
|
+
//#endregion
|
|
107
|
+
exports.registerSolidityTypes = registerSolidityTypes;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Environment } from "@marcbachmann/cel-js";
|
|
2
|
+
|
|
3
|
+
//#region src/environment/register-types.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Subset of the CEL Environment API needed for Solidity type registration.
|
|
6
|
+
* Mirrors the parameter signatures from Environment but drops the return type
|
|
7
|
+
* to void — registerSolidityTypes never chains the return value.
|
|
8
|
+
*/
|
|
9
|
+
type SolidityTypeHost = { [K in "registerType" | "registerOperator" | "registerFunction"]: (...args: Parameters<Environment[K]>) => void };
|
|
10
|
+
/**
|
|
11
|
+
* Register all Solidity primitive types on a CEL Environment.
|
|
12
|
+
*/
|
|
13
|
+
declare const registerSolidityTypes: (env: SolidityTypeHost) => void;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { registerSolidityTypes };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Environment } from "@marcbachmann/cel-js";
|
|
2
|
+
|
|
3
|
+
//#region src/environment/register-types.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Subset of the CEL Environment API needed for Solidity type registration.
|
|
6
|
+
* Mirrors the parameter signatures from Environment but drops the return type
|
|
7
|
+
* to void — registerSolidityTypes never chains the return value.
|
|
8
|
+
*/
|
|
9
|
+
type SolidityTypeHost = { [K in "registerType" | "registerOperator" | "registerFunction"]: (...args: Parameters<Environment[K]>) => void };
|
|
10
|
+
/**
|
|
11
|
+
* Register all Solidity primitive types on a CEL Environment.
|
|
12
|
+
*/
|
|
13
|
+
declare const registerSolidityTypes: (env: SolidityTypeHost) => void;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { registerSolidityTypes };
|