@seljs/checker 1.3.0-beta.3 → 1.3.0-beta.33

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.
@@ -25,12 +25,7 @@ var CelCodecRegistry = class {
25
25
  this.codecs.set("bool", zod.z.boolean());
26
26
  this.codecs.set("string", zod.z.string());
27
27
  this.codecs.set("int", zod.z.bigint());
28
- this.codecs.set("bytes", zod.z.union([zod.z.instanceof(Uint8Array), zod.z.string().transform((s) => {
29
- const hex = s.startsWith("0x") ? s.slice(2) : s;
30
- const bytes = new Uint8Array(hex.length / 2);
31
- for (let i = 0; i < bytes.length; i++) bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
32
- return bytes;
33
- })]));
28
+ this.codecs.set("bytes", zod.z.union([zod.z.instanceof(Uint8Array), zod.z.string().transform((s) => (0, _seljs_types.hexToBytes)(s))]));
34
29
  this.codecs.set("dyn", zod.z.unknown().transform((v) => typeof v === "bigint" ? new _seljs_types.SolidityIntTypeWrapper(v) : v));
35
30
  for (const desc of options?.structs ?? []) {
36
31
  this.codecs.set(desc.name, this.buildStructCodec(desc));
@@ -1,4 +1,4 @@
1
- import { SolidityAddressTypeWrapper, SolidityIntTypeWrapper } from "@seljs/types";
1
+ import { SolidityAddressTypeWrapper, SolidityIntTypeWrapper, hexToBytes } from "@seljs/types";
2
2
  import { z } from "zod";
3
3
  //#region src/environment/codec-registry.ts
4
4
  const solidityAddressCodec = z.codec(z.string(), z.instanceof(SolidityAddressTypeWrapper), {
@@ -24,12 +24,7 @@ var CelCodecRegistry = class {
24
24
  this.codecs.set("bool", z.boolean());
25
25
  this.codecs.set("string", z.string());
26
26
  this.codecs.set("int", z.bigint());
27
- this.codecs.set("bytes", z.union([z.instanceof(Uint8Array), z.string().transform((s) => {
28
- const hex = s.startsWith("0x") ? s.slice(2) : s;
29
- const bytes = new Uint8Array(hex.length / 2);
30
- for (let i = 0; i < bytes.length; i++) bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
31
- return bytes;
32
- })]));
27
+ this.codecs.set("bytes", z.union([z.instanceof(Uint8Array), z.string().transform((s) => hexToBytes(s))]));
33
28
  this.codecs.set("dyn", z.unknown().transform((v) => typeof v === "bigint" ? new SolidityIntTypeWrapper(v) : v));
34
29
  for (const desc of options?.structs ?? []) {
35
30
  this.codecs.set(desc.name, this.buildStructCodec(desc));
@@ -50,7 +50,7 @@ const hydrateEnvironment = (env, schema, handler) => {
50
50
  const returnType = method.returns || "dyn";
51
51
  const methodHandler = handler !== void 0 ? async (...args) => {
52
52
  const raw = await handler(contract.name, method.name, args.slice(1));
53
- if (!codecRegistry) throw new Error("codecRegistry is required when handler is provided");
53
+ if (!codecRegistry) throw new _seljs_common.SELConfigError("codecRegistry is required when handler is provided", { setting: "codecRegistry" });
54
54
  return codecRegistry.resolve(returnType).parse(raw);
55
55
  } : () => void 0;
56
56
  try {
@@ -93,7 +93,7 @@ const hydrateEnvironment = (env, schema, handler) => {
93
93
  if (!fn.receiverType) continue;
94
94
  const fnHandler = handler !== void 0 ? async (...args) => {
95
95
  const raw = await handler(fn.receiverType, fn.name, args);
96
- if (!codecRegistry) throw new Error("codecRegistry is required when handler is provided");
96
+ if (!codecRegistry) throw new _seljs_common.SELConfigError("codecRegistry is required when handler is provided", { setting: "codecRegistry" });
97
97
  return codecRegistry.resolve(fn.returns).parse(raw);
98
98
  } : () => void 0;
99
99
  try {
@@ -155,7 +155,7 @@ const createRuntimeEnvironment = (schema, handler, options) => {
155
155
  });
156
156
  require_register_types.registerSolidityTypes(env);
157
157
  const result = hydrateEnvironment(env, schema, handler);
158
- if (!result.codecRegistry) throw new Error("codecRegistry is required when handler is provided");
158
+ if (!result.codecRegistry) throw new _seljs_common.SELConfigError("codecRegistry is required when handler is provided", { setting: "codecRegistry" });
159
159
  return {
160
160
  env,
161
161
  contractBindings: result.contractBindings,
@@ -2,7 +2,7 @@ import { createLogger } from "../debug.mjs";
2
2
  import { CelCodecRegistry } from "./codec-registry.mjs";
3
3
  import { registerSolidityTypes } from "./register-types.mjs";
4
4
  import { toCelLiteralType } from "./value-wrappers.mjs";
5
- import { contractTypeName } from "@seljs/common";
5
+ import { SELConfigError, contractTypeName } from "@seljs/common";
6
6
  import { Environment } from "@marcbachmann/cel-js";
7
7
  //#region src/environment/hydrate.ts
8
8
  const debug = createLogger("hydrate");
@@ -49,7 +49,7 @@ const hydrateEnvironment = (env, schema, handler) => {
49
49
  const returnType = method.returns || "dyn";
50
50
  const methodHandler = handler !== void 0 ? async (...args) => {
51
51
  const raw = await handler(contract.name, method.name, args.slice(1));
52
- if (!codecRegistry) throw new Error("codecRegistry is required when handler is provided");
52
+ if (!codecRegistry) throw new SELConfigError("codecRegistry is required when handler is provided", { setting: "codecRegistry" });
53
53
  return codecRegistry.resolve(returnType).parse(raw);
54
54
  } : () => void 0;
55
55
  try {
@@ -92,7 +92,7 @@ const hydrateEnvironment = (env, schema, handler) => {
92
92
  if (!fn.receiverType) continue;
93
93
  const fnHandler = handler !== void 0 ? async (...args) => {
94
94
  const raw = await handler(fn.receiverType, fn.name, args);
95
- if (!codecRegistry) throw new Error("codecRegistry is required when handler is provided");
95
+ if (!codecRegistry) throw new SELConfigError("codecRegistry is required when handler is provided", { setting: "codecRegistry" });
96
96
  return codecRegistry.resolve(fn.returns).parse(raw);
97
97
  } : () => void 0;
98
98
  try {
@@ -154,7 +154,7 @@ const createRuntimeEnvironment = (schema, handler, options) => {
154
154
  });
155
155
  registerSolidityTypes(env);
156
156
  const result = hydrateEnvironment(env, schema, handler);
157
- if (!result.codecRegistry) throw new Error("codecRegistry is required when handler is provided");
157
+ if (!result.codecRegistry) throw new SELConfigError("codecRegistry is required when handler is provided", { setting: "codecRegistry" });
158
158
  return {
159
159
  env,
160
160
  contractBindings: result.contractBindings,
@@ -1,5 +1,7 @@
1
1
  require("../_virtual/_rolldown/runtime.cjs");
2
+ let _seljs_common = require("@seljs/common");
2
3
  let _seljs_types = require("@seljs/types");
4
+ let viem = require("viem");
3
5
  //#region src/environment/register-types.ts
4
6
  /**
5
7
  * Try to register an operator, silently ignoring "already registered" errors.
@@ -27,12 +29,12 @@ const registerIntegerOperators = (env) => {
27
29
  env.registerOperator("sol_int * sol_int", (a, b) => toSolInt((0, _seljs_types.toBigInt)(a) * (0, _seljs_types.toBigInt)(b)));
28
30
  env.registerOperator("sol_int / sol_int", (a, b) => {
29
31
  const divisor = (0, _seljs_types.toBigInt)(b);
30
- if (divisor === 0n) throw new Error("division by zero");
32
+ if (divisor === 0n) throw new _seljs_common.SELEvaluationError("division by zero");
31
33
  return toSolInt((0, _seljs_types.toBigInt)(a) / divisor);
32
34
  });
33
35
  env.registerOperator("sol_int % sol_int", (a, b) => {
34
36
  const divisor = (0, _seljs_types.toBigInt)(b);
35
- if (divisor === 0n) throw new Error("modulo by zero");
37
+ if (divisor === 0n) throw new _seljs_common.SELEvaluationError("modulo by zero");
36
38
  return toSolInt((0, _seljs_types.toBigInt)(a) % divisor);
37
39
  });
38
40
  env.registerOperator("-sol_int", (a) => toSolInt(-(0, _seljs_types.toBigInt)(a)));
@@ -46,12 +48,25 @@ const registerIntegerOperators = (env) => {
46
48
  tryRegisterOperator(env, "sol_int * int", (a, b) => toSolInt((0, _seljs_types.toBigInt)(a) * (0, _seljs_types.toBigInt)(b)));
47
49
  tryRegisterOperator(env, "sol_int / int", (a, b) => {
48
50
  const divisor = (0, _seljs_types.toBigInt)(b);
49
- if (divisor === 0n) throw new Error("division by zero");
51
+ if (divisor === 0n) throw new _seljs_common.SELEvaluationError("division by zero");
50
52
  return toSolInt((0, _seljs_types.toBigInt)(a) / divisor);
51
53
  });
52
54
  tryRegisterOperator(env, "sol_int % int", (a, b) => {
53
55
  const divisor = (0, _seljs_types.toBigInt)(b);
54
- if (divisor === 0n) throw new Error("modulo by zero");
56
+ if (divisor === 0n) throw new _seljs_common.SELEvaluationError("modulo by zero");
57
+ return toSolInt((0, _seljs_types.toBigInt)(a) % divisor);
58
+ });
59
+ tryRegisterOperator(env, "int + sol_int: sol_int", (a, b) => toSolInt((0, _seljs_types.toBigInt)(a) + (0, _seljs_types.toBigInt)(b)));
60
+ tryRegisterOperator(env, "int - sol_int: sol_int", (a, b) => toSolInt((0, _seljs_types.toBigInt)(a) - (0, _seljs_types.toBigInt)(b)));
61
+ tryRegisterOperator(env, "int * sol_int: sol_int", (a, b) => toSolInt((0, _seljs_types.toBigInt)(a) * (0, _seljs_types.toBigInt)(b)));
62
+ tryRegisterOperator(env, "int / sol_int: sol_int", (a, b) => {
63
+ const divisor = (0, _seljs_types.toBigInt)(b);
64
+ if (divisor === 0n) throw new _seljs_common.SELEvaluationError("division by zero");
65
+ return toSolInt((0, _seljs_types.toBigInt)(a) / divisor);
66
+ });
67
+ tryRegisterOperator(env, "int % sol_int: sol_int", (a, b) => {
68
+ const divisor = (0, _seljs_types.toBigInt)(b);
69
+ if (divisor === 0n) throw new _seljs_common.SELEvaluationError("modulo by zero");
55
70
  return toSolInt((0, _seljs_types.toBigInt)(a) % divisor);
56
71
  });
57
72
  tryRegisterOperator(env, "sol_int == int", (a, b) => (0, _seljs_types.toBigInt)(a) === (0, _seljs_types.toBigInt)(b));
@@ -78,11 +93,17 @@ const registerSolidityTypes = (env) => {
78
93
  for (const sig of entry.castSignatures) env.registerFunction(sig, (value) => new Ctor(value));
79
94
  }
80
95
  env.registerFunction("parseUnits(string, int): sol_int", (value, decimals) => (0, _seljs_types.parseUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
96
+ env.registerFunction("parseUnits(string, sol_int): sol_int", (value, decimals) => (0, _seljs_types.parseUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
81
97
  env.registerFunction("parseUnits(int, int): sol_int", (value, decimals) => (0, _seljs_types.parseUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
98
+ env.registerFunction("parseUnits(int, sol_int): sol_int", (value, decimals) => (0, _seljs_types.parseUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
82
99
  env.registerFunction("parseUnits(double, int): sol_int", (value, decimals) => (0, _seljs_types.parseUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
100
+ env.registerFunction("parseUnits(double, sol_int): sol_int", (value, decimals) => (0, _seljs_types.parseUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
83
101
  env.registerFunction("parseUnits(sol_int, int): sol_int", (value, decimals) => (0, _seljs_types.parseUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
102
+ env.registerFunction("parseUnits(sol_int, sol_int): sol_int", (value, decimals) => (0, _seljs_types.parseUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
84
103
  env.registerFunction("formatUnits(sol_int, int): double", (value, decimals) => (0, _seljs_types.formatUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
104
+ env.registerFunction("formatUnits(sol_int, sol_int): double", (value, decimals) => (0, _seljs_types.formatUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
85
105
  env.registerFunction("formatUnits(int, int): double", (value, decimals) => (0, _seljs_types.formatUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
106
+ env.registerFunction("formatUnits(int, sol_int): double", (value, decimals) => (0, _seljs_types.formatUnitsValue)(value, Number((0, _seljs_types.toBigInt)(decimals))));
86
107
  env.registerFunction("min(sol_int, sol_int): sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) <= (0, _seljs_types.toBigInt)(b) ? toSolInt(a) : toSolInt(b));
87
108
  env.registerFunction("min(sol_int, int): sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) <= (0, _seljs_types.toBigInt)(b) ? toSolInt(a) : toSolInt(b));
88
109
  env.registerFunction("min(int, sol_int): sol_int", (a, b) => (0, _seljs_types.toBigInt)(a) <= (0, _seljs_types.toBigInt)(b) ? toSolInt(a) : toSolInt(b));
@@ -99,9 +120,65 @@ const registerSolidityTypes = (env) => {
99
120
  const v = (0, _seljs_types.toBigInt)(a);
100
121
  return toSolInt(v < 0n ? -v : v);
101
122
  });
123
+ const registerListSolIntReducer = (name, handler) => {
124
+ env.registerFunction({
125
+ name,
126
+ receiverType: "list<sol_int>",
127
+ returnType: "sol_int",
128
+ params: []
129
+ }, handler);
130
+ };
131
+ registerListSolIntReducer("sum", (list) => {
132
+ let total = 0n;
133
+ for (const item of list) total += (0, _seljs_types.toBigInt)(item);
134
+ return toSolInt(total);
135
+ });
136
+ registerListSolIntReducer("min", (list) => {
137
+ const items = list;
138
+ if (items.length === 0) throw new _seljs_common.SELEvaluationError("list<sol_int>.min(): list is empty");
139
+ let smallest = (0, _seljs_types.toBigInt)(items[0]);
140
+ for (let i = 1; i < items.length; i++) {
141
+ const v = (0, _seljs_types.toBigInt)(items[i]);
142
+ if (v < smallest) smallest = v;
143
+ }
144
+ return toSolInt(smallest);
145
+ });
146
+ registerListSolIntReducer("max", (list) => {
147
+ const items = list;
148
+ if (items.length === 0) throw new _seljs_common.SELEvaluationError("list<sol_int>.max(): list is empty");
149
+ let largest = (0, _seljs_types.toBigInt)(items[0]);
150
+ for (let i = 1; i < items.length; i++) {
151
+ const v = (0, _seljs_types.toBigInt)(items[i]);
152
+ if (v > largest) largest = v;
153
+ }
154
+ return toSolInt(largest);
155
+ });
102
156
  const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
103
157
  env.registerFunction("isZeroAddress(sol_address): bool", (addr) => (0, _seljs_types.toAddress)(addr) === ZERO_ADDRESS);
104
158
  env.registerFunction("isZeroAddress(string): bool", (addr) => (0, _seljs_types.toAddress)(addr) === ZERO_ADDRESS);
159
+ env.registerFunction("hexBytes(string): bytes", (hex) => (0, _seljs_types.hexToBytes)(hex));
160
+ env.registerFunction("hexBytes(string, int): bytes", (hex, length) => {
161
+ const out = (0, _seljs_types.hexToBytes)(hex);
162
+ const expected = Number((0, _seljs_types.toBigInt)(length));
163
+ if (out.length !== expected) throw new _seljs_common.SELEvaluationError(`hexBytes: expected ${String(expected)} bytes, got ${String(out.length)}`);
164
+ return out;
165
+ });
166
+ env.registerFunction("keccak256(string): bytes", (value) => (0, _seljs_types.hexToBytes)((0, viem.keccak256)((0, viem.toBytes)(value))));
167
+ env.registerFunction("keccak256(bytes): bytes", (value) => (0, _seljs_types.hexToBytes)((0, viem.keccak256)(value)));
168
+ class SelNamespace {}
169
+ const selFields = {};
170
+ const selValues = {};
171
+ for (const constant of _seljs_types.EVM_CONSTANTS) {
172
+ selFields[constant.name] = constant.type;
173
+ if (constant.type === "sol_int") selValues[constant.name] = new _seljs_types.SolidityIntTypeWrapper(constant.value);
174
+ else if (constant.type === "sol_address") selValues[constant.name] = new _seljs_types.SolidityAddressTypeWrapper(constant.value);
175
+ else selValues[constant.name] = constant.value;
176
+ }
177
+ env.registerType("SelNamespace", {
178
+ ctor: SelNamespace,
179
+ fields: selFields
180
+ });
181
+ env.registerConstant("sel", "SelNamespace", Object.assign(new SelNamespace(), selValues));
105
182
  };
106
183
  //#endregion
107
184
  exports.registerSolidityTypes = registerSolidityTypes;
@@ -6,7 +6,7 @@ import { Environment } from "@marcbachmann/cel-js";
6
6
  * Mirrors the parameter signatures from Environment but drops the return type
7
7
  * to void — registerSolidityTypes never chains the return value.
8
8
  */
9
- type SolidityTypeHost = { [K in "registerType" | "registerOperator" | "registerFunction"]: (...args: Parameters<Environment[K]>) => void };
9
+ type SolidityTypeHost = { [K in "registerType" | "registerOperator" | "registerFunction" | "registerConstant"]: (...args: Parameters<Environment[K]>) => void };
10
10
  /**
11
11
  * Register all Solidity primitive types on a CEL Environment.
12
12
  */
@@ -6,7 +6,7 @@ import { Environment } from "@marcbachmann/cel-js";
6
6
  * Mirrors the parameter signatures from Environment but drops the return type
7
7
  * to void — registerSolidityTypes never chains the return value.
8
8
  */
9
- type SolidityTypeHost = { [K in "registerType" | "registerOperator" | "registerFunction"]: (...args: Parameters<Environment[K]>) => void };
9
+ type SolidityTypeHost = { [K in "registerType" | "registerOperator" | "registerFunction" | "registerConstant"]: (...args: Parameters<Environment[K]>) => void };
10
10
  /**
11
11
  * Register all Solidity primitive types on a CEL Environment.
12
12
  */
@@ -1,4 +1,6 @@
1
- import { SOLIDITY_TYPES, SolidityIntTypeWrapper, formatUnitsValue, parseUnitsValue, toAddress, toBigInt } from "@seljs/types";
1
+ import { SELEvaluationError } from "@seljs/common";
2
+ import { EVM_CONSTANTS, SOLIDITY_TYPES, SolidityAddressTypeWrapper, SolidityIntTypeWrapper, formatUnitsValue, hexToBytes, parseUnitsValue, toAddress, toBigInt } from "@seljs/types";
3
+ import { keccak256, toBytes } from "viem";
2
4
  //#region src/environment/register-types.ts
3
5
  /**
4
6
  * Try to register an operator, silently ignoring "already registered" errors.
@@ -26,12 +28,12 @@ const registerIntegerOperators = (env) => {
26
28
  env.registerOperator("sol_int * sol_int", (a, b) => toSolInt(toBigInt(a) * toBigInt(b)));
27
29
  env.registerOperator("sol_int / sol_int", (a, b) => {
28
30
  const divisor = toBigInt(b);
29
- if (divisor === 0n) throw new Error("division by zero");
31
+ if (divisor === 0n) throw new SELEvaluationError("division by zero");
30
32
  return toSolInt(toBigInt(a) / divisor);
31
33
  });
32
34
  env.registerOperator("sol_int % sol_int", (a, b) => {
33
35
  const divisor = toBigInt(b);
34
- if (divisor === 0n) throw new Error("modulo by zero");
36
+ if (divisor === 0n) throw new SELEvaluationError("modulo by zero");
35
37
  return toSolInt(toBigInt(a) % divisor);
36
38
  });
37
39
  env.registerOperator("-sol_int", (a) => toSolInt(-toBigInt(a)));
@@ -45,12 +47,25 @@ const registerIntegerOperators = (env) => {
45
47
  tryRegisterOperator(env, "sol_int * int", (a, b) => toSolInt(toBigInt(a) * toBigInt(b)));
46
48
  tryRegisterOperator(env, "sol_int / int", (a, b) => {
47
49
  const divisor = toBigInt(b);
48
- if (divisor === 0n) throw new Error("division by zero");
50
+ if (divisor === 0n) throw new SELEvaluationError("division by zero");
49
51
  return toSolInt(toBigInt(a) / divisor);
50
52
  });
51
53
  tryRegisterOperator(env, "sol_int % int", (a, b) => {
52
54
  const divisor = toBigInt(b);
53
- if (divisor === 0n) throw new Error("modulo by zero");
55
+ if (divisor === 0n) throw new SELEvaluationError("modulo by zero");
56
+ return toSolInt(toBigInt(a) % divisor);
57
+ });
58
+ tryRegisterOperator(env, "int + sol_int: sol_int", (a, b) => toSolInt(toBigInt(a) + toBigInt(b)));
59
+ tryRegisterOperator(env, "int - sol_int: sol_int", (a, b) => toSolInt(toBigInt(a) - toBigInt(b)));
60
+ tryRegisterOperator(env, "int * sol_int: sol_int", (a, b) => toSolInt(toBigInt(a) * toBigInt(b)));
61
+ tryRegisterOperator(env, "int / sol_int: sol_int", (a, b) => {
62
+ const divisor = toBigInt(b);
63
+ if (divisor === 0n) throw new SELEvaluationError("division by zero");
64
+ return toSolInt(toBigInt(a) / divisor);
65
+ });
66
+ tryRegisterOperator(env, "int % sol_int: sol_int", (a, b) => {
67
+ const divisor = toBigInt(b);
68
+ if (divisor === 0n) throw new SELEvaluationError("modulo by zero");
54
69
  return toSolInt(toBigInt(a) % divisor);
55
70
  });
56
71
  tryRegisterOperator(env, "sol_int == int", (a, b) => toBigInt(a) === toBigInt(b));
@@ -77,11 +92,17 @@ const registerSolidityTypes = (env) => {
77
92
  for (const sig of entry.castSignatures) env.registerFunction(sig, (value) => new Ctor(value));
78
93
  }
79
94
  env.registerFunction("parseUnits(string, int): sol_int", (value, decimals) => parseUnitsValue(value, Number(toBigInt(decimals))));
95
+ env.registerFunction("parseUnits(string, sol_int): sol_int", (value, decimals) => parseUnitsValue(value, Number(toBigInt(decimals))));
80
96
  env.registerFunction("parseUnits(int, int): sol_int", (value, decimals) => parseUnitsValue(value, Number(toBigInt(decimals))));
97
+ env.registerFunction("parseUnits(int, sol_int): sol_int", (value, decimals) => parseUnitsValue(value, Number(toBigInt(decimals))));
81
98
  env.registerFunction("parseUnits(double, int): sol_int", (value, decimals) => parseUnitsValue(value, Number(toBigInt(decimals))));
99
+ env.registerFunction("parseUnits(double, sol_int): sol_int", (value, decimals) => parseUnitsValue(value, Number(toBigInt(decimals))));
82
100
  env.registerFunction("parseUnits(sol_int, int): sol_int", (value, decimals) => parseUnitsValue(value, Number(toBigInt(decimals))));
101
+ env.registerFunction("parseUnits(sol_int, sol_int): sol_int", (value, decimals) => parseUnitsValue(value, Number(toBigInt(decimals))));
83
102
  env.registerFunction("formatUnits(sol_int, int): double", (value, decimals) => formatUnitsValue(value, Number(toBigInt(decimals))));
103
+ env.registerFunction("formatUnits(sol_int, sol_int): double", (value, decimals) => formatUnitsValue(value, Number(toBigInt(decimals))));
84
104
  env.registerFunction("formatUnits(int, int): double", (value, decimals) => formatUnitsValue(value, Number(toBigInt(decimals))));
105
+ env.registerFunction("formatUnits(int, sol_int): double", (value, decimals) => formatUnitsValue(value, Number(toBigInt(decimals))));
85
106
  env.registerFunction("min(sol_int, sol_int): sol_int", (a, b) => toBigInt(a) <= toBigInt(b) ? toSolInt(a) : toSolInt(b));
86
107
  env.registerFunction("min(sol_int, int): sol_int", (a, b) => toBigInt(a) <= toBigInt(b) ? toSolInt(a) : toSolInt(b));
87
108
  env.registerFunction("min(int, sol_int): sol_int", (a, b) => toBigInt(a) <= toBigInt(b) ? toSolInt(a) : toSolInt(b));
@@ -98,9 +119,65 @@ const registerSolidityTypes = (env) => {
98
119
  const v = toBigInt(a);
99
120
  return toSolInt(v < 0n ? -v : v);
100
121
  });
122
+ const registerListSolIntReducer = (name, handler) => {
123
+ env.registerFunction({
124
+ name,
125
+ receiverType: "list<sol_int>",
126
+ returnType: "sol_int",
127
+ params: []
128
+ }, handler);
129
+ };
130
+ registerListSolIntReducer("sum", (list) => {
131
+ let total = 0n;
132
+ for (const item of list) total += toBigInt(item);
133
+ return toSolInt(total);
134
+ });
135
+ registerListSolIntReducer("min", (list) => {
136
+ const items = list;
137
+ if (items.length === 0) throw new SELEvaluationError("list<sol_int>.min(): list is empty");
138
+ let smallest = toBigInt(items[0]);
139
+ for (let i = 1; i < items.length; i++) {
140
+ const v = toBigInt(items[i]);
141
+ if (v < smallest) smallest = v;
142
+ }
143
+ return toSolInt(smallest);
144
+ });
145
+ registerListSolIntReducer("max", (list) => {
146
+ const items = list;
147
+ if (items.length === 0) throw new SELEvaluationError("list<sol_int>.max(): list is empty");
148
+ let largest = toBigInt(items[0]);
149
+ for (let i = 1; i < items.length; i++) {
150
+ const v = toBigInt(items[i]);
151
+ if (v > largest) largest = v;
152
+ }
153
+ return toSolInt(largest);
154
+ });
101
155
  const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
102
156
  env.registerFunction("isZeroAddress(sol_address): bool", (addr) => toAddress(addr) === ZERO_ADDRESS);
103
157
  env.registerFunction("isZeroAddress(string): bool", (addr) => toAddress(addr) === ZERO_ADDRESS);
158
+ env.registerFunction("hexBytes(string): bytes", (hex) => hexToBytes(hex));
159
+ env.registerFunction("hexBytes(string, int): bytes", (hex, length) => {
160
+ const out = hexToBytes(hex);
161
+ const expected = Number(toBigInt(length));
162
+ if (out.length !== expected) throw new SELEvaluationError(`hexBytes: expected ${String(expected)} bytes, got ${String(out.length)}`);
163
+ return out;
164
+ });
165
+ env.registerFunction("keccak256(string): bytes", (value) => hexToBytes(keccak256(toBytes(value))));
166
+ env.registerFunction("keccak256(bytes): bytes", (value) => hexToBytes(keccak256(value)));
167
+ class SelNamespace {}
168
+ const selFields = {};
169
+ const selValues = {};
170
+ for (const constant of EVM_CONSTANTS) {
171
+ selFields[constant.name] = constant.type;
172
+ if (constant.type === "sol_int") selValues[constant.name] = new SolidityIntTypeWrapper(constant.value);
173
+ else if (constant.type === "sol_address") selValues[constant.name] = new SolidityAddressTypeWrapper(constant.value);
174
+ else selValues[constant.name] = constant.value;
175
+ }
176
+ env.registerType("SelNamespace", {
177
+ ctor: SelNamespace,
178
+ fields: selFields
179
+ });
180
+ env.registerConstant("sel", "SelNamespace", Object.assign(new SelNamespace(), selValues));
104
181
  };
105
182
  //#endregion
106
183
  export { registerSolidityTypes };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seljs/checker",
3
- "version": "1.3.0-beta.3",
3
+ "version": "1.3.0-beta.33",
4
4
  "repository": {
5
5
  "url": "https://github.com/abinnovision/seljs"
6
6
  },
@@ -50,13 +50,14 @@
50
50
  },
51
51
  "dependencies": {
52
52
  "@marcbachmann/cel-js": "^7.5.3",
53
- "@seljs/common": "1.3.0-beta.3",
53
+ "@seljs/common": "1.3.0-beta.33",
54
54
  "@seljs/schema": "1.2.0",
55
- "@seljs/types": "1.3.0-beta.3",
56
- "debug": "^4.4.3"
55
+ "@seljs/types": "1.3.0-beta.33",
56
+ "debug": "^4.4.3",
57
+ "viem": "^2.47.6"
57
58
  },
58
59
  "devDependencies": {
59
- "@abinnovision/eslint-config-base": "^3.2.0",
60
+ "@abinnovision/eslint-config-base": "^3.2.2",
60
61
  "@abinnovision/prettier-config": "^2.1.5",
61
62
  "@seljs-internal/tsconfig": "^0.0.0",
62
63
  "@types/debug": "^4.1.13",