@seljs/runtime 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/_virtual/_rolldown/runtime.cjs +23 -0
- package/dist/analysis/call-collector.cjs +233 -0
- package/dist/analysis/call-collector.mjs +232 -0
- package/dist/analysis/dependency-analyzer.cjs +68 -0
- package/dist/analysis/dependency-analyzer.mjs +68 -0
- package/dist/analysis/round-planner.cjs +65 -0
- package/dist/analysis/round-planner.mjs +65 -0
- package/dist/analysis/types.d.cts +115 -0
- package/dist/analysis/types.d.mts +115 -0
- package/dist/debug.cjs +17 -0
- package/dist/debug.mjs +15 -0
- package/dist/environment/context.cjs +11 -0
- package/dist/environment/context.mjs +11 -0
- package/dist/environment/contract-caller.cjs +81 -0
- package/dist/environment/contract-caller.mjs +77 -0
- package/dist/environment/environment.cjs +254 -0
- package/dist/environment/environment.d.cts +84 -0
- package/dist/environment/environment.d.mts +84 -0
- package/dist/environment/environment.mjs +252 -0
- package/dist/environment/error-wrapper.cjs +29 -0
- package/dist/environment/error-wrapper.mjs +27 -0
- package/dist/environment/index.cjs +1 -0
- package/dist/environment/index.d.mts +2 -0
- package/dist/environment/index.mjs +2 -0
- package/dist/environment/replay-cache.cjs +48 -0
- package/dist/environment/replay-cache.mjs +47 -0
- package/dist/environment/types.d.cts +60 -0
- package/dist/environment/types.d.mts +60 -0
- package/dist/errors/errors.cjs +68 -0
- package/dist/errors/errors.d.cts +64 -0
- package/dist/errors/errors.d.mts +64 -0
- package/dist/errors/errors.mjs +63 -0
- package/dist/errors/index.cjs +3 -0
- package/dist/errors/index.d.mts +1 -0
- package/dist/errors/index.mjs +2 -0
- package/dist/execution/multi-round-executor.cjs +45 -0
- package/dist/execution/multi-round-executor.mjs +44 -0
- package/dist/execution/multicall-batcher.cjs +51 -0
- package/dist/execution/multicall-batcher.mjs +50 -0
- package/dist/execution/multicall.cjs +39 -0
- package/dist/execution/multicall.mjs +38 -0
- package/dist/execution/result-cache.cjs +63 -0
- package/dist/execution/result-cache.mjs +63 -0
- package/dist/execution/round-executor.cjs +81 -0
- package/dist/execution/round-executor.mjs +80 -0
- package/dist/execution/types.d.cts +58 -0
- package/dist/execution/types.d.mts +58 -0
- package/dist/factory.cjs +6 -0
- package/dist/factory.d.cts +7 -0
- package/dist/factory.d.mts +6 -0
- package/dist/factory.mjs +6 -0
- package/dist/index.cjs +18 -0
- package/dist/index.d.cts +7 -0
- package/dist/index.d.mts +7 -0
- package/dist/index.mjs +6 -0
- package/package.json +26 -19
- package/dist/analysis/call-collector.d.ts +0 -20
- package/dist/analysis/call-collector.d.ts.map +0 -1
- package/dist/analysis/call-collector.js +0 -272
- package/dist/analysis/dependency-analyzer.d.ts +0 -14
- package/dist/analysis/dependency-analyzer.d.ts.map +0 -1
- package/dist/analysis/dependency-analyzer.js +0 -76
- package/dist/analysis/index.d.ts +0 -2
- package/dist/analysis/index.d.ts.map +0 -1
- package/dist/analysis/index.js +0 -1
- package/dist/analysis/round-planner.d.ts +0 -32
- package/dist/analysis/round-planner.d.ts.map +0 -1
- package/dist/analysis/round-planner.js +0 -69
- package/dist/analysis/types.d.ts +0 -113
- package/dist/analysis/types.d.ts.map +0 -1
- package/dist/analysis/types.js +0 -1
- package/dist/debug.d.ts +0 -13
- package/dist/debug.d.ts.map +0 -1
- package/dist/debug.js +0 -12
- package/dist/environment/context.d.ts +0 -3
- package/dist/environment/context.d.ts.map +0 -1
- package/dist/environment/context.js +0 -8
- package/dist/environment/contract-caller.d.ts +0 -25
- package/dist/environment/contract-caller.d.ts.map +0 -1
- package/dist/environment/contract-caller.js +0 -85
- package/dist/environment/environment.d.ts +0 -81
- package/dist/environment/environment.d.ts.map +0 -1
- package/dist/environment/environment.js +0 -279
- package/dist/environment/error-wrapper.d.ts +0 -11
- package/dist/environment/error-wrapper.d.ts.map +0 -1
- package/dist/environment/error-wrapper.js +0 -33
- package/dist/environment/index.d.ts +0 -3
- package/dist/environment/index.d.ts.map +0 -1
- package/dist/environment/index.js +0 -2
- package/dist/environment/replay-cache.d.ts +0 -23
- package/dist/environment/replay-cache.d.ts.map +0 -1
- package/dist/environment/replay-cache.js +0 -51
- package/dist/environment/types.d.ts +0 -57
- package/dist/environment/types.d.ts.map +0 -1
- package/dist/environment/types.js +0 -1
- package/dist/errors/errors.d.ts +0 -63
- package/dist/errors/errors.d.ts.map +0 -1
- package/dist/errors/errors.js +0 -63
- package/dist/errors/index.d.ts +0 -2
- package/dist/errors/index.d.ts.map +0 -1
- package/dist/errors/index.js +0 -1
- package/dist/execution/index.d.ts +0 -2
- package/dist/execution/index.d.ts.map +0 -1
- package/dist/execution/index.js +0 -1
- package/dist/execution/multi-round-executor.d.ts +0 -17
- package/dist/execution/multi-round-executor.d.ts.map +0 -1
- package/dist/execution/multi-round-executor.js +0 -47
- package/dist/execution/multicall-batcher.d.ts +0 -14
- package/dist/execution/multicall-batcher.d.ts.map +0 -1
- package/dist/execution/multicall-batcher.js +0 -53
- package/dist/execution/multicall.d.ts +0 -42
- package/dist/execution/multicall.d.ts.map +0 -1
- package/dist/execution/multicall.js +0 -29
- package/dist/execution/result-cache.d.ts +0 -47
- package/dist/execution/result-cache.d.ts.map +0 -1
- package/dist/execution/result-cache.js +0 -65
- package/dist/execution/round-executor.d.ts +0 -18
- package/dist/execution/round-executor.d.ts.map +0 -1
- package/dist/execution/round-executor.js +0 -95
- package/dist/execution/types.d.ts +0 -55
- package/dist/execution/types.d.ts.map +0 -1
- package/dist/execution/types.js +0 -1
- package/dist/factory.d.ts +0 -3
- package/dist/factory.d.ts.map +0 -1
- package/dist/factory.js +0 -2
- package/dist/index.d.ts +0 -10
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -7
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require("../_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
const require_debug = require("../debug.cjs");
|
|
3
|
+
const require_errors = require("../errors/errors.cjs");
|
|
4
|
+
require("../errors/index.cjs");
|
|
5
|
+
const require_multicall = require("./multicall.cjs");
|
|
6
|
+
let viem_actions = require("viem/actions");
|
|
7
|
+
//#region src/execution/multicall-batcher.ts
|
|
8
|
+
const debug = require_debug.createLogger("execute:multicall");
|
|
9
|
+
var MulticallBatcher = class {
|
|
10
|
+
address;
|
|
11
|
+
batchSize;
|
|
12
|
+
constructor(client, options) {
|
|
13
|
+
this.client = client;
|
|
14
|
+
this.address = options?.address ?? "0xcA11bde05977b3631167028862bE2a173976CA11";
|
|
15
|
+
this.batchSize = options?.batchSize ?? 200;
|
|
16
|
+
}
|
|
17
|
+
async executeBatch(calls, blockNumber) {
|
|
18
|
+
if (calls.length === 0) return [];
|
|
19
|
+
if (calls.length <= this.batchSize) {
|
|
20
|
+
debug("batch: %d calls (single chunk)", calls.length);
|
|
21
|
+
return await this.executeChunk(calls, blockNumber);
|
|
22
|
+
}
|
|
23
|
+
debug("batch: %d calls (chunked, batchSize=%d)", calls.length, this.batchSize);
|
|
24
|
+
const results = [];
|
|
25
|
+
for (let i = 0; i < calls.length; i += this.batchSize) {
|
|
26
|
+
const chunk = calls.slice(i, i + this.batchSize);
|
|
27
|
+
debug("chunk %d/%d", i / this.batchSize + 1, Math.ceil(calls.length / this.batchSize));
|
|
28
|
+
const chunkResults = await this.executeChunk(chunk, blockNumber);
|
|
29
|
+
results.push(...chunkResults);
|
|
30
|
+
}
|
|
31
|
+
return results;
|
|
32
|
+
}
|
|
33
|
+
async executeChunk(calls, blockNumber) {
|
|
34
|
+
try {
|
|
35
|
+
return (await (0, viem_actions.readContract)(this.client, {
|
|
36
|
+
address: this.address,
|
|
37
|
+
abi: require_multicall.multicall3Abi,
|
|
38
|
+
functionName: "aggregate3",
|
|
39
|
+
args: [calls],
|
|
40
|
+
blockNumber
|
|
41
|
+
})).map((r) => ({
|
|
42
|
+
success: r.success,
|
|
43
|
+
returnData: r.returnData
|
|
44
|
+
}));
|
|
45
|
+
} catch (error) {
|
|
46
|
+
throw new require_errors.MulticallBatchError("Multicall3 aggregate3 call failed", { cause: error });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
//#endregion
|
|
51
|
+
exports.MulticallBatcher = MulticallBatcher;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { createLogger } from "../debug.mjs";
|
|
2
|
+
import { MulticallBatchError } from "../errors/errors.mjs";
|
|
3
|
+
import "../errors/index.mjs";
|
|
4
|
+
import { multicall3Abi } from "./multicall.mjs";
|
|
5
|
+
import { readContract } from "viem/actions";
|
|
6
|
+
//#region src/execution/multicall-batcher.ts
|
|
7
|
+
const debug = createLogger("execute:multicall");
|
|
8
|
+
var MulticallBatcher = class {
|
|
9
|
+
address;
|
|
10
|
+
batchSize;
|
|
11
|
+
constructor(client, options) {
|
|
12
|
+
this.client = client;
|
|
13
|
+
this.address = options?.address ?? "0xcA11bde05977b3631167028862bE2a173976CA11";
|
|
14
|
+
this.batchSize = options?.batchSize ?? 200;
|
|
15
|
+
}
|
|
16
|
+
async executeBatch(calls, blockNumber) {
|
|
17
|
+
if (calls.length === 0) return [];
|
|
18
|
+
if (calls.length <= this.batchSize) {
|
|
19
|
+
debug("batch: %d calls (single chunk)", calls.length);
|
|
20
|
+
return await this.executeChunk(calls, blockNumber);
|
|
21
|
+
}
|
|
22
|
+
debug("batch: %d calls (chunked, batchSize=%d)", calls.length, this.batchSize);
|
|
23
|
+
const results = [];
|
|
24
|
+
for (let i = 0; i < calls.length; i += this.batchSize) {
|
|
25
|
+
const chunk = calls.slice(i, i + this.batchSize);
|
|
26
|
+
debug("chunk %d/%d", i / this.batchSize + 1, Math.ceil(calls.length / this.batchSize));
|
|
27
|
+
const chunkResults = await this.executeChunk(chunk, blockNumber);
|
|
28
|
+
results.push(...chunkResults);
|
|
29
|
+
}
|
|
30
|
+
return results;
|
|
31
|
+
}
|
|
32
|
+
async executeChunk(calls, blockNumber) {
|
|
33
|
+
try {
|
|
34
|
+
return (await readContract(this.client, {
|
|
35
|
+
address: this.address,
|
|
36
|
+
abi: multicall3Abi,
|
|
37
|
+
functionName: "aggregate3",
|
|
38
|
+
args: [calls],
|
|
39
|
+
blockNumber
|
|
40
|
+
})).map((r) => ({
|
|
41
|
+
success: r.success,
|
|
42
|
+
returnData: r.returnData
|
|
43
|
+
}));
|
|
44
|
+
} catch (error) {
|
|
45
|
+
throw new MulticallBatchError("Multicall3 aggregate3 call failed", { cause: error });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
//#endregion
|
|
50
|
+
export { MulticallBatcher };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
//#region src/execution/multicall.ts
|
|
2
|
+
const MULTICALL3_ADDRESS = "0xcA11bde05977b3631167028862bE2a173976CA11";
|
|
3
|
+
const multicall3Abi = [{
|
|
4
|
+
name: "aggregate3",
|
|
5
|
+
type: "function",
|
|
6
|
+
stateMutability: "payable",
|
|
7
|
+
inputs: [{
|
|
8
|
+
name: "calls",
|
|
9
|
+
type: "tuple[]",
|
|
10
|
+
components: [
|
|
11
|
+
{
|
|
12
|
+
name: "target",
|
|
13
|
+
type: "address"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
name: "allowFailure",
|
|
17
|
+
type: "bool"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: "callData",
|
|
21
|
+
type: "bytes"
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}],
|
|
25
|
+
outputs: [{
|
|
26
|
+
name: "returnData",
|
|
27
|
+
type: "tuple[]",
|
|
28
|
+
components: [{
|
|
29
|
+
name: "success",
|
|
30
|
+
type: "bool"
|
|
31
|
+
}, {
|
|
32
|
+
name: "returnData",
|
|
33
|
+
type: "bytes"
|
|
34
|
+
}]
|
|
35
|
+
}]
|
|
36
|
+
}];
|
|
37
|
+
//#endregion
|
|
38
|
+
exports.MULTICALL3_ADDRESS = MULTICALL3_ADDRESS;
|
|
39
|
+
exports.multicall3Abi = multicall3Abi;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
//#region src/execution/multicall.ts
|
|
2
|
+
const MULTICALL3_ADDRESS = "0xcA11bde05977b3631167028862bE2a173976CA11";
|
|
3
|
+
const multicall3Abi = [{
|
|
4
|
+
name: "aggregate3",
|
|
5
|
+
type: "function",
|
|
6
|
+
stateMutability: "payable",
|
|
7
|
+
inputs: [{
|
|
8
|
+
name: "calls",
|
|
9
|
+
type: "tuple[]",
|
|
10
|
+
components: [
|
|
11
|
+
{
|
|
12
|
+
name: "target",
|
|
13
|
+
type: "address"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
name: "allowFailure",
|
|
17
|
+
type: "bool"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: "callData",
|
|
21
|
+
type: "bytes"
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}],
|
|
25
|
+
outputs: [{
|
|
26
|
+
name: "returnData",
|
|
27
|
+
type: "tuple[]",
|
|
28
|
+
components: [{
|
|
29
|
+
name: "success",
|
|
30
|
+
type: "bool"
|
|
31
|
+
}, {
|
|
32
|
+
name: "returnData",
|
|
33
|
+
type: "bytes"
|
|
34
|
+
}]
|
|
35
|
+
}]
|
|
36
|
+
}];
|
|
37
|
+
//#endregion
|
|
38
|
+
export { MULTICALL3_ADDRESS, multicall3Abi };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
//#region src/execution/result-cache.ts
|
|
2
|
+
/**
|
|
3
|
+
* Cache for storing contract call results during expression evaluation.
|
|
4
|
+
*
|
|
5
|
+
* Uses Map-based storage with deterministic call IDs for efficient
|
|
6
|
+
* lookup and deduplication of repeated contract calls.
|
|
7
|
+
*/
|
|
8
|
+
var ResultCache = class {
|
|
9
|
+
cache = /* @__PURE__ */ new Map();
|
|
10
|
+
/**
|
|
11
|
+
* Generate a deterministic call ID from contract details.
|
|
12
|
+
*
|
|
13
|
+
* The ID format is `contract:method:serializedArgs` where args are
|
|
14
|
+
* JSON-stringified with special handling for bigint values.
|
|
15
|
+
*
|
|
16
|
+
* @param contract - Contract name (e.g., "token", "vault")
|
|
17
|
+
* @param method - Method name (e.g., "balanceOf", "totalSupply")
|
|
18
|
+
* @param args - Method arguments
|
|
19
|
+
* @returns Deterministic call ID string
|
|
20
|
+
*/
|
|
21
|
+
generateCallId(contract, method, args) {
|
|
22
|
+
return `${contract}:${method}:${JSON.stringify(args, (_, v) => {
|
|
23
|
+
if (typeof v === "bigint") return `${String(v)}n`;
|
|
24
|
+
if (typeof v === "object" && v !== null && !Array.isArray(v)) return Object.fromEntries(Object.entries(v).sort(([a], [b]) => a.localeCompare(b)));
|
|
25
|
+
return v;
|
|
26
|
+
})}`;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Store a result in the cache.
|
|
30
|
+
*
|
|
31
|
+
* @param callId - The call ID (from generateCallId)
|
|
32
|
+
* @param result - The result to cache
|
|
33
|
+
*/
|
|
34
|
+
set(callId, result) {
|
|
35
|
+
this.cache.set(callId, result);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Retrieve a cached result.
|
|
39
|
+
*
|
|
40
|
+
* @param callId - The call ID to look up
|
|
41
|
+
* @returns The cached result, or undefined if not found
|
|
42
|
+
*/
|
|
43
|
+
get(callId) {
|
|
44
|
+
return this.cache.get(callId);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Check if a result is cached.
|
|
48
|
+
*
|
|
49
|
+
* @param callId - The call ID to check
|
|
50
|
+
* @returns true if cached, false otherwise
|
|
51
|
+
*/
|
|
52
|
+
has(callId) {
|
|
53
|
+
return this.cache.has(callId);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Clear all cached results.
|
|
57
|
+
*/
|
|
58
|
+
clear() {
|
|
59
|
+
this.cache.clear();
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
//#endregion
|
|
63
|
+
exports.ResultCache = ResultCache;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
//#region src/execution/result-cache.ts
|
|
2
|
+
/**
|
|
3
|
+
* Cache for storing contract call results during expression evaluation.
|
|
4
|
+
*
|
|
5
|
+
* Uses Map-based storage with deterministic call IDs for efficient
|
|
6
|
+
* lookup and deduplication of repeated contract calls.
|
|
7
|
+
*/
|
|
8
|
+
var ResultCache = class {
|
|
9
|
+
cache = /* @__PURE__ */ new Map();
|
|
10
|
+
/**
|
|
11
|
+
* Generate a deterministic call ID from contract details.
|
|
12
|
+
*
|
|
13
|
+
* The ID format is `contract:method:serializedArgs` where args are
|
|
14
|
+
* JSON-stringified with special handling for bigint values.
|
|
15
|
+
*
|
|
16
|
+
* @param contract - Contract name (e.g., "token", "vault")
|
|
17
|
+
* @param method - Method name (e.g., "balanceOf", "totalSupply")
|
|
18
|
+
* @param args - Method arguments
|
|
19
|
+
* @returns Deterministic call ID string
|
|
20
|
+
*/
|
|
21
|
+
generateCallId(contract, method, args) {
|
|
22
|
+
return `${contract}:${method}:${JSON.stringify(args, (_, v) => {
|
|
23
|
+
if (typeof v === "bigint") return `${String(v)}n`;
|
|
24
|
+
if (typeof v === "object" && v !== null && !Array.isArray(v)) return Object.fromEntries(Object.entries(v).sort(([a], [b]) => a.localeCompare(b)));
|
|
25
|
+
return v;
|
|
26
|
+
})}`;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Store a result in the cache.
|
|
30
|
+
*
|
|
31
|
+
* @param callId - The call ID (from generateCallId)
|
|
32
|
+
* @param result - The result to cache
|
|
33
|
+
*/
|
|
34
|
+
set(callId, result) {
|
|
35
|
+
this.cache.set(callId, result);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Retrieve a cached result.
|
|
39
|
+
*
|
|
40
|
+
* @param callId - The call ID to look up
|
|
41
|
+
* @returns The cached result, or undefined if not found
|
|
42
|
+
*/
|
|
43
|
+
get(callId) {
|
|
44
|
+
return this.cache.get(callId);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Check if a result is cached.
|
|
48
|
+
*
|
|
49
|
+
* @param callId - The call ID to check
|
|
50
|
+
* @returns true if cached, false otherwise
|
|
51
|
+
*/
|
|
52
|
+
has(callId) {
|
|
53
|
+
return this.cache.has(callId);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Clear all cached results.
|
|
57
|
+
*/
|
|
58
|
+
clear() {
|
|
59
|
+
this.cache.clear();
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
//#endregion
|
|
63
|
+
export { ResultCache };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
require("../_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
const require_debug = require("../debug.cjs");
|
|
3
|
+
const require_errors = require("../errors/errors.cjs");
|
|
4
|
+
require("../errors/index.cjs");
|
|
5
|
+
let viem = require("viem");
|
|
6
|
+
//#region src/execution/round-executor.ts
|
|
7
|
+
const debug = require_debug.createLogger("execute:round");
|
|
8
|
+
var RoundExecutor = class {
|
|
9
|
+
constructor(contracts, cache, batcher) {
|
|
10
|
+
this.contracts = contracts;
|
|
11
|
+
this.cache = cache;
|
|
12
|
+
this.batcher = batcher;
|
|
13
|
+
}
|
|
14
|
+
async executeRound(round, context) {
|
|
15
|
+
const encodedCalls = [];
|
|
16
|
+
let failedCallIndex;
|
|
17
|
+
let failedCallContract;
|
|
18
|
+
let failedCallMethod;
|
|
19
|
+
try {
|
|
20
|
+
for (const [i, call] of round.calls.entries()) {
|
|
21
|
+
failedCallIndex = i;
|
|
22
|
+
failedCallContract = call.contract;
|
|
23
|
+
failedCallMethod = call.method;
|
|
24
|
+
const contract = this.contracts.get(call.contract);
|
|
25
|
+
if (!contract) throw new Error(`No ABI registered for contract "${call.contract}"`);
|
|
26
|
+
const resolvedArgs = this.resolveArgs(call.args, context);
|
|
27
|
+
encodedCalls.push({
|
|
28
|
+
target: contract.address,
|
|
29
|
+
allowFailure: false,
|
|
30
|
+
callData: (0, viem.encodeFunctionData)({
|
|
31
|
+
abi: contract.abi,
|
|
32
|
+
functionName: call.method,
|
|
33
|
+
args: resolvedArgs
|
|
34
|
+
})
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
} catch (error) {
|
|
38
|
+
if (error instanceof require_errors.MulticallBatchError) throw error;
|
|
39
|
+
throw new require_errors.MulticallBatchError("Failed to encode call", {
|
|
40
|
+
cause: error,
|
|
41
|
+
failedCallIndex,
|
|
42
|
+
contractName: failedCallContract,
|
|
43
|
+
methodName: failedCallMethod
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
debug("encoding %d calls for multicall", encodedCalls.length);
|
|
47
|
+
const results = await this.batcher.executeBatch(encodedCalls, context.blockNumber);
|
|
48
|
+
for (const [i, call] of round.calls.entries()) {
|
|
49
|
+
const contract = this.contracts.get(call.contract);
|
|
50
|
+
if (!contract) throw new Error(`No ABI registered for contract "${call.contract}"`);
|
|
51
|
+
const result = results[i];
|
|
52
|
+
if (!result?.success) throw new require_errors.MulticallBatchError(`Call failed: ${call.contract}.${call.method}`, {
|
|
53
|
+
failedCallIndex: i,
|
|
54
|
+
contractName: call.contract,
|
|
55
|
+
methodName: call.method
|
|
56
|
+
});
|
|
57
|
+
const decoded = (0, viem.decodeFunctionResult)({
|
|
58
|
+
abi: contract.abi,
|
|
59
|
+
functionName: call.method,
|
|
60
|
+
data: result.returnData
|
|
61
|
+
});
|
|
62
|
+
debug("decoded %s.%s -> %o", call.contract, call.method, decoded);
|
|
63
|
+
this.cache.set(call.id, decoded);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
resolveArgs(args, context) {
|
|
67
|
+
return args.map((arg) => {
|
|
68
|
+
if (arg.type === "literal") return arg.value;
|
|
69
|
+
if (arg.type === "variable") {
|
|
70
|
+
const name = arg.variableName;
|
|
71
|
+
if (!name) return;
|
|
72
|
+
return context.variables[name];
|
|
73
|
+
}
|
|
74
|
+
const id = arg.dependsOnCallId;
|
|
75
|
+
if (!id) return;
|
|
76
|
+
return this.cache.get(id);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
//#endregion
|
|
81
|
+
exports.RoundExecutor = RoundExecutor;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { createLogger } from "../debug.mjs";
|
|
2
|
+
import { MulticallBatchError } from "../errors/errors.mjs";
|
|
3
|
+
import "../errors/index.mjs";
|
|
4
|
+
import { decodeFunctionResult, encodeFunctionData } from "viem";
|
|
5
|
+
//#region src/execution/round-executor.ts
|
|
6
|
+
const debug = createLogger("execute:round");
|
|
7
|
+
var RoundExecutor = class {
|
|
8
|
+
constructor(contracts, cache, batcher) {
|
|
9
|
+
this.contracts = contracts;
|
|
10
|
+
this.cache = cache;
|
|
11
|
+
this.batcher = batcher;
|
|
12
|
+
}
|
|
13
|
+
async executeRound(round, context) {
|
|
14
|
+
const encodedCalls = [];
|
|
15
|
+
let failedCallIndex;
|
|
16
|
+
let failedCallContract;
|
|
17
|
+
let failedCallMethod;
|
|
18
|
+
try {
|
|
19
|
+
for (const [i, call] of round.calls.entries()) {
|
|
20
|
+
failedCallIndex = i;
|
|
21
|
+
failedCallContract = call.contract;
|
|
22
|
+
failedCallMethod = call.method;
|
|
23
|
+
const contract = this.contracts.get(call.contract);
|
|
24
|
+
if (!contract) throw new Error(`No ABI registered for contract "${call.contract}"`);
|
|
25
|
+
const resolvedArgs = this.resolveArgs(call.args, context);
|
|
26
|
+
encodedCalls.push({
|
|
27
|
+
target: contract.address,
|
|
28
|
+
allowFailure: false,
|
|
29
|
+
callData: encodeFunctionData({
|
|
30
|
+
abi: contract.abi,
|
|
31
|
+
functionName: call.method,
|
|
32
|
+
args: resolvedArgs
|
|
33
|
+
})
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (error instanceof MulticallBatchError) throw error;
|
|
38
|
+
throw new MulticallBatchError("Failed to encode call", {
|
|
39
|
+
cause: error,
|
|
40
|
+
failedCallIndex,
|
|
41
|
+
contractName: failedCallContract,
|
|
42
|
+
methodName: failedCallMethod
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
debug("encoding %d calls for multicall", encodedCalls.length);
|
|
46
|
+
const results = await this.batcher.executeBatch(encodedCalls, context.blockNumber);
|
|
47
|
+
for (const [i, call] of round.calls.entries()) {
|
|
48
|
+
const contract = this.contracts.get(call.contract);
|
|
49
|
+
if (!contract) throw new Error(`No ABI registered for contract "${call.contract}"`);
|
|
50
|
+
const result = results[i];
|
|
51
|
+
if (!result?.success) throw new MulticallBatchError(`Call failed: ${call.contract}.${call.method}`, {
|
|
52
|
+
failedCallIndex: i,
|
|
53
|
+
contractName: call.contract,
|
|
54
|
+
methodName: call.method
|
|
55
|
+
});
|
|
56
|
+
const decoded = decodeFunctionResult({
|
|
57
|
+
abi: contract.abi,
|
|
58
|
+
functionName: call.method,
|
|
59
|
+
data: result.returnData
|
|
60
|
+
});
|
|
61
|
+
debug("decoded %s.%s -> %o", call.contract, call.method, decoded);
|
|
62
|
+
this.cache.set(call.id, decoded);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
resolveArgs(args, context) {
|
|
66
|
+
return args.map((arg) => {
|
|
67
|
+
if (arg.type === "literal") return arg.value;
|
|
68
|
+
if (arg.type === "variable") {
|
|
69
|
+
const name = arg.variableName;
|
|
70
|
+
if (!name) return;
|
|
71
|
+
return context.variables[name];
|
|
72
|
+
}
|
|
73
|
+
const id = arg.dependsOnCallId;
|
|
74
|
+
if (!id) return;
|
|
75
|
+
return this.cache.get(id);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
//#endregion
|
|
80
|
+
export { RoundExecutor };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { PublicClient } from "viem";
|
|
2
|
+
|
|
3
|
+
//#region src/execution/types.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Metadata about the execution.
|
|
6
|
+
* Contains statistics and block information from the execution run.
|
|
7
|
+
*/
|
|
8
|
+
interface ExecutionMeta {
|
|
9
|
+
/** Number of rounds executed (topological depth) */
|
|
10
|
+
roundsExecuted: number;
|
|
11
|
+
/** Total number of contract calls executed */
|
|
12
|
+
totalCalls: number;
|
|
13
|
+
/** Block number at which calls were executed */
|
|
14
|
+
blockNumber: bigint;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Result of executing an SEL expression with contract calls.
|
|
18
|
+
* Maps call IDs to their decoded results.
|
|
19
|
+
*/
|
|
20
|
+
interface ExecutionResult {
|
|
21
|
+
/** Map of callId to decoded result value */
|
|
22
|
+
results: Map<string, unknown>;
|
|
23
|
+
/** Execution metadata */
|
|
24
|
+
meta: ExecutionMeta;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Context passed to the executor for running contract calls.
|
|
28
|
+
* Contains the client, block number, and variable bindings.
|
|
29
|
+
*/
|
|
30
|
+
interface ExecutionContext {
|
|
31
|
+
/** Viem public client for making contract calls */
|
|
32
|
+
client: PublicClient;
|
|
33
|
+
/** Block number for consistent reads across all calls */
|
|
34
|
+
blockNumber: bigint;
|
|
35
|
+
/** Variable name to value mapping from evaluate() context */
|
|
36
|
+
variables: Record<string, unknown>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Options for the evaluate() call.
|
|
40
|
+
*/
|
|
41
|
+
interface EvaluateOptions {
|
|
42
|
+
/** Override viem client for this evaluation */
|
|
43
|
+
client?: PublicClient;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Result of evaluating a SEL expression.
|
|
47
|
+
*
|
|
48
|
+
* Always returned by `evaluate()`. The `meta` field is present when
|
|
49
|
+
* contract calls were executed, absent for pure CEL expressions.
|
|
50
|
+
*/
|
|
51
|
+
interface EvaluateResult<T = unknown> {
|
|
52
|
+
/** The evaluated result value */
|
|
53
|
+
value: T;
|
|
54
|
+
/** Execution metadata, present when contract calls were executed */
|
|
55
|
+
meta?: ExecutionMeta;
|
|
56
|
+
}
|
|
57
|
+
//#endregion
|
|
58
|
+
export { EvaluateOptions, EvaluateResult, ExecutionContext, ExecutionMeta, ExecutionResult };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { PublicClient } from "viem";
|
|
2
|
+
|
|
3
|
+
//#region src/execution/types.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Metadata about the execution.
|
|
6
|
+
* Contains statistics and block information from the execution run.
|
|
7
|
+
*/
|
|
8
|
+
interface ExecutionMeta {
|
|
9
|
+
/** Number of rounds executed (topological depth) */
|
|
10
|
+
roundsExecuted: number;
|
|
11
|
+
/** Total number of contract calls executed */
|
|
12
|
+
totalCalls: number;
|
|
13
|
+
/** Block number at which calls were executed */
|
|
14
|
+
blockNumber: bigint;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Result of executing an SEL expression with contract calls.
|
|
18
|
+
* Maps call IDs to their decoded results.
|
|
19
|
+
*/
|
|
20
|
+
interface ExecutionResult {
|
|
21
|
+
/** Map of callId to decoded result value */
|
|
22
|
+
results: Map<string, unknown>;
|
|
23
|
+
/** Execution metadata */
|
|
24
|
+
meta: ExecutionMeta;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Context passed to the executor for running contract calls.
|
|
28
|
+
* Contains the client, block number, and variable bindings.
|
|
29
|
+
*/
|
|
30
|
+
interface ExecutionContext {
|
|
31
|
+
/** Viem public client for making contract calls */
|
|
32
|
+
client: PublicClient;
|
|
33
|
+
/** Block number for consistent reads across all calls */
|
|
34
|
+
blockNumber: bigint;
|
|
35
|
+
/** Variable name to value mapping from evaluate() context */
|
|
36
|
+
variables: Record<string, unknown>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Options for the evaluate() call.
|
|
40
|
+
*/
|
|
41
|
+
interface EvaluateOptions {
|
|
42
|
+
/** Override viem client for this evaluation */
|
|
43
|
+
client?: PublicClient;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Result of evaluating a SEL expression.
|
|
47
|
+
*
|
|
48
|
+
* Always returned by `evaluate()`. The `meta` field is present when
|
|
49
|
+
* contract calls were executed, absent for pure CEL expressions.
|
|
50
|
+
*/
|
|
51
|
+
interface EvaluateResult<T = unknown> {
|
|
52
|
+
/** The evaluated result value */
|
|
53
|
+
value: T;
|
|
54
|
+
/** Execution metadata, present when contract calls were executed */
|
|
55
|
+
meta?: ExecutionMeta;
|
|
56
|
+
}
|
|
57
|
+
//#endregion
|
|
58
|
+
export { EvaluateOptions, EvaluateResult, ExecutionContext, ExecutionMeta, ExecutionResult };
|
package/dist/factory.cjs
ADDED
package/dist/factory.mjs
ADDED
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
require("./_virtual/_rolldown/runtime.cjs");
|
|
3
|
+
const require_errors = require("./errors/errors.cjs");
|
|
4
|
+
require("./errors/index.cjs");
|
|
5
|
+
const require_environment = require("./environment/environment.cjs");
|
|
6
|
+
require("./environment/index.cjs");
|
|
7
|
+
const require_factory = require("./factory.cjs");
|
|
8
|
+
let _seljs_common = require("@seljs/common");
|
|
9
|
+
exports.CircularDependencyError = require_errors.CircularDependencyError;
|
|
10
|
+
exports.ExecutionLimitError = require_errors.ExecutionLimitError;
|
|
11
|
+
exports.MulticallBatchError = require_errors.MulticallBatchError;
|
|
12
|
+
exports.SELContractError = require_errors.SELContractError;
|
|
13
|
+
exports.SELError = _seljs_common.SELError;
|
|
14
|
+
exports.SELEvaluationError = require_errors.SELEvaluationError;
|
|
15
|
+
exports.SELParseError = _seljs_common.SELParseError;
|
|
16
|
+
exports.SELRuntime = require_environment.SELRuntime;
|
|
17
|
+
exports.SELTypeError = _seljs_common.SELTypeError;
|
|
18
|
+
exports.createSEL = require_factory.createSEL;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { MulticallOptions, SELLimits, SELRuntimeConfig } from "./environment/types.cjs";
|
|
2
|
+
import { EvaluateOptions, EvaluateResult, ExecutionContext, ExecutionMeta, ExecutionResult } from "./execution/types.cjs";
|
|
3
|
+
import { SELRuntime } from "./environment/environment.cjs";
|
|
4
|
+
import { CircularDependencyError, ExecutionLimitError, MulticallBatchError, SELContractError, SELError, SELEvaluationError, SELParseError, SELTypeError } from "./errors/errors.cjs";
|
|
5
|
+
import { createSEL } from "./factory.cjs";
|
|
6
|
+
import { CallArgument, CollectedCall, DependencyGraph, ExecutionPlan, ExecutionRound, GraphNode } from "./analysis/types.cjs";
|
|
7
|
+
export { CallArgument, CircularDependencyError, CollectedCall, DependencyGraph, EvaluateOptions, EvaluateResult, ExecutionContext, ExecutionLimitError, ExecutionMeta, ExecutionPlan, ExecutionResult, ExecutionRound, GraphNode, MulticallBatchError, MulticallOptions, SELContractError, SELError, SELEvaluationError, SELLimits, SELParseError, SELRuntime, SELRuntimeConfig, SELTypeError, createSEL };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { MulticallOptions, SELLimits, SELRuntimeConfig } from "./environment/types.mjs";
|
|
2
|
+
import { EvaluateOptions, EvaluateResult, ExecutionContext, ExecutionMeta, ExecutionResult } from "./execution/types.mjs";
|
|
3
|
+
import { SELRuntime } from "./environment/environment.mjs";
|
|
4
|
+
import { CircularDependencyError, ExecutionLimitError, MulticallBatchError, SELContractError, SELError, SELEvaluationError, SELParseError, SELTypeError } from "./errors/errors.mjs";
|
|
5
|
+
import { createSEL } from "./factory.mjs";
|
|
6
|
+
import { CallArgument, CollectedCall, DependencyGraph, ExecutionPlan, ExecutionRound, GraphNode } from "./analysis/types.mjs";
|
|
7
|
+
export { CallArgument, CircularDependencyError, CollectedCall, DependencyGraph, EvaluateOptions, EvaluateResult, ExecutionContext, ExecutionLimitError, ExecutionMeta, ExecutionPlan, ExecutionResult, ExecutionRound, GraphNode, MulticallBatchError, MulticallOptions, SELContractError, SELError, SELEvaluationError, SELLimits, SELParseError, SELRuntime, SELRuntimeConfig, SELTypeError, createSEL };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { CircularDependencyError, ExecutionLimitError, MulticallBatchError, SELContractError, SELError, SELEvaluationError, SELParseError, SELTypeError } from "./errors/errors.mjs";
|
|
2
|
+
import "./errors/index.mjs";
|
|
3
|
+
import { SELRuntime } from "./environment/environment.mjs";
|
|
4
|
+
import "./environment/index.mjs";
|
|
5
|
+
import { createSEL } from "./factory.mjs";
|
|
6
|
+
export { CircularDependencyError, ExecutionLimitError, MulticallBatchError, SELContractError, SELError, SELEvaluationError, SELParseError, SELRuntime, SELTypeError, createSEL };
|