univo 0.2.8 → 0.2.10
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/cli.mjs +1 -1
- package/dist/index.mjs +47 -22
- package/dist/realtime.mjs +2 -1
- package/dist/shared/{univo.Br975GsZ.mjs → univo.DfCC9G2B.mjs} +2 -5
- package/dist/transport.d.mts +2 -2
- package/dist/transport.d.ts +2 -2
- package/dist/transport.mjs +18 -5
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { config } from 'dotenv';
|
|
|
5
5
|
import { WebSocket } from 'partysocket';
|
|
6
6
|
import { defineCommand, runMain } from 'citty';
|
|
7
7
|
import { http } from './transport.mjs';
|
|
8
|
-
import { c as createLogger, v as version,
|
|
8
|
+
import { c as createLogger, v as version, f as name } from './shared/univo.DfCC9G2B.mjs';
|
|
9
9
|
import './shared/univo.C0flyVee.mjs';
|
|
10
10
|
|
|
11
11
|
const log = createLogger({ quiet: false });
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as createLogger, d as decompress, a as decoder, h as hexToNumber, i as isHexEqual, r as retry, v as version, n as
|
|
1
|
+
import { c as createLogger, d as decompress, a as decoder, h as hexToNumber, i as isHexEqual, r as retry, v as version, n as normalizeHex } from './shared/univo.DfCC9G2B.mjs';
|
|
2
2
|
import { c as createException, g as getException, a as catchException } from './shared/univo.C0flyVee.mjs';
|
|
3
3
|
|
|
4
4
|
function matchFilter(block, filter) {
|
|
@@ -129,6 +129,7 @@ function indexer(opts) {
|
|
|
129
129
|
}
|
|
130
130
|
return block;
|
|
131
131
|
}
|
|
132
|
+
const GetBlockError = createException("Failed to load block from the provided `getBlock` function");
|
|
132
133
|
const public_getFinalizedHeight = async (chain) => {
|
|
133
134
|
const [[stored], finalizedBlock] = await Promise.all([
|
|
134
135
|
metadata.blocks.list({ chain }),
|
|
@@ -147,26 +148,43 @@ function indexer(opts) {
|
|
|
147
148
|
return Math.min(indexerHeight, finalizedHeight);
|
|
148
149
|
};
|
|
149
150
|
const public_writeUnfinalizedHeads = async (heads) => {
|
|
151
|
+
if (heads.length === 0) {
|
|
152
|
+
return log.debug("No heads received, returning...");
|
|
153
|
+
}
|
|
150
154
|
let chain = void 0;
|
|
151
155
|
for (const head of heads) {
|
|
152
156
|
if (chain === void 0) {
|
|
153
157
|
chain = head.chain;
|
|
154
158
|
}
|
|
155
159
|
if (!isHexEqual(chain, head.chain)) {
|
|
156
|
-
throw new Error(
|
|
160
|
+
throw new Error("Received heads from separate chains");
|
|
157
161
|
}
|
|
158
162
|
}
|
|
159
163
|
if (chain === void 0) {
|
|
160
|
-
|
|
164
|
+
throw new Error("Internal error. Expected chain to be defined after checking heads length");
|
|
161
165
|
}
|
|
162
166
|
log.debug(`Received ${heads.length} unfinalized heads...`);
|
|
163
167
|
const blocks_start = Date.now();
|
|
164
|
-
const blocks_nullable = await Promise.all(
|
|
165
|
-
|
|
168
|
+
const [finalizedBlock, ...blocks_nullable] = await Promise.all([
|
|
169
|
+
getBlock({ chain, number: "finalized" }),
|
|
170
|
+
...heads.map(async (head) => {
|
|
166
171
|
return await getBlock({ chain, number: head.number, hash: head.hash });
|
|
167
172
|
})
|
|
168
|
-
);
|
|
169
|
-
|
|
173
|
+
]);
|
|
174
|
+
if (finalizedBlock === null) {
|
|
175
|
+
log.debug("Failed to determine finalized height when processing unfinalized heads");
|
|
176
|
+
throw new Error(GetBlockError);
|
|
177
|
+
}
|
|
178
|
+
const finalizedHeight = hexToNumber(finalizedBlock.eth_getBlockByNumber.number);
|
|
179
|
+
const blocks = blocks_nullable.flatMap((block) => {
|
|
180
|
+
if (block === null) {
|
|
181
|
+
return [];
|
|
182
|
+
}
|
|
183
|
+
if (hexToNumber(block.eth_getBlockByNumber.number) <= finalizedHeight) {
|
|
184
|
+
return [];
|
|
185
|
+
}
|
|
186
|
+
return block;
|
|
187
|
+
});
|
|
170
188
|
if (blocks.length === 0) {
|
|
171
189
|
return log.debug("All blocks failed to load, aborting early...");
|
|
172
190
|
}
|
|
@@ -259,7 +277,7 @@ function indexer(opts) {
|
|
|
259
277
|
chain = head.chain;
|
|
260
278
|
}
|
|
261
279
|
if (!isHexEqual(chain, head.chain)) {
|
|
262
|
-
throw new Error(
|
|
280
|
+
throw new Error("Received heads from separate chains");
|
|
263
281
|
}
|
|
264
282
|
}
|
|
265
283
|
if (chain === void 0) {
|
|
@@ -272,17 +290,15 @@ function indexer(opts) {
|
|
|
272
290
|
let previousHead = firstHead;
|
|
273
291
|
for (const head of remainingHeads) {
|
|
274
292
|
if (hexToNumber(head.number) !== hexToNumber(previousHead.number) + 1) {
|
|
275
|
-
|
|
276
|
-
throw new Error(InvalidHeadsError);
|
|
293
|
+
throw new Error("Found invalid block number in received heads, aborting...");
|
|
277
294
|
}
|
|
278
295
|
if (!isHexEqual(head.parentHash, previousHead.hash)) {
|
|
279
|
-
|
|
280
|
-
throw new Error(InvalidHeadsError);
|
|
296
|
+
throw new Error("Found invalid block hash in received heads, aborting...");
|
|
281
297
|
}
|
|
282
298
|
previousHead = head;
|
|
283
299
|
}
|
|
284
|
-
const [
|
|
285
|
-
|
|
300
|
+
const [[unfinalizedMetadataBlock], finalizedBlock] = await Promise.all([
|
|
301
|
+
metadata.blocks.list({ chain }),
|
|
286
302
|
//
|
|
287
303
|
getBlock({ chain, number: "finalized" })
|
|
288
304
|
]);
|
|
@@ -293,16 +309,27 @@ function indexer(opts) {
|
|
|
293
309
|
const finalizedHeight = hexToNumber(finalizedBlock.eth_getBlockByNumber.number);
|
|
294
310
|
for (const head of heads) {
|
|
295
311
|
if (hexToNumber(head.number) > finalizedHeight) {
|
|
296
|
-
throw new Error(
|
|
312
|
+
throw new Error("Received head greater than chain finalized height");
|
|
297
313
|
}
|
|
298
314
|
}
|
|
315
|
+
if (unfinalizedMetadataBlock === void 0) {
|
|
316
|
+
return log.debug("No heads to finalize, returning...");
|
|
317
|
+
}
|
|
318
|
+
const indexerHeight = hexToNumber(unfinalizedMetadataBlock.number) - 1;
|
|
299
319
|
log.debug(`Indexer height ${indexerHeight}, finalized height ${finalizedHeight}`);
|
|
320
|
+
if (indexerHeight === finalizedHeight) {
|
|
321
|
+
return log.debug("No heads to finalize, returning...");
|
|
322
|
+
}
|
|
300
323
|
const newHeads = heads.filter((head) => {
|
|
301
324
|
return hexToNumber(head.number) > indexerHeight;
|
|
302
325
|
});
|
|
303
|
-
|
|
326
|
+
const [firstNewHead] = newHeads;
|
|
327
|
+
if (firstNewHead === void 0) {
|
|
304
328
|
return log.debug("No new heads received, returning...");
|
|
305
329
|
}
|
|
330
|
+
if (hexToNumber(firstNewHead.number) !== indexerHeight + 1) {
|
|
331
|
+
throw new Error("Client advanced too far. Heads received are greater than the indexer height");
|
|
332
|
+
}
|
|
306
333
|
for (const head of newHeads) {
|
|
307
334
|
const processed = await metadata.blocks.get({ chain: head.chain, number: head.number });
|
|
308
335
|
if (processed.length === 0) {
|
|
@@ -328,7 +355,7 @@ function indexer(opts) {
|
|
|
328
355
|
block = await getBlock({ chain: head.chain, number: head.number, hash: head.hash });
|
|
329
356
|
}
|
|
330
357
|
if (block === null) {
|
|
331
|
-
throw new Error(
|
|
358
|
+
throw new Error("Received unknown head that wasn't canonical");
|
|
332
359
|
}
|
|
333
360
|
const promises = events_grouped_by_storage_map.entries().map(async ([storage, grouped_events]) => {
|
|
334
361
|
const batch = [];
|
|
@@ -453,6 +480,7 @@ function indexer(opts) {
|
|
|
453
480
|
};
|
|
454
481
|
return new Proxy(value, createProxyHandler());
|
|
455
482
|
};
|
|
483
|
+
const IncompleteBlockError = createException("Received block with missing required property");
|
|
456
484
|
const private_writeEvents = async (params) => {
|
|
457
485
|
if (all_events.length === 0) return { failures: [] };
|
|
458
486
|
const relevant_events = all_events.filter((event2) => params.events.includes(event2.id));
|
|
@@ -644,6 +672,7 @@ function indexer(opts) {
|
|
|
644
672
|
events_grouped_by_storage_map.set(event2.storage, group);
|
|
645
673
|
return event2;
|
|
646
674
|
};
|
|
675
|
+
const UnknownMethodError = createException("The requested method does not exist");
|
|
647
676
|
const handler = async (req) => {
|
|
648
677
|
let body_buffer;
|
|
649
678
|
try {
|
|
@@ -710,6 +739,7 @@ function indexer(opts) {
|
|
|
710
739
|
} catch (error) {
|
|
711
740
|
const message = getException(error);
|
|
712
741
|
if (message) {
|
|
742
|
+
log.error(message);
|
|
713
743
|
return Response.json(
|
|
714
744
|
{ jsonrpc: "2.0", id: json.id, error: { code: 0, message } },
|
|
715
745
|
//
|
|
@@ -728,10 +758,5 @@ function indexer(opts) {
|
|
|
728
758
|
};
|
|
729
759
|
return { fetch: handler, event };
|
|
730
760
|
}
|
|
731
|
-
const InvalidHeadsError = createException("Received invalid finalized heads");
|
|
732
|
-
const UnknownMethodError = createException("The requested method does not exist");
|
|
733
|
-
const MultipleChainsError = createException("Received heads from separate chains");
|
|
734
|
-
const IncompleteBlockError = createException("Received block with missing required property");
|
|
735
|
-
const GetBlockError = createException("Failed to load block from the provided `getBlock` function");
|
|
736
761
|
|
|
737
762
|
export { indexer, matchFilter };
|
package/dist/realtime.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as createLogger,
|
|
1
|
+
import { c as createLogger, b as iife, h as hexToNumber, e as numberToHex, m as mutex, r as retry, i as isHexEqual } from './shared/univo.DfCC9G2B.mjs';
|
|
2
2
|
|
|
3
3
|
const MAX_LENGTH = 1e4;
|
|
4
4
|
function defineBlockchain(opts) {
|
|
@@ -160,6 +160,7 @@ function realtime(opts) {
|
|
|
160
160
|
let indexerHeight = initialIndexerHeight;
|
|
161
161
|
const poll = async () => {
|
|
162
162
|
try {
|
|
163
|
+
log.debug("Polling for finalized height...");
|
|
163
164
|
const finalizedBlock = await opts.node.request({
|
|
164
165
|
method: "eth_getBlockByNumber",
|
|
165
166
|
params: ["finalized", false]
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const name = "univo";
|
|
2
|
-
const version = "0.2.
|
|
2
|
+
const version = "0.2.10";
|
|
3
3
|
|
|
4
4
|
function createLogger(opts) {
|
|
5
5
|
let prefix = `[${name}@${version}]`;
|
|
@@ -73,9 +73,6 @@ function raise(...args) {
|
|
|
73
73
|
if (args[0] instanceof Error) throw args[0];
|
|
74
74
|
throw new Error(...args);
|
|
75
75
|
}
|
|
76
|
-
function nonNullable(value) {
|
|
77
|
-
return value !== null && value !== void 0;
|
|
78
|
-
}
|
|
79
76
|
async function compress(input) {
|
|
80
77
|
const compressed = new Blob([input]).stream().pipeThrough(new CompressionStream("gzip"));
|
|
81
78
|
return new Response(compressed).arrayBuffer();
|
|
@@ -92,4 +89,4 @@ const normalizeHex = (hex, length) => {
|
|
|
92
89
|
return `0x${hex.slice(2).toLowerCase().padStart(length, "0")}`;
|
|
93
90
|
};
|
|
94
91
|
|
|
95
|
-
export { decoder as a,
|
|
92
|
+
export { decoder as a, iife as b, createLogger as c, decompress as d, numberToHex as e, name as f, compress as g, hexToNumber as h, isHexEqual as i, raise as j, mutex as m, normalizeHex as n, retry as r, version as v };
|
package/dist/transport.d.mts
CHANGED
|
@@ -2,8 +2,8 @@ import { Rpc } from './rpc.mjs';
|
|
|
2
2
|
import './index.mjs';
|
|
3
3
|
import 'unstorage';
|
|
4
4
|
|
|
5
|
-
type
|
|
6
|
-
type Transport<R extends Rpc, P extends
|
|
5
|
+
type Protocol = "http" | "wss";
|
|
6
|
+
type Transport<R extends Rpc, P extends Protocol = Protocol> = {
|
|
7
7
|
/**
|
|
8
8
|
* The underlying transport protocol.
|
|
9
9
|
*/
|
package/dist/transport.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ import { Rpc } from './rpc.js';
|
|
|
2
2
|
import './index.js';
|
|
3
3
|
import 'unstorage';
|
|
4
4
|
|
|
5
|
-
type
|
|
6
|
-
type Transport<R extends Rpc, P extends
|
|
5
|
+
type Protocol = "http" | "wss";
|
|
6
|
+
type Transport<R extends Rpc, P extends Protocol = Protocol> = {
|
|
7
7
|
/**
|
|
8
8
|
* The underlying transport protocol.
|
|
9
9
|
*/
|
package/dist/transport.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import ws from 'ws';
|
|
2
2
|
import { WebSocket } from 'partysocket';
|
|
3
3
|
import { c as createException } from './shared/univo.C0flyVee.mjs';
|
|
4
|
-
import {
|
|
4
|
+
import { g as compress, j as raise, c as createLogger } from './shared/univo.DfCC9G2B.mjs';
|
|
5
5
|
|
|
6
6
|
function createSocket(url, opts) {
|
|
7
7
|
const socket = new WebSocket(url, [], { WebSocket: ws });
|
|
@@ -26,7 +26,9 @@ function wss(url, opts = {}) {
|
|
|
26
26
|
logger.error(new Error("Socket error", { cause }));
|
|
27
27
|
},
|
|
28
28
|
async onOpen() {
|
|
29
|
-
if (subscriptions.size === 0)
|
|
29
|
+
if (subscriptions.size === 0) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
30
32
|
const params2 = [];
|
|
31
33
|
for (const [id2, subscription] of subscriptions) {
|
|
32
34
|
params2.push(subscription.param);
|
|
@@ -74,13 +76,24 @@ function wss(url, opts = {}) {
|
|
|
74
76
|
}
|
|
75
77
|
});
|
|
76
78
|
const request = async (opts2) => {
|
|
77
|
-
return await new Promise((resolve) => {
|
|
79
|
+
return await new Promise((resolve, reject) => {
|
|
78
80
|
const body = Object.assign({ id: id++ }, opts2);
|
|
81
|
+
const timeout = setTimeout(() => {
|
|
82
|
+
requests.delete(body.id);
|
|
83
|
+
reject(new Error("wss request timed out after 30 seconds"));
|
|
84
|
+
}, 30 * 1e3);
|
|
79
85
|
requests.set(body.id, (data) => {
|
|
86
|
+
clearTimeout(timeout);
|
|
80
87
|
requests.delete(body.id);
|
|
81
88
|
resolve(data);
|
|
82
89
|
});
|
|
83
|
-
|
|
90
|
+
try {
|
|
91
|
+
socket.send(JSON.stringify(body));
|
|
92
|
+
} catch (cause) {
|
|
93
|
+
clearTimeout(timeout);
|
|
94
|
+
requests.delete(body.id);
|
|
95
|
+
reject(new Error(ClientConnectionError, { cause }));
|
|
96
|
+
}
|
|
84
97
|
});
|
|
85
98
|
};
|
|
86
99
|
const subscribe = async (param, handler) => {
|
|
@@ -148,7 +161,7 @@ function http(url, opts = {}) {
|
|
|
148
161
|
headers.set("Content-Encoding", "gzip");
|
|
149
162
|
headers.set("Authorization", `Bearer ${opts.signingKey}`);
|
|
150
163
|
}
|
|
151
|
-
const res = await fetch(url, { headers, body, method: "POST" }).catch((cause) => {
|
|
164
|
+
const res = await fetch(url, { headers, body, method: "POST", signal: AbortSignal.timeout(30 * 1e3) }).catch((cause) => {
|
|
152
165
|
throw new Error(ClientConnectionError, { cause });
|
|
153
166
|
});
|
|
154
167
|
const json = await res.json().catch((cause) => {
|