@monolythium/core-sdk 0.1.0

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/index.js ADDED
@@ -0,0 +1,2214 @@
1
+ import { JsonRpcApiProvider, Network, AbstractSigner } from 'ethers';
2
+
3
+ // src/error.ts
4
+ var SdkError = class _SdkError extends Error {
5
+ kind;
6
+ code;
7
+ data;
8
+ constructor(kind, message, opts) {
9
+ super(message, opts?.cause ? { cause: opts.cause } : void 0);
10
+ this.name = "SdkError";
11
+ this.kind = kind;
12
+ this.code = opts?.code;
13
+ this.data = opts?.data;
14
+ }
15
+ static transport(message, cause) {
16
+ return new _SdkError("transport", message, { cause });
17
+ }
18
+ static rpc(code, message, data) {
19
+ return new _SdkError("rpc", `rpc error ${code}: ${message}`, { code, data });
20
+ }
21
+ static malformed(message) {
22
+ return new _SdkError("malformed", message);
23
+ }
24
+ static endpoint(message) {
25
+ return new _SdkError("endpoint", message);
26
+ }
27
+ };
28
+
29
+ // src/types.ts
30
+ function encodeBlockSelector(b) {
31
+ if (typeof b === "number") return `0x${b.toString(16)}`;
32
+ if (typeof b === "bigint") return `0x${b.toString(16)}`;
33
+ return b;
34
+ }
35
+
36
+ // src/api.ts
37
+ var SDK_VERSION = "0.1.0";
38
+ function apiEndpointFromRpcEndpoint(endpoint) {
39
+ const raw = endpoint.trim();
40
+ if (raw.length === 0) {
41
+ throw SdkError.endpoint("endpoint cannot be empty");
42
+ }
43
+ const noTrailing = raw.replace(/\/+$/, "");
44
+ if (noTrailing.endsWith("/api/v1")) {
45
+ return noTrailing;
46
+ }
47
+ if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(noTrailing)) {
48
+ const url = new URL(noTrailing);
49
+ const path = url.pathname.replace(/\/+$/, "");
50
+ if (path === "" || path === "/" || path === "/rpc") {
51
+ url.pathname = "/api/v1";
52
+ } else if (path.endsWith("/rpc")) {
53
+ url.pathname = `${path.slice(0, -"/rpc".length)}/api/v1`;
54
+ } else {
55
+ url.pathname = "/api/v1";
56
+ }
57
+ url.search = "";
58
+ url.hash = "";
59
+ return url.toString().replace(/\/+$/, "");
60
+ }
61
+ return "/api/v1";
62
+ }
63
+ var ApiClient = class {
64
+ baseUrl;
65
+ #fetch;
66
+ #headers;
67
+ constructor(endpoint, options = {}) {
68
+ this.baseUrl = (options.apiBaseUrl ?? apiEndpointFromRpcEndpoint(endpoint)).replace(/\/+$/, "");
69
+ this.#fetch = options.fetch ?? globalThis.fetch.bind(globalThis);
70
+ this.#headers = {
71
+ accept: "application/json",
72
+ "user-agent": `monolythium-core-sdk/${SDK_VERSION}`,
73
+ ...options.headers ?? {}
74
+ };
75
+ }
76
+ async get(path, query = {}) {
77
+ return this.#get(path, query, false);
78
+ }
79
+ async health() {
80
+ return this.#get("/health", {}, true);
81
+ }
82
+ async capabilities() {
83
+ return this.get("/capabilities");
84
+ }
85
+ async provenance() {
86
+ return this.get("/provenance");
87
+ }
88
+ async search(query, limit = 10) {
89
+ return this.get("/search", { q: query, limit });
90
+ }
91
+ async stats() {
92
+ return this.get("/stats");
93
+ }
94
+ async block(block = "latest") {
95
+ return this.get(`/blocks/${encodePathBlock(block)}`);
96
+ }
97
+ async blockTransactions(block = "latest", page = 0, limit = 25) {
98
+ return this.get(`/blocks/${encodePathBlock(block)}/transactions`, { page, limit });
99
+ }
100
+ async transactions(limit = 50, cursor) {
101
+ return this.get("/transactions", { limit, cursor });
102
+ }
103
+ async transaction(hash) {
104
+ return this.get(`/transactions/${encodePathSegment(hash)}`);
105
+ }
106
+ async transactionReceipt(hash) {
107
+ return this.get(`/transactions/${encodePathSegment(hash)}/receipt`);
108
+ }
109
+ async addressProfile(address) {
110
+ return this.get(`/addresses/${encodePathSegment(address)}/profile`);
111
+ }
112
+ async addressFlow(address, limit = 250) {
113
+ return this.get(`/addresses/${encodePathSegment(address)}/flow`, { limit });
114
+ }
115
+ async addressActivity(address, limit = 50, cursor) {
116
+ return this.get(`/addresses/${encodePathSegment(address)}/activity`, {
117
+ limit,
118
+ cursor
119
+ });
120
+ }
121
+ async addressActivityKind(address) {
122
+ return this.get(`/addresses/${encodePathSegment(address)}/activity-kind`);
123
+ }
124
+ async clusters(page = 0, limit = 25) {
125
+ return this.get("/clusters", { page, limit });
126
+ }
127
+ async cluster(clusterId) {
128
+ return this.get(`/clusters/${encodePathSegment(clusterId)}`);
129
+ }
130
+ async operator(operatorId) {
131
+ return this.get(`/operators/${encodePathSegment(operatorId)}`);
132
+ }
133
+ async serviceProbe(peerId, serviceMask) {
134
+ return this.get(
135
+ `/service-probes/${encodePathSegment(peerId)}/${encodePathSegment(serviceMask)}`
136
+ );
137
+ }
138
+ async markets(limit = 50) {
139
+ return this.get("/markets", { limit });
140
+ }
141
+ async market(marketId) {
142
+ return this.get(`/markets/${encodePathSegment(marketId)}`);
143
+ }
144
+ async marketTrades(marketId, limit = 50, cursor) {
145
+ return this.get(`/markets/${encodePathSegment(marketId)}/trades`, { limit, cursor });
146
+ }
147
+ async marketOhlc(marketId, fromBlock, toBlock, bucketBlocks) {
148
+ return this.get(`/markets/${encodePathSegment(marketId)}/ohlc`, {
149
+ fromBlock,
150
+ toBlock,
151
+ bucketBlocks
152
+ });
153
+ }
154
+ async marketOrderBook(marketId, levels = 20) {
155
+ return this.get(`/markets/${encodePathSegment(marketId)}/orderbook`, { levels });
156
+ }
157
+ async upgradeStatus(height) {
158
+ return this.get("/upgrades/status", {
159
+ height: height == null ? void 0 : encodeBlockSelector(height)
160
+ });
161
+ }
162
+ async #get(path, query, allowUnavailableBody) {
163
+ const url = buildUrl(this.baseUrl, path, query);
164
+ let resp;
165
+ try {
166
+ resp = await this.#fetch(url, {
167
+ method: "GET",
168
+ headers: this.#headers
169
+ });
170
+ } catch (cause) {
171
+ throw SdkError.transport(
172
+ `transport failure calling ${url}: ${cause?.message ?? cause}`,
173
+ cause
174
+ );
175
+ }
176
+ let parsed;
177
+ try {
178
+ parsed = await resp.json();
179
+ } catch (cause) {
180
+ throw SdkError.malformed(
181
+ `non-JSON response (HTTP ${resp.status}): ${cause?.message ?? cause}`
182
+ );
183
+ }
184
+ const error = parseApiError(parsed);
185
+ if (error) {
186
+ throw SdkError.rpc(error.code, error.message, error.data);
187
+ }
188
+ if (!resp.ok && !(allowUnavailableBody && resp.status === 503)) {
189
+ throw SdkError.transport(`HTTP ${resp.status} calling ${url}`);
190
+ }
191
+ return parsed;
192
+ }
193
+ };
194
+ function parseApiError(value) {
195
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
196
+ const error = value["error"];
197
+ if (!error || typeof error !== "object" || Array.isArray(error)) return null;
198
+ const row = error;
199
+ if (typeof row["code"] !== "number" || typeof row["message"] !== "string") {
200
+ return null;
201
+ }
202
+ return {
203
+ code: row["code"],
204
+ message: row["message"],
205
+ data: row["data"]
206
+ };
207
+ }
208
+ function buildUrl(baseUrl, path, query) {
209
+ const cleanBase = baseUrl.replace(/\/+$/, "");
210
+ const cleanPath = path.startsWith("/") ? path : `/${path}`;
211
+ const params = new URLSearchParams();
212
+ for (const [key, value] of Object.entries(query)) {
213
+ if (value === void 0 || value === null) continue;
214
+ params.set(key, typeof value === "bigint" ? value.toString() : String(value));
215
+ }
216
+ const qs = params.toString();
217
+ return qs.length === 0 ? `${cleanBase}${cleanPath}` : `${cleanBase}${cleanPath}?${qs}`;
218
+ }
219
+ function encodePathBlock(block) {
220
+ return encodePathSegment(encodeBlockSelector(block));
221
+ }
222
+ function encodePathSegment(value) {
223
+ return encodeURIComponent(typeof value === "bigint" ? value.toString() : String(value));
224
+ }
225
+
226
+ // src/consts.ts
227
+ var BURN_ADDR = "0x0000000000000000000000000000000000000000";
228
+ var PRECOMPILE_ADDRESSES = {
229
+ /** Native fungible-token factory — non-gateable, foundational. */
230
+ TOKEN_FACTORY: "0x0000000000000000000000000000000000001000",
231
+ /** Native central-limit order book — gateable. */
232
+ CLOB: "0x0000000000000000000000000000000000001001",
233
+ /** Agent execution surface (zkML-gated, ADR-0011/ADR-0020) — gateable. */
234
+ AGENT: "0x0000000000000000000000000000000000001003",
235
+ /** Account privacy policy + stealth/confidential ops — gateable. */
236
+ PRIVACY: "0x0000000000000000000000000000000000001004",
237
+ /** Operator + RPC node registry — non-gateable consensus invariant. */
238
+ NODE_REGISTRY: "0x0000000000000000000000000000000000001005",
239
+ /** IBC light-client + packet routing — gateable. */
240
+ IBC: "0x0000000000000000000000000000000000001007",
241
+ /** Native zk-light-client bridge — gateable. */
242
+ BRIDGE: "0x0000000000000000000000000000000000001008",
243
+ /** Decentralized multi-signer oracle (OI-0036) — non-gateable. */
244
+ ORACLE: "0x0000000000000000000000000000000000001009",
245
+ /** Distributed delegation primitive (Stage E.5a, Law §7.6) — gateable. */
246
+ DELEGATION: "0x000000000000000000000000000000000000100A",
247
+ /** One-time emergency-key registry (Law §5.4 / §2.9) — non-gateable. */
248
+ EMERGENCY_KEY: "0x0000000000000000000000000000000000001100",
249
+ /** VRF precompile (Law §5.4 / §5.6). */
250
+ VRF: "0x0000000000000000000000000000000000001101",
251
+ /** Streaming-payments primitive (Law §5.4 / §5.7) — gateable. */
252
+ STREAMING_PAYMENTS: "0x0000000000000000000000000000000000001102",
253
+ /** Human-readable name registry (Law §5.4 / §5.8) — gateable. */
254
+ NAME_REGISTRY: "0x0000000000000000000000000000000000001103",
255
+ /** Cluster-name registry. */
256
+ CLUSTER_NAME_REGISTRY: "0x0000000000000000000000000000000000001104",
257
+ /** Agent-commerce attestation precompile. */
258
+ ATTESTATION: "0x0000000000000000000000000000000000001105",
259
+ /** Agent-commerce consent precompile. */
260
+ CONSENT: "0x0000000000000000000000000000000000001106",
261
+ /** Agent-commerce issuer registry. */
262
+ ISSUER_REGISTRY: "0x0000000000000000000000000000000000001107",
263
+ /** Agent-commerce discovery precompile. */
264
+ DISCOVERY: "0x0000000000000000000000000000000000001108",
265
+ /** Agent-commerce availability precompile. */
266
+ AVAILABILITY: "0x0000000000000000000000000000000000001109",
267
+ /** Agent-commerce escrow precompile. */
268
+ ESCROW: "0x000000000000000000000000000000000000110A",
269
+ /** Agent-commerce arbiter registry. */
270
+ ARBITER_REGISTRY: "0x000000000000000000000000000000000000110B",
271
+ /** Agent spending policy — gateable, activated by Stage 7 milestones. */
272
+ SPENDING_POLICY: "0x000000000000000000000000000000000000110C",
273
+ /** Primary ML-DSA-65 pubkey registry — gateable, ADR-0034. */
274
+ PUBKEY_REGISTRY: "0x000000000000000000000000000000000000110D"
275
+ };
276
+
277
+ // src/node-registry.ts
278
+ var NODE_REGISTRY_CAPABILITIES = {
279
+ SERVES_RPC: 1,
280
+ SERVES_INDEXER: 2,
281
+ SERVES_BROADCASTER: 4,
282
+ SERVES_ARCHIVE: 8,
283
+ SERVES_WEBSOCKET: 16,
284
+ SERVES_LIGHT_CLIENT: 32,
285
+ SERVES_ORACLE_WRITER: 64,
286
+ SERVES_BRIDGE_RELAY: 128,
287
+ SERVES_PUBLIC_API: 256
288
+ };
289
+ var NODE_REGISTRY_CAPABILITY_MASK = 65535;
290
+ var NODE_REGISTRY_PUBLIC_SERVICE_MASK = NODE_REGISTRY_CAPABILITIES.SERVES_RPC | NODE_REGISTRY_CAPABILITIES.SERVES_INDEXER | NODE_REGISTRY_CAPABILITIES.SERVES_ARCHIVE | NODE_REGISTRY_CAPABILITIES.SERVES_WEBSOCKET | NODE_REGISTRY_CAPABILITIES.SERVES_PUBLIC_API;
291
+ var SERVICE_PROBE_STATUS = {
292
+ UNKNOWN: 0,
293
+ REACHABLE: 1,
294
+ DEGRADED: 2,
295
+ UNREACHABLE: 3
296
+ };
297
+ var NODE_REGISTRY_SELECTORS = {
298
+ reportServiceProbe: "0xeee31bba",
299
+ getServiceProbe: "0x1fcbfbce"
300
+ };
301
+ var NodeRegistryError = class extends Error {
302
+ constructor(message) {
303
+ super(message);
304
+ this.name = "NodeRegistryError";
305
+ }
306
+ };
307
+ function nodeRegistryAddressHex() {
308
+ return PRECOMPILE_ADDRESSES.NODE_REGISTRY.toLowerCase();
309
+ }
310
+ function isValidNodeRegistryCapabilities(flags) {
311
+ return Number.isInteger(flags) && flags >= 0 && (flags & ~NODE_REGISTRY_CAPABILITY_MASK) === 0;
312
+ }
313
+ function isValidPublicServiceProbeMask(mask) {
314
+ return Number.isInteger(mask) && mask > 0 && (mask & ~NODE_REGISTRY_PUBLIC_SERVICE_MASK) === 0;
315
+ }
316
+ function isSinglePublicServiceProbeMask(mask) {
317
+ return isValidPublicServiceProbeMask(mask) && bitCount(mask) === 1;
318
+ }
319
+ function isConcreteServiceProbeStatus(status) {
320
+ return status === SERVICE_PROBE_STATUS.REACHABLE || status === SERVICE_PROBE_STATUS.DEGRADED || status === SERVICE_PROBE_STATUS.UNREACHABLE;
321
+ }
322
+ function serviceProbeStatusLabel(status) {
323
+ switch (status) {
324
+ case SERVICE_PROBE_STATUS.REACHABLE:
325
+ return "reachable";
326
+ case SERVICE_PROBE_STATUS.DEGRADED:
327
+ return "degraded";
328
+ case SERVICE_PROBE_STATUS.UNREACHABLE:
329
+ return "unreachable";
330
+ default:
331
+ return "unknown";
332
+ }
333
+ }
334
+ function encodeReportServiceProbeCalldata(args) {
335
+ if (!isValidPublicServiceProbeMask(args.serviceMask)) {
336
+ throw new NodeRegistryError(
337
+ `serviceMask 0x${args.serviceMask.toString(16).padStart(8, "0")} is not a valid public-service mask`
338
+ );
339
+ }
340
+ if (!isConcreteServiceProbeStatus(args.status)) {
341
+ throw new NodeRegistryError(`status ${args.status} is not a concrete service-probe outcome`);
342
+ }
343
+ const latencyMs = expectUint32(args.latencyMs, "latencyMs");
344
+ return bytesToHex(
345
+ concatBytes(
346
+ hexToBytes(NODE_REGISTRY_SELECTORS.reportServiceProbe),
347
+ expectLength(toBytes(args.peerId), 32, "peerId"),
348
+ uint32Word(args.serviceMask),
349
+ uint8Word(args.status),
350
+ uint32Word(latencyMs),
351
+ expectLength(toBytes(args.probeDigest), 32, "probeDigest")
352
+ )
353
+ );
354
+ }
355
+ function bitCount(value) {
356
+ let n = value >>> 0;
357
+ let count = 0;
358
+ while (n !== 0) {
359
+ count += n & 1;
360
+ n >>>= 1;
361
+ }
362
+ return count;
363
+ }
364
+ function expectUint32(value, name) {
365
+ if (!Number.isInteger(value) || value < 0 || value > 4294967295) {
366
+ throw new NodeRegistryError(`${name} must be a uint32`);
367
+ }
368
+ return value;
369
+ }
370
+ function uint32Word(value) {
371
+ const out = new Uint8Array(32);
372
+ const n = expectUint32(value, "uint32");
373
+ out[28] = n >>> 24 & 255;
374
+ out[29] = n >>> 16 & 255;
375
+ out[30] = n >>> 8 & 255;
376
+ out[31] = n & 255;
377
+ return out;
378
+ }
379
+ function uint8Word(value) {
380
+ if (!Number.isInteger(value) || value < 0 || value > 255) {
381
+ throw new NodeRegistryError("uint8 value out of range");
382
+ }
383
+ const out = new Uint8Array(32);
384
+ out[31] = value;
385
+ return out;
386
+ }
387
+ function toBytes(value) {
388
+ if (typeof value === "string") {
389
+ return hexToBytes(value);
390
+ }
391
+ return value instanceof Uint8Array ? value : Uint8Array.from(value);
392
+ }
393
+ function hexToBytes(hex) {
394
+ const body = hex.startsWith("0x") || hex.startsWith("0X") ? hex.slice(2) : hex;
395
+ if (body.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(body)) {
396
+ throw new NodeRegistryError("invalid hex bytes");
397
+ }
398
+ const out = new Uint8Array(body.length / 2);
399
+ for (let i = 0; i < out.length; i++) {
400
+ out[i] = Number.parseInt(body.slice(i * 2, i * 2 + 2), 16);
401
+ }
402
+ return out;
403
+ }
404
+ function bytesToHex(bytes) {
405
+ return `0x${[...bytes].map((b) => b.toString(16).padStart(2, "0")).join("")}`;
406
+ }
407
+ function concatBytes(...parts) {
408
+ const out = new Uint8Array(parts.reduce((acc, p) => acc + p.length, 0));
409
+ let offset = 0;
410
+ for (const part of parts) {
411
+ out.set(part, offset);
412
+ offset += part.length;
413
+ }
414
+ return out;
415
+ }
416
+ function expectLength(value, len, name) {
417
+ if (value.length !== len) {
418
+ throw new NodeRegistryError(`${name} must be ${len} bytes, got ${value.length}`);
419
+ }
420
+ return value;
421
+ }
422
+
423
+ // src/registry.ts
424
+ var TESTNET_69420 = {
425
+ chain_id: 69420,
426
+ network: "testnet-69420",
427
+ display_name: "Monolythium Testnet",
428
+ description: "Live development testnet for Monolythium v4.0 / LythiumDAG-BFT. Foundation-operated. Wipe + regenesis is allowed without notice \u2014 do NOT store value on this network.",
429
+ genesis_hash: "0x325057e476b7be3730a22c92b9289f4a14a3414a2a081bd279b43eeba36b0075",
430
+ binary_sha: "44a9ec4",
431
+ rpc: [
432
+ {
433
+ url: "http://178.105.15.216:8545",
434
+ provider: "monolythium-foundation",
435
+ region: "fsn1",
436
+ tier: "official",
437
+ notes: "operator-2; primary foundation seed (operator-1 offline pending BLS key reissue)"
438
+ },
439
+ {
440
+ url: "http://178.104.233.182:8545",
441
+ provider: "monolythium-foundation",
442
+ region: "nbg1",
443
+ tier: "official",
444
+ notes: "operator-3"
445
+ },
446
+ {
447
+ url: "http://65.108.94.1:8545",
448
+ provider: "monolythium-foundation",
449
+ region: "hel1",
450
+ tier: "official",
451
+ notes: "operator-4"
452
+ },
453
+ {
454
+ url: "http://95.216.154.155:8545",
455
+ provider: "monolythium-foundation",
456
+ region: "hel1",
457
+ tier: "official",
458
+ notes: "operator-5"
459
+ },
460
+ {
461
+ url: "http://87.99.145.48:8545",
462
+ provider: "monolythium-foundation",
463
+ region: "ash",
464
+ tier: "official",
465
+ notes: "operator-6; US east"
466
+ },
467
+ {
468
+ url: "http://5.223.85.76:8545",
469
+ provider: "monolythium-foundation",
470
+ region: "sin",
471
+ tier: "official",
472
+ notes: "operator-7; APAC"
473
+ }
474
+ ],
475
+ p2p: [
476
+ {
477
+ multiaddr: "/ip4/178.105.15.216/tcp/29898/p2p/12D3KooWDKk9ALxqchazXGcRGbqyopWtAGRbf4WQFS2dABV7gQGb",
478
+ region: "fsn1"
479
+ },
480
+ {
481
+ multiaddr: "/ip4/178.104.233.182/tcp/29898/p2p/12D3KooW9uVG8csFCtSxoFaYBsGzXBgVwQhAw84TGj4dfRi9LH1c",
482
+ region: "nbg1"
483
+ },
484
+ {
485
+ multiaddr: "/ip4/65.108.94.1/tcp/29898/p2p/12D3KooWKvkjEVkA64TdbSoVjDW2sWUzgkAMbPZsZvfxZw2W6zVy",
486
+ region: "hel1"
487
+ },
488
+ {
489
+ multiaddr: "/ip4/95.216.154.155/tcp/29898/p2p/12D3KooWCcVjSuERAGzG6Xb3wjUj22fGrgP2QXDJfquxQ72TBMd8",
490
+ region: "hel1"
491
+ },
492
+ {
493
+ multiaddr: "/ip4/87.99.145.48/tcp/29898/p2p/12D3KooWMKw9Qxx7RE3PjQGMZq94C23UDjnTbZCNWFy6Dc4YcCdL",
494
+ region: "ash"
495
+ },
496
+ {
497
+ multiaddr: "/ip4/5.223.85.76/tcp/29898/p2p/12D3KooWSTeApBSKR4DpKvJAuqKfHxNhdbNg9mi9u8f4UNfzN5Cu",
498
+ region: "sin"
499
+ }
500
+ ]
501
+ };
502
+ var CHAIN_REGISTRY = {
503
+ "testnet-69420": TESTNET_69420
504
+ };
505
+ var CHAIN_REGISTRY_RAW_BASE = "https://raw.githubusercontent.com/monolythium/chain-registry/master/chains";
506
+ function getChainInfo(network) {
507
+ const info = CHAIN_REGISTRY[network];
508
+ if (!info) {
509
+ throw new Error(`unknown Monolythium network: ${network}`);
510
+ }
511
+ return info;
512
+ }
513
+ function getRpcEndpoints(network) {
514
+ return getChainInfo(network).rpc;
515
+ }
516
+ function getP2pSeeds(network) {
517
+ return getChainInfo(network).p2p;
518
+ }
519
+ async function fetchChainInfoLatest(network, options = {}) {
520
+ const fetchImpl = options.fetch ?? globalThis.fetch.bind(globalThis);
521
+ const rawBaseUrl = options.rawBaseUrl ?? CHAIN_REGISTRY_RAW_BASE;
522
+ const resp = await fetchImpl(`${rawBaseUrl}/${network}.toml`);
523
+ if (!resp.ok) {
524
+ throw new Error(`failed to fetch chain registry ${network}: HTTP ${resp.status}`);
525
+ }
526
+ return parseChainRegistryToml(await resp.text());
527
+ }
528
+ async function fetchChainRegistryLatest(networks = ["testnet-69420"], options = {}) {
529
+ const entries = await Promise.all(
530
+ networks.map(async (network) => [network, await fetchChainInfoLatest(network, options)])
531
+ );
532
+ return Object.fromEntries(entries);
533
+ }
534
+ function parseChainRegistryToml(input) {
535
+ const info = {
536
+ rpc: [],
537
+ p2p: [],
538
+ explorer: []
539
+ };
540
+ let section = "root";
541
+ for (const rawLine of input.split(/\r?\n/)) {
542
+ const line = rawLine.replace(/\s+#.*$/, "").trim();
543
+ if (!line || line.startsWith("#")) continue;
544
+ if (line === "[[rpc]]") {
545
+ section = "rpc";
546
+ info.rpc.push({ url: "", provider: "", tier: "community" });
547
+ continue;
548
+ }
549
+ if (line === "[[p2p]]") {
550
+ section = "p2p";
551
+ info.p2p.push({ multiaddr: "" });
552
+ continue;
553
+ }
554
+ if (line === "[[explorer]]") {
555
+ section = "explorer";
556
+ info.explorer.push({ url: "", name: "" });
557
+ continue;
558
+ }
559
+ const match = /^([A-Za-z0-9_]+)\s*=\s*(.+)$/.exec(line);
560
+ if (!match) continue;
561
+ const [, key, rawValue] = match;
562
+ const value = parseTomlScalar(rawValue);
563
+ if (section === "root") {
564
+ info[key] = value;
565
+ } else {
566
+ const list = info[section];
567
+ const target = list[list.length - 1];
568
+ target[key] = value;
569
+ }
570
+ }
571
+ if (!info.network || !info.chain_id || !info.genesis_hash || !info.binary_sha) {
572
+ throw new Error("chain registry TOML is missing required top-level fields");
573
+ }
574
+ if (info.rpc.length === 0 || info.rpc.some((r) => !r.url || !r.provider || !r.tier)) {
575
+ throw new Error("chain registry TOML must include at least one complete rpc endpoint");
576
+ }
577
+ if (info.p2p.length === 0 || info.p2p.some((p) => !p.multiaddr)) {
578
+ throw new Error("chain registry TOML must include at least one p2p seed");
579
+ }
580
+ const out = {
581
+ chain_id: Number(info.chain_id),
582
+ network: String(info.network),
583
+ display_name: info.display_name ? String(info.display_name) : void 0,
584
+ description: info.description ? String(info.description) : void 0,
585
+ genesis_hash: String(info.genesis_hash),
586
+ binary_sha: String(info.binary_sha),
587
+ rpc: info.rpc,
588
+ p2p: info.p2p
589
+ };
590
+ if (info.explorer.length > 0) out.explorer = info.explorer;
591
+ return out;
592
+ }
593
+ function parseTomlScalar(raw) {
594
+ const value = raw.trim();
595
+ if (value.startsWith('"') && value.endsWith('"')) {
596
+ return value.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, "\\");
597
+ }
598
+ if (value === "true") return true;
599
+ if (value === "false") return false;
600
+ if (/^-?\d+$/.test(value)) return Number(value);
601
+ return value;
602
+ }
603
+
604
+ // src/client.ts
605
+ var SDK_VERSION2 = "0.1.0";
606
+ function resolveChainInfo(network, registry) {
607
+ if (registry) {
608
+ const info = registry[network];
609
+ if (!info) {
610
+ throw SdkError.endpoint(`unknown Monolythium network: ${network}`);
611
+ }
612
+ return info;
613
+ }
614
+ try {
615
+ return getChainInfo(network);
616
+ } catch (err) {
617
+ throw SdkError.endpoint(err?.message ?? String(err));
618
+ }
619
+ }
620
+ var RpcClient = class _RpcClient {
621
+ endpoint;
622
+ #fetch;
623
+ #headers;
624
+ #nextId;
625
+ constructor(endpoint, options = {}) {
626
+ if (!endpoint || endpoint.length === 0) {
627
+ throw SdkError.endpoint("endpoint cannot be empty");
628
+ }
629
+ this.endpoint = endpoint;
630
+ this.#fetch = options.fetch ?? globalThis.fetch.bind(globalThis);
631
+ this.#headers = {
632
+ "content-type": "application/json",
633
+ "user-agent": `monolythium-core-sdk/${SDK_VERSION2}`,
634
+ ...options.headers ?? {}
635
+ };
636
+ this.#nextId = 1;
637
+ }
638
+ /**
639
+ * Construct a client from the chain-registry network slug.
640
+ *
641
+ * Defaults to the SDK-bundled registry snapshot from
642
+ * `monolythium/chain-registry`. Set `probe: true` to walk the
643
+ * registry endpoints in order and return the first endpoint whose
644
+ * `eth_chainId` matches the registry chain id.
645
+ */
646
+ static async forNetwork(network = "testnet-69420", options = {}) {
647
+ const info = resolveChainInfo(network, options.registry);
648
+ if (info.rpc.length === 0) {
649
+ throw SdkError.endpoint(`network ${network} has no RPC endpoints`);
650
+ }
651
+ if (options.probe) {
652
+ return this.fromFirstReachable(info, options);
653
+ }
654
+ return new _RpcClient(info.rpc[0].url, options);
655
+ }
656
+ /**
657
+ * Walk a chain-registry entry in order and return the first endpoint
658
+ * whose `eth_chainId` matches the registry `chain_id`.
659
+ */
660
+ static async fromFirstReachable(chain, options = {}) {
661
+ const errors = [];
662
+ for (const endpoint of chain.rpc) {
663
+ const client = new _RpcClient(endpoint.url, options);
664
+ try {
665
+ const chainId = await client.ethChainId();
666
+ if (chainId === BigInt(chain.chain_id)) {
667
+ return client;
668
+ }
669
+ errors.push(`${endpoint.url}: chain id ${chainId} != ${chain.chain_id}`);
670
+ } catch (err) {
671
+ errors.push(`${endpoint.url}: ${err?.message ?? err}`);
672
+ }
673
+ }
674
+ throw SdkError.endpoint(
675
+ `no reachable RPC endpoint for ${chain.network}; tried ${errors.join("; ")}`
676
+ );
677
+ }
678
+ /**
679
+ * Send an arbitrary JSON-RPC method. Most callers should prefer the
680
+ * typed wrappers below; this is the escape hatch for methods the
681
+ * SDK does not yet wrap.
682
+ */
683
+ async call(method, params = []) {
684
+ const id = this.#nextId++;
685
+ const body = { jsonrpc: "2.0", id, method, params };
686
+ let resp;
687
+ try {
688
+ resp = await this.#fetch(this.endpoint, {
689
+ method: "POST",
690
+ headers: this.#headers,
691
+ body: JSON.stringify(body)
692
+ });
693
+ } catch (cause) {
694
+ throw SdkError.transport(
695
+ `transport failure calling ${method}: ${cause?.message ?? cause}`,
696
+ cause
697
+ );
698
+ }
699
+ let parsed;
700
+ try {
701
+ parsed = await resp.json();
702
+ } catch (cause) {
703
+ throw SdkError.malformed(
704
+ `non-JSON response (HTTP ${resp.status}): ${cause?.message ?? cause}`
705
+ );
706
+ }
707
+ if (parsed.error) {
708
+ throw SdkError.rpc(parsed.error.code, parsed.error.message, parsed.error.data);
709
+ }
710
+ if (!("result" in parsed) || parsed.result === void 0) {
711
+ if (!resp.ok) {
712
+ throw SdkError.malformed(`HTTP ${resp.status} with no JSON-RPC result`);
713
+ }
714
+ throw SdkError.malformed("response is missing both `result` and `error`");
715
+ }
716
+ return parsed.result;
717
+ }
718
+ // ---- eth_* / net_* / web3_* ---------------------------------------
719
+ /** `eth_chainId` — configured chain id. */
720
+ async ethChainId() {
721
+ return parseQuantityBig(await this.call("eth_chainId", []));
722
+ }
723
+ /** `eth_blockNumber` — latest committed height. */
724
+ async ethBlockNumber() {
725
+ return parseQuantityBig(await this.call("eth_blockNumber", []));
726
+ }
727
+ /** `eth_getBalance` — balance + Merkle proof envelope. */
728
+ async ethGetBalance(address, block = "latest") {
729
+ return this.call("eth_getBalance", [address, encodeBlockSelector(block)]);
730
+ }
731
+ /** `eth_getStorageAt` — storage word + Merkle proof. */
732
+ async ethGetStorageAt(address, slot, block = "latest") {
733
+ return this.call("eth_getStorageAt", [
734
+ address,
735
+ slot,
736
+ encodeBlockSelector(block)
737
+ ]);
738
+ }
739
+ /** `eth_getTransactionCount` — sender nonce. */
740
+ async ethGetTransactionCount(address, block = "latest") {
741
+ return parseQuantityBig(
742
+ await this.call("eth_getTransactionCount", [
743
+ address,
744
+ encodeBlockSelector(block)
745
+ ])
746
+ );
747
+ }
748
+ /** `eth_getCode` — deployed bytecode (`0x` for an EOA, `0xfe` for a precompile). */
749
+ async ethGetCode(address, block = "latest") {
750
+ return this.call("eth_getCode", [address, encodeBlockSelector(block)]);
751
+ }
752
+ /** `eth_getBlockByNumber` — fetch a block header by height/tag. */
753
+ async ethGetBlockByNumber(block = "latest") {
754
+ return normalizeBlockHeader(await this.call("eth_getBlockByNumber", [encodeBlockSelector(block)]));
755
+ }
756
+ /** `eth_getBlockByHash` — fetch a block header by hash. */
757
+ async ethGetBlockByHash(hash) {
758
+ return normalizeBlockHeader(await this.call("eth_getBlockByHash", [hash]));
759
+ }
760
+ /** `eth_getTransactionByHash` — fetch an included transaction by hash. */
761
+ async ethGetTransactionByHash(txHash) {
762
+ return this.call("eth_getTransactionByHash", [txHash]);
763
+ }
764
+ /** `eth_getTransactionReceipt` — receipt for a confirmed tx. */
765
+ async ethGetTransactionReceipt(txHash) {
766
+ return this.call("eth_getTransactionReceipt", [txHash]);
767
+ }
768
+ /** `eth_sendRawTransaction` — submit a signed raw tx. */
769
+ async ethSendRawTransaction(rawTx) {
770
+ return this.call("eth_sendRawTransaction", [rawTx]);
771
+ }
772
+ /** `eth_call` — dry-run a transaction. */
773
+ async ethCall(request, block = "latest") {
774
+ return this.call("eth_call", [request, encodeBlockSelector(block)]);
775
+ }
776
+ /** `eth_estimateGas` — gas estimate for a dry-run. */
777
+ async ethEstimateGas(request, block = "latest") {
778
+ return parseQuantityBig(
779
+ await this.call("eth_estimateGas", [request, encodeBlockSelector(block)])
780
+ );
781
+ }
782
+ /** `eth_gasPrice` — minimum gas price the node will accept. */
783
+ async ethGasPrice() {
784
+ return parseQuantityBig(await this.call("eth_gasPrice", []));
785
+ }
786
+ /** `eth_feeHistory` — base-fee + gas-used history. */
787
+ async ethFeeHistory(blockCount, newestBlock = "latest", rewardPercentiles = []) {
788
+ return this.call("eth_feeHistory", [
789
+ `0x${blockCount.toString(16)}`,
790
+ encodeBlockSelector(newestBlock),
791
+ rewardPercentiles
792
+ ]);
793
+ }
794
+ /** `eth_syncing` — `null` when caught up. */
795
+ async ethSyncing() {
796
+ const v = await this.call("eth_syncing", []);
797
+ if (v === false || v === null || v === void 0) return null;
798
+ return v;
799
+ }
800
+ /** `net_version` — chain id as a decimal string. */
801
+ async netVersion() {
802
+ return this.call("net_version", []);
803
+ }
804
+ /** `net_peerCount` — number of connected peers. */
805
+ async netPeerCount() {
806
+ return parseQuantityBig(await this.call("net_peerCount", []));
807
+ }
808
+ /** `net_listening` — whether the node accepts inbound peers. */
809
+ async netListening() {
810
+ return this.call("net_listening", []);
811
+ }
812
+ /** `web3_clientVersion` — server's client-version string. */
813
+ async web3ClientVersion() {
814
+ return this.call("web3_clientVersion", []);
815
+ }
816
+ /** `web3_sha3` — Keccak-256 of `data`. */
817
+ async web3Sha3(data) {
818
+ return this.call("web3_sha3", [data]);
819
+ }
820
+ // ---- lyth_* (Law §13.2 native namespace) --------------------------
821
+ /** `lyth_listProviders` — paged registry enumeration. */
822
+ async lythListProviders(capabilityMask, cursor = null, limit = 100) {
823
+ return this.call("lyth_listProviders", [capabilityMask, cursor, limit]);
824
+ }
825
+ /** `lyth_getRegistration` — single registry lookup. */
826
+ async lythGetRegistration(peerId) {
827
+ return this.call("lyth_getRegistration", [peerId]);
828
+ }
829
+ /** `lyth_registryStateProof` — Merkle proof for a registry entry. */
830
+ async lythRegistryStateProof(peerId) {
831
+ return this.call("lyth_registryStateProof", [peerId]);
832
+ }
833
+ /** `lyth_getAccountPolicy` — privacy posture for an account. */
834
+ async lythGetAccountPolicy(address) {
835
+ return this.call("lyth_getAccountPolicy", [address]);
836
+ }
837
+ /** `lyth_getAssetPolicy` — privacy posture for an asset. */
838
+ async lythGetAssetPolicy(tokenId) {
839
+ return this.call("lyth_getAssetPolicy", [tokenId]);
840
+ }
841
+ /** `lyth_getTokenBalances` — indexed per-asset balances for one address. */
842
+ async lythGetTokenBalances(address) {
843
+ return this.call("lyth_getTokenBalances", [address]);
844
+ }
845
+ /** `lyth_getAddressLabel` — indexed display/category label for one address. */
846
+ async lythGetAddressLabel(address) {
847
+ const v = await this.call("lyth_getAddressLabel", [address]);
848
+ if (v === null || v === void 0) return null;
849
+ return v;
850
+ }
851
+ /** `lyth_getAddressActivity` — indexed per-address activity timeline. */
852
+ async lythGetAddressActivity(address, limit = 50, cursor) {
853
+ const params = cursor === void 0 ? [address, limit] : [address, limit, cursor];
854
+ return this.call("lyth_getAddressActivity", params);
855
+ }
856
+ /** `lyth_addressActivityKind` — activity index coverage for one address. */
857
+ async lythAddressActivityKind(address) {
858
+ return this.call("lyth_addressActivityKind", [address]);
859
+ }
860
+ /** `lyth_decodeTx` — explorer-grade decoded transaction envelope. */
861
+ async lythDecodeTx(txHash) {
862
+ return this.call("lyth_decodeTx", [txHash]);
863
+ }
864
+ /** `lyth_gapRecords` — retained ingestion/indexing gaps for a block range. */
865
+ async lythGapRecords(fromBlock, toBlock) {
866
+ return this.call("lyth_gapRecords", [
867
+ encodeRpcU64Number(fromBlock, "fromBlock"),
868
+ encodeRpcU64Number(toBlock, "toBlock")
869
+ ]);
870
+ }
871
+ /** `lyth_dagParents` — parent vertices for a DAG round. */
872
+ async lythDagParents(round) {
873
+ return this.call("lyth_dagParents", [encodeRpcU64Number(round, "round")]);
874
+ }
875
+ /** `lyth_richList` — top holders for a token id. */
876
+ async lythRichList(tokenId, limit) {
877
+ const params = limit == null ? [tokenId] : [tokenId, limit];
878
+ return this.call("lyth_richList", params);
879
+ }
880
+ /** `lyth_clobMarket` — live CLOB market metadata for a market id. */
881
+ async lythClobMarket(marketId) {
882
+ return this.call("lyth_clobMarket", [marketId]);
883
+ }
884
+ /** `lyth_clobMarkets` — CLOB markets observed through indexed trades. */
885
+ async lythClobMarkets(limit) {
886
+ const params = limit == null ? [] : [limit];
887
+ return this.call("lyth_clobMarkets", params);
888
+ }
889
+ /** `lyth_clobTrades` — CLOB fills for one market. */
890
+ async lythClobTrades(marketId, limit = 50, cursor) {
891
+ const params = cursor === void 0 ? [marketId, limit] : [marketId, limit, cursor];
892
+ return this.call("lyth_clobTrades", params);
893
+ }
894
+ /** `lyth_clobOhlc` — CLOB OHLC candles for a market over a block range. */
895
+ async lythClobOhlc(marketId, fromBlock, toBlock, bucketBlocks) {
896
+ const params = fromBlock == null && toBlock == null && bucketBlocks == null ? [marketId] : [
897
+ marketId,
898
+ fromBlock == null ? null : encodeRpcU64Number(fromBlock, "fromBlock"),
899
+ toBlock == null ? null : encodeRpcU64Number(toBlock, "toBlock"),
900
+ bucketBlocks == null ? null : encodeRpcU64Number(bucketBlocks, "bucketBlocks")
901
+ ];
902
+ return this.call("lyth_clobOhlc", params);
903
+ }
904
+ /** `lyth_clobOrderBook` — live CLOB depth from canonical state. */
905
+ async lythClobOrderBook(marketId, levels) {
906
+ const params = levels == null ? [marketId] : [marketId, levels];
907
+ return this.call("lyth_clobOrderBook", params);
908
+ }
909
+ /** `lyth_txFeed` — paged global transaction feed. */
910
+ async lythTxFeed(limit = 50, cursor) {
911
+ const params = cursor === void 0 ? [limit] : [limit, cursor];
912
+ return this.call("lyth_txFeed", params);
913
+ }
914
+ /** `lyth_addressProfile` — live account + label + activity aggregate. */
915
+ async lythAddressProfile(address) {
916
+ return this.call("lyth_addressProfile", [address]);
917
+ }
918
+ /** `lyth_addressFlow` — recent indexed address-flow aggregate. */
919
+ async lythAddressFlow(address, limit = 250) {
920
+ return this.call("lyth_addressFlow", [address, limit]);
921
+ }
922
+ /** `lyth_search` — exact live resolver for hashes, addresses, blocks, and clusters. */
923
+ async lythSearch(query, limit = 10) {
924
+ return this.call("lyth_search", [query, limit]);
925
+ }
926
+ /** `lyth_chainStats` — compact live chain/indexer/mempool summary. */
927
+ async lythChainStats() {
928
+ return this.call("lyth_chainStats", []);
929
+ }
930
+ /** `lyth_mempoolStatus` — aggregate mempool snapshot. */
931
+ async lythMempoolStatus() {
932
+ return normalizeMempoolSnapshot(await this.call("lyth_mempoolStatus", []));
933
+ }
934
+ /** `lyth_mempoolPending` — pending txs for a sender. */
935
+ async lythMempoolPending(sender) {
936
+ return this.call("lyth_mempoolPending", [sender]);
937
+ }
938
+ /** `lyth_currentRound` — latest committed height. */
939
+ async lythCurrentRound() {
940
+ return normalizeRoundInfo(await this.call("lyth_currentRound", []));
941
+ }
942
+ /** `lyth_peerSummary` — public-safe aggregate peer-network diagnostics. */
943
+ async lythPeerSummary() {
944
+ return this.call("lyth_peerSummary", []);
945
+ }
946
+ /**
947
+ * `lyth_listActivePrecompiles` — milestone-gated precompile catalogue
948
+ * (OI-0170 / ADR-0015 §5).
949
+ */
950
+ async lythListActivePrecompiles(block = "latest") {
951
+ return this.call("lyth_listActivePrecompiles", [encodeBlockSelector(block)]);
952
+ }
953
+ /** `lyth_capabilities` — address-keyed precompile capability map. */
954
+ async lythCapabilities(block) {
955
+ const params = block === void 0 ? [] : [encodeBlockSelector(block)];
956
+ return this.call("lyth_capabilities", params);
957
+ }
958
+ /**
959
+ * `lyth_operatorCapabilities` — node-level availability for operator UI
960
+ * and explorer surfaces.
961
+ */
962
+ async lythOperatorCapabilities() {
963
+ return this.call("lyth_operatorCapabilities", []);
964
+ }
965
+ /** `lyth_indexerStatus` — indexer status; `null` when disabled. */
966
+ async lythIndexerStatus() {
967
+ const v = await this.call("lyth_indexerStatus", []);
968
+ if (v === null || v === void 0) return null;
969
+ return v;
970
+ }
971
+ /** `lyth_getStorageProof` — batched Merkle proofs. */
972
+ async lythGetStorageProof(address, slots) {
973
+ return this.call("lyth_getStorageProof", [address, slots]);
974
+ }
975
+ /** `lyth_getDelegations` — wallet delegation rows at a block. */
976
+ async lythGetDelegations(wallet, block) {
977
+ const params = block === void 0 ? [wallet] : [wallet, encodeBlockSelector(block)];
978
+ return this.call("lyth_getDelegations", params);
979
+ }
980
+ /** `lyth_getDelegationHistory` — indexed per-wallet delegation event timeline. */
981
+ async lythGetDelegationHistory(wallet, limit = 50, cursor) {
982
+ const params = cursor === void 0 ? [wallet, limit] : [wallet, limit, cursor];
983
+ return this.call("lyth_getDelegationHistory", params);
984
+ }
985
+ /** `lyth_getClusterDelegators` — delegator addresses for a cluster. */
986
+ async lythGetClusterDelegators(cluster, block) {
987
+ const params = block === void 0 ? [cluster] : [cluster, encodeBlockSelector(block)];
988
+ return this.call("lyth_getClusterDelegators", params);
989
+ }
990
+ /** `lyth_getDelegationCap` — active per-cluster cap at a block. */
991
+ async lythGetDelegationCap(block) {
992
+ const params = block === void 0 ? [] : [encodeBlockSelector(block)];
993
+ return this.call("lyth_getDelegationCap", params);
994
+ }
995
+ /** `lyth_getTpmAttestation` — TPM quote digest + EK id for a peer. */
996
+ async lythGetTpmAttestation(peerId, block) {
997
+ const params = block === void 0 ? [peerId] : [peerId, encodeBlockSelector(block)];
998
+ return this.call("lyth_getTpmAttestation", params);
999
+ }
1000
+ /** `lyth_getClusterEntity` — entity flag for a cluster. */
1001
+ async lythGetClusterEntity(cluster, block) {
1002
+ const params = block === void 0 ? [cluster] : [cluster, encodeBlockSelector(block)];
1003
+ return this.call("lyth_getClusterEntity", params);
1004
+ }
1005
+ /** `lyth_getEntityRatchet` — entity-ratchet snapshot at a block. */
1006
+ async lythGetEntityRatchet(block) {
1007
+ const params = block === void 0 ? [] : [encodeBlockSelector(block)];
1008
+ return this.call("lyth_getEntityRatchet", params);
1009
+ }
1010
+ /** `lyth_operatorInfo` — canonical operator identity envelope. */
1011
+ async lythOperatorInfo(operatorId) {
1012
+ return normalizeOperatorInfo(await this.call("lyth_operatorInfo", [operatorId]));
1013
+ }
1014
+ /** `lyth_getServiceProbe` — latest external reachability report for one public service. */
1015
+ async lythGetServiceProbe(peerId, serviceMask) {
1016
+ assertHexBytes(peerId, 32, "peerId");
1017
+ if (!isSinglePublicServiceProbeMask(serviceMask)) {
1018
+ throw SdkError.malformed("serviceMask must contain exactly one public-service bit");
1019
+ }
1020
+ const value = await this.call("lyth_getServiceProbe", [peerId, serviceMask]);
1021
+ if (value === null || value === void 0) return null;
1022
+ return normalizeServiceProbe(value);
1023
+ }
1024
+ /** `lyth_reportServiceProbe` — submit a pre-signed public-service probe report. */
1025
+ async lythReportServiceProbe(req) {
1026
+ assertHexBytes(req.peerId, 32, "peerId");
1027
+ if (!isValidPublicServiceProbeMask(req.serviceMask)) {
1028
+ throw SdkError.malformed("serviceMask must name one or more public-service bits");
1029
+ }
1030
+ if (!isConcreteServiceProbeStatus(req.status)) {
1031
+ throw SdkError.malformed("status must be reachable, degraded, or unreachable");
1032
+ }
1033
+ assertSafeUint32(req.latencyMs, "latencyMs");
1034
+ assertHexBytes(req.probeDigest, 32, "probeDigest");
1035
+ assertNonEmptyHex(req.signedRawTx, "signedRawTx");
1036
+ return this.call("lyth_reportServiceProbe", [req]);
1037
+ }
1038
+ /** `lyth_clusterStatus` — canonical cluster status envelope. */
1039
+ async lythClusterStatus(clusterId) {
1040
+ return normalizeClusterStatus(await this.call("lyth_clusterStatus", [clusterId]));
1041
+ }
1042
+ /** `lyth_clusterDirectory` — paged public cluster directory. */
1043
+ async lythClusterDirectory(page = 0, limit = 25) {
1044
+ return normalizeClusterDirectoryPage(
1045
+ await this.call("lyth_clusterDirectory", [page, limit])
1046
+ );
1047
+ }
1048
+ /** `lyth_clusters` — alias for `lyth_clusterDirectory`. */
1049
+ async lythClusters(page = 0, limit = 25) {
1050
+ return normalizeClusterDirectoryPage(await this.call("lyth_clusters", [page, limit]));
1051
+ }
1052
+ /**
1053
+ * `lyth_submitPendingChange` — operator-onboarding transport for the
1054
+ * pending-change ledger. Server validates the envelope shape.
1055
+ */
1056
+ async lythSubmitPendingChange(envelope) {
1057
+ return this.call("lyth_submitPendingChange", [envelope]);
1058
+ }
1059
+ /** `lyth_submitEncrypted` — submit a bincode-encoded encrypted envelope hex. */
1060
+ async lythSubmitEncrypted(envelopeHex) {
1061
+ return this.call("lyth_submitEncrypted", [envelopeHex]);
1062
+ }
1063
+ /** `lyth_getEncryptionKey` — cluster ML-KEM encapsulation key. */
1064
+ async lythGetEncryptionKey() {
1065
+ return this.call("lyth_getEncryptionKey", []);
1066
+ }
1067
+ /** `lyth_syncStatus` — DAG-sync driver snapshot. */
1068
+ async lythSyncStatus() {
1069
+ const v = await this.call("lyth_syncStatus", []);
1070
+ if (v === null || v === void 0) return null;
1071
+ return v;
1072
+ }
1073
+ /** `lyth_resolveOperatorAuthority` — operator id to authority index. */
1074
+ async lythResolveOperatorAuthority(operatorId) {
1075
+ return normalizeOperatorAuthority(
1076
+ await this.call("lyth_resolveOperatorAuthority", [operatorId])
1077
+ );
1078
+ }
1079
+ /** `lyth_signingActivity` — recent per-round signing participation. */
1080
+ async lythSigningActivity(authorityIndex, limit) {
1081
+ const params = limit == null ? [authorityIndex] : [authorityIndex, limit];
1082
+ return normalizeSigningActivity(await this.call("lyth_signingActivity", params));
1083
+ }
1084
+ /** `lyth_upcomingDuties` — deterministic upcoming duty windows. */
1085
+ async lythUpcomingDuties(authorityIndex, horizonRounds) {
1086
+ const params = horizonRounds == null ? [authorityIndex] : [authorityIndex, horizonRounds];
1087
+ return normalizeUpcomingDuties(await this.call("lyth_upcomingDuties", params));
1088
+ }
1089
+ /** `lyth_operatorRisk` — miss-rate and jail-status window. */
1090
+ async lythOperatorRisk(authorityIndex, windowRounds) {
1091
+ const params = windowRounds == null ? [authorityIndex] : [authorityIndex, windowRounds];
1092
+ return normalizeOperatorRisk(await this.call("lyth_operatorRisk", params));
1093
+ }
1094
+ /** `lyth_upgradeStatus` — signed network-upgrade readiness at a height. */
1095
+ async lythUpgradeStatus(block) {
1096
+ const params = block === void 0 ? [] : [encodeBlockSelector(block)];
1097
+ return this.call("lyth_upgradeStatus", params);
1098
+ }
1099
+ /** `lyth_runtimeProvenance` — public-safe build/runtime provenance. */
1100
+ async lythRuntimeProvenance() {
1101
+ return this.call("lyth_runtimeProvenance", []);
1102
+ }
1103
+ /** `lyth_txStatus` — discriminated transaction lookup outcome. */
1104
+ async lythTxStatus(txHash) {
1105
+ return this.call("lyth_txStatus", [txHash]);
1106
+ }
1107
+ /** `lyth_verticesAtRound` — per-vertex authorship observed at a DAG round. */
1108
+ async lythVerticesAtRound(round) {
1109
+ return this.call("lyth_verticesAtRound", [
1110
+ encodeRpcU64Number(round, "round")
1111
+ ]);
1112
+ }
1113
+ /** `lyth_metricsRange` — retained telemetry series when the node has them. */
1114
+ async lythMetricsRange(selectors, range) {
1115
+ const params = range === void 0 ? [selectors] : [
1116
+ selectors,
1117
+ range === null ? null : [
1118
+ encodeRpcU64Number(range[0], "fromBlock"),
1119
+ encodeRpcU64Number(range[1], "toBlock")
1120
+ ]
1121
+ ];
1122
+ return this.call("lyth_metricsRange", params);
1123
+ }
1124
+ /** `lyth_getLatestCheckpoint` — latest PQ-finality checkpoint rows. */
1125
+ async lythGetLatestCheckpoint(belowHeight) {
1126
+ const params = belowHeight === void 0 ? [] : [encodeOptionalHeight(belowHeight)];
1127
+ return this.call("lyth_getLatestCheckpoint", params);
1128
+ }
1129
+ /** `lyth_getClusterResignations` — in-flight + applied operator resignations. */
1130
+ async lythGetClusterResignations(operator, status) {
1131
+ const params = status === void 0 ? operator == null ? [] : [operator] : [operator ?? null, status];
1132
+ return this.call("lyth_getClusterResignations", params);
1133
+ }
1134
+ /** `lyth_getBlsRoundCertificate` — round-advancement BLS aggregate. */
1135
+ async lythGetBlsRoundCertificate(round) {
1136
+ return this.call("lyth_getBlsRoundCertificate", [encodeRpcInteger(round)]);
1137
+ }
1138
+ /** `lyth_getLeaderCertificate` — leader-vote BLS aggregate for a block ref. */
1139
+ async lythGetLeaderCertificate(round, authority, digest) {
1140
+ return this.call("lyth_getLeaderCertificate", [encodeRpcInteger(round), authority, digest]);
1141
+ }
1142
+ /** `lyth_getDacCertificate` — data-availability certificate for a block ref. */
1143
+ async lythGetDacCertificate(round, authority, digest) {
1144
+ return this.call("lyth_getDacCertificate", [encodeRpcInteger(round), authority, digest]);
1145
+ }
1146
+ /** `lyth_subscribe` — WebSocket-only; returns an RPC error over HTTP. */
1147
+ async lythSubscribe(channel) {
1148
+ return this.call("lyth_subscribe", [channel]);
1149
+ }
1150
+ /** `lyth_unsubscribe` — counterpart to `lythSubscribe`. */
1151
+ async lythUnsubscribe(subId) {
1152
+ return this.call("lyth_unsubscribe", [subId]);
1153
+ }
1154
+ // ---- debug_* ------------------------------------------------------
1155
+ // Server-side gated by `RpcConfig::debug_enabled`. When the namespace
1156
+ // is disabled, every call surfaces as `SdkError.rpc`.
1157
+ /** `debug_traceTransaction` — revm trace for a confirmed tx. */
1158
+ async debugTraceTransaction(txHash) {
1159
+ return this.call("debug_traceTransaction", [txHash]);
1160
+ }
1161
+ /** `debug_traceCall` — revm trace for a dry-run. */
1162
+ async debugTraceCall(request, block = "latest") {
1163
+ return this.call("debug_traceCall", [request, encodeBlockSelector(block)]);
1164
+ }
1165
+ /** `debug_traceBlockByNumber` — revm traces for an entire block. */
1166
+ async debugTraceBlockByNumber(block) {
1167
+ return this.call("debug_traceBlockByNumber", [encodeBlockSelector(block)]);
1168
+ }
1169
+ /** `debug_mempoolDump` — full mempool snapshot. */
1170
+ async debugMempoolDump() {
1171
+ return normalizeMempoolSnapshot(await this.call("debug_mempoolDump", []));
1172
+ }
1173
+ /** `debug_p2pPeers` — connected libp2p peer list. */
1174
+ async debugP2pPeers() {
1175
+ return this.call("debug_p2pPeers", []);
1176
+ }
1177
+ /** `debug_stateDiff` — state-diff for a block range. */
1178
+ async debugStateDiff(params) {
1179
+ return this.call("debug_stateDiff", params);
1180
+ }
1181
+ /** `debug_chainReorg` — testnet-only reorg trigger. */
1182
+ async debugChainReorg(params) {
1183
+ return this.call("debug_chainReorg", params);
1184
+ }
1185
+ // ---- mesh_* -------------------------------------------------------
1186
+ /** `mesh_buildUnsignedTx` — build an unsigned transaction envelope. */
1187
+ async meshBuildUnsignedTx(intent) {
1188
+ return this.call("mesh_buildUnsignedTx", [intent]);
1189
+ }
1190
+ /** `mesh_combineTx` — combine an unsigned envelope with a wallet signature. */
1191
+ async meshCombineTx(unsignedTx, signatureHex, algo, pubkeyHex) {
1192
+ const params = algo === void 0 ? [unsignedTx, signatureHex] : pubkeyHex === void 0 ? [unsignedTx, signatureHex, algo] : [unsignedTx, signatureHex, algo, pubkeyHex];
1193
+ return this.call("mesh_combineTx", params);
1194
+ }
1195
+ /** `mesh_decodeTx` — decode a signed or unsigned mesh envelope. */
1196
+ async meshDecodeTx(envelopeHex, signed = false) {
1197
+ return this.call("mesh_decodeTx", [envelopeHex, signed]);
1198
+ }
1199
+ /** `mesh_submitTx` — submit a signed mesh envelope. */
1200
+ async meshSubmitTx(signedTx) {
1201
+ return this.call("mesh_submitTx", [signedTx]);
1202
+ }
1203
+ };
1204
+ function parseQuantityBig(hex) {
1205
+ if (!hex) return 0n;
1206
+ const rest = hex.startsWith("0x") || hex.startsWith("0X") ? hex.slice(2) : hex;
1207
+ if (rest.length === 0) return 0n;
1208
+ if (!/^[0-9a-fA-F]+$/.test(rest)) {
1209
+ throw SdkError.malformed(`invalid hex quantity: ${hex}`);
1210
+ }
1211
+ return BigInt(`0x${rest}`);
1212
+ }
1213
+ function parseQuantity(hex) {
1214
+ const big = parseQuantityBig(hex);
1215
+ if (big > BigInt(Number.MAX_SAFE_INTEGER)) {
1216
+ throw SdkError.malformed(`hex quantity exceeds safe integer: ${hex}`);
1217
+ }
1218
+ return Number(big);
1219
+ }
1220
+ function encodeRpcInteger(v) {
1221
+ if (typeof v === "bigint") return `0x${v.toString(16)}`;
1222
+ return v;
1223
+ }
1224
+ function encodeOptionalHeight(v) {
1225
+ if (v === null) return null;
1226
+ return encodeRpcInteger(v);
1227
+ }
1228
+ function encodeRpcU64Number(v, label) {
1229
+ return parseRpcNumber(v, label);
1230
+ }
1231
+ function parseRpcBigint(value, label) {
1232
+ if (typeof value === "bigint") {
1233
+ if (value < 0n) {
1234
+ throw SdkError.malformed(`${label} must be a non-negative quantity`);
1235
+ }
1236
+ return value;
1237
+ }
1238
+ if (typeof value === "number") {
1239
+ if (!Number.isSafeInteger(value) || value < 0) {
1240
+ throw SdkError.malformed(`${label} must be a non-negative safe integer`);
1241
+ }
1242
+ return BigInt(value);
1243
+ }
1244
+ if (typeof value === "string") {
1245
+ if (value.startsWith("0x") || value.startsWith("0X")) return parseQuantityBig(value);
1246
+ if (/^\d+$/.test(value)) return BigInt(value);
1247
+ }
1248
+ throw SdkError.malformed(`${label} must be a bigint-compatible quantity`);
1249
+ }
1250
+ function parseRpcNumber(value, label) {
1251
+ const big = parseRpcBigint(value, label);
1252
+ if (big > BigInt(Number.MAX_SAFE_INTEGER)) {
1253
+ throw SdkError.malformed(`${label} exceeds safe integer range`);
1254
+ }
1255
+ return Number(big);
1256
+ }
1257
+ function parseRpcNumberNullable(value, label) {
1258
+ return value === null || value === void 0 ? null : parseRpcNumber(value, label);
1259
+ }
1260
+ function parseRpcBigintNullable(value, label) {
1261
+ return value === null || value === void 0 ? null : parseRpcBigint(value, label);
1262
+ }
1263
+ function parseStringNullable(value) {
1264
+ return value === null || value === void 0 ? null : String(value);
1265
+ }
1266
+ function expectObject(value, label) {
1267
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
1268
+ throw SdkError.malformed(`${label} must be an object`);
1269
+ }
1270
+ return value;
1271
+ }
1272
+ function normalizeServiceProbe(value) {
1273
+ const row = expectObject(value, "service probe response");
1274
+ return {
1275
+ serviceMask: parseRpcNumber(row["serviceMask"], "service probe serviceMask"),
1276
+ status: String(row["status"]),
1277
+ statusCode: parseRpcNumber(row["statusCode"], "service probe statusCode"),
1278
+ lastProbeBlock: parseRpcNumber(row["lastProbeBlock"], "service probe lastProbeBlock"),
1279
+ latencyMs: parseRpcNumber(row["latencyMs"], "service probe latencyMs"),
1280
+ probeDigest: String(row["probeDigest"]),
1281
+ reporter: String(row["reporter"])
1282
+ };
1283
+ }
1284
+ function assertSafeUint32(value, label) {
1285
+ if (!Number.isInteger(value) || value < 0 || value > 4294967295) {
1286
+ throw SdkError.malformed(`${label} must be a uint32`);
1287
+ }
1288
+ }
1289
+ function assertHexBytes(value, expectedLen, label) {
1290
+ const body = hexBody(value, label);
1291
+ if (body.length !== expectedLen * 2) {
1292
+ throw SdkError.malformed(`${label} must be ${expectedLen} bytes`);
1293
+ }
1294
+ }
1295
+ function assertNonEmptyHex(value, label) {
1296
+ const body = hexBody(value, label);
1297
+ if (body.length === 0) {
1298
+ throw SdkError.malformed(`${label} must be non-empty`);
1299
+ }
1300
+ }
1301
+ function hexBody(value, label) {
1302
+ const body = value.startsWith("0x") || value.startsWith("0X") ? value.slice(2) : value;
1303
+ if (body.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(body)) {
1304
+ throw SdkError.malformed(`${label} must be hex bytes`);
1305
+ }
1306
+ return body;
1307
+ }
1308
+ function normalizeOperatorInfo(value) {
1309
+ const row = expectObject(value, "operator info response");
1310
+ const activeClusterIds = row["activeClusterIds"];
1311
+ if (!Array.isArray(activeClusterIds)) {
1312
+ throw SdkError.malformed("operator info activeClusterIds must be an array");
1313
+ }
1314
+ const capability = row["capability"];
1315
+ return {
1316
+ operatorId: String(row["operatorId"]),
1317
+ moniker: parseStringNullable(row["moniker"]),
1318
+ alias: parseStringNullable(row["alias"]),
1319
+ chainAddress: String(row["chainAddress"]),
1320
+ bonded: Boolean(row["bonded"]),
1321
+ commissionBps: parseRpcNumberNullable(row["commissionBps"], "operator info commissionBps"),
1322
+ delegationCount: parseRpcNumberNullable(
1323
+ row["delegationCount"],
1324
+ "operator info delegationCount"
1325
+ ),
1326
+ bondedAmount: String(row["bondedAmount"]),
1327
+ activeClusterIds: activeClusterIds.map(
1328
+ (v, i) => parseRpcNumber(v, `operator info activeClusterIds[${i}]`)
1329
+ ),
1330
+ operatorKeyFingerprint: parseStringNullable(row["operatorKeyFingerprint"]),
1331
+ blsKeyFingerprint: parseStringNullable(row["blsKeyFingerprint"]),
1332
+ lifecycleState: String(row["lifecycleState"]),
1333
+ capability: capability && typeof capability === "object" && !Array.isArray(capability) ? capability : {}
1334
+ };
1335
+ }
1336
+ function normalizeClusterMember(value, label) {
1337
+ const row = expectObject(value, label);
1338
+ return {
1339
+ operatorId: String(row["operatorId"]),
1340
+ blsPubkey: String(row["blsPubkey"]),
1341
+ state: String(row["state"])
1342
+ };
1343
+ }
1344
+ function normalizeClusterStatus(value) {
1345
+ const row = expectObject(value, "cluster status response");
1346
+ const members = row["members"];
1347
+ if (!Array.isArray(members)) {
1348
+ throw SdkError.malformed("cluster status members must be an array");
1349
+ }
1350
+ return {
1351
+ clusterId: parseRpcNumber(row["clusterId"], "cluster status clusterId"),
1352
+ threshold: parseRpcNumber(row["threshold"], "cluster status threshold"),
1353
+ size: parseRpcNumber(row["size"], "cluster status size"),
1354
+ live: parseRpcNumber(row["live"], "cluster status live"),
1355
+ lagging: parseRpcNumber(row["lagging"], "cluster status lagging"),
1356
+ offline: parseRpcNumber(row["offline"], "cluster status offline"),
1357
+ maintenance: parseRpcNumber(row["maintenance"], "cluster status maintenance"),
1358
+ members: members.map((member, i) => normalizeClusterMember(member, `cluster status members[${i}]`)),
1359
+ epoch: parseRpcBigintNullable(row["epoch"], "cluster status epoch"),
1360
+ round: parseRpcBigintNullable(row["round"], "cluster status round"),
1361
+ quorum: String(row["quorum"]),
1362
+ reputationScore: parseRpcNumberNullable(
1363
+ row["reputationScore"],
1364
+ "cluster status reputationScore"
1365
+ ),
1366
+ livenessScore: parseRpcNumberNullable(row["livenessScore"], "cluster status livenessScore"),
1367
+ lastUpdateHeight: parseRpcBigint(row["lastUpdateHeight"], "cluster status lastUpdateHeight")
1368
+ };
1369
+ }
1370
+ function normalizeClusterDirectoryEntry(value, label) {
1371
+ const row = expectObject(value, label);
1372
+ const regionDiversity = row["regionDiversity"];
1373
+ if (regionDiversity !== null && regionDiversity !== void 0 && !Array.isArray(regionDiversity)) {
1374
+ throw SdkError.malformed(`${label}.regionDiversity must be an array or null`);
1375
+ }
1376
+ return {
1377
+ clusterId: parseRpcNumber(row["clusterId"], `${label}.clusterId`),
1378
+ size: parseRpcNumber(row["size"], `${label}.size`),
1379
+ threshold: parseRpcNumber(row["threshold"], `${label}.threshold`),
1380
+ aggregateHealth: String(row["aggregateHealth"]),
1381
+ regionDiversity: Array.isArray(regionDiversity) ? regionDiversity.map(String) : null,
1382
+ active: Boolean(row["active"])
1383
+ };
1384
+ }
1385
+ function normalizeClusterDirectoryPage(value) {
1386
+ const row = expectObject(value, "cluster directory response");
1387
+ const clusters = row["clusters"];
1388
+ if (!Array.isArray(clusters)) {
1389
+ throw SdkError.malformed("cluster directory clusters must be an array");
1390
+ }
1391
+ return {
1392
+ page: parseRpcNumber(row["page"], "cluster directory page"),
1393
+ limit: parseRpcNumber(row["limit"], "cluster directory limit"),
1394
+ totalClusters: parseRpcNumber(row["totalClusters"], "cluster directory totalClusters"),
1395
+ clusters: clusters.map(
1396
+ (cluster, i) => normalizeClusterDirectoryEntry(cluster, `cluster directory clusters[${i}]`)
1397
+ )
1398
+ };
1399
+ }
1400
+ function normalizeOperatorAuthority(value) {
1401
+ const row = expectObject(value, "operator authority response");
1402
+ return {
1403
+ schemaVersion: parseRpcNumber(row["schemaVersion"], "operator authority schemaVersion"),
1404
+ operatorId: String(row["operatorId"]),
1405
+ authorityIndex: parseRpcNumber(row["authorityIndex"], "operator authority authorityIndex"),
1406
+ blsPubkey: String(row["blsPubkey"]),
1407
+ active: Boolean(row["active"])
1408
+ };
1409
+ }
1410
+ function normalizeSigningActivity(value) {
1411
+ const row = expectObject(value, "signing activity response");
1412
+ const entries = row["entries"];
1413
+ if (!Array.isArray(entries)) {
1414
+ throw SdkError.malformed("signing activity entries must be an array");
1415
+ }
1416
+ return {
1417
+ schemaVersion: parseRpcNumber(row["schemaVersion"], "signing activity schemaVersion"),
1418
+ authorityIndex: parseRpcNumber(row["authorityIndex"], "signing activity authorityIndex"),
1419
+ currentRound: parseRpcBigint(row["currentRound"], "signing activity currentRound"),
1420
+ limit: parseRpcNumber(row["limit"], "signing activity limit"),
1421
+ entries: entries.map((entry, i) => {
1422
+ const e = expectObject(entry, `signing activity entries[${i}]`);
1423
+ return {
1424
+ round: parseRpcBigint(e["round"], `signing activity entries[${i}].round`),
1425
+ status: String(e["status"])
1426
+ };
1427
+ })
1428
+ };
1429
+ }
1430
+ function normalizeDutyAbsence(value, label) {
1431
+ const row = expectObject(value, label);
1432
+ return { reason: String(row["reason"]) };
1433
+ }
1434
+ function normalizeKeyRotationWindow(value) {
1435
+ const row = expectObject(value, "upcoming duties keyRotation");
1436
+ if ("nextRound" in row) {
1437
+ return {
1438
+ nextRound: parseRpcBigint(row["nextRound"], "upcoming duties keyRotation.nextRound"),
1439
+ epochLengthRounds: parseRpcBigint(
1440
+ row["epochLengthRounds"],
1441
+ "upcoming duties keyRotation.epochLengthRounds"
1442
+ )
1443
+ };
1444
+ }
1445
+ return { reason: String(row["reason"]) };
1446
+ }
1447
+ function normalizeUpcomingDuties(value) {
1448
+ const row = expectObject(value, "upcoming duties response");
1449
+ const duties = expectObject(row["duties"], "upcoming duties duties");
1450
+ const attestation = expectObject(duties["attestation"], "upcoming duties attestation");
1451
+ return {
1452
+ schemaVersion: parseRpcNumber(row["schemaVersion"], "upcoming duties schemaVersion"),
1453
+ authorityIndex: parseRpcNumber(row["authorityIndex"], "upcoming duties authorityIndex"),
1454
+ currentRound: parseRpcBigint(row["currentRound"], "upcoming duties currentRound"),
1455
+ horizonRounds: parseRpcNumber(row["horizonRounds"], "upcoming duties horizonRounds"),
1456
+ duties: {
1457
+ attestation: {
1458
+ startRound: parseRpcBigint(attestation["startRound"], "upcoming duties attestation.startRound"),
1459
+ endRound: parseRpcBigint(attestation["endRound"], "upcoming duties attestation.endRound"),
1460
+ kind: String(attestation["kind"])
1461
+ },
1462
+ blockProduction: normalizeDutyAbsence(
1463
+ duties["blockProduction"],
1464
+ "upcoming duties blockProduction"
1465
+ ),
1466
+ sync: normalizeDutyAbsence(duties["sync"], "upcoming duties sync"),
1467
+ keyRotation: normalizeKeyRotationWindow(duties["keyRotation"])
1468
+ }
1469
+ };
1470
+ }
1471
+ function normalizeJailStatus(value) {
1472
+ const row = expectObject(value, "operator risk jailStatus");
1473
+ if ("jailed" in row || "tombstoned" in row) {
1474
+ return {
1475
+ jailed: Boolean(row["jailed"]),
1476
+ tombstoned: Boolean(row["tombstoned"]),
1477
+ jailedUntilHeight: parseRpcBigint(
1478
+ row["jailedUntilHeight"],
1479
+ "operator risk jailStatus.jailedUntilHeight"
1480
+ ),
1481
+ unjailCount: parseRpcBigint(row["unjailCount"], "operator risk jailStatus.unjailCount")
1482
+ };
1483
+ }
1484
+ return { reason: String(row["reason"]) };
1485
+ }
1486
+ function normalizeOperatorRisk(value) {
1487
+ const row = expectObject(value, "operator risk response");
1488
+ const reasons = row["reasons"];
1489
+ if (!Array.isArray(reasons)) {
1490
+ throw SdkError.malformed("operator risk reasons must be an array");
1491
+ }
1492
+ return {
1493
+ schemaVersion: parseRpcNumber(row["schemaVersion"], "operator risk schemaVersion"),
1494
+ authorityIndex: parseRpcNumber(row["authorityIndex"], "operator risk authorityIndex"),
1495
+ dataHeight: parseRpcBigint(row["dataHeight"], "operator risk dataHeight"),
1496
+ windowRounds: parseRpcNumber(row["windowRounds"], "operator risk windowRounds"),
1497
+ missedRounds: parseRpcNumber(row["missedRounds"], "operator risk missedRounds"),
1498
+ observedRounds: parseRpcNumber(row["observedRounds"], "operator risk observedRounds"),
1499
+ missRateBps: parseRpcNumber(row["missRateBps"], "operator risk missRateBps"),
1500
+ thresholdBps: parseRpcNumber(row["thresholdBps"], "operator risk thresholdBps"),
1501
+ remainingHeadroomBps: parseRpcNumber(
1502
+ row["remainingHeadroomBps"],
1503
+ "operator risk remainingHeadroomBps"
1504
+ ),
1505
+ jailStatus: normalizeJailStatus(row["jailStatus"]),
1506
+ reasons: reasons.map(String)
1507
+ };
1508
+ }
1509
+ function normalizeBlockHeader(value) {
1510
+ if (value === null || value === void 0) return null;
1511
+ if (!value || typeof value !== "object") {
1512
+ throw SdkError.malformed("block header must be an object or null");
1513
+ }
1514
+ const h = value;
1515
+ return {
1516
+ number: parseRpcBigint(h["number"], "block header number"),
1517
+ hash: String(h["hash"]),
1518
+ parent_hash: String(h["parent_hash"]),
1519
+ state_root: String(h["state_root"]),
1520
+ timestamp: parseRpcBigint(h["timestamp"], "block header timestamp"),
1521
+ gas_used: parseRpcBigint(h["gas_used"], "block header gas_used"),
1522
+ gas_limit: parseRpcBigint(h["gas_limit"], "block header gas_limit")
1523
+ };
1524
+ }
1525
+ function normalizeRoundInfo(value) {
1526
+ if (!value || typeof value !== "object") {
1527
+ throw SdkError.malformed("round info must be an object");
1528
+ }
1529
+ const row = value;
1530
+ return {
1531
+ height: parseRpcBigint(row["height"], "round height")
1532
+ };
1533
+ }
1534
+ function normalizeMempoolSnapshot(value) {
1535
+ if (!value || typeof value !== "object") {
1536
+ throw SdkError.malformed("mempool snapshot must be an object");
1537
+ }
1538
+ const row = value;
1539
+ const bytesByClass = row["bytes_by_class"];
1540
+ if (!Array.isArray(bytesByClass) || bytesByClass.length !== 7) {
1541
+ throw SdkError.malformed("mempool bytes_by_class must contain 7 entries");
1542
+ }
1543
+ return {
1544
+ count_ready: parseRpcBigint(row["count_ready"], "mempool count_ready"),
1545
+ count_pending: parseRpcBigint(row["count_pending"], "mempool count_pending"),
1546
+ mailbox_depth: parseRpcBigint(row["mailbox_depth"], "mempool mailbox_depth"),
1547
+ bytes_by_class: bytesByClass.map((v, i) => parseRpcBigint(v, `mempool bytes_by_class[${i}]`))
1548
+ };
1549
+ }
1550
+
1551
+ // src/address.ts
1552
+ var ADDRESS_HRP = "mono";
1553
+ var CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
1554
+ var CHARSET_MAP = new Map([...CHARSET].map((c, i) => [c, i]));
1555
+ var BECH32M_CONST = 734539939;
1556
+ var HEX_20_BYTE_RE = /^0x[0-9a-fA-F]{40}$/;
1557
+ var AddressError = class extends Error {
1558
+ constructor(message) {
1559
+ super(message);
1560
+ this.name = "AddressError";
1561
+ }
1562
+ };
1563
+ function hexToAddressBytes(address) {
1564
+ if (!HEX_20_BYTE_RE.test(address)) {
1565
+ throw new AddressError("expected 0x-prefixed 20-byte hex address");
1566
+ }
1567
+ const out = new Uint8Array(20);
1568
+ const body = address.slice(2);
1569
+ for (let i = 0; i < 20; i++) {
1570
+ out[i] = Number.parseInt(body.slice(i * 2, i * 2 + 2), 16);
1571
+ }
1572
+ return out;
1573
+ }
1574
+ function addressBytesToHex(address) {
1575
+ const bytes = expectLength2(address, 20, "address");
1576
+ return `0x${[...bytes].map((b) => b.toString(16).padStart(2, "0")).join("")}`;
1577
+ }
1578
+ function addressToBech32(address) {
1579
+ const bytes = typeof address === "string" ? hexToAddressBytes(address) : expectLength2(address, 20, "address");
1580
+ const words = convertBits([...bytes], 8, 5, true);
1581
+ const checksum = createChecksum(ADDRESS_HRP, words);
1582
+ return `${ADDRESS_HRP}1${[...words, ...checksum].map((v) => CHARSET[v]).join("")}`;
1583
+ }
1584
+ function bech32ToAddressBytes(address) {
1585
+ const parsed = decodeBech32m(address);
1586
+ if (parsed.hrp !== ADDRESS_HRP) {
1587
+ throw new AddressError(`unexpected hrp '${parsed.hrp}', expected '${ADDRESS_HRP}'`);
1588
+ }
1589
+ const bytes = convertBits(parsed.data, 5, 8, false);
1590
+ if (bytes.length !== 20) {
1591
+ throw new AddressError(`expected 20-byte payload, got ${bytes.length} bytes`);
1592
+ }
1593
+ return Uint8Array.from(bytes);
1594
+ }
1595
+ function bech32ToAddress(address) {
1596
+ return addressBytesToHex(bech32ToAddressBytes(address));
1597
+ }
1598
+ function parseAddress(address) {
1599
+ if (address.startsWith("0x") || address.startsWith("0X")) {
1600
+ return hexToAddressBytes(address);
1601
+ }
1602
+ return bech32ToAddressBytes(address);
1603
+ }
1604
+ function normalizeAddressHex(address) {
1605
+ return addressBytesToHex(parseAddress(address));
1606
+ }
1607
+ function decodeBech32m(input) {
1608
+ if (input.length < 8) {
1609
+ throw new AddressError("bech32m address is too short");
1610
+ }
1611
+ const hasLower = input !== input.toUpperCase();
1612
+ const hasUpper = input !== input.toLowerCase();
1613
+ if (hasLower && hasUpper) {
1614
+ throw new AddressError("bech32m address cannot mix upper and lower case");
1615
+ }
1616
+ const s = input.toLowerCase();
1617
+ const sep = s.lastIndexOf("1");
1618
+ if (sep <= 0 || sep + 7 > s.length) {
1619
+ throw new AddressError("bech32m separator/checksum shape is invalid");
1620
+ }
1621
+ const hrp = s.slice(0, sep);
1622
+ const values = [];
1623
+ for (const c of s.slice(sep + 1)) {
1624
+ const v = CHARSET_MAP.get(c);
1625
+ if (v === void 0) {
1626
+ throw new AddressError(`invalid bech32m character '${c}'`);
1627
+ }
1628
+ values.push(v);
1629
+ }
1630
+ if (!verifyChecksum(hrp, values)) {
1631
+ throw new AddressError("bech32m checksum mismatch");
1632
+ }
1633
+ return { hrp, data: values.slice(0, -6) };
1634
+ }
1635
+ function hrpExpand(hrp) {
1636
+ const high = [...hrp].map((c) => c.charCodeAt(0) >> 5);
1637
+ const low = [...hrp].map((c) => c.charCodeAt(0) & 31);
1638
+ return [...high, 0, ...low];
1639
+ }
1640
+ function polymod(values) {
1641
+ const generators = [996825010, 642813549, 513874426, 1027748829, 705979059];
1642
+ let chk = 1;
1643
+ for (const value of values) {
1644
+ const top = chk >> 25;
1645
+ chk = (chk & 33554431) << 5 ^ value;
1646
+ for (let i = 0; i < 5; i++) {
1647
+ if ((top >> i & 1) === 1) {
1648
+ chk ^= generators[i];
1649
+ }
1650
+ }
1651
+ }
1652
+ return chk >>> 0;
1653
+ }
1654
+ function createChecksum(hrp, data) {
1655
+ const values = [...hrpExpand(hrp), ...data, 0, 0, 0, 0, 0, 0];
1656
+ const mod = polymod(values) ^ BECH32M_CONST;
1657
+ const out = [];
1658
+ for (let p = 0; p < 6; p++) {
1659
+ out.push(mod >> 5 * (5 - p) & 31);
1660
+ }
1661
+ return out;
1662
+ }
1663
+ function verifyChecksum(hrp, values) {
1664
+ return polymod([...hrpExpand(hrp), ...values]) === BECH32M_CONST;
1665
+ }
1666
+ function convertBits(data, fromBits, toBits, pad) {
1667
+ let acc = 0;
1668
+ let bits = 0;
1669
+ const ret = [];
1670
+ const maxv = (1 << toBits) - 1;
1671
+ const maxAcc = (1 << fromBits + toBits - 1) - 1;
1672
+ for (const value of data) {
1673
+ if (value < 0 || value >> fromBits !== 0) {
1674
+ throw new AddressError("invalid address payload value");
1675
+ }
1676
+ acc = (acc << fromBits | value) & maxAcc;
1677
+ bits += fromBits;
1678
+ while (bits >= toBits) {
1679
+ bits -= toBits;
1680
+ ret.push(acc >> bits & maxv);
1681
+ }
1682
+ }
1683
+ if (pad) {
1684
+ if (bits > 0) {
1685
+ ret.push(acc << toBits - bits & maxv);
1686
+ }
1687
+ } else if (bits >= fromBits || (acc << toBits - bits & maxv) !== 0) {
1688
+ throw new AddressError("invalid bech32m padding");
1689
+ }
1690
+ return ret;
1691
+ }
1692
+ function expectLength2(value, len, name) {
1693
+ if (value.length !== len) {
1694
+ throw new AddressError(`${name} must be ${len} bytes`);
1695
+ }
1696
+ return value instanceof Uint8Array ? value : Uint8Array.from(value);
1697
+ }
1698
+
1699
+ // src/spending-policy.ts
1700
+ var SET_POLICY_CLAIM_DOMAIN_TAG = "lyth.spending-policy.claim.v1";
1701
+ var ML_DSA_65_PUBLIC_KEY_LEN = 1952;
1702
+ var ML_DSA_65_SIGNATURE_LEN = 3309;
1703
+ var SPENDING_POLICY_SELECTORS = {
1704
+ setPolicy: "0xd6a518b2",
1705
+ setPolicyClaim: "0x08d78f9c",
1706
+ claimPolicyByAddress: "0xc2397fe9",
1707
+ enable: "0x5bfa1b68",
1708
+ disable: "0xe6c09edf",
1709
+ recordSpend: "0xdca04292"
1710
+ };
1711
+ var SpendingPolicyError = class extends Error {
1712
+ constructor(message) {
1713
+ super(message);
1714
+ this.name = "SpendingPolicyError";
1715
+ }
1716
+ };
1717
+ function spendingPolicyAddressHex() {
1718
+ return PRECOMPILE_ADDRESSES.SPENDING_POLICY.toLowerCase();
1719
+ }
1720
+ function composeClaimBoundMessage(chainId, args, opts) {
1721
+ const precompileAddress = toAddressBytes(opts?.precompileAddress ?? PRECOMPILE_ADDRESSES.SPENDING_POLICY);
1722
+ const normalized = normalizeArgs(args);
1723
+ return concatBytes2(
1724
+ new TextEncoder().encode(SET_POLICY_CLAIM_DOMAIN_TAG),
1725
+ uint64Bytes(chainId, "chainId"),
1726
+ precompileAddress,
1727
+ normalized.subAccount,
1728
+ normalized.principal,
1729
+ uint128Bytes(normalized.dailyCapWei, "dailyCapWei"),
1730
+ uint128Bytes(normalized.perTxCapWei, "perTxCapWei"),
1731
+ normalized.allowRoot,
1732
+ normalized.denyRoot,
1733
+ uint64Bytes(opts?.expectedPolicyVersion ?? 0n, "expectedPolicyVersion")
1734
+ );
1735
+ }
1736
+ function encodeSetPolicyCalldata(args) {
1737
+ const normalized = normalizeArgs(args);
1738
+ return bytesToHex2(
1739
+ concatBytes2(
1740
+ hexToBytes2(SPENDING_POLICY_SELECTORS.setPolicy),
1741
+ encodePolicyWords(normalized)
1742
+ )
1743
+ );
1744
+ }
1745
+ function encodeSetPolicyClaimCalldata(args, subAccountPubkey, subAccountSig) {
1746
+ const normalized = normalizeArgs(args);
1747
+ const pubkey = toBytes2(subAccountPubkey);
1748
+ const sig = toBytes2(subAccountSig);
1749
+ if (pubkey.length !== ML_DSA_65_PUBLIC_KEY_LEN) {
1750
+ throw new SpendingPolicyError(
1751
+ `subAccountPubkey must be ${ML_DSA_65_PUBLIC_KEY_LEN} bytes, got ${pubkey.length}`
1752
+ );
1753
+ }
1754
+ if (sig.length !== ML_DSA_65_SIGNATURE_LEN) {
1755
+ throw new SpendingPolicyError(
1756
+ `subAccountSig must be ${ML_DSA_65_SIGNATURE_LEN} bytes, got ${sig.length}`
1757
+ );
1758
+ }
1759
+ return bytesToHex2(
1760
+ concatBytes2(
1761
+ hexToBytes2(SPENDING_POLICY_SELECTORS.setPolicyClaim),
1762
+ encodePolicyWords(normalized),
1763
+ pubkey,
1764
+ sig
1765
+ )
1766
+ );
1767
+ }
1768
+ function encodeClaimPolicyByAddressCalldata(args, subAccountSig) {
1769
+ const normalized = normalizeArgs(args);
1770
+ const sig = toBytes2(subAccountSig);
1771
+ if (sig.length !== ML_DSA_65_SIGNATURE_LEN) {
1772
+ throw new SpendingPolicyError(
1773
+ `subAccountSig must be ${ML_DSA_65_SIGNATURE_LEN} bytes, got ${sig.length}`
1774
+ );
1775
+ }
1776
+ return bytesToHex2(
1777
+ concatBytes2(
1778
+ hexToBytes2(SPENDING_POLICY_SELECTORS.claimPolicyByAddress),
1779
+ encodePolicyWords(normalized),
1780
+ sig
1781
+ )
1782
+ );
1783
+ }
1784
+ function encodeEnableCalldata(subAccount) {
1785
+ return encodeSingleAddressCall(SPENDING_POLICY_SELECTORS.enable, subAccount);
1786
+ }
1787
+ function encodeDisableCalldata(subAccount) {
1788
+ return encodeSingleAddressCall(SPENDING_POLICY_SELECTORS.disable, subAccount);
1789
+ }
1790
+ function normalizeArgs(args) {
1791
+ return {
1792
+ subAccount: toAddressBytes(args.subAccount),
1793
+ principal: toAddressBytes(args.principal),
1794
+ dailyCapWei: toBigint(args.dailyCapWei, "dailyCapWei"),
1795
+ perTxCapWei: toBigint(args.perTxCapWei, "perTxCapWei"),
1796
+ allowRoot: expectLength3(toBytes2(args.allowRoot), 32, "allowRoot"),
1797
+ denyRoot: expectLength3(toBytes2(args.denyRoot), 32, "denyRoot")
1798
+ };
1799
+ }
1800
+ function encodePolicyWords(args) {
1801
+ return concatBytes2(
1802
+ encodeAddressWord(args.subAccount),
1803
+ encodeAddressWord(args.principal),
1804
+ encodeUint128Word(args.dailyCapWei),
1805
+ encodeUint128Word(args.perTxCapWei),
1806
+ args.allowRoot,
1807
+ args.denyRoot
1808
+ );
1809
+ }
1810
+ function encodeSingleAddressCall(selector, address) {
1811
+ return bytesToHex2(concatBytes2(hexToBytes2(selector), encodeAddressWord(toAddressBytes(address))));
1812
+ }
1813
+ function encodeAddressWord(address) {
1814
+ return concatBytes2(new Uint8Array(12), address);
1815
+ }
1816
+ function encodeUint128Word(value) {
1817
+ return concatBytes2(new Uint8Array(16), uint128Bytes(value, "uint128"));
1818
+ }
1819
+ function toAddressBytes(value) {
1820
+ if (typeof value === "string") {
1821
+ return hexToAddressBytes(value);
1822
+ }
1823
+ return expectLength3(value instanceof Uint8Array ? value : Uint8Array.from(value), 20, "address");
1824
+ }
1825
+ function toBytes2(value) {
1826
+ if (typeof value === "string") {
1827
+ return hexToBytes2(value);
1828
+ }
1829
+ return value instanceof Uint8Array ? value : Uint8Array.from(value);
1830
+ }
1831
+ function hexToBytes2(hex) {
1832
+ const body = hex.startsWith("0x") || hex.startsWith("0X") ? hex.slice(2) : hex;
1833
+ if (body.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(body)) {
1834
+ throw new SpendingPolicyError("invalid hex bytes");
1835
+ }
1836
+ const out = new Uint8Array(body.length / 2);
1837
+ for (let i = 0; i < out.length; i++) {
1838
+ out[i] = Number.parseInt(body.slice(i * 2, i * 2 + 2), 16);
1839
+ }
1840
+ return out;
1841
+ }
1842
+ function bytesToHex2(bytes) {
1843
+ return `0x${[...bytes].map((b) => b.toString(16).padStart(2, "0")).join("")}`;
1844
+ }
1845
+ function concatBytes2(...parts) {
1846
+ const out = new Uint8Array(parts.reduce((acc, p) => acc + p.length, 0));
1847
+ let offset = 0;
1848
+ for (const part of parts) {
1849
+ out.set(part, offset);
1850
+ offset += part.length;
1851
+ }
1852
+ return out;
1853
+ }
1854
+ function expectLength3(value, len, name) {
1855
+ if (value.length !== len) {
1856
+ throw new SpendingPolicyError(`${name} must be ${len} bytes`);
1857
+ }
1858
+ return value;
1859
+ }
1860
+ function toBigint(value, name) {
1861
+ const n = typeof value === "bigint" ? value : BigInt(value);
1862
+ if (n < 0n) {
1863
+ throw new SpendingPolicyError(`${name} must be non-negative`);
1864
+ }
1865
+ return n;
1866
+ }
1867
+ function uint64Bytes(value, name) {
1868
+ const n = toBigint(value, name);
1869
+ if (n > 0xffffffffffffffffn) {
1870
+ throw new SpendingPolicyError(`${name} exceeds uint64`);
1871
+ }
1872
+ return bigintBytes(n, 8);
1873
+ }
1874
+ function uint128Bytes(value, name) {
1875
+ if (value > 0xffffffffffffffffffffffffffffffffn) {
1876
+ throw new SpendingPolicyError(`${name} exceeds uint128`);
1877
+ }
1878
+ return bigintBytes(value, 16);
1879
+ }
1880
+ function bigintBytes(value, len) {
1881
+ const out = new Uint8Array(len);
1882
+ let n = value;
1883
+ for (let i = len - 1; i >= 0; i--) {
1884
+ out[i] = Number(n & 0xffn);
1885
+ n >>= 8n;
1886
+ }
1887
+ return out;
1888
+ }
1889
+
1890
+ // src/pubkey-registry.ts
1891
+ var PUBKEY_REGISTRY_ML_DSA_65_PUBLIC_KEY_LEN = 1952;
1892
+ var PUBKEY_REGISTRY_SELECTORS = {
1893
+ registerPubkey: "0x5fe984e7",
1894
+ lookupPubkey: "0x87c42001",
1895
+ hasPubkey: "0x01c0d167"
1896
+ };
1897
+ var PubkeyRegistryError = class extends Error {
1898
+ constructor(message) {
1899
+ super(message);
1900
+ this.name = "PubkeyRegistryError";
1901
+ }
1902
+ };
1903
+ function pubkeyRegistryAddressHex() {
1904
+ return PRECOMPILE_ADDRESSES.PUBKEY_REGISTRY.toLowerCase();
1905
+ }
1906
+ function encodeRegisterPubkeyCalldata(pubkey) {
1907
+ const bytes = toBytes3(pubkey);
1908
+ if (bytes.length !== PUBKEY_REGISTRY_ML_DSA_65_PUBLIC_KEY_LEN) {
1909
+ throw new PubkeyRegistryError(
1910
+ `pubkey must be ${PUBKEY_REGISTRY_ML_DSA_65_PUBLIC_KEY_LEN} bytes, got ${bytes.length}`
1911
+ );
1912
+ }
1913
+ return bytesToHex3(
1914
+ concatBytes3(
1915
+ hexToBytes3(PUBKEY_REGISTRY_SELECTORS.registerPubkey),
1916
+ uint256Word(32n),
1917
+ uint256Word(BigInt(bytes.length)),
1918
+ bytes
1919
+ )
1920
+ );
1921
+ }
1922
+ function encodeLookupPubkeyCalldata(address) {
1923
+ return encodeSingleAddressCall2(PUBKEY_REGISTRY_SELECTORS.lookupPubkey, address);
1924
+ }
1925
+ function encodeHasPubkeyCalldata(address) {
1926
+ return encodeSingleAddressCall2(PUBKEY_REGISTRY_SELECTORS.hasPubkey, address);
1927
+ }
1928
+ function decodeLookupPubkeyReturn(data) {
1929
+ const bytes = toBytes3(data);
1930
+ if (bytes.length < 96) {
1931
+ throw new PubkeyRegistryError("lookup return must be at least 96 bytes");
1932
+ }
1933
+ const offset = wordToBigint(bytes.slice(0, 32));
1934
+ if (offset !== 64n) {
1935
+ throw new PubkeyRegistryError("lookup pubkey offset must be 0x40");
1936
+ }
1937
+ const setBlock = wordToBigint(bytes.slice(32, 64));
1938
+ const len = wordToBigint(bytes.slice(Number(offset), Number(offset) + 32));
1939
+ if (len > BigInt(Number.MAX_SAFE_INTEGER)) {
1940
+ throw new PubkeyRegistryError("pubkey length exceeds safe integer range");
1941
+ }
1942
+ const bodyLen = Number(len);
1943
+ const bodyStart = Number(offset) + 32;
1944
+ const padded = Math.ceil(bodyLen / 32) * 32;
1945
+ if (bytes.length < bodyStart + padded) {
1946
+ throw new PubkeyRegistryError("lookup return bytes body is truncated");
1947
+ }
1948
+ return {
1949
+ pubkey: bytes.slice(bodyStart, bodyStart + bodyLen),
1950
+ setBlock
1951
+ };
1952
+ }
1953
+ function decodeHasPubkeyReturn(data) {
1954
+ const bytes = toBytes3(data);
1955
+ if (bytes.length !== 32) {
1956
+ throw new PubkeyRegistryError("hasPubkey return must be 32 bytes");
1957
+ }
1958
+ for (let i = 0; i < 31; i++) {
1959
+ if (bytes[i] !== 0) {
1960
+ throw new PubkeyRegistryError("hasPubkey bool high bytes must be zero");
1961
+ }
1962
+ }
1963
+ if (bytes[31] === 0) return false;
1964
+ if (bytes[31] === 1) return true;
1965
+ throw new PubkeyRegistryError("hasPubkey bool must be 0 or 1");
1966
+ }
1967
+ function encodeSingleAddressCall2(selector, address) {
1968
+ return bytesToHex3(concatBytes3(hexToBytes3(selector), addressWord(toAddressBytes2(address))));
1969
+ }
1970
+ function addressWord(address) {
1971
+ return concatBytes3(new Uint8Array(12), address);
1972
+ }
1973
+ function toAddressBytes2(value) {
1974
+ if (typeof value === "string") {
1975
+ return hexToAddressBytes(value);
1976
+ }
1977
+ return expectLength4(value instanceof Uint8Array ? value : Uint8Array.from(value), 20, "address");
1978
+ }
1979
+ function toBytes3(value) {
1980
+ if (typeof value === "string") {
1981
+ return hexToBytes3(value);
1982
+ }
1983
+ return value instanceof Uint8Array ? value : Uint8Array.from(value);
1984
+ }
1985
+ function hexToBytes3(hex) {
1986
+ const body = hex.startsWith("0x") || hex.startsWith("0X") ? hex.slice(2) : hex;
1987
+ if (body.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(body)) {
1988
+ throw new PubkeyRegistryError("invalid hex bytes");
1989
+ }
1990
+ const out = new Uint8Array(body.length / 2);
1991
+ for (let i = 0; i < out.length; i++) {
1992
+ out[i] = Number.parseInt(body.slice(i * 2, i * 2 + 2), 16);
1993
+ }
1994
+ return out;
1995
+ }
1996
+ function bytesToHex3(bytes) {
1997
+ return `0x${[...bytes].map((b) => b.toString(16).padStart(2, "0")).join("")}`;
1998
+ }
1999
+ function concatBytes3(...parts) {
2000
+ const out = new Uint8Array(parts.reduce((acc, p) => acc + p.length, 0));
2001
+ let offset = 0;
2002
+ for (const part of parts) {
2003
+ out.set(part, offset);
2004
+ offset += part.length;
2005
+ }
2006
+ return out;
2007
+ }
2008
+ function expectLength4(value, len, name) {
2009
+ if (value.length !== len) {
2010
+ throw new PubkeyRegistryError(`${name} must be ${len} bytes`);
2011
+ }
2012
+ return value;
2013
+ }
2014
+ function uint256Word(value) {
2015
+ if (value < 0n || value > (1n << 256n) - 1n) {
2016
+ throw new PubkeyRegistryError("uint256 value out of range");
2017
+ }
2018
+ const out = new Uint8Array(32);
2019
+ let n = value;
2020
+ for (let i = 31; i >= 0; i--) {
2021
+ out[i] = Number(n & 0xffn);
2022
+ n >>= 8n;
2023
+ }
2024
+ return out;
2025
+ }
2026
+ function wordToBigint(word) {
2027
+ if (word.length !== 32) {
2028
+ throw new PubkeyRegistryError("ABI word must be 32 bytes");
2029
+ }
2030
+ let out = 0n;
2031
+ for (const b of word) {
2032
+ out = out << 8n | BigInt(b);
2033
+ }
2034
+ return out;
2035
+ }
2036
+
2037
+ // src/ethers/network.ts
2038
+ var MONOLYTHIUM_TESTNET_CHAIN_ID = 69420n;
2039
+ var MONOLYTHIUM_TESTNET_NETWORK_NAME = "monolythium-testnet";
2040
+ var MONOLYTHIUM_NETWORKS = {
2041
+ testnet: {
2042
+ chainId: MONOLYTHIUM_TESTNET_CHAIN_ID,
2043
+ name: MONOLYTHIUM_TESTNET_NETWORK_NAME
2044
+ }
2045
+ };
2046
+
2047
+ // src/ethers/provider.ts
2048
+ var MonolythiumProvider = class extends JsonRpcApiProvider {
2049
+ /** Underlying SDK client. Exposed for callers that want native types. */
2050
+ rpcClient;
2051
+ constructor(endpointOrClient, options = {}) {
2052
+ const network = options.network ?? {
2053
+ chainId: MONOLYTHIUM_TESTNET_CHAIN_ID,
2054
+ name: MONOLYTHIUM_TESTNET_NETWORK_NAME
2055
+ };
2056
+ try {
2057
+ Network.register(
2058
+ network.name,
2059
+ () => new Network(network.name, network.chainId)
2060
+ );
2061
+ } catch (_e) {
2062
+ }
2063
+ super(new Network(network.name, network.chainId));
2064
+ this.rpcClient = typeof endpointOrClient === "string" ? new RpcClient(endpointOrClient, {
2065
+ fetch: options.fetch,
2066
+ headers: options.headers
2067
+ }) : endpointOrClient;
2068
+ }
2069
+ /**
2070
+ * Forward a single JSON-RPC method through the SDK transport. Ethers'
2071
+ * `_perform` calls this and ethers callers can also call `provider.send`
2072
+ * directly to access methods the rich provider interface does not wrap
2073
+ * (e.g. `lyth_*`).
2074
+ */
2075
+ async _send(payload) {
2076
+ const calls = Array.isArray(payload) ? payload : [payload];
2077
+ return Promise.all(calls.map((p) => this.#sendOne(p)));
2078
+ }
2079
+ async #sendOne(p) {
2080
+ try {
2081
+ const params = Array.isArray(p.params) ? p.params : p.params === void 0 ? [] : p.params;
2082
+ const result = await this.rpcClient.call(p.method, params);
2083
+ return { id: p.id, result };
2084
+ } catch (e) {
2085
+ if (e instanceof SdkError && e.kind === "rpc") {
2086
+ return {
2087
+ id: p.id,
2088
+ error: {
2089
+ code: e.code ?? -32603,
2090
+ message: e.message,
2091
+ data: e.data
2092
+ }
2093
+ };
2094
+ }
2095
+ const msg = e?.message ?? String(e);
2096
+ return {
2097
+ id: p.id,
2098
+ error: { code: -32603, message: `${msg}` }
2099
+ };
2100
+ }
2101
+ }
2102
+ };
2103
+ var MonolythiumSigner = class _MonolythiumSigner extends AbstractSigner {
2104
+ #backend;
2105
+ constructor(backend, provider) {
2106
+ super(provider ?? null);
2107
+ this.#backend = backend;
2108
+ }
2109
+ /**
2110
+ * Wrap any ethers v6 `BaseWallet` (the parent class of `Wallet`,
2111
+ * `HDNodeWallet`, and friends) so callers don't have to write a
2112
+ * `MonolythiumSignerBackend` for the common test / dev path.
2113
+ *
2114
+ * Both `new Wallet(privateKey)` and `Wallet.createRandom()` /
2115
+ * `HDNodeWallet.fromMnemonic(...)` are accepted.
2116
+ */
2117
+ static fromEthersWallet(wallet, provider) {
2118
+ const backend = {
2119
+ getAddress: async () => wallet.address,
2120
+ signTransaction: (tx) => wallet.signTransaction(tx),
2121
+ signMessage: (message) => wallet.signMessage(message),
2122
+ signTypedData: (domain, types, value) => wallet.signTypedData(domain, types, value)
2123
+ };
2124
+ return new _MonolythiumSigner(backend, provider);
2125
+ }
2126
+ async getAddress() {
2127
+ return this.#backend.getAddress();
2128
+ }
2129
+ connect(provider) {
2130
+ return new _MonolythiumSigner(this.#backend, provider);
2131
+ }
2132
+ async signTransaction(tx) {
2133
+ return this.#backend.signTransaction(tx);
2134
+ }
2135
+ async signMessage(message) {
2136
+ return this.#backend.signMessage(message);
2137
+ }
2138
+ async signTypedData(domain, types, value) {
2139
+ return this.#backend.signTypedData(domain, types, value);
2140
+ }
2141
+ };
2142
+
2143
+ // src/ethers/tx-translate.ts
2144
+ function toHexQuantity(v) {
2145
+ if (v === null || v === void 0) return void 0;
2146
+ if (typeof v === "string") {
2147
+ if (v.startsWith("0x") || v.startsWith("0X")) return v;
2148
+ return `0x${BigInt(v).toString(16)}`;
2149
+ }
2150
+ if (typeof v === "number") return `0x${v.toString(16)}`;
2151
+ return `0x${v.toString(16)}`;
2152
+ }
2153
+ function translateTxIn(req) {
2154
+ const out = {};
2155
+ if (req.from !== void 0 && req.from !== null) out.from = req.from;
2156
+ if (req.to !== void 0 && req.to !== null) out.to = req.to;
2157
+ const gas = toHexQuantity(req.gasLimit);
2158
+ if (gas !== void 0) out.gas = gas;
2159
+ const gasPrice = toHexQuantity(req.gasPrice);
2160
+ if (gasPrice !== void 0) out.gasPrice = gasPrice;
2161
+ const value = toHexQuantity(req.value);
2162
+ if (value !== void 0) out.value = value;
2163
+ if (req.data !== void 0 && req.data !== null) out.data = req.data;
2164
+ return out;
2165
+ }
2166
+ function translateReceiptOut(monoReceipt, fromAddress, toAddress) {
2167
+ return {
2168
+ transactionHash: monoReceipt.tx_hash,
2169
+ blockHash: monoReceipt.block_hash,
2170
+ blockNumber: `0x${BigInt(monoReceipt.block_number).toString(16)}`,
2171
+ transactionIndex: `0x${monoReceipt.tx_index.toString(16)}`,
2172
+ status: monoReceipt.status === 1 ? "0x1" : "0x0",
2173
+ gasUsed: `0x${BigInt(monoReceipt.gas_used).toString(16)}`,
2174
+ cumulativeGasUsed: `0x${BigInt(monoReceipt.gas_used).toString(16)}`,
2175
+ effectiveGasPrice: "0x0",
2176
+ contractAddress: null,
2177
+ from: fromAddress ?? "0x0000000000000000000000000000000000000000",
2178
+ to: toAddress,
2179
+ type: "0x2",
2180
+ logsBloom: `0x${"0".repeat(512)}`,
2181
+ logs: []
2182
+ };
2183
+ }
2184
+ function translateBlockOut(header) {
2185
+ return {
2186
+ number: `0x${header.number.toString(16)}`,
2187
+ hash: header.hash,
2188
+ parentHash: header.parent_hash,
2189
+ timestamp: `0x${header.timestamp.toString(16)}`,
2190
+ gasUsed: `0x${header.gas_used.toString(16)}`,
2191
+ gasLimit: `0x${header.gas_limit.toString(16)}`,
2192
+ stateRoot: header.state_root,
2193
+ miner: "0x0000000000000000000000000000000000000000",
2194
+ difficulty: "0x0",
2195
+ nonce: "0x0000000000000000",
2196
+ baseFeePerGas: null,
2197
+ extraData: "0x",
2198
+ mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
2199
+ transactions: [],
2200
+ transactionsRoot: "0x0000000000000000000000000000000000000000000000000000000000000000",
2201
+ receiptsRoot: "0x0000000000000000000000000000000000000000000000000000000000000000",
2202
+ logsBloom: `0x${"0".repeat(512)}`,
2203
+ sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
2204
+ uncles: [],
2205
+ size: "0x0"
2206
+ };
2207
+ }
2208
+
2209
+ // src/index.ts
2210
+ var version = "0.1.0";
2211
+
2212
+ export { ADDRESS_HRP, AddressError, ApiClient, BURN_ADDR, CHAIN_REGISTRY, CHAIN_REGISTRY_RAW_BASE, ML_DSA_65_PUBLIC_KEY_LEN, ML_DSA_65_SIGNATURE_LEN, MONOLYTHIUM_NETWORKS, MONOLYTHIUM_TESTNET_CHAIN_ID, MONOLYTHIUM_TESTNET_NETWORK_NAME, MonolythiumProvider, MonolythiumSigner, NODE_REGISTRY_CAPABILITIES, NODE_REGISTRY_CAPABILITY_MASK, NODE_REGISTRY_PUBLIC_SERVICE_MASK, NODE_REGISTRY_SELECTORS, NodeRegistryError, PRECOMPILE_ADDRESSES, PUBKEY_REGISTRY_ML_DSA_65_PUBLIC_KEY_LEN, PUBKEY_REGISTRY_SELECTORS, PubkeyRegistryError, RpcClient, SERVICE_PROBE_STATUS, SET_POLICY_CLAIM_DOMAIN_TAG, SPENDING_POLICY_SELECTORS, SdkError, SpendingPolicyError, TESTNET_69420, addressBytesToHex, addressToBech32, apiEndpointFromRpcEndpoint, bech32ToAddress, bech32ToAddressBytes, composeClaimBoundMessage, decodeHasPubkeyReturn, decodeLookupPubkeyReturn, encodeBlockSelector, encodeClaimPolicyByAddressCalldata, encodeDisableCalldata, encodeEnableCalldata, encodeHasPubkeyCalldata, encodeLookupPubkeyCalldata, encodeRegisterPubkeyCalldata, encodeReportServiceProbeCalldata, encodeSetPolicyCalldata, encodeSetPolicyClaimCalldata, fetchChainInfoLatest, fetchChainRegistryLatest, getChainInfo, getP2pSeeds, getRpcEndpoints, hexToAddressBytes, isConcreteServiceProbeStatus, isSinglePublicServiceProbeMask, isValidNodeRegistryCapabilities, isValidPublicServiceProbeMask, nodeRegistryAddressHex, normalizeAddressHex, parseAddress, parseChainRegistryToml, parseQuantity, parseQuantityBig, pubkeyRegistryAddressHex, serviceProbeStatusLabel, spendingPolicyAddressHex, translateBlockOut, translateReceiptOut, translateTxIn, version };
2213
+ //# sourceMappingURL=index.js.map
2214
+ //# sourceMappingURL=index.js.map