@sentio/runtime 2.40.0-rc.3 → 2.40.0-rc.30
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/{chunk-Y3KJTCAS.js → chunk-XWTAA3QK.js} +15791 -14004
- package/lib/index.d.ts +22 -9
- package/lib/index.js +7 -1
- package/lib/processor-runner.d.ts +3 -0
- package/lib/processor-runner.js +14974 -27315
- package/package.json +1 -1
- package/src/db-context.ts +19 -40
- package/src/gen/processor/protos/processor.ts +121 -76
- package/src/index.ts +1 -0
- package/src/metrics.ts +138 -0
- package/src/multicall.ts +1615 -0
- package/src/plugin.ts +7 -3
- package/src/processor-runner.ts +62 -21
- package/src/provider.ts +3 -9
- package/src/service.ts +95 -40
- package/src/utils.ts +11 -3
package/src/plugin.ts
CHANGED
@@ -28,7 +28,7 @@ export abstract class Plugin {
|
|
28
28
|
return ProcessResult.create()
|
29
29
|
}
|
30
30
|
|
31
|
-
async preprocessBinding(request: DataBinding): Promise<PreprocessResult> {
|
31
|
+
async preprocessBinding(request: DataBinding, preprocessStore: { [k: string]: any }): Promise<PreprocessResult> {
|
32
32
|
return PreprocessResult.create()
|
33
33
|
}
|
34
34
|
}
|
@@ -84,13 +84,17 @@ export class PluginManager {
|
|
84
84
|
})
|
85
85
|
}
|
86
86
|
|
87
|
-
preprocessBinding(
|
87
|
+
preprocessBinding(
|
88
|
+
request: DataBinding,
|
89
|
+
preprocessStore: { [k: string]: any },
|
90
|
+
dbContext?: StoreContext
|
91
|
+
): Promise<PreprocessResult> {
|
88
92
|
const plugin = this.typesToPlugin.get(request.handlerType)
|
89
93
|
if (!plugin) {
|
90
94
|
throw new Error(`No plugin for ${request.handlerType}`)
|
91
95
|
}
|
92
96
|
return this.dbContextLocalStorage.run(dbContext, () => {
|
93
|
-
return plugin.preprocessBinding(request)
|
97
|
+
return plugin.preprocessBinding(request, preprocessStore)
|
94
98
|
})
|
95
99
|
}
|
96
100
|
}
|
package/src/processor-runner.ts
CHANGED
@@ -7,9 +7,9 @@ import { compressionAlgorithms } from '@grpc/grpc-js'
|
|
7
7
|
import commandLineArgs from 'command-line-args'
|
8
8
|
import { createServer } from 'nice-grpc'
|
9
9
|
import { errorDetailsServerMiddleware } from 'nice-grpc-error-details'
|
10
|
-
import { registry as niceGrpcRegistry
|
10
|
+
// import { registry as niceGrpcRegistry } from 'nice-grpc-prometheus'
|
11
11
|
import { openTelemetryServerMiddleware } from 'nice-grpc-opentelemetry'
|
12
|
-
import { register as globalRegistry, Registry } from 'prom-client'
|
12
|
+
// import { register as globalRegistry, Registry } from 'prom-client'
|
13
13
|
import http from 'http'
|
14
14
|
// @ts-ignore inspector promises is not included in @type/node
|
15
15
|
import { Session } from 'node:inspector/promises'
|
@@ -21,22 +21,17 @@ import { FullProcessorServiceImpl } from './full-service.js'
|
|
21
21
|
import { ChainConfig } from './chain-config.js'
|
22
22
|
import { setupLogger } from './logger.js'
|
23
23
|
|
24
|
-
import { NodeSDK } from '@opentelemetry/sdk-node'
|
24
|
+
// import { NodeSDK } from '@opentelemetry/sdk-node'
|
25
|
+
import { envDetector } from '@opentelemetry/resources'
|
25
26
|
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-grpc'
|
26
27
|
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc'
|
27
|
-
import { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics'
|
28
|
+
import { PeriodicExportingMetricReader, MeterProvider } from '@opentelemetry/sdk-metrics'
|
29
|
+
import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base'
|
30
|
+
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'
|
31
|
+
import { diag, DiagConsoleLogger, DiagLogLevel, metrics, trace } from '@opentelemetry/api'
|
32
|
+
import { PrometheusExporter } from '@opentelemetry/exporter-prometheus'
|
28
33
|
|
29
|
-
const
|
30
|
-
traceExporter: new OTLPTraceExporter(),
|
31
|
-
metricReader: new PeriodicExportingMetricReader({
|
32
|
-
exporter: new OTLPMetricExporter()
|
33
|
-
})
|
34
|
-
// instrumentations: [getNodeAutoInstrumentations()],
|
35
|
-
})
|
36
|
-
|
37
|
-
sdk.start()
|
38
|
-
|
39
|
-
const mergedRegistry = Registry.merge([globalRegistry, niceGrpcRegistry])
|
34
|
+
// const mergedRegistry = Registry.merge([globalRegistry, niceGrpcRegistry])
|
40
35
|
|
41
36
|
const optionDefinitions = [
|
42
37
|
{ name: 'target', type: String, defaultOption: true },
|
@@ -58,9 +53,55 @@ const optionDefinitions = [
|
|
58
53
|
|
59
54
|
const options = commandLineArgs(optionDefinitions, { partial: true })
|
60
55
|
|
61
|
-
|
56
|
+
const logLevel = process.env['LOG_LEVEL']?.toUpperCase()
|
57
|
+
|
58
|
+
setupLogger(options['log-format'] === 'json', logLevel === 'debug' ? true : options.debug)
|
62
59
|
console.debug('Starting with', options.target)
|
63
60
|
|
61
|
+
if (options.debug) {
|
62
|
+
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG)
|
63
|
+
}
|
64
|
+
|
65
|
+
const resource = await envDetector.detect()
|
66
|
+
|
67
|
+
const meterProvider = new MeterProvider({
|
68
|
+
resource,
|
69
|
+
readers: [
|
70
|
+
new PeriodicExportingMetricReader({
|
71
|
+
exporter: new OTLPMetricExporter()
|
72
|
+
}),
|
73
|
+
new PrometheusExporter({
|
74
|
+
// http://localhost:4041/metrics
|
75
|
+
port: 4041
|
76
|
+
})
|
77
|
+
]
|
78
|
+
})
|
79
|
+
|
80
|
+
const traceProvider = new NodeTracerProvider({
|
81
|
+
resource: resource
|
82
|
+
})
|
83
|
+
const exporter = new OTLPTraceExporter() // new ConsoleSpanExporter();
|
84
|
+
const processor = new BatchSpanProcessor(exporter)
|
85
|
+
traceProvider.addSpanProcessor(processor)
|
86
|
+
traceProvider.register()
|
87
|
+
|
88
|
+
metrics.setGlobalMeterProvider(meterProvider)
|
89
|
+
trace.setGlobalTracerProvider(traceProvider)
|
90
|
+
;['SIGINT', 'SIGTERM'].forEach((signal) => {
|
91
|
+
process.on(signal as any, () => shutdownProvider())
|
92
|
+
})
|
93
|
+
|
94
|
+
export async function shutdownProvider() {
|
95
|
+
const traceProvider = trace.getTracerProvider()
|
96
|
+
if (traceProvider instanceof NodeTracerProvider) {
|
97
|
+
traceProvider.shutdown().catch(console.error)
|
98
|
+
}
|
99
|
+
const meterProvider = metrics.getMeterProvider()
|
100
|
+
if (meterProvider instanceof MeterProvider) {
|
101
|
+
meterProvider.shutdown().catch(console.error)
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
64
105
|
Error.stackTraceLimit = 20
|
65
106
|
|
66
107
|
const fullPath = path.resolve(options['chains-config'])
|
@@ -99,7 +140,7 @@ const server = createServer({
|
|
99
140
|
'grpc.max_receive_message_length': 384 * 1024 * 1024,
|
100
141
|
'grpc.default_compression_algorithm': compressionAlgorithms.gzip
|
101
142
|
})
|
102
|
-
.use(prometheusServerMiddleware())
|
143
|
+
// .use(prometheusServerMiddleware())
|
103
144
|
.use(openTelemetryServerMiddleware())
|
104
145
|
.use(errorDetailsServerMiddleware)
|
105
146
|
const baseService = new ProcessorServiceImpl(async () => {
|
@@ -122,10 +163,10 @@ const httpServer = http
|
|
122
163
|
const reqUrl = new URL(req.url, `http://${req.headers.host}`)
|
123
164
|
const queries = reqUrl.searchParams
|
124
165
|
switch (reqUrl.pathname) {
|
125
|
-
case '/metrics':
|
126
|
-
|
127
|
-
|
128
|
-
|
166
|
+
// case '/metrics':
|
167
|
+
// const metrics = await mergedRegistry.metrics()
|
168
|
+
// res.write(metrics)
|
169
|
+
// break
|
129
170
|
case '/profile': {
|
130
171
|
try {
|
131
172
|
const profileTime = parseInt(queries.get('t') || '1000', 10) || 1000
|
package/src/provider.ts
CHANGED
@@ -4,17 +4,11 @@ import PQueue from 'p-queue'
|
|
4
4
|
import { Endpoints } from './endpoints.js'
|
5
5
|
import { EthChainId } from '@sentio/chain'
|
6
6
|
import { LRUCache } from 'lru-cache'
|
7
|
-
import {
|
7
|
+
import { providerMetrics } from './metrics.js'
|
8
|
+
const { miss_count, hit_count, total_duration, total_queued, queue_size } = providerMetrics
|
8
9
|
|
9
10
|
export const DummyProvider = new JsonRpcProvider('', Network.from(1))
|
10
11
|
|
11
|
-
const meter = metrics.getMeter('processor_provider')
|
12
|
-
const hit_count = meter.createCounter('provider_hit_count')
|
13
|
-
const miss_count = meter.createCounter('provider_miss_count')
|
14
|
-
const queue_size = meter.createGauge('provider_queue_size')
|
15
|
-
const total_duration = meter.createCounter('provider_total_duration')
|
16
|
-
const total_queued = meter.createCounter('provider_total_queued')
|
17
|
-
|
18
12
|
const providers = new Map<string, JsonRpcProvider>()
|
19
13
|
|
20
14
|
// export function getEthChainId(networkish?: EthContext | EthChainId): EthChainId {
|
@@ -38,7 +32,7 @@ export function getProvider(chainId?: EthChainId): Provider {
|
|
38
32
|
const address = Endpoints.INSTANCE.chainServer.get(chainId)
|
39
33
|
const key = network.chainId.toString() + '-' + address
|
40
34
|
|
41
|
-
console.
|
35
|
+
console.debug(`init provider for ${chainId}, address: ${address}`)
|
42
36
|
let provider = providers.get(key)
|
43
37
|
|
44
38
|
if (provider) {
|
package/src/service.ts
CHANGED
@@ -25,20 +25,18 @@ import {
|
|
25
25
|
} from '@sentio/protos'
|
26
26
|
|
27
27
|
import { PluginManager } from './plugin.js'
|
28
|
-
import { errorString, mergeProcessResults } from './utils.js'
|
28
|
+
import { errorString, makeEthCallKey, mergeProcessResults } from './utils.js'
|
29
29
|
import { freezeGlobalConfig, GLOBAL_CONFIG } from './global-config.js'
|
30
30
|
|
31
31
|
import { StoreContext } from './db-context.js'
|
32
32
|
import { Subject } from 'rxjs'
|
33
|
-
import { metrics } from '@opentelemetry/api'
|
34
33
|
import { getProvider } from './provider.js'
|
35
34
|
import { EthChainId } from '@sentio/chain'
|
36
|
-
import { Provider
|
35
|
+
import { Provider } from 'ethers'
|
36
|
+
import { decodeMulticallResult, encodeMulticallData, getMulticallAddress, Multicall3Call } from './multicall.js'
|
37
37
|
|
38
|
-
|
39
|
-
const process_binding_count =
|
40
|
-
const process_binding_time = meter.createCounter('process_binding_time')
|
41
|
-
const process_binding_error = meter.createCounter('process_binding_error')
|
38
|
+
import { processMetrics, providerMetrics, dbMetrics } from './metrics.js'
|
39
|
+
const { process_binding_count, process_binding_time, process_binding_error } = processMetrics
|
42
40
|
|
43
41
|
;(BigInt.prototype as any).toJSON = function () {
|
44
42
|
return this.toString()
|
@@ -54,6 +52,8 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
54
52
|
|
55
53
|
private readonly shutdownHandler?: () => void
|
56
54
|
|
55
|
+
private preparedData: PreparedData | undefined
|
56
|
+
|
57
57
|
constructor(loader: () => Promise<any>, shutdownHandler?: () => void) {
|
58
58
|
this.loader = loader
|
59
59
|
this.shutdownHandler = shutdownHandler
|
@@ -126,11 +126,11 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
126
126
|
}
|
127
127
|
|
128
128
|
async processBindings(request: ProcessBindingsRequest, options?: CallContext): Promise<ProcessBindingResponse> {
|
129
|
-
const
|
129
|
+
const preparedData = await this.preprocessBindings(request.bindings, {}, undefined, options)
|
130
130
|
|
131
131
|
const promises = []
|
132
132
|
for (const binding of request.bindings) {
|
133
|
-
const promise = this.processBinding(binding,
|
133
|
+
const promise = this.processBinding(binding, preparedData)
|
134
134
|
if (GLOBAL_CONFIG.execution.sequential) {
|
135
135
|
await promise
|
136
136
|
}
|
@@ -157,13 +157,14 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
157
157
|
|
158
158
|
async preprocessBindings(
|
159
159
|
bindings: DataBinding[],
|
160
|
+
preprocessStore: { [k: string]: any },
|
160
161
|
dbContext?: StoreContext,
|
161
162
|
options?: CallContext
|
162
|
-
): Promise<
|
163
|
-
console.
|
163
|
+
): Promise<PreparedData> {
|
164
|
+
console.debug(`preprocessBindings start, bindings: ${bindings.length}`)
|
164
165
|
const promises = []
|
165
166
|
for (const binding of bindings) {
|
166
|
-
promises.push(this.preprocessBinding(binding, dbContext, options))
|
167
|
+
promises.push(this.preprocessBinding(binding, preprocessStore, dbContext, options))
|
167
168
|
}
|
168
169
|
let preprocessResults: PreprocessResult[]
|
169
170
|
try {
|
@@ -171,18 +172,15 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
171
172
|
} catch (e) {
|
172
173
|
throw e
|
173
174
|
}
|
174
|
-
console.log(
|
175
|
-
'ethCallParams: ',
|
176
|
-
preprocessResults.map((r) => r.ethCallParams)
|
177
|
-
)
|
178
175
|
const groupedRequests = new Map<string, EthCallParam[]>()
|
179
176
|
const providers = new Map<string, Provider>()
|
180
177
|
for (const result of preprocessResults) {
|
181
178
|
for (const param of result.ethCallParams) {
|
182
|
-
|
183
|
-
|
179
|
+
const { chainId, blockTag } = param.context!
|
180
|
+
if (!providers.has(chainId)) {
|
181
|
+
providers.set(chainId, getProvider(chainId as EthChainId))
|
184
182
|
}
|
185
|
-
const key =
|
183
|
+
const key = [chainId, blockTag].join('|')
|
186
184
|
if (!groupedRequests.has(key)) {
|
187
185
|
groupedRequests.set(key, [])
|
188
186
|
}
|
@@ -191,35 +189,84 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
191
189
|
}
|
192
190
|
|
193
191
|
const start = Date.now()
|
194
|
-
const
|
192
|
+
const MULTICALL_THRESHOLD = 1
|
193
|
+
const callPromises: Promise<[string, string]>[] = []
|
194
|
+
const multicallPromises: Promise<[string, string][]>[] = []
|
195
|
+
|
195
196
|
for (const params of groupedRequests.values()) {
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
const
|
200
|
-
|
197
|
+
const { chainId, blockTag } = params[0].context!
|
198
|
+
const multicallAddress = getMulticallAddress(chainId as EthChainId)
|
199
|
+
if (params.length <= MULTICALL_THRESHOLD || !multicallAddress) {
|
200
|
+
for (const param of params) {
|
201
|
+
callPromises.push(
|
202
|
+
providers
|
203
|
+
.get(chainId)!
|
204
|
+
.call({
|
205
|
+
to: param.context!.address,
|
206
|
+
data: param.calldata,
|
207
|
+
blockTag
|
208
|
+
})
|
209
|
+
.then((result) => [makeEthCallKey(param), result])
|
210
|
+
)
|
211
|
+
}
|
212
|
+
continue
|
213
|
+
}
|
214
|
+
|
215
|
+
// construct multicalls
|
216
|
+
const CHUNK_SIZE = 128
|
217
|
+
for (let i = 0; i < params.length; i += CHUNK_SIZE) {
|
218
|
+
const chunk = params.slice(i, i + CHUNK_SIZE)
|
219
|
+
const calls: Multicall3Call[] = chunk.map((param) => ({
|
220
|
+
target: param.context!.address,
|
221
|
+
callData: param.calldata
|
222
|
+
}))
|
223
|
+
const data = encodeMulticallData(calls)
|
224
|
+
multicallPromises.push(
|
201
225
|
providers
|
202
|
-
.get(
|
226
|
+
.get(chainId)!
|
203
227
|
.call({
|
204
|
-
to:
|
205
|
-
data:
|
228
|
+
to: multicallAddress,
|
229
|
+
data: data,
|
230
|
+
blockTag
|
231
|
+
})
|
232
|
+
.then((raw) => {
|
233
|
+
const result = decodeMulticallResult(raw).returnData
|
234
|
+
if (result.length != chunk.length) {
|
235
|
+
throw new Error(`multicall result length mismatch, params: ${chunk.length}, result: ${result.length}`)
|
236
|
+
}
|
237
|
+
const ret: [string, string][] = []
|
238
|
+
for (let i = 0; i < chunk.length; i++) {
|
239
|
+
ret.push([makeEthCallKey(chunk[i]), result[i]])
|
240
|
+
}
|
241
|
+
return ret
|
206
242
|
})
|
207
|
-
.then((ret) => [calldata, frag.decodeFunctionResult(param.function, ret).toArray()] as [string, any[]])
|
208
243
|
)
|
209
244
|
}
|
210
245
|
}
|
211
|
-
|
246
|
+
|
247
|
+
let results: { [p: string]: string } = {}
|
212
248
|
try {
|
213
249
|
results = Object.fromEntries(await Promise.all(callPromises))
|
250
|
+
for (const multicallResult of await Promise.all(multicallPromises)) {
|
251
|
+
results = {
|
252
|
+
...results,
|
253
|
+
...Object.fromEntries(multicallResult)
|
254
|
+
}
|
255
|
+
}
|
214
256
|
} catch (e) {
|
215
257
|
console.error(`eth call error: ${e}`)
|
216
258
|
}
|
217
|
-
console.log(
|
218
|
-
|
259
|
+
console.log(
|
260
|
+
`${Object.keys(results).length} calls finished, actual calls: ${callPromises.length + multicallPromises.length}, elapsed: ${Date.now() - start}ms`
|
261
|
+
)
|
262
|
+
return {
|
263
|
+
ethCallResults: results
|
264
|
+
}
|
219
265
|
}
|
220
266
|
|
221
267
|
async preprocessBinding(
|
222
268
|
request: DataBinding,
|
269
|
+
preprocessStore: { [k: string]: any },
|
223
270
|
dbContext?: StoreContext,
|
224
271
|
options?: CallContext
|
225
272
|
): Promise<PreprocessResult> {
|
@@ -238,7 +285,7 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
238
285
|
]
|
239
286
|
)
|
240
287
|
}
|
241
|
-
return await PluginManager.INSTANCE.preprocessBinding(request, dbContext)
|
288
|
+
return await PluginManager.INSTANCE.preprocessBinding(request, preprocessStore, dbContext)
|
242
289
|
}
|
243
290
|
|
244
291
|
async processBinding(
|
@@ -274,6 +321,7 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
274
321
|
const subject = new Subject<DeepPartial<ProcessStreamResponse>>()
|
275
322
|
this.handleRequests(requests, subject)
|
276
323
|
.then(() => {
|
324
|
+
this.preparedData = { ethCallResults: {} }
|
277
325
|
subject.complete()
|
278
326
|
})
|
279
327
|
.catch((e) => {
|
@@ -288,16 +336,23 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
288
336
|
subject: Subject<DeepPartial<PreprocessStreamResponse>>
|
289
337
|
) {
|
290
338
|
const contexts = new Contexts()
|
339
|
+
const preprocessStore: { [k: string]: any } = {}
|
291
340
|
|
292
341
|
for await (const request of requests) {
|
293
342
|
try {
|
294
|
-
console.debug('received request:', request)
|
295
343
|
if (request.bindings) {
|
296
344
|
const bindings = request.bindings.bindings
|
297
345
|
const dbContext = contexts.new(request.processId, subject)
|
298
346
|
const start = Date.now()
|
299
|
-
this.preprocessBindings(bindings, dbContext)
|
300
|
-
.then(() => {
|
347
|
+
this.preprocessBindings(bindings, preprocessStore, dbContext, undefined)
|
348
|
+
.then((preparedData) => {
|
349
|
+
// TODO maybe not proper to pass data in this way
|
350
|
+
this.preparedData = {
|
351
|
+
ethCallResults: {
|
352
|
+
...this.preparedData?.ethCallResults,
|
353
|
+
...preparedData.ethCallResults
|
354
|
+
}
|
355
|
+
}
|
301
356
|
subject.next({
|
302
357
|
processId: request.processId
|
303
358
|
})
|
@@ -305,12 +360,10 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
305
360
|
.catch((e) => {
|
306
361
|
console.debug(e)
|
307
362
|
dbContext.error(request.processId, e)
|
308
|
-
process_binding_error.add(1)
|
309
363
|
})
|
310
364
|
.finally(() => {
|
311
365
|
const cost = Date.now() - start
|
312
366
|
console.debug('preprocessBinding', request.processId, ' took', cost, 'ms')
|
313
|
-
process_binding_time.add(cost)
|
314
367
|
contexts.delete(request.processId)
|
315
368
|
})
|
316
369
|
}
|
@@ -350,13 +403,13 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
350
403
|
|
351
404
|
for await (const request of requests) {
|
352
405
|
try {
|
353
|
-
console.debug('received request:', request)
|
406
|
+
// console.debug('received request:', request)
|
354
407
|
if (request.binding) {
|
355
408
|
process_binding_count.add(1)
|
356
409
|
const binding = request.binding
|
357
410
|
const dbContext = contexts.new(request.processId, subject)
|
358
411
|
const start = Date.now()
|
359
|
-
PluginManager.INSTANCE.processBinding(binding,
|
412
|
+
PluginManager.INSTANCE.processBinding(binding, this.preparedData, dbContext)
|
360
413
|
.then((result) => {
|
361
414
|
subject.next({
|
362
415
|
result,
|
@@ -374,6 +427,8 @@ export class ProcessorServiceImpl implements ProcessorServiceImplementation {
|
|
374
427
|
console.debug('processBinding', request.processId, ' took', cost, 'ms')
|
375
428
|
process_binding_time.add(cost)
|
376
429
|
contexts.delete(request.processId)
|
430
|
+
console.debug('db stats', JSON.stringify(dbMetrics.stats()))
|
431
|
+
console.debug('provider stats', JSON.stringify(providerMetrics.stats()))
|
377
432
|
})
|
378
433
|
}
|
379
434
|
if (request.dbResult) {
|
package/src/utils.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import { ProcessResult } from '@sentio/protos'
|
1
|
+
import { EthCallParam, ProcessResult } from '@sentio/protos'
|
2
2
|
|
3
3
|
// TODO better handling this, because old proto doesn't have this
|
4
4
|
import { StateResult, ProcessResult as ProcessResultFull } from './gen/processor/protos/processor.js'
|
@@ -8,7 +8,7 @@ import { Required } from 'utility-types'
|
|
8
8
|
export function mergeProcessResults(results: ProcessResult[]): Required<ProcessResult, 'states'> {
|
9
9
|
const res = {
|
10
10
|
...ProcessResultFull.create(),
|
11
|
-
states: StateResult.create()
|
11
|
+
states: StateResult.create()
|
12
12
|
}
|
13
13
|
|
14
14
|
for (const r of results) {
|
@@ -17,7 +17,7 @@ export function mergeProcessResults(results: ProcessResult[]): Required<ProcessR
|
|
17
17
|
res.events = res.events.concat(r.events)
|
18
18
|
res.exports = res.exports.concat(r.exports)
|
19
19
|
res.states = {
|
20
|
-
configUpdated: res.states?.configUpdated || r.states?.configUpdated || false
|
20
|
+
configUpdated: res.states?.configUpdated || r.states?.configUpdated || false
|
21
21
|
}
|
22
22
|
}
|
23
23
|
return res
|
@@ -28,3 +28,11 @@ export function errorString(e: Error): string {
|
|
28
28
|
}
|
29
29
|
|
30
30
|
export const USER_PROCESSOR = 'user_processor'
|
31
|
+
|
32
|
+
export function makeEthCallKey(param: EthCallParam) {
|
33
|
+
if (!param.context) {
|
34
|
+
throw new Error('null context for eth call')
|
35
|
+
}
|
36
|
+
const { chainId, address, blockTag } = param.context
|
37
|
+
return `${chainId}|${address}|${blockTag}|${param.calldata}`.toLowerCase()
|
38
|
+
}
|