@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.
- package/dist/analysis/dependency-analyzer.cjs +3 -3
- package/dist/analysis/dependency-analyzer.mjs +4 -4
- package/dist/analysis/round-planner.cjs +3 -3
- package/dist/analysis/round-planner.mjs +4 -4
- package/dist/environment/contract-caller.cjs +1 -1
- package/dist/environment/contract-caller.mjs +2 -2
- package/dist/environment/environment.cjs +18 -11
- package/dist/environment/environment.d.cts +15 -3
- package/dist/environment/environment.d.mts +15 -3
- package/dist/environment/environment.mjs +19 -12
- package/dist/environment/error-wrapper.cjs +68 -9
- package/dist/environment/error-wrapper.mjs +69 -11
- package/dist/environment/types.d.cts +1 -1
- package/dist/environment/types.d.mts +1 -1
- package/dist/errors/errors.cjs +99 -42
- package/dist/errors/errors.d.cts +86 -44
- package/dist/errors/errors.d.mts +86 -44
- package/dist/errors/errors.mjs +93 -41
- package/dist/errors/index.d.mts +1 -1
- package/dist/execution/multicall-batcher.cjs +3 -3
- package/dist/execution/multicall-batcher.mjs +4 -4
- package/dist/execution/round-executor.cjs +6 -6
- package/dist/execution/round-executor.mjs +7 -7
- package/dist/index.cjs +10 -3
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/package.json +7 -6
|
@@ -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
|
|
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.
|
|
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
|
|
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 {
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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 {
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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 {
|
|
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
|
|
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
|
|
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
|
|
133
|
-
* @throws {@link
|
|
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.
|
|
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
|
|
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
|
|
74
|
-
* @throws {@link
|
|
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
|
|
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
|
|
74
|
-
* @throws {@link
|
|
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 {
|
|
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
|
|
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
|
|
132
|
-
* @throws {@link
|
|
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
|
|
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
|
-
*
|
|
13
|
-
*
|
|
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.
|
|
23
|
-
if (error instanceof _marcbachmann_cel_js.TypeError) return new _seljs_common.
|
|
24
|
-
if (error instanceof
|
|
25
|
-
return new
|
|
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 {
|
|
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
|
-
*
|
|
13
|
-
*
|
|
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
|
|
23
|
-
if (error instanceof TypeError) return new
|
|
24
|
-
if (error instanceof
|
|
25
|
-
return new
|
|
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
|
|
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
|
|
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) */
|