@seljs/runtime 1.3.0-beta.3 → 1.3.0-beta.32

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.
Files changed (34) hide show
  1. package/dist/analysis/dependency-analyzer.cjs +3 -3
  2. package/dist/analysis/dependency-analyzer.mjs +4 -4
  3. package/dist/analysis/round-planner.cjs +3 -3
  4. package/dist/analysis/round-planner.mjs +4 -4
  5. package/dist/environment/client.d.cts +1 -1
  6. package/dist/environment/client.d.mts +1 -1
  7. package/dist/environment/contract-caller.cjs +1 -1
  8. package/dist/environment/contract-caller.mjs +2 -2
  9. package/dist/environment/environment.cjs +25 -15
  10. package/dist/environment/environment.d.cts +15 -4
  11. package/dist/environment/environment.d.mts +15 -4
  12. package/dist/environment/environment.mjs +26 -15
  13. package/dist/environment/error-wrapper.cjs +71 -13
  14. package/dist/environment/error-wrapper.mjs +71 -12
  15. package/dist/environment/types.d.cts +1 -1
  16. package/dist/environment/types.d.mts +1 -1
  17. package/dist/errors/errors.cjs +102 -33
  18. package/dist/errors/errors.d.cts +98 -31
  19. package/dist/errors/errors.d.mts +98 -31
  20. package/dist/errors/errors.mjs +96 -31
  21. package/dist/errors/index.d.mts +1 -1
  22. package/dist/execution/decode-revert.cjs +67 -0
  23. package/dist/execution/decode-revert.mjs +66 -0
  24. package/dist/execution/multicall-batcher.cjs +3 -3
  25. package/dist/execution/multicall-batcher.mjs +4 -4
  26. package/dist/execution/round-executor.cjs +18 -10
  27. package/dist/execution/round-executor.mjs +19 -11
  28. package/dist/execution/types.d.cts +37 -11
  29. package/dist/execution/types.d.mts +37 -11
  30. package/dist/index.cjs +11 -6
  31. package/dist/index.d.cts +2 -2
  32. package/dist/index.d.mts +2 -2
  33. package/dist/index.mjs +2 -2
  34. package/package.json +8 -7
@@ -5,7 +5,7 @@ const debug = require("../debug.cjs").createLogger("analysis:dependency");
5
5
  /**
6
6
  * Detects circular dependencies in the graph using DFS with a recursion stack.
7
7
  *
8
- * @throws {@link CircularDependencyError} If a cycle is found, including the call IDs forming the cycle
8
+ * @throws {@link SELCircularDependencyError} If a cycle is found, including the call IDs forming the cycle
9
9
  */
10
10
  const detectCycles = (nodes, edges) => {
11
11
  const visited = /* @__PURE__ */ new Set();
@@ -14,7 +14,7 @@ const detectCycles = (nodes, edges) => {
14
14
  if (inStack.has(nodeId)) {
15
15
  const cycleStart = path.indexOf(nodeId);
16
16
  const cycle = path.slice(cycleStart);
17
- throw new require_errors.CircularDependencyError(`Circular dependency detected: ${cycle.join(" -> ")} -> ${nodeId}`, { callIds: cycle });
17
+ throw new require_errors.SELCircularDependencyError(`Circular dependency detected: ${cycle.join(" -> ")} -> ${nodeId}`, { callIds: cycle });
18
18
  }
19
19
  if (visited.has(nodeId)) return;
20
20
  visited.add(nodeId);
@@ -35,7 +35,7 @@ const detectCycles = (nodes, edges) => {
35
35
  *
36
36
  * @param calls - Array of collected contract calls from AST traversal
37
37
  * @returns A dependency graph with nodes and directed edges
38
- * @throws {@link CircularDependencyError} If a circular dependency is detected between calls
38
+ * @throws {@link SELCircularDependencyError} If a circular dependency is detected between calls
39
39
  */
40
40
  const analyzeDependencies = (calls) => {
41
41
  const nodes = /* @__PURE__ */ new Map();
@@ -1,4 +1,4 @@
1
- import { CircularDependencyError } from "../errors/errors.mjs";
1
+ import { SELCircularDependencyError } from "../errors/errors.mjs";
2
2
  import "../errors/index.mjs";
3
3
  import { createLogger } from "../debug.mjs";
4
4
  //#region src/analysis/dependency-analyzer.ts
@@ -6,7 +6,7 @@ const debug = createLogger("analysis:dependency");
6
6
  /**
7
7
  * Detects circular dependencies in the graph using DFS with a recursion stack.
8
8
  *
9
- * @throws {@link CircularDependencyError} If a cycle is found, including the call IDs forming the cycle
9
+ * @throws {@link SELCircularDependencyError} If a cycle is found, including the call IDs forming the cycle
10
10
  */
11
11
  const detectCycles = (nodes, edges) => {
12
12
  const visited = /* @__PURE__ */ new Set();
@@ -15,7 +15,7 @@ const detectCycles = (nodes, edges) => {
15
15
  if (inStack.has(nodeId)) {
16
16
  const cycleStart = path.indexOf(nodeId);
17
17
  const cycle = path.slice(cycleStart);
18
- throw new CircularDependencyError(`Circular dependency detected: ${cycle.join(" -> ")} -> ${nodeId}`, { callIds: cycle });
18
+ throw new SELCircularDependencyError(`Circular dependency detected: ${cycle.join(" -> ")} -> ${nodeId}`, { callIds: cycle });
19
19
  }
20
20
  if (visited.has(nodeId)) return;
21
21
  visited.add(nodeId);
@@ -36,7 +36,7 @@ const detectCycles = (nodes, edges) => {
36
36
  *
37
37
  * @param calls - Array of collected contract calls from AST traversal
38
38
  * @returns A dependency graph with nodes and directed edges
39
- * @throws {@link CircularDependencyError} If a circular dependency is detected between calls
39
+ * @throws {@link SELCircularDependencyError} If a circular dependency is detected between calls
40
40
  */
41
41
  const analyzeDependencies = (calls) => {
42
42
  const nodes = /* @__PURE__ */ new Map();
@@ -12,13 +12,13 @@ const debug = require("../debug.cjs").createLogger("analysis:plan");
12
12
  * @param graph Dependency graph representing calls and their relationships.
13
13
  * @param limits Optional limits for maximum rounds and total calls.
14
14
  * @returns Execution plan containing planned rounds, total calls, and maximum depth.
15
- * @throws ExecutionLimitError If total calls exceed maxCalls or rounds exceed maxRounds.
15
+ * @throws {@link SELExecutionLimitError} If total calls exceed maxCalls or rounds exceed maxRounds.
16
16
  */
17
17
  const planRounds = (graph, limits = {}) => {
18
18
  const maxRounds = limits.maxRounds ?? 10;
19
19
  const maxCalls = limits.maxCalls ?? 100;
20
20
  const totalCalls = graph.nodes.size;
21
- if (totalCalls > maxCalls) throw new require_errors.ExecutionLimitError(`Execution limit exceeded: ${String(totalCalls)} calls exceeds maxCalls (${String(maxCalls)})`, {
21
+ if (totalCalls > maxCalls) throw new require_errors.SELExecutionLimitError(`Execution limit exceeded: ${String(totalCalls)} calls exceeds maxCalls (${String(maxCalls)})`, {
22
22
  limitType: "maxCalls",
23
23
  limit: maxCalls,
24
24
  actual: totalCalls
@@ -36,7 +36,7 @@ const planRounds = (graph, limits = {}) => {
36
36
  const readyNodes = [];
37
37
  for (const [nodeId, degree] of inDegree) if (degree === 0 && !processed.has(nodeId)) readyNodes.push(nodeId);
38
38
  if (readyNodes.length === 0) break;
39
- if (rounds.length >= maxRounds) throw new require_errors.ExecutionLimitError(`Execution limit exceeded: requires more than maxRounds (${String(maxRounds)}) rounds`, {
39
+ if (rounds.length >= maxRounds) throw new require_errors.SELExecutionLimitError(`Execution limit exceeded: requires more than maxRounds (${String(maxRounds)}) rounds`, {
40
40
  limitType: "maxRounds",
41
41
  limit: maxRounds,
42
42
  actual: rounds.length + 1
@@ -1,4 +1,4 @@
1
- import { ExecutionLimitError } from "../errors/errors.mjs";
1
+ import { SELExecutionLimitError } from "../errors/errors.mjs";
2
2
  import "../errors/index.mjs";
3
3
  import { createLogger } from "../debug.mjs";
4
4
  //#region src/analysis/round-planner.ts
@@ -13,13 +13,13 @@ const debug = createLogger("analysis:plan");
13
13
  * @param graph Dependency graph representing calls and their relationships.
14
14
  * @param limits Optional limits for maximum rounds and total calls.
15
15
  * @returns Execution plan containing planned rounds, total calls, and maximum depth.
16
- * @throws ExecutionLimitError If total calls exceed maxCalls or rounds exceed maxRounds.
16
+ * @throws {@link SELExecutionLimitError} If total calls exceed maxCalls or rounds exceed maxRounds.
17
17
  */
18
18
  const planRounds = (graph, limits = {}) => {
19
19
  const maxRounds = limits.maxRounds ?? 10;
20
20
  const maxCalls = limits.maxCalls ?? 100;
21
21
  const totalCalls = graph.nodes.size;
22
- if (totalCalls > maxCalls) throw new ExecutionLimitError(`Execution limit exceeded: ${String(totalCalls)} calls exceeds maxCalls (${String(maxCalls)})`, {
22
+ if (totalCalls > maxCalls) throw new SELExecutionLimitError(`Execution limit exceeded: ${String(totalCalls)} calls exceeds maxCalls (${String(maxCalls)})`, {
23
23
  limitType: "maxCalls",
24
24
  limit: maxCalls,
25
25
  actual: totalCalls
@@ -37,7 +37,7 @@ const planRounds = (graph, limits = {}) => {
37
37
  const readyNodes = [];
38
38
  for (const [nodeId, degree] of inDegree) if (degree === 0 && !processed.has(nodeId)) readyNodes.push(nodeId);
39
39
  if (readyNodes.length === 0) break;
40
- if (rounds.length >= maxRounds) throw new ExecutionLimitError(`Execution limit exceeded: requires more than maxRounds (${String(maxRounds)}) rounds`, {
40
+ if (rounds.length >= maxRounds) throw new SELExecutionLimitError(`Execution limit exceeded: requires more than maxRounds (${String(maxRounds)}) rounds`, {
41
41
  limitType: "maxRounds",
42
42
  limit: maxRounds,
43
43
  actual: rounds.length + 1
@@ -16,7 +16,7 @@ interface SELClient {
16
16
  data: `0x${string}`;
17
17
  blockNumber?: bigint;
18
18
  }) => Promise<{
19
- data?: `0x${string}`;
19
+ data?: `0x${string}` | undefined;
20
20
  }>;
21
21
  /**
22
22
  * Get the current block number (eth_blockNumber) for pinning reads
@@ -16,7 +16,7 @@ interface SELClient {
16
16
  data: `0x${string}`;
17
17
  blockNumber?: bigint;
18
18
  }) => Promise<{
19
- data?: `0x${string}`;
19
+ data?: `0x${string}` | undefined;
20
20
  }>;
21
21
  /**
22
22
  * Get the current block number (eth_blockNumber) for pinning reads
@@ -18,7 +18,7 @@ var CallCounter = class {
18
18
  }
19
19
  increment(contractName, methodName) {
20
20
  this.count++;
21
- if (this.count > this.maxCalls) throw new require_errors.ExecutionLimitError(`Execution limit exceeded: ${String(this.count)} calls exceeds maxCalls (${String(this.maxCalls)})`, {
21
+ if (this.count > this.maxCalls) throw new require_errors.SELExecutionLimitError(`Execution limit exceeded: ${String(this.count)} calls exceeds maxCalls (${String(this.maxCalls)})`, {
22
22
  limitType: "maxCalls",
23
23
  limit: this.maxCalls,
24
24
  actual: this.count
@@ -1,4 +1,4 @@
1
- import { ExecutionLimitError, SELContractError } from "../errors/errors.mjs";
1
+ import { SELContractError, SELExecutionLimitError } from "../errors/errors.mjs";
2
2
  import "../errors/index.mjs";
3
3
  import { createReplayCallId } from "./replay-cache.mjs";
4
4
  import { createLogger } from "../debug.mjs";
@@ -17,7 +17,7 @@ var CallCounter = class {
17
17
  }
18
18
  increment(contractName, methodName) {
19
19
  this.count++;
20
- if (this.count > this.maxCalls) throw new ExecutionLimitError(`Execution limit exceeded: ${String(this.count)} calls exceeds maxCalls (${String(this.maxCalls)})`, {
20
+ if (this.count > this.maxCalls) throw new SELExecutionLimitError(`Execution limit exceeded: ${String(this.count)} calls exceeds maxCalls (${String(this.maxCalls)})`, {
21
21
  limitType: "maxCalls",
22
22
  limit: this.maxCalls,
23
23
  actual: this.count
@@ -13,7 +13,6 @@ const require_dependency_analyzer = require("../analysis/dependency-analyzer.cjs
13
13
  const require_round_planner = require("../analysis/round-planner.cjs");
14
14
  const require_multi_round_executor = require("../execution/multi-round-executor.cjs");
15
15
  let _seljs_checker = require("@seljs/checker");
16
- let _seljs_common = require("@seljs/common");
17
16
  //#region src/environment/environment.ts
18
17
  /**
19
18
  * Core SEL runtime that bridges CEL expression evaluation with EVM contract reads.
@@ -106,7 +105,9 @@ var SELRuntime = class {
106
105
  *
107
106
  * @param expression - A CEL expression string to type-check
108
107
  * @returns The type-check result containing validity, inferred type, and any errors
109
- * @throws {@link SELTypeError} If the expression contains unrecoverable type errors
108
+ * @throws {@link SELParseError} If the expression cannot be parsed
109
+ * @throws {@link SELTypeCheckError} If the CEL type-checker rejects the expression
110
+ * @throws {@link SELLintError} If lint rules with error severity match
110
111
  */
111
112
  check(expression) {
112
113
  try {
@@ -130,10 +131,19 @@ var SELRuntime = class {
130
131
  * @param context Variable bindings for evaluation
131
132
  * @param options Optional client override
132
133
  * @returns An {@link EvaluateResult} containing the value and optional execution metadata
133
- * @throws {@link SELParseError} If the expression has invalid syntax
134
- * @throws {@link SELTypeError} If type-checking fails
135
- * @throws {@link SELContractError} If a contract call fails or no client is available
134
+ * @throws {@link SELParseError} If the expression cannot be parsed
135
+ * @throws {@link SELTypeCheckError} If the CEL type-checker rejects the expression
136
+ * @throws {@link SELLintError} If lint rules with error severity match
137
+ * @throws {@link SELConfigError} If an ABI / codec registry entry is missing
138
+ * @throws {@link SELContractError} If a contract call fails (non-revert)
139
+ * @throws {@link SELContractRevertError} If a contract call reverted
140
+ * @throws {@link SELMulticallBatchError} If the Multicall3 batch itself failed
141
+ * @throws {@link SELProviderTransportError} If the JSON-RPC transport failed
142
+ * @throws {@link SELProviderRpcError} If the node returned a JSON-RPC error
143
+ * @throws {@link SELExecutionLimitError} If maxRounds / maxCalls were exceeded
144
+ * @throws {@link SELCircularDependencyError} If the call graph has a cycle
136
145
  * @throws {@link SELEvaluationError} If CEL evaluation fails
146
+ * @throws {@link SELTypeConversionError} If a Solidity type wrapper rejected an input
137
147
  */
138
148
  async evaluate(expression, context, options) {
139
149
  let release;
@@ -149,23 +159,21 @@ var SELRuntime = class {
149
159
  }
150
160
  }
151
161
  planExecution(expression, evaluationContext) {
162
+ const checkResult = this.checker.check(expression);
163
+ if (!checkResult.valid) throw new require_errors.SELLintError(checkResult.diagnostics.filter((d) => d.severity === "error"));
152
164
  const parseResult = this.env.parse(expression);
153
165
  const collectedCalls = require_call_collector.collectCalls(parseResult.ast, { get: (name) => this.findContract(name) });
154
166
  debug("evaluate: collected %d calls", collectedCalls.length);
155
167
  const normalizedContext = Object.keys(evaluationContext).length ? require_context.normalizeContextForEvaluation(evaluationContext, this.variableTypes, this.codecRegistry) : void 0;
156
168
  const executionVariables = Object.keys(evaluationContext).length ? evaluationContext : {};
157
- const typeCheckResult = parseResult.check();
158
- if (!typeCheckResult.valid) throw new _seljs_common.SELTypeError(typeCheckResult.error?.message ?? "Type check failed", { cause: typeCheckResult.error });
159
- const lintResult = this.checker.check(expression);
160
- const lintErrors = lintResult.diagnostics.filter((d) => d.severity === "error");
161
- if (lintErrors.length > 0) throw new require_errors.SELLintError(lintErrors);
169
+ const diagnostics = checkResult.diagnostics.filter((d) => d.severity !== "error");
162
170
  return {
163
171
  parseResult,
164
172
  collectedCalls,
165
173
  normalizedContext,
166
174
  executionVariables,
167
- typeCheckResult,
168
- diagnostics: lintResult.diagnostics.filter((d) => d.severity !== "error")
175
+ resolvedType: checkResult.type,
176
+ diagnostics
169
177
  };
170
178
  }
171
179
  async executeContractCalls(collectedCalls, executionVariables, resolvedClient) {
@@ -179,8 +187,9 @@ var SELRuntime = class {
179
187
  try {
180
188
  executionResult = await executor.execute(plan, executionVariables, await require_contract_caller.resolveExecutionBlockNumber(resolvedClient));
181
189
  } catch (error) {
190
+ if (error instanceof require_errors.SELContractRevertError) throw error;
182
191
  let failedCall = collectedCalls[0];
183
- if (error instanceof require_errors.MulticallBatchError) {
192
+ if (error instanceof require_errors.SELMulticallBatchError) {
184
193
  if (error.contractName && error.methodName) {
185
194
  const contractName = error.contractName;
186
195
  const methodName = error.methodName;
@@ -216,7 +225,7 @@ var SELRuntime = class {
216
225
  const resolvedClient = options?.client ?? this.client;
217
226
  if (resolvedClient && resolvedClient !== this.client) require_client.validateClient(resolvedClient);
218
227
  try {
219
- const { parseResult, collectedCalls, normalizedContext, executionVariables, typeCheckResult, diagnostics } = this.planExecution(expression, context ?? {});
228
+ const { parseResult, collectedCalls, normalizedContext, executionVariables, resolvedType, diagnostics } = this.planExecution(expression, context ?? {});
220
229
  let executionMeta;
221
230
  let executionCache;
222
231
  if (collectedCalls.length > 0) {
@@ -240,12 +249,13 @@ var SELRuntime = class {
240
249
  this.currentClient = void 0;
241
250
  this.currentCallCounter = void 0;
242
251
  }
243
- const value = typeCheckResult.type ? this.codecRegistry.encode(typeCheckResult.type, result) : result;
252
+ const value = resolvedType ? this.codecRegistry.encode(resolvedType, result) : result;
244
253
  debug("evaluate: result type=%s", typeof value);
245
254
  const evalResult = executionMeta ? {
246
255
  value,
247
256
  meta: executionMeta
248
257
  } : { value };
258
+ if (resolvedType) evalResult.type = resolvedType;
249
259
  if (diagnostics.length > 0) evalResult.diagnostics = diagnostics;
250
260
  return evalResult;
251
261
  } catch (error) {
@@ -52,7 +52,9 @@ declare class SELRuntime {
52
52
  *
53
53
  * @param expression - A CEL expression string to type-check
54
54
  * @returns The type-check result containing validity, inferred type, and any errors
55
- * @throws {@link SELTypeError} If the expression contains unrecoverable type errors
55
+ * @throws {@link SELParseError} If the expression cannot be parsed
56
+ * @throws {@link SELTypeCheckError} If the CEL type-checker rejects the expression
57
+ * @throws {@link SELLintError} If lint rules with error severity match
56
58
  */
57
59
  check(expression: string): TypeCheckResult;
58
60
  /**
@@ -70,10 +72,19 @@ declare class SELRuntime {
70
72
  * @param context Variable bindings for evaluation
71
73
  * @param options Optional client override
72
74
  * @returns An {@link EvaluateResult} containing the value and optional execution metadata
73
- * @throws {@link SELParseError} If the expression has invalid syntax
74
- * @throws {@link SELTypeError} If type-checking fails
75
- * @throws {@link SELContractError} If a contract call fails or no client is available
75
+ * @throws {@link SELParseError} If the expression cannot be parsed
76
+ * @throws {@link SELTypeCheckError} If the CEL type-checker rejects the expression
77
+ * @throws {@link SELLintError} If lint rules with error severity match
78
+ * @throws {@link SELConfigError} If an ABI / codec registry entry is missing
79
+ * @throws {@link SELContractError} If a contract call fails (non-revert)
80
+ * @throws {@link SELContractRevertError} If a contract call reverted
81
+ * @throws {@link SELMulticallBatchError} If the Multicall3 batch itself failed
82
+ * @throws {@link SELProviderTransportError} If the JSON-RPC transport failed
83
+ * @throws {@link SELProviderRpcError} If the node returned a JSON-RPC error
84
+ * @throws {@link SELExecutionLimitError} If maxRounds / maxCalls were exceeded
85
+ * @throws {@link SELCircularDependencyError} If the call graph has a cycle
76
86
  * @throws {@link SELEvaluationError} If CEL evaluation fails
87
+ * @throws {@link SELTypeConversionError} If a Solidity type wrapper rejected an input
77
88
  */
78
89
  evaluate<T = unknown>(expression: string, context?: Record<string, unknown>, options?: EvaluateOptions): Promise<EvaluateResult<T>>;
79
90
  private planExecution;
@@ -52,7 +52,9 @@ declare class SELRuntime {
52
52
  *
53
53
  * @param expression - A CEL expression string to type-check
54
54
  * @returns The type-check result containing validity, inferred type, and any errors
55
- * @throws {@link SELTypeError} If the expression contains unrecoverable type errors
55
+ * @throws {@link SELParseError} If the expression cannot be parsed
56
+ * @throws {@link SELTypeCheckError} If the CEL type-checker rejects the expression
57
+ * @throws {@link SELLintError} If lint rules with error severity match
56
58
  */
57
59
  check(expression: string): TypeCheckResult;
58
60
  /**
@@ -70,10 +72,19 @@ declare class SELRuntime {
70
72
  * @param context Variable bindings for evaluation
71
73
  * @param options Optional client override
72
74
  * @returns An {@link EvaluateResult} containing the value and optional execution metadata
73
- * @throws {@link SELParseError} If the expression has invalid syntax
74
- * @throws {@link SELTypeError} If type-checking fails
75
- * @throws {@link SELContractError} If a contract call fails or no client is available
75
+ * @throws {@link SELParseError} If the expression cannot be parsed
76
+ * @throws {@link SELTypeCheckError} If the CEL type-checker rejects the expression
77
+ * @throws {@link SELLintError} If lint rules with error severity match
78
+ * @throws {@link SELConfigError} If an ABI / codec registry entry is missing
79
+ * @throws {@link SELContractError} If a contract call fails (non-revert)
80
+ * @throws {@link SELContractRevertError} If a contract call reverted
81
+ * @throws {@link SELMulticallBatchError} If the Multicall3 batch itself failed
82
+ * @throws {@link SELProviderTransportError} If the JSON-RPC transport failed
83
+ * @throws {@link SELProviderRpcError} If the node returned a JSON-RPC error
84
+ * @throws {@link SELExecutionLimitError} If maxRounds / maxCalls were exceeded
85
+ * @throws {@link SELCircularDependencyError} If the call graph has a cycle
76
86
  * @throws {@link SELEvaluationError} If CEL evaluation fails
87
+ * @throws {@link SELTypeConversionError} If a Solidity type wrapper rejected an input
77
88
  */
78
89
  evaluate<T = unknown>(expression: string, context?: Record<string, unknown>, options?: EvaluateOptions): Promise<EvaluateResult<T>>;
79
90
  private planExecution;
@@ -1,5 +1,5 @@
1
1
  import { getBuiltinContracts } from "./builtin-contracts.mjs";
2
- import { MulticallBatchError, SELContractError, SELLintError, SELTypeError } from "../errors/errors.mjs";
2
+ import { SELContractError, SELContractRevertError, SELLintError, SELMulticallBatchError } from "../errors/errors.mjs";
3
3
  import "../errors/index.mjs";
4
4
  import { validateClient } from "./client.mjs";
5
5
  import { normalizeContextForEvaluation } from "./context.mjs";
@@ -104,7 +104,9 @@ var SELRuntime = class {
104
104
  *
105
105
  * @param expression - A CEL expression string to type-check
106
106
  * @returns The type-check result containing validity, inferred type, and any errors
107
- * @throws {@link SELTypeError} If the expression contains unrecoverable type errors
107
+ * @throws {@link SELParseError} If the expression cannot be parsed
108
+ * @throws {@link SELTypeCheckError} If the CEL type-checker rejects the expression
109
+ * @throws {@link SELLintError} If lint rules with error severity match
108
110
  */
109
111
  check(expression) {
110
112
  try {
@@ -128,10 +130,19 @@ var SELRuntime = class {
128
130
  * @param context Variable bindings for evaluation
129
131
  * @param options Optional client override
130
132
  * @returns An {@link EvaluateResult} containing the value and optional execution metadata
131
- * @throws {@link SELParseError} If the expression has invalid syntax
132
- * @throws {@link SELTypeError} If type-checking fails
133
- * @throws {@link SELContractError} If a contract call fails or no client is available
133
+ * @throws {@link SELParseError} If the expression cannot be parsed
134
+ * @throws {@link SELTypeCheckError} If the CEL type-checker rejects the expression
135
+ * @throws {@link SELLintError} If lint rules with error severity match
136
+ * @throws {@link SELConfigError} If an ABI / codec registry entry is missing
137
+ * @throws {@link SELContractError} If a contract call fails (non-revert)
138
+ * @throws {@link SELContractRevertError} If a contract call reverted
139
+ * @throws {@link SELMulticallBatchError} If the Multicall3 batch itself failed
140
+ * @throws {@link SELProviderTransportError} If the JSON-RPC transport failed
141
+ * @throws {@link SELProviderRpcError} If the node returned a JSON-RPC error
142
+ * @throws {@link SELExecutionLimitError} If maxRounds / maxCalls were exceeded
143
+ * @throws {@link SELCircularDependencyError} If the call graph has a cycle
134
144
  * @throws {@link SELEvaluationError} If CEL evaluation fails
145
+ * @throws {@link SELTypeConversionError} If a Solidity type wrapper rejected an input
135
146
  */
136
147
  async evaluate(expression, context, options) {
137
148
  let release;
@@ -147,23 +158,21 @@ var SELRuntime = class {
147
158
  }
148
159
  }
149
160
  planExecution(expression, evaluationContext) {
161
+ const checkResult = this.checker.check(expression);
162
+ if (!checkResult.valid) throw new SELLintError(checkResult.diagnostics.filter((d) => d.severity === "error"));
150
163
  const parseResult = this.env.parse(expression);
151
164
  const collectedCalls = collectCalls(parseResult.ast, { get: (name) => this.findContract(name) });
152
165
  debug("evaluate: collected %d calls", collectedCalls.length);
153
166
  const normalizedContext = Object.keys(evaluationContext).length ? normalizeContextForEvaluation(evaluationContext, this.variableTypes, this.codecRegistry) : void 0;
154
167
  const executionVariables = Object.keys(evaluationContext).length ? evaluationContext : {};
155
- const typeCheckResult = parseResult.check();
156
- if (!typeCheckResult.valid) throw new SELTypeError(typeCheckResult.error?.message ?? "Type check failed", { cause: typeCheckResult.error });
157
- const lintResult = this.checker.check(expression);
158
- const lintErrors = lintResult.diagnostics.filter((d) => d.severity === "error");
159
- if (lintErrors.length > 0) throw new SELLintError(lintErrors);
168
+ const diagnostics = checkResult.diagnostics.filter((d) => d.severity !== "error");
160
169
  return {
161
170
  parseResult,
162
171
  collectedCalls,
163
172
  normalizedContext,
164
173
  executionVariables,
165
- typeCheckResult,
166
- diagnostics: lintResult.diagnostics.filter((d) => d.severity !== "error")
174
+ resolvedType: checkResult.type,
175
+ diagnostics
167
176
  };
168
177
  }
169
178
  async executeContractCalls(collectedCalls, executionVariables, resolvedClient) {
@@ -177,8 +186,9 @@ var SELRuntime = class {
177
186
  try {
178
187
  executionResult = await executor.execute(plan, executionVariables, await resolveExecutionBlockNumber(resolvedClient));
179
188
  } catch (error) {
189
+ if (error instanceof SELContractRevertError) throw error;
180
190
  let failedCall = collectedCalls[0];
181
- if (error instanceof MulticallBatchError) {
191
+ if (error instanceof SELMulticallBatchError) {
182
192
  if (error.contractName && error.methodName) {
183
193
  const contractName = error.contractName;
184
194
  const methodName = error.methodName;
@@ -214,7 +224,7 @@ var SELRuntime = class {
214
224
  const resolvedClient = options?.client ?? this.client;
215
225
  if (resolvedClient && resolvedClient !== this.client) validateClient(resolvedClient);
216
226
  try {
217
- const { parseResult, collectedCalls, normalizedContext, executionVariables, typeCheckResult, diagnostics } = this.planExecution(expression, context ?? {});
227
+ const { parseResult, collectedCalls, normalizedContext, executionVariables, resolvedType, diagnostics } = this.planExecution(expression, context ?? {});
218
228
  let executionMeta;
219
229
  let executionCache;
220
230
  if (collectedCalls.length > 0) {
@@ -238,12 +248,13 @@ var SELRuntime = class {
238
248
  this.currentClient = void 0;
239
249
  this.currentCallCounter = void 0;
240
250
  }
241
- const value = typeCheckResult.type ? this.codecRegistry.encode(typeCheckResult.type, result) : result;
251
+ const value = resolvedType ? this.codecRegistry.encode(resolvedType, result) : result;
242
252
  debug("evaluate: result type=%s", typeof value);
243
253
  const evalResult = executionMeta ? {
244
254
  value,
245
255
  meta: executionMeta
246
256
  } : { value };
257
+ if (resolvedType) evalResult.type = resolvedType;
247
258
  if (diagnostics.length > 0) evalResult.diagnostics = diagnostics;
248
259
  return evalResult;
249
260
  } catch (error) {
@@ -1,29 +1,87 @@
1
1
  require("../_virtual/_rolldown/runtime.cjs");
2
2
  const require_errors = require("../errors/errors.cjs");
3
3
  require("../errors/index.cjs");
4
- let _marcbachmann_cel_js = require("@marcbachmann/cel-js");
5
4
  let _seljs_common = require("@seljs/common");
5
+ let _marcbachmann_cel_js = require("@marcbachmann/cel-js");
6
+ let viem = require("viem");
6
7
  //#region src/environment/error-wrapper.ts
7
8
  /**
9
+ * Compose a human-readable message from a viem error. Uses `shortMessage`
10
+ * when present and appends any `metaMessages` lines so context like the
11
+ * contract address, function call, and chain is not lost.
12
+ */
13
+ const extractViemMessage = (error) => {
14
+ const shortMessage = error.shortMessage || error.message;
15
+ const meta = error.metaMessages;
16
+ if (!meta || meta.length === 0) return shortMessage;
17
+ return `${shortMessage}\n${meta.join("\n")}`;
18
+ };
19
+ const wrapContractRevert = (error) => {
20
+ const decoded = error.data ? {
21
+ name: error.data.errorName,
22
+ args: error.data.args ?? []
23
+ } : void 0;
24
+ return new require_errors.SELContractRevertError(extractViemMessage(error), {
25
+ cause: error,
26
+ revertReason: error.reason,
27
+ revertData: error.raw,
28
+ decodedError: decoded
29
+ });
30
+ };
31
+ const wrapViemError = (error) => {
32
+ const nestedRevert = error.walk((e) => e instanceof viem.ContractFunctionRevertedError);
33
+ if (nestedRevert) return wrapContractRevert(nestedRevert);
34
+ if (error instanceof viem.ContractFunctionRevertedError) return wrapContractRevert(error);
35
+ if (error instanceof viem.ContractFunctionExecutionError) return new require_errors.SELContractError(extractViemMessage(error), {
36
+ cause: error,
37
+ contractName: error.contractAddress,
38
+ methodName: error.functionName
39
+ });
40
+ if (error instanceof viem.AbiDecodingDataSizeInvalidError || error instanceof viem.AbiDecodingZeroDataError || error instanceof viem.AbiErrorSignatureNotFoundError) return new require_errors.SELContractError(extractViemMessage(error), { cause: error });
41
+ if (error instanceof viem.HttpRequestError) return new require_errors.SELProviderTransportError(extractViemMessage(error), {
42
+ cause: error,
43
+ httpStatus: error.status,
44
+ url: error.url,
45
+ body: typeof error.body === "string" ? error.body : error.body !== void 0 ? JSON.stringify(error.body) : void 0
46
+ });
47
+ if (error instanceof viem.TimeoutError || error instanceof viem.WebSocketRequestError) return new require_errors.SELProviderTransportError(extractViemMessage(error), {
48
+ cause: error,
49
+ url: error instanceof viem.WebSocketRequestError ? error.url : void 0
50
+ });
51
+ if (error instanceof viem.RpcError) {
52
+ const rpc = error;
53
+ return new require_errors.SELProviderRpcError(extractViemMessage(error), {
54
+ cause: error,
55
+ rpcCode: rpc.code,
56
+ rpcData: rpc.data
57
+ });
58
+ }
59
+ return new require_errors.SELProviderError(extractViemMessage(error), { cause: error });
60
+ };
61
+ /**
8
62
  * Wraps an unknown error into a known SEL error type.
9
- * - If the error is already a SEL error, it is returned as is.
10
- * - If the error is a CEL error, it is wrapped into the corresponding SEL error type.
11
- * - If the error is an unknown type, it is wrapped into a generic Error.
12
63
  *
13
- * @param error The error to wrap.
14
- * @returns The wrapped error.
64
+ * - A `SELError` is returned as-is.
65
+ * - cel-js errors (`ParseError`, `TypeError`, `EvaluationError`) become the
66
+ * matching `SEL*Error` and preserve `cause`.
67
+ * - viem errors are routed by concrete class: reverts → `SELContractRevertError`,
68
+ * transport/timeout → `SELProviderTransportError`, JSON-RPC → `SELProviderRpcError`,
69
+ * contract execution / ABI decode → `SELContractError`, everything else → `SELProviderError`.
70
+ * - Any other `Error` becomes `SELEvaluationError` with the original as `cause`.
15
71
  */
16
72
  const wrapError = (error) => {
17
- if (error instanceof require_errors.SELContractError) return error;
18
- if (error instanceof _marcbachmann_cel_js.ParseError) return new _seljs_common.SELParseError(error.message, { cause: error });
73
+ if (error instanceof _seljs_common.SELError) return error;
19
74
  if (error instanceof _marcbachmann_cel_js.EvaluationError) {
20
75
  const cause = error.cause;
21
- if (cause instanceof require_errors.SELContractError) return cause;
22
- return new require_errors.SELEvaluationError(error.message, { cause: error });
76
+ if (cause instanceof _seljs_common.SELError) return cause;
77
+ if (cause instanceof viem.BaseError) return wrapViemError(cause);
78
+ return new _seljs_common.SELEvaluationError(error.message, { cause: error });
23
79
  }
24
- if (error instanceof _marcbachmann_cel_js.TypeError) return new _seljs_common.SELTypeError(error.message, { cause: error });
25
- if (error instanceof Error) return error;
26
- return new Error(String(error));
80
+ if (error instanceof _marcbachmann_cel_js.ParseError) return new _seljs_common.SELParseError(error.message, { cause: error });
81
+ if (error instanceof _marcbachmann_cel_js.TypeError) return new _seljs_common.SELTypeCheckError(error.message, { cause: error });
82
+ if (error instanceof viem.BaseError) return wrapViemError(error);
83
+ if (error instanceof Error) return new _seljs_common.SELEvaluationError(error.message, { cause: error });
84
+ return new _seljs_common.SELEvaluationError(String(error));
27
85
  };
28
86
  //#endregion
29
87
  exports.wrapError = wrapError;
@@ -1,27 +1,86 @@
1
- import { SELContractError, SELEvaluationError, SELParseError, SELTypeError } from "../errors/errors.mjs";
1
+ import { SELContractError, SELContractRevertError, SELProviderError, SELProviderRpcError, SELProviderTransportError } from "../errors/errors.mjs";
2
2
  import "../errors/index.mjs";
3
+ import { SELError, SELEvaluationError, SELParseError, SELTypeCheckError } from "@seljs/common";
3
4
  import { EvaluationError, ParseError, TypeError } from "@marcbachmann/cel-js";
5
+ import { AbiDecodingDataSizeInvalidError, AbiDecodingZeroDataError, AbiErrorSignatureNotFoundError, BaseError, ContractFunctionExecutionError, ContractFunctionRevertedError, HttpRequestError, RpcError, TimeoutError, WebSocketRequestError } from "viem";
4
6
  //#region src/environment/error-wrapper.ts
5
7
  /**
8
+ * Compose a human-readable message from a viem error. Uses `shortMessage`
9
+ * when present and appends any `metaMessages` lines so context like the
10
+ * contract address, function call, and chain is not lost.
11
+ */
12
+ const extractViemMessage = (error) => {
13
+ const shortMessage = error.shortMessage || error.message;
14
+ const meta = error.metaMessages;
15
+ if (!meta || meta.length === 0) return shortMessage;
16
+ return `${shortMessage}\n${meta.join("\n")}`;
17
+ };
18
+ const wrapContractRevert = (error) => {
19
+ const decoded = error.data ? {
20
+ name: error.data.errorName,
21
+ args: error.data.args ?? []
22
+ } : void 0;
23
+ return new SELContractRevertError(extractViemMessage(error), {
24
+ cause: error,
25
+ revertReason: error.reason,
26
+ revertData: error.raw,
27
+ decodedError: decoded
28
+ });
29
+ };
30
+ const wrapViemError = (error) => {
31
+ const nestedRevert = error.walk((e) => e instanceof ContractFunctionRevertedError);
32
+ if (nestedRevert) return wrapContractRevert(nestedRevert);
33
+ if (error instanceof ContractFunctionRevertedError) return wrapContractRevert(error);
34
+ if (error instanceof ContractFunctionExecutionError) return new SELContractError(extractViemMessage(error), {
35
+ cause: error,
36
+ contractName: error.contractAddress,
37
+ methodName: error.functionName
38
+ });
39
+ if (error instanceof AbiDecodingDataSizeInvalidError || error instanceof AbiDecodingZeroDataError || error instanceof AbiErrorSignatureNotFoundError) return new SELContractError(extractViemMessage(error), { cause: error });
40
+ if (error instanceof HttpRequestError) return new SELProviderTransportError(extractViemMessage(error), {
41
+ cause: error,
42
+ httpStatus: error.status,
43
+ url: error.url,
44
+ body: typeof error.body === "string" ? error.body : error.body !== void 0 ? JSON.stringify(error.body) : void 0
45
+ });
46
+ if (error instanceof TimeoutError || error instanceof WebSocketRequestError) return new SELProviderTransportError(extractViemMessage(error), {
47
+ cause: error,
48
+ url: error instanceof WebSocketRequestError ? error.url : void 0
49
+ });
50
+ if (error instanceof RpcError) {
51
+ const rpc = error;
52
+ return new SELProviderRpcError(extractViemMessage(error), {
53
+ cause: error,
54
+ rpcCode: rpc.code,
55
+ rpcData: rpc.data
56
+ });
57
+ }
58
+ return new SELProviderError(extractViemMessage(error), { cause: error });
59
+ };
60
+ /**
6
61
  * Wraps an unknown error into a known SEL error type.
7
- * - If the error is already a SEL error, it is returned as is.
8
- * - If the error is a CEL error, it is wrapped into the corresponding SEL error type.
9
- * - If the error is an unknown type, it is wrapped into a generic Error.
10
62
  *
11
- * @param error The error to wrap.
12
- * @returns The wrapped error.
63
+ * - A `SELError` is returned as-is.
64
+ * - cel-js errors (`ParseError`, `TypeError`, `EvaluationError`) become the
65
+ * matching `SEL*Error` and preserve `cause`.
66
+ * - viem errors are routed by concrete class: reverts → `SELContractRevertError`,
67
+ * transport/timeout → `SELProviderTransportError`, JSON-RPC → `SELProviderRpcError`,
68
+ * contract execution / ABI decode → `SELContractError`, everything else → `SELProviderError`.
69
+ * - Any other `Error` becomes `SELEvaluationError` with the original as `cause`.
13
70
  */
14
71
  const wrapError = (error) => {
15
- if (error instanceof SELContractError) return error;
16
- if (error instanceof ParseError) return new SELParseError(error.message, { cause: error });
72
+ if (error instanceof SELError) return error;
17
73
  if (error instanceof EvaluationError) {
18
74
  const cause = error.cause;
19
- if (cause instanceof SELContractError) return cause;
75
+ if (cause instanceof SELError) return cause;
76
+ if (cause instanceof BaseError) return wrapViemError(cause);
20
77
  return new SELEvaluationError(error.message, { cause: error });
21
78
  }
22
- if (error instanceof TypeError) return new SELTypeError(error.message, { cause: error });
23
- if (error instanceof Error) return error;
24
- return new Error(String(error));
79
+ if (error instanceof ParseError) return new SELParseError(error.message, { cause: error });
80
+ if (error instanceof TypeError) return new SELTypeCheckError(error.message, { cause: error });
81
+ if (error instanceof BaseError) return wrapViemError(error);
82
+ if (error instanceof Error) return new SELEvaluationError(error.message, { cause: error });
83
+ return new SELEvaluationError(String(error));
25
84
  };
26
85
  //#endregion
27
86
  export { wrapError };