univo 0.1.15
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/LICENSE +21 -0
- package/README.md +27 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.mjs +71 -0
- package/dist/client.d.mts +24 -0
- package/dist/client.d.ts +24 -0
- package/dist/client.mjs +43 -0
- package/dist/index.d.mts +113 -0
- package/dist/index.d.ts +113 -0
- package/dist/index.mjs +516 -0
- package/dist/realtime.d.mts +50 -0
- package/dist/realtime.d.ts +50 -0
- package/dist/realtime.mjs +210 -0
- package/dist/shared/univo.rTUTP64t.mjs +154 -0
- package/package.json +55 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 univo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# univo
|
|
2
|
+
|
|
3
|
+
[![npm version][npm-version-src]][npm-version-href]
|
|
4
|
+
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
5
|
+
|
|
6
|
+
Blazing-fast, developer-friendly blockchain indexing software designed to help you extract, transform, and load historical and realtime blockchain data into your own storage systems at scale.
|
|
7
|
+
|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
Conceptually, indexing software is responsible for synchronising data between a blockchain and some other storage system. The end goal is that your off-chain storage always accurately reflects the latest on-chain state.
|
|
11
|
+
|
|
12
|
+
univo was forged from years of experience building and maintaining blockchain indexers across the Ethereum ecosystem. It is designed to fit into your existing application and ensures that indexing blockchains remains simple, fast, and affordable as your application grows in scale and complexity.
|
|
13
|
+
|
|
14
|
+
## Documentation
|
|
15
|
+
|
|
16
|
+
Visit [univo.app](https://univo.app/docs) for documentation, guides, and the API reference.
|
|
17
|
+
|
|
18
|
+
## License
|
|
19
|
+
|
|
20
|
+
univo is MIT-licensed open-source software.
|
|
21
|
+
|
|
22
|
+
<!-- Badges -->
|
|
23
|
+
|
|
24
|
+
[npm-version-src]: https://img.shields.io/npm/v/univo?style=flat&colorA=18181B&colorB=F0DB4F
|
|
25
|
+
[npm-version-href]: https://npmjs.com/package/univo
|
|
26
|
+
[npm-downloads-src]: https://img.shields.io/npm/dm/univo?style=flat&colorA=18181B&colorB=F0DB4F
|
|
27
|
+
[npm-downloads-href]: https://npmjs.com/package/univo
|
package/dist/cli.d.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
package/dist/cli.mjs
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import WS from 'ws';
|
|
3
|
+
import open from 'open';
|
|
4
|
+
import { config } from 'dotenv';
|
|
5
|
+
import { WebSocket } from 'partysocket';
|
|
6
|
+
import { defineCommand, runMain } from 'citty';
|
|
7
|
+
import { http } from './client.mjs';
|
|
8
|
+
import { c as createLogger, e as version, l as name } from './shared/univo.rTUTP64t.mjs';
|
|
9
|
+
|
|
10
|
+
const log = createLogger({ quiet: false });
|
|
11
|
+
const dev = defineCommand({
|
|
12
|
+
args: {
|
|
13
|
+
url: {
|
|
14
|
+
required: true,
|
|
15
|
+
type: "positional",
|
|
16
|
+
description: "Endpoint url like http://localhost:3000"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
async run(ctx) {
|
|
20
|
+
try {
|
|
21
|
+
if (!ctx.args.url.startsWith("http://")) throw new Error("`url` must start with http://");
|
|
22
|
+
config();
|
|
23
|
+
const localSigningKey = process.env.UNIVO_SIGNING_KEY;
|
|
24
|
+
if (localSigningKey === void 0) throw new Error("Please provide a UNIVO_SIGNING_KEY environment variable");
|
|
25
|
+
const client = http(ctx.args.url, { signingKey: localSigningKey });
|
|
26
|
+
const [events, metadata] = await Promise.all([
|
|
27
|
+
client.request({ jsonrpc: "2.0", id: 0, method: "private_getEvents", params: [] }),
|
|
28
|
+
client.request({ jsonrpc: "2.0", id: 0, method: "private_getMetadata", params: [] })
|
|
29
|
+
]);
|
|
30
|
+
if (events.error) throw new Error(`Failed to connect to ${ctx.args.url}. Check that your server is running on the correct port.`);
|
|
31
|
+
if (metadata.error) throw new Error(`Failed to connect to ${ctx.args.url}. Check that your server is running on the correct port.`);
|
|
32
|
+
const remoteSigningKey = crypto.randomUUID();
|
|
33
|
+
const url = `https://tunnel-univo.app/v1/${crypto.randomUUID()}`;
|
|
34
|
+
const endpoint = {
|
|
35
|
+
url,
|
|
36
|
+
events: events.result,
|
|
37
|
+
metadata: metadata.result,
|
|
38
|
+
signing_key: remoteSigningKey
|
|
39
|
+
};
|
|
40
|
+
const data = btoa(JSON.stringify(endpoint));
|
|
41
|
+
await open(`https://univo.app/dev/${data}`);
|
|
42
|
+
const ws = new WebSocket(url, [], { WebSocket: WS });
|
|
43
|
+
ws.binaryType = "arraybuffer";
|
|
44
|
+
ws.onerror = (event) => log.error(event.message);
|
|
45
|
+
ws.onopen = () => log.info(`Dev server started for ${ctx.args.url}`);
|
|
46
|
+
ws.onclose = () => log.info(`Dev server closed for ${ctx.args.url}`);
|
|
47
|
+
ws.onmessage = async (event) => {
|
|
48
|
+
try {
|
|
49
|
+
const request = JSON.parse(event.data);
|
|
50
|
+
log.info(`Received request ${request.id}:${request.method}`);
|
|
51
|
+
const response = await client.request(request);
|
|
52
|
+
ws.send(JSON.stringify(response));
|
|
53
|
+
} catch (error) {
|
|
54
|
+
const response = { jsonrpc: "2.0", id: null, error: { code: 0, message: "Invalid request" } };
|
|
55
|
+
ws.send(JSON.stringify(response));
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
} catch (error) {
|
|
59
|
+
if (error instanceof Error) return log.error(error.message);
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
const main = defineCommand({
|
|
65
|
+
subCommands: { dev },
|
|
66
|
+
meta: { name, version }
|
|
67
|
+
});
|
|
68
|
+
runMain(main).catch((error) => {
|
|
69
|
+
if (error instanceof Error) log.error(error.message);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Rpc } from './index.mjs';
|
|
2
|
+
|
|
3
|
+
type Request<M extends keyof Rpc> = {
|
|
4
|
+
jsonrpc: "2.0";
|
|
5
|
+
id: number;
|
|
6
|
+
method: M;
|
|
7
|
+
params: Parameters<Rpc[M]>;
|
|
8
|
+
};
|
|
9
|
+
type Response<M extends keyof Rpc> = {
|
|
10
|
+
jsonrpc: "2.0";
|
|
11
|
+
id: number;
|
|
12
|
+
result?: Awaited<ReturnType<Rpc[M]>>;
|
|
13
|
+
error?: {
|
|
14
|
+
code: number;
|
|
15
|
+
message: string;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
declare function http(url: string, opts?: {
|
|
19
|
+
signingKey?: string;
|
|
20
|
+
}): {
|
|
21
|
+
request<M extends keyof Rpc>({ jsonrpc, id, method, params }: Request<M>): Promise<Response<M>>;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export { http };
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Rpc } from './index.js';
|
|
2
|
+
|
|
3
|
+
type Request<M extends keyof Rpc> = {
|
|
4
|
+
jsonrpc: "2.0";
|
|
5
|
+
id: number;
|
|
6
|
+
method: M;
|
|
7
|
+
params: Parameters<Rpc[M]>;
|
|
8
|
+
};
|
|
9
|
+
type Response<M extends keyof Rpc> = {
|
|
10
|
+
jsonrpc: "2.0";
|
|
11
|
+
id: number;
|
|
12
|
+
result?: Awaited<ReturnType<Rpc[M]>>;
|
|
13
|
+
error?: {
|
|
14
|
+
code: number;
|
|
15
|
+
message: string;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
declare function http(url: string, opts?: {
|
|
19
|
+
signingKey?: string;
|
|
20
|
+
}): {
|
|
21
|
+
request<M extends keyof Rpc>({ jsonrpc, id, method, params }: Request<M>): Promise<Response<M>>;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export { http };
|
package/dist/client.mjs
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { a as createException, o as compress, f as getSignature, g as getException } from './shared/univo.rTUTP64t.mjs';
|
|
2
|
+
|
|
3
|
+
const MIN_GZIP_SIZE = 1024;
|
|
4
|
+
function http(url, opts = {}) {
|
|
5
|
+
return {
|
|
6
|
+
async request({ jsonrpc, id, method, params }) {
|
|
7
|
+
try {
|
|
8
|
+
let body = JSON.stringify({ jsonrpc, id, method, params });
|
|
9
|
+
const headers = new Headers();
|
|
10
|
+
headers.set("Content-Type", "application/json");
|
|
11
|
+
if (method.startsWith("private_")) {
|
|
12
|
+
if (opts.signingKey === void 0) throw new Error(ClientUnauthorizedError);
|
|
13
|
+
if (body.length > MIN_GZIP_SIZE) {
|
|
14
|
+
body = await compress(body).catch((cause) => {
|
|
15
|
+
throw new Error(ClientCompressionError, { cause });
|
|
16
|
+
});
|
|
17
|
+
headers.set("Content-Encoding", "gzip");
|
|
18
|
+
}
|
|
19
|
+
const signature = await getSignature({ key: opts.signingKey, body }).catch((cause) => {
|
|
20
|
+
throw new Error(ClientSignatureError, { cause });
|
|
21
|
+
});
|
|
22
|
+
headers.set("X-Univo-Signature", signature);
|
|
23
|
+
}
|
|
24
|
+
const res = await fetch(url, { headers, body, method: "POST" }).catch((cause) => {
|
|
25
|
+
throw new Error(ClientConnectionError, { cause });
|
|
26
|
+
});
|
|
27
|
+
return await res.json().catch((cause) => {
|
|
28
|
+
throw new Error(ClientResponseError, { cause });
|
|
29
|
+
});
|
|
30
|
+
} catch (error) {
|
|
31
|
+
const message = getException(error) || "Unknown RPC error";
|
|
32
|
+
return { jsonrpc, id, error: { code: 0, message } };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const ClientCompressionError = createException("An error occurred when compressing the request");
|
|
38
|
+
const ClientConnectionError = createException("An errored occurred when connecting to the server");
|
|
39
|
+
const ClientResponseError = createException("An error occurred when reading the servers response");
|
|
40
|
+
const ClientSignatureError = createException("An error occurred with the outgoing request signature");
|
|
41
|
+
const ClientUnauthorizedError = createException("Attempted to execute a private method without providing a request signing key");
|
|
42
|
+
|
|
43
|
+
export { http };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
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;
|
|
2
|
+
type Flatten<T> = {
|
|
3
|
+
[K in keyof T as CamelToSnake<Extract<K, string>>]: T[K];
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
type Block = {
|
|
7
|
+
eth_chainId: `0x${string}`;
|
|
8
|
+
eth_getBlockByHash: {
|
|
9
|
+
hash: `0x${string}`;
|
|
10
|
+
number: `0x${string}`;
|
|
11
|
+
};
|
|
12
|
+
eth_getBlockReceipts: Array<{
|
|
13
|
+
logs: Array<{
|
|
14
|
+
address: `0x${string}`;
|
|
15
|
+
topics: `0x${string}`[];
|
|
16
|
+
}>;
|
|
17
|
+
}>;
|
|
18
|
+
};
|
|
19
|
+
type Filter = {
|
|
20
|
+
/** The chain id */
|
|
21
|
+
chain: number;
|
|
22
|
+
/** Block to querying/listening from */
|
|
23
|
+
fromBlock: number;
|
|
24
|
+
/** Block to query/listen until */
|
|
25
|
+
toBlock?: number;
|
|
26
|
+
/** The event */
|
|
27
|
+
event?: `0x${string}`;
|
|
28
|
+
/** The contract address from which logs should originate */
|
|
29
|
+
address?: `0x${string}`;
|
|
30
|
+
};
|
|
31
|
+
declare function matchFilter(block: Block, filter: Filter): boolean;
|
|
32
|
+
type Event<TBlock, TEvent> = {
|
|
33
|
+
/** Human-readable identifier for the event */
|
|
34
|
+
id: string;
|
|
35
|
+
/** The set of filters that determines if the handler should execute for a given block */
|
|
36
|
+
filters: Filter[];
|
|
37
|
+
/** The handler that transforms a block into a list of events */
|
|
38
|
+
handler: (block: TBlock) => TEvent[];
|
|
39
|
+
/** Persist storage */
|
|
40
|
+
storage: {
|
|
41
|
+
upsert: (events: TEvent[]) => Promise<void>;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
type Head = {
|
|
45
|
+
hash: `0x${string}`;
|
|
46
|
+
chain: `0x${string}`;
|
|
47
|
+
number: `0x${string}`;
|
|
48
|
+
};
|
|
49
|
+
type Metadata = {
|
|
50
|
+
version: string;
|
|
51
|
+
language: string;
|
|
52
|
+
max_concurrency: number | undefined;
|
|
53
|
+
};
|
|
54
|
+
type Result = {
|
|
55
|
+
status: string;
|
|
56
|
+
event_id: string;
|
|
57
|
+
chain: `0x${string}`;
|
|
58
|
+
block_hash: `0x${string}`;
|
|
59
|
+
block_number: `0x${string}`;
|
|
60
|
+
created_at: number;
|
|
61
|
+
};
|
|
62
|
+
type IndexerOptions<TBlock> = {
|
|
63
|
+
/**
|
|
64
|
+
* Logs are emitted based on the environment LOG_LEVEL. Set `quiet: true` to surpress all logs.
|
|
65
|
+
* Available log options are `DEBUG`, `INFO`, `WARN`, and `ERROR`.
|
|
66
|
+
*/
|
|
67
|
+
quiet?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Request signing key
|
|
70
|
+
*/
|
|
71
|
+
signingKey: string;
|
|
72
|
+
/**
|
|
73
|
+
* Maximum number of concurrent connections to open when backfilling blocks
|
|
74
|
+
*/
|
|
75
|
+
maxConcurrency?: number;
|
|
76
|
+
/**
|
|
77
|
+
* This function is to load each block when indexing blocks in realtime. This ensures that all block
|
|
78
|
+
* data processed originates from a trusted RPC source and can be safely relied on.
|
|
79
|
+
*/
|
|
80
|
+
getBlock: (block: Head) => Promise<TBlock>;
|
|
81
|
+
};
|
|
82
|
+
type Indexer<TBlock> = {
|
|
83
|
+
fetch: (req: Request) => Promise<Response>;
|
|
84
|
+
event: <TEvent>(event: Event<TBlock, TEvent>) => Event<TBlock, TEvent>;
|
|
85
|
+
};
|
|
86
|
+
type Rpc = {
|
|
87
|
+
public_writeBlocks(endpoint: string, heads: Head[]): Promise<void>;
|
|
88
|
+
private_getMetadata(): Promise<Metadata>;
|
|
89
|
+
private_getEvents(): Promise<{
|
|
90
|
+
id: string;
|
|
91
|
+
filters: Flatten<Filter>[];
|
|
92
|
+
}[]>;
|
|
93
|
+
private_writeEvents(params: {
|
|
94
|
+
events: string[];
|
|
95
|
+
blocks: Block[];
|
|
96
|
+
}): Promise<{
|
|
97
|
+
failures: Result[];
|
|
98
|
+
}>;
|
|
99
|
+
private_writeEventsAndGetKeys(params: {
|
|
100
|
+
events: string[];
|
|
101
|
+
block: Block;
|
|
102
|
+
}): Promise<{
|
|
103
|
+
results: Result[];
|
|
104
|
+
keys: string[];
|
|
105
|
+
}>;
|
|
106
|
+
};
|
|
107
|
+
declare function indexer<TBlock extends Block>(opts: IndexerOptions<TBlock>): {
|
|
108
|
+
fetch: (req: Request) => Promise<Response>;
|
|
109
|
+
event: <TEvent>(event: Event<TBlock, TEvent>) => Event<TBlock, TEvent>;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export { indexer, matchFilter };
|
|
113
|
+
export type { Event, Indexer, Rpc };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
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;
|
|
2
|
+
type Flatten<T> = {
|
|
3
|
+
[K in keyof T as CamelToSnake<Extract<K, string>>]: T[K];
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
type Block = {
|
|
7
|
+
eth_chainId: `0x${string}`;
|
|
8
|
+
eth_getBlockByHash: {
|
|
9
|
+
hash: `0x${string}`;
|
|
10
|
+
number: `0x${string}`;
|
|
11
|
+
};
|
|
12
|
+
eth_getBlockReceipts: Array<{
|
|
13
|
+
logs: Array<{
|
|
14
|
+
address: `0x${string}`;
|
|
15
|
+
topics: `0x${string}`[];
|
|
16
|
+
}>;
|
|
17
|
+
}>;
|
|
18
|
+
};
|
|
19
|
+
type Filter = {
|
|
20
|
+
/** The chain id */
|
|
21
|
+
chain: number;
|
|
22
|
+
/** Block to querying/listening from */
|
|
23
|
+
fromBlock: number;
|
|
24
|
+
/** Block to query/listen until */
|
|
25
|
+
toBlock?: number;
|
|
26
|
+
/** The event */
|
|
27
|
+
event?: `0x${string}`;
|
|
28
|
+
/** The contract address from which logs should originate */
|
|
29
|
+
address?: `0x${string}`;
|
|
30
|
+
};
|
|
31
|
+
declare function matchFilter(block: Block, filter: Filter): boolean;
|
|
32
|
+
type Event<TBlock, TEvent> = {
|
|
33
|
+
/** Human-readable identifier for the event */
|
|
34
|
+
id: string;
|
|
35
|
+
/** The set of filters that determines if the handler should execute for a given block */
|
|
36
|
+
filters: Filter[];
|
|
37
|
+
/** The handler that transforms a block into a list of events */
|
|
38
|
+
handler: (block: TBlock) => TEvent[];
|
|
39
|
+
/** Persist storage */
|
|
40
|
+
storage: {
|
|
41
|
+
upsert: (events: TEvent[]) => Promise<void>;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
type Head = {
|
|
45
|
+
hash: `0x${string}`;
|
|
46
|
+
chain: `0x${string}`;
|
|
47
|
+
number: `0x${string}`;
|
|
48
|
+
};
|
|
49
|
+
type Metadata = {
|
|
50
|
+
version: string;
|
|
51
|
+
language: string;
|
|
52
|
+
max_concurrency: number | undefined;
|
|
53
|
+
};
|
|
54
|
+
type Result = {
|
|
55
|
+
status: string;
|
|
56
|
+
event_id: string;
|
|
57
|
+
chain: `0x${string}`;
|
|
58
|
+
block_hash: `0x${string}`;
|
|
59
|
+
block_number: `0x${string}`;
|
|
60
|
+
created_at: number;
|
|
61
|
+
};
|
|
62
|
+
type IndexerOptions<TBlock> = {
|
|
63
|
+
/**
|
|
64
|
+
* Logs are emitted based on the environment LOG_LEVEL. Set `quiet: true` to surpress all logs.
|
|
65
|
+
* Available log options are `DEBUG`, `INFO`, `WARN`, and `ERROR`.
|
|
66
|
+
*/
|
|
67
|
+
quiet?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Request signing key
|
|
70
|
+
*/
|
|
71
|
+
signingKey: string;
|
|
72
|
+
/**
|
|
73
|
+
* Maximum number of concurrent connections to open when backfilling blocks
|
|
74
|
+
*/
|
|
75
|
+
maxConcurrency?: number;
|
|
76
|
+
/**
|
|
77
|
+
* This function is to load each block when indexing blocks in realtime. This ensures that all block
|
|
78
|
+
* data processed originates from a trusted RPC source and can be safely relied on.
|
|
79
|
+
*/
|
|
80
|
+
getBlock: (block: Head) => Promise<TBlock>;
|
|
81
|
+
};
|
|
82
|
+
type Indexer<TBlock> = {
|
|
83
|
+
fetch: (req: Request) => Promise<Response>;
|
|
84
|
+
event: <TEvent>(event: Event<TBlock, TEvent>) => Event<TBlock, TEvent>;
|
|
85
|
+
};
|
|
86
|
+
type Rpc = {
|
|
87
|
+
public_writeBlocks(endpoint: string, heads: Head[]): Promise<void>;
|
|
88
|
+
private_getMetadata(): Promise<Metadata>;
|
|
89
|
+
private_getEvents(): Promise<{
|
|
90
|
+
id: string;
|
|
91
|
+
filters: Flatten<Filter>[];
|
|
92
|
+
}[]>;
|
|
93
|
+
private_writeEvents(params: {
|
|
94
|
+
events: string[];
|
|
95
|
+
blocks: Block[];
|
|
96
|
+
}): Promise<{
|
|
97
|
+
failures: Result[];
|
|
98
|
+
}>;
|
|
99
|
+
private_writeEventsAndGetKeys(params: {
|
|
100
|
+
events: string[];
|
|
101
|
+
block: Block;
|
|
102
|
+
}): Promise<{
|
|
103
|
+
results: Result[];
|
|
104
|
+
keys: string[];
|
|
105
|
+
}>;
|
|
106
|
+
};
|
|
107
|
+
declare function indexer<TBlock extends Block>(opts: IndexerOptions<TBlock>): {
|
|
108
|
+
fetch: (req: Request) => Promise<Response>;
|
|
109
|
+
event: <TEvent>(event: Event<TBlock, TEvent>) => Event<TBlock, TEvent>;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export { indexer, matchFilter };
|
|
113
|
+
export type { Event, Indexer, Rpc };
|