@notuslabs/yail 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/LICENSE +21 -0
- package/README.md +226 -0
- package/bin/yail.js +7 -0
- package/dist/addresses/registry.d.ts +57 -0
- package/dist/addresses/registry.d.ts.map +1 -0
- package/dist/addresses/registry.js +131 -0
- package/dist/addresses/registry.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +204 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config/address.d.ts +32 -0
- package/dist/config/address.d.ts.map +1 -0
- package/dist/config/address.js +31 -0
- package/dist/config/address.js.map +1 -0
- package/dist/config/chain-ref.d.ts +5 -0
- package/dist/config/chain-ref.d.ts.map +1 -0
- package/dist/config/chain-ref.js +13 -0
- package/dist/config/chain-ref.js.map +1 -0
- package/dist/config/create-config.d.ts +9 -0
- package/dist/config/create-config.d.ts.map +1 -0
- package/dist/config/create-config.js +86 -0
- package/dist/config/create-config.js.map +1 -0
- package/dist/config/index.d.ts +5 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +3 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/types.d.ts +113 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +2 -0
- package/dist/config/types.js.map +1 -0
- package/dist/db/batch.d.ts +33 -0
- package/dist/db/batch.d.ts.map +1 -0
- package/dist/db/batch.js +71 -0
- package/dist/db/batch.js.map +1 -0
- package/dist/db/client.d.ts +50 -0
- package/dist/db/client.d.ts.map +1 -0
- package/dist/db/client.js +104 -0
- package/dist/db/client.js.map +1 -0
- package/dist/db/index.d.ts +11 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +7 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/internal.d.ts +2332 -0
- package/dist/db/internal.d.ts.map +1 -0
- package/dist/db/internal.js +75 -0
- package/dist/db/internal.js.map +1 -0
- package/dist/db/migrate.d.ts +22 -0
- package/dist/db/migrate.d.ts.map +1 -0
- package/dist/db/migrate.js +72 -0
- package/dist/db/migrate.js.map +1 -0
- package/dist/db/serialize.d.ts +14 -0
- package/dist/db/serialize.d.ts.map +1 -0
- package/dist/db/serialize.js +133 -0
- package/dist/db/serialize.js.map +1 -0
- package/dist/db/sql.d.ts +44 -0
- package/dist/db/sql.d.ts.map +1 -0
- package/dist/db/sql.js +122 -0
- package/dist/db/sql.js.map +1 -0
- package/dist/http/client.d.ts +40 -0
- package/dist/http/client.d.ts.map +1 -0
- package/dist/http/client.js +128 -0
- package/dist/http/client.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer/context.d.ts +84 -0
- package/dist/indexer/context.d.ts.map +1 -0
- package/dist/indexer/context.js +45 -0
- package/dist/indexer/context.js.map +1 -0
- package/dist/indexer/events.d.ts +87 -0
- package/dist/indexer/events.d.ts.map +1 -0
- package/dist/indexer/events.js +88 -0
- package/dist/indexer/events.js.map +1 -0
- package/dist/indexer/indexer.d.ts +114 -0
- package/dist/indexer/indexer.d.ts.map +1 -0
- package/dist/indexer/indexer.js +237 -0
- package/dist/indexer/indexer.js.map +1 -0
- package/dist/indexer/jobs.d.ts +61 -0
- package/dist/indexer/jobs.d.ts.map +1 -0
- package/dist/indexer/jobs.js +170 -0
- package/dist/indexer/jobs.js.map +1 -0
- package/dist/indexer/plan.d.ts +73 -0
- package/dist/indexer/plan.d.ts.map +1 -0
- package/dist/indexer/plan.js +238 -0
- package/dist/indexer/plan.js.map +1 -0
- package/dist/indexer/runtime.d.ts +100 -0
- package/dist/indexer/runtime.d.ts.map +1 -0
- package/dist/indexer/runtime.js +572 -0
- package/dist/indexer/runtime.js.map +1 -0
- package/dist/observability/logger.d.ts +23 -0
- package/dist/observability/logger.d.ts.map +1 -0
- package/dist/observability/logger.js +72 -0
- package/dist/observability/logger.js.map +1 -0
- package/dist/observability/metrics.d.ts +61 -0
- package/dist/observability/metrics.d.ts.map +1 -0
- package/dist/observability/metrics.js +131 -0
- package/dist/observability/metrics.js.map +1 -0
- package/dist/observability/otel.d.ts +28 -0
- package/dist/observability/otel.d.ts.map +1 -0
- package/dist/observability/otel.js +49 -0
- package/dist/observability/otel.js.map +1 -0
- package/dist/rpc/cached-client.d.ts +33 -0
- package/dist/rpc/cached-client.d.ts.map +1 -0
- package/dist/rpc/cached-client.js +50 -0
- package/dist/rpc/cached-client.js.map +1 -0
- package/dist/schema/column.d.ts +61 -0
- package/dist/schema/column.d.ts.map +1 -0
- package/dist/schema/column.js +76 -0
- package/dist/schema/column.js.map +1 -0
- package/dist/schema/ddl.d.ts +9 -0
- package/dist/schema/ddl.d.ts.map +1 -0
- package/dist/schema/ddl.js +58 -0
- package/dist/schema/ddl.js.map +1 -0
- package/dist/schema/index.d.ts +8 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +5 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/table.d.ts +69 -0
- package/dist/schema/table.d.ts.map +1 -0
- package/dist/schema/table.js +35 -0
- package/dist/schema/table.js.map +1 -0
- package/dist/schema/view.d.ts +19 -0
- package/dist/schema/view.d.ts.map +1 -0
- package/dist/schema/view.js +16 -0
- package/dist/schema/view.js.map +1 -0
- package/dist/server/api.d.ts +11 -0
- package/dist/server/api.d.ts.map +1 -0
- package/dist/server/api.js +71 -0
- package/dist/server/api.js.map +1 -0
- package/dist/sources/cached.d.ts +27 -0
- package/dist/sources/cached.d.ts.map +1 -0
- package/dist/sources/cached.js +111 -0
- package/dist/sources/cached.js.map +1 -0
- package/dist/sources/esplora.d.ts +22 -0
- package/dist/sources/esplora.d.ts.map +1 -0
- package/dist/sources/esplora.js +138 -0
- package/dist/sources/esplora.js.map +1 -0
- package/dist/sources/fixture.d.ts +51 -0
- package/dist/sources/fixture.d.ts.map +1 -0
- package/dist/sources/fixture.js +102 -0
- package/dist/sources/fixture.js.map +1 -0
- package/dist/sources/hypersync.d.ts +19 -0
- package/dist/sources/hypersync.d.ts.map +1 -0
- package/dist/sources/hypersync.js +169 -0
- package/dist/sources/hypersync.js.map +1 -0
- package/dist/sources/index.d.ts +13 -0
- package/dist/sources/index.d.ts.map +1 -0
- package/dist/sources/index.js +7 -0
- package/dist/sources/index.js.map +1 -0
- package/dist/sources/rpc.d.ts +21 -0
- package/dist/sources/rpc.d.ts.map +1 -0
- package/dist/sources/rpc.js +187 -0
- package/dist/sources/rpc.js.map +1 -0
- package/dist/sources/types.d.ts +137 -0
- package/dist/sources/types.d.ts.map +1 -0
- package/dist/sources/types.js +17 -0
- package/dist/sources/types.js.map +1 -0
- package/dist/testing/index.d.ts +20 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +44 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/util.d.ts +9 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +25 -0
- package/dist/util.js.map +1 -0
- package/package.json +100 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { httpCache } from "../db/internal.js";
|
|
3
|
+
import { sql } from "../db/sql.js";
|
|
4
|
+
/**
|
|
5
|
+
* HTTP client with an optional response cache. Cached calls are deterministic
|
|
6
|
+
* across re-indexes, which is what you want for price lookups, swap
|
|
7
|
+
* classification via aggregator APIs, token metadata, etc.
|
|
8
|
+
*/
|
|
9
|
+
export function createHttpClient(options = {}) {
|
|
10
|
+
const doFetch = options.fetch ?? fetch;
|
|
11
|
+
const memory = new Map();
|
|
12
|
+
const memorySize = options.memorySize ?? 5000;
|
|
13
|
+
const persist = options.persist !== false && options.db !== undefined;
|
|
14
|
+
const retries = options.retries ?? 3;
|
|
15
|
+
const remember = (key, res, expiresAt) => {
|
|
16
|
+
if (memory.size >= memorySize)
|
|
17
|
+
memory.delete(memory.keys().next().value);
|
|
18
|
+
memory.set(key, { res, expiresAt });
|
|
19
|
+
};
|
|
20
|
+
async function run(url, init = {}) {
|
|
21
|
+
const { cache, cacheKey, ...reqInit } = init;
|
|
22
|
+
let ttl = 0;
|
|
23
|
+
if (cache === true)
|
|
24
|
+
ttl = Infinity;
|
|
25
|
+
else if (typeof cache === "number")
|
|
26
|
+
ttl = cache;
|
|
27
|
+
let key;
|
|
28
|
+
if (ttl > 0)
|
|
29
|
+
key = hashRequest(url, reqInit, cacheKey);
|
|
30
|
+
const now = Date.now();
|
|
31
|
+
if (key) {
|
|
32
|
+
const m = memory.get(key);
|
|
33
|
+
if (m && m.expiresAt > now) {
|
|
34
|
+
options.onCache?.(true);
|
|
35
|
+
return { ...m.res, cached: true };
|
|
36
|
+
}
|
|
37
|
+
if (persist) {
|
|
38
|
+
const rows = await options.db.rows(httpCache, sql `WHERE key = ${key} LIMIT 1`);
|
|
39
|
+
const row = rows[0];
|
|
40
|
+
if (row && row.expiresAt.getTime() > now) {
|
|
41
|
+
const res = toResponse(row.status, JSON.parse(row.headers), row.body, true);
|
|
42
|
+
remember(key, res, row.expiresAt.getTime());
|
|
43
|
+
options.onCache?.(true);
|
|
44
|
+
return res;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
options.onCache?.(false);
|
|
48
|
+
}
|
|
49
|
+
const res = await fetchWithRetry(url, reqInit);
|
|
50
|
+
if (key && res.ok) {
|
|
51
|
+
let expiresAt = now + ttl;
|
|
52
|
+
if (ttl === Infinity)
|
|
53
|
+
expiresAt = new Date("2200-01-01T00:00:00Z").getTime();
|
|
54
|
+
remember(key, res, expiresAt);
|
|
55
|
+
if (persist) {
|
|
56
|
+
await options.db.insert(httpCache).values({
|
|
57
|
+
key,
|
|
58
|
+
url,
|
|
59
|
+
status: res.status,
|
|
60
|
+
headers: JSON.stringify(res.headers),
|
|
61
|
+
body: res.body,
|
|
62
|
+
fetchedAt: new Date(now),
|
|
63
|
+
expiresAt: new Date(expiresAt),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return res;
|
|
68
|
+
}
|
|
69
|
+
async function fetchWithRetry(url, init) {
|
|
70
|
+
let attempt = 0;
|
|
71
|
+
for (;;) {
|
|
72
|
+
try {
|
|
73
|
+
const r = await doFetch(url, init);
|
|
74
|
+
if ((r.status === 429 || r.status >= 500) && attempt < retries) {
|
|
75
|
+
attempt++;
|
|
76
|
+
await new Promise((res) => setTimeout(res, 300 * 2 ** attempt));
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const headers = {};
|
|
80
|
+
r.headers.forEach((v, k) => (headers[k] = v));
|
|
81
|
+
return toResponse(r.status, headers, await r.text(), false);
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
if (attempt >= retries)
|
|
85
|
+
throw err;
|
|
86
|
+
attempt++;
|
|
87
|
+
await new Promise((res) => setTimeout(res, 300 * 2 ** attempt));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
fetch: run,
|
|
93
|
+
get: (url, init) => run(url, { ...init, method: "GET" }),
|
|
94
|
+
post: (url, body, init) => run(url, {
|
|
95
|
+
...init,
|
|
96
|
+
method: "POST",
|
|
97
|
+
headers: { "content-type": "application/json", ...init?.headers },
|
|
98
|
+
body: toBody(body),
|
|
99
|
+
}),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function toBody(body) {
|
|
103
|
+
if (typeof body === "string")
|
|
104
|
+
return body;
|
|
105
|
+
return JSON.stringify(body);
|
|
106
|
+
}
|
|
107
|
+
function toResponse(status, headers, body, cached) {
|
|
108
|
+
return {
|
|
109
|
+
status,
|
|
110
|
+
ok: status >= 200 && status < 300,
|
|
111
|
+
headers,
|
|
112
|
+
body,
|
|
113
|
+
cached,
|
|
114
|
+
json() {
|
|
115
|
+
return JSON.parse(body);
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function hashRequest(url, init, extra) {
|
|
120
|
+
const h = createHash("sha256");
|
|
121
|
+
h.update(init.method ?? "GET").update("\n").update(url).update("\n");
|
|
122
|
+
if (init.body)
|
|
123
|
+
h.update(toBody(init.body));
|
|
124
|
+
if (extra)
|
|
125
|
+
h.update("\n").update(extra);
|
|
126
|
+
return h.digest("hex").slice(0, 40);
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/http/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export { createConfig, addressSet, factory } from "./config/index.js";
|
|
2
|
+
export type { Config, ChainConfig, ContractConfig, AccountConfig, EventFilter, AddressSpec, AddressSetRef, FactoryRef, CacheConfig, ObservabilityConfig, ServerConfig, IndexingConfig, AddressSetConfig } from "./config/index.js";
|
|
3
|
+
export { t, table, materializedView, tableDdl, materializedViewDdl } from "./schema/index.js";
|
|
4
|
+
export type { Table, TableOptions, TableEngine, Column, InsertRow, InferRow, MaterializedView } from "./schema/index.js";
|
|
5
|
+
export { createDb, sql, migrate, schemaDdl, BatchWriter, internalTables } from "./db/index.js";
|
|
6
|
+
export type { Db, DatabaseConfig, SqlFragment, MigrateOptions } from "./db/index.js";
|
|
7
|
+
export { hypersync, rpc, cached, esplora, fixtureSource } from "./sources/index.js";
|
|
8
|
+
export type { Source, EvmSource, BitcoinSource, EvmQuery, EvmBatch, EvmLog, EvmBlock, EvmTransaction, BitcoinQuery, BitcoinBatch, BitcoinTransaction, HypersyncOptions, RpcSourceOptions, EsploraOptions, CachedSourceOptions } from "./sources/index.js";
|
|
9
|
+
export { createIndexer } from "./indexer/indexer.js";
|
|
10
|
+
export type { Indexer, IndexerOptions, StatusSnapshot, ReindexRequest } from "./indexer/indexer.js";
|
|
11
|
+
export type { HandlerContext, HandlerDb, AddressesApi } from "./indexer/context.js";
|
|
12
|
+
export type { ContractEvent, EvmAccountEvent, BitcoinAccountEvent, SetupEvent, EventNames, EventOf } from "./indexer/events.js";
|
|
13
|
+
export type { HttpClient, HttpResponse, HttpRequestInit, HttpCacheOptions } from "./http/client.js";
|
|
14
|
+
export type { CachedClient, ReadContractParams } from "./rpc/cached-client.js";
|
|
15
|
+
export type { AddressRow, AddressStatus } from "./addresses/registry.js";
|
|
16
|
+
export { createError } from "./observability/logger.js";
|
|
17
|
+
export type { Observability, WideLogger } from "./observability/logger.js";
|
|
18
|
+
export { createApp } from "./server/api.js";
|
|
19
|
+
export { parseAbi, parseAbiItem, formatUnits, parseUnits, getAddress, isAddress } from "viem";
|
|
20
|
+
export type { Abi, AbiEvent } from "viem";
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACtE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,mBAAmB,EAAE,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAGnO,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC9F,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACzH,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/F,YAAY,EAAE,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGrF,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACpF,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAG1P,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACpG,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpF,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,mBAAmB,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAChI,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpG,YAAY,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAGzE,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAC9F,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Config
|
|
2
|
+
export { createConfig, addressSet, factory } from "./config/index.js";
|
|
3
|
+
// Schema + database
|
|
4
|
+
export { t, table, materializedView, tableDdl, materializedViewDdl } from "./schema/index.js";
|
|
5
|
+
export { createDb, sql, migrate, schemaDdl, BatchWriter, internalTables } from "./db/index.js";
|
|
6
|
+
// Sources
|
|
7
|
+
export { hypersync, rpc, cached, esplora, fixtureSource } from "./sources/index.js";
|
|
8
|
+
// Indexer
|
|
9
|
+
export { createIndexer } from "./indexer/indexer.js";
|
|
10
|
+
// Observability
|
|
11
|
+
export { createError } from "./observability/logger.js";
|
|
12
|
+
export { createApp } from "./server/api.js";
|
|
13
|
+
// Handy re-exports
|
|
14
|
+
export { parseAbi, parseAbiItem, formatUnits, parseUnits, getAddress, isAddress } from "viem";
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,SAAS;AACT,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAGtE,oBAAoB;AACpB,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE9F,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/F,UAAU;AACV,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGpF,UAAU;AACV,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAQrD,gBAAgB;AAChB,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAExD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,mBAAmB;AACnB,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { Abi } from "viem";
|
|
2
|
+
import type { AddressRegistry, AddressRow } from "../addresses/registry.js";
|
|
3
|
+
import type { Db } from "../db/client.js";
|
|
4
|
+
import { BatchWriter } from "../db/batch.js";
|
|
5
|
+
import type { RowMeta } from "../db/serialize.js";
|
|
6
|
+
import type { HttpClient } from "../http/client.js";
|
|
7
|
+
import type { CachedClient } from "../rpc/cached-client.js";
|
|
8
|
+
import type { InferRow, InsertRow, Table } from "../schema/table.js";
|
|
9
|
+
import type { WideLogger } from "../observability/logger.js";
|
|
10
|
+
import type { Config } from "../config/types.js";
|
|
11
|
+
/** `context.db`: same as `Db` but inserts are buffered and flushed per batch. */
|
|
12
|
+
export interface HandlerDb extends Omit<Db, "insert"> {
|
|
13
|
+
/** Buffered insert. Rows become visible in ClickHouse after the batch flushes (before the checkpoint is written). */
|
|
14
|
+
insert<T extends Table<any>>(table: T): {
|
|
15
|
+
values(rows: InsertRow<T> | InsertRow<T>[]): void;
|
|
16
|
+
};
|
|
17
|
+
/** Buffer-aware lookup: returns the latest row written in this batch for the key, else reads ClickHouse (FINAL). */
|
|
18
|
+
find<T extends Table<any>>(table: T, key: Partial<InferRow<T>>): Promise<InferRow<T> | null>;
|
|
19
|
+
/** Force a flush now (rarely needed). */
|
|
20
|
+
flush(): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
export interface AddressesApi {
|
|
23
|
+
/** Is the address a live or pending member of the set on the current chain? */
|
|
24
|
+
has(set: string, address: string, chain?: string): boolean;
|
|
25
|
+
/** Register an address for backfill + live indexing. Idempotent. */
|
|
26
|
+
register(set: string, address: string, options?: {
|
|
27
|
+
chain?: string;
|
|
28
|
+
fromBlock?: number;
|
|
29
|
+
meta?: Record<string, unknown>;
|
|
30
|
+
}): Promise<AddressRow>;
|
|
31
|
+
list(set: string, chain?: string): AddressRow[];
|
|
32
|
+
}
|
|
33
|
+
export interface HandlerContext<C extends Config<any, any, any> = Config<any, any, any>, chain extends string = string> {
|
|
34
|
+
chain: {
|
|
35
|
+
name: chain;
|
|
36
|
+
id: number | string;
|
|
37
|
+
kind: "evm" | "bitcoin";
|
|
38
|
+
};
|
|
39
|
+
db: HandlerDb;
|
|
40
|
+
/** Cached contract reads; only defined for EVM chains with `rpc` configured. */
|
|
41
|
+
client: CachedClient | undefined;
|
|
42
|
+
http: HttpClient;
|
|
43
|
+
addresses: AddressesApi;
|
|
44
|
+
/** ABIs and static addresses from the config, for `client.readContract`. */
|
|
45
|
+
contracts: {
|
|
46
|
+
[K in keyof NonNullable<C["contracts"]> & string]: {
|
|
47
|
+
abi: NonNullable<C["contracts"]>[K]["abi"];
|
|
48
|
+
address?: string;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
/** evlog wide-event logger for the current batch. `log.set({...})` adds fields to the batch event. */
|
|
52
|
+
log: WideLogger;
|
|
53
|
+
/** True while running an address backfill or re-index job (vs. the live loop). */
|
|
54
|
+
backfill: boolean;
|
|
55
|
+
}
|
|
56
|
+
export interface ContextDeps {
|
|
57
|
+
db: Db;
|
|
58
|
+
writer: BatchWriter;
|
|
59
|
+
registry: AddressRegistry;
|
|
60
|
+
http: HttpClient;
|
|
61
|
+
client: CachedClient | undefined;
|
|
62
|
+
chain: {
|
|
63
|
+
name: string;
|
|
64
|
+
id: number | string;
|
|
65
|
+
kind: "evm" | "bitcoin";
|
|
66
|
+
};
|
|
67
|
+
contracts: Record<string, {
|
|
68
|
+
abi: Abi;
|
|
69
|
+
address?: string;
|
|
70
|
+
}>;
|
|
71
|
+
defaultFromBlock: (set: string) => number;
|
|
72
|
+
log: WideLogger;
|
|
73
|
+
backfill: boolean;
|
|
74
|
+
/** Set by the runtime before each handler call. */
|
|
75
|
+
meta: {
|
|
76
|
+
current: RowMeta;
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
export declare function createHandlerDb(db: Db, writer: BatchWriter, meta: {
|
|
80
|
+
current: RowMeta;
|
|
81
|
+
}): HandlerDb;
|
|
82
|
+
export declare function createContext(deps: ContextDeps): HandlerContext<any, string>;
|
|
83
|
+
export { BatchWriter };
|
|
84
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/indexer/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAChC,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAGjD,iFAAiF;AACjF,MAAM,WAAW,SAAU,SAAQ,IAAI,CAAC,EAAE,EAAE,QAAQ,CAAC;IACnD,qHAAqH;IACrH,MAAM,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG;QAAE,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAA;KAAE,CAAC;IAC9F,oHAAoH;IACpH,IAAI,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7F,yCAAyC;IACzC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,+EAA+E;IAC/E,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3D,oEAAoE;IACpE,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAC9I,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE,CAAC;CACjD;AAED,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,KAAK,SAAS,MAAM,GAAG,MAAM;IACpH,KAAK,EAAE;QAAE,IAAI,EAAE,KAAK,CAAC;QAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,IAAI,EAAE,KAAK,GAAG,SAAS,CAAA;KAAE,CAAC;IACrE,EAAE,EAAE,SAAS,CAAC;IACd,gFAAgF;IAChF,MAAM,EAAE,YAAY,GAAG,SAAS,CAAC;IACjC,IAAI,EAAE,UAAU,CAAC;IACjB,SAAS,EAAE,YAAY,CAAC;IACxB,4EAA4E;IAC5E,SAAS,EAAE;SAAG,CAAC,IAAI,MAAM,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,GAAG,MAAM,GAAG;YAAE,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YAAC,OAAO,CAAC,EAAE,MAAM,CAAA;SAAE;KAAE,CAAC;IACnI,sGAAsG;IACtG,GAAG,EAAE,UAAU,CAAC;IAChB,kFAAkF;IAClF,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,EAAE,CAAC;IACP,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,eAAe,CAAC;IAC1B,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,YAAY,GAAG,SAAS,CAAC;IACjC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,IAAI,EAAE,KAAK,GAAG,SAAS,CAAA;KAAE,CAAC;IACtE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,GAAG,EAAE,GAAG,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1D,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1C,GAAG,EAAE,UAAU,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,mDAAmD;IACnD,IAAI,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;CAC5B;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,CAoBlG;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,WAAW,GAAG,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,CAkB5E;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { BatchWriter } from "../db/batch.js";
|
|
2
|
+
import { toArray } from "../util.js";
|
|
3
|
+
export function createHandlerDb(db, writer, meta) {
|
|
4
|
+
const handlerDb = {
|
|
5
|
+
...db,
|
|
6
|
+
insert(table) {
|
|
7
|
+
return {
|
|
8
|
+
values(rows) {
|
|
9
|
+
for (const r of toArray(rows))
|
|
10
|
+
writer.add(table, r, meta.current);
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
},
|
|
14
|
+
async find(table, key) {
|
|
15
|
+
const buffered = writer.peek(table, key);
|
|
16
|
+
if (buffered)
|
|
17
|
+
return buffered;
|
|
18
|
+
return db.find(table, key);
|
|
19
|
+
},
|
|
20
|
+
async flush() {
|
|
21
|
+
await writer.flush();
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
return handlerDb;
|
|
25
|
+
}
|
|
26
|
+
export function createContext(deps) {
|
|
27
|
+
return {
|
|
28
|
+
chain: deps.chain,
|
|
29
|
+
db: createHandlerDb(deps.db, deps.writer, deps.meta),
|
|
30
|
+
client: deps.client,
|
|
31
|
+
http: deps.http,
|
|
32
|
+
addresses: {
|
|
33
|
+
has: (set, address, chain) => deps.registry.has(set, chain ?? deps.chain.name, address),
|
|
34
|
+
register: (set, address, options) => deps.registry
|
|
35
|
+
.register({ set, chain: options?.chain ?? deps.chain.name, address, fromBlock: options?.fromBlock ?? deps.defaultFromBlock(set), meta: options?.meta })
|
|
36
|
+
.then((rows) => rows[0]),
|
|
37
|
+
list: (set, chain) => deps.registry.list({ set, chain: chain ?? deps.chain.name }),
|
|
38
|
+
},
|
|
39
|
+
contracts: deps.contracts,
|
|
40
|
+
log: deps.log,
|
|
41
|
+
backfill: deps.backfill,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export { BatchWriter };
|
|
45
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/indexer/context.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAO7C,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAkDrC,MAAM,UAAU,eAAe,CAAC,EAAM,EAAE,MAAmB,EAAE,IAA0B;IACrF,MAAM,SAAS,GAAc;QAC3B,GAAG,EAAE;QACL,MAAM,CAAC,KAAK;YACV,OAAO;gBACL,MAAM,CAAC,IAAI;oBACT,KAAK,MAAM,CAAC,IAAI,OAAO,CAAM,IAAI,CAAC;wBAAE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;gBACzE,CAAC;aACF,CAAC;QACJ,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG;YACnB,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YACzC,IAAI,QAAQ;gBAAE,OAAO,QAAQ,CAAC;YAC9B,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC7B,CAAC;QACD,KAAK,CAAC,KAAK;YACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;KACF,CAAC;IACF,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAiB;IAC7C,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,EAAE,EAAE,eAAe,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC;QACpD,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,SAAS,EAAE;YACT,GAAG,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC;YACvF,QAAQ,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CAClC,IAAI,CAAC,QAAQ;iBACV,QAAQ,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,IAAI,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;iBACtJ,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC;YAC7B,IAAI,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;SACnF;QACD,SAAS,EAAE,IAAI,CAAC,SAAgB;QAChC,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,QAAQ,EAAE,IAAI,CAAC,QAAQ;KACxB,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { type Abi, type AbiEvent, type ContractEventName, type DecodeEventLogReturnType } from "viem";
|
|
2
|
+
import type { Config, EventFilter } from "../config/types.js";
|
|
3
|
+
import type { BitcoinTransaction, EvmBlock, EvmLog, EvmTransaction } from "../sources/types.js";
|
|
4
|
+
type ContractsOf<C extends Config<any, any, any>> = NonNullable<C["contracts"]>;
|
|
5
|
+
type AccountsOf<C extends Config<any, any, any>> = NonNullable<C["accounts"]>;
|
|
6
|
+
export type ContractEventNames<C extends Config<any, any, any>> = {
|
|
7
|
+
[K in keyof ContractsOf<C> & string]: `${K}:${ContractEventName<ContractsOf<C>[K]["abi"]>}`;
|
|
8
|
+
}[keyof ContractsOf<C> & string];
|
|
9
|
+
export type AccountEventNames<C extends Config<any, any, any>> = {
|
|
10
|
+
[K in keyof AccountsOf<C> & string]: `${K}:transaction`;
|
|
11
|
+
}[keyof AccountsOf<C> & string];
|
|
12
|
+
export type EventNames<C extends Config<any, any, any>> = ContractEventNames<C> | AccountEventNames<C> | "setup";
|
|
13
|
+
export interface ContractEvent<abi extends Abi = Abi, name extends string = string> {
|
|
14
|
+
/** Event name as in the ABI. */
|
|
15
|
+
name: name;
|
|
16
|
+
/** Decoded, typed arguments. */
|
|
17
|
+
args: name extends ContractEventName<abi> ? DecodeEventLogReturnType<abi, name>["args"] : Record<string, unknown>;
|
|
18
|
+
/** Emitting contract, lowercase. */
|
|
19
|
+
address: string;
|
|
20
|
+
log: EvmLog;
|
|
21
|
+
block: EvmBlock;
|
|
22
|
+
/** Present when the contract sets `includeTransactions: true`. */
|
|
23
|
+
transaction?: EvmTransaction;
|
|
24
|
+
}
|
|
25
|
+
export interface EvmAccountEvent {
|
|
26
|
+
/** The matched account address (lowercase). */
|
|
27
|
+
address: string;
|
|
28
|
+
direction: "from" | "to" | "self";
|
|
29
|
+
transaction: EvmTransaction;
|
|
30
|
+
block: EvmBlock;
|
|
31
|
+
}
|
|
32
|
+
export interface BitcoinAccountEvent {
|
|
33
|
+
/** The matched account address. */
|
|
34
|
+
address: string;
|
|
35
|
+
tx: BitcoinTransaction;
|
|
36
|
+
block: {
|
|
37
|
+
height: number;
|
|
38
|
+
hash: string;
|
|
39
|
+
time: number;
|
|
40
|
+
};
|
|
41
|
+
/** Sum of outputs paying the address, in satoshis. */
|
|
42
|
+
received: bigint;
|
|
43
|
+
/** Sum of inputs spent from the address, in satoshis. */
|
|
44
|
+
sent: bigint;
|
|
45
|
+
/** received - sent (negative when the address paid out). */
|
|
46
|
+
net: bigint;
|
|
47
|
+
fee: bigint;
|
|
48
|
+
/** True when the address funded at least one input. */
|
|
49
|
+
isSender: boolean;
|
|
50
|
+
}
|
|
51
|
+
export interface SetupEvent {
|
|
52
|
+
/** Block the chain starts (or resumes) indexing from. */
|
|
53
|
+
block: number;
|
|
54
|
+
}
|
|
55
|
+
type ChainKind<C extends Config<any, any, any>, ref> = ref extends string ? C["chains"][ref]["source"]["kind"] : C["chains"][keyof ref & string]["source"]["kind"];
|
|
56
|
+
export type AccountEventOf<C extends Config<any, any, any>, K extends keyof AccountsOf<C>> = ChainKind<C, AccountsOf<C>[K]["chain"]> extends "bitcoin" ? BitcoinAccountEvent : ChainKind<C, AccountsOf<C>[K]["chain"]> extends "evm" ? EvmAccountEvent : EvmAccountEvent | BitcoinAccountEvent;
|
|
57
|
+
export type EventOf<C extends Config<any, any, any>, name extends string> = name extends "setup" ? SetupEvent : name extends `${infer K}:${infer E}` ? K extends keyof ContractsOf<C> ? ContractEvent<ContractsOf<C>[K]["abi"], E> : K extends keyof AccountsOf<C> ? AccountEventOf<C, K> : never : never;
|
|
58
|
+
export type ChainNames<C extends Config<any, any, any>> = keyof C["chains"] & string;
|
|
59
|
+
export interface CompiledFilter {
|
|
60
|
+
event: AbiEvent;
|
|
61
|
+
topic0: string;
|
|
62
|
+
/** topic position (1..3) -> allowed values (padded hex) or an address set name. */
|
|
63
|
+
topics: Array<{
|
|
64
|
+
index: number;
|
|
65
|
+
values?: string[];
|
|
66
|
+
set?: string;
|
|
67
|
+
}>;
|
|
68
|
+
}
|
|
69
|
+
export interface CompiledEvent {
|
|
70
|
+
name: string;
|
|
71
|
+
abi: AbiEvent;
|
|
72
|
+
topic0: string;
|
|
73
|
+
}
|
|
74
|
+
export declare function eventTopic(event: AbiEvent): string;
|
|
75
|
+
export declare function abiEvents(abi: Abi): AbiEvent[];
|
|
76
|
+
export declare function compileFilter(abi: Abi, filter: EventFilter): CompiledFilter;
|
|
77
|
+
export declare function encodeTopicValue(type: string, value: string | number | bigint | boolean): string;
|
|
78
|
+
export declare function padAddress(address: string): string;
|
|
79
|
+
export declare function unpadAddress(topic: string): string;
|
|
80
|
+
export declare function decodeLog(event: AbiEvent, log: EvmLog): {
|
|
81
|
+
args: Record<string, unknown>;
|
|
82
|
+
} | null;
|
|
83
|
+
/** Does a log satisfy a compiled filter? `inSet` resolves address-set membership. */
|
|
84
|
+
export declare function logMatchesFilter(log: EvmLog, filter: CompiledFilter, inSet: (set: string, address: string) => boolean): boolean;
|
|
85
|
+
export declare function bitcoinAccountEvent(tx: BitcoinTransaction, address: string): BitcoinAccountEvent | null;
|
|
86
|
+
export {};
|
|
87
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/indexer/events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { decodeEventLog, encodeAbiParameters, toEventSelector } from "viem";
|
|
2
|
+
import { isAddressSet } from "../config/address.js";
|
|
3
|
+
import { toArray } from "../util.js";
|
|
4
|
+
export function eventTopic(event) {
|
|
5
|
+
return toEventSelector(event).toLowerCase();
|
|
6
|
+
}
|
|
7
|
+
export function abiEvents(abi) {
|
|
8
|
+
return abi.filter((x) => x.type === "event");
|
|
9
|
+
}
|
|
10
|
+
export function compileFilter(abi, filter) {
|
|
11
|
+
const event = abiEvents(abi).find((e) => e.name === filter.event);
|
|
12
|
+
if (!event)
|
|
13
|
+
throw new Error(`filter: unknown event ${filter.event}`);
|
|
14
|
+
const indexed = event.inputs.filter((i) => i.indexed);
|
|
15
|
+
const topics = [];
|
|
16
|
+
for (const [name, value] of Object.entries(filter.args ?? {})) {
|
|
17
|
+
const idx = indexed.findIndex((i) => i.name === name);
|
|
18
|
+
if (idx < 0)
|
|
19
|
+
throw new Error(`filter: ${filter.event}.${name} is not an indexed parameter`);
|
|
20
|
+
const input = indexed[idx];
|
|
21
|
+
if (isAddressSet(value)) {
|
|
22
|
+
if (input.type !== "address")
|
|
23
|
+
throw new Error(`filter: ${filter.event}.${name} must be an address to use addressSet()`);
|
|
24
|
+
topics.push({ index: idx + 1, set: value.set });
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
topics.push({ index: idx + 1, values: toArray(value).map((v) => encodeTopicValue(input.type, v)) });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return { event, topic0: eventTopic(event), topics };
|
|
31
|
+
}
|
|
32
|
+
export function encodeTopicValue(type, value) {
|
|
33
|
+
if (type === "address")
|
|
34
|
+
return `0x${"0".repeat(24)}${String(value).toLowerCase().replace(/^0x/, "")}`;
|
|
35
|
+
if (type.startsWith("bytes") && type !== "bytes")
|
|
36
|
+
return String(value).toLowerCase();
|
|
37
|
+
return encodeAbiParameters([{ type }], [value]).toLowerCase();
|
|
38
|
+
}
|
|
39
|
+
export function padAddress(address) {
|
|
40
|
+
return `0x${"0".repeat(24)}${address.toLowerCase().replace(/^0x/, "")}`;
|
|
41
|
+
}
|
|
42
|
+
export function unpadAddress(topic) {
|
|
43
|
+
return `0x${topic.slice(-40)}`.toLowerCase();
|
|
44
|
+
}
|
|
45
|
+
export function decodeLog(event, log) {
|
|
46
|
+
try {
|
|
47
|
+
const decoded = decodeEventLog({ abi: [event], data: log.data, topics: log.topics, strict: false });
|
|
48
|
+
return { args: (decoded.args ?? {}) };
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** Does a log satisfy a compiled filter? `inSet` resolves address-set membership. */
|
|
55
|
+
export function logMatchesFilter(log, filter, inSet) {
|
|
56
|
+
if ((log.topics[0] ?? "").toLowerCase() !== filter.topic0)
|
|
57
|
+
return false;
|
|
58
|
+
for (const t of filter.topics) {
|
|
59
|
+
const topic = log.topics[t.index]?.toLowerCase();
|
|
60
|
+
if (!topic)
|
|
61
|
+
return false;
|
|
62
|
+
if (t.set !== undefined) {
|
|
63
|
+
if (!inSet(t.set, unpadAddress(topic)))
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
else if (t.values && !t.values.includes(topic))
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
export function bitcoinAccountEvent(tx, address) {
|
|
72
|
+
let received = 0n;
|
|
73
|
+
let sent = 0n;
|
|
74
|
+
let isSender = false;
|
|
75
|
+
for (const o of tx.vout)
|
|
76
|
+
if (o.address === address)
|
|
77
|
+
received += o.value;
|
|
78
|
+
for (const i of tx.vin) {
|
|
79
|
+
if (i.prevout?.address === address) {
|
|
80
|
+
sent += i.prevout.value;
|
|
81
|
+
isSender = true;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (received === 0n && sent === 0n)
|
|
85
|
+
return null;
|
|
86
|
+
return { address, tx, block: { height: tx.blockHeight, hash: tx.blockHash, time: tx.blockTime }, received, sent, net: received - sent, fee: tx.fee, isSender };
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/indexer/events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { AddressRegistry, type AddressRow } from "../addresses/registry.js";
|
|
2
|
+
import type { Config } from "../config/types.js";
|
|
3
|
+
import { type Db } from "../db/client.js";
|
|
4
|
+
import { type MigrateOptions, type SchemaModule } from "../db/migrate.js";
|
|
5
|
+
import { type HttpClient } from "../http/client.js";
|
|
6
|
+
import { type Observability } from "../observability/logger.js";
|
|
7
|
+
import type { MaterializedView } from "../schema/view.js";
|
|
8
|
+
import type { Table } from "../schema/table.js";
|
|
9
|
+
import { isAddressSet, isFactory } from "../config/address.js";
|
|
10
|
+
import type { HandlerContext } from "./context.js";
|
|
11
|
+
import type { ChainNames, EventNames, EventOf } from "./events.js";
|
|
12
|
+
import { JobRunner, type JobRow } from "./jobs.js";
|
|
13
|
+
import { type ChainPlan } from "./plan.js";
|
|
14
|
+
import { ChainRunner } from "./runtime.js";
|
|
15
|
+
export interface IndexerOptions<C extends Config<any, any, any>> {
|
|
16
|
+
config: C;
|
|
17
|
+
/** The schema module (`import * as schema from "./schema"`) or an array of tables/views. */
|
|
18
|
+
schema: SchemaModule | ReadonlyArray<Table<any> | MaterializedView>;
|
|
19
|
+
/** What to do when a handler throws. `stop` (default) halts the chain so data stays consistent. */
|
|
20
|
+
onError?: "stop" | "skip";
|
|
21
|
+
/** Override `fetch` used by `context.http` (tests). */
|
|
22
|
+
fetch?: typeof fetch;
|
|
23
|
+
}
|
|
24
|
+
export interface StatusSnapshot {
|
|
25
|
+
chains: Record<string, {
|
|
26
|
+
cursor: number;
|
|
27
|
+
head: number;
|
|
28
|
+
finalized: number;
|
|
29
|
+
lagBlocks: number;
|
|
30
|
+
caughtUp: boolean;
|
|
31
|
+
running: boolean;
|
|
32
|
+
error?: string;
|
|
33
|
+
pendingJobs: number;
|
|
34
|
+
blocksIndexed: number;
|
|
35
|
+
eventsProcessed: number;
|
|
36
|
+
batches: number;
|
|
37
|
+
errors: number;
|
|
38
|
+
lastBatchMs: number;
|
|
39
|
+
lastBatchAt?: string;
|
|
40
|
+
}>;
|
|
41
|
+
addresses: Array<{
|
|
42
|
+
set: string;
|
|
43
|
+
chain: string;
|
|
44
|
+
status: string;
|
|
45
|
+
count: number;
|
|
46
|
+
}>;
|
|
47
|
+
counters: Record<string, number>;
|
|
48
|
+
}
|
|
49
|
+
export interface ReindexRequest {
|
|
50
|
+
chain: string;
|
|
51
|
+
/** Re-index a block range [fromBlock, toBlock). */
|
|
52
|
+
fromBlock?: number;
|
|
53
|
+
toBlock?: number;
|
|
54
|
+
/** Or re-index one entity: delete rows where the scope column equals `value` and re-run its address history. */
|
|
55
|
+
scope?: string;
|
|
56
|
+
value?: string;
|
|
57
|
+
}
|
|
58
|
+
export interface Indexer<C extends Config<any, any, any>> {
|
|
59
|
+
readonly config: C;
|
|
60
|
+
readonly schema: SchemaModule | ReadonlyArray<Table<any> | MaterializedView>;
|
|
61
|
+
/** Register a handler. Names are `Contract:Event`, `Account:transaction`, or `setup`. */
|
|
62
|
+
on<name extends EventNames<C>>(name: name, handler: (args: {
|
|
63
|
+
event: EventOf<C, name>;
|
|
64
|
+
context: HandlerContext<C, ChainNames<C>>;
|
|
65
|
+
}) => Promise<void> | void): Indexer<C>;
|
|
66
|
+
/** Connect, migrate, and prepare runners without indexing. Idempotent. */
|
|
67
|
+
init(): Promise<void>;
|
|
68
|
+
/** Run migrations only. */
|
|
69
|
+
migrate(options?: MigrateOptions): Promise<void>;
|
|
70
|
+
/** Index continuously (live). Resolves when stopped or when a chain fails. */
|
|
71
|
+
start(options?: {
|
|
72
|
+
server?: boolean;
|
|
73
|
+
}): Promise<void>;
|
|
74
|
+
/** Index until every chain is caught up to its finalized head and all jobs are done, then stop. For tests and one-shot runs. */
|
|
75
|
+
run(): Promise<void>;
|
|
76
|
+
stop(): Promise<void>;
|
|
77
|
+
/** The ClickHouse client (available after `init`). */
|
|
78
|
+
readonly db: Db;
|
|
79
|
+
readonly observability: Observability;
|
|
80
|
+
readonly http: HttpClient;
|
|
81
|
+
addresses: {
|
|
82
|
+
register(input: {
|
|
83
|
+
set: string;
|
|
84
|
+
address: string;
|
|
85
|
+
chain?: string;
|
|
86
|
+
fromBlock?: number;
|
|
87
|
+
meta?: Record<string, unknown>;
|
|
88
|
+
} | Array<{
|
|
89
|
+
set: string;
|
|
90
|
+
address: string;
|
|
91
|
+
chain?: string;
|
|
92
|
+
fromBlock?: number;
|
|
93
|
+
meta?: Record<string, unknown>;
|
|
94
|
+
}>): Promise<AddressRow[]>;
|
|
95
|
+
list(filter?: {
|
|
96
|
+
set?: string;
|
|
97
|
+
chain?: string;
|
|
98
|
+
status?: AddressRow["status"];
|
|
99
|
+
}): AddressRow[];
|
|
100
|
+
has(set: string, chain: string, address: string): boolean;
|
|
101
|
+
};
|
|
102
|
+
reindex(request: ReindexRequest): Promise<JobRow[]>;
|
|
103
|
+
status(): Promise<StatusSnapshot>;
|
|
104
|
+
/** Internal: access to plans/runners (used by the server and tests). */
|
|
105
|
+
readonly internals: {
|
|
106
|
+
plans: Map<string, ChainPlan>;
|
|
107
|
+
runners: Map<string, ChainRunner>;
|
|
108
|
+
jobs: Map<string, JobRunner>;
|
|
109
|
+
registry: AddressRegistry;
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
export declare function createIndexer<C extends Config<any, any, any>>(options: IndexerOptions<C>): Indexer<C>;
|
|
113
|
+
export { isAddressSet, isFactory };
|
|
114
|
+
//# sourceMappingURL=indexer.d.ts.map
|