univo 0.4.0 → 0.4.2
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.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +190 -87
- package/dist/proxy.d.mts +1 -1
- package/dist/proxy.d.ts +1 -1
- package/dist/proxy.mjs +2 -2
- package/dist/realtime.d.mts +4 -4
- package/dist/realtime.d.ts +4 -4
- package/dist/realtime.mjs +323 -122
- package/dist/rpc.d.mts +1 -1
- package/dist/rpc.d.ts +1 -1
- package/dist/shared/{univo.CEA4vY0E.d.ts → univo.7S1OTdpc.d.ts} +30 -37
- package/dist/shared/univo.CUNaTwXY.mjs +162 -0
- package/dist/shared/{univo.DYd1g40o.d.mts → univo.Ckj3I8tQ.d.mts} +30 -37
- package/dist/transport.d.mts +1 -1
- package/dist/transport.d.ts +1 -1
- package/dist/transport.mjs +54 -36
- package/package.json +1 -1
- package/dist/shared/univo.mlthZw0m.mjs +0 -91
package/dist/realtime.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { hexToNumber } from 'viem';
|
|
2
|
-
import { c as createLogger, b as iife, m as mutex, r as retry, i as isHexEqual } from './shared/univo.
|
|
2
|
+
import { c as createLogger, b as iife, m as mutex, l as lifecycle, q as queue, r as retry, i as isHexEqual } from './shared/univo.CUNaTwXY.mjs';
|
|
3
3
|
|
|
4
4
|
function defineBlockchain(opts) {
|
|
5
5
|
const log = createLogger({ quiet: opts.quiet });
|
|
@@ -77,156 +77,357 @@ function defineBlockchain(opts) {
|
|
|
77
77
|
await reconcile(parentBlock);
|
|
78
78
|
return await reconcile(newBlock);
|
|
79
79
|
}
|
|
80
|
+
const enqueue = queue();
|
|
80
81
|
return {
|
|
81
82
|
chain,
|
|
82
|
-
prune:
|
|
83
|
-
reconcile:
|
|
83
|
+
prune: (tail) => enqueue(() => prune(tail)),
|
|
84
|
+
reconcile: (newBlock) => enqueue(() => reconcile(newBlock))
|
|
84
85
|
};
|
|
85
86
|
}
|
|
86
87
|
const POLLING_INTERVAL_MS = 12 * 1e3;
|
|
87
|
-
function realtime(
|
|
88
|
-
const log = createLogger({ quiet:
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
88
|
+
function realtime(realtime2) {
|
|
89
|
+
const log = createLogger({ quiet: realtime2.quiet, prefix: "[realtime]" });
|
|
90
|
+
const instance = ({ chain, node }) => {
|
|
91
|
+
const { isDisposed, onCleanup, interrupt } = lifecycle({
|
|
92
|
+
onCleanupError: (error) => {
|
|
93
|
+
if (error instanceof Error) {
|
|
94
|
+
log.warn(error.message);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
const promise = iife(async () => {
|
|
99
|
+
const [chainLatestBlock, chainFinalizedBlock] = await Promise.all([
|
|
100
|
+
node.request({ method: "eth_getBlockByNumber", params: ["latest", false] }),
|
|
101
|
+
//
|
|
102
|
+
node.request({ method: "eth_getBlockByNumber", params: ["finalized", false] })
|
|
103
|
+
]);
|
|
104
|
+
if (isDisposed()) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (chainLatestBlock === null) {
|
|
108
|
+
throw new Error("Latest block not found");
|
|
109
|
+
}
|
|
110
|
+
if (chainFinalizedBlock === null) {
|
|
111
|
+
throw new Error("Finalized block not found");
|
|
112
|
+
}
|
|
113
|
+
const unfinalized = defineBlockchain({
|
|
114
|
+
quiet: realtime2.quiet,
|
|
115
|
+
getBlockByHash: async (hash) => {
|
|
116
|
+
const block = await node.request({ method: "eth_getBlockByHash", params: [hash, false] });
|
|
117
|
+
if (block === null) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
return { number: block.number, hash: block.hash, parent_hash: block.parentHash };
|
|
121
|
+
},
|
|
122
|
+
onBlockAdded: async (head) => {
|
|
123
|
+
try {
|
|
124
|
+
log.debug("Received unfinalized head");
|
|
125
|
+
await realtime2.indexer.request({
|
|
126
|
+
method: "public_writeUnfinalizedHead",
|
|
127
|
+
params: [{ chain, ...head }]
|
|
128
|
+
});
|
|
129
|
+
log.debug("Delivered unfinalized head");
|
|
130
|
+
} catch (error) {
|
|
131
|
+
if (error instanceof Error) {
|
|
132
|
+
log.warn(`Failed to write unfinalized head: ${error.message}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
onBlockReorganised: async (head) => {
|
|
137
|
+
try {
|
|
138
|
+
log.debug("Received reorganised head");
|
|
139
|
+
await retry(
|
|
140
|
+
() => realtime2.indexer.request({ method: "public_deleteReorganisedHead", params: [{ chain, ...head }] }),
|
|
141
|
+
//
|
|
142
|
+
2
|
|
143
|
+
);
|
|
144
|
+
log.debug("Delivered reorganised head");
|
|
145
|
+
} catch (error) {
|
|
146
|
+
if (error instanceof Error) {
|
|
147
|
+
log.warn(`Failed to write reorganised head: ${error.message}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
await unfinalized.reconcile({
|
|
153
|
+
hash: chainLatestBlock.hash,
|
|
154
|
+
number: chainLatestBlock.number,
|
|
155
|
+
parent_hash: chainLatestBlock.parentHash
|
|
156
|
+
});
|
|
157
|
+
if (isDisposed()) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
log.debug("Subscribing unfinalized chain to new heads...");
|
|
161
|
+
const unsubscribe = await node.subscribe("newHeads", async (head) => {
|
|
162
|
+
await unfinalized.reconcile({ hash: head.hash, number: head.number, parent_hash: head.parentHash }).catch((error) => {
|
|
163
|
+
if (error instanceof Error) {
|
|
164
|
+
log.error(`Failed to reconcile unfinalized head: ${error.message}`);
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
onCleanup(() => unsubscribe());
|
|
169
|
+
if (isDisposed()) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
log.debug("Subscribed unfinalized chain to new heads");
|
|
173
|
+
async function finalize() {
|
|
115
174
|
try {
|
|
116
|
-
log.debug("
|
|
117
|
-
await
|
|
118
|
-
|
|
119
|
-
params: [{ chain, ...head }]
|
|
120
|
-
});
|
|
121
|
-
log.debug("Delivered unfinalized head");
|
|
175
|
+
log.debug("Finalizing indexer...");
|
|
176
|
+
await realtime2.indexer.request({ params: [chain], method: "public_finalize" });
|
|
177
|
+
log.debug("Indexer finalized");
|
|
122
178
|
} catch (error) {
|
|
123
179
|
if (error instanceof Error) {
|
|
124
|
-
log.warn(`Failed to
|
|
180
|
+
log.warn(`Failed to finalize: ${error.message}`);
|
|
125
181
|
}
|
|
126
182
|
}
|
|
127
|
-
}
|
|
128
|
-
|
|
183
|
+
}
|
|
184
|
+
const mutex_finalize = mutex(finalize);
|
|
185
|
+
let chainFinalizedHeight = hexToNumber(chainFinalizedBlock.number);
|
|
186
|
+
async function poll() {
|
|
129
187
|
try {
|
|
130
|
-
log.debug("
|
|
131
|
-
await
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
)
|
|
136
|
-
|
|
188
|
+
log.debug("Polling for finalized height...");
|
|
189
|
+
const finalizedBlock = await node.request({
|
|
190
|
+
method: "eth_getBlockByNumber",
|
|
191
|
+
params: ["finalized", false]
|
|
192
|
+
});
|
|
193
|
+
if (finalizedBlock === null) {
|
|
194
|
+
throw new Error("Finalized block not found");
|
|
195
|
+
}
|
|
196
|
+
const nextFinalizedHeight = hexToNumber(finalizedBlock.number);
|
|
197
|
+
if (nextFinalizedHeight <= chainFinalizedHeight) {
|
|
198
|
+
return log.debug("Chain finalized height has not progressed");
|
|
199
|
+
}
|
|
200
|
+
await realtime2.indexer.request({ params: [chain], method: "public_writeFinalizedHeight" });
|
|
201
|
+
const newFinalizedHeads = unfinalized.chain.filter((head) => {
|
|
202
|
+
if (hexToNumber(head.number) > chainFinalizedHeight && hexToNumber(head.number) <= nextFinalizedHeight) {
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
return false;
|
|
206
|
+
}).map((head) => {
|
|
207
|
+
return { chain, ...head };
|
|
208
|
+
});
|
|
209
|
+
if (newFinalizedHeads.length === 0) {
|
|
210
|
+
chainFinalizedHeight = nextFinalizedHeight;
|
|
211
|
+
return log.debug("No new finalized heads to process");
|
|
212
|
+
}
|
|
213
|
+
log.debug(`Processing ${newFinalizedHeads.length} finalized head(s) in parallel`);
|
|
214
|
+
const promises = newFinalizedHeads.map(async (head) => {
|
|
215
|
+
try {
|
|
216
|
+
log.debug("Received finalized head");
|
|
217
|
+
await realtime2.indexer.request({ params: [head], method: "public_writeFinalizedHead" });
|
|
218
|
+
log.debug("Delivered finalized head");
|
|
219
|
+
} catch (error) {
|
|
220
|
+
if (error instanceof Error) {
|
|
221
|
+
log.warn(`Failed to write finalized head: ${error.message}`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
await Promise.allSettled(promises);
|
|
226
|
+
log.debug(`Processed ${newFinalizedHeads.length} finalized head(s) in parallel`);
|
|
227
|
+
chainFinalizedHeight = nextFinalizedHeight;
|
|
228
|
+
await unfinalized.prune({
|
|
229
|
+
hash: finalizedBlock.hash,
|
|
230
|
+
number: finalizedBlock.number,
|
|
231
|
+
parent_hash: finalizedBlock.parentHash
|
|
232
|
+
});
|
|
233
|
+
await mutex_finalize();
|
|
137
234
|
} catch (error) {
|
|
138
235
|
if (error instanceof Error) {
|
|
139
|
-
log.
|
|
236
|
+
log.error(`Failed to reconcile finalized head: ${error.message}`);
|
|
140
237
|
}
|
|
141
238
|
}
|
|
142
239
|
}
|
|
240
|
+
const id = setInterval(poll, POLLING_INTERVAL_MS);
|
|
241
|
+
onCleanup(() => clearInterval(id));
|
|
242
|
+
log.debug("Started polling finalized height");
|
|
143
243
|
});
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
await opts.node.subscribe("newHeads", async (head) => {
|
|
150
|
-
await unfinalized.reconcile({ hash: head.hash, number: head.number, parent_hash: head.parentHash }).catch((error) => {
|
|
151
|
-
if (error instanceof Error) {
|
|
152
|
-
log.error(`Failed to reconcile unfinalized head: ${error.message}`);
|
|
153
|
-
}
|
|
154
|
-
});
|
|
244
|
+
promise.catch((error) => {
|
|
245
|
+
if (error instanceof Error) {
|
|
246
|
+
log.error(error.message);
|
|
247
|
+
}
|
|
248
|
+
interrupt();
|
|
155
249
|
});
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
log.debug("Indexer finalized");
|
|
162
|
-
} catch (error) {
|
|
250
|
+
return interrupt;
|
|
251
|
+
};
|
|
252
|
+
const browser = (browser2) => {
|
|
253
|
+
const { isDisposed, onCleanup, interrupt } = lifecycle({
|
|
254
|
+
onCleanupError: (error) => {
|
|
163
255
|
if (error instanceof Error) {
|
|
164
|
-
log.warn(
|
|
256
|
+
log.warn(error.message);
|
|
165
257
|
}
|
|
166
258
|
}
|
|
259
|
+
});
|
|
260
|
+
browser2.signal.addEventListener("abort", interrupt, { once: true });
|
|
261
|
+
onCleanup(() => browser2.signal.removeEventListener("abort", interrupt));
|
|
262
|
+
if (browser2.signal.aborted) {
|
|
263
|
+
interrupt();
|
|
167
264
|
}
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
265
|
+
const promise = iife(async () => {
|
|
266
|
+
if (isDisposed()) {
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
const subscriptions = {
|
|
270
|
+
node: /* @__PURE__ */ new Map(),
|
|
271
|
+
abstraction: /* @__PURE__ */ new Map()
|
|
272
|
+
};
|
|
273
|
+
const transport = {
|
|
274
|
+
protocol: "browser",
|
|
275
|
+
request: async (request) => {
|
|
276
|
+
if (request.method !== "eth_unsubscribe") {
|
|
277
|
+
browser2.signal.throwIfAborted();
|
|
278
|
+
}
|
|
279
|
+
const res = await browser2.provider.request({ method: request.method, params: request.params });
|
|
280
|
+
if (request.method !== "eth_unsubscribe" && request.method !== "eth_subscribe") {
|
|
281
|
+
browser2.signal.throwIfAborted();
|
|
282
|
+
}
|
|
283
|
+
return res;
|
|
284
|
+
},
|
|
285
|
+
subscribe: async (param, listener) => {
|
|
286
|
+
const listeners = subscriptions.abstraction.get(param);
|
|
287
|
+
if (listeners === void 0) {
|
|
288
|
+
const listeners2 = /* @__PURE__ */ new Set();
|
|
289
|
+
listeners2.add(listener);
|
|
290
|
+
subscriptions.abstraction.set(param, listeners2);
|
|
291
|
+
const id = await transport.request({ method: "eth_subscribe", params: [param] }).catch((cause) => {
|
|
292
|
+
throw new Error(`Failed to initialise subscription for param ${param}`, { cause });
|
|
293
|
+
});
|
|
294
|
+
subscriptions.node.set(id, param);
|
|
295
|
+
} else {
|
|
296
|
+
listeners.add(listener);
|
|
297
|
+
}
|
|
298
|
+
return async function unsubscribe() {
|
|
299
|
+
const listeners2 = subscriptions.abstraction.get(param);
|
|
300
|
+
if (listeners2 === void 0) {
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
listeners2.delete(listener);
|
|
304
|
+
if (listeners2.size === 0) {
|
|
305
|
+
for (const [id, _param] of subscriptions.node) {
|
|
306
|
+
if (param === _param) {
|
|
307
|
+
await transport.request({ method: "eth_unsubscribe", params: [id] }).catch(() => {
|
|
308
|
+
log.warn("Failed to unsubscribe unused subscription");
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
};
|
|
179
314
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
315
|
+
};
|
|
316
|
+
const onMessage = async (message) => {
|
|
317
|
+
if (message.type === "eth_subscription") {
|
|
318
|
+
const param = subscriptions.node.get(message.data.subscription);
|
|
319
|
+
if (param === void 0) {
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
const listeners = subscriptions.abstraction.get(param);
|
|
323
|
+
if (listeners === void 0) {
|
|
324
|
+
return await transport.request({ method: "eth_unsubscribe", params: [message.data.subscription] }).catch(() => {
|
|
325
|
+
log.warn("Failed to unsubscribe stale subscription");
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
for (const listener of listeners) {
|
|
329
|
+
try {
|
|
330
|
+
listener(message.data.result);
|
|
331
|
+
} catch (error) {
|
|
332
|
+
if (error instanceof Error) {
|
|
333
|
+
log.error(error.message);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
183
337
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
338
|
+
};
|
|
339
|
+
browser2.provider.on("message", onMessage);
|
|
340
|
+
onCleanup(() => browser2.provider.removeListener("message", onMessage));
|
|
341
|
+
const _interrupt = instance({ chain: browser2.chain, node: transport });
|
|
342
|
+
onCleanup(() => _interrupt());
|
|
343
|
+
});
|
|
344
|
+
promise.catch((error) => {
|
|
345
|
+
if (error instanceof Error) {
|
|
346
|
+
log.error(error.message);
|
|
347
|
+
}
|
|
348
|
+
interrupt();
|
|
349
|
+
});
|
|
350
|
+
return interrupt;
|
|
351
|
+
};
|
|
352
|
+
iife(async () => {
|
|
353
|
+
try {
|
|
354
|
+
log.debug("Initialising realtime client");
|
|
355
|
+
if (realtime2.node.protocol === "wss") {
|
|
356
|
+
log.debug("Found user provided node");
|
|
357
|
+
const [chain, metadata] = await Promise.all([
|
|
358
|
+
realtime2.node.request({ method: "eth_chainId", params: [] }),
|
|
359
|
+
realtime2.indexer.request({ method: "public_getMetadata", params: [] })
|
|
360
|
+
]);
|
|
361
|
+
log.debug(`Determined chain identifier for connected node: ${hexToNumber(chain)}`);
|
|
362
|
+
if (!metadata.chains.some((_chain) => _chain === chain)) {
|
|
363
|
+
throw new Error("Provided `node` is connected to a chain not indexed by the provided `indexer`");
|
|
196
364
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
365
|
+
instance({ chain, node: realtime2.node });
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
if (realtime2.node.protocol === "browser") {
|
|
369
|
+
log.debug("Looking for browser injected node providers");
|
|
370
|
+
if (typeof window === "undefined") {
|
|
371
|
+
return log.debug("Browser indexing invoked on the server, aborting...");
|
|
372
|
+
}
|
|
373
|
+
const metadata = await realtime2.indexer.request({ method: "public_getMetadata", params: [] });
|
|
374
|
+
const providers = /* @__PURE__ */ new Map();
|
|
375
|
+
const sessions = /* @__PURE__ */ new Map();
|
|
376
|
+
window.addEventListener("eip6963:announceProvider", async (event) => {
|
|
377
|
+
const typed = event;
|
|
378
|
+
const provider = typed.detail;
|
|
379
|
+
if (providers.get(provider.info.uuid) !== void 0) {
|
|
380
|
+
return log.debug(`Found duplicate provider (${provider.info.uuid})`);
|
|
381
|
+
}
|
|
382
|
+
log.debug(`Found provider (${provider.info.uuid})`);
|
|
383
|
+
providers.set(provider.info.uuid, provider);
|
|
384
|
+
let controller = new AbortController();
|
|
385
|
+
const initialise = (initialise2) => {
|
|
386
|
+
for (const [key2, interrupt2] of sessions) {
|
|
387
|
+
if (key2.startsWith(provider.info.uuid)) {
|
|
388
|
+
try {
|
|
389
|
+
interrupt2();
|
|
390
|
+
sessions.delete(key2);
|
|
391
|
+
} catch (error) {
|
|
392
|
+
if (error instanceof Error) {
|
|
393
|
+
log.error(error.message);
|
|
394
|
+
}
|
|
395
|
+
sessions.delete(key2);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
206
398
|
}
|
|
399
|
+
if (!metadata.chains.includes(initialise2.chain)) {
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
for (const key2 of sessions.keys()) {
|
|
403
|
+
if (key2.endsWith(`:${initialise2.chain}`)) {
|
|
404
|
+
return log.debug(`Already indexing key ${key2}, aborting initialisation...`);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
const key = `${provider.info.uuid}:${initialise2.chain}`;
|
|
408
|
+
log.debug(`Initialising indexing for key ${key}`);
|
|
409
|
+
const interrupt = browser({ signal: initialise2.signal, chain: initialise2.chain, provider: provider.provider });
|
|
410
|
+
sessions.set(key, interrupt);
|
|
411
|
+
};
|
|
412
|
+
provider.provider.on("chainChanged", async (chain) => {
|
|
413
|
+
log.debug(`Provider (${provider.info.uuid}) changed to chain (${hexToNumber(chain)})`);
|
|
414
|
+
controller.abort();
|
|
415
|
+
controller = new AbortController();
|
|
416
|
+
initialise({ chain, signal: controller.signal });
|
|
417
|
+
});
|
|
418
|
+
const initialSignal = controller.signal;
|
|
419
|
+
const initialChain = await provider.provider.request({ method: "eth_chainId" });
|
|
420
|
+
if (initialSignal.aborted) {
|
|
421
|
+
return;
|
|
207
422
|
}
|
|
423
|
+
initialise({ chain: initialChain, signal: initialSignal });
|
|
208
424
|
});
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
number: finalizedBlock.number,
|
|
215
|
-
parent_hash: finalizedBlock.parentHash
|
|
216
|
-
});
|
|
217
|
-
await mutex_finalize();
|
|
218
|
-
} catch (error) {
|
|
219
|
-
if (error instanceof Error) {
|
|
220
|
-
log.error(`Failed to reconcile finalized head: ${error.message}`);
|
|
221
|
-
}
|
|
425
|
+
window.dispatchEvent(new Event("eip6963:requestProvider"));
|
|
426
|
+
}
|
|
427
|
+
} catch (error) {
|
|
428
|
+
if (error instanceof Error) {
|
|
429
|
+
log.error(error.message);
|
|
222
430
|
}
|
|
223
|
-
}
|
|
224
|
-
setInterval(poll, POLLING_INTERVAL_MS);
|
|
225
|
-
log.debug("Started polling finalized height");
|
|
226
|
-
});
|
|
227
|
-
promise.catch((error) => {
|
|
228
|
-
if (error instanceof Error) {
|
|
229
|
-
log.error(`Failed to initialise realtime client: ${error.message}`);
|
|
230
431
|
}
|
|
231
432
|
});
|
|
232
433
|
}
|
package/dist/rpc.d.mts
CHANGED
package/dist/rpc.d.ts
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import { RpcBlock, RpcTransactionReceipt } from 'viem';
|
|
2
2
|
import { Storage } from '../metadata.js';
|
|
3
3
|
|
|
4
|
-
type CamelToSnake<T extends string, P extends string = ""> = string extends T ? string : T extends `${infer C0}${infer R}` ? CamelToSnake<R, `${P}${C0 extends Lowercase<C0> ? "" : "_"}${Lowercase<C0>}`> : P;
|
|
5
|
-
type Flatten<T> = {
|
|
6
|
-
[K in keyof T as CamelToSnake<Extract<K, string>>]: T[K];
|
|
7
|
-
};
|
|
8
|
-
|
|
9
4
|
type Rpc = {
|
|
10
5
|
/**
|
|
11
6
|
* All available methods that can be requested
|
|
@@ -47,16 +42,13 @@ type IndexerRpc = {
|
|
|
47
42
|
*/
|
|
48
43
|
public_finalize: (chain: `0x${string}`) => Promise<void>;
|
|
49
44
|
/**
|
|
50
|
-
* @returns
|
|
45
|
+
* @returns Public metadata about the indexer
|
|
51
46
|
*/
|
|
52
|
-
|
|
47
|
+
public_getMetadata: () => Promise<PublicMetadata>;
|
|
53
48
|
/**
|
|
54
|
-
* @returns
|
|
49
|
+
* @returns Private metadata about the indexer
|
|
55
50
|
*/
|
|
56
|
-
|
|
57
|
-
id: string;
|
|
58
|
-
filters: Flatten<Filter>[];
|
|
59
|
-
}[]>;
|
|
51
|
+
private_getMetadata: () => Promise<PrivateMetadata>;
|
|
60
52
|
/**
|
|
61
53
|
* Accepts a list of events and a batch of minified block data and writes to storage
|
|
62
54
|
* @returns A list of failures that occured for each event and block pair
|
|
@@ -82,10 +74,7 @@ type IndexerRpc = {
|
|
|
82
74
|
subscribe: Record<string, never>;
|
|
83
75
|
};
|
|
84
76
|
|
|
85
|
-
|
|
86
|
-
* Types -----------------------------------------------------------------------------------------------------------------------------------
|
|
87
|
-
*/
|
|
88
|
-
type Protocol = "http" | "wss" | "local";
|
|
77
|
+
type Protocol = "http" | "wss" | "local" | "browser";
|
|
89
78
|
type Transport<R extends Rpc, P extends Protocol = Protocol> = {
|
|
90
79
|
/**
|
|
91
80
|
* The underlying transport protocol.
|
|
@@ -104,38 +93,33 @@ type Transport<R extends Rpc, P extends Protocol = Protocol> = {
|
|
|
104
93
|
* Subscribes to specific event to receive and invoke a callback for a stream of values
|
|
105
94
|
* @returns An async function to unsubscribe from the stream
|
|
106
95
|
*/
|
|
107
|
-
subscribe: <M extends keyof R["subscribe"]>(param: M,
|
|
96
|
+
subscribe: <M extends keyof R["subscribe"]>(param: M, listener: (message: R["subscribe"][M]) => void) => Promise<() => Promise<void>>;
|
|
108
97
|
};
|
|
109
98
|
/**
|
|
110
|
-
*
|
|
99
|
+
* local -----------------------------------------------------------------------------------------------------------------------------------
|
|
111
100
|
*/
|
|
112
101
|
declare function local<R extends Rpc>(rpc: R): Transport<R, "local">;
|
|
102
|
+
/**
|
|
103
|
+
* browser -----------------------------------------------------------------------------------------------------------------------------------
|
|
104
|
+
*/
|
|
105
|
+
declare function browser(): Transport<Rpc, "browser">;
|
|
113
106
|
declare function wss<R extends Rpc>(url: string, opts?: {
|
|
114
107
|
quiet?: boolean;
|
|
115
108
|
}): Transport<R, "wss">;
|
|
116
109
|
/**
|
|
117
|
-
*
|
|
110
|
+
* http -----------------------------------------------------------------------------------------------------------------------------------
|
|
118
111
|
*/
|
|
119
112
|
declare function http<R extends Rpc>(url: string, opts?: {
|
|
120
113
|
signingKey?: string;
|
|
121
114
|
}): Transport<R, "http">;
|
|
122
115
|
|
|
116
|
+
type CamelToSnake<T extends string, P extends string = ""> = string extends T ? string : T extends `${infer C0}${infer R}` ? CamelToSnake<R, `${P}${C0 extends Lowercase<C0> ? "" : "_"}${Lowercase<C0>}`> : P;
|
|
117
|
+
type Flatten<T> = {
|
|
118
|
+
[K in keyof T as CamelToSnake<Extract<K, string>>]: T[K];
|
|
119
|
+
};
|
|
120
|
+
|
|
123
121
|
/**
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
* Extend this interface in your application to expose additional RPC methods to every event:
|
|
127
|
-
*
|
|
128
|
-
* ```ts
|
|
129
|
-
* import "univo";
|
|
130
|
-
*
|
|
131
|
-
* declare module "univo" {
|
|
132
|
-
* interface Block {
|
|
133
|
-
* eth_getBalance: `0x${string}`;
|
|
134
|
-
* }
|
|
135
|
-
* }
|
|
136
|
-
* ```
|
|
137
|
-
*
|
|
138
|
-
* Your `getBlock` function must also return any required fields added by the augmentation.
|
|
122
|
+
* Block
|
|
139
123
|
*/
|
|
140
124
|
interface Block {
|
|
141
125
|
eth_chainId: `0x${string}`;
|
|
@@ -156,6 +140,8 @@ type Filter = {
|
|
|
156
140
|
event?: `0x${string}`;
|
|
157
141
|
/** Index blocks that involve this address */
|
|
158
142
|
address?: `0x${string}`;
|
|
143
|
+
/** Index blocks where this function signature was invoked */
|
|
144
|
+
function?: `0x${string}`;
|
|
159
145
|
};
|
|
160
146
|
/**
|
|
161
147
|
* Events -----------------------------------------------------------------------------------------------------------------------------------
|
|
@@ -276,9 +262,16 @@ type Head = {
|
|
|
276
262
|
number: `0x${string}`;
|
|
277
263
|
parent_hash: `0x${string}`;
|
|
278
264
|
};
|
|
279
|
-
type
|
|
265
|
+
type PublicMetadata = {
|
|
266
|
+
chains: `0x${string}`[];
|
|
267
|
+
};
|
|
268
|
+
type PrivateMetadata = {
|
|
280
269
|
version: string;
|
|
281
270
|
language: string;
|
|
271
|
+
events: {
|
|
272
|
+
id: string;
|
|
273
|
+
filters: Flatten<Filter>[];
|
|
274
|
+
}[];
|
|
282
275
|
};
|
|
283
276
|
type Result = {
|
|
284
277
|
status: string;
|
|
@@ -350,5 +343,5 @@ type Indexer = {
|
|
|
350
343
|
};
|
|
351
344
|
declare function defineIndexer(opts: Indexer): Transport<IndexerRpc, "local">;
|
|
352
345
|
|
|
353
|
-
export { defineEvent as a,
|
|
354
|
-
export type { Action as A, Block as B, Event as E, Filter as F, Head as H, IndexerRpc as I,
|
|
346
|
+
export { defineEvent as a, browser as b, defineAction as c, defineIndexer as d, http as h, local as l, wss as w };
|
|
347
|
+
export type { Action as A, Block as B, Event as E, Filter as F, Head as H, IndexerRpc as I, PublicMetadata as P, Rpc as R, Transport as T, Indexer as e, PrivateMetadata as f, Result as g };
|