@seljs/runtime 1.3.0-beta.28 → 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.
@@ -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
@@ -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
@@ -105,7 +105,9 @@ var SELRuntime = class {
105
105
  *
106
106
  * @param expression - A CEL expression string to type-check
107
107
  * @returns The type-check result containing validity, inferred type, and any errors
108
- * @throws {@link SELEvaluationError} 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
109
111
  */
110
112
  check(expression) {
111
113
  try {
@@ -129,9 +131,19 @@ var SELRuntime = class {
129
131
  * @param context Variable bindings for evaluation
130
132
  * @param options Optional client override
131
133
  * @returns An {@link EvaluateResult} containing the value and optional execution metadata
132
- * @throws {@link SELLintError} If the expression fails parse, type-check, or lint rules
133
- * @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
134
145
  * @throws {@link SELEvaluationError} If CEL evaluation fails
146
+ * @throws {@link SELTypeConversionError} If a Solidity type wrapper rejected an input
135
147
  */
136
148
  async evaluate(expression, context, options) {
137
149
  let release;
@@ -175,8 +187,9 @@ var SELRuntime = class {
175
187
  try {
176
188
  executionResult = await executor.execute(plan, executionVariables, await require_contract_caller.resolveExecutionBlockNumber(resolvedClient));
177
189
  } catch (error) {
190
+ if (error instanceof require_errors.SELContractRevertError) throw error;
178
191
  let failedCall = collectedCalls[0];
179
- if (error instanceof require_errors.MulticallBatchError) {
192
+ if (error instanceof require_errors.SELMulticallBatchError) {
180
193
  if (error.contractName && error.methodName) {
181
194
  const contractName = error.contractName;
182
195
  const methodName = error.methodName;
@@ -194,16 +207,10 @@ var SELRuntime = class {
194
207
  } else if (typeof error.failedCallIndex === "number") failedCall = collectedCalls[error.failedCallIndex] ?? failedCall;
195
208
  }
196
209
  if (!failedCall) throw error;
197
- const revertFields = error instanceof require_errors.MulticallBatchError ? {
198
- revertReason: error.revertReason,
199
- revertData: error.revertData,
200
- decodedError: error.decodedError
201
- } : {};
202
210
  throw new require_errors.SELContractError(`Contract call failed: ${failedCall.contract}.${failedCall.method}`, {
203
211
  cause: error,
204
212
  contractName: failedCall.contract,
205
- methodName: failedCall.method,
206
- ...revertFields
213
+ methodName: failedCall.method
207
214
  });
208
215
  }
209
216
  return {
@@ -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 SELEvaluationError} 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,9 +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 SELLintError} If the expression fails parse, type-check, or lint rules
74
- * @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
75
86
  * @throws {@link SELEvaluationError} If CEL evaluation fails
87
+ * @throws {@link SELTypeConversionError} If a Solidity type wrapper rejected an input
76
88
  */
77
89
  evaluate<T = unknown>(expression: string, context?: Record<string, unknown>, options?: EvaluateOptions): Promise<EvaluateResult<T>>;
78
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 SELEvaluationError} 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,9 +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 SELLintError} If the expression fails parse, type-check, or lint rules
74
- * @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
75
86
  * @throws {@link SELEvaluationError} If CEL evaluation fails
87
+ * @throws {@link SELTypeConversionError} If a Solidity type wrapper rejected an input
76
88
  */
77
89
  evaluate<T = unknown>(expression: string, context?: Record<string, unknown>, options?: EvaluateOptions): Promise<EvaluateResult<T>>;
78
90
  private planExecution;
@@ -1,5 +1,5 @@
1
1
  import { getBuiltinContracts } from "./builtin-contracts.mjs";
2
- import { MulticallBatchError, SELContractError, SELLintError } 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 SELEvaluationError} 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,9 +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 SELLintError} If the expression fails parse, type-check, or lint rules
132
- * @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
133
144
  * @throws {@link SELEvaluationError} If CEL evaluation fails
145
+ * @throws {@link SELTypeConversionError} If a Solidity type wrapper rejected an input
134
146
  */
135
147
  async evaluate(expression, context, options) {
136
148
  let release;
@@ -174,8 +186,9 @@ var SELRuntime = class {
174
186
  try {
175
187
  executionResult = await executor.execute(plan, executionVariables, await resolveExecutionBlockNumber(resolvedClient));
176
188
  } catch (error) {
189
+ if (error instanceof SELContractRevertError) throw error;
177
190
  let failedCall = collectedCalls[0];
178
- if (error instanceof MulticallBatchError) {
191
+ if (error instanceof SELMulticallBatchError) {
179
192
  if (error.contractName && error.methodName) {
180
193
  const contractName = error.contractName;
181
194
  const methodName = error.methodName;
@@ -193,16 +206,10 @@ var SELRuntime = class {
193
206
  } else if (typeof error.failedCallIndex === "number") failedCall = collectedCalls[error.failedCallIndex] ?? failedCall;
194
207
  }
195
208
  if (!failedCall) throw error;
196
- const revertFields = error instanceof MulticallBatchError ? {
197
- revertReason: error.revertReason,
198
- revertData: error.revertData,
199
- decodedError: error.decodedError
200
- } : {};
201
209
  throw new SELContractError(`Contract call failed: ${failedCall.contract}.${failedCall.method}`, {
202
210
  cause: error,
203
211
  contractName: failedCall.contract,
204
- methodName: failedCall.method,
205
- ...revertFields
212
+ methodName: failedCall.method
206
213
  });
207
214
  }
208
215
  return {
@@ -1,28 +1,87 @@
1
1
  require("../_virtual/_rolldown/runtime.cjs");
2
+ const require_errors = require("../errors/errors.cjs");
2
3
  require("../errors/index.cjs");
3
4
  let _seljs_common = require("@seljs/common");
4
5
  let _marcbachmann_cel_js = require("@marcbachmann/cel-js");
6
+ let viem = require("viem");
5
7
  //#region src/environment/error-wrapper.ts
6
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
+ /**
7
62
  * Wraps an unknown error into a known SEL error type.
8
- * - If the error is already a SEL error, it is returned as is.
9
- * - If the error is a CEL error, it is wrapped into the corresponding SEL error type.
10
- * - If the error is an unknown type, it is wrapped into a generic Error.
11
63
  *
12
- * @param error The error to wrap.
13
- * @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`.
14
71
  */
15
72
  const wrapError = (error) => {
16
73
  if (error instanceof _seljs_common.SELError) return error;
17
74
  if (error instanceof _marcbachmann_cel_js.EvaluationError) {
18
75
  const cause = error.cause;
19
76
  if (cause instanceof _seljs_common.SELError) return cause;
77
+ if (cause instanceof viem.BaseError) return wrapViemError(cause);
20
78
  return new _seljs_common.SELEvaluationError(error.message, { cause: error });
21
79
  }
22
- if (error instanceof _marcbachmann_cel_js.ParseError) return new _seljs_common.SELEvaluationError(error.message, { cause: error });
23
- if (error instanceof _marcbachmann_cel_js.TypeError) return new _seljs_common.SELEvaluationError(error.message, { cause: error });
24
- if (error instanceof Error) return error;
25
- 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));
26
85
  };
27
86
  //#endregion
28
87
  exports.wrapError = wrapError;
@@ -1,28 +1,86 @@
1
- import { SELEvaluationError } from "../errors/errors.mjs";
1
+ import { SELContractError, SELContractRevertError, SELProviderError, SELProviderRpcError, SELProviderTransportError } from "../errors/errors.mjs";
2
2
  import "../errors/index.mjs";
3
- import { SELError } from "@seljs/common";
3
+ import { SELError, SELEvaluationError, SELParseError, SELTypeCheckError } from "@seljs/common";
4
4
  import { EvaluationError, ParseError, TypeError } from "@marcbachmann/cel-js";
5
+ import { AbiDecodingDataSizeInvalidError, AbiDecodingZeroDataError, AbiErrorSignatureNotFoundError, BaseError, ContractFunctionExecutionError, ContractFunctionRevertedError, HttpRequestError, RpcError, TimeoutError, WebSocketRequestError } from "viem";
5
6
  //#region src/environment/error-wrapper.ts
6
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
+ /**
7
61
  * Wraps an unknown error into a known SEL error type.
8
- * - If the error is already a SEL error, it is returned as is.
9
- * - If the error is a CEL error, it is wrapped into the corresponding SEL error type.
10
- * - If the error is an unknown type, it is wrapped into a generic Error.
11
62
  *
12
- * @param error The error to wrap.
13
- * @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`.
14
70
  */
15
71
  const wrapError = (error) => {
16
72
  if (error instanceof SELError) return error;
17
73
  if (error instanceof EvaluationError) {
18
74
  const cause = error.cause;
19
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 ParseError) return new SELEvaluationError(error.message, { cause: error });
23
- if (error instanceof TypeError) return new SELEvaluationError(error.message, { cause: error });
24
- if (error instanceof Error) return error;
25
- 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));
26
84
  };
27
85
  //#endregion
28
86
  export { wrapError };
@@ -19,7 +19,7 @@ interface MulticallOptions {
19
19
  * Limits for contract call execution.
20
20
  *
21
21
  * Execution limits (`maxRounds`, `maxCalls`) bound the multi-round contract
22
- * execution engine. An {@link ExecutionLimitError} is thrown when exceeded.
22
+ * execution engine. An {@link SELExecutionLimitError} is thrown when exceeded.
23
23
  */
24
24
  interface SELLimits {
25
25
  /** Maximum number of dependency-ordered execution rounds (default: 10) */
@@ -19,7 +19,7 @@ interface MulticallOptions {
19
19
  * Limits for contract call execution.
20
20
  *
21
21
  * Execution limits (`maxRounds`, `maxCalls`) bound the multi-round contract
22
- * execution engine. An {@link ExecutionLimitError} is thrown when exceeded.
22
+ * execution engine. An {@link SELExecutionLimitError} is thrown when exceeded.
23
23
  */
24
24
  interface SELLimits {
25
25
  /** Maximum number of dependency-ordered execution rounds (default: 10) */