@subsquid/evm-stream 0.0.1-2-0.3887d2

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/lib/source.js ADDED
@@ -0,0 +1,193 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getBlockValidator = exports.EvmPortalDataSource = void 0;
4
+ exports.mapBlock = mapBlock;
5
+ const util_internal_range_1 = require("@subsquid/util-internal-range");
6
+ const portal_client_1 = require("@subsquid/portal-client");
7
+ const util_internal_1 = require("@subsquid/util-internal");
8
+ const util_internal_validation_1 = require("@subsquid/util-internal-validation");
9
+ const schema_1 = require("./schema");
10
+ const query_1 = require("./query");
11
+ const data_source_1 = require("@subsquid/data-source");
12
+ class EvmPortalDataSource {
13
+ constructor(options) {
14
+ this.portal = typeof options.portal === 'string' ? new portal_client_1.PortalClient({ url: options.portal }) : options.portal;
15
+ this.fields = options.query.fields;
16
+ this.requests = (0, util_internal_range_1.mergeRangeRequests)(options.query.requests, query_1.mergeDataRequests);
17
+ }
18
+ getHeight() {
19
+ return this.portal.getFinalizedHeight();
20
+ }
21
+ getFinalizedHeight() {
22
+ return this.portal.getFinalizedHeight();
23
+ }
24
+ getBlockStream(range, stopOnHead) {
25
+ let fields = getFields(this.fields);
26
+ let requests = (0, util_internal_range_1.applyRangeBound)(this.requests, range);
27
+ let { writable, readable } = new TransformStream({
28
+ transform: async (data, controller) => {
29
+ let blocks = data.map((b) => {
30
+ let block = mapBlock(b, fields);
31
+ Object.defineProperty(block, data_source_1.DataSource.blockRef, {
32
+ value: { hash: block.header.hash, number: block.header.number },
33
+ });
34
+ return block;
35
+ });
36
+ Object.defineProperty(blocks, data_source_1.DataSource.finalizedHead, {
37
+ value: data[portal_client_1.PortalClient.finalizedHead],
38
+ });
39
+ controller.enqueue(blocks);
40
+ },
41
+ });
42
+ const ingest = async () => {
43
+ for (let request of requests) {
44
+ let query = {
45
+ type: 'evm',
46
+ fromBlock: request.range.from,
47
+ toBlock: request.range.to,
48
+ fields,
49
+ ...request.request,
50
+ };
51
+ await this.portal.getFinalizedStream(query, { stopOnHead }).pipeTo(writable, {
52
+ preventClose: true,
53
+ });
54
+ }
55
+ };
56
+ ingest()
57
+ .then(() => writable.close(), (reason) => writable.abort(reason))
58
+ .catch(() => { });
59
+ return readable;
60
+ }
61
+ }
62
+ exports.EvmPortalDataSource = EvmPortalDataSource;
63
+ exports.getBlockValidator = (0, util_internal_1.weakMemo)((fields) => {
64
+ let BlockHeader = (0, util_internal_validation_1.object)((0, schema_1.getBlockHeaderProps)(fields.block, true));
65
+ let Transaction = (0, util_internal_validation_1.object)({
66
+ hash: fields.transaction?.hash ? util_internal_validation_1.BYTES : undefined,
67
+ ...(0, schema_1.getTxProps)(fields.transaction, true),
68
+ sighash: fields.transaction?.sighash ? (0, util_internal_validation_1.withDefault)('0x', util_internal_validation_1.BYTES) : undefined,
69
+ ...(0, schema_1.getTxReceiptProps)(fields.transaction, true),
70
+ });
71
+ let Log = (0, util_internal_validation_1.object)((0, schema_1.getLogProps)(fields.log, true));
72
+ let Trace = (0, schema_1.getTraceFrameValidator)(fields.trace, true);
73
+ let stateDiffBase = {
74
+ transactionIndex: util_internal_validation_1.NAT,
75
+ address: util_internal_validation_1.BYTES,
76
+ key: util_internal_validation_1.STRING,
77
+ };
78
+ let StateDiff = (0, util_internal_validation_1.taggedUnion)('kind', {
79
+ ['=']: (0, util_internal_validation_1.object)({ ...stateDiffBase }),
80
+ ['+']: (0, util_internal_validation_1.object)({ ...stateDiffBase, ...(0, schema_1.project)(fields.stateDiff, { next: util_internal_validation_1.BYTES }) }),
81
+ ['*']: (0, util_internal_validation_1.object)({ ...stateDiffBase, ...(0, schema_1.project)(fields.stateDiff, { prev: util_internal_validation_1.BYTES, next: util_internal_validation_1.BYTES }) }),
82
+ ['-']: (0, util_internal_validation_1.object)({ ...stateDiffBase, ...(0, schema_1.project)(fields.stateDiff, { prev: util_internal_validation_1.BYTES }) }),
83
+ });
84
+ return (0, util_internal_validation_1.object)({
85
+ header: BlockHeader,
86
+ transactions: (0, util_internal_validation_1.withDefault)([], (0, util_internal_validation_1.array)(Transaction)),
87
+ logs: (0, util_internal_validation_1.withDefault)([], (0, util_internal_validation_1.array)(Log)),
88
+ traces: (0, util_internal_validation_1.withDefault)([], (0, util_internal_validation_1.array)(Trace)),
89
+ stateDiffs: (0, util_internal_validation_1.withDefault)([], (0, util_internal_validation_1.array)(StateDiff)),
90
+ });
91
+ });
92
+ function mapBlock(rawBlock, fields) {
93
+ let validator = (0, exports.getBlockValidator)(fields);
94
+ let block = (0, util_internal_validation_1.cast)(validator, rawBlock);
95
+ // let {number, hash, parentHash, ...hdr} = src.header
96
+ // if (hdr.timestamp) {
97
+ // hdr.timestamp = hdr.timestamp * 1000 // convert to ms
98
+ // }
99
+ // let header = new BlockHeader(number, hash, parentHash)
100
+ // Object.assign(header, hdr)
101
+ // let block = new Block(header)
102
+ // if (src.transactions) {
103
+ // for (let {transactionIndex, ...props} of src.transactions) {
104
+ // let tx = new Transaction(header, transactionIndex)
105
+ // Object.assign(tx, props)
106
+ // block.transactions.push(tx)
107
+ // }
108
+ // }
109
+ // if (src.logs) {
110
+ // for (let {logIndex, transactionIndex, ...props} of src.logs) {
111
+ // let log = new Log(header, logIndex, transactionIndex)
112
+ // Object.assign(log, props)
113
+ // block.logs.push(log)
114
+ // }
115
+ // }
116
+ // if (src.traces) {
117
+ // for (let {transactionIndex, traceAddress, type, ...props} of src.traces) {
118
+ // transactionIndex = assertNotNull(transactionIndex)
119
+ // let trace: Trace
120
+ // switch (type) {
121
+ // case 'create':
122
+ // trace = new TraceCreate(header, transactionIndex, traceAddress)
123
+ // break
124
+ // case 'call':
125
+ // trace = new TraceCall(header, transactionIndex, traceAddress)
126
+ // break
127
+ // case 'suicide':
128
+ // trace = new TraceSuicide(header, transactionIndex, traceAddress)
129
+ // break
130
+ // case 'reward':
131
+ // trace = new TraceReward(header, transactionIndex, traceAddress)
132
+ // break
133
+ // default:
134
+ // throw unexpectedCase()
135
+ // }
136
+ // Object.assign(trace, props)
137
+ // block.traces.push(trace)
138
+ // }
139
+ // }
140
+ // if (src.stateDiffs) {
141
+ // for (let {transactionIndex, address, key, kind, ...props} of src.stateDiffs) {
142
+ // let diff: StateDiff
143
+ // switch (kind) {
144
+ // case '=':
145
+ // diff = new StateDiffNoChange(header, transactionIndex, address, key)
146
+ // break
147
+ // case '+':
148
+ // diff = new StateDiffAdd(header, transactionIndex, address, key)
149
+ // break
150
+ // case '*':
151
+ // diff = new StateDiffChange(header, transactionIndex, address, key)
152
+ // break
153
+ // case '-':
154
+ // diff = new StateDiffDelete(header, transactionIndex, address, key)
155
+ // break
156
+ // default:
157
+ // throw unexpectedCase()
158
+ // }
159
+ // Object.assign(diff, props)
160
+ // block.stateDiffs.push(diff)
161
+ // }
162
+ // }
163
+ // setUpRelations(block)
164
+ return block;
165
+ }
166
+ function getFields(fields) {
167
+ return (0, query_1.mergeSelection)(REQUIRED_FIELDS, fields);
168
+ }
169
+ const REQUIRED_FIELDS = {
170
+ block: {
171
+ number: true,
172
+ hash: true,
173
+ parentHash: true,
174
+ },
175
+ // transaction: {
176
+ // transactionIndex: true,
177
+ // },
178
+ // log: {
179
+ // logIndex: true,
180
+ // transactionIndex: true,
181
+ // },
182
+ // trace: {
183
+ // transactionIndex: true,
184
+ // traceAddress: true,
185
+ // type: true,
186
+ // },
187
+ // stateDiff: {
188
+ // transactionIndex: true,
189
+ // address: true,
190
+ // key: true,
191
+ // },
192
+ };
193
+ //# sourceMappingURL=source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.js","sourceRoot":"","sources":["../src/source.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@subsquid/evm-stream",
3
+ "version": "0.0.1-2-0.3887d2",
4
+ "description": "EVM block data streamer",
5
+ "license": "GPL-3.0-or-later",
6
+ "repository": "git@github.com:subsquid/squid.git",
7
+ "publishConfig": {
8
+ "access": "public"
9
+ },
10
+ "files": [
11
+ "lib",
12
+ "src"
13
+ ],
14
+ "main": "lib/index.js",
15
+ "dependencies": {
16
+ "@subsquid/logger": "^1.3.3",
17
+ "@subsquid/portal-client": "0.1.0-2-0.3887d2",
18
+ "@subsquid/util-internal": "3.3.0-2-0.3887d2",
19
+ "@subsquid/util-internal-range": "~0.3.0",
20
+ "@subsquid/http-client": "1.7.0-2-0.3887d2",
21
+ "@subsquid/util-internal-validation": "~0.7.0",
22
+ "@subsquid/data-source": "0.0.1-2-0.3887d2"
23
+ },
24
+ "devDependencies": {
25
+ "@types/node": "^18.18.14",
26
+ "typescript": "~5.5.4"
27
+ },
28
+ "scripts": {
29
+ "build": "rm -rf lib && tsc"
30
+ }
31
+ }
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './source'
2
+ export * from './query'
package/src/query.ts ADDED
@@ -0,0 +1,195 @@
1
+ import {applyRangeBound, mergeRangeRequests, Range, RangeRequest} from '@subsquid/util-internal-range'
2
+ import type {Evm} from '@subsquid/portal-client'
3
+ import type {MergeSelection, MergeSelectionAll, Selection} from '@subsquid/util-internal'
4
+
5
+ export * from '@subsquid/portal-client/lib/query/evm'
6
+
7
+ export type RequestOptions<R> = {range?: Range; request: R}
8
+ export type LogRequestOptions = RequestOptions<Evm.LogRequest>
9
+ export type TransactionRequestOptions = RequestOptions<Evm.TransactionRequest>
10
+ export type TraceRequestOptions = RequestOptions<Evm.TraceRequest>
11
+ export type StateDiffRequestOptions = RequestOptions<Evm.StateDiffRequest>
12
+
13
+ export type EvmQueryOptions<F extends Evm.FieldSelection = Evm.FieldSelection> = {
14
+ fields: F
15
+ requests: RangeRequest<Evm.DataRequest>[]
16
+ }
17
+
18
+ export class EvmQueryBuilder<F extends Evm.FieldSelection = {block: {number: true; hash: true}}> {
19
+ private range: Range = {from: 0}
20
+ private requests: RangeRequest<Evm.DataRequest>[] = []
21
+ private fields: F = {
22
+ block: {number: true, hash: true},
23
+ } as F
24
+
25
+ addLog(options: LogRequestOptions): this {
26
+ this.requests.push({
27
+ range: options.range ?? {from: 0},
28
+ request: {
29
+ logs: [mapRequest(options)],
30
+ },
31
+ })
32
+ return this
33
+ }
34
+
35
+ addTransaction(options: TransactionRequestOptions): this {
36
+ this.requests.push({
37
+ range: options.range ?? {from: 0},
38
+ request: {
39
+ transactions: [mapRequest(options)],
40
+ },
41
+ })
42
+ return this
43
+ }
44
+
45
+ addTrace(options: TraceRequestOptions): this {
46
+ this.requests.push({
47
+ range: options.range ?? {from: 0},
48
+ request: {
49
+ traces: [mapRequest(options)],
50
+ },
51
+ })
52
+ return this
53
+ }
54
+
55
+ addStateDiff(options: StateDiffRequestOptions): this {
56
+ this.requests.push({
57
+ range: options.range ?? {from: 0},
58
+ request: {
59
+ stateDiffs: [mapRequest(options)],
60
+ },
61
+ })
62
+ return this
63
+ }
64
+
65
+ setRange(range: Range): this {
66
+ this.range = range
67
+ return this
68
+ }
69
+
70
+ setFields<F extends Evm.FieldSelection>(fields: F): EvmQueryBuilder<F> {
71
+ this.fields = fields as any
72
+ return this as any
73
+ }
74
+
75
+ build(): EvmQueryOptions<F> {
76
+ let requests = mergeRangeRequests(this.requests, mergeDataRequests)
77
+
78
+ return {
79
+ fields: this.fields,
80
+ requests: applyRangeBound(requests, this.range),
81
+ }
82
+ }
83
+ }
84
+
85
+ export function mergeDataRequests(...requests: Evm.DataRequest[]): Evm.DataRequest {
86
+ let res: Evm.DataRequest = {}
87
+
88
+ for (let req of requests) {
89
+ res.transactions = concatRequestLists(res.transactions, req.transactions)
90
+ res.logs = concatRequestLists(res.logs, req.logs)
91
+ res.traces = concatRequestLists(res.traces, req.traces)
92
+ res.stateDiffs = concatRequestLists(res.stateDiffs, req.stateDiffs)
93
+ if (res.includeAllBlocks || req.includeAllBlocks) {
94
+ res.includeAllBlocks = true
95
+ }
96
+ }
97
+
98
+ return res
99
+ }
100
+
101
+ export type MergeFieldSelection<T extends Evm.FieldSelection, U extends Evm.FieldSelection> = MergeSelection<T, U>
102
+
103
+ // NOTE: without condition creates ugly type for some reason
104
+ export type MergeQueryOptions<T extends EvmQueryOptions, U extends EvmQueryOptions> = EvmQueryOptions<
105
+ MergeSelection<T['fields'], U['fields']>
106
+ > extends infer R
107
+ ? R
108
+ : never
109
+
110
+ export type MergeQueryOptionsAll<T extends readonly EvmQueryOptions[]> = T extends readonly [infer F, ...infer R]
111
+ ? F extends EvmQueryOptions
112
+ ? R extends [EvmQueryOptions, ...EvmQueryOptions[]]
113
+ ? MergeQueryOptions<F, MergeQueryOptionsAll<R>>
114
+ : F
115
+ : never
116
+ : never
117
+
118
+ type Test = MergeQueryOptionsAll<
119
+ [
120
+ EvmQueryOptions<{
121
+ block: {number: true; hash: true}
122
+ transaction: {from: true; to: true; hash: true}
123
+ }>,
124
+ EvmQueryOptions<{block: {number: true; hash: true; difficulty: true}}>,
125
+ EvmQueryOptions<{block: {number: true; hash: true; nonce: true}}>
126
+ ]
127
+ >
128
+
129
+ export function mergeRequests(...requests: RangeRequest<Evm.DataRequest>[]): RangeRequest<Evm.DataRequest>[] {
130
+ return mergeRangeRequests(requests, mergeDataRequests)
131
+ }
132
+ export function mergeQueries<T extends EvmQueryOptions, U extends EvmQueryOptions>(a: T, b: U): MergeQueryOptions<T, U>
133
+ export function mergeQueries<T extends readonly EvmQueryOptions[]>(...queries: T): MergeQueryOptionsAll<T>
134
+ export function mergeQueries<T extends readonly EvmQueryOptions[]>(...queries: T) {
135
+ return {
136
+ fields: mergeSelection(...queries.map((q) => q.fields)),
137
+ requests: mergeRequests(...queries.flatMap((q) => q.requests)),
138
+ }
139
+ }
140
+
141
+ let test = mergeQueries(
142
+ {} as EvmQueryOptions<{
143
+ block: {number: true; hash: true}
144
+ transaction: {from: true; to: true; hash: true}
145
+ }>,
146
+ {} as EvmQueryOptions<{
147
+ transaction: {from: true}
148
+ block: {number: true; hash: true; difficulty: true}
149
+ }>,
150
+ {} as EvmQueryOptions<{block: {number: true; hash: true; nonce: true}}>
151
+ )
152
+
153
+ function concatRequestLists<T extends object>(a?: T[], b?: T[]): T[] | undefined {
154
+ let result: T[] = []
155
+ if (a) {
156
+ result.push(...a)
157
+ }
158
+ if (b) {
159
+ result.push(...b)
160
+ }
161
+ return result.length == 0 ? undefined : result
162
+ }
163
+
164
+ function mapRequest<T>(options: RequestOptions<T>): T {
165
+ let req = {...options.request}
166
+ for (let key in req) {
167
+ let val = (req as any)[key]
168
+ if (Array.isArray(val)) {
169
+ ;(req as any)[key] = val.map((s) => {
170
+ return typeof s == 'string' ? s.toLowerCase() : s
171
+ })
172
+ }
173
+ }
174
+ return req
175
+ }
176
+
177
+ export function mergeSelection<T extends Selection, U extends Selection>(a: T, b: U): MergeSelection<T, U>
178
+ export function mergeSelection<T extends readonly Selection[]>(...selections: T): MergeSelectionAll<T>
179
+ export function mergeSelection<T extends readonly Selection[]>(...selections: T) {
180
+ let res: Selection = {}
181
+
182
+ for (let selection of selections) {
183
+ for (let key in selection) {
184
+ if (res[key] == null) {
185
+ res[key] = selection[key]
186
+ } else if (res[key] === true || selection[key] === true) {
187
+ res[key] === true
188
+ } else if (typeof res[key] === 'object' && typeof selection[key] === 'object') {
189
+ res[key] = mergeSelection(res[key], selection[key])
190
+ }
191
+ }
192
+ }
193
+
194
+ return res
195
+ }