event-log-harvester
Advanced tools
Comparing version 0.2.0 to 0.2.1
@@ -1,47 +0,55 @@ | ||
async function F(l, c, o) { | ||
const { | ||
eventFilters: e, | ||
getLogs: a, | ||
failOnDecodeError: f = !1 | ||
} = l, t = {}; | ||
async function E(n, c, t) { | ||
const { eventFilters: e, failOnDecodeError: a = !1 } = n, f = {}; | ||
let r = /* @__PURE__ */ new Set(); | ||
const h = /* @__PURE__ */ new Set(); | ||
let s = !1; | ||
for (const n in e) | ||
t[n] = [], e[n].forEach((k) => { | ||
!k.addresses || k.addresses.length === 0 ? s = !0 : k.addresses.forEach((p) => r.add(p)), k.topics.forEach((p) => h.add(p)); | ||
const o = []; | ||
let m = !1; | ||
for (const d in e) | ||
f[d] = [], e[d].forEach((u) => { | ||
!u.address || u.address.length === 0 ? m = !0 : u.address.forEach((i) => r.add(i)), u.topics.forEach((i, s) => { | ||
o[s] ? o[s].includes(i) || o[s].push(i) : o.push([i]); | ||
}); | ||
}); | ||
s && (r = void 0); | ||
const w = (await a({ | ||
fromBlock: c, | ||
toBlock: o, | ||
addresses: r ? Array.from(r) : void 0, | ||
topics: h.size > 0 ? Array.from(h) : void 0 | ||
})).map(async (n) => { | ||
for (const i in e) | ||
await g( | ||
m && (r = void 0); | ||
const w = (await $( | ||
n, | ||
c, | ||
t, | ||
r ? Array.from(r) : void 0, | ||
o | ||
)).map(async (d) => { | ||
for (const p in e) | ||
await A( | ||
e, | ||
i, | ||
n, | ||
t, | ||
f | ||
p, | ||
d, | ||
f, | ||
a | ||
); | ||
}); | ||
return await Promise.all(w), t; | ||
return await Promise.all(w), f; | ||
} | ||
async function g(l, c, o, e, a) { | ||
const t = l[c].find( | ||
(r) => (!r.addresses || r.addresses.length === 0 || r.addresses.includes(o.address)) && r.topics[0] === o.topics[0] && o.blockNumber >= r.fromBlock && o.blockNumber <= r.toBlock | ||
async function $({ getLogs: n }, c, t, e, a) { | ||
return n({ | ||
fromBlock: c, | ||
toBlock: t, | ||
address: e, | ||
topics: a | ||
}); | ||
} | ||
async function A(n, c, t, e, a) { | ||
const r = n[c].find( | ||
(o) => (!o.address || o.address.length === 0 || o.address.includes(t.address)) && // TODO add support for multiple topics | ||
o.topics[0] === t.topics[0] && t.blockNumber >= o.fromBlock && t.blockNumber <= o.toBlock | ||
); | ||
if (t) | ||
if (r) | ||
try { | ||
o.data = o.data === "0x" ? "0x0000000000000000000000000000000000000000000000000000000000000000" : o.data; | ||
const r = await t.decodeLog(o); | ||
e[c] || (e[c] = []), e[c].push(r); | ||
} catch (r) { | ||
t.data = t.data === "0x" ? "0x0000000000000000000000000000000000000000000000000000000000000000" : t.data; | ||
const o = await r.decodeLog(t); | ||
e[c] || (e[c] = []), e[c].push(o); | ||
} catch (o) { | ||
if (console.error( | ||
`Error decoding log for key ${c.toString()}:`, | ||
r, | ||
o, | ||
t | ||
t, | ||
r | ||
), a) | ||
@@ -51,67 +59,69 @@ throw new Error("Decoding error occurred"); | ||
} | ||
async function E(l, c, o) { | ||
const { maxRetries: e = 0 } = l; | ||
async function D(n, c, t) { | ||
const { maxRetries: e = 0 } = n; | ||
let a = 0; | ||
for (; e === -1 || a < e; ) | ||
try { | ||
return await F(l, c, o); | ||
return await E(n, c, t); | ||
} catch (f) { | ||
if (a += 1, console.error(`Attempt ${a} failed: ${f.message}`), e !== -1 && a >= e) | ||
throw new Error(`Failed to fetch logs after ${e} retries`); | ||
await new Promise((t) => setTimeout(t, 1e3 * a)); | ||
await new Promise((r) => setTimeout(r, 1e3 * a)); | ||
} | ||
throw new Error("Failed to fetch logs"); | ||
} | ||
function A(l, c, o) { | ||
function L(n, c, t) { | ||
const e = {}; | ||
for (const a in l) { | ||
const t = l[a].filter( | ||
(r) => r.fromBlock <= o && r.toBlock >= c | ||
for (const a in n) { | ||
const r = n[a].filter( | ||
(o) => o.fromBlock <= t && o.toBlock >= c | ||
); | ||
t.length > 0 && (e[a] = t); | ||
r.length > 0 && (e[a] = r); | ||
} | ||
return e; | ||
} | ||
async function $(l) { | ||
async function M(n) { | ||
const { | ||
batchSize: c = 1e3, | ||
eventFilters: o, | ||
eventFilters: t, | ||
failOnCallbackError: e = !1, | ||
onBatchComplete: a, | ||
progressInfo: f | ||
} = l, t = {}, r = Math.min( | ||
...Object.values(o).flat().map((s) => s.fromBlock) | ||
), h = Math.max( | ||
...Object.values(o).flat().map((s) => s.toBlock) | ||
} = n, r = {}, o = Math.min( | ||
...Object.values(t).flat().map((l) => l.fromBlock) | ||
), m = Math.max( | ||
...Object.values(t).flat().map((l) => l.toBlock) | ||
); | ||
for (let s = r; s <= h; s += c) { | ||
const m = Math.min(s + c - 1, h), w = A( | ||
o, | ||
s, | ||
m | ||
for (let l = o; l <= m; l += c) { | ||
const w = Date.now(), d = Math.min(l + c - 1, m), p = L( | ||
t, | ||
l, | ||
d | ||
); | ||
if (Object.keys(w).length > 0) { | ||
const n = await E( | ||
let u = 0; | ||
if (Object.keys(p).length > 0) { | ||
const i = await D( | ||
n, | ||
l, | ||
s, | ||
m | ||
d | ||
); | ||
for (const i in n) { | ||
t[i] || (t[i] = []); | ||
const k = n[i]; | ||
t[i].push(...k); | ||
const p = w[i].map((d) => { | ||
if (d.onBatchComplete) { | ||
const b = k.filter((u) => { | ||
const B = !d.addresses || d.addresses.includes(u.address), v = d.topics[0] === u.topics[0], y = u.blockNumber >= d.fromBlock && u.blockNumber <= d.toBlock; | ||
return B && v && y; | ||
for (const s in t) { | ||
r[s] || (r[s] = []), i[s] || (i[s] = []); | ||
const b = i[s]; | ||
r[s].push(...b); | ||
const v = t[s].map((h) => { | ||
if (h.onBatchComplete) { | ||
const B = b.filter((k) => { | ||
const y = !h.address || h.address.includes(k.address), F = h.topics[0] === k.topics[0], g = k.blockNumber >= h.fromBlock && k.blockNumber <= h.toBlock; | ||
return y && F && g; | ||
}); | ||
u += B.length; | ||
try { | ||
return d.onBatchComplete(b, { | ||
startBlock: s, | ||
endBlock: m | ||
return h.onBatchComplete(B, { | ||
startBlock: l, | ||
endBlock: d | ||
}); | ||
} catch (u) { | ||
if (console.error(`Error in callback for filter ${i}:`, u), e) | ||
throw u; | ||
} catch (k) { | ||
if (console.error(`Error in callback for filter ${s}:`, k), e) | ||
throw k; | ||
} | ||
@@ -121,6 +131,6 @@ } | ||
try { | ||
await Promise.all(p); | ||
} catch (d) { | ||
if (console.error(`Error in callback for filter ${i}:`, d), e) | ||
throw d; | ||
await Promise.all(v); | ||
} catch (h) { | ||
if (console.error(`Error in callback for filter ${s}:`, h), e) | ||
throw h; | ||
} | ||
@@ -130,9 +140,9 @@ } | ||
try { | ||
await a(n, { startBlock: s, endBlock: m }); | ||
} catch (i) { | ||
await a(i, { startBlock: l, endBlock: d }); | ||
} catch (s) { | ||
if (console.error( | ||
`Error in callback onBatchComplete from ${s} to ${m} }:`, | ||
i | ||
`Error in callback onBatchComplete from ${l} to ${d} }:`, | ||
s | ||
), e) | ||
throw i; | ||
throw s; | ||
} | ||
@@ -142,20 +152,22 @@ } | ||
try { | ||
const n = { | ||
fromBlock: r, | ||
toBlock: h, | ||
const i = Date.now(), s = { | ||
fromBlock: o, | ||
toBlock: m, | ||
batchSize: c, | ||
batchStartBlock: s, | ||
batchEndBlock: m, | ||
progressPercent: m / h * 100 | ||
batchStartBlock: l, | ||
batchEndBlock: d, | ||
progressPercent: d / m * 100, | ||
elapsedTimeMs: i - w, | ||
logCount: u | ||
}; | ||
f(n); | ||
} catch (n) { | ||
if (console.error("Error in callback progressInfo", n), e) | ||
throw n; | ||
f(s); | ||
} catch (i) { | ||
if (console.error("Error in callback progressInfo", i), e) | ||
throw i; | ||
} | ||
} | ||
return t; | ||
return r; | ||
} | ||
export { | ||
$ as harvestLogs | ||
M as harvestLogs | ||
}; |
@@ -17,4 +17,4 @@ export type BaseLog = { | ||
toBlock: number; | ||
addresses?: Array<string>; | ||
topics?: Array<string | null>; | ||
address?: Array<string>; | ||
topics: Array<(string | null) | Array<string | null>>; | ||
}) => Promise<Array<TLog>>; | ||
@@ -32,7 +32,9 @@ onBatchComplete?: (results: LogDecodedRecord<T>, metadata: { | ||
progressPercent: number; | ||
elapsedTimeMs: number; | ||
logCount: number; | ||
}) => Promise<void> | void; | ||
} | ||
export interface EventFilter<TValue extends Record<string, unknown>> { | ||
addresses?: string[]; | ||
topics: (string | null)[]; | ||
address?: string[]; | ||
topics: Array<string | null>; | ||
fromBlock: number; | ||
@@ -39,0 +41,0 @@ toBlock: number; |
{ | ||
"name": "event-log-harvester", | ||
"version": "0.2.0", | ||
"version": "0.2.1", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
@@ -9,3 +9,3 @@ # Ethereum Event Logs Harvester | ||
### 1. Event Log Harvester with Ethers.js: | ||
### 1. Event Log Harvester: | ||
@@ -17,3 +17,3 @@ - The tool is designed to fetch and decode Ethereum event logs based on user-defined filters. | ||
- **addresses**: An array of contract addresses to listen to. | ||
- **address**: An array of contract addresses to listen to. | ||
- **topics**: The topics to filter events by (e.g., event signatures). | ||
@@ -54,2 +54,6 @@ - **abi**: The ABI (Application Binary Interface) required to decode the events. | ||
```bash | ||
npm install event-log-harvester | ||
npm install event-log-harvester | ||
## Example | ||
```typescript |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
15769
266
56
0