@eclesia/indexer-engine 2.11.1 → 2.12.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.
@@ -123,7 +123,7 @@ var EcleciaIndexer = class extends require_index.EclesiaEmitter {
123
123
  ]
124
124
  });
125
125
  const queueErrorHandler = (e) => {
126
- this.prometheus?.recordError("block_queue");
126
+ this.prometheus?.recordError("rpc");
127
127
  this.log.error("Error enqueueing block data: " + e);
128
128
  };
129
129
  if (this.config.minimal) this.blockQueue = new require_index$2.CircularBuffer(this.config.batchSize, queueErrorHandler);
@@ -206,7 +206,7 @@ var EcleciaIndexer = class extends require_index.EclesiaEmitter {
206
206
  return true;
207
207
  } catch (error) {
208
208
  this.log.error("RPC connection error: " + error);
209
- this.prometheus?.recordError("connect_rpc_error");
209
+ this.prometheus?.recordError("rpc");
210
210
  this.tryToRecover = true;
211
211
  return false;
212
212
  }
@@ -253,12 +253,12 @@ var EcleciaIndexer = class extends require_index.EclesiaEmitter {
253
253
  if (this.config.usePolling) this.pollForBlock();
254
254
  else if (this.subscription) this.subscription.addListener(this.blockListener);
255
255
  else {
256
- this.prometheus?.recordError("subscription_error");
256
+ this.prometheus?.recordError("rpc");
257
257
  throw new Error("Could not subscribe to new blocks");
258
258
  }
259
259
  } catch (e) {
260
260
  this.log.error("Failed to set up block listening: " + e);
261
- this.prometheus?.recordError("block_listening_error");
261
+ this.prometheus?.recordError("rpc");
262
262
  this.setStatus("FAILED");
263
263
  throw e;
264
264
  }
@@ -266,7 +266,7 @@ var EcleciaIndexer = class extends require_index.EclesiaEmitter {
266
266
  this.tryToRecover = false;
267
267
  this.fetcher().catch((e) => {
268
268
  this.setStatus("FAILED");
269
- this.prometheus?.recordError("fetching_error");
269
+ this.prometheus?.recordError("rpc");
270
270
  throw new Error("Error in fetching service: " + e);
271
271
  });
272
272
  const hrTime = process.hrtime();
@@ -285,7 +285,7 @@ var EcleciaIndexer = class extends require_index.EclesiaEmitter {
285
285
  const toProcess = await Promise.race([this.blockQueue.dequeue(), timeoutPromise]);
286
286
  this.log.silly("Retrieved block data");
287
287
  if (!toProcess || !toProcess[0] || !toProcess[1]) {
288
- this.prometheus?.recordError("rpc_error");
288
+ this.prometheus?.recordError("rpc");
289
289
  throw new Error("Could not fetch block");
290
290
  }
291
291
  height = toProcess[0].block.header.height;
@@ -298,7 +298,7 @@ var EcleciaIndexer = class extends require_index.EclesiaEmitter {
298
298
  const toProcess = await Promise.race([this.blockQueue.dequeue(), timeoutPromise]);
299
299
  this.log.silly("Retrieved block data");
300
300
  if (!toProcess || !toProcess[0] || !toProcess[1] || !toProcess[2]) {
301
- this.prometheus?.recordError("rpc_error");
301
+ this.prometheus?.recordError("rpc");
302
302
  throw new Error("Could not fetch block");
303
303
  }
304
304
  this.log.silly("Decoded block");
@@ -333,7 +333,7 @@ var EcleciaIndexer = class extends require_index.EclesiaEmitter {
333
333
  await this.config.endTransaction(true);
334
334
  this.log.silly("Committed db tx");
335
335
  } catch (e) {
336
- this.prometheus?.recordError("block_processing_error");
336
+ this.prometheus?.recordError("block");
337
337
  this.log.error("Block processing error: " + e);
338
338
  this.setStatus("FAILED");
339
339
  try {
@@ -575,7 +575,7 @@ var EcleciaIndexer = class extends require_index.EclesiaEmitter {
575
575
  else {
576
576
  this.tryToRecover = true;
577
577
  this.setStatus("FAILED");
578
- this.prometheus?.recordError("abci_query_error");
578
+ this.prometheus?.recordError("rpc");
579
579
  throw new Error("RPC not responding. Query at: " + path);
580
580
  }
581
581
  } catch (_e) {
@@ -595,7 +595,7 @@ var EcleciaIndexer = class extends require_index.EclesiaEmitter {
595
595
  if (this.blockQueue.synced && !this.tryToRecover) {
596
596
  this.latestHeight = height;
597
597
  if (this.blockQueue.size() + 1 == this.config.batchSize) {
598
- this.prometheus?.recordError("block_queue_full");
598
+ this.prometheus?.recordError("block");
599
599
  this.log.error("Block queue is full. Cannot add new block");
600
600
  this.tryToRecover = true;
601
601
  this.retryCount++;
@@ -730,7 +730,7 @@ var EcleciaIndexer = class extends require_index.EclesiaEmitter {
730
730
  try {
731
731
  await this.config.endTransaction(false);
732
732
  } catch (dbe) {
733
- this.prometheus?.recordError("database_error");
733
+ this.prometheus?.recordError("database");
734
734
  this.log.error("Error ending transaction. Must be a DB error: " + dbe);
735
735
  }
736
736
  this.log.error("Failed to import genesis");
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["DEFAULT_START_HEIGHT","DEFAULT_BATCH_SIZE","DEFAULT_POLLING_INTERVAL_MS","DEFAULT_HEALTH_CHECK_PORT","DEFAULT_PROMETHEUS_PORT","EclesiaEmitter","CircularBuffer","IndexerMetrics","timeoutPromise: ReturnType<typeof this.blockQueue.dequeue>","QUEUE_DEQUEUE_TIMEOUT_MS","QueryValidatorsResponse","PERIODIC_INTERVALS","hrTime","processStart: [number, number]","beginBlockEvents: readonly Event[] | readonly Event38[]","endBlockEvents: readonly Event[] | readonly Event38[]","decodeAttr","Tx","events: Array<{\n msg_index?: number\n events: (Event | Event38)[]\n }>","eventsToAdd: typeof events","MsgExec","events","timeoutPromise: Promise<[BlockResponse, BlockResultsResponse]>","RPC_TIMEOUT_MS","timeoutPromise: Promise<[BlockResponse, BlockResultsResponse, Uint8Array]>","QueryValidatorsRequest","PAGINATION_LIMITS","Parser","Pick","StreamArray","Batch","GENESIS_BATCH_SIZE","StreamValues"],"sources":["../../src/indexer/index.ts"],"sourcesContent":["/* eslint-disable @stylistic/no-multi-spaces */\n/* eslint-disable max-lines */\nimport {\n createHash,\n} from \"node:crypto\";\nimport * as fs from \"node:fs\";\n\nimport {\n BlockResponse, BlockResultsResponse, CometClient, connectComet, Event, toRfc3339WithNanoseconds,\n} from \"@cosmjs/tendermint-rpc\";\nimport {\n BlockResultsResponse as BlockResultsResponse38, Event as Event38,\n} from \"@cosmjs/tendermint-rpc/build/comet38/responses.js\";\nimport {\n MsgExec,\n} from \"cosmjs-types/cosmos/authz/v1beta1/tx.js\";\nimport {\n QueryValidatorsRequest,\n QueryValidatorsResponse,\n} from \"cosmjs-types/cosmos/staking/v1beta1/query.js\";\nimport {\n Validator,\n} from \"cosmjs-types/cosmos/staking/v1beta1/staking.js\";\nimport {\n Tx,\n} from \"cosmjs-types/cosmos/tx/v1beta1/tx.js\";\nimport Fastify, {\n FastifyInstance,\n} from \"fastify\";\nimport {\n chain,\n} from \"stream-chain\";\nimport Parser from \"stream-json\";\nimport Pick from \"stream-json/filters/Pick.js\";\nimport StreamArray from \"stream-json/streamers/StreamArray.js\";\nimport StreamValues from \"stream-json/streamers/StreamValues.js\";\nimport Batch from \"stream-json/utils/Batch.js\";\nimport {\n v4 as uuidv4,\n} from \"uuid\";\nimport * as winston from \"winston\";\n\nimport {\n DEFAULT_BATCH_SIZE, DEFAULT_HEALTH_CHECK_PORT, DEFAULT_POLLING_INTERVAL_MS, DEFAULT_PROMETHEUS_PORT, DEFAULT_START_HEIGHT,\n GENESIS_BATCH_SIZE, PAGINATION_LIMITS, PERIODIC_INTERVALS, QUEUE_DEQUEUE_TIMEOUT_MS, RPC_TIMEOUT_MS,\n} from \"../constants.js\";\nimport {\n EclesiaEmitter,\n} from \"../emitter/index.js\";\nimport {\n IndexerMetrics,\n} from \"../metrics/index.js\";\nimport {\n CircularBuffer,\n} from \"../promise-queue/index.js\";\nimport {\n BlockQueue, EcleciaIndexerConfig, EmitFunc, MinimalBlockQueue,\n UUIDEvent, WithHeightAndUUID,\n} from \"../types/index.js\";\nimport {\n decodeAttr,\n} from \"../utils/index.js\";\nimport {\n validateFilePath, validatePort, validatePositiveInteger, validateUrl,\n} from \"../validation/index.js\";\n\n/** Default configuration for the Eclesia indexer */\nexport const defaultIndexerConfig = {\n startHeight: DEFAULT_START_HEIGHT, // Start indexing from block 1\n batchSize: DEFAULT_BATCH_SIZE, // Process blocks in batches of 500\n modules: [], // No modules enabled by default\n getNextHeight: () => DEFAULT_START_HEIGHT, // Default height retrieval function\n logLevel: \"info\" as EcleciaIndexerConfig[\"logLevel\"], // Default log level\n usePolling: false, // Use WebSocket subscription by default\n pollingInterval: DEFAULT_POLLING_INTERVAL_MS, // Poll every 5 seconds when polling enabled\n shouldProcessGenesis: () => false, // Skip genesis processing by default\n minimal: true, // Use minimal indexing by default\n enableHealthcheck: true, // Enable health check server by default\n healthCheckPort: DEFAULT_HEALTH_CHECK_PORT, // Default health check port\n enablePrometheus: false, // Disable Prometheus metrics server by default\n prometheusPort: DEFAULT_PROMETHEUS_PORT, // Default Prometheus metrics server port\n init: () => Promise.resolve(), // No-op initialization function\n beginTransaction: () => Promise.resolve(), // No-op transaction begin function\n endTransaction: (_status: boolean) => Promise.resolve(), // No-op transaction end function\n};\n\n/**\n * Core blockchain indexer that connects to Tendermint RPC and processes blocks\n * Extends EclesiaEmitter to provide event-driven architecture for modules\n */\nexport class EcleciaIndexer extends EclesiaEmitter {\n /** Indexer configuration settings */\n public config: EcleciaIndexerConfig;\n\n /** Fastify HTTP server for health checks */\n private fastify: FastifyInstance | null = null;\n\n /** Prometheus HTTP server instance */\n private prometheusServer: FastifyInstance | null = null;\n\n /** Indicates if the indexer has started */\n private started: boolean = false;\n\n /** Queue for managing block processing pipeline */\n private blockQueue: BlockQueue;\n\n /** Latest block height from the chain */\n private latestHeight!: number;\n\n /** Next block height to process */\n public heightToProcess!: number;\n\n /** Whether the indexer has been initialized */\n private initialized = false;\n\n /** Prometheus metrics server instance */\n public prometheus: IndexerMetrics | null = null;\n\n /** Number of retry attempts for error recovery */\n private retryCount = 0;\n\n /** CometBFT client for ad-hoc queries */\n public client!: CometClient;\n\n /** CometBFT client for block and validator queries */\n public blockClient!: CometClient;\n\n /** Winston logger instance */\n public log: winston.Logger;\n\n /** Flag indicating if indexer should attempt recovery */\n private tryToRecover: boolean = false;\n\n /** Health check status for monitoring */\n private healthCheck = {\n status: \"CONNECTING\",\n };\n\n /** WebSocket subscription for new block notifications */\n private subscription: ReturnType<CometClient[\"subscribeNewBlock\"]> | null = null;\n\n /** Timeout handler for block reception */\n private blockTimeout: NodeJS.Timeout | null = null;\n\n /**\n * Creates a new Eclesia indexer instance\n * @param config - Indexer configuration options\n */\n constructor(config: EcleciaIndexerConfig) {\n super();\n\n // Validate required configuration\n validateUrl(config.rpcUrl, \"rpcUrl\");\n validatePositiveInteger(config.batchSize, \"batchSize\");\n\n // Validate optional genesis path if processing genesis\n if (config.genesisPath) {\n validateFilePath(config.genesisPath, \"genesisPath\");\n }\n\n // Validate health check port if provided\n if (config.healthCheckPort !== undefined) {\n validatePort(config.healthCheckPort, \"healthCheckPort\");\n }\n\n // Validate prometheus port if provided\n if (config.prometheusPort !== undefined) {\n validatePort(config.prometheusPort, \"prometheusPort\");\n }\n\n // Validate start height if provided\n if (config.startHeight !== undefined) {\n validatePositiveInteger(config.startHeight, \"startHeight\");\n }\n\n // Validate polling interval if provided\n if (config.pollingInterval !== undefined) {\n validatePositiveInteger(config.pollingInterval, \"pollingInterval\");\n }\n\n this.config = {\n ...defaultIndexerConfig,\n ...config,\n };\n\n // Initialize logger first so it can be used by queue error handler\n const {\n printf,\n } = winston.format;\n\n const eclesiaFormat = printf(({\n level, message, timestamp,\n }) => {\n return `${timestamp} [${level.toUpperCase()}]:\\t${message}`;\n });\n this.log = winston.createLogger({\n level: this.config.logLevel,\n defaultMeta: {\n service: \"Eclesia Indexer\",\n },\n transports: [\n new winston.transports.File({\n filename: \"error.log\",\n level: \"error\",\n }),\n new winston.transports.File({\n filename: \"combined.log\",\n }),\n new winston.transports.Console({\n format: winston.format.combine(winston.format.splat(),\n winston.format.timestamp(),\n eclesiaFormat,\n winston.format.colorize({\n all: true,\n })),\n }),\n ],\n });\n\n // Initialize block queue based on minimal or full indexing mode\n // Pass error handler that uses the logger\n const queueErrorHandler = (e: unknown) => {\n this.prometheus?.recordError(\"block_queue\");\n this.log.error(\"Error enqueueing block data: \" + e);\n };\n\n if (this.config.minimal) {\n // Minimal mode: only store block and block results\n this.blockQueue = new CircularBuffer<[BlockResponse, BlockResultsResponse]>(this.config.batchSize, queueErrorHandler);\n }\n else {\n // Full mode: also store validator information\n this.blockQueue = new CircularBuffer<[BlockResponse, BlockResultsResponse, Uint8Array]>(this.config.batchSize, queueErrorHandler);\n }\n\n this.on(\"_unhandled\",\n (msg) => {\n if (msg.uuid) {\n this.log.verbose(\"Unhandled event: \" + msg.type);\n this.emit(\"uuid\",\n {\n status: true,\n uuid: msg.uuid,\n });\n }\n });\n if (this.config.enablePrometheus) {\n this.prometheus = new IndexerMetrics();\n this.prometheusServer = Fastify({\n logger: false,\n });\n this.prometheusServer.get(\"/metrics\",\n async (_req, res) => {\n res.header(\"Content-Type\", this.prometheus!.registry.contentType);\n res.send(await this.prometheus!.getMetrics());\n },\n );\n\n const prometheusPort = this.config.prometheusPort\n ?? (process.env.PROMETHEUS_PORT ? parseInt(process.env.PROMETHEUS_PORT, 10) : DEFAULT_PROMETHEUS_PORT);\n this.prometheusServer.listen({\n port: prometheusPort,\n host: \"0.0.0.0\",\n },\n (err) => {\n if (err) {\n this.log.error(\"Prometheus error: \" + err);\n this.prometheus?.recordError(\"metrics_server\");\n this.emit(\"fatal-error\", {\n error: err,\n message: \"Failed to start metrics server\",\n });\n }\n });\n }\n if (this.config.enableHealthcheck) {\n this.fastify = Fastify({\n logger: false,\n });\n this.fastify.get(\"/health\",\n async (_request, reply) => {\n const code = this.healthCheck.status == \"OK\"\n ? 200\n : 503;\n reply.code(code).send(this.healthCheck);\n });\n const healthPort = this.config.healthCheckPort\n ?? (process.env.HEALTH_CHECK_PORT ? parseInt(process.env.HEALTH_CHECK_PORT, 10) : DEFAULT_HEALTH_CHECK_PORT);\n this.fastify.listen({\n port: healthPort,\n host: \"0.0.0.0\",\n },\n (err) => {\n if (err) {\n this.log.error(\"Health check server error: \" + err);\n this.prometheus?.recordError(\"health_check_server\");\n this.emit(\"fatal-error\", {\n error: err,\n message: \"Failed to start health check server\",\n });\n }\n });\n }\n }\n\n private setStatus(status: string) {\n this.healthCheck.status = status;\n }\n\n private blockListener = {\n next: (data: {\n header: {\n height: number\n }\n }) => {\n this.newBlockReceived(data.header.height);\n },\n };\n\n private isMinimal(_blockqueue: BlockQueue): _blockqueue is MinimalBlockQueue {\n if (this.config.minimal) {\n return true;\n }\n else {\n return false;\n }\n }\n\n public async connect() {\n try {\n if (this.client && this.tryToRecover) {\n this.log.verbose(\"Recover from error. Attempting to disconnect from RPC\");\n this.client.disconnect();\n this.blockClient.disconnect();\n this.log.verbose(\"Disconnected from RPC\");\n }\n this.client = await connectComet(this.config.rpcUrl);\n this.log.info(\"Connected to RPC for ad hoc queries\");\n\n this.blockClient = await connectComet(this.config.rpcUrl);\n this.log.info(\"Connected to RPC for block & validator info\");\n\n return true;\n }\n catch (error) {\n this.log.error(\"RPC connection error: \" + error);\n this.prometheus?.recordError(\"connect_rpc_error\");\n this.tryToRecover = true;\n return false;\n }\n }\n\n public stop() {\n this.started = false;\n }\n\n public async start() {\n this.started = true;\n if (this.blockQueue) {\n this.blockQueue.clear();\n this.log.verbose(\"Starting, clearing block queue\");\n }\n if (!this.initialized) {\n try {\n if (this.config.init) {\n await this.config.init();\n }\n }\n catch (e) {\n this.log.error(\"Failed to initialize indexer: \" + e);\n\n this.prometheus?.recordError(\"init_error\");\n this.setStatus(\"FAILED\");\n throw e;\n }\n if (await this.config.shouldProcessGenesis()) {\n try {\n if (this.config.genesisPath) {\n await this.parseGenesis();\n }\n }\n catch (e) {\n this.log.error(\"Failed to parse genesis: \" + e);\n\n this.prometheus?.recordError(\"genesis_error\");\n this.setStatus(\"FAILED\");\n throw e;\n }\n }\n this.initialized = true;\n }\n try {\n await this.connect();\n if (!this.config.usePolling && this.subscription) {\n this.subscription.removeListener(this.blockListener);\n this.subscription = null;\n this.log.verbose(\"Removed existing block listener and subscription\");\n }\n if (!this.config.usePolling) {\n this.subscription = this.client.subscribeNewBlock\n ? this.client.subscribeNewBlock()\n : null;\n }\n const status = await this.client.status();\n this.latestHeight = status.syncInfo.latestBlockHeight;\n this.log.info(\"Current chain height: \" + this.latestHeight);\n\n this.heightToProcess = await this.config.getNextHeight();\n if (this.config.usePolling) {\n this.pollForBlock();\n }\n else {\n if (this.subscription) {\n this.subscription.addListener(this.blockListener);\n }\n else {\n this.prometheus?.recordError(\"subscription_error\");\n throw new Error(\"Could not subscribe to new blocks\");\n }\n }\n }\n catch (e) {\n this.log.error(\"Failed to set up block listening: \" + e);\n this.prometheus?.recordError(\"block_listening_error\");\n this.setStatus(\"FAILED\");\n throw e;\n }\n this.log.debug(\"Starting main processing loop\");\n this.tryToRecover = false;\n this.fetcher().catch((e) => {\n this.setStatus(\"FAILED\");\n\n this.prometheus?.recordError(\"fetching_error\");\n throw new Error(\"Error in fetching service: \" + e);\n });\n\n const hrTime = process.hrtime();\n let ms = hrTime[0] * 1000000 + hrTime[1] / 1000;\n while (this.blockQueue.size() > 0 && !this.tryToRecover && this.started && (this.config.endHeight === undefined || this.heightToProcess <= this.config.endHeight)) {\n if (this.config.enablePrometheus) {\n this.prometheus!.updateRetryCount(this.retryCount);\n }\n // await the dequeued promise is essentially awaiting fetched data for that block\n try {\n if (this.tryToRecover) {\n throw new Error(\"Exiting processing loop. Attempting to recover indexer\");\n }\n // Index block inside a db transaction to ensure data consistency\n await this.config.beginTransaction();\n this.log.silly(\"Started db tx\");\n let height, timestamp;\n if (this.isMinimal(this.blockQueue)) {\n const timeoutPromise: ReturnType<typeof this.blockQueue.dequeue> = new Promise((resolve, reject) => {\n setTimeout(reject, QUEUE_DEQUEUE_TIMEOUT_MS, []);\n });\n const toProcess = await Promise.race([this.blockQueue.dequeue(), timeoutPromise]);\n this.log.silly(\"Retrieved block data\");\n if (!toProcess || !toProcess[0] || !toProcess[1]) {\n this.prometheus?.recordError(\"rpc_error\");\n throw new Error(\"Could not fetch block\");\n }\n height = toProcess[0].block.header.height;\n timestamp = toRfc3339WithNanoseconds(toProcess[0].block.header.time);\n await this.processBlock(toProcess[0],\n toProcess[1]);\n }\n else {\n const timeoutPromise: ReturnType<typeof this.blockQueue.dequeue> = new Promise((resolve, reject) => {\n setTimeout(reject, QUEUE_DEQUEUE_TIMEOUT_MS, []);\n });\n const toProcess = await Promise.race([this.blockQueue.dequeue(), timeoutPromise]);\n this.log.silly(\"Retrieved block data\");\n if (!toProcess || !toProcess[0] || !toProcess[1] || !toProcess[2]) {\n this.prometheus?.recordError(\"rpc_error\");\n throw new Error(\"Could not fetch block\");\n }\n\n this.log.silly(\"Decoded block\");\n height = toProcess[0].block.header.height;\n timestamp = toRfc3339WithNanoseconds(toProcess[0].block.header.time);\n await this.processBlock(toProcess[0],\n toProcess[1],\n QueryValidatorsResponse.decode(toProcess[2]).validators);\n }\n // Emit events to trigger periodic operations every 50, 100 and 1000 blocks\n if (height % PERIODIC_INTERVALS.LARGE == 0) {\n const hrTime = process.hrtime();\n const newms = hrTime[0] * 1000000 + hrTime[1] / 1000;\n const duration = newms - ms;\n ms = newms;\n const rate = 1000000000 / duration;\n this.log.info(\"Processing:\" + rate.toFixed(2) + \"blocks/sec\");\n await this.asyncEmit(\"periodic/1000\",\n {\n value: null,\n height,\n timestamp,\n });\n }\n if (height % PERIODIC_INTERVALS.MEDIUM == 0) {\n await this.asyncEmit(\"periodic/100\",\n {\n value: null,\n height,\n timestamp,\n });\n }\n if (height % PERIODIC_INTERVALS.SMALL == 0) {\n await this.asyncEmit(\"periodic/50\",\n {\n value: null,\n height,\n timestamp,\n });\n }\n this.log.silly(\"Handled periodic events\");\n\n await this.config.endTransaction(true);\n\n this.log.silly(\"Committed db tx\");\n }\n catch (e) {\n this.prometheus?.recordError(\"block_processing_error\");\n this.log.error(\"Block processing error: \" + e);\n this.setStatus(\"FAILED\");\n try {\n await this.config.endTransaction(false);\n }\n catch (dbe) {\n this.prometheus?.recordError(\"database\");\n this.log.error(\"Error ending transaction. Must be a DB error: \" + dbe);\n }\n this.tryToRecover = true;\n this.retryCount++;\n break;\n }\n this.retryCount = 0;\n this.setStatus(\"OK\");\n }\n if (this.config.endHeight !== undefined && this.heightToProcess >= this.config.endHeight!) {\n this.log.info(\"Reached configured end height. Stopping indexer.\");\n this.stop();\n }\n if (this.started) {\n if (this.retryCount < 3) {\n this.log.debug(\"Indexer retryCount: \" + this.retryCount);\n this.log.info(\"Indexer is restarting\");\n setTimeout(() => this.start(),\n this.retryCount * 5000);\n }\n else {\n this.log.info(\"Indexer failed too many times. Exiting.\");\n this.emit(\"fatal-error\", {\n error: new Error(\"Max retry attempts exceeded\"),\n message: \"Indexer failed too many times\",\n retryCount: this.retryCount,\n });\n }\n }\n }\n\n public asyncEmit: EmitFunc<keyof WithHeightAndUUID<EventMap>> = async (\n type,\n event,\n ) => {\n event.uuid = uuidv4();\n\n /*\n * More than 1 listener can be registered for an event type\n * Fortunately these are all set up during module init() so we have a consistent count\n * so we can count responses to resolve when complete\n * values are irrelevant as promise resolution is only used for flow control\n */\n let listenerCount = this.handled.get(type);\n if (!listenerCount) {\n // Setting listenerCount to 1 (the unhandled listener)\n listenerCount = 1;\n }\n let listenersResponded = 0;\n const prom = new Promise<void>((resolve, reject) => {\n const returnFunc = (ev: UUIDEvent) => {\n if (ev.uuid == event.uuid) {\n if (ev.status) {\n listenersResponded++;\n if (listenersResponded == listenerCount) {\n // All listeners have done their thing so we can remove listener, resolve and continue execution\n this.off(\"uuid\",\n returnFunc);\n resolve();\n }\n }\n else {\n // At least 1 listener is reporting an error. Reject and handle exception at the original asyncEmit location\n reject(ev.error);\n }\n }\n };\n this.on(\"uuid\",\n returnFunc);\n });\n this.emit(type,\n event);\n\n return prom;\n };\n\n private async processBlock(block: BlockResponse, block_results: BlockResultsResponse | BlockResultsResponse38, validators?: Validator[]) {\n let processStart: [number, number] = [0, 0];\n if (this.config.logLevel == \"silly\") {\n processStart = process.hrtime();\n }\n let endTimer;\n if (this.config.enablePrometheus) {\n endTimer = this.prometheus!.timeBlockProcessing();\n }\n const height = block.block.header.height;\n this.heightToProcess = height;\n this.log.debug(\"Processing block: %d\",\n height);\n // Initialize height & timestamp to be used for this block-processing run\n const timestamp = toRfc3339WithNanoseconds(block.block.header.time);\n\n // Use & await asyncEmit to ensure db insertions in order\n\n /*\n * Emit block information to any interested modules.\n * Primarily the required block module listens to this\n */\n await this.asyncEmit(\"block\",\n {\n value: {\n block,\n block_results,\n },\n height,\n timestamp,\n });\n this.log.silly(\"Modules handled block event\");\n\n let beginBlockEvents: readonly Event[] | readonly Event38[];\n let endBlockEvents: readonly Event[] | readonly Event38[];\n if ((block_results as BlockResultsResponse38).finalizeBlockEvents) {\n beginBlockEvents = (block_results as BlockResultsResponse38).finalizeBlockEvents.filter(x => x.attributes.find(a => decodeAttr(a.key) == \"mode\" && decodeAttr(a.value) == \"begin_block\")) as readonly Event38[];\n endBlockEvents = (block_results as BlockResultsResponse38).finalizeBlockEvents.filter(x => x.attributes.find(a => decodeAttr(a.key) == \"mode\" && decodeAttr(a.value) == \"end_block\")) as readonly Event38[];\n }\n else {\n beginBlockEvents = (block_results as BlockResultsResponse).beginBlockEvents;\n endBlockEvents = (block_results as BlockResultsResponse).endBlockEvents;\n }\n // Deal with begin_block events first\n await this.asyncEmit(\"begin_block\",\n {\n value: {\n events: beginBlockEvents!,\n validators,\n },\n height,\n timestamp,\n });\n\n this.log.silly(\"Modules handled begin_block events\");\n\n // Then individual tx_events\n await this.asyncEmit(\"tx_events\",\n {\n value: block_results.results,\n height,\n timestamp,\n });\n this.log.silly(\"Modules handled tx events\");\n\n // Emit details and result for each tx msg separately\n for (let t = 0; t < block.block.txs.length; t++) {\n const tx = Tx.decode(block.block.txs[t]);\n\n const result = block_results.results[t].code;\n const txlog = block_results.results[t].log;\n\n if (result != 0) {\n // Tx failed. Ignore\n continue;\n }\n if (tx.body && tx.body.memo != \"\") {\n const txHash = createHash(\"sha256\").update(block.block.txs[t])\n .digest(\"hex\");\n await this.asyncEmit(\"tx_memo\",\n {\n value: {\n txHash,\n txBody: tx.body,\n },\n height,\n timestamp,\n });\n }\n // parsing log rather than using events directly in order to have msg_index available to filter appropriate events for each msg\n let events: Array<{\n msg_index?: number\n events: (Event | Event38)[]\n }> = txlog\n ? JSON.parse(txlog)\n : [];\n if (events.length == 0) {\n const eventsToAdd: typeof events = [];\n this.log.silly(\"No events found in tx log. Parsing events for msg_index\");\n for (let m = 0; m < block_results.results[t].events.length; m++) {\n if (block_results.results[t].events[m].attributes.find(a => decodeAttr(a.key) == \"msg_index\")) {\n const mi = decodeAttr(block_results.results[t].events[m].attributes.find(a => decodeAttr(a.key) == \"msg_index\")?.value ?? \"\");\n if (mi != \"\") {\n const miNum = parseInt(mi);\n let ev = eventsToAdd.find(x => x.msg_index == miNum);\n if (!ev) {\n ev = {\n msg_index: miNum,\n events: [block_results.results[t].events[m]],\n };\n eventsToAdd.push(ev);\n }\n else {\n ev.events.push(block_results.results[t].events[m] as Event);\n }\n }\n }\n }\n events = events.concat(eventsToAdd);\n }\n const msgs = tx.body?.messages;\n\n if (msgs) {\n for (let i = 0; i < msgs.length; i++) {\n this.log.silly(\"Indexer broadcasting msg for handling: \" + msgs[i].typeUrl);\n const msgevents\n = msgs.length > 1\n ? events.find(x => x.msg_index == i)?.events\n : events[0].events;\n await this.asyncEmit(msgs[i].typeUrl as never,\n {\n value: {\n tx: msgs[i].value as never,\n events: msgevents,\n } as never,\n height,\n timestamp,\n });\n if (msgs[i].typeUrl == \"/cosmos.authz.v1beta1.MsgExec\") {\n const authzMsgs = MsgExec.decode(msgs[i].value).msgs;\n if (authzMsgs) {\n for (let r = 0; r < authzMsgs.length; r++) {\n this.log.silly(\"Indexer broadcasting msg for handling: \" + authzMsgs[r].typeUrl);\n const authzMsgEvents = msgevents?.reduce((events, evt) => {\n if (evt.attributes.filter(x => decodeAttr(x.key) == \"authz_msg_index\" && decodeAttr(x.value) == \"\" + r).length > 0) {\n events.push(evt);\n }\n return events;\n },\n [] as (Event | Event38)[]);\n await this.asyncEmit(authzMsgs[r].typeUrl as never,\n {\n value: {\n tx: authzMsgs[r].value as never,\n events: authzMsgEvents,\n } as never,\n height,\n timestamp,\n });\n }\n }\n }\n }\n }\n }\n this.log.silly(\"Modules handled msg events\");\n if (this.config.enablePrometheus) {\n this.prometheus!.recordTransactions(block.block.txs.length);\n }\n // Then deal with end_block events\n await this.asyncEmit(\"end_block\",\n {\n value: endBlockEvents!,\n height,\n timestamp,\n });\n this.log.silly(\"Modules handled end_block events\");\n if (this.config.logLevel == \"silly\") {\n const processEnd = process.hrtime(processStart);\n const processTime = processEnd[0] * 1000 + processEnd[1] / 1000000;\n this.log.silly(\"Processed block %d in %d ms\",\n height,\n processTime.toFixed(2));\n }\n\n if (this.config.enablePrometheus) {\n endTimer!();\n }\n if (this.config.enablePrometheus) {\n this.prometheus!.updateBlockMetrics(height, this.latestHeight, this.blockQueue.size());\n }\n }\n\n private async fetcher() {\n for (let i = this.heightToProcess; i <= this.latestHeight; i++) {\n this.log.debug(\"Fetching: \" + i);\n if (this.tryToRecover) {\n this.log.verbose(\"Exiting fetcher loop. Attempting to recover indexer\");\n break;\n }\n try {\n if (this.isMinimal(this.blockQueue)) {\n const timeoutPromise: Promise<[BlockResponse, BlockResultsResponse]> = new Promise((resolve, reject) => {\n setTimeout(reject,\n RPC_TIMEOUT_MS,\n false);\n });\n const toIndex = Promise.race([Promise.all([this.blockClient.block(i) as Promise<BlockResponse>, this.blockClient.blockResults(i) as Promise<BlockResultsResponse>]), timeoutPromise]).catch((e) => {\n this.log.error(\"Error fetching block: \" + i + \" : \" + e);\n this.tryToRecover = true;\n return Promise.resolve([]);\n }) as Promise<[BlockResponse, BlockResultsResponse]>;\n this.blockQueue.enqueue(toIndex);\n }\n else {\n const timeoutPromise: Promise<[BlockResponse, BlockResultsResponse, Uint8Array]> = new Promise((resolve, reject) => {\n setTimeout(reject,\n RPC_TIMEOUT_MS,\n false);\n });\n const q = QueryValidatorsRequest.fromPartial({\n pagination: {\n limit: PAGINATION_LIMITS.VALIDATORS,\n },\n });\n const vals = QueryValidatorsRequest.encode(q).finish();\n const toIndex = Promise.race([\n Promise.all([\n this.blockClient.block(i) as Promise<BlockResponse>,\n this.blockClient.blockResults(i) as Promise<BlockResultsResponse>,\n this.callABCI(\"/cosmos.staking.v1beta1.Query/Validators\",\n vals,\n i,\n false),\n ]),\n timeoutPromise,\n ]).catch((e) => {\n this.log.error(\"Error fetching block: \" + i + \" : \" + e);\n this.tryToRecover = true;\n return Promise.resolve([]);\n }) as Promise<[BlockResponse, BlockResultsResponse, Uint8Array]>;\n this.blockQueue.enqueue(toIndex);\n }\n await this.blockQueue.continue();\n if (this.tryToRecover) {\n this.retryCount++;\n throw new Error(\"RPC not responding\");\n }\n }\n catch (e) {\n this.log.error(\"Fetching error: \" + e);\n break;\n }\n }\n if (!this.tryToRecover) {\n this.blockQueue.setSynced();\n this.log.info(\"Synced to latest height\");\n }\n }\n\n public async callABCI(path: string, data: Uint8Array, height?: number, adHoc: boolean = true): Promise<Uint8Array> {\n try {\n const endTimer = this.prometheus?.timeRpcCall(path) ?? void 0;\n const abciq = await\n (adHoc\n ? this.client\n : this.blockClient).abciQuery({\n path,\n data,\n height: height,\n });\n endTimer?.();\n if (abciq) {\n return abciq.value;\n }\n else {\n this.tryToRecover = true;\n this.setStatus(\"FAILED\");\n this.prometheus?.recordError(\"abci_query_error\");\n throw new Error(\"RPC not responding. Query at: \" + path);\n }\n }\n catch (_e) {\n this.tryToRecover = true;\n this.setStatus(\"FAILED\");\n this.retryCount++;\n throw new Error(\"RPC not responding. Query at: \" + path);\n }\n }\n\n private newBlockReceived(height: number): void {\n if (this.blockTimeout) {\n clearTimeout(this.blockTimeout);\n }\n this.blockTimeout = setTimeout(() => {\n this.tryToRecover = true;\n }, 30000);\n this.log.info(\"Received new block: %d\",\n height);\n if (height == this.latestHeight) {\n return;\n }\n // If we are synced, add to end of queue\n if (this.blockQueue.synced && !this.tryToRecover) {\n this.latestHeight = height;\n if (this.blockQueue.size() + 1 == this.config.batchSize) {\n this.prometheus?.recordError(\"block_queue_full\");\n this.log.error(\"Block queue is full. Cannot add new block\");\n this.tryToRecover = true;\n this.retryCount++;\n return;\n }\n try {\n if (this.isMinimal(this.blockQueue)) {\n this.blockQueue.enqueue(Promise.all([this.client.block(height) as Promise<BlockResponse>, this.client.blockResults(height) as Promise<BlockResultsResponse>]).catch((e) => {\n this.log.error(\"Error fetching block: \" + height + \" : \" + e);\n\n return Promise.resolve([]);\n }) as Promise<[BlockResponse, BlockResultsResponse]>);\n }\n else {\n const q = QueryValidatorsRequest.fromPartial({\n pagination: {\n limit: 1000n,\n },\n });\n const vals = QueryValidatorsRequest.encode(q).finish();\n this.blockQueue.enqueue(Promise.all([\n this.client.block(height) as Promise<BlockResponse>,\n this.client.blockResults(height) as Promise<BlockResultsResponse>,\n this.callABCI(\"/cosmos.staking.v1beta1.Query/Validators\",\n vals,\n height,\n false),\n ]).catch((e) => {\n this.log.error(\"Error fetching block: \" + height + \" : \" + e);\n return Promise.resolve([]);\n }) as Promise<[BlockResponse, BlockResultsResponse, Uint8Array]>);\n }\n }\n catch (e) {\n this.log.error(\"New Block Received error: \" + e);\n }\n }\n else {\n this.latestHeight = height;\n }\n }\n\n private async pollForBlock() {\n try {\n const status = await this.client.status();\n if (status.syncInfo.latestBlockHeight > this.latestHeight) {\n while (this.latestHeight < status.syncInfo.latestBlockHeight) {\n this.newBlockReceived(this.latestHeight + 1);\n }\n }\n setTimeout(() => {\n this.pollForBlock();\n },\n this.config.pollingInterval);\n }\n catch (e) {\n this.log.error(\"Error polling for new block: \" + e);\n this.tryToRecover = true;\n this.retryCount++;\n }\n }\n\n private readGenesis(): Parser.Parser {\n if (this.config.genesisPath) {\n return fs.createReadStream(this.config.genesisPath).pipe(Parser.parser());\n }\n else {\n throw new Error(\"Genesis path not set\");\n }\n }\n\n private async setArrayReader(path: string, processor: (chunk: unknown) => Promise<void>): Promise<boolean> {\n const readPromise = new Promise<boolean>((resolve, reject) => {\n try {\n const filters = path.split(\".\");\n const pickers = filters.map(filter => Pick.pick({\n filter,\n }));\n let counter = 0;\n let chunkCounter = 0;\n\n // Wrapper processor that handles transaction chunking\n const chunkProcessor = async (data: unknown) => {\n chunkCounter++;\n this.log.debug(`Processing genesis chunk ${chunkCounter}`);\n\n await processor(data);\n\n // Commit and restart transaction every 5 chunks (5000 entries)\n // This prevents timeout on large genesis files\n if (chunkCounter % 5 === 0) {\n this.log.debug(`Committing transaction after chunk ${chunkCounter}`);\n await this.config.endTransaction(true);\n await this.config.beginTransaction();\n }\n };\n\n chain([\n this.readGenesis(),\n ...pickers,\n StreamArray.streamArray(),\n Batch.batch({\n batchSize: GENESIS_BATCH_SIZE,\n }),\n chunkProcessor,\n ])\n .on(\"data\",\n (data) => {\n if (data && Array.isArray(data)) {\n counter = counter + data.length;\n }\n })\n .on(\"end\",\n () => {\n this.log.info(`Processed ${counter} entries in ${chunkCounter} chunks`);\n resolve(true);\n });\n }\n catch (_e) {\n this.log.verbose(\"Error in setArrayReader: \" + _e);\n reject();\n }\n });\n\n return readPromise;\n }\n\n private async setValueReader(path: string, processor: (chunk: unknown) => Promise<void>): Promise<boolean> {\n const readPromise = new Promise<boolean>((resolve, reject) => {\n try {\n const filters = path.split(\".\");\n const pickers = filters.map(filter => Pick.pick({\n filter,\n }));\n\n let counter = 0;\n chain([this.readGenesis(), ...pickers, StreamValues.streamValues(), processor])\n .on(\"data\",\n (_data) => {\n counter++;\n })\n .on(\"end\",\n () => {\n this.log.info(`Processed ${counter} entries`);\n resolve(true);\n });\n }\n catch (_e) {\n reject();\n }\n });\n\n return readPromise;\n }\n\n private async parseGenesis() {\n this.log.info(\"Parsing genesis\");\n await this.config.beginTransaction();\n try {\n this.log.info(\"Starting genesis import\");\n this.log.debug(\"Importing genesis file...\");\n\n for (const [key, _value] of this.handled) {\n if (key.startsWith(\"genesis/\")) {\n const genesisEntry = key.split(\"/\");\n\n this.log.verbose(\"Importing \" + key + \"...\");\n if (genesisEntry[1] == \"array\") {\n await this.setArrayReader(genesisEntry[2],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async (data: any) => {\n await this.asyncEmit(key as never,\n {\n value: data.map((x: {\n value: never\n }) => x.value),\n } as never);\n return data;\n });\n }\n else {\n await this.setValueReader(genesisEntry[2],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async (data: any) => {\n await this.asyncEmit(key as never,\n {\n value: data.value,\n } as never);\n return data;\n });\n }\n }\n }\n\n this.log.info(\"Importing gen TXs...\");\n\n await this.setArrayReader(\"app_state.genutil.gen_txs\",\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async (data: any) => {\n for (let j = 0; j < data.length; j++) {\n const gentx = data[j].value;\n for (let i = 0; i < gentx.body.messages.length; i++) {\n const msg = gentx.body.messages[i];\n await this.asyncEmit((\"gentx\" + msg[\"@type\"]) as never,\n {\n value: msg,\n } as never);\n }\n }\n return data;\n });\n await this.config.endTransaction(true);\n\n this.log.info(\"Finished importing\");\n }\n catch (e) {\n try {\n await this.config.endTransaction(false);\n }\n catch (dbe) {\n this.prometheus?.recordError(\"database_error\");\n this.log.error(\"Error ending transaction. Must be a DB error: \" + dbe);\n }\n this.log.error(\"Failed to import genesis\");\n throw e;\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmEA,MAAa,uBAAuB;CAClC,aAAaA;CACb,WAAWC;CACX,SAAS,EAAE;CACX,qBAAqBD;CACrB,UAAU;CACV,YAAY;CACZ,iBAAiBE;CACjB,4BAA4B;CAC5B,SAAS;CACT,mBAAmB;CACnB,iBAAiBC;CACjB,kBAAkB;CAClB,gBAAgBC;CAChB,YAAY,QAAQ,SAAS;CAC7B,wBAAwB,QAAQ,SAAS;CACzC,iBAAiB,YAAqB,QAAQ,SAAS;CACxD;;;;;AAMD,IAAa,iBAAb,cAAoCC,6BAAe;;CAEjD,AAAO;;CAGP,AAAQ,UAAkC;;CAG1C,AAAQ,mBAA2C;;CAGnD,AAAQ,UAAmB;;CAG3B,AAAQ;;CAGR,AAAQ;;CAGR,AAAO;;CAGP,AAAQ,cAAc;;CAGtB,AAAO,aAAoC;;CAG3C,AAAQ,aAAa;;CAGrB,AAAO;;CAGP,AAAO;;CAGP,AAAO;;CAGP,AAAQ,eAAwB;;CAGhC,AAAQ,cAAc,EACpB,QAAQ,cACT;;CAGD,AAAQ,eAAoE;;CAG5E,AAAQ,eAAsC;;;;;CAM9C,YAAY,QAA8B;AACxC,SAAO;AAGP,8BAAY,OAAO,QAAQ,SAAS;AACpC,0CAAwB,OAAO,WAAW,YAAY;AAGtD,MAAI,OAAO,YACT,kCAAiB,OAAO,aAAa,cAAc;AAIrD,MAAI,OAAO,oBAAoB,OAC7B,8BAAa,OAAO,iBAAiB,kBAAkB;AAIzD,MAAI,OAAO,mBAAmB,OAC5B,8BAAa,OAAO,gBAAgB,iBAAiB;AAIvD,MAAI,OAAO,gBAAgB,OACzB,yCAAwB,OAAO,aAAa,cAAc;AAI5D,MAAI,OAAO,oBAAoB,OAC7B,yCAAwB,OAAO,iBAAiB,kBAAkB;AAGpE,OAAK,SAAS;GACZ,GAAG;GACH,GAAG;GACJ;EAGD,MAAM,EACJ,WACE,QAAQ;EAEZ,MAAM,gBAAgB,QAAQ,EAC5B,OAAO,SAAS,gBACZ;AACJ,UAAO,GAAG,UAAU,IAAI,MAAM,aAAa,CAAC,MAAM;IAClD;AACF,OAAK,MAAM,QAAQ,aAAa;GAC9B,OAAO,KAAK,OAAO;GACnB,aAAa,EACX,SAAS,mBACV;GACD,YAAY;IACV,IAAI,QAAQ,WAAW,KAAK;KAC1B,UAAU;KACV,OAAO;KACR,CAAC;IACF,IAAI,QAAQ,WAAW,KAAK,EAC1B,UAAU,gBACX,CAAC;IACF,IAAI,QAAQ,WAAW,QAAQ,EAC7B,QAAQ,QAAQ,OAAO,QAAQ,QAAQ,OAAO,OAAO,EACnD,QAAQ,OAAO,WAAW,EAC1B,eACA,QAAQ,OAAO,SAAS,EACtB,KAAK,MACN,CAAC,CAAC,EACN,CAAC;IACH;GACF,CAAC;EAIF,MAAM,qBAAqB,MAAe;AACxC,QAAK,YAAY,YAAY,cAAc;AAC3C,QAAK,IAAI,MAAM,kCAAkC,EAAE;;AAGrD,MAAI,KAAK,OAAO,QAEd,MAAK,aAAa,IAAIC,+BAAsD,KAAK,OAAO,WAAW,kBAAkB;MAIrH,MAAK,aAAa,IAAIA,+BAAkE,KAAK,OAAO,WAAW,kBAAkB;AAGnI,OAAK,GAAG,eACL,QAAQ;AACP,OAAI,IAAI,MAAM;AACZ,SAAK,IAAI,QAAQ,sBAAsB,IAAI,KAAK;AAChD,SAAK,KAAK,QACR;KACE,QAAQ;KACR,MAAM,IAAI;KACX,CAAC;;IAEN;AACJ,MAAI,KAAK,OAAO,kBAAkB;AAChC,QAAK,aAAa,IAAIC,gCAAgB;AACtC,QAAK,wCAA2B,EAC9B,QAAQ,OACT,CAAC;AACF,QAAK,iBAAiB,IAAI,YACxB,OAAO,MAAM,QAAQ;AACnB,QAAI,OAAO,gBAAgB,KAAK,WAAY,SAAS,YAAY;AACjE,QAAI,KAAK,MAAM,KAAK,WAAY,YAAY,CAAC;KAEhD;GAED,MAAM,iBAAiB,KAAK,OAAO,mBAC7B,QAAQ,IAAI,kBAAkB,SAAS,QAAQ,IAAI,iBAAiB,GAAG,GAAGH;AAChF,QAAK,iBAAiB,OAAO;IAC3B,MAAM;IACN,MAAM;IACP,GACA,QAAQ;AACP,QAAI,KAAK;AACP,UAAK,IAAI,MAAM,uBAAuB,IAAI;AAC1C,UAAK,YAAY,YAAY,iBAAiB;AAC9C,UAAK,KAAK,eAAe;MACvB,OAAO;MACP,SAAS;MACV,CAAC;;KAEJ;;AAEJ,MAAI,KAAK,OAAO,mBAAmB;AACjC,QAAK,+BAAkB,EACrB,QAAQ,OACT,CAAC;AACF,QAAK,QAAQ,IAAI,WACf,OAAO,UAAU,UAAU;IACzB,MAAM,OAAO,KAAK,YAAY,UAAU,OACpC,MACA;AACJ,UAAM,KAAK,KAAK,CAAC,KAAK,KAAK,YAAY;KACvC;GACJ,MAAM,aAAa,KAAK,OAAO,oBACzB,QAAQ,IAAI,oBAAoB,SAAS,QAAQ,IAAI,mBAAmB,GAAG,GAAGD;AACpF,QAAK,QAAQ,OAAO;IAClB,MAAM;IACN,MAAM;IACP,GACA,QAAQ;AACP,QAAI,KAAK;AACP,UAAK,IAAI,MAAM,gCAAgC,IAAI;AACnD,UAAK,YAAY,YAAY,sBAAsB;AACnD,UAAK,KAAK,eAAe;MACvB,OAAO;MACP,SAAS;MACV,CAAC;;KAEJ;;;CAIN,AAAQ,UAAU,QAAgB;AAChC,OAAK,YAAY,SAAS;;CAG5B,AAAQ,gBAAgB,EACtB,OAAO,SAID;AACJ,OAAK,iBAAiB,KAAK,OAAO,OAAO;IAE5C;CAED,AAAQ,UAAU,aAA2D;AAC3E,MAAI,KAAK,OAAO,QACd,QAAO;MAGP,QAAO;;CAIX,MAAa,UAAU;AACrB,MAAI;AACF,OAAI,KAAK,UAAU,KAAK,cAAc;AACpC,SAAK,IAAI,QAAQ,wDAAwD;AACzE,SAAK,OAAO,YAAY;AACxB,SAAK,YAAY,YAAY;AAC7B,SAAK,IAAI,QAAQ,wBAAwB;;AAE3C,QAAK,SAAS,gDAAmB,KAAK,OAAO,OAAO;AACpD,QAAK,IAAI,KAAK,sCAAsC;AAEpD,QAAK,cAAc,gDAAmB,KAAK,OAAO,OAAO;AACzD,QAAK,IAAI,KAAK,8CAA8C;AAE5D,UAAO;WAEF,OAAO;AACZ,QAAK,IAAI,MAAM,2BAA2B,MAAM;AAChD,QAAK,YAAY,YAAY,oBAAoB;AACjD,QAAK,eAAe;AACpB,UAAO;;;CAIX,AAAO,OAAO;AACZ,OAAK,UAAU;;CAGjB,MAAa,QAAQ;AACnB,OAAK,UAAU;AACf,MAAI,KAAK,YAAY;AACnB,QAAK,WAAW,OAAO;AACvB,QAAK,IAAI,QAAQ,iCAAiC;;AAEpD,MAAI,CAAC,KAAK,aAAa;AACrB,OAAI;AACF,QAAI,KAAK,OAAO,KACd,OAAM,KAAK,OAAO,MAAM;YAGrB,GAAG;AACR,SAAK,IAAI,MAAM,mCAAmC,EAAE;AAEpD,SAAK,YAAY,YAAY,aAAa;AAC1C,SAAK,UAAU,SAAS;AACxB,UAAM;;AAER,OAAI,MAAM,KAAK,OAAO,sBAAsB,CAC1C,KAAI;AACF,QAAI,KAAK,OAAO,YACd,OAAM,KAAK,cAAc;YAGtB,GAAG;AACR,SAAK,IAAI,MAAM,8BAA8B,EAAE;AAE/C,SAAK,YAAY,YAAY,gBAAgB;AAC7C,SAAK,UAAU,SAAS;AACxB,UAAM;;AAGV,QAAK,cAAc;;AAErB,MAAI;AACF,SAAM,KAAK,SAAS;AACpB,OAAI,CAAC,KAAK,OAAO,cAAc,KAAK,cAAc;AAChD,SAAK,aAAa,eAAe,KAAK,cAAc;AACpD,SAAK,eAAe;AACpB,SAAK,IAAI,QAAQ,mDAAmD;;AAEtE,OAAI,CAAC,KAAK,OAAO,WACf,MAAK,eAAe,KAAK,OAAO,oBAC5B,KAAK,OAAO,mBAAmB,GAC/B;AAGN,QAAK,gBADU,MAAM,KAAK,OAAO,QAAQ,EACd,SAAS;AACpC,QAAK,IAAI,KAAK,2BAA2B,KAAK,aAAa;AAE3D,QAAK,kBAAkB,MAAM,KAAK,OAAO,eAAe;AACxD,OAAI,KAAK,OAAO,WACd,MAAK,cAAc;YAGf,KAAK,aACP,MAAK,aAAa,YAAY,KAAK,cAAc;QAE9C;AACH,SAAK,YAAY,YAAY,qBAAqB;AAClD,UAAM,IAAI,MAAM,oCAAoC;;WAInD,GAAG;AACR,QAAK,IAAI,MAAM,uCAAuC,EAAE;AACxD,QAAK,YAAY,YAAY,wBAAwB;AACrD,QAAK,UAAU,SAAS;AACxB,SAAM;;AAER,OAAK,IAAI,MAAM,gCAAgC;AAC/C,OAAK,eAAe;AACpB,OAAK,SAAS,CAAC,OAAO,MAAM;AAC1B,QAAK,UAAU,SAAS;AAExB,QAAK,YAAY,YAAY,iBAAiB;AAC9C,SAAM,IAAI,MAAM,gCAAgC,EAAE;IAClD;EAEF,MAAM,SAAS,QAAQ,QAAQ;EAC/B,IAAI,KAAK,OAAO,KAAK,MAAU,OAAO,KAAK;AAC3C,SAAO,KAAK,WAAW,MAAM,GAAG,KAAK,CAAC,KAAK,gBAAgB,KAAK,YAAY,KAAK,OAAO,cAAc,UAAa,KAAK,mBAAmB,KAAK,OAAO,YAAY;AACjK,OAAI,KAAK,OAAO,iBACd,MAAK,WAAY,iBAAiB,KAAK,WAAW;AAGpD,OAAI;AACF,QAAI,KAAK,aACP,OAAM,IAAI,MAAM,yDAAyD;AAG3E,UAAM,KAAK,OAAO,kBAAkB;AACpC,SAAK,IAAI,MAAM,gBAAgB;IAC/B,IAAI,QAAQ;AACZ,QAAI,KAAK,UAAU,KAAK,WAAW,EAAE;KACnC,MAAMK,iBAA6D,IAAI,SAAS,SAAS,WAAW;AAClG,iBAAW,QAAQC,4CAA0B,EAAE,CAAC;OAChD;KACF,MAAM,YAAY,MAAM,QAAQ,KAAK,CAAC,KAAK,WAAW,SAAS,EAAE,eAAe,CAAC;AACjF,UAAK,IAAI,MAAM,uBAAuB;AACtC,SAAI,CAAC,aAAa,CAAC,UAAU,MAAM,CAAC,UAAU,IAAI;AAChD,WAAK,YAAY,YAAY,YAAY;AACzC,YAAM,IAAI,MAAM,wBAAwB;;AAE1C,cAAS,UAAU,GAAG,MAAM,OAAO;AACnC,uEAAqC,UAAU,GAAG,MAAM,OAAO,KAAK;AACpE,WAAM,KAAK,aAAa,UAAU,IAChC,UAAU,GAAG;WAEZ;KACH,MAAMD,iBAA6D,IAAI,SAAS,SAAS,WAAW;AAClG,iBAAW,QAAQC,4CAA0B,EAAE,CAAC;OAChD;KACF,MAAM,YAAY,MAAM,QAAQ,KAAK,CAAC,KAAK,WAAW,SAAS,EAAE,eAAe,CAAC;AACjF,UAAK,IAAI,MAAM,uBAAuB;AACtC,SAAI,CAAC,aAAa,CAAC,UAAU,MAAM,CAAC,UAAU,MAAM,CAAC,UAAU,IAAI;AACjE,WAAK,YAAY,YAAY,YAAY;AACzC,YAAM,IAAI,MAAM,wBAAwB;;AAG1C,UAAK,IAAI,MAAM,gBAAgB;AAC/B,cAAS,UAAU,GAAG,MAAM,OAAO;AACnC,uEAAqC,UAAU,GAAG,MAAM,OAAO,KAAK;AACpE,WAAM,KAAK,aAAa,UAAU,IAChC,UAAU,IACVC,qEAAwB,OAAO,UAAU,GAAG,CAAC,WAAW;;AAG5D,QAAI,SAASC,qCAAmB,SAAS,GAAG;KAC1C,MAAMC,WAAS,QAAQ,QAAQ;KAC/B,MAAM,QAAQA,SAAO,KAAK,MAAUA,SAAO,KAAK;KAChD,MAAM,WAAW,QAAQ;AACzB,UAAK;KACL,MAAM,OAAO,MAAa;AAC1B,UAAK,IAAI,KAAK,gBAAgB,KAAK,QAAQ,EAAE,GAAG,aAAa;AAC7D,WAAM,KAAK,UAAU,iBACnB;MACE,OAAO;MACP;MACA;MACD,CAAC;;AAEN,QAAI,SAASD,qCAAmB,UAAU,EACxC,OAAM,KAAK,UAAU,gBACnB;KACE,OAAO;KACP;KACA;KACD,CAAC;AAEN,QAAI,SAASA,qCAAmB,SAAS,EACvC,OAAM,KAAK,UAAU,eACnB;KACE,OAAO;KACP;KACA;KACD,CAAC;AAEN,SAAK,IAAI,MAAM,0BAA0B;AAEzC,UAAM,KAAK,OAAO,eAAe,KAAK;AAEtC,SAAK,IAAI,MAAM,kBAAkB;YAE5B,GAAG;AACR,SAAK,YAAY,YAAY,yBAAyB;AACtD,SAAK,IAAI,MAAM,6BAA6B,EAAE;AAC9C,SAAK,UAAU,SAAS;AACxB,QAAI;AACF,WAAM,KAAK,OAAO,eAAe,MAAM;aAElC,KAAK;AACV,UAAK,YAAY,YAAY,WAAW;AACxC,UAAK,IAAI,MAAM,mDAAmD,IAAI;;AAExE,SAAK,eAAe;AACpB,SAAK;AACL;;AAEF,QAAK,aAAa;AAClB,QAAK,UAAU,KAAK;;AAEtB,MAAI,KAAK,OAAO,cAAc,UAAa,KAAK,mBAAmB,KAAK,OAAO,WAAY;AACzF,QAAK,IAAI,KAAK,mDAAmD;AACjE,QAAK,MAAM;;AAEb,MAAI,KAAK,QACP,KAAI,KAAK,aAAa,GAAG;AACvB,QAAK,IAAI,MAAM,yBAAyB,KAAK,WAAW;AACxD,QAAK,IAAI,KAAK,wBAAwB;AACtC,oBAAiB,KAAK,OAAO,EAC3B,KAAK,aAAa,IAAK;SAEtB;AACH,QAAK,IAAI,KAAK,0CAA0C;AACxD,QAAK,KAAK,eAAe;IACvB,uBAAO,IAAI,MAAM,8BAA8B;IAC/C,SAAS;IACT,YAAY,KAAK;IAClB,CAAC;;;CAKR,AAAO,YAAyD,OAC9D,MACA,UACG;AACH,QAAM,qBAAe;EAQrB,IAAI,gBAAgB,KAAK,QAAQ,IAAI,KAAK;AAC1C,MAAI,CAAC,cAEH,iBAAgB;EAElB,IAAI,qBAAqB;EACzB,MAAM,OAAO,IAAI,SAAe,SAAS,WAAW;GAClD,MAAM,cAAc,OAAkB;AACpC,QAAI,GAAG,QAAQ,MAAM,KACnB,KAAI,GAAG,QAAQ;AACb;AACA,SAAI,sBAAsB,eAAe;AAEvC,WAAK,IAAI,QACP,WAAW;AACb,eAAS;;UAKX,QAAO,GAAG,MAAM;;AAItB,QAAK,GAAG,QACN,WAAW;IACb;AACF,OAAK,KAAK,MACR,MAAM;AAER,SAAO;;CAGT,MAAc,aAAa,OAAsB,eAA8D,YAA0B;EACvI,IAAIE,eAAiC,CAAC,GAAG,EAAE;AAC3C,MAAI,KAAK,OAAO,YAAY,QAC1B,gBAAe,QAAQ,QAAQ;EAEjC,IAAI;AACJ,MAAI,KAAK,OAAO,iBACd,YAAW,KAAK,WAAY,qBAAqB;EAEnD,MAAM,SAAS,MAAM,MAAM,OAAO;AAClC,OAAK,kBAAkB;AACvB,OAAK,IAAI,MAAM,wBACb,OAAO;EAET,MAAM,kEAAqC,MAAM,MAAM,OAAO,KAAK;AAQnE,QAAM,KAAK,UAAU,SACnB;GACE,OAAO;IACL;IACA;IACD;GACD;GACA;GACD,CAAC;AACJ,OAAK,IAAI,MAAM,8BAA8B;EAE7C,IAAIC;EACJ,IAAIC;AACJ,MAAK,cAAyC,qBAAqB;AACjE,sBAAoB,cAAyC,oBAAoB,QAAO,MAAK,EAAE,WAAW,MAAK,MAAKC,wBAAW,EAAE,IAAI,IAAI,UAAUA,wBAAW,EAAE,MAAM,IAAI,cAAc,CAAC;AACzL,oBAAkB,cAAyC,oBAAoB,QAAO,MAAK,EAAE,WAAW,MAAK,MAAKA,wBAAW,EAAE,IAAI,IAAI,UAAUA,wBAAW,EAAE,MAAM,IAAI,YAAY,CAAC;SAElL;AACH,sBAAoB,cAAuC;AAC3D,oBAAkB,cAAuC;;AAG3D,QAAM,KAAK,UAAU,eACnB;GACE,OAAO;IACL,QAAQ;IACR;IACD;GACD;GACA;GACD,CAAC;AAEJ,OAAK,IAAI,MAAM,qCAAqC;AAGpD,QAAM,KAAK,UAAU,aACnB;GACE,OAAO,cAAc;GACrB;GACA;GACD,CAAC;AACJ,OAAK,IAAI,MAAM,4BAA4B;AAG3C,OAAK,IAAI,IAAI,GAAG,IAAI,MAAM,MAAM,IAAI,QAAQ,KAAK;GAC/C,MAAM,KAAKC,wCAAG,OAAO,MAAM,MAAM,IAAI,GAAG;GAExC,MAAM,SAAS,cAAc,QAAQ,GAAG;GACxC,MAAM,QAAQ,cAAc,QAAQ,GAAG;AAEvC,OAAI,UAAU,EAEZ;AAEF,OAAI,GAAG,QAAQ,GAAG,KAAK,QAAQ,IAAI;IACjC,MAAM,gCAAoB,SAAS,CAAC,OAAO,MAAM,MAAM,IAAI,GAAG,CAC3D,OAAO,MAAM;AAChB,UAAM,KAAK,UAAU,WACnB;KACE,OAAO;MACL;MACA,QAAQ,GAAG;MACZ;KACD;KACA;KACD,CAAC;;GAGN,IAAIC,SAGC,QACD,KAAK,MAAM,MAAM,GACjB,EAAE;AACN,OAAI,OAAO,UAAU,GAAG;IACtB,MAAMC,cAA6B,EAAE;AACrC,SAAK,IAAI,MAAM,0DAA0D;AACzE,SAAK,IAAI,IAAI,GAAG,IAAI,cAAc,QAAQ,GAAG,OAAO,QAAQ,IAC1D,KAAI,cAAc,QAAQ,GAAG,OAAO,GAAG,WAAW,MAAK,MAAKH,wBAAW,EAAE,IAAI,IAAI,YAAY,EAAE;KAC7F,MAAM,KAAKA,wBAAW,cAAc,QAAQ,GAAG,OAAO,GAAG,WAAW,MAAK,MAAKA,wBAAW,EAAE,IAAI,IAAI,YAAY,EAAE,SAAS,GAAG;AAC7H,SAAI,MAAM,IAAI;MACZ,MAAM,QAAQ,SAAS,GAAG;MAC1B,IAAI,KAAK,YAAY,MAAK,MAAK,EAAE,aAAa,MAAM;AACpD,UAAI,CAAC,IAAI;AACP,YAAK;QACH,WAAW;QACX,QAAQ,CAAC,cAAc,QAAQ,GAAG,OAAO,GAAG;QAC7C;AACD,mBAAY,KAAK,GAAG;YAGpB,IAAG,OAAO,KAAK,cAAc,QAAQ,GAAG,OAAO,GAAY;;;AAKnE,aAAS,OAAO,OAAO,YAAY;;GAErC,MAAM,OAAO,GAAG,MAAM;AAEtB,OAAI,KACF,MAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,SAAK,IAAI,MAAM,4CAA4C,KAAK,GAAG,QAAQ;IAC3E,MAAM,YACF,KAAK,SAAS,IACZ,OAAO,MAAK,MAAK,EAAE,aAAa,EAAE,EAAE,SACpC,OAAO,GAAG;AAChB,UAAM,KAAK,UAAU,KAAK,GAAG,SAC3B;KACE,OAAO;MACL,IAAI,KAAK,GAAG;MACZ,QAAQ;MACT;KACD;KACA;KACD,CAAC;AACJ,QAAI,KAAK,GAAG,WAAW,iCAAiC;KACtD,MAAM,YAAYI,gDAAQ,OAAO,KAAK,GAAG,MAAM,CAAC;AAChD,SAAI,UACF,MAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,WAAK,IAAI,MAAM,4CAA4C,UAAU,GAAG,QAAQ;MAChF,MAAM,iBAAiB,WAAW,QAAQ,UAAQ,QAAQ;AACxD,WAAI,IAAI,WAAW,QAAO,MAAKJ,wBAAW,EAAE,IAAI,IAAI,qBAAqBA,wBAAW,EAAE,MAAM,IAAI,KAAK,EAAE,CAAC,SAAS,EAC/G,UAAO,KAAK,IAAI;AAElB,cAAOK;SAET,EAAE,CAAwB;AAC1B,YAAM,KAAK,UAAU,UAAU,GAAG,SAChC;OACE,OAAO;QACL,IAAI,UAAU,GAAG;QACjB,QAAQ;QACT;OACD;OACA;OACD,CAAC;;;;;AAOhB,OAAK,IAAI,MAAM,6BAA6B;AAC5C,MAAI,KAAK,OAAO,iBACd,MAAK,WAAY,mBAAmB,MAAM,MAAM,IAAI,OAAO;AAG7D,QAAM,KAAK,UAAU,aACnB;GACE,OAAO;GACP;GACA;GACD,CAAC;AACJ,OAAK,IAAI,MAAM,mCAAmC;AAClD,MAAI,KAAK,OAAO,YAAY,SAAS;GACnC,MAAM,aAAa,QAAQ,OAAO,aAAa;GAC/C,MAAM,cAAc,WAAW,KAAK,MAAO,WAAW,KAAK;AAC3D,QAAK,IAAI,MAAM,+BACb,QACA,YAAY,QAAQ,EAAE,CAAC;;AAG3B,MAAI,KAAK,OAAO,iBACd,WAAW;AAEb,MAAI,KAAK,OAAO,iBACd,MAAK,WAAY,mBAAmB,QAAQ,KAAK,cAAc,KAAK,WAAW,MAAM,CAAC;;CAI1F,MAAc,UAAU;AACtB,OAAK,IAAI,IAAI,KAAK,iBAAiB,KAAK,KAAK,cAAc,KAAK;AAC9D,QAAK,IAAI,MAAM,eAAe,EAAE;AAChC,OAAI,KAAK,cAAc;AACrB,SAAK,IAAI,QAAQ,sDAAsD;AACvE;;AAEF,OAAI;AACF,QAAI,KAAK,UAAU,KAAK,WAAW,EAAE;KACnC,MAAMC,iBAAiE,IAAI,SAAS,SAAS,WAAW;AACtG,iBAAW,QACTC,kCACA,MAAM;OACR;KACF,MAAM,UAAU,QAAQ,KAAK,CAAC,QAAQ,IAAI,CAAC,KAAK,YAAY,MAAM,EAAE,EAA4B,KAAK,YAAY,aAAa,EAAE,CAAkC,CAAC,EAAE,eAAe,CAAC,CAAC,OAAO,MAAM;AACjM,WAAK,IAAI,MAAM,2BAA2B,IAAI,QAAQ,EAAE;AACxD,WAAK,eAAe;AACpB,aAAO,QAAQ,QAAQ,EAAE,CAAC;OAC1B;AACF,UAAK,WAAW,QAAQ,QAAQ;WAE7B;KACH,MAAMC,iBAA6E,IAAI,SAAS,SAAS,WAAW;AAClH,iBAAW,QACTD,kCACA,MAAM;OACR;KACF,MAAM,IAAIE,oEAAuB,YAAY,EAC3C,YAAY,EACV,OAAOC,oCAAkB,YAC1B,EACF,CAAC;KACF,MAAM,OAAOD,oEAAuB,OAAO,EAAE,CAAC,QAAQ;KACtD,MAAM,UAAU,QAAQ,KAAK,CAC3B,QAAQ,IAAI;MACV,KAAK,YAAY,MAAM,EAAE;MACzB,KAAK,YAAY,aAAa,EAAE;MAChC,KAAK,SAAS,4CACZ,MACA,GACA,MAAM;MACT,CAAC,EACF,eACD,CAAC,CAAC,OAAO,MAAM;AACd,WAAK,IAAI,MAAM,2BAA2B,IAAI,QAAQ,EAAE;AACxD,WAAK,eAAe;AACpB,aAAO,QAAQ,QAAQ,EAAE,CAAC;OAC1B;AACF,UAAK,WAAW,QAAQ,QAAQ;;AAElC,UAAM,KAAK,WAAW,UAAU;AAChC,QAAI,KAAK,cAAc;AACrB,UAAK;AACL,WAAM,IAAI,MAAM,qBAAqB;;YAGlC,GAAG;AACR,SAAK,IAAI,MAAM,qBAAqB,EAAE;AACtC;;;AAGJ,MAAI,CAAC,KAAK,cAAc;AACtB,QAAK,WAAW,WAAW;AAC3B,QAAK,IAAI,KAAK,0BAA0B;;;CAI5C,MAAa,SAAS,MAAc,MAAkB,QAAiB,QAAiB,MAA2B;AACjH,MAAI;GACF,MAAM,WAAW,KAAK,YAAY,YAAY,KAAK,IAAI,KAAK;GAC5D,MAAM,QAAQ,OACb,QACG,KAAK,SACL,KAAK,aAAa,UAAU;IAC9B;IACA;IACQ;IACT,CAAC;AACF,eAAY;AACZ,OAAI,MACF,QAAO,MAAM;QAEV;AACH,SAAK,eAAe;AACpB,SAAK,UAAU,SAAS;AACxB,SAAK,YAAY,YAAY,mBAAmB;AAChD,UAAM,IAAI,MAAM,mCAAmC,KAAK;;WAGrD,IAAI;AACT,QAAK,eAAe;AACpB,QAAK,UAAU,SAAS;AACxB,QAAK;AACL,SAAM,IAAI,MAAM,mCAAmC,KAAK;;;CAI5D,AAAQ,iBAAiB,QAAsB;AAC7C,MAAI,KAAK,aACP,cAAa,KAAK,aAAa;AAEjC,OAAK,eAAe,iBAAiB;AACnC,QAAK,eAAe;KACnB,IAAM;AACT,OAAK,IAAI,KAAK,0BACZ,OAAO;AACT,MAAI,UAAU,KAAK,aACjB;AAGF,MAAI,KAAK,WAAW,UAAU,CAAC,KAAK,cAAc;AAChD,QAAK,eAAe;AACpB,OAAI,KAAK,WAAW,MAAM,GAAG,KAAK,KAAK,OAAO,WAAW;AACvD,SAAK,YAAY,YAAY,mBAAmB;AAChD,SAAK,IAAI,MAAM,4CAA4C;AAC3D,SAAK,eAAe;AACpB,SAAK;AACL;;AAEF,OAAI;AACF,QAAI,KAAK,UAAU,KAAK,WAAW,CACjC,MAAK,WAAW,QAAQ,QAAQ,IAAI,CAAC,KAAK,OAAO,MAAM,OAAO,EAA4B,KAAK,OAAO,aAAa,OAAO,CAAkC,CAAC,CAAC,OAAO,MAAM;AACzK,UAAK,IAAI,MAAM,2BAA2B,SAAS,QAAQ,EAAE;AAE7D,YAAO,QAAQ,QAAQ,EAAE,CAAC;MAC1B,CAAmD;SAElD;KACH,MAAM,IAAIA,oEAAuB,YAAY,EAC3C,YAAY,EACV,OAAO,OACR,EACF,CAAC;KACF,MAAM,OAAOA,oEAAuB,OAAO,EAAE,CAAC,QAAQ;AACtD,UAAK,WAAW,QAAQ,QAAQ,IAAI;MAClC,KAAK,OAAO,MAAM,OAAO;MACzB,KAAK,OAAO,aAAa,OAAO;MAChC,KAAK,SAAS,4CACZ,MACA,QACA,MAAM;MACT,CAAC,CAAC,OAAO,MAAM;AACd,WAAK,IAAI,MAAM,2BAA2B,SAAS,QAAQ,EAAE;AAC7D,aAAO,QAAQ,QAAQ,EAAE,CAAC;OAC1B,CAA+D;;YAG9D,GAAG;AACR,SAAK,IAAI,MAAM,+BAA+B,EAAE;;QAIlD,MAAK,eAAe;;CAIxB,MAAc,eAAe;AAC3B,MAAI;GACF,MAAM,SAAS,MAAM,KAAK,OAAO,QAAQ;AACzC,OAAI,OAAO,SAAS,oBAAoB,KAAK,aAC3C,QAAO,KAAK,eAAe,OAAO,SAAS,kBACzC,MAAK,iBAAiB,KAAK,eAAe,EAAE;AAGhD,oBAAiB;AACf,SAAK,cAAc;MAErB,KAAK,OAAO,gBAAgB;WAEvB,GAAG;AACR,QAAK,IAAI,MAAM,kCAAkC,EAAE;AACnD,QAAK,eAAe;AACpB,QAAK;;;CAIT,AAAQ,cAA6B;AACnC,MAAI,KAAK,OAAO,YACd,QAAO,GAAG,iBAAiB,KAAK,OAAO,YAAY,CAAC,KAAKE,oBAAO,QAAQ,CAAC;MAGzE,OAAM,IAAI,MAAM,uBAAuB;;CAI3C,MAAc,eAAe,MAAc,WAAgE;AAqDzG,SApDoB,IAAI,SAAkB,SAAS,WAAW;AAC5D,OAAI;IAEF,MAAM,UADU,KAAK,MAAM,IAAI,CACP,KAAI,WAAUC,oCAAK,KAAK,EAC9C,QACD,CAAC,CAAC;IACH,IAAI,UAAU;IACd,IAAI,eAAe;IAGnB,MAAM,iBAAiB,OAAO,SAAkB;AAC9C;AACA,UAAK,IAAI,MAAM,4BAA4B,eAAe;AAE1D,WAAM,UAAU,KAAK;AAIrB,SAAI,eAAe,MAAM,GAAG;AAC1B,WAAK,IAAI,MAAM,sCAAsC,eAAe;AACpE,YAAM,KAAK,OAAO,eAAe,KAAK;AACtC,YAAM,KAAK,OAAO,kBAAkB;;;AAIxC,4BAAM;KACJ,KAAK,aAAa;KAClB,GAAG;KACHC,6CAAY,aAAa;KACzBC,mCAAM,MAAM,EACV,WAAWC,sCACZ,CAAC;KACF;KACD,CAAC,CACC,GAAG,SACD,SAAS;AACR,SAAI,QAAQ,MAAM,QAAQ,KAAK,CAC7B,WAAU,UAAU,KAAK;MAE3B,CACH,GAAG,aACI;AACJ,UAAK,IAAI,KAAK,aAAa,QAAQ,cAAc,aAAa,SAAS;AACvE,aAAQ,KAAK;MACb;YAED,IAAI;AACT,SAAK,IAAI,QAAQ,8BAA8B,GAAG;AAClD,YAAQ;;IAEV;;CAKJ,MAAc,eAAe,MAAc,WAAgE;AAyBzG,SAxBoB,IAAI,SAAkB,SAAS,WAAW;AAC5D,OAAI;IAEF,MAAM,UADU,KAAK,MAAM,IAAI,CACP,KAAI,WAAUH,oCAAK,KAAK,EAC9C,QACD,CAAC,CAAC;IAEH,IAAI,UAAU;AACd,4BAAM;KAAC,KAAK,aAAa;KAAE,GAAG;KAASI,8CAAa,cAAc;KAAE;KAAU,CAAC,CAC5E,GAAG,SACD,UAAU;AACT;MACA,CACH,GAAG,aACI;AACJ,UAAK,IAAI,KAAK,aAAa,QAAQ,UAAU;AAC7C,aAAQ,KAAK;MACb;YAED,IAAI;AACT,YAAQ;;IAEV;;CAKJ,MAAc,eAAe;AAC3B,OAAK,IAAI,KAAK,kBAAkB;AAChC,QAAM,KAAK,OAAO,kBAAkB;AACpC,MAAI;AACF,QAAK,IAAI,KAAK,0BAA0B;AACxC,QAAK,IAAI,MAAM,4BAA4B;AAE3C,QAAK,MAAM,CAAC,KAAK,WAAW,KAAK,QAC/B,KAAI,IAAI,WAAW,WAAW,EAAE;IAC9B,MAAM,eAAe,IAAI,MAAM,IAAI;AAEnC,SAAK,IAAI,QAAQ,eAAe,MAAM,MAAM;AAC5C,QAAI,aAAa,MAAM,QACrB,OAAM,KAAK,eAAe,aAAa,IAErC,OAAO,SAAc;AACnB,WAAM,KAAK,UAAU,KACnB,EACE,OAAO,KAAK,KAAK,MAEX,EAAE,MAAM,EACf,CAAU;AACb,YAAO;MACP;QAGJ,OAAM,KAAK,eAAe,aAAa,IAErC,OAAO,SAAc;AACnB,WAAM,KAAK,UAAU,KACnB,EACE,OAAO,KAAK,OACb,CAAU;AACb,YAAO;MACP;;AAKV,QAAK,IAAI,KAAK,uBAAuB;AAErC,SAAM,KAAK,eAAe,6BAExB,OAAO,SAAc;AACnB,SAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;KACpC,MAAM,QAAQ,KAAK,GAAG;AACtB,UAAK,IAAI,IAAI,GAAG,IAAI,MAAM,KAAK,SAAS,QAAQ,KAAK;MACnD,MAAM,MAAM,MAAM,KAAK,SAAS;AAChC,YAAM,KAAK,UAAW,UAAU,IAAI,UAClC,EACE,OAAO,KACR,CAAU;;;AAGjB,WAAO;KACP;AACJ,SAAM,KAAK,OAAO,eAAe,KAAK;AAEtC,QAAK,IAAI,KAAK,qBAAqB;WAE9B,GAAG;AACR,OAAI;AACF,UAAM,KAAK,OAAO,eAAe,MAAM;YAElC,KAAK;AACV,SAAK,YAAY,YAAY,iBAAiB;AAC9C,SAAK,IAAI,MAAM,mDAAmD,IAAI;;AAExE,QAAK,IAAI,MAAM,2BAA2B;AAC1C,SAAM"}
1
+ {"version":3,"file":"index.cjs","names":["DEFAULT_START_HEIGHT","DEFAULT_BATCH_SIZE","DEFAULT_POLLING_INTERVAL_MS","DEFAULT_HEALTH_CHECK_PORT","DEFAULT_PROMETHEUS_PORT","EclesiaEmitter","CircularBuffer","IndexerMetrics","timeoutPromise: ReturnType<typeof this.blockQueue.dequeue>","QUEUE_DEQUEUE_TIMEOUT_MS","QueryValidatorsResponse","PERIODIC_INTERVALS","hrTime","processStart: [number, number]","beginBlockEvents: readonly Event[] | readonly Event38[]","endBlockEvents: readonly Event[] | readonly Event38[]","decodeAttr","Tx","events: Array<{\n msg_index?: number\n events: (Event | Event38)[]\n }>","eventsToAdd: typeof events","MsgExec","events","timeoutPromise: Promise<[BlockResponse, BlockResultsResponse]>","RPC_TIMEOUT_MS","timeoutPromise: Promise<[BlockResponse, BlockResultsResponse, Uint8Array]>","QueryValidatorsRequest","PAGINATION_LIMITS","Parser","Pick","StreamArray","Batch","GENESIS_BATCH_SIZE","StreamValues"],"sources":["../../src/indexer/index.ts"],"sourcesContent":["/* eslint-disable @stylistic/no-multi-spaces */\n/* eslint-disable max-lines */\nimport {\n createHash,\n} from \"node:crypto\";\nimport * as fs from \"node:fs\";\n\nimport {\n BlockResponse, BlockResultsResponse, CometClient, connectComet, Event, toRfc3339WithNanoseconds,\n} from \"@cosmjs/tendermint-rpc\";\nimport {\n BlockResultsResponse as BlockResultsResponse38, Event as Event38,\n} from \"@cosmjs/tendermint-rpc/build/comet38/responses.js\";\nimport {\n MsgExec,\n} from \"cosmjs-types/cosmos/authz/v1beta1/tx.js\";\nimport {\n QueryValidatorsRequest,\n QueryValidatorsResponse,\n} from \"cosmjs-types/cosmos/staking/v1beta1/query.js\";\nimport {\n Validator,\n} from \"cosmjs-types/cosmos/staking/v1beta1/staking.js\";\nimport {\n Tx,\n} from \"cosmjs-types/cosmos/tx/v1beta1/tx.js\";\nimport Fastify, {\n FastifyInstance,\n} from \"fastify\";\nimport {\n chain,\n} from \"stream-chain\";\nimport Parser from \"stream-json\";\nimport Pick from \"stream-json/filters/Pick.js\";\nimport StreamArray from \"stream-json/streamers/StreamArray.js\";\nimport StreamValues from \"stream-json/streamers/StreamValues.js\";\nimport Batch from \"stream-json/utils/Batch.js\";\nimport {\n v4 as uuidv4,\n} from \"uuid\";\nimport * as winston from \"winston\";\n\nimport {\n DEFAULT_BATCH_SIZE, DEFAULT_HEALTH_CHECK_PORT, DEFAULT_POLLING_INTERVAL_MS, DEFAULT_PROMETHEUS_PORT, DEFAULT_START_HEIGHT,\n GENESIS_BATCH_SIZE, PAGINATION_LIMITS, PERIODIC_INTERVALS, QUEUE_DEQUEUE_TIMEOUT_MS, RPC_TIMEOUT_MS,\n} from \"../constants.js\";\nimport {\n EclesiaEmitter,\n} from \"../emitter/index.js\";\nimport {\n IndexerMetrics,\n} from \"../metrics/index.js\";\nimport {\n CircularBuffer,\n} from \"../promise-queue/index.js\";\nimport {\n BlockQueue, EcleciaIndexerConfig, EmitFunc, MinimalBlockQueue,\n UUIDEvent, WithHeightAndUUID,\n} from \"../types/index.js\";\nimport {\n decodeAttr,\n} from \"../utils/index.js\";\nimport {\n validateFilePath, validatePort, validatePositiveInteger, validateUrl,\n} from \"../validation/index.js\";\n\n/** Default configuration for the Eclesia indexer */\nexport const defaultIndexerConfig = {\n startHeight: DEFAULT_START_HEIGHT, // Start indexing from block 1\n batchSize: DEFAULT_BATCH_SIZE, // Process blocks in batches of 500\n modules: [], // No modules enabled by default\n getNextHeight: () => DEFAULT_START_HEIGHT, // Default height retrieval function\n logLevel: \"info\" as EcleciaIndexerConfig[\"logLevel\"], // Default log level\n usePolling: false, // Use WebSocket subscription by default\n pollingInterval: DEFAULT_POLLING_INTERVAL_MS, // Poll every 5 seconds when polling enabled\n shouldProcessGenesis: () => false, // Skip genesis processing by default\n minimal: true, // Use minimal indexing by default\n enableHealthcheck: true, // Enable health check server by default\n healthCheckPort: DEFAULT_HEALTH_CHECK_PORT, // Default health check port\n enablePrometheus: false, // Disable Prometheus metrics server by default\n prometheusPort: DEFAULT_PROMETHEUS_PORT, // Default Prometheus metrics server port\n init: () => Promise.resolve(), // No-op initialization function\n beginTransaction: () => Promise.resolve(), // No-op transaction begin function\n endTransaction: (_status: boolean) => Promise.resolve(), // No-op transaction end function\n};\n\n/**\n * Core blockchain indexer that connects to Tendermint RPC and processes blocks\n * Extends EclesiaEmitter to provide event-driven architecture for modules\n */\nexport class EcleciaIndexer extends EclesiaEmitter {\n /** Indexer configuration settings */\n public config: EcleciaIndexerConfig;\n\n /** Fastify HTTP server for health checks */\n private fastify: FastifyInstance | null = null;\n\n /** Prometheus HTTP server instance */\n private prometheusServer: FastifyInstance | null = null;\n\n /** Indicates if the indexer has started */\n private started: boolean = false;\n\n /** Queue for managing block processing pipeline */\n private blockQueue: BlockQueue;\n\n /** Latest block height from the chain */\n private latestHeight!: number;\n\n /** Next block height to process */\n public heightToProcess!: number;\n\n /** Whether the indexer has been initialized */\n private initialized = false;\n\n /** Prometheus metrics server instance */\n public prometheus: IndexerMetrics | null = null;\n\n /** Number of retry attempts for error recovery */\n private retryCount = 0;\n\n /** CometBFT client for ad-hoc queries */\n public client!: CometClient;\n\n /** CometBFT client for block and validator queries */\n public blockClient!: CometClient;\n\n /** Winston logger instance */\n public log: winston.Logger;\n\n /** Flag indicating if indexer should attempt recovery */\n private tryToRecover: boolean = false;\n\n /** Health check status for monitoring */\n private healthCheck = {\n status: \"CONNECTING\",\n };\n\n /** WebSocket subscription for new block notifications */\n private subscription: ReturnType<CometClient[\"subscribeNewBlock\"]> | null = null;\n\n /** Timeout handler for block reception */\n private blockTimeout: NodeJS.Timeout | null = null;\n\n /**\n * Creates a new Eclesia indexer instance\n * @param config - Indexer configuration options\n */\n constructor(config: EcleciaIndexerConfig) {\n super();\n\n // Validate required configuration\n validateUrl(config.rpcUrl, \"rpcUrl\");\n validatePositiveInteger(config.batchSize, \"batchSize\");\n\n // Validate optional genesis path if processing genesis\n if (config.genesisPath) {\n validateFilePath(config.genesisPath, \"genesisPath\");\n }\n\n // Validate health check port if provided\n if (config.healthCheckPort !== undefined) {\n validatePort(config.healthCheckPort, \"healthCheckPort\");\n }\n\n // Validate prometheus port if provided\n if (config.prometheusPort !== undefined) {\n validatePort(config.prometheusPort, \"prometheusPort\");\n }\n\n // Validate start height if provided\n if (config.startHeight !== undefined) {\n validatePositiveInteger(config.startHeight, \"startHeight\");\n }\n\n // Validate polling interval if provided\n if (config.pollingInterval !== undefined) {\n validatePositiveInteger(config.pollingInterval, \"pollingInterval\");\n }\n\n this.config = {\n ...defaultIndexerConfig,\n ...config,\n };\n\n // Initialize logger first so it can be used by queue error handler\n const {\n printf,\n } = winston.format;\n\n const eclesiaFormat = printf(({\n level, message, timestamp,\n }) => {\n return `${timestamp} [${level.toUpperCase()}]:\\t${message}`;\n });\n this.log = winston.createLogger({\n level: this.config.logLevel,\n defaultMeta: {\n service: \"Eclesia Indexer\",\n },\n transports: [\n new winston.transports.File({\n filename: \"error.log\",\n level: \"error\",\n }),\n new winston.transports.File({\n filename: \"combined.log\",\n }),\n new winston.transports.Console({\n format: winston.format.combine(winston.format.splat(),\n winston.format.timestamp(),\n eclesiaFormat,\n winston.format.colorize({\n all: true,\n })),\n }),\n ],\n });\n\n // Initialize block queue based on minimal or full indexing mode\n // Pass error handler that uses the logger\n const queueErrorHandler = (e: unknown) => {\n this.prometheus?.recordError(\"rpc\");\n this.log.error(\"Error enqueueing block data: \" + e);\n };\n\n if (this.config.minimal) {\n // Minimal mode: only store block and block results\n this.blockQueue = new CircularBuffer<[BlockResponse, BlockResultsResponse]>(this.config.batchSize, queueErrorHandler);\n }\n else {\n // Full mode: also store validator information\n this.blockQueue = new CircularBuffer<[BlockResponse, BlockResultsResponse, Uint8Array]>(this.config.batchSize, queueErrorHandler);\n }\n\n this.on(\"_unhandled\",\n (msg) => {\n if (msg.uuid) {\n this.log.verbose(\"Unhandled event: \" + msg.type);\n this.emit(\"uuid\",\n {\n status: true,\n uuid: msg.uuid,\n });\n }\n });\n if (this.config.enablePrometheus) {\n this.prometheus = new IndexerMetrics();\n this.prometheusServer = Fastify({\n logger: false,\n });\n this.prometheusServer.get(\"/metrics\",\n async (_req, res) => {\n res.header(\"Content-Type\", this.prometheus!.registry.contentType);\n res.send(await this.prometheus!.getMetrics());\n },\n );\n\n const prometheusPort = this.config.prometheusPort\n ?? (process.env.PROMETHEUS_PORT ? parseInt(process.env.PROMETHEUS_PORT, 10) : DEFAULT_PROMETHEUS_PORT);\n this.prometheusServer.listen({\n port: prometheusPort,\n host: \"0.0.0.0\",\n },\n (err) => {\n if (err) {\n this.log.error(\"Prometheus error: \" + err);\n this.prometheus?.recordError(\"metrics_server\");\n this.emit(\"fatal-error\", {\n error: err,\n message: \"Failed to start metrics server\",\n });\n }\n });\n }\n if (this.config.enableHealthcheck) {\n this.fastify = Fastify({\n logger: false,\n });\n this.fastify.get(\"/health\",\n async (_request, reply) => {\n const code = this.healthCheck.status == \"OK\"\n ? 200\n : 503;\n reply.code(code).send(this.healthCheck);\n });\n const healthPort = this.config.healthCheckPort\n ?? (process.env.HEALTH_CHECK_PORT ? parseInt(process.env.HEALTH_CHECK_PORT, 10) : DEFAULT_HEALTH_CHECK_PORT);\n this.fastify.listen({\n port: healthPort,\n host: \"0.0.0.0\",\n },\n (err) => {\n if (err) {\n this.log.error(\"Health check server error: \" + err);\n this.prometheus?.recordError(\"health_check_server\");\n this.emit(\"fatal-error\", {\n error: err,\n message: \"Failed to start health check server\",\n });\n }\n });\n }\n }\n\n private setStatus(status: string) {\n this.healthCheck.status = status;\n }\n\n private blockListener = {\n next: (data: {\n header: {\n height: number\n }\n }) => {\n this.newBlockReceived(data.header.height);\n },\n };\n\n private isMinimal(_blockqueue: BlockQueue): _blockqueue is MinimalBlockQueue {\n if (this.config.minimal) {\n return true;\n }\n else {\n return false;\n }\n }\n\n public async connect() {\n try {\n if (this.client && this.tryToRecover) {\n this.log.verbose(\"Recover from error. Attempting to disconnect from RPC\");\n this.client.disconnect();\n this.blockClient.disconnect();\n this.log.verbose(\"Disconnected from RPC\");\n }\n this.client = await connectComet(this.config.rpcUrl);\n this.log.info(\"Connected to RPC for ad hoc queries\");\n\n this.blockClient = await connectComet(this.config.rpcUrl);\n this.log.info(\"Connected to RPC for block & validator info\");\n\n return true;\n }\n catch (error) {\n this.log.error(\"RPC connection error: \" + error);\n this.prometheus?.recordError(\"rpc\");\n this.tryToRecover = true;\n return false;\n }\n }\n\n public stop() {\n this.started = false;\n }\n\n public async start() {\n this.started = true;\n if (this.blockQueue) {\n this.blockQueue.clear();\n this.log.verbose(\"Starting, clearing block queue\");\n }\n if (!this.initialized) {\n try {\n if (this.config.init) {\n await this.config.init();\n }\n }\n catch (e) {\n this.log.error(\"Failed to initialize indexer: \" + e);\n\n this.prometheus?.recordError(\"init_error\");\n this.setStatus(\"FAILED\");\n throw e;\n }\n if (await this.config.shouldProcessGenesis()) {\n try {\n if (this.config.genesisPath) {\n await this.parseGenesis();\n }\n }\n catch (e) {\n this.log.error(\"Failed to parse genesis: \" + e);\n\n this.prometheus?.recordError(\"genesis_error\");\n this.setStatus(\"FAILED\");\n throw e;\n }\n }\n this.initialized = true;\n }\n try {\n await this.connect();\n if (!this.config.usePolling && this.subscription) {\n this.subscription.removeListener(this.blockListener);\n this.subscription = null;\n this.log.verbose(\"Removed existing block listener and subscription\");\n }\n if (!this.config.usePolling) {\n this.subscription = this.client.subscribeNewBlock\n ? this.client.subscribeNewBlock()\n : null;\n }\n const status = await this.client.status();\n this.latestHeight = status.syncInfo.latestBlockHeight;\n this.log.info(\"Current chain height: \" + this.latestHeight);\n\n this.heightToProcess = await this.config.getNextHeight();\n if (this.config.usePolling) {\n this.pollForBlock();\n }\n else {\n if (this.subscription) {\n this.subscription.addListener(this.blockListener);\n }\n else {\n this.prometheus?.recordError(\"rpc\");\n throw new Error(\"Could not subscribe to new blocks\");\n }\n }\n }\n catch (e) {\n this.log.error(\"Failed to set up block listening: \" + e);\n this.prometheus?.recordError(\"rpc\");\n this.setStatus(\"FAILED\");\n throw e;\n }\n this.log.debug(\"Starting main processing loop\");\n this.tryToRecover = false;\n this.fetcher().catch((e) => {\n this.setStatus(\"FAILED\");\n\n this.prometheus?.recordError(\"rpc\");\n throw new Error(\"Error in fetching service: \" + e);\n });\n\n const hrTime = process.hrtime();\n let ms = hrTime[0] * 1000000 + hrTime[1] / 1000;\n while (this.blockQueue.size() > 0 && !this.tryToRecover && this.started && (this.config.endHeight === undefined || this.heightToProcess <= this.config.endHeight)) {\n if (this.config.enablePrometheus) {\n this.prometheus!.updateRetryCount(this.retryCount);\n }\n // await the dequeued promise is essentially awaiting fetched data for that block\n try {\n if (this.tryToRecover) {\n throw new Error(\"Exiting processing loop. Attempting to recover indexer\");\n }\n // Index block inside a db transaction to ensure data consistency\n await this.config.beginTransaction();\n this.log.silly(\"Started db tx\");\n let height, timestamp;\n if (this.isMinimal(this.blockQueue)) {\n const timeoutPromise: ReturnType<typeof this.blockQueue.dequeue> = new Promise((resolve, reject) => {\n setTimeout(reject, QUEUE_DEQUEUE_TIMEOUT_MS, []);\n });\n const toProcess = await Promise.race([this.blockQueue.dequeue(), timeoutPromise]);\n this.log.silly(\"Retrieved block data\");\n if (!toProcess || !toProcess[0] || !toProcess[1]) {\n this.prometheus?.recordError(\"rpc\");\n throw new Error(\"Could not fetch block\");\n }\n height = toProcess[0].block.header.height;\n timestamp = toRfc3339WithNanoseconds(toProcess[0].block.header.time);\n await this.processBlock(toProcess[0],\n toProcess[1]);\n }\n else {\n const timeoutPromise: ReturnType<typeof this.blockQueue.dequeue> = new Promise((resolve, reject) => {\n setTimeout(reject, QUEUE_DEQUEUE_TIMEOUT_MS, []);\n });\n const toProcess = await Promise.race([this.blockQueue.dequeue(), timeoutPromise]);\n this.log.silly(\"Retrieved block data\");\n if (!toProcess || !toProcess[0] || !toProcess[1] || !toProcess[2]) {\n this.prometheus?.recordError(\"rpc\");\n throw new Error(\"Could not fetch block\");\n }\n\n this.log.silly(\"Decoded block\");\n height = toProcess[0].block.header.height;\n timestamp = toRfc3339WithNanoseconds(toProcess[0].block.header.time);\n await this.processBlock(toProcess[0],\n toProcess[1],\n QueryValidatorsResponse.decode(toProcess[2]).validators);\n }\n // Emit events to trigger periodic operations every 50, 100 and 1000 blocks\n if (height % PERIODIC_INTERVALS.LARGE == 0) {\n const hrTime = process.hrtime();\n const newms = hrTime[0] * 1000000 + hrTime[1] / 1000;\n const duration = newms - ms;\n ms = newms;\n const rate = 1000000000 / duration;\n this.log.info(\"Processing:\" + rate.toFixed(2) + \"blocks/sec\");\n await this.asyncEmit(\"periodic/1000\",\n {\n value: null,\n height,\n timestamp,\n });\n }\n if (height % PERIODIC_INTERVALS.MEDIUM == 0) {\n await this.asyncEmit(\"periodic/100\",\n {\n value: null,\n height,\n timestamp,\n });\n }\n if (height % PERIODIC_INTERVALS.SMALL == 0) {\n await this.asyncEmit(\"periodic/50\",\n {\n value: null,\n height,\n timestamp,\n });\n }\n this.log.silly(\"Handled periodic events\");\n\n await this.config.endTransaction(true);\n\n this.log.silly(\"Committed db tx\");\n }\n catch (e) {\n this.prometheus?.recordError(\"block\");\n this.log.error(\"Block processing error: \" + e);\n this.setStatus(\"FAILED\");\n try {\n await this.config.endTransaction(false);\n }\n catch (dbe) {\n this.prometheus?.recordError(\"database\");\n this.log.error(\"Error ending transaction. Must be a DB error: \" + dbe);\n }\n this.tryToRecover = true;\n this.retryCount++;\n break;\n }\n this.retryCount = 0;\n this.setStatus(\"OK\");\n }\n if (this.config.endHeight !== undefined && this.heightToProcess >= this.config.endHeight!) {\n this.log.info(\"Reached configured end height. Stopping indexer.\");\n this.stop();\n }\n if (this.started) {\n if (this.retryCount < 3) {\n this.log.debug(\"Indexer retryCount: \" + this.retryCount);\n this.log.info(\"Indexer is restarting\");\n setTimeout(() => this.start(),\n this.retryCount * 5000);\n }\n else {\n this.log.info(\"Indexer failed too many times. Exiting.\");\n this.emit(\"fatal-error\", {\n error: new Error(\"Max retry attempts exceeded\"),\n message: \"Indexer failed too many times\",\n retryCount: this.retryCount,\n });\n }\n }\n }\n\n public asyncEmit: EmitFunc<keyof WithHeightAndUUID<EventMap>> = async (\n type,\n event,\n ) => {\n event.uuid = uuidv4();\n\n /*\n * More than 1 listener can be registered for an event type\n * Fortunately these are all set up during module init() so we have a consistent count\n * so we can count responses to resolve when complete\n * values are irrelevant as promise resolution is only used for flow control\n */\n let listenerCount = this.handled.get(type);\n if (!listenerCount) {\n // Setting listenerCount to 1 (the unhandled listener)\n listenerCount = 1;\n }\n let listenersResponded = 0;\n const prom = new Promise<void>((resolve, reject) => {\n const returnFunc = (ev: UUIDEvent) => {\n if (ev.uuid == event.uuid) {\n if (ev.status) {\n listenersResponded++;\n if (listenersResponded == listenerCount) {\n // All listeners have done their thing so we can remove listener, resolve and continue execution\n this.off(\"uuid\",\n returnFunc);\n resolve();\n }\n }\n else {\n // At least 1 listener is reporting an error. Reject and handle exception at the original asyncEmit location\n reject(ev.error);\n }\n }\n };\n this.on(\"uuid\",\n returnFunc);\n });\n this.emit(type,\n event);\n\n return prom;\n };\n\n private async processBlock(block: BlockResponse, block_results: BlockResultsResponse | BlockResultsResponse38, validators?: Validator[]) {\n let processStart: [number, number] = [0, 0];\n if (this.config.logLevel == \"silly\") {\n processStart = process.hrtime();\n }\n let endTimer;\n if (this.config.enablePrometheus) {\n endTimer = this.prometheus!.timeBlockProcessing();\n }\n const height = block.block.header.height;\n this.heightToProcess = height;\n this.log.debug(\"Processing block: %d\",\n height);\n // Initialize height & timestamp to be used for this block-processing run\n const timestamp = toRfc3339WithNanoseconds(block.block.header.time);\n\n // Use & await asyncEmit to ensure db insertions in order\n\n /*\n * Emit block information to any interested modules.\n * Primarily the required block module listens to this\n */\n await this.asyncEmit(\"block\",\n {\n value: {\n block,\n block_results,\n },\n height,\n timestamp,\n });\n this.log.silly(\"Modules handled block event\");\n\n let beginBlockEvents: readonly Event[] | readonly Event38[];\n let endBlockEvents: readonly Event[] | readonly Event38[];\n if ((block_results as BlockResultsResponse38).finalizeBlockEvents) {\n beginBlockEvents = (block_results as BlockResultsResponse38).finalizeBlockEvents.filter(x => x.attributes.find(a => decodeAttr(a.key) == \"mode\" && decodeAttr(a.value) == \"begin_block\")) as readonly Event38[];\n endBlockEvents = (block_results as BlockResultsResponse38).finalizeBlockEvents.filter(x => x.attributes.find(a => decodeAttr(a.key) == \"mode\" && decodeAttr(a.value) == \"end_block\")) as readonly Event38[];\n }\n else {\n beginBlockEvents = (block_results as BlockResultsResponse).beginBlockEvents;\n endBlockEvents = (block_results as BlockResultsResponse).endBlockEvents;\n }\n // Deal with begin_block events first\n await this.asyncEmit(\"begin_block\",\n {\n value: {\n events: beginBlockEvents!,\n validators,\n },\n height,\n timestamp,\n });\n\n this.log.silly(\"Modules handled begin_block events\");\n\n // Then individual tx_events\n await this.asyncEmit(\"tx_events\",\n {\n value: block_results.results,\n height,\n timestamp,\n });\n this.log.silly(\"Modules handled tx events\");\n\n // Emit details and result for each tx msg separately\n for (let t = 0; t < block.block.txs.length; t++) {\n const tx = Tx.decode(block.block.txs[t]);\n\n const result = block_results.results[t].code;\n const txlog = block_results.results[t].log;\n\n if (result != 0) {\n // Tx failed. Ignore\n continue;\n }\n if (tx.body && tx.body.memo != \"\") {\n const txHash = createHash(\"sha256\").update(block.block.txs[t])\n .digest(\"hex\");\n await this.asyncEmit(\"tx_memo\",\n {\n value: {\n txHash,\n txBody: tx.body,\n },\n height,\n timestamp,\n });\n }\n // parsing log rather than using events directly in order to have msg_index available to filter appropriate events for each msg\n let events: Array<{\n msg_index?: number\n events: (Event | Event38)[]\n }> = txlog\n ? JSON.parse(txlog)\n : [];\n if (events.length == 0) {\n const eventsToAdd: typeof events = [];\n this.log.silly(\"No events found in tx log. Parsing events for msg_index\");\n for (let m = 0; m < block_results.results[t].events.length; m++) {\n if (block_results.results[t].events[m].attributes.find(a => decodeAttr(a.key) == \"msg_index\")) {\n const mi = decodeAttr(block_results.results[t].events[m].attributes.find(a => decodeAttr(a.key) == \"msg_index\")?.value ?? \"\");\n if (mi != \"\") {\n const miNum = parseInt(mi);\n let ev = eventsToAdd.find(x => x.msg_index == miNum);\n if (!ev) {\n ev = {\n msg_index: miNum,\n events: [block_results.results[t].events[m]],\n };\n eventsToAdd.push(ev);\n }\n else {\n ev.events.push(block_results.results[t].events[m] as Event);\n }\n }\n }\n }\n events = events.concat(eventsToAdd);\n }\n const msgs = tx.body?.messages;\n\n if (msgs) {\n for (let i = 0; i < msgs.length; i++) {\n this.log.silly(\"Indexer broadcasting msg for handling: \" + msgs[i].typeUrl);\n const msgevents\n = msgs.length > 1\n ? events.find(x => x.msg_index == i)?.events\n : events[0].events;\n await this.asyncEmit(msgs[i].typeUrl as never,\n {\n value: {\n tx: msgs[i].value as never,\n events: msgevents,\n } as never,\n height,\n timestamp,\n });\n if (msgs[i].typeUrl == \"/cosmos.authz.v1beta1.MsgExec\") {\n const authzMsgs = MsgExec.decode(msgs[i].value).msgs;\n if (authzMsgs) {\n for (let r = 0; r < authzMsgs.length; r++) {\n this.log.silly(\"Indexer broadcasting msg for handling: \" + authzMsgs[r].typeUrl);\n const authzMsgEvents = msgevents?.reduce((events, evt) => {\n if (evt.attributes.filter(x => decodeAttr(x.key) == \"authz_msg_index\" && decodeAttr(x.value) == \"\" + r).length > 0) {\n events.push(evt);\n }\n return events;\n },\n [] as (Event | Event38)[]);\n await this.asyncEmit(authzMsgs[r].typeUrl as never,\n {\n value: {\n tx: authzMsgs[r].value as never,\n events: authzMsgEvents,\n } as never,\n height,\n timestamp,\n });\n }\n }\n }\n }\n }\n }\n this.log.silly(\"Modules handled msg events\");\n if (this.config.enablePrometheus) {\n this.prometheus!.recordTransactions(block.block.txs.length);\n }\n // Then deal with end_block events\n await this.asyncEmit(\"end_block\",\n {\n value: endBlockEvents!,\n height,\n timestamp,\n });\n this.log.silly(\"Modules handled end_block events\");\n if (this.config.logLevel == \"silly\") {\n const processEnd = process.hrtime(processStart);\n const processTime = processEnd[0] * 1000 + processEnd[1] / 1000000;\n this.log.silly(\"Processed block %d in %d ms\",\n height,\n processTime.toFixed(2));\n }\n\n if (this.config.enablePrometheus) {\n endTimer!();\n }\n if (this.config.enablePrometheus) {\n this.prometheus!.updateBlockMetrics(height, this.latestHeight, this.blockQueue.size());\n }\n }\n\n private async fetcher() {\n for (let i = this.heightToProcess; i <= this.latestHeight; i++) {\n this.log.debug(\"Fetching: \" + i);\n if (this.tryToRecover) {\n this.log.verbose(\"Exiting fetcher loop. Attempting to recover indexer\");\n break;\n }\n try {\n if (this.isMinimal(this.blockQueue)) {\n const timeoutPromise: Promise<[BlockResponse, BlockResultsResponse]> = new Promise((resolve, reject) => {\n setTimeout(reject,\n RPC_TIMEOUT_MS,\n false);\n });\n const toIndex = Promise.race([Promise.all([this.blockClient.block(i) as Promise<BlockResponse>, this.blockClient.blockResults(i) as Promise<BlockResultsResponse>]), timeoutPromise]).catch((e) => {\n this.log.error(\"Error fetching block: \" + i + \" : \" + e);\n this.tryToRecover = true;\n return Promise.resolve([]);\n }) as Promise<[BlockResponse, BlockResultsResponse]>;\n this.blockQueue.enqueue(toIndex);\n }\n else {\n const timeoutPromise: Promise<[BlockResponse, BlockResultsResponse, Uint8Array]> = new Promise((resolve, reject) => {\n setTimeout(reject,\n RPC_TIMEOUT_MS,\n false);\n });\n const q = QueryValidatorsRequest.fromPartial({\n pagination: {\n limit: PAGINATION_LIMITS.VALIDATORS,\n },\n });\n const vals = QueryValidatorsRequest.encode(q).finish();\n const toIndex = Promise.race([\n Promise.all([\n this.blockClient.block(i) as Promise<BlockResponse>,\n this.blockClient.blockResults(i) as Promise<BlockResultsResponse>,\n this.callABCI(\"/cosmos.staking.v1beta1.Query/Validators\",\n vals,\n i,\n false),\n ]),\n timeoutPromise,\n ]).catch((e) => {\n this.log.error(\"Error fetching block: \" + i + \" : \" + e);\n this.tryToRecover = true;\n return Promise.resolve([]);\n }) as Promise<[BlockResponse, BlockResultsResponse, Uint8Array]>;\n this.blockQueue.enqueue(toIndex);\n }\n await this.blockQueue.continue();\n if (this.tryToRecover) {\n this.retryCount++;\n throw new Error(\"RPC not responding\");\n }\n }\n catch (e) {\n this.log.error(\"Fetching error: \" + e);\n break;\n }\n }\n if (!this.tryToRecover) {\n this.blockQueue.setSynced();\n this.log.info(\"Synced to latest height\");\n }\n }\n\n public async callABCI(path: string, data: Uint8Array, height?: number, adHoc: boolean = true): Promise<Uint8Array> {\n try {\n const endTimer = this.prometheus?.timeRpcCall(path) ?? void 0;\n const abciq = await\n (adHoc\n ? this.client\n : this.blockClient).abciQuery({\n path,\n data,\n height: height,\n });\n endTimer?.();\n if (abciq) {\n return abciq.value;\n }\n else {\n this.tryToRecover = true;\n this.setStatus(\"FAILED\");\n this.prometheus?.recordError(\"rpc\");\n throw new Error(\"RPC not responding. Query at: \" + path);\n }\n }\n catch (_e) {\n this.tryToRecover = true;\n this.setStatus(\"FAILED\");\n this.retryCount++;\n throw new Error(\"RPC not responding. Query at: \" + path);\n }\n }\n\n private newBlockReceived(height: number): void {\n if (this.blockTimeout) {\n clearTimeout(this.blockTimeout);\n }\n this.blockTimeout = setTimeout(() => {\n this.tryToRecover = true;\n }, 30000);\n this.log.info(\"Received new block: %d\",\n height);\n if (height == this.latestHeight) {\n return;\n }\n // If we are synced, add to end of queue\n if (this.blockQueue.synced && !this.tryToRecover) {\n this.latestHeight = height;\n if (this.blockQueue.size() + 1 == this.config.batchSize) {\n this.prometheus?.recordError(\"block\");\n this.log.error(\"Block queue is full. Cannot add new block\");\n this.tryToRecover = true;\n this.retryCount++;\n return;\n }\n try {\n if (this.isMinimal(this.blockQueue)) {\n this.blockQueue.enqueue(Promise.all([this.client.block(height) as Promise<BlockResponse>, this.client.blockResults(height) as Promise<BlockResultsResponse>]).catch((e) => {\n this.log.error(\"Error fetching block: \" + height + \" : \" + e);\n\n return Promise.resolve([]);\n }) as Promise<[BlockResponse, BlockResultsResponse]>);\n }\n else {\n const q = QueryValidatorsRequest.fromPartial({\n pagination: {\n limit: 1000n,\n },\n });\n const vals = QueryValidatorsRequest.encode(q).finish();\n this.blockQueue.enqueue(Promise.all([\n this.client.block(height) as Promise<BlockResponse>,\n this.client.blockResults(height) as Promise<BlockResultsResponse>,\n this.callABCI(\"/cosmos.staking.v1beta1.Query/Validators\",\n vals,\n height,\n false),\n ]).catch((e) => {\n this.log.error(\"Error fetching block: \" + height + \" : \" + e);\n return Promise.resolve([]);\n }) as Promise<[BlockResponse, BlockResultsResponse, Uint8Array]>);\n }\n }\n catch (e) {\n this.log.error(\"New Block Received error: \" + e);\n }\n }\n else {\n this.latestHeight = height;\n }\n }\n\n private async pollForBlock() {\n try {\n const status = await this.client.status();\n if (status.syncInfo.latestBlockHeight > this.latestHeight) {\n while (this.latestHeight < status.syncInfo.latestBlockHeight) {\n this.newBlockReceived(this.latestHeight + 1);\n }\n }\n setTimeout(() => {\n this.pollForBlock();\n },\n this.config.pollingInterval);\n }\n catch (e) {\n this.log.error(\"Error polling for new block: \" + e);\n this.tryToRecover = true;\n this.retryCount++;\n }\n }\n\n private readGenesis(): Parser.Parser {\n if (this.config.genesisPath) {\n return fs.createReadStream(this.config.genesisPath).pipe(Parser.parser());\n }\n else {\n throw new Error(\"Genesis path not set\");\n }\n }\n\n private async setArrayReader(path: string, processor: (chunk: unknown) => Promise<void>): Promise<boolean> {\n const readPromise = new Promise<boolean>((resolve, reject) => {\n try {\n const filters = path.split(\".\");\n const pickers = filters.map(filter => Pick.pick({\n filter,\n }));\n let counter = 0;\n let chunkCounter = 0;\n\n // Wrapper processor that handles transaction chunking\n const chunkProcessor = async (data: unknown) => {\n chunkCounter++;\n this.log.debug(`Processing genesis chunk ${chunkCounter}`);\n\n await processor(data);\n\n // Commit and restart transaction every 5 chunks (5000 entries)\n // This prevents timeout on large genesis files\n if (chunkCounter % 5 === 0) {\n this.log.debug(`Committing transaction after chunk ${chunkCounter}`);\n await this.config.endTransaction(true);\n await this.config.beginTransaction();\n }\n };\n\n chain([\n this.readGenesis(),\n ...pickers,\n StreamArray.streamArray(),\n Batch.batch({\n batchSize: GENESIS_BATCH_SIZE,\n }),\n chunkProcessor,\n ])\n .on(\"data\",\n (data) => {\n if (data && Array.isArray(data)) {\n counter = counter + data.length;\n }\n })\n .on(\"end\",\n () => {\n this.log.info(`Processed ${counter} entries in ${chunkCounter} chunks`);\n resolve(true);\n });\n }\n catch (_e) {\n this.log.verbose(\"Error in setArrayReader: \" + _e);\n reject();\n }\n });\n\n return readPromise;\n }\n\n private async setValueReader(path: string, processor: (chunk: unknown) => Promise<void>): Promise<boolean> {\n const readPromise = new Promise<boolean>((resolve, reject) => {\n try {\n const filters = path.split(\".\");\n const pickers = filters.map(filter => Pick.pick({\n filter,\n }));\n\n let counter = 0;\n chain([this.readGenesis(), ...pickers, StreamValues.streamValues(), processor])\n .on(\"data\",\n (_data) => {\n counter++;\n })\n .on(\"end\",\n () => {\n this.log.info(`Processed ${counter} entries`);\n resolve(true);\n });\n }\n catch (_e) {\n reject();\n }\n });\n\n return readPromise;\n }\n\n private async parseGenesis() {\n this.log.info(\"Parsing genesis\");\n await this.config.beginTransaction();\n try {\n this.log.info(\"Starting genesis import\");\n this.log.debug(\"Importing genesis file...\");\n\n for (const [key, _value] of this.handled) {\n if (key.startsWith(\"genesis/\")) {\n const genesisEntry = key.split(\"/\");\n\n this.log.verbose(\"Importing \" + key + \"...\");\n if (genesisEntry[1] == \"array\") {\n await this.setArrayReader(genesisEntry[2],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async (data: any) => {\n await this.asyncEmit(key as never,\n {\n value: data.map((x: {\n value: never\n }) => x.value),\n } as never);\n return data;\n });\n }\n else {\n await this.setValueReader(genesisEntry[2],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async (data: any) => {\n await this.asyncEmit(key as never,\n {\n value: data.value,\n } as never);\n return data;\n });\n }\n }\n }\n\n this.log.info(\"Importing gen TXs...\");\n\n await this.setArrayReader(\"app_state.genutil.gen_txs\",\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async (data: any) => {\n for (let j = 0; j < data.length; j++) {\n const gentx = data[j].value;\n for (let i = 0; i < gentx.body.messages.length; i++) {\n const msg = gentx.body.messages[i];\n await this.asyncEmit((\"gentx\" + msg[\"@type\"]) as never,\n {\n value: msg,\n } as never);\n }\n }\n return data;\n });\n await this.config.endTransaction(true);\n\n this.log.info(\"Finished importing\");\n }\n catch (e) {\n try {\n await this.config.endTransaction(false);\n }\n catch (dbe) {\n this.prometheus?.recordError(\"database\");\n this.log.error(\"Error ending transaction. Must be a DB error: \" + dbe);\n }\n this.log.error(\"Failed to import genesis\");\n throw e;\n }\n }\n}\n"],"mappings":"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"}
@@ -114,7 +114,7 @@ var EcleciaIndexer = class extends EclesiaEmitter {
114
114
  ]
115
115
  });
116
116
  const queueErrorHandler = (e) => {
117
- this.prometheus?.recordError("block_queue");
117
+ this.prometheus?.recordError("rpc");
118
118
  this.log.error("Error enqueueing block data: " + e);
119
119
  };
120
120
  if (this.config.minimal) this.blockQueue = new CircularBuffer(this.config.batchSize, queueErrorHandler);
@@ -197,7 +197,7 @@ var EcleciaIndexer = class extends EclesiaEmitter {
197
197
  return true;
198
198
  } catch (error) {
199
199
  this.log.error("RPC connection error: " + error);
200
- this.prometheus?.recordError("connect_rpc_error");
200
+ this.prometheus?.recordError("rpc");
201
201
  this.tryToRecover = true;
202
202
  return false;
203
203
  }
@@ -244,12 +244,12 @@ var EcleciaIndexer = class extends EclesiaEmitter {
244
244
  if (this.config.usePolling) this.pollForBlock();
245
245
  else if (this.subscription) this.subscription.addListener(this.blockListener);
246
246
  else {
247
- this.prometheus?.recordError("subscription_error");
247
+ this.prometheus?.recordError("rpc");
248
248
  throw new Error("Could not subscribe to new blocks");
249
249
  }
250
250
  } catch (e) {
251
251
  this.log.error("Failed to set up block listening: " + e);
252
- this.prometheus?.recordError("block_listening_error");
252
+ this.prometheus?.recordError("rpc");
253
253
  this.setStatus("FAILED");
254
254
  throw e;
255
255
  }
@@ -257,7 +257,7 @@ var EcleciaIndexer = class extends EclesiaEmitter {
257
257
  this.tryToRecover = false;
258
258
  this.fetcher().catch((e) => {
259
259
  this.setStatus("FAILED");
260
- this.prometheus?.recordError("fetching_error");
260
+ this.prometheus?.recordError("rpc");
261
261
  throw new Error("Error in fetching service: " + e);
262
262
  });
263
263
  const hrTime = process.hrtime();
@@ -276,7 +276,7 @@ var EcleciaIndexer = class extends EclesiaEmitter {
276
276
  const toProcess = await Promise.race([this.blockQueue.dequeue(), timeoutPromise]);
277
277
  this.log.silly("Retrieved block data");
278
278
  if (!toProcess || !toProcess[0] || !toProcess[1]) {
279
- this.prometheus?.recordError("rpc_error");
279
+ this.prometheus?.recordError("rpc");
280
280
  throw new Error("Could not fetch block");
281
281
  }
282
282
  height = toProcess[0].block.header.height;
@@ -289,7 +289,7 @@ var EcleciaIndexer = class extends EclesiaEmitter {
289
289
  const toProcess = await Promise.race([this.blockQueue.dequeue(), timeoutPromise]);
290
290
  this.log.silly("Retrieved block data");
291
291
  if (!toProcess || !toProcess[0] || !toProcess[1] || !toProcess[2]) {
292
- this.prometheus?.recordError("rpc_error");
292
+ this.prometheus?.recordError("rpc");
293
293
  throw new Error("Could not fetch block");
294
294
  }
295
295
  this.log.silly("Decoded block");
@@ -324,7 +324,7 @@ var EcleciaIndexer = class extends EclesiaEmitter {
324
324
  await this.config.endTransaction(true);
325
325
  this.log.silly("Committed db tx");
326
326
  } catch (e) {
327
- this.prometheus?.recordError("block_processing_error");
327
+ this.prometheus?.recordError("block");
328
328
  this.log.error("Block processing error: " + e);
329
329
  this.setStatus("FAILED");
330
330
  try {
@@ -566,7 +566,7 @@ var EcleciaIndexer = class extends EclesiaEmitter {
566
566
  else {
567
567
  this.tryToRecover = true;
568
568
  this.setStatus("FAILED");
569
- this.prometheus?.recordError("abci_query_error");
569
+ this.prometheus?.recordError("rpc");
570
570
  throw new Error("RPC not responding. Query at: " + path);
571
571
  }
572
572
  } catch (_e) {
@@ -586,7 +586,7 @@ var EcleciaIndexer = class extends EclesiaEmitter {
586
586
  if (this.blockQueue.synced && !this.tryToRecover) {
587
587
  this.latestHeight = height;
588
588
  if (this.blockQueue.size() + 1 == this.config.batchSize) {
589
- this.prometheus?.recordError("block_queue_full");
589
+ this.prometheus?.recordError("block");
590
590
  this.log.error("Block queue is full. Cannot add new block");
591
591
  this.tryToRecover = true;
592
592
  this.retryCount++;
@@ -721,7 +721,7 @@ var EcleciaIndexer = class extends EclesiaEmitter {
721
721
  try {
722
722
  await this.config.endTransaction(false);
723
723
  } catch (dbe) {
724
- this.prometheus?.recordError("database_error");
724
+ this.prometheus?.recordError("database");
725
725
  this.log.error("Error ending transaction. Must be a DB error: " + dbe);
726
726
  }
727
727
  this.log.error("Failed to import genesis");
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["timeoutPromise: ReturnType<typeof this.blockQueue.dequeue>","hrTime","uuidv4","processStart: [number, number]","beginBlockEvents: readonly Event[] | readonly Event38[]","endBlockEvents: readonly Event[] | readonly Event38[]","events: Array<{\n msg_index?: number\n events: (Event | Event38)[]\n }>","eventsToAdd: typeof events","events","timeoutPromise: Promise<[BlockResponse, BlockResultsResponse]>","timeoutPromise: Promise<[BlockResponse, BlockResultsResponse, Uint8Array]>"],"sources":["../../src/indexer/index.ts"],"sourcesContent":["/* eslint-disable @stylistic/no-multi-spaces */\n/* eslint-disable max-lines */\nimport {\n createHash,\n} from \"node:crypto\";\nimport * as fs from \"node:fs\";\n\nimport {\n BlockResponse, BlockResultsResponse, CometClient, connectComet, Event, toRfc3339WithNanoseconds,\n} from \"@cosmjs/tendermint-rpc\";\nimport {\n BlockResultsResponse as BlockResultsResponse38, Event as Event38,\n} from \"@cosmjs/tendermint-rpc/build/comet38/responses.js\";\nimport {\n MsgExec,\n} from \"cosmjs-types/cosmos/authz/v1beta1/tx.js\";\nimport {\n QueryValidatorsRequest,\n QueryValidatorsResponse,\n} from \"cosmjs-types/cosmos/staking/v1beta1/query.js\";\nimport {\n Validator,\n} from \"cosmjs-types/cosmos/staking/v1beta1/staking.js\";\nimport {\n Tx,\n} from \"cosmjs-types/cosmos/tx/v1beta1/tx.js\";\nimport Fastify, {\n FastifyInstance,\n} from \"fastify\";\nimport {\n chain,\n} from \"stream-chain\";\nimport Parser from \"stream-json\";\nimport Pick from \"stream-json/filters/Pick.js\";\nimport StreamArray from \"stream-json/streamers/StreamArray.js\";\nimport StreamValues from \"stream-json/streamers/StreamValues.js\";\nimport Batch from \"stream-json/utils/Batch.js\";\nimport {\n v4 as uuidv4,\n} from \"uuid\";\nimport * as winston from \"winston\";\n\nimport {\n DEFAULT_BATCH_SIZE, DEFAULT_HEALTH_CHECK_PORT, DEFAULT_POLLING_INTERVAL_MS, DEFAULT_PROMETHEUS_PORT, DEFAULT_START_HEIGHT,\n GENESIS_BATCH_SIZE, PAGINATION_LIMITS, PERIODIC_INTERVALS, QUEUE_DEQUEUE_TIMEOUT_MS, RPC_TIMEOUT_MS,\n} from \"../constants.js\";\nimport {\n EclesiaEmitter,\n} from \"../emitter/index.js\";\nimport {\n IndexerMetrics,\n} from \"../metrics/index.js\";\nimport {\n CircularBuffer,\n} from \"../promise-queue/index.js\";\nimport {\n BlockQueue, EcleciaIndexerConfig, EmitFunc, MinimalBlockQueue,\n UUIDEvent, WithHeightAndUUID,\n} from \"../types/index.js\";\nimport {\n decodeAttr,\n} from \"../utils/index.js\";\nimport {\n validateFilePath, validatePort, validatePositiveInteger, validateUrl,\n} from \"../validation/index.js\";\n\n/** Default configuration for the Eclesia indexer */\nexport const defaultIndexerConfig = {\n startHeight: DEFAULT_START_HEIGHT, // Start indexing from block 1\n batchSize: DEFAULT_BATCH_SIZE, // Process blocks in batches of 500\n modules: [], // No modules enabled by default\n getNextHeight: () => DEFAULT_START_HEIGHT, // Default height retrieval function\n logLevel: \"info\" as EcleciaIndexerConfig[\"logLevel\"], // Default log level\n usePolling: false, // Use WebSocket subscription by default\n pollingInterval: DEFAULT_POLLING_INTERVAL_MS, // Poll every 5 seconds when polling enabled\n shouldProcessGenesis: () => false, // Skip genesis processing by default\n minimal: true, // Use minimal indexing by default\n enableHealthcheck: true, // Enable health check server by default\n healthCheckPort: DEFAULT_HEALTH_CHECK_PORT, // Default health check port\n enablePrometheus: false, // Disable Prometheus metrics server by default\n prometheusPort: DEFAULT_PROMETHEUS_PORT, // Default Prometheus metrics server port\n init: () => Promise.resolve(), // No-op initialization function\n beginTransaction: () => Promise.resolve(), // No-op transaction begin function\n endTransaction: (_status: boolean) => Promise.resolve(), // No-op transaction end function\n};\n\n/**\n * Core blockchain indexer that connects to Tendermint RPC and processes blocks\n * Extends EclesiaEmitter to provide event-driven architecture for modules\n */\nexport class EcleciaIndexer extends EclesiaEmitter {\n /** Indexer configuration settings */\n public config: EcleciaIndexerConfig;\n\n /** Fastify HTTP server for health checks */\n private fastify: FastifyInstance | null = null;\n\n /** Prometheus HTTP server instance */\n private prometheusServer: FastifyInstance | null = null;\n\n /** Indicates if the indexer has started */\n private started: boolean = false;\n\n /** Queue for managing block processing pipeline */\n private blockQueue: BlockQueue;\n\n /** Latest block height from the chain */\n private latestHeight!: number;\n\n /** Next block height to process */\n public heightToProcess!: number;\n\n /** Whether the indexer has been initialized */\n private initialized = false;\n\n /** Prometheus metrics server instance */\n public prometheus: IndexerMetrics | null = null;\n\n /** Number of retry attempts for error recovery */\n private retryCount = 0;\n\n /** CometBFT client for ad-hoc queries */\n public client!: CometClient;\n\n /** CometBFT client for block and validator queries */\n public blockClient!: CometClient;\n\n /** Winston logger instance */\n public log: winston.Logger;\n\n /** Flag indicating if indexer should attempt recovery */\n private tryToRecover: boolean = false;\n\n /** Health check status for monitoring */\n private healthCheck = {\n status: \"CONNECTING\",\n };\n\n /** WebSocket subscription for new block notifications */\n private subscription: ReturnType<CometClient[\"subscribeNewBlock\"]> | null = null;\n\n /** Timeout handler for block reception */\n private blockTimeout: NodeJS.Timeout | null = null;\n\n /**\n * Creates a new Eclesia indexer instance\n * @param config - Indexer configuration options\n */\n constructor(config: EcleciaIndexerConfig) {\n super();\n\n // Validate required configuration\n validateUrl(config.rpcUrl, \"rpcUrl\");\n validatePositiveInteger(config.batchSize, \"batchSize\");\n\n // Validate optional genesis path if processing genesis\n if (config.genesisPath) {\n validateFilePath(config.genesisPath, \"genesisPath\");\n }\n\n // Validate health check port if provided\n if (config.healthCheckPort !== undefined) {\n validatePort(config.healthCheckPort, \"healthCheckPort\");\n }\n\n // Validate prometheus port if provided\n if (config.prometheusPort !== undefined) {\n validatePort(config.prometheusPort, \"prometheusPort\");\n }\n\n // Validate start height if provided\n if (config.startHeight !== undefined) {\n validatePositiveInteger(config.startHeight, \"startHeight\");\n }\n\n // Validate polling interval if provided\n if (config.pollingInterval !== undefined) {\n validatePositiveInteger(config.pollingInterval, \"pollingInterval\");\n }\n\n this.config = {\n ...defaultIndexerConfig,\n ...config,\n };\n\n // Initialize logger first so it can be used by queue error handler\n const {\n printf,\n } = winston.format;\n\n const eclesiaFormat = printf(({\n level, message, timestamp,\n }) => {\n return `${timestamp} [${level.toUpperCase()}]:\\t${message}`;\n });\n this.log = winston.createLogger({\n level: this.config.logLevel,\n defaultMeta: {\n service: \"Eclesia Indexer\",\n },\n transports: [\n new winston.transports.File({\n filename: \"error.log\",\n level: \"error\",\n }),\n new winston.transports.File({\n filename: \"combined.log\",\n }),\n new winston.transports.Console({\n format: winston.format.combine(winston.format.splat(),\n winston.format.timestamp(),\n eclesiaFormat,\n winston.format.colorize({\n all: true,\n })),\n }),\n ],\n });\n\n // Initialize block queue based on minimal or full indexing mode\n // Pass error handler that uses the logger\n const queueErrorHandler = (e: unknown) => {\n this.prometheus?.recordError(\"block_queue\");\n this.log.error(\"Error enqueueing block data: \" + e);\n };\n\n if (this.config.minimal) {\n // Minimal mode: only store block and block results\n this.blockQueue = new CircularBuffer<[BlockResponse, BlockResultsResponse]>(this.config.batchSize, queueErrorHandler);\n }\n else {\n // Full mode: also store validator information\n this.blockQueue = new CircularBuffer<[BlockResponse, BlockResultsResponse, Uint8Array]>(this.config.batchSize, queueErrorHandler);\n }\n\n this.on(\"_unhandled\",\n (msg) => {\n if (msg.uuid) {\n this.log.verbose(\"Unhandled event: \" + msg.type);\n this.emit(\"uuid\",\n {\n status: true,\n uuid: msg.uuid,\n });\n }\n });\n if (this.config.enablePrometheus) {\n this.prometheus = new IndexerMetrics();\n this.prometheusServer = Fastify({\n logger: false,\n });\n this.prometheusServer.get(\"/metrics\",\n async (_req, res) => {\n res.header(\"Content-Type\", this.prometheus!.registry.contentType);\n res.send(await this.prometheus!.getMetrics());\n },\n );\n\n const prometheusPort = this.config.prometheusPort\n ?? (process.env.PROMETHEUS_PORT ? parseInt(process.env.PROMETHEUS_PORT, 10) : DEFAULT_PROMETHEUS_PORT);\n this.prometheusServer.listen({\n port: prometheusPort,\n host: \"0.0.0.0\",\n },\n (err) => {\n if (err) {\n this.log.error(\"Prometheus error: \" + err);\n this.prometheus?.recordError(\"metrics_server\");\n this.emit(\"fatal-error\", {\n error: err,\n message: \"Failed to start metrics server\",\n });\n }\n });\n }\n if (this.config.enableHealthcheck) {\n this.fastify = Fastify({\n logger: false,\n });\n this.fastify.get(\"/health\",\n async (_request, reply) => {\n const code = this.healthCheck.status == \"OK\"\n ? 200\n : 503;\n reply.code(code).send(this.healthCheck);\n });\n const healthPort = this.config.healthCheckPort\n ?? (process.env.HEALTH_CHECK_PORT ? parseInt(process.env.HEALTH_CHECK_PORT, 10) : DEFAULT_HEALTH_CHECK_PORT);\n this.fastify.listen({\n port: healthPort,\n host: \"0.0.0.0\",\n },\n (err) => {\n if (err) {\n this.log.error(\"Health check server error: \" + err);\n this.prometheus?.recordError(\"health_check_server\");\n this.emit(\"fatal-error\", {\n error: err,\n message: \"Failed to start health check server\",\n });\n }\n });\n }\n }\n\n private setStatus(status: string) {\n this.healthCheck.status = status;\n }\n\n private blockListener = {\n next: (data: {\n header: {\n height: number\n }\n }) => {\n this.newBlockReceived(data.header.height);\n },\n };\n\n private isMinimal(_blockqueue: BlockQueue): _blockqueue is MinimalBlockQueue {\n if (this.config.minimal) {\n return true;\n }\n else {\n return false;\n }\n }\n\n public async connect() {\n try {\n if (this.client && this.tryToRecover) {\n this.log.verbose(\"Recover from error. Attempting to disconnect from RPC\");\n this.client.disconnect();\n this.blockClient.disconnect();\n this.log.verbose(\"Disconnected from RPC\");\n }\n this.client = await connectComet(this.config.rpcUrl);\n this.log.info(\"Connected to RPC for ad hoc queries\");\n\n this.blockClient = await connectComet(this.config.rpcUrl);\n this.log.info(\"Connected to RPC for block & validator info\");\n\n return true;\n }\n catch (error) {\n this.log.error(\"RPC connection error: \" + error);\n this.prometheus?.recordError(\"connect_rpc_error\");\n this.tryToRecover = true;\n return false;\n }\n }\n\n public stop() {\n this.started = false;\n }\n\n public async start() {\n this.started = true;\n if (this.blockQueue) {\n this.blockQueue.clear();\n this.log.verbose(\"Starting, clearing block queue\");\n }\n if (!this.initialized) {\n try {\n if (this.config.init) {\n await this.config.init();\n }\n }\n catch (e) {\n this.log.error(\"Failed to initialize indexer: \" + e);\n\n this.prometheus?.recordError(\"init_error\");\n this.setStatus(\"FAILED\");\n throw e;\n }\n if (await this.config.shouldProcessGenesis()) {\n try {\n if (this.config.genesisPath) {\n await this.parseGenesis();\n }\n }\n catch (e) {\n this.log.error(\"Failed to parse genesis: \" + e);\n\n this.prometheus?.recordError(\"genesis_error\");\n this.setStatus(\"FAILED\");\n throw e;\n }\n }\n this.initialized = true;\n }\n try {\n await this.connect();\n if (!this.config.usePolling && this.subscription) {\n this.subscription.removeListener(this.blockListener);\n this.subscription = null;\n this.log.verbose(\"Removed existing block listener and subscription\");\n }\n if (!this.config.usePolling) {\n this.subscription = this.client.subscribeNewBlock\n ? this.client.subscribeNewBlock()\n : null;\n }\n const status = await this.client.status();\n this.latestHeight = status.syncInfo.latestBlockHeight;\n this.log.info(\"Current chain height: \" + this.latestHeight);\n\n this.heightToProcess = await this.config.getNextHeight();\n if (this.config.usePolling) {\n this.pollForBlock();\n }\n else {\n if (this.subscription) {\n this.subscription.addListener(this.blockListener);\n }\n else {\n this.prometheus?.recordError(\"subscription_error\");\n throw new Error(\"Could not subscribe to new blocks\");\n }\n }\n }\n catch (e) {\n this.log.error(\"Failed to set up block listening: \" + e);\n this.prometheus?.recordError(\"block_listening_error\");\n this.setStatus(\"FAILED\");\n throw e;\n }\n this.log.debug(\"Starting main processing loop\");\n this.tryToRecover = false;\n this.fetcher().catch((e) => {\n this.setStatus(\"FAILED\");\n\n this.prometheus?.recordError(\"fetching_error\");\n throw new Error(\"Error in fetching service: \" + e);\n });\n\n const hrTime = process.hrtime();\n let ms = hrTime[0] * 1000000 + hrTime[1] / 1000;\n while (this.blockQueue.size() > 0 && !this.tryToRecover && this.started && (this.config.endHeight === undefined || this.heightToProcess <= this.config.endHeight)) {\n if (this.config.enablePrometheus) {\n this.prometheus!.updateRetryCount(this.retryCount);\n }\n // await the dequeued promise is essentially awaiting fetched data for that block\n try {\n if (this.tryToRecover) {\n throw new Error(\"Exiting processing loop. Attempting to recover indexer\");\n }\n // Index block inside a db transaction to ensure data consistency\n await this.config.beginTransaction();\n this.log.silly(\"Started db tx\");\n let height, timestamp;\n if (this.isMinimal(this.blockQueue)) {\n const timeoutPromise: ReturnType<typeof this.blockQueue.dequeue> = new Promise((resolve, reject) => {\n setTimeout(reject, QUEUE_DEQUEUE_TIMEOUT_MS, []);\n });\n const toProcess = await Promise.race([this.blockQueue.dequeue(), timeoutPromise]);\n this.log.silly(\"Retrieved block data\");\n if (!toProcess || !toProcess[0] || !toProcess[1]) {\n this.prometheus?.recordError(\"rpc_error\");\n throw new Error(\"Could not fetch block\");\n }\n height = toProcess[0].block.header.height;\n timestamp = toRfc3339WithNanoseconds(toProcess[0].block.header.time);\n await this.processBlock(toProcess[0],\n toProcess[1]);\n }\n else {\n const timeoutPromise: ReturnType<typeof this.blockQueue.dequeue> = new Promise((resolve, reject) => {\n setTimeout(reject, QUEUE_DEQUEUE_TIMEOUT_MS, []);\n });\n const toProcess = await Promise.race([this.blockQueue.dequeue(), timeoutPromise]);\n this.log.silly(\"Retrieved block data\");\n if (!toProcess || !toProcess[0] || !toProcess[1] || !toProcess[2]) {\n this.prometheus?.recordError(\"rpc_error\");\n throw new Error(\"Could not fetch block\");\n }\n\n this.log.silly(\"Decoded block\");\n height = toProcess[0].block.header.height;\n timestamp = toRfc3339WithNanoseconds(toProcess[0].block.header.time);\n await this.processBlock(toProcess[0],\n toProcess[1],\n QueryValidatorsResponse.decode(toProcess[2]).validators);\n }\n // Emit events to trigger periodic operations every 50, 100 and 1000 blocks\n if (height % PERIODIC_INTERVALS.LARGE == 0) {\n const hrTime = process.hrtime();\n const newms = hrTime[0] * 1000000 + hrTime[1] / 1000;\n const duration = newms - ms;\n ms = newms;\n const rate = 1000000000 / duration;\n this.log.info(\"Processing:\" + rate.toFixed(2) + \"blocks/sec\");\n await this.asyncEmit(\"periodic/1000\",\n {\n value: null,\n height,\n timestamp,\n });\n }\n if (height % PERIODIC_INTERVALS.MEDIUM == 0) {\n await this.asyncEmit(\"periodic/100\",\n {\n value: null,\n height,\n timestamp,\n });\n }\n if (height % PERIODIC_INTERVALS.SMALL == 0) {\n await this.asyncEmit(\"periodic/50\",\n {\n value: null,\n height,\n timestamp,\n });\n }\n this.log.silly(\"Handled periodic events\");\n\n await this.config.endTransaction(true);\n\n this.log.silly(\"Committed db tx\");\n }\n catch (e) {\n this.prometheus?.recordError(\"block_processing_error\");\n this.log.error(\"Block processing error: \" + e);\n this.setStatus(\"FAILED\");\n try {\n await this.config.endTransaction(false);\n }\n catch (dbe) {\n this.prometheus?.recordError(\"database\");\n this.log.error(\"Error ending transaction. Must be a DB error: \" + dbe);\n }\n this.tryToRecover = true;\n this.retryCount++;\n break;\n }\n this.retryCount = 0;\n this.setStatus(\"OK\");\n }\n if (this.config.endHeight !== undefined && this.heightToProcess >= this.config.endHeight!) {\n this.log.info(\"Reached configured end height. Stopping indexer.\");\n this.stop();\n }\n if (this.started) {\n if (this.retryCount < 3) {\n this.log.debug(\"Indexer retryCount: \" + this.retryCount);\n this.log.info(\"Indexer is restarting\");\n setTimeout(() => this.start(),\n this.retryCount * 5000);\n }\n else {\n this.log.info(\"Indexer failed too many times. Exiting.\");\n this.emit(\"fatal-error\", {\n error: new Error(\"Max retry attempts exceeded\"),\n message: \"Indexer failed too many times\",\n retryCount: this.retryCount,\n });\n }\n }\n }\n\n public asyncEmit: EmitFunc<keyof WithHeightAndUUID<EventMap>> = async (\n type,\n event,\n ) => {\n event.uuid = uuidv4();\n\n /*\n * More than 1 listener can be registered for an event type\n * Fortunately these are all set up during module init() so we have a consistent count\n * so we can count responses to resolve when complete\n * values are irrelevant as promise resolution is only used for flow control\n */\n let listenerCount = this.handled.get(type);\n if (!listenerCount) {\n // Setting listenerCount to 1 (the unhandled listener)\n listenerCount = 1;\n }\n let listenersResponded = 0;\n const prom = new Promise<void>((resolve, reject) => {\n const returnFunc = (ev: UUIDEvent) => {\n if (ev.uuid == event.uuid) {\n if (ev.status) {\n listenersResponded++;\n if (listenersResponded == listenerCount) {\n // All listeners have done their thing so we can remove listener, resolve and continue execution\n this.off(\"uuid\",\n returnFunc);\n resolve();\n }\n }\n else {\n // At least 1 listener is reporting an error. Reject and handle exception at the original asyncEmit location\n reject(ev.error);\n }\n }\n };\n this.on(\"uuid\",\n returnFunc);\n });\n this.emit(type,\n event);\n\n return prom;\n };\n\n private async processBlock(block: BlockResponse, block_results: BlockResultsResponse | BlockResultsResponse38, validators?: Validator[]) {\n let processStart: [number, number] = [0, 0];\n if (this.config.logLevel == \"silly\") {\n processStart = process.hrtime();\n }\n let endTimer;\n if (this.config.enablePrometheus) {\n endTimer = this.prometheus!.timeBlockProcessing();\n }\n const height = block.block.header.height;\n this.heightToProcess = height;\n this.log.debug(\"Processing block: %d\",\n height);\n // Initialize height & timestamp to be used for this block-processing run\n const timestamp = toRfc3339WithNanoseconds(block.block.header.time);\n\n // Use & await asyncEmit to ensure db insertions in order\n\n /*\n * Emit block information to any interested modules.\n * Primarily the required block module listens to this\n */\n await this.asyncEmit(\"block\",\n {\n value: {\n block,\n block_results,\n },\n height,\n timestamp,\n });\n this.log.silly(\"Modules handled block event\");\n\n let beginBlockEvents: readonly Event[] | readonly Event38[];\n let endBlockEvents: readonly Event[] | readonly Event38[];\n if ((block_results as BlockResultsResponse38).finalizeBlockEvents) {\n beginBlockEvents = (block_results as BlockResultsResponse38).finalizeBlockEvents.filter(x => x.attributes.find(a => decodeAttr(a.key) == \"mode\" && decodeAttr(a.value) == \"begin_block\")) as readonly Event38[];\n endBlockEvents = (block_results as BlockResultsResponse38).finalizeBlockEvents.filter(x => x.attributes.find(a => decodeAttr(a.key) == \"mode\" && decodeAttr(a.value) == \"end_block\")) as readonly Event38[];\n }\n else {\n beginBlockEvents = (block_results as BlockResultsResponse).beginBlockEvents;\n endBlockEvents = (block_results as BlockResultsResponse).endBlockEvents;\n }\n // Deal with begin_block events first\n await this.asyncEmit(\"begin_block\",\n {\n value: {\n events: beginBlockEvents!,\n validators,\n },\n height,\n timestamp,\n });\n\n this.log.silly(\"Modules handled begin_block events\");\n\n // Then individual tx_events\n await this.asyncEmit(\"tx_events\",\n {\n value: block_results.results,\n height,\n timestamp,\n });\n this.log.silly(\"Modules handled tx events\");\n\n // Emit details and result for each tx msg separately\n for (let t = 0; t < block.block.txs.length; t++) {\n const tx = Tx.decode(block.block.txs[t]);\n\n const result = block_results.results[t].code;\n const txlog = block_results.results[t].log;\n\n if (result != 0) {\n // Tx failed. Ignore\n continue;\n }\n if (tx.body && tx.body.memo != \"\") {\n const txHash = createHash(\"sha256\").update(block.block.txs[t])\n .digest(\"hex\");\n await this.asyncEmit(\"tx_memo\",\n {\n value: {\n txHash,\n txBody: tx.body,\n },\n height,\n timestamp,\n });\n }\n // parsing log rather than using events directly in order to have msg_index available to filter appropriate events for each msg\n let events: Array<{\n msg_index?: number\n events: (Event | Event38)[]\n }> = txlog\n ? JSON.parse(txlog)\n : [];\n if (events.length == 0) {\n const eventsToAdd: typeof events = [];\n this.log.silly(\"No events found in tx log. Parsing events for msg_index\");\n for (let m = 0; m < block_results.results[t].events.length; m++) {\n if (block_results.results[t].events[m].attributes.find(a => decodeAttr(a.key) == \"msg_index\")) {\n const mi = decodeAttr(block_results.results[t].events[m].attributes.find(a => decodeAttr(a.key) == \"msg_index\")?.value ?? \"\");\n if (mi != \"\") {\n const miNum = parseInt(mi);\n let ev = eventsToAdd.find(x => x.msg_index == miNum);\n if (!ev) {\n ev = {\n msg_index: miNum,\n events: [block_results.results[t].events[m]],\n };\n eventsToAdd.push(ev);\n }\n else {\n ev.events.push(block_results.results[t].events[m] as Event);\n }\n }\n }\n }\n events = events.concat(eventsToAdd);\n }\n const msgs = tx.body?.messages;\n\n if (msgs) {\n for (let i = 0; i < msgs.length; i++) {\n this.log.silly(\"Indexer broadcasting msg for handling: \" + msgs[i].typeUrl);\n const msgevents\n = msgs.length > 1\n ? events.find(x => x.msg_index == i)?.events\n : events[0].events;\n await this.asyncEmit(msgs[i].typeUrl as never,\n {\n value: {\n tx: msgs[i].value as never,\n events: msgevents,\n } as never,\n height,\n timestamp,\n });\n if (msgs[i].typeUrl == \"/cosmos.authz.v1beta1.MsgExec\") {\n const authzMsgs = MsgExec.decode(msgs[i].value).msgs;\n if (authzMsgs) {\n for (let r = 0; r < authzMsgs.length; r++) {\n this.log.silly(\"Indexer broadcasting msg for handling: \" + authzMsgs[r].typeUrl);\n const authzMsgEvents = msgevents?.reduce((events, evt) => {\n if (evt.attributes.filter(x => decodeAttr(x.key) == \"authz_msg_index\" && decodeAttr(x.value) == \"\" + r).length > 0) {\n events.push(evt);\n }\n return events;\n },\n [] as (Event | Event38)[]);\n await this.asyncEmit(authzMsgs[r].typeUrl as never,\n {\n value: {\n tx: authzMsgs[r].value as never,\n events: authzMsgEvents,\n } as never,\n height,\n timestamp,\n });\n }\n }\n }\n }\n }\n }\n this.log.silly(\"Modules handled msg events\");\n if (this.config.enablePrometheus) {\n this.prometheus!.recordTransactions(block.block.txs.length);\n }\n // Then deal with end_block events\n await this.asyncEmit(\"end_block\",\n {\n value: endBlockEvents!,\n height,\n timestamp,\n });\n this.log.silly(\"Modules handled end_block events\");\n if (this.config.logLevel == \"silly\") {\n const processEnd = process.hrtime(processStart);\n const processTime = processEnd[0] * 1000 + processEnd[1] / 1000000;\n this.log.silly(\"Processed block %d in %d ms\",\n height,\n processTime.toFixed(2));\n }\n\n if (this.config.enablePrometheus) {\n endTimer!();\n }\n if (this.config.enablePrometheus) {\n this.prometheus!.updateBlockMetrics(height, this.latestHeight, this.blockQueue.size());\n }\n }\n\n private async fetcher() {\n for (let i = this.heightToProcess; i <= this.latestHeight; i++) {\n this.log.debug(\"Fetching: \" + i);\n if (this.tryToRecover) {\n this.log.verbose(\"Exiting fetcher loop. Attempting to recover indexer\");\n break;\n }\n try {\n if (this.isMinimal(this.blockQueue)) {\n const timeoutPromise: Promise<[BlockResponse, BlockResultsResponse]> = new Promise((resolve, reject) => {\n setTimeout(reject,\n RPC_TIMEOUT_MS,\n false);\n });\n const toIndex = Promise.race([Promise.all([this.blockClient.block(i) as Promise<BlockResponse>, this.blockClient.blockResults(i) as Promise<BlockResultsResponse>]), timeoutPromise]).catch((e) => {\n this.log.error(\"Error fetching block: \" + i + \" : \" + e);\n this.tryToRecover = true;\n return Promise.resolve([]);\n }) as Promise<[BlockResponse, BlockResultsResponse]>;\n this.blockQueue.enqueue(toIndex);\n }\n else {\n const timeoutPromise: Promise<[BlockResponse, BlockResultsResponse, Uint8Array]> = new Promise((resolve, reject) => {\n setTimeout(reject,\n RPC_TIMEOUT_MS,\n false);\n });\n const q = QueryValidatorsRequest.fromPartial({\n pagination: {\n limit: PAGINATION_LIMITS.VALIDATORS,\n },\n });\n const vals = QueryValidatorsRequest.encode(q).finish();\n const toIndex = Promise.race([\n Promise.all([\n this.blockClient.block(i) as Promise<BlockResponse>,\n this.blockClient.blockResults(i) as Promise<BlockResultsResponse>,\n this.callABCI(\"/cosmos.staking.v1beta1.Query/Validators\",\n vals,\n i,\n false),\n ]),\n timeoutPromise,\n ]).catch((e) => {\n this.log.error(\"Error fetching block: \" + i + \" : \" + e);\n this.tryToRecover = true;\n return Promise.resolve([]);\n }) as Promise<[BlockResponse, BlockResultsResponse, Uint8Array]>;\n this.blockQueue.enqueue(toIndex);\n }\n await this.blockQueue.continue();\n if (this.tryToRecover) {\n this.retryCount++;\n throw new Error(\"RPC not responding\");\n }\n }\n catch (e) {\n this.log.error(\"Fetching error: \" + e);\n break;\n }\n }\n if (!this.tryToRecover) {\n this.blockQueue.setSynced();\n this.log.info(\"Synced to latest height\");\n }\n }\n\n public async callABCI(path: string, data: Uint8Array, height?: number, adHoc: boolean = true): Promise<Uint8Array> {\n try {\n const endTimer = this.prometheus?.timeRpcCall(path) ?? void 0;\n const abciq = await\n (adHoc\n ? this.client\n : this.blockClient).abciQuery({\n path,\n data,\n height: height,\n });\n endTimer?.();\n if (abciq) {\n return abciq.value;\n }\n else {\n this.tryToRecover = true;\n this.setStatus(\"FAILED\");\n this.prometheus?.recordError(\"abci_query_error\");\n throw new Error(\"RPC not responding. Query at: \" + path);\n }\n }\n catch (_e) {\n this.tryToRecover = true;\n this.setStatus(\"FAILED\");\n this.retryCount++;\n throw new Error(\"RPC not responding. Query at: \" + path);\n }\n }\n\n private newBlockReceived(height: number): void {\n if (this.blockTimeout) {\n clearTimeout(this.blockTimeout);\n }\n this.blockTimeout = setTimeout(() => {\n this.tryToRecover = true;\n }, 30000);\n this.log.info(\"Received new block: %d\",\n height);\n if (height == this.latestHeight) {\n return;\n }\n // If we are synced, add to end of queue\n if (this.blockQueue.synced && !this.tryToRecover) {\n this.latestHeight = height;\n if (this.blockQueue.size() + 1 == this.config.batchSize) {\n this.prometheus?.recordError(\"block_queue_full\");\n this.log.error(\"Block queue is full. Cannot add new block\");\n this.tryToRecover = true;\n this.retryCount++;\n return;\n }\n try {\n if (this.isMinimal(this.blockQueue)) {\n this.blockQueue.enqueue(Promise.all([this.client.block(height) as Promise<BlockResponse>, this.client.blockResults(height) as Promise<BlockResultsResponse>]).catch((e) => {\n this.log.error(\"Error fetching block: \" + height + \" : \" + e);\n\n return Promise.resolve([]);\n }) as Promise<[BlockResponse, BlockResultsResponse]>);\n }\n else {\n const q = QueryValidatorsRequest.fromPartial({\n pagination: {\n limit: 1000n,\n },\n });\n const vals = QueryValidatorsRequest.encode(q).finish();\n this.blockQueue.enqueue(Promise.all([\n this.client.block(height) as Promise<BlockResponse>,\n this.client.blockResults(height) as Promise<BlockResultsResponse>,\n this.callABCI(\"/cosmos.staking.v1beta1.Query/Validators\",\n vals,\n height,\n false),\n ]).catch((e) => {\n this.log.error(\"Error fetching block: \" + height + \" : \" + e);\n return Promise.resolve([]);\n }) as Promise<[BlockResponse, BlockResultsResponse, Uint8Array]>);\n }\n }\n catch (e) {\n this.log.error(\"New Block Received error: \" + e);\n }\n }\n else {\n this.latestHeight = height;\n }\n }\n\n private async pollForBlock() {\n try {\n const status = await this.client.status();\n if (status.syncInfo.latestBlockHeight > this.latestHeight) {\n while (this.latestHeight < status.syncInfo.latestBlockHeight) {\n this.newBlockReceived(this.latestHeight + 1);\n }\n }\n setTimeout(() => {\n this.pollForBlock();\n },\n this.config.pollingInterval);\n }\n catch (e) {\n this.log.error(\"Error polling for new block: \" + e);\n this.tryToRecover = true;\n this.retryCount++;\n }\n }\n\n private readGenesis(): Parser.Parser {\n if (this.config.genesisPath) {\n return fs.createReadStream(this.config.genesisPath).pipe(Parser.parser());\n }\n else {\n throw new Error(\"Genesis path not set\");\n }\n }\n\n private async setArrayReader(path: string, processor: (chunk: unknown) => Promise<void>): Promise<boolean> {\n const readPromise = new Promise<boolean>((resolve, reject) => {\n try {\n const filters = path.split(\".\");\n const pickers = filters.map(filter => Pick.pick({\n filter,\n }));\n let counter = 0;\n let chunkCounter = 0;\n\n // Wrapper processor that handles transaction chunking\n const chunkProcessor = async (data: unknown) => {\n chunkCounter++;\n this.log.debug(`Processing genesis chunk ${chunkCounter}`);\n\n await processor(data);\n\n // Commit and restart transaction every 5 chunks (5000 entries)\n // This prevents timeout on large genesis files\n if (chunkCounter % 5 === 0) {\n this.log.debug(`Committing transaction after chunk ${chunkCounter}`);\n await this.config.endTransaction(true);\n await this.config.beginTransaction();\n }\n };\n\n chain([\n this.readGenesis(),\n ...pickers,\n StreamArray.streamArray(),\n Batch.batch({\n batchSize: GENESIS_BATCH_SIZE,\n }),\n chunkProcessor,\n ])\n .on(\"data\",\n (data) => {\n if (data && Array.isArray(data)) {\n counter = counter + data.length;\n }\n })\n .on(\"end\",\n () => {\n this.log.info(`Processed ${counter} entries in ${chunkCounter} chunks`);\n resolve(true);\n });\n }\n catch (_e) {\n this.log.verbose(\"Error in setArrayReader: \" + _e);\n reject();\n }\n });\n\n return readPromise;\n }\n\n private async setValueReader(path: string, processor: (chunk: unknown) => Promise<void>): Promise<boolean> {\n const readPromise = new Promise<boolean>((resolve, reject) => {\n try {\n const filters = path.split(\".\");\n const pickers = filters.map(filter => Pick.pick({\n filter,\n }));\n\n let counter = 0;\n chain([this.readGenesis(), ...pickers, StreamValues.streamValues(), processor])\n .on(\"data\",\n (_data) => {\n counter++;\n })\n .on(\"end\",\n () => {\n this.log.info(`Processed ${counter} entries`);\n resolve(true);\n });\n }\n catch (_e) {\n reject();\n }\n });\n\n return readPromise;\n }\n\n private async parseGenesis() {\n this.log.info(\"Parsing genesis\");\n await this.config.beginTransaction();\n try {\n this.log.info(\"Starting genesis import\");\n this.log.debug(\"Importing genesis file...\");\n\n for (const [key, _value] of this.handled) {\n if (key.startsWith(\"genesis/\")) {\n const genesisEntry = key.split(\"/\");\n\n this.log.verbose(\"Importing \" + key + \"...\");\n if (genesisEntry[1] == \"array\") {\n await this.setArrayReader(genesisEntry[2],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async (data: any) => {\n await this.asyncEmit(key as never,\n {\n value: data.map((x: {\n value: never\n }) => x.value),\n } as never);\n return data;\n });\n }\n else {\n await this.setValueReader(genesisEntry[2],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async (data: any) => {\n await this.asyncEmit(key as never,\n {\n value: data.value,\n } as never);\n return data;\n });\n }\n }\n }\n\n this.log.info(\"Importing gen TXs...\");\n\n await this.setArrayReader(\"app_state.genutil.gen_txs\",\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async (data: any) => {\n for (let j = 0; j < data.length; j++) {\n const gentx = data[j].value;\n for (let i = 0; i < gentx.body.messages.length; i++) {\n const msg = gentx.body.messages[i];\n await this.asyncEmit((\"gentx\" + msg[\"@type\"]) as never,\n {\n value: msg,\n } as never);\n }\n }\n return data;\n });\n await this.config.endTransaction(true);\n\n this.log.info(\"Finished importing\");\n }\n catch (e) {\n try {\n await this.config.endTransaction(false);\n }\n catch (dbe) {\n this.prometheus?.recordError(\"database_error\");\n this.log.error(\"Error ending transaction. Must be a DB error: \" + dbe);\n }\n this.log.error(\"Failed to import genesis\");\n throw e;\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["timeoutPromise: ReturnType<typeof this.blockQueue.dequeue>","hrTime","uuidv4","processStart: [number, number]","beginBlockEvents: readonly Event[] | readonly Event38[]","endBlockEvents: readonly Event[] | readonly Event38[]","events: Array<{\n msg_index?: number\n events: (Event | Event38)[]\n }>","eventsToAdd: typeof events","events","timeoutPromise: Promise<[BlockResponse, BlockResultsResponse]>","timeoutPromise: Promise<[BlockResponse, BlockResultsResponse, Uint8Array]>"],"sources":["../../src/indexer/index.ts"],"sourcesContent":["/* eslint-disable @stylistic/no-multi-spaces */\n/* eslint-disable max-lines */\nimport {\n createHash,\n} from \"node:crypto\";\nimport * as fs from \"node:fs\";\n\nimport {\n BlockResponse, BlockResultsResponse, CometClient, connectComet, Event, toRfc3339WithNanoseconds,\n} from \"@cosmjs/tendermint-rpc\";\nimport {\n BlockResultsResponse as BlockResultsResponse38, Event as Event38,\n} from \"@cosmjs/tendermint-rpc/build/comet38/responses.js\";\nimport {\n MsgExec,\n} from \"cosmjs-types/cosmos/authz/v1beta1/tx.js\";\nimport {\n QueryValidatorsRequest,\n QueryValidatorsResponse,\n} from \"cosmjs-types/cosmos/staking/v1beta1/query.js\";\nimport {\n Validator,\n} from \"cosmjs-types/cosmos/staking/v1beta1/staking.js\";\nimport {\n Tx,\n} from \"cosmjs-types/cosmos/tx/v1beta1/tx.js\";\nimport Fastify, {\n FastifyInstance,\n} from \"fastify\";\nimport {\n chain,\n} from \"stream-chain\";\nimport Parser from \"stream-json\";\nimport Pick from \"stream-json/filters/Pick.js\";\nimport StreamArray from \"stream-json/streamers/StreamArray.js\";\nimport StreamValues from \"stream-json/streamers/StreamValues.js\";\nimport Batch from \"stream-json/utils/Batch.js\";\nimport {\n v4 as uuidv4,\n} from \"uuid\";\nimport * as winston from \"winston\";\n\nimport {\n DEFAULT_BATCH_SIZE, DEFAULT_HEALTH_CHECK_PORT, DEFAULT_POLLING_INTERVAL_MS, DEFAULT_PROMETHEUS_PORT, DEFAULT_START_HEIGHT,\n GENESIS_BATCH_SIZE, PAGINATION_LIMITS, PERIODIC_INTERVALS, QUEUE_DEQUEUE_TIMEOUT_MS, RPC_TIMEOUT_MS,\n} from \"../constants.js\";\nimport {\n EclesiaEmitter,\n} from \"../emitter/index.js\";\nimport {\n IndexerMetrics,\n} from \"../metrics/index.js\";\nimport {\n CircularBuffer,\n} from \"../promise-queue/index.js\";\nimport {\n BlockQueue, EcleciaIndexerConfig, EmitFunc, MinimalBlockQueue,\n UUIDEvent, WithHeightAndUUID,\n} from \"../types/index.js\";\nimport {\n decodeAttr,\n} from \"../utils/index.js\";\nimport {\n validateFilePath, validatePort, validatePositiveInteger, validateUrl,\n} from \"../validation/index.js\";\n\n/** Default configuration for the Eclesia indexer */\nexport const defaultIndexerConfig = {\n startHeight: DEFAULT_START_HEIGHT, // Start indexing from block 1\n batchSize: DEFAULT_BATCH_SIZE, // Process blocks in batches of 500\n modules: [], // No modules enabled by default\n getNextHeight: () => DEFAULT_START_HEIGHT, // Default height retrieval function\n logLevel: \"info\" as EcleciaIndexerConfig[\"logLevel\"], // Default log level\n usePolling: false, // Use WebSocket subscription by default\n pollingInterval: DEFAULT_POLLING_INTERVAL_MS, // Poll every 5 seconds when polling enabled\n shouldProcessGenesis: () => false, // Skip genesis processing by default\n minimal: true, // Use minimal indexing by default\n enableHealthcheck: true, // Enable health check server by default\n healthCheckPort: DEFAULT_HEALTH_CHECK_PORT, // Default health check port\n enablePrometheus: false, // Disable Prometheus metrics server by default\n prometheusPort: DEFAULT_PROMETHEUS_PORT, // Default Prometheus metrics server port\n init: () => Promise.resolve(), // No-op initialization function\n beginTransaction: () => Promise.resolve(), // No-op transaction begin function\n endTransaction: (_status: boolean) => Promise.resolve(), // No-op transaction end function\n};\n\n/**\n * Core blockchain indexer that connects to Tendermint RPC and processes blocks\n * Extends EclesiaEmitter to provide event-driven architecture for modules\n */\nexport class EcleciaIndexer extends EclesiaEmitter {\n /** Indexer configuration settings */\n public config: EcleciaIndexerConfig;\n\n /** Fastify HTTP server for health checks */\n private fastify: FastifyInstance | null = null;\n\n /** Prometheus HTTP server instance */\n private prometheusServer: FastifyInstance | null = null;\n\n /** Indicates if the indexer has started */\n private started: boolean = false;\n\n /** Queue for managing block processing pipeline */\n private blockQueue: BlockQueue;\n\n /** Latest block height from the chain */\n private latestHeight!: number;\n\n /** Next block height to process */\n public heightToProcess!: number;\n\n /** Whether the indexer has been initialized */\n private initialized = false;\n\n /** Prometheus metrics server instance */\n public prometheus: IndexerMetrics | null = null;\n\n /** Number of retry attempts for error recovery */\n private retryCount = 0;\n\n /** CometBFT client for ad-hoc queries */\n public client!: CometClient;\n\n /** CometBFT client for block and validator queries */\n public blockClient!: CometClient;\n\n /** Winston logger instance */\n public log: winston.Logger;\n\n /** Flag indicating if indexer should attempt recovery */\n private tryToRecover: boolean = false;\n\n /** Health check status for monitoring */\n private healthCheck = {\n status: \"CONNECTING\",\n };\n\n /** WebSocket subscription for new block notifications */\n private subscription: ReturnType<CometClient[\"subscribeNewBlock\"]> | null = null;\n\n /** Timeout handler for block reception */\n private blockTimeout: NodeJS.Timeout | null = null;\n\n /**\n * Creates a new Eclesia indexer instance\n * @param config - Indexer configuration options\n */\n constructor(config: EcleciaIndexerConfig) {\n super();\n\n // Validate required configuration\n validateUrl(config.rpcUrl, \"rpcUrl\");\n validatePositiveInteger(config.batchSize, \"batchSize\");\n\n // Validate optional genesis path if processing genesis\n if (config.genesisPath) {\n validateFilePath(config.genesisPath, \"genesisPath\");\n }\n\n // Validate health check port if provided\n if (config.healthCheckPort !== undefined) {\n validatePort(config.healthCheckPort, \"healthCheckPort\");\n }\n\n // Validate prometheus port if provided\n if (config.prometheusPort !== undefined) {\n validatePort(config.prometheusPort, \"prometheusPort\");\n }\n\n // Validate start height if provided\n if (config.startHeight !== undefined) {\n validatePositiveInteger(config.startHeight, \"startHeight\");\n }\n\n // Validate polling interval if provided\n if (config.pollingInterval !== undefined) {\n validatePositiveInteger(config.pollingInterval, \"pollingInterval\");\n }\n\n this.config = {\n ...defaultIndexerConfig,\n ...config,\n };\n\n // Initialize logger first so it can be used by queue error handler\n const {\n printf,\n } = winston.format;\n\n const eclesiaFormat = printf(({\n level, message, timestamp,\n }) => {\n return `${timestamp} [${level.toUpperCase()}]:\\t${message}`;\n });\n this.log = winston.createLogger({\n level: this.config.logLevel,\n defaultMeta: {\n service: \"Eclesia Indexer\",\n },\n transports: [\n new winston.transports.File({\n filename: \"error.log\",\n level: \"error\",\n }),\n new winston.transports.File({\n filename: \"combined.log\",\n }),\n new winston.transports.Console({\n format: winston.format.combine(winston.format.splat(),\n winston.format.timestamp(),\n eclesiaFormat,\n winston.format.colorize({\n all: true,\n })),\n }),\n ],\n });\n\n // Initialize block queue based on minimal or full indexing mode\n // Pass error handler that uses the logger\n const queueErrorHandler = (e: unknown) => {\n this.prometheus?.recordError(\"rpc\");\n this.log.error(\"Error enqueueing block data: \" + e);\n };\n\n if (this.config.minimal) {\n // Minimal mode: only store block and block results\n this.blockQueue = new CircularBuffer<[BlockResponse, BlockResultsResponse]>(this.config.batchSize, queueErrorHandler);\n }\n else {\n // Full mode: also store validator information\n this.blockQueue = new CircularBuffer<[BlockResponse, BlockResultsResponse, Uint8Array]>(this.config.batchSize, queueErrorHandler);\n }\n\n this.on(\"_unhandled\",\n (msg) => {\n if (msg.uuid) {\n this.log.verbose(\"Unhandled event: \" + msg.type);\n this.emit(\"uuid\",\n {\n status: true,\n uuid: msg.uuid,\n });\n }\n });\n if (this.config.enablePrometheus) {\n this.prometheus = new IndexerMetrics();\n this.prometheusServer = Fastify({\n logger: false,\n });\n this.prometheusServer.get(\"/metrics\",\n async (_req, res) => {\n res.header(\"Content-Type\", this.prometheus!.registry.contentType);\n res.send(await this.prometheus!.getMetrics());\n },\n );\n\n const prometheusPort = this.config.prometheusPort\n ?? (process.env.PROMETHEUS_PORT ? parseInt(process.env.PROMETHEUS_PORT, 10) : DEFAULT_PROMETHEUS_PORT);\n this.prometheusServer.listen({\n port: prometheusPort,\n host: \"0.0.0.0\",\n },\n (err) => {\n if (err) {\n this.log.error(\"Prometheus error: \" + err);\n this.prometheus?.recordError(\"metrics_server\");\n this.emit(\"fatal-error\", {\n error: err,\n message: \"Failed to start metrics server\",\n });\n }\n });\n }\n if (this.config.enableHealthcheck) {\n this.fastify = Fastify({\n logger: false,\n });\n this.fastify.get(\"/health\",\n async (_request, reply) => {\n const code = this.healthCheck.status == \"OK\"\n ? 200\n : 503;\n reply.code(code).send(this.healthCheck);\n });\n const healthPort = this.config.healthCheckPort\n ?? (process.env.HEALTH_CHECK_PORT ? parseInt(process.env.HEALTH_CHECK_PORT, 10) : DEFAULT_HEALTH_CHECK_PORT);\n this.fastify.listen({\n port: healthPort,\n host: \"0.0.0.0\",\n },\n (err) => {\n if (err) {\n this.log.error(\"Health check server error: \" + err);\n this.prometheus?.recordError(\"health_check_server\");\n this.emit(\"fatal-error\", {\n error: err,\n message: \"Failed to start health check server\",\n });\n }\n });\n }\n }\n\n private setStatus(status: string) {\n this.healthCheck.status = status;\n }\n\n private blockListener = {\n next: (data: {\n header: {\n height: number\n }\n }) => {\n this.newBlockReceived(data.header.height);\n },\n };\n\n private isMinimal(_blockqueue: BlockQueue): _blockqueue is MinimalBlockQueue {\n if (this.config.minimal) {\n return true;\n }\n else {\n return false;\n }\n }\n\n public async connect() {\n try {\n if (this.client && this.tryToRecover) {\n this.log.verbose(\"Recover from error. Attempting to disconnect from RPC\");\n this.client.disconnect();\n this.blockClient.disconnect();\n this.log.verbose(\"Disconnected from RPC\");\n }\n this.client = await connectComet(this.config.rpcUrl);\n this.log.info(\"Connected to RPC for ad hoc queries\");\n\n this.blockClient = await connectComet(this.config.rpcUrl);\n this.log.info(\"Connected to RPC for block & validator info\");\n\n return true;\n }\n catch (error) {\n this.log.error(\"RPC connection error: \" + error);\n this.prometheus?.recordError(\"rpc\");\n this.tryToRecover = true;\n return false;\n }\n }\n\n public stop() {\n this.started = false;\n }\n\n public async start() {\n this.started = true;\n if (this.blockQueue) {\n this.blockQueue.clear();\n this.log.verbose(\"Starting, clearing block queue\");\n }\n if (!this.initialized) {\n try {\n if (this.config.init) {\n await this.config.init();\n }\n }\n catch (e) {\n this.log.error(\"Failed to initialize indexer: \" + e);\n\n this.prometheus?.recordError(\"init_error\");\n this.setStatus(\"FAILED\");\n throw e;\n }\n if (await this.config.shouldProcessGenesis()) {\n try {\n if (this.config.genesisPath) {\n await this.parseGenesis();\n }\n }\n catch (e) {\n this.log.error(\"Failed to parse genesis: \" + e);\n\n this.prometheus?.recordError(\"genesis_error\");\n this.setStatus(\"FAILED\");\n throw e;\n }\n }\n this.initialized = true;\n }\n try {\n await this.connect();\n if (!this.config.usePolling && this.subscription) {\n this.subscription.removeListener(this.blockListener);\n this.subscription = null;\n this.log.verbose(\"Removed existing block listener and subscription\");\n }\n if (!this.config.usePolling) {\n this.subscription = this.client.subscribeNewBlock\n ? this.client.subscribeNewBlock()\n : null;\n }\n const status = await this.client.status();\n this.latestHeight = status.syncInfo.latestBlockHeight;\n this.log.info(\"Current chain height: \" + this.latestHeight);\n\n this.heightToProcess = await this.config.getNextHeight();\n if (this.config.usePolling) {\n this.pollForBlock();\n }\n else {\n if (this.subscription) {\n this.subscription.addListener(this.blockListener);\n }\n else {\n this.prometheus?.recordError(\"rpc\");\n throw new Error(\"Could not subscribe to new blocks\");\n }\n }\n }\n catch (e) {\n this.log.error(\"Failed to set up block listening: \" + e);\n this.prometheus?.recordError(\"rpc\");\n this.setStatus(\"FAILED\");\n throw e;\n }\n this.log.debug(\"Starting main processing loop\");\n this.tryToRecover = false;\n this.fetcher().catch((e) => {\n this.setStatus(\"FAILED\");\n\n this.prometheus?.recordError(\"rpc\");\n throw new Error(\"Error in fetching service: \" + e);\n });\n\n const hrTime = process.hrtime();\n let ms = hrTime[0] * 1000000 + hrTime[1] / 1000;\n while (this.blockQueue.size() > 0 && !this.tryToRecover && this.started && (this.config.endHeight === undefined || this.heightToProcess <= this.config.endHeight)) {\n if (this.config.enablePrometheus) {\n this.prometheus!.updateRetryCount(this.retryCount);\n }\n // await the dequeued promise is essentially awaiting fetched data for that block\n try {\n if (this.tryToRecover) {\n throw new Error(\"Exiting processing loop. Attempting to recover indexer\");\n }\n // Index block inside a db transaction to ensure data consistency\n await this.config.beginTransaction();\n this.log.silly(\"Started db tx\");\n let height, timestamp;\n if (this.isMinimal(this.blockQueue)) {\n const timeoutPromise: ReturnType<typeof this.blockQueue.dequeue> = new Promise((resolve, reject) => {\n setTimeout(reject, QUEUE_DEQUEUE_TIMEOUT_MS, []);\n });\n const toProcess = await Promise.race([this.blockQueue.dequeue(), timeoutPromise]);\n this.log.silly(\"Retrieved block data\");\n if (!toProcess || !toProcess[0] || !toProcess[1]) {\n this.prometheus?.recordError(\"rpc\");\n throw new Error(\"Could not fetch block\");\n }\n height = toProcess[0].block.header.height;\n timestamp = toRfc3339WithNanoseconds(toProcess[0].block.header.time);\n await this.processBlock(toProcess[0],\n toProcess[1]);\n }\n else {\n const timeoutPromise: ReturnType<typeof this.blockQueue.dequeue> = new Promise((resolve, reject) => {\n setTimeout(reject, QUEUE_DEQUEUE_TIMEOUT_MS, []);\n });\n const toProcess = await Promise.race([this.blockQueue.dequeue(), timeoutPromise]);\n this.log.silly(\"Retrieved block data\");\n if (!toProcess || !toProcess[0] || !toProcess[1] || !toProcess[2]) {\n this.prometheus?.recordError(\"rpc\");\n throw new Error(\"Could not fetch block\");\n }\n\n this.log.silly(\"Decoded block\");\n height = toProcess[0].block.header.height;\n timestamp = toRfc3339WithNanoseconds(toProcess[0].block.header.time);\n await this.processBlock(toProcess[0],\n toProcess[1],\n QueryValidatorsResponse.decode(toProcess[2]).validators);\n }\n // Emit events to trigger periodic operations every 50, 100 and 1000 blocks\n if (height % PERIODIC_INTERVALS.LARGE == 0) {\n const hrTime = process.hrtime();\n const newms = hrTime[0] * 1000000 + hrTime[1] / 1000;\n const duration = newms - ms;\n ms = newms;\n const rate = 1000000000 / duration;\n this.log.info(\"Processing:\" + rate.toFixed(2) + \"blocks/sec\");\n await this.asyncEmit(\"periodic/1000\",\n {\n value: null,\n height,\n timestamp,\n });\n }\n if (height % PERIODIC_INTERVALS.MEDIUM == 0) {\n await this.asyncEmit(\"periodic/100\",\n {\n value: null,\n height,\n timestamp,\n });\n }\n if (height % PERIODIC_INTERVALS.SMALL == 0) {\n await this.asyncEmit(\"periodic/50\",\n {\n value: null,\n height,\n timestamp,\n });\n }\n this.log.silly(\"Handled periodic events\");\n\n await this.config.endTransaction(true);\n\n this.log.silly(\"Committed db tx\");\n }\n catch (e) {\n this.prometheus?.recordError(\"block\");\n this.log.error(\"Block processing error: \" + e);\n this.setStatus(\"FAILED\");\n try {\n await this.config.endTransaction(false);\n }\n catch (dbe) {\n this.prometheus?.recordError(\"database\");\n this.log.error(\"Error ending transaction. Must be a DB error: \" + dbe);\n }\n this.tryToRecover = true;\n this.retryCount++;\n break;\n }\n this.retryCount = 0;\n this.setStatus(\"OK\");\n }\n if (this.config.endHeight !== undefined && this.heightToProcess >= this.config.endHeight!) {\n this.log.info(\"Reached configured end height. Stopping indexer.\");\n this.stop();\n }\n if (this.started) {\n if (this.retryCount < 3) {\n this.log.debug(\"Indexer retryCount: \" + this.retryCount);\n this.log.info(\"Indexer is restarting\");\n setTimeout(() => this.start(),\n this.retryCount * 5000);\n }\n else {\n this.log.info(\"Indexer failed too many times. Exiting.\");\n this.emit(\"fatal-error\", {\n error: new Error(\"Max retry attempts exceeded\"),\n message: \"Indexer failed too many times\",\n retryCount: this.retryCount,\n });\n }\n }\n }\n\n public asyncEmit: EmitFunc<keyof WithHeightAndUUID<EventMap>> = async (\n type,\n event,\n ) => {\n event.uuid = uuidv4();\n\n /*\n * More than 1 listener can be registered for an event type\n * Fortunately these are all set up during module init() so we have a consistent count\n * so we can count responses to resolve when complete\n * values are irrelevant as promise resolution is only used for flow control\n */\n let listenerCount = this.handled.get(type);\n if (!listenerCount) {\n // Setting listenerCount to 1 (the unhandled listener)\n listenerCount = 1;\n }\n let listenersResponded = 0;\n const prom = new Promise<void>((resolve, reject) => {\n const returnFunc = (ev: UUIDEvent) => {\n if (ev.uuid == event.uuid) {\n if (ev.status) {\n listenersResponded++;\n if (listenersResponded == listenerCount) {\n // All listeners have done their thing so we can remove listener, resolve and continue execution\n this.off(\"uuid\",\n returnFunc);\n resolve();\n }\n }\n else {\n // At least 1 listener is reporting an error. Reject and handle exception at the original asyncEmit location\n reject(ev.error);\n }\n }\n };\n this.on(\"uuid\",\n returnFunc);\n });\n this.emit(type,\n event);\n\n return prom;\n };\n\n private async processBlock(block: BlockResponse, block_results: BlockResultsResponse | BlockResultsResponse38, validators?: Validator[]) {\n let processStart: [number, number] = [0, 0];\n if (this.config.logLevel == \"silly\") {\n processStart = process.hrtime();\n }\n let endTimer;\n if (this.config.enablePrometheus) {\n endTimer = this.prometheus!.timeBlockProcessing();\n }\n const height = block.block.header.height;\n this.heightToProcess = height;\n this.log.debug(\"Processing block: %d\",\n height);\n // Initialize height & timestamp to be used for this block-processing run\n const timestamp = toRfc3339WithNanoseconds(block.block.header.time);\n\n // Use & await asyncEmit to ensure db insertions in order\n\n /*\n * Emit block information to any interested modules.\n * Primarily the required block module listens to this\n */\n await this.asyncEmit(\"block\",\n {\n value: {\n block,\n block_results,\n },\n height,\n timestamp,\n });\n this.log.silly(\"Modules handled block event\");\n\n let beginBlockEvents: readonly Event[] | readonly Event38[];\n let endBlockEvents: readonly Event[] | readonly Event38[];\n if ((block_results as BlockResultsResponse38).finalizeBlockEvents) {\n beginBlockEvents = (block_results as BlockResultsResponse38).finalizeBlockEvents.filter(x => x.attributes.find(a => decodeAttr(a.key) == \"mode\" && decodeAttr(a.value) == \"begin_block\")) as readonly Event38[];\n endBlockEvents = (block_results as BlockResultsResponse38).finalizeBlockEvents.filter(x => x.attributes.find(a => decodeAttr(a.key) == \"mode\" && decodeAttr(a.value) == \"end_block\")) as readonly Event38[];\n }\n else {\n beginBlockEvents = (block_results as BlockResultsResponse).beginBlockEvents;\n endBlockEvents = (block_results as BlockResultsResponse).endBlockEvents;\n }\n // Deal with begin_block events first\n await this.asyncEmit(\"begin_block\",\n {\n value: {\n events: beginBlockEvents!,\n validators,\n },\n height,\n timestamp,\n });\n\n this.log.silly(\"Modules handled begin_block events\");\n\n // Then individual tx_events\n await this.asyncEmit(\"tx_events\",\n {\n value: block_results.results,\n height,\n timestamp,\n });\n this.log.silly(\"Modules handled tx events\");\n\n // Emit details and result for each tx msg separately\n for (let t = 0; t < block.block.txs.length; t++) {\n const tx = Tx.decode(block.block.txs[t]);\n\n const result = block_results.results[t].code;\n const txlog = block_results.results[t].log;\n\n if (result != 0) {\n // Tx failed. Ignore\n continue;\n }\n if (tx.body && tx.body.memo != \"\") {\n const txHash = createHash(\"sha256\").update(block.block.txs[t])\n .digest(\"hex\");\n await this.asyncEmit(\"tx_memo\",\n {\n value: {\n txHash,\n txBody: tx.body,\n },\n height,\n timestamp,\n });\n }\n // parsing log rather than using events directly in order to have msg_index available to filter appropriate events for each msg\n let events: Array<{\n msg_index?: number\n events: (Event | Event38)[]\n }> = txlog\n ? JSON.parse(txlog)\n : [];\n if (events.length == 0) {\n const eventsToAdd: typeof events = [];\n this.log.silly(\"No events found in tx log. Parsing events for msg_index\");\n for (let m = 0; m < block_results.results[t].events.length; m++) {\n if (block_results.results[t].events[m].attributes.find(a => decodeAttr(a.key) == \"msg_index\")) {\n const mi = decodeAttr(block_results.results[t].events[m].attributes.find(a => decodeAttr(a.key) == \"msg_index\")?.value ?? \"\");\n if (mi != \"\") {\n const miNum = parseInt(mi);\n let ev = eventsToAdd.find(x => x.msg_index == miNum);\n if (!ev) {\n ev = {\n msg_index: miNum,\n events: [block_results.results[t].events[m]],\n };\n eventsToAdd.push(ev);\n }\n else {\n ev.events.push(block_results.results[t].events[m] as Event);\n }\n }\n }\n }\n events = events.concat(eventsToAdd);\n }\n const msgs = tx.body?.messages;\n\n if (msgs) {\n for (let i = 0; i < msgs.length; i++) {\n this.log.silly(\"Indexer broadcasting msg for handling: \" + msgs[i].typeUrl);\n const msgevents\n = msgs.length > 1\n ? events.find(x => x.msg_index == i)?.events\n : events[0].events;\n await this.asyncEmit(msgs[i].typeUrl as never,\n {\n value: {\n tx: msgs[i].value as never,\n events: msgevents,\n } as never,\n height,\n timestamp,\n });\n if (msgs[i].typeUrl == \"/cosmos.authz.v1beta1.MsgExec\") {\n const authzMsgs = MsgExec.decode(msgs[i].value).msgs;\n if (authzMsgs) {\n for (let r = 0; r < authzMsgs.length; r++) {\n this.log.silly(\"Indexer broadcasting msg for handling: \" + authzMsgs[r].typeUrl);\n const authzMsgEvents = msgevents?.reduce((events, evt) => {\n if (evt.attributes.filter(x => decodeAttr(x.key) == \"authz_msg_index\" && decodeAttr(x.value) == \"\" + r).length > 0) {\n events.push(evt);\n }\n return events;\n },\n [] as (Event | Event38)[]);\n await this.asyncEmit(authzMsgs[r].typeUrl as never,\n {\n value: {\n tx: authzMsgs[r].value as never,\n events: authzMsgEvents,\n } as never,\n height,\n timestamp,\n });\n }\n }\n }\n }\n }\n }\n this.log.silly(\"Modules handled msg events\");\n if (this.config.enablePrometheus) {\n this.prometheus!.recordTransactions(block.block.txs.length);\n }\n // Then deal with end_block events\n await this.asyncEmit(\"end_block\",\n {\n value: endBlockEvents!,\n height,\n timestamp,\n });\n this.log.silly(\"Modules handled end_block events\");\n if (this.config.logLevel == \"silly\") {\n const processEnd = process.hrtime(processStart);\n const processTime = processEnd[0] * 1000 + processEnd[1] / 1000000;\n this.log.silly(\"Processed block %d in %d ms\",\n height,\n processTime.toFixed(2));\n }\n\n if (this.config.enablePrometheus) {\n endTimer!();\n }\n if (this.config.enablePrometheus) {\n this.prometheus!.updateBlockMetrics(height, this.latestHeight, this.blockQueue.size());\n }\n }\n\n private async fetcher() {\n for (let i = this.heightToProcess; i <= this.latestHeight; i++) {\n this.log.debug(\"Fetching: \" + i);\n if (this.tryToRecover) {\n this.log.verbose(\"Exiting fetcher loop. Attempting to recover indexer\");\n break;\n }\n try {\n if (this.isMinimal(this.blockQueue)) {\n const timeoutPromise: Promise<[BlockResponse, BlockResultsResponse]> = new Promise((resolve, reject) => {\n setTimeout(reject,\n RPC_TIMEOUT_MS,\n false);\n });\n const toIndex = Promise.race([Promise.all([this.blockClient.block(i) as Promise<BlockResponse>, this.blockClient.blockResults(i) as Promise<BlockResultsResponse>]), timeoutPromise]).catch((e) => {\n this.log.error(\"Error fetching block: \" + i + \" : \" + e);\n this.tryToRecover = true;\n return Promise.resolve([]);\n }) as Promise<[BlockResponse, BlockResultsResponse]>;\n this.blockQueue.enqueue(toIndex);\n }\n else {\n const timeoutPromise: Promise<[BlockResponse, BlockResultsResponse, Uint8Array]> = new Promise((resolve, reject) => {\n setTimeout(reject,\n RPC_TIMEOUT_MS,\n false);\n });\n const q = QueryValidatorsRequest.fromPartial({\n pagination: {\n limit: PAGINATION_LIMITS.VALIDATORS,\n },\n });\n const vals = QueryValidatorsRequest.encode(q).finish();\n const toIndex = Promise.race([\n Promise.all([\n this.blockClient.block(i) as Promise<BlockResponse>,\n this.blockClient.blockResults(i) as Promise<BlockResultsResponse>,\n this.callABCI(\"/cosmos.staking.v1beta1.Query/Validators\",\n vals,\n i,\n false),\n ]),\n timeoutPromise,\n ]).catch((e) => {\n this.log.error(\"Error fetching block: \" + i + \" : \" + e);\n this.tryToRecover = true;\n return Promise.resolve([]);\n }) as Promise<[BlockResponse, BlockResultsResponse, Uint8Array]>;\n this.blockQueue.enqueue(toIndex);\n }\n await this.blockQueue.continue();\n if (this.tryToRecover) {\n this.retryCount++;\n throw new Error(\"RPC not responding\");\n }\n }\n catch (e) {\n this.log.error(\"Fetching error: \" + e);\n break;\n }\n }\n if (!this.tryToRecover) {\n this.blockQueue.setSynced();\n this.log.info(\"Synced to latest height\");\n }\n }\n\n public async callABCI(path: string, data: Uint8Array, height?: number, adHoc: boolean = true): Promise<Uint8Array> {\n try {\n const endTimer = this.prometheus?.timeRpcCall(path) ?? void 0;\n const abciq = await\n (adHoc\n ? this.client\n : this.blockClient).abciQuery({\n path,\n data,\n height: height,\n });\n endTimer?.();\n if (abciq) {\n return abciq.value;\n }\n else {\n this.tryToRecover = true;\n this.setStatus(\"FAILED\");\n this.prometheus?.recordError(\"rpc\");\n throw new Error(\"RPC not responding. Query at: \" + path);\n }\n }\n catch (_e) {\n this.tryToRecover = true;\n this.setStatus(\"FAILED\");\n this.retryCount++;\n throw new Error(\"RPC not responding. Query at: \" + path);\n }\n }\n\n private newBlockReceived(height: number): void {\n if (this.blockTimeout) {\n clearTimeout(this.blockTimeout);\n }\n this.blockTimeout = setTimeout(() => {\n this.tryToRecover = true;\n }, 30000);\n this.log.info(\"Received new block: %d\",\n height);\n if (height == this.latestHeight) {\n return;\n }\n // If we are synced, add to end of queue\n if (this.blockQueue.synced && !this.tryToRecover) {\n this.latestHeight = height;\n if (this.blockQueue.size() + 1 == this.config.batchSize) {\n this.prometheus?.recordError(\"block\");\n this.log.error(\"Block queue is full. Cannot add new block\");\n this.tryToRecover = true;\n this.retryCount++;\n return;\n }\n try {\n if (this.isMinimal(this.blockQueue)) {\n this.blockQueue.enqueue(Promise.all([this.client.block(height) as Promise<BlockResponse>, this.client.blockResults(height) as Promise<BlockResultsResponse>]).catch((e) => {\n this.log.error(\"Error fetching block: \" + height + \" : \" + e);\n\n return Promise.resolve([]);\n }) as Promise<[BlockResponse, BlockResultsResponse]>);\n }\n else {\n const q = QueryValidatorsRequest.fromPartial({\n pagination: {\n limit: 1000n,\n },\n });\n const vals = QueryValidatorsRequest.encode(q).finish();\n this.blockQueue.enqueue(Promise.all([\n this.client.block(height) as Promise<BlockResponse>,\n this.client.blockResults(height) as Promise<BlockResultsResponse>,\n this.callABCI(\"/cosmos.staking.v1beta1.Query/Validators\",\n vals,\n height,\n false),\n ]).catch((e) => {\n this.log.error(\"Error fetching block: \" + height + \" : \" + e);\n return Promise.resolve([]);\n }) as Promise<[BlockResponse, BlockResultsResponse, Uint8Array]>);\n }\n }\n catch (e) {\n this.log.error(\"New Block Received error: \" + e);\n }\n }\n else {\n this.latestHeight = height;\n }\n }\n\n private async pollForBlock() {\n try {\n const status = await this.client.status();\n if (status.syncInfo.latestBlockHeight > this.latestHeight) {\n while (this.latestHeight < status.syncInfo.latestBlockHeight) {\n this.newBlockReceived(this.latestHeight + 1);\n }\n }\n setTimeout(() => {\n this.pollForBlock();\n },\n this.config.pollingInterval);\n }\n catch (e) {\n this.log.error(\"Error polling for new block: \" + e);\n this.tryToRecover = true;\n this.retryCount++;\n }\n }\n\n private readGenesis(): Parser.Parser {\n if (this.config.genesisPath) {\n return fs.createReadStream(this.config.genesisPath).pipe(Parser.parser());\n }\n else {\n throw new Error(\"Genesis path not set\");\n }\n }\n\n private async setArrayReader(path: string, processor: (chunk: unknown) => Promise<void>): Promise<boolean> {\n const readPromise = new Promise<boolean>((resolve, reject) => {\n try {\n const filters = path.split(\".\");\n const pickers = filters.map(filter => Pick.pick({\n filter,\n }));\n let counter = 0;\n let chunkCounter = 0;\n\n // Wrapper processor that handles transaction chunking\n const chunkProcessor = async (data: unknown) => {\n chunkCounter++;\n this.log.debug(`Processing genesis chunk ${chunkCounter}`);\n\n await processor(data);\n\n // Commit and restart transaction every 5 chunks (5000 entries)\n // This prevents timeout on large genesis files\n if (chunkCounter % 5 === 0) {\n this.log.debug(`Committing transaction after chunk ${chunkCounter}`);\n await this.config.endTransaction(true);\n await this.config.beginTransaction();\n }\n };\n\n chain([\n this.readGenesis(),\n ...pickers,\n StreamArray.streamArray(),\n Batch.batch({\n batchSize: GENESIS_BATCH_SIZE,\n }),\n chunkProcessor,\n ])\n .on(\"data\",\n (data) => {\n if (data && Array.isArray(data)) {\n counter = counter + data.length;\n }\n })\n .on(\"end\",\n () => {\n this.log.info(`Processed ${counter} entries in ${chunkCounter} chunks`);\n resolve(true);\n });\n }\n catch (_e) {\n this.log.verbose(\"Error in setArrayReader: \" + _e);\n reject();\n }\n });\n\n return readPromise;\n }\n\n private async setValueReader(path: string, processor: (chunk: unknown) => Promise<void>): Promise<boolean> {\n const readPromise = new Promise<boolean>((resolve, reject) => {\n try {\n const filters = path.split(\".\");\n const pickers = filters.map(filter => Pick.pick({\n filter,\n }));\n\n let counter = 0;\n chain([this.readGenesis(), ...pickers, StreamValues.streamValues(), processor])\n .on(\"data\",\n (_data) => {\n counter++;\n })\n .on(\"end\",\n () => {\n this.log.info(`Processed ${counter} entries`);\n resolve(true);\n });\n }\n catch (_e) {\n reject();\n }\n });\n\n return readPromise;\n }\n\n private async parseGenesis() {\n this.log.info(\"Parsing genesis\");\n await this.config.beginTransaction();\n try {\n this.log.info(\"Starting genesis import\");\n this.log.debug(\"Importing genesis file...\");\n\n for (const [key, _value] of this.handled) {\n if (key.startsWith(\"genesis/\")) {\n const genesisEntry = key.split(\"/\");\n\n this.log.verbose(\"Importing \" + key + \"...\");\n if (genesisEntry[1] == \"array\") {\n await this.setArrayReader(genesisEntry[2],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async (data: any) => {\n await this.asyncEmit(key as never,\n {\n value: data.map((x: {\n value: never\n }) => x.value),\n } as never);\n return data;\n });\n }\n else {\n await this.setValueReader(genesisEntry[2],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async (data: any) => {\n await this.asyncEmit(key as never,\n {\n value: data.value,\n } as never);\n return data;\n });\n }\n }\n }\n\n this.log.info(\"Importing gen TXs...\");\n\n await this.setArrayReader(\"app_state.genutil.gen_txs\",\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async (data: any) => {\n for (let j = 0; j < data.length; j++) {\n const gentx = data[j].value;\n for (let i = 0; i < gentx.body.messages.length; i++) {\n const msg = gentx.body.messages[i];\n await this.asyncEmit((\"gentx\" + msg[\"@type\"]) as never,\n {\n value: msg,\n } as never);\n }\n }\n return data;\n });\n await this.config.endTransaction(true);\n\n this.log.info(\"Finished importing\");\n }\n catch (e) {\n try {\n await this.config.endTransaction(false);\n }\n catch (dbe) {\n this.prometheus?.recordError(\"database\");\n this.log.error(\"Error ending transaction. Must be a DB error: \" + dbe);\n }\n this.log.error(\"Failed to import genesis\");\n throw e;\n }\n }\n}\n"],"mappings":"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"}
@@ -24,6 +24,8 @@ var IndexerMetrics = class {
24
24
  errors;
25
25
  /** Counter for RPC errors */
26
26
  rpcErrors;
27
+ /** Counter for block processing errors */
28
+ processingErrors;
27
29
  /** Counter for database errors */
28
30
  databaseErrors;
29
31
  /** Histogram for block processing duration */
@@ -75,6 +77,11 @@ var IndexerMetrics = class {
75
77
  help: "Total number of RPC errors",
76
78
  registers: [this.registry]
77
79
  });
80
+ this.processingErrors = new prom_client.Counter({
81
+ name: "indexer_processing_errors_total",
82
+ help: "Total number of Block Processing errors",
83
+ registers: [this.registry]
84
+ });
78
85
  this.databaseErrors = new prom_client.Counter({
79
86
  name: "indexer_database_errors_total",
80
87
  help: "Total number of database errors",
@@ -92,7 +99,8 @@ var IndexerMetrics = class {
92
99
  .5,
93
100
  1,
94
101
  2,
95
- 5
102
+ 5,
103
+ 10
96
104
  ],
97
105
  registers: [this.registry]
98
106
  });
@@ -107,7 +115,8 @@ var IndexerMetrics = class {
107
115
  1,
108
116
  2,
109
117
  5,
110
- 10
118
+ 10,
119
+ 100
111
120
  ],
112
121
  labelNames: ["method"],
113
122
  registers: [this.registry]
@@ -122,7 +131,8 @@ var IndexerMetrics = class {
122
131
  .05,
123
132
  .1,
124
133
  .5,
125
- 1
134
+ 1,
135
+ 5
126
136
  ],
127
137
  labelNames: ["query_type"],
128
138
  registers: [this.registry]
@@ -159,6 +169,7 @@ var IndexerMetrics = class {
159
169
  this.errors.inc({ type });
160
170
  if (type === "rpc") this.rpcErrors.inc();
161
171
  else if (type === "database") this.databaseErrors.inc();
172
+ else if (type === "block") this.processingErrors.inc();
162
173
  }
163
174
  /**
164
175
  * Records block processing duration
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["Registry","Counter","Gauge","Histogram"],"sources":["../../src/metrics/index.ts"],"sourcesContent":["/**\n * Prometheus metrics for monitoring indexer performance and health\n * Exposes metrics for blocks indexed, queue depth, errors, and processing times\n */\n\nimport {\n collectDefaultMetrics, Counter, Gauge, Histogram, Registry,\n} from \"prom-client\";\n\n/** Prometheus metrics registry */\nexport class IndexerMetrics {\n /** Prometheus registry instance */\n public readonly registry: Registry;\n\n /** Counter for total blocks indexed */\n public readonly blocksIndexed: Counter;\n\n /** Gauge for current block height */\n public readonly currentHeight: Gauge;\n\n /** Gauge for latest chain block height */\n public readonly latestHeight: Gauge;\n\n /** Gauge for blocks behind chain tip */\n public readonly blocksBehind: Gauge;\n\n /** Gauge for block queue depth */\n public readonly queueDepth: Gauge;\n\n /** Counter for total errors */\n public readonly errors: Counter;\n\n /** Counter for RPC errors */\n public readonly rpcErrors: Counter;\n\n /** Counter for database errors */\n public readonly databaseErrors: Counter;\n\n /** Histogram for block processing duration */\n public readonly blockProcessingDuration: Histogram;\n\n /** Histogram for RPC call duration */\n public readonly rpcCallDuration: Histogram;\n\n /** Histogram for database query duration */\n public readonly databaseQueryDuration: Histogram;\n\n /** Gauge for retry count */\n public readonly retryCount: Gauge;\n\n /** Counter for total transactions processed */\n public readonly transactionsProcessed: Counter;\n\n constructor() {\n this.registry = new Registry();\n\n // Collect default Node.js metrics (memory, CPU, etc.)\n collectDefaultMetrics({\n register: this.registry,\n });\n\n // Block indexing metrics\n this.blocksIndexed = new Counter({\n name: \"indexer_blocks_indexed_total\",\n help: \"Total number of blocks indexed\",\n registers: [this.registry],\n });\n\n this.currentHeight = new Gauge({\n name: \"indexer_current_height\",\n help: \"Current block height being processed\",\n registers: [this.registry],\n });\n\n this.latestHeight = new Gauge({\n name: \"indexer_latest_chain_height\",\n help: \"Latest block height on the chain\",\n registers: [this.registry],\n });\n\n this.blocksBehind = new Gauge({\n name: \"indexer_blocks_behind\",\n help: \"Number of blocks behind chain tip\",\n registers: [this.registry],\n });\n\n this.queueDepth = new Gauge({\n name: \"indexer_queue_depth\",\n help: \"Current depth of block processing queue\",\n registers: [this.registry],\n });\n\n // Error metrics\n this.errors = new Counter({\n name: \"indexer_errors_total\",\n help: \"Total number of indexer errors\",\n labelNames: [\"type\"],\n registers: [this.registry],\n });\n\n this.rpcErrors = new Counter({\n name: \"indexer_rpc_errors_total\",\n help: \"Total number of RPC errors\",\n registers: [this.registry],\n });\n\n this.databaseErrors = new Counter({\n name: \"indexer_database_errors_total\",\n help: \"Total number of database errors\",\n registers: [this.registry],\n });\n\n // Performance metrics\n this.blockProcessingDuration = new Histogram({\n name: \"indexer_block_processing_duration_seconds\",\n help: \"Time spent processing a single block\",\n buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 2, 5],\n registers: [this.registry],\n });\n\n this.rpcCallDuration = new Histogram({\n name: \"indexer_rpc_call_duration_seconds\",\n help: \"Duration of RPC calls\",\n buckets: [0.01, 0.05, 0.1, 0.5, 1, 2, 5, 10],\n labelNames: [\"method\"],\n registers: [this.registry],\n });\n\n this.databaseQueryDuration = new Histogram({\n name: \"indexer_database_query_duration_seconds\",\n help: \"Duration of database queries\",\n buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1],\n labelNames: [\"query_type\"],\n registers: [this.registry],\n });\n\n // Operational metrics\n this.retryCount = new Gauge({\n name: \"indexer_retry_count\",\n help: \"Current number of retry attempts\",\n registers: [this.registry],\n });\n\n this.transactionsProcessed = new Counter({\n name: \"indexer_transactions_processed_total\",\n help: \"Total number of transactions processed\",\n registers: [this.registry],\n });\n }\n\n /**\n * Updates block indexing metrics\n * @param currentHeight - Current height being processed\n * @param latestHeight - Latest height on chain\n * @param queueSize - Current queue depth\n */\n updateBlockMetrics(currentHeight: number, latestHeight: number, queueSize: number) {\n this.blocksIndexed.inc();\n this.currentHeight.set(currentHeight);\n this.latestHeight.set(latestHeight);\n this.blocksBehind.set(latestHeight - currentHeight);\n this.queueDepth.set(queueSize);\n }\n\n /**\n * Records an error occurrence\n * @param type - Error type (rpc, database, processing, etc.)\n */\n recordError(type: string) {\n this.errors.inc({\n type,\n });\n\n if (type === \"rpc\") {\n this.rpcErrors.inc();\n }\n else if (type === \"database\") {\n this.databaseErrors.inc();\n }\n }\n\n /**\n * Records block processing duration\n * @param durationSeconds - Duration in seconds\n */\n recordBlockProcessing(durationSeconds: number) {\n this.blockProcessingDuration.observe(durationSeconds);\n }\n\n /**\n * Times a block processing operation\n * @returns End timer function to call when operation completes\n */\n timeBlockProcessing() {\n return this.blockProcessingDuration.startTimer();\n }\n\n /**\n * Records RPC call duration\n * @param method - RPC method name\n * @param durationSeconds - Duration in seconds\n */\n recordRpcCall(method: string, durationSeconds: number) {\n this.rpcCallDuration.observe({\n method,\n }, durationSeconds);\n }\n\n /**\n * Times an RPC call operation\n * @param method - RPC method name\n * @returns End timer function to call when operation completes\n */\n timeRpcCall(method: string) {\n return this.rpcCallDuration.startTimer({\n method,\n });\n }\n\n /**\n * Records database query duration\n * @param queryType - Type of query (select, insert, update, delete, etc.)\n * @param durationSeconds - Duration in seconds\n */\n recordDatabaseQuery(queryType: string, durationSeconds: number) {\n this.databaseQueryDuration.observe({\n query_type: queryType,\n }, durationSeconds);\n }\n\n /**\n * Times a database query operation\n * @param queryType - Type of query (select, insert, update, delete, etc.)\n * @returns End timer function to call when operation completes\n */\n timeDatabaseQuery(queryType: string) {\n return this.databaseQueryDuration.startTimer({\n query_type: queryType,\n });\n }\n\n /**\n * Updates the retry count gauge\n * @param count - Current retry count\n */\n updateRetryCount(count: number) {\n this.retryCount.set(count);\n }\n\n /**\n * Increments the retry count gauge by 1\n */\n incrementRetryCount() {\n this.retryCount.inc();\n }\n\n /**\n * Resets the retry count gauge to 0\n */\n resetRetryCount() {\n this.retryCount.set(0);\n }\n\n /**\n * Records transactions processed\n * @param count - Number of transactions to record (defaults to 1)\n */\n recordTransactions(count: number = 1) {\n this.transactionsProcessed.inc(count);\n }\n\n /**\n * Gets metrics in Prometheus format\n * @returns Prometheus metrics string\n */\n async getMetrics(): Promise<string> {\n return this.registry.metrics();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["Registry","Counter","Gauge","Histogram"],"sources":["../../src/metrics/index.ts"],"sourcesContent":["/**\n * Prometheus metrics for monitoring indexer performance and health\n * Exposes metrics for blocks indexed, queue depth, errors, and processing times\n */\n\nimport {\n collectDefaultMetrics, Counter, Gauge, Histogram, Registry,\n} from \"prom-client\";\n\n/** Prometheus metrics registry */\nexport class IndexerMetrics {\n /** Prometheus registry instance */\n public readonly registry: Registry;\n\n /** Counter for total blocks indexed */\n public readonly blocksIndexed: Counter;\n\n /** Gauge for current block height */\n public readonly currentHeight: Gauge;\n\n /** Gauge for latest chain block height */\n public readonly latestHeight: Gauge;\n\n /** Gauge for blocks behind chain tip */\n public readonly blocksBehind: Gauge;\n\n /** Gauge for block queue depth */\n public readonly queueDepth: Gauge;\n\n /** Counter for total errors */\n public readonly errors: Counter;\n\n /** Counter for RPC errors */\n public readonly rpcErrors: Counter;\n\n /** Counter for block processing errors */\n public readonly processingErrors: Counter;\n\n /** Counter for database errors */\n public readonly databaseErrors: Counter;\n\n /** Histogram for block processing duration */\n public readonly blockProcessingDuration: Histogram;\n\n /** Histogram for RPC call duration */\n public readonly rpcCallDuration: Histogram;\n\n /** Histogram for database query duration */\n public readonly databaseQueryDuration: Histogram;\n\n /** Gauge for retry count */\n public readonly retryCount: Gauge;\n\n /** Counter for total transactions processed */\n public readonly transactionsProcessed: Counter;\n\n constructor() {\n this.registry = new Registry();\n\n // Collect default Node.js metrics (memory, CPU, etc.)\n collectDefaultMetrics({\n register: this.registry,\n });\n\n // Block indexing metrics\n this.blocksIndexed = new Counter({\n name: \"indexer_blocks_indexed_total\",\n help: \"Total number of blocks indexed\",\n registers: [this.registry],\n });\n\n this.currentHeight = new Gauge({\n name: \"indexer_current_height\",\n help: \"Current block height being processed\",\n registers: [this.registry],\n });\n\n this.latestHeight = new Gauge({\n name: \"indexer_latest_chain_height\",\n help: \"Latest block height on the chain\",\n registers: [this.registry],\n });\n\n this.blocksBehind = new Gauge({\n name: \"indexer_blocks_behind\",\n help: \"Number of blocks behind chain tip\",\n registers: [this.registry],\n });\n\n this.queueDepth = new Gauge({\n name: \"indexer_queue_depth\",\n help: \"Current depth of block processing queue\",\n registers: [this.registry],\n });\n\n // Error metrics\n this.errors = new Counter({\n name: \"indexer_errors_total\",\n help: \"Total number of indexer errors\",\n labelNames: [\"type\"],\n registers: [this.registry],\n });\n\n this.rpcErrors = new Counter({\n name: \"indexer_rpc_errors_total\",\n help: \"Total number of RPC errors\",\n registers: [this.registry],\n });\n\n this.processingErrors = new Counter({\n name: \"indexer_processing_errors_total\",\n help: \"Total number of Block Processing errors\",\n registers: [this.registry],\n });\n\n this.databaseErrors = new Counter({\n name: \"indexer_database_errors_total\",\n help: \"Total number of database errors\",\n registers: [this.registry],\n });\n\n // Performance metrics\n this.blockProcessingDuration = new Histogram({\n name: \"indexer_block_processing_duration_seconds\",\n help: \"Time spent processing a single block\",\n buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 2, 5, 10],\n registers: [this.registry],\n });\n\n this.rpcCallDuration = new Histogram({\n name: \"indexer_rpc_call_duration_seconds\",\n help: \"Duration of RPC calls\",\n buckets: [0.01, 0.05, 0.1, 0.5, 1, 2, 5, 10, 100],\n labelNames: [\"method\"],\n registers: [this.registry],\n });\n\n this.databaseQueryDuration = new Histogram({\n name: \"indexer_database_query_duration_seconds\",\n help: \"Duration of database queries\",\n buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 5],\n labelNames: [\"query_type\"],\n registers: [this.registry],\n });\n\n // Operational metrics\n this.retryCount = new Gauge({\n name: \"indexer_retry_count\",\n help: \"Current number of retry attempts\",\n registers: [this.registry],\n });\n\n this.transactionsProcessed = new Counter({\n name: \"indexer_transactions_processed_total\",\n help: \"Total number of transactions processed\",\n registers: [this.registry],\n });\n }\n\n /**\n * Updates block indexing metrics\n * @param currentHeight - Current height being processed\n * @param latestHeight - Latest height on chain\n * @param queueSize - Current queue depth\n */\n updateBlockMetrics(currentHeight: number, latestHeight: number, queueSize: number) {\n this.blocksIndexed.inc();\n this.currentHeight.set(currentHeight);\n this.latestHeight.set(latestHeight);\n this.blocksBehind.set(latestHeight - currentHeight);\n this.queueDepth.set(queueSize);\n }\n\n /**\n * Records an error occurrence\n * @param type - Error type (rpc, database, processing, etc.)\n */\n recordError(type: string) {\n this.errors.inc({\n type,\n });\n\n if (type === \"rpc\") {\n this.rpcErrors.inc();\n }\n else if (type === \"database\") {\n this.databaseErrors.inc();\n }\n else if (type === \"block\") {\n this.processingErrors.inc();\n }\n }\n\n /**\n * Records block processing duration\n * @param durationSeconds - Duration in seconds\n */\n recordBlockProcessing(durationSeconds: number) {\n this.blockProcessingDuration.observe(durationSeconds);\n }\n\n /**\n * Times a block processing operation\n * @returns End timer function to call when operation completes\n */\n timeBlockProcessing() {\n return this.blockProcessingDuration.startTimer();\n }\n\n /**\n * Records RPC call duration\n * @param method - RPC method name\n * @param durationSeconds - Duration in seconds\n */\n recordRpcCall(method: string, durationSeconds: number) {\n this.rpcCallDuration.observe({\n method,\n }, durationSeconds);\n }\n\n /**\n * Times an RPC call operation\n * @param method - RPC method name\n * @returns End timer function to call when operation completes\n */\n timeRpcCall(method: string) {\n return this.rpcCallDuration.startTimer({\n method,\n });\n }\n\n /**\n * Records database query duration\n * @param queryType - Type of query (select, insert, update, delete, etc.)\n * @param durationSeconds - Duration in seconds\n */\n recordDatabaseQuery(queryType: string, durationSeconds: number) {\n this.databaseQueryDuration.observe({\n query_type: queryType,\n }, durationSeconds);\n }\n\n /**\n * Times a database query operation\n * @param queryType - Type of query (select, insert, update, delete, etc.)\n * @returns End timer function to call when operation completes\n */\n timeDatabaseQuery(queryType: string) {\n return this.databaseQueryDuration.startTimer({\n query_type: queryType,\n });\n }\n\n /**\n * Updates the retry count gauge\n * @param count - Current retry count\n */\n updateRetryCount(count: number) {\n this.retryCount.set(count);\n }\n\n /**\n * Increments the retry count gauge by 1\n */\n incrementRetryCount() {\n this.retryCount.inc();\n }\n\n /**\n * Resets the retry count gauge to 0\n */\n resetRetryCount() {\n this.retryCount.set(0);\n }\n\n /**\n * Records transactions processed\n * @param count - Number of transactions to record (defaults to 1)\n */\n recordTransactions(count: number = 1) {\n this.transactionsProcessed.inc(count);\n }\n\n /**\n * Gets metrics in Prometheus format\n * @returns Prometheus metrics string\n */\n async getMetrics(): Promise<string> {\n return this.registry.metrics();\n }\n}\n"],"mappings":"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"}
@@ -20,6 +20,8 @@ declare class IndexerMetrics {
20
20
  readonly errors: Counter;
21
21
  /** Counter for RPC errors */
22
22
  readonly rpcErrors: Counter;
23
+ /** Counter for block processing errors */
24
+ readonly processingErrors: Counter;
23
25
  /** Counter for database errors */
24
26
  readonly databaseErrors: Counter;
25
27
  /** Histogram for block processing duration */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/metrics/index.ts"],"sourcesContent":[],"mappings":";;;;;AAkBiC,cARpB,cAAA,CAQoB;EAGD;EAGA,SAAA,QAAA,EAZJ,QAYI;EAGF;EAGJ,SAAA,aAAA,EAfO,OAeP;EAGG;EAGK,SAAA,aAAA,EAlBD,KAkBC;EAGS;EAGR,SAAA,YAAA,EArBH,KAqBG;EAGM;EAGX,SAAA,YAAA,EAxBE,KAwBF;EAGW;EA8IpB,SAAA,UAAA,EAtKS,KAsKT;EAAA;EAoBO,SAAA,MAAA,EAvLF,OAuLE;EAAA;EAsBS,SAAA,SAAA,EA1MR,OA0MQ;EAAA;EAwCf,SAAA,cAAA,EA/OY,OA+OZ;EAAO;oCA5Oc;;4BAGR;;kCAGM;;uBAGX;;kCAGW;;;;;;;;;;;;;;;;;;;;;;;mCA8IpB,QAAA;;;;;;;;;;;;yCAoBO,QAAA;;;;;;;;;;;;kDAsBS,QAAA;;;;;;;;;;;;;;;;;;;;;;;gBAwCf"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/metrics/index.ts"],"sourcesContent":[],"mappings":";;;;;AAkBiC,cARpB,cAAA,CAQoB;EAGD;EAGA,SAAA,QAAA,EAZJ,QAYI;EAGF;EAGJ,SAAA,aAAA,EAfO,OAeP;EAGG;EAGO,SAAA,aAAA,EAlBH,KAkBG;EAGF;EAGS,SAAA,YAAA,EArBX,KAqBW;EAGR;EAGM,SAAA,YAAA,EAxBT,KAwBS;EAGX;EAGW,SAAA,UAAA,EA3BX,KA2BW;EAuJpB;EAAA,SAAA,MAAA,EA/KK,OA+KL;EAoBO;EAAA,SAAA,SAAA,EAhMC,OAgMD;EAsBS;EAAA,SAAA,gBAAA,EAnND,OAmNC;EAwCf;EAAO,SAAA,cAAA,EAxPK,OAwPL;;oCArPc;;4BAGR;;kCAGM;;uBAGX;;kCAGW;;;;;;;;;;;;;;;;;;;;;;;mCAuJpB,QAAA;;;;;;;;;;;;yCAoBO,QAAA;;;;;;;;;;;;kDAsBS,QAAA;;;;;;;;;;;;;;;;;;;;;;;gBAwCf"}
@@ -20,6 +20,8 @@ declare class IndexerMetrics {
20
20
  readonly errors: Counter;
21
21
  /** Counter for RPC errors */
22
22
  readonly rpcErrors: Counter;
23
+ /** Counter for block processing errors */
24
+ readonly processingErrors: Counter;
23
25
  /** Counter for database errors */
24
26
  readonly databaseErrors: Counter;
25
27
  /** Histogram for block processing duration */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/metrics/index.ts"],"sourcesContent":[],"mappings":";;;;;AAkBiC,cARpB,cAAA,CAQoB;EAGD;EAGA,SAAA,QAAA,EAZJ,QAYI;EAGF;EAGJ,SAAA,aAAA,EAfO,OAeP;EAGG;EAGK,SAAA,aAAA,EAlBD,KAkBC;EAGS;EAGR,SAAA,YAAA,EArBH,KAqBG;EAGM;EAGX,SAAA,YAAA,EAxBE,KAwBF;EAGW;EA8IpB,SAAA,UAAA,EAtKS,KAsKT;EAAA;EAoBO,SAAA,MAAA,EAvLF,OAuLE;EAAA;EAsBS,SAAA,SAAA,EA1MR,OA0MQ;EAAA;EAwCf,SAAA,cAAA,EA/OY,OA+OZ;EAAO;oCA5Oc;;4BAGR;;kCAGM;;uBAGX;;kCAGW;;;;;;;;;;;;;;;;;;;;;;;mCA8IpB,QAAA;;;;;;;;;;;;yCAoBO,QAAA;;;;;;;;;;;;kDAsBS,QAAA;;;;;;;;;;;;;;;;;;;;;;;gBAwCf"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/metrics/index.ts"],"sourcesContent":[],"mappings":";;;;;AAkBiC,cARpB,cAAA,CAQoB;EAGD;EAGA,SAAA,QAAA,EAZJ,QAYI;EAGF;EAGJ,SAAA,aAAA,EAfO,OAeP;EAGG;EAGO,SAAA,aAAA,EAlBH,KAkBG;EAGF;EAGS,SAAA,YAAA,EArBX,KAqBW;EAGR;EAGM,SAAA,YAAA,EAxBT,KAwBS;EAGX;EAGW,SAAA,UAAA,EA3BX,KA2BW;EAuJpB;EAAA,SAAA,MAAA,EA/KK,OA+KL;EAoBO;EAAA,SAAA,SAAA,EAhMC,OAgMD;EAsBS;EAAA,SAAA,gBAAA,EAnND,OAmNC;EAwCf;EAAO,SAAA,cAAA,EAxPK,OAwPL;;oCArPc;;4BAGR;;kCAGM;;uBAGX;;kCAGW;;;;;;;;;;;;;;;;;;;;;;;mCAuJpB,QAAA;;;;;;;;;;;;yCAoBO,QAAA;;;;;;;;;;;;kDAsBS,QAAA;;;;;;;;;;;;;;;;;;;;;;;gBAwCf"}
@@ -23,6 +23,8 @@ var IndexerMetrics = class {
23
23
  errors;
24
24
  /** Counter for RPC errors */
25
25
  rpcErrors;
26
+ /** Counter for block processing errors */
27
+ processingErrors;
26
28
  /** Counter for database errors */
27
29
  databaseErrors;
28
30
  /** Histogram for block processing duration */
@@ -74,6 +76,11 @@ var IndexerMetrics = class {
74
76
  help: "Total number of RPC errors",
75
77
  registers: [this.registry]
76
78
  });
79
+ this.processingErrors = new Counter({
80
+ name: "indexer_processing_errors_total",
81
+ help: "Total number of Block Processing errors",
82
+ registers: [this.registry]
83
+ });
77
84
  this.databaseErrors = new Counter({
78
85
  name: "indexer_database_errors_total",
79
86
  help: "Total number of database errors",
@@ -91,7 +98,8 @@ var IndexerMetrics = class {
91
98
  .5,
92
99
  1,
93
100
  2,
94
- 5
101
+ 5,
102
+ 10
95
103
  ],
96
104
  registers: [this.registry]
97
105
  });
@@ -106,7 +114,8 @@ var IndexerMetrics = class {
106
114
  1,
107
115
  2,
108
116
  5,
109
- 10
117
+ 10,
118
+ 100
110
119
  ],
111
120
  labelNames: ["method"],
112
121
  registers: [this.registry]
@@ -121,7 +130,8 @@ var IndexerMetrics = class {
121
130
  .05,
122
131
  .1,
123
132
  .5,
124
- 1
133
+ 1,
134
+ 5
125
135
  ],
126
136
  labelNames: ["query_type"],
127
137
  registers: [this.registry]
@@ -158,6 +168,7 @@ var IndexerMetrics = class {
158
168
  this.errors.inc({ type });
159
169
  if (type === "rpc") this.rpcErrors.inc();
160
170
  else if (type === "database") this.databaseErrors.inc();
171
+ else if (type === "block") this.processingErrors.inc();
161
172
  }
162
173
  /**
163
174
  * Records block processing duration
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/metrics/index.ts"],"sourcesContent":["/**\n * Prometheus metrics for monitoring indexer performance and health\n * Exposes metrics for blocks indexed, queue depth, errors, and processing times\n */\n\nimport {\n collectDefaultMetrics, Counter, Gauge, Histogram, Registry,\n} from \"prom-client\";\n\n/** Prometheus metrics registry */\nexport class IndexerMetrics {\n /** Prometheus registry instance */\n public readonly registry: Registry;\n\n /** Counter for total blocks indexed */\n public readonly blocksIndexed: Counter;\n\n /** Gauge for current block height */\n public readonly currentHeight: Gauge;\n\n /** Gauge for latest chain block height */\n public readonly latestHeight: Gauge;\n\n /** Gauge for blocks behind chain tip */\n public readonly blocksBehind: Gauge;\n\n /** Gauge for block queue depth */\n public readonly queueDepth: Gauge;\n\n /** Counter for total errors */\n public readonly errors: Counter;\n\n /** Counter for RPC errors */\n public readonly rpcErrors: Counter;\n\n /** Counter for database errors */\n public readonly databaseErrors: Counter;\n\n /** Histogram for block processing duration */\n public readonly blockProcessingDuration: Histogram;\n\n /** Histogram for RPC call duration */\n public readonly rpcCallDuration: Histogram;\n\n /** Histogram for database query duration */\n public readonly databaseQueryDuration: Histogram;\n\n /** Gauge for retry count */\n public readonly retryCount: Gauge;\n\n /** Counter for total transactions processed */\n public readonly transactionsProcessed: Counter;\n\n constructor() {\n this.registry = new Registry();\n\n // Collect default Node.js metrics (memory, CPU, etc.)\n collectDefaultMetrics({\n register: this.registry,\n });\n\n // Block indexing metrics\n this.blocksIndexed = new Counter({\n name: \"indexer_blocks_indexed_total\",\n help: \"Total number of blocks indexed\",\n registers: [this.registry],\n });\n\n this.currentHeight = new Gauge({\n name: \"indexer_current_height\",\n help: \"Current block height being processed\",\n registers: [this.registry],\n });\n\n this.latestHeight = new Gauge({\n name: \"indexer_latest_chain_height\",\n help: \"Latest block height on the chain\",\n registers: [this.registry],\n });\n\n this.blocksBehind = new Gauge({\n name: \"indexer_blocks_behind\",\n help: \"Number of blocks behind chain tip\",\n registers: [this.registry],\n });\n\n this.queueDepth = new Gauge({\n name: \"indexer_queue_depth\",\n help: \"Current depth of block processing queue\",\n registers: [this.registry],\n });\n\n // Error metrics\n this.errors = new Counter({\n name: \"indexer_errors_total\",\n help: \"Total number of indexer errors\",\n labelNames: [\"type\"],\n registers: [this.registry],\n });\n\n this.rpcErrors = new Counter({\n name: \"indexer_rpc_errors_total\",\n help: \"Total number of RPC errors\",\n registers: [this.registry],\n });\n\n this.databaseErrors = new Counter({\n name: \"indexer_database_errors_total\",\n help: \"Total number of database errors\",\n registers: [this.registry],\n });\n\n // Performance metrics\n this.blockProcessingDuration = new Histogram({\n name: \"indexer_block_processing_duration_seconds\",\n help: \"Time spent processing a single block\",\n buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 2, 5],\n registers: [this.registry],\n });\n\n this.rpcCallDuration = new Histogram({\n name: \"indexer_rpc_call_duration_seconds\",\n help: \"Duration of RPC calls\",\n buckets: [0.01, 0.05, 0.1, 0.5, 1, 2, 5, 10],\n labelNames: [\"method\"],\n registers: [this.registry],\n });\n\n this.databaseQueryDuration = new Histogram({\n name: \"indexer_database_query_duration_seconds\",\n help: \"Duration of database queries\",\n buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1],\n labelNames: [\"query_type\"],\n registers: [this.registry],\n });\n\n // Operational metrics\n this.retryCount = new Gauge({\n name: \"indexer_retry_count\",\n help: \"Current number of retry attempts\",\n registers: [this.registry],\n });\n\n this.transactionsProcessed = new Counter({\n name: \"indexer_transactions_processed_total\",\n help: \"Total number of transactions processed\",\n registers: [this.registry],\n });\n }\n\n /**\n * Updates block indexing metrics\n * @param currentHeight - Current height being processed\n * @param latestHeight - Latest height on chain\n * @param queueSize - Current queue depth\n */\n updateBlockMetrics(currentHeight: number, latestHeight: number, queueSize: number) {\n this.blocksIndexed.inc();\n this.currentHeight.set(currentHeight);\n this.latestHeight.set(latestHeight);\n this.blocksBehind.set(latestHeight - currentHeight);\n this.queueDepth.set(queueSize);\n }\n\n /**\n * Records an error occurrence\n * @param type - Error type (rpc, database, processing, etc.)\n */\n recordError(type: string) {\n this.errors.inc({\n type,\n });\n\n if (type === \"rpc\") {\n this.rpcErrors.inc();\n }\n else if (type === \"database\") {\n this.databaseErrors.inc();\n }\n }\n\n /**\n * Records block processing duration\n * @param durationSeconds - Duration in seconds\n */\n recordBlockProcessing(durationSeconds: number) {\n this.blockProcessingDuration.observe(durationSeconds);\n }\n\n /**\n * Times a block processing operation\n * @returns End timer function to call when operation completes\n */\n timeBlockProcessing() {\n return this.blockProcessingDuration.startTimer();\n }\n\n /**\n * Records RPC call duration\n * @param method - RPC method name\n * @param durationSeconds - Duration in seconds\n */\n recordRpcCall(method: string, durationSeconds: number) {\n this.rpcCallDuration.observe({\n method,\n }, durationSeconds);\n }\n\n /**\n * Times an RPC call operation\n * @param method - RPC method name\n * @returns End timer function to call when operation completes\n */\n timeRpcCall(method: string) {\n return this.rpcCallDuration.startTimer({\n method,\n });\n }\n\n /**\n * Records database query duration\n * @param queryType - Type of query (select, insert, update, delete, etc.)\n * @param durationSeconds - Duration in seconds\n */\n recordDatabaseQuery(queryType: string, durationSeconds: number) {\n this.databaseQueryDuration.observe({\n query_type: queryType,\n }, durationSeconds);\n }\n\n /**\n * Times a database query operation\n * @param queryType - Type of query (select, insert, update, delete, etc.)\n * @returns End timer function to call when operation completes\n */\n timeDatabaseQuery(queryType: string) {\n return this.databaseQueryDuration.startTimer({\n query_type: queryType,\n });\n }\n\n /**\n * Updates the retry count gauge\n * @param count - Current retry count\n */\n updateRetryCount(count: number) {\n this.retryCount.set(count);\n }\n\n /**\n * Increments the retry count gauge by 1\n */\n incrementRetryCount() {\n this.retryCount.inc();\n }\n\n /**\n * Resets the retry count gauge to 0\n */\n resetRetryCount() {\n this.retryCount.set(0);\n }\n\n /**\n * Records transactions processed\n * @param count - Number of transactions to record (defaults to 1)\n */\n recordTransactions(count: number = 1) {\n this.transactionsProcessed.inc(count);\n }\n\n /**\n * Gets metrics in Prometheus format\n * @returns Prometheus metrics string\n */\n async getMetrics(): Promise<string> {\n return this.registry.metrics();\n }\n}\n"],"mappings":";;;;;;;;AAUA,IAAa,iBAAb,MAA4B;;CAE1B,AAAgB;;CAGhB,AAAgB;;CAGhB,AAAgB;;CAGhB,AAAgB;;CAGhB,AAAgB;;CAGhB,AAAgB;;CAGhB,AAAgB;;CAGhB,AAAgB;;CAGhB,AAAgB;;CAGhB,AAAgB;;CAGhB,AAAgB;;CAGhB,AAAgB;;CAGhB,AAAgB;;CAGhB,AAAgB;CAEhB,cAAc;AACZ,OAAK,WAAW,IAAI,UAAU;AAG9B,wBAAsB,EACpB,UAAU,KAAK,UAChB,CAAC;AAGF,OAAK,gBAAgB,IAAI,QAAQ;GAC/B,MAAM;GACN,MAAM;GACN,WAAW,CAAC,KAAK,SAAS;GAC3B,CAAC;AAEF,OAAK,gBAAgB,IAAI,MAAM;GAC7B,MAAM;GACN,MAAM;GACN,WAAW,CAAC,KAAK,SAAS;GAC3B,CAAC;AAEF,OAAK,eAAe,IAAI,MAAM;GAC5B,MAAM;GACN,MAAM;GACN,WAAW,CAAC,KAAK,SAAS;GAC3B,CAAC;AAEF,OAAK,eAAe,IAAI,MAAM;GAC5B,MAAM;GACN,MAAM;GACN,WAAW,CAAC,KAAK,SAAS;GAC3B,CAAC;AAEF,OAAK,aAAa,IAAI,MAAM;GAC1B,MAAM;GACN,MAAM;GACN,WAAW,CAAC,KAAK,SAAS;GAC3B,CAAC;AAGF,OAAK,SAAS,IAAI,QAAQ;GACxB,MAAM;GACN,MAAM;GACN,YAAY,CAAC,OAAO;GACpB,WAAW,CAAC,KAAK,SAAS;GAC3B,CAAC;AAEF,OAAK,YAAY,IAAI,QAAQ;GAC3B,MAAM;GACN,MAAM;GACN,WAAW,CAAC,KAAK,SAAS;GAC3B,CAAC;AAEF,OAAK,iBAAiB,IAAI,QAAQ;GAChC,MAAM;GACN,MAAM;GACN,WAAW,CAAC,KAAK,SAAS;GAC3B,CAAC;AAGF,OAAK,0BAA0B,IAAI,UAAU;GAC3C,MAAM;GACN,MAAM;GACN,SAAS;IAAC;IAAO;IAAO;IAAM;IAAM;IAAK;IAAK;IAAG;IAAG;IAAE;GACtD,WAAW,CAAC,KAAK,SAAS;GAC3B,CAAC;AAEF,OAAK,kBAAkB,IAAI,UAAU;GACnC,MAAM;GACN,MAAM;GACN,SAAS;IAAC;IAAM;IAAM;IAAK;IAAK;IAAG;IAAG;IAAG;IAAG;GAC5C,YAAY,CAAC,SAAS;GACtB,WAAW,CAAC,KAAK,SAAS;GAC3B,CAAC;AAEF,OAAK,wBAAwB,IAAI,UAAU;GACzC,MAAM;GACN,MAAM;GACN,SAAS;IAAC;IAAO;IAAO;IAAM;IAAM;IAAK;IAAK;IAAE;GAChD,YAAY,CAAC,aAAa;GAC1B,WAAW,CAAC,KAAK,SAAS;GAC3B,CAAC;AAGF,OAAK,aAAa,IAAI,MAAM;GAC1B,MAAM;GACN,MAAM;GACN,WAAW,CAAC,KAAK,SAAS;GAC3B,CAAC;AAEF,OAAK,wBAAwB,IAAI,QAAQ;GACvC,MAAM;GACN,MAAM;GACN,WAAW,CAAC,KAAK,SAAS;GAC3B,CAAC;;;;;;;;CASJ,mBAAmB,eAAuB,cAAsB,WAAmB;AACjF,OAAK,cAAc,KAAK;AACxB,OAAK,cAAc,IAAI,cAAc;AACrC,OAAK,aAAa,IAAI,aAAa;AACnC,OAAK,aAAa,IAAI,eAAe,cAAc;AACnD,OAAK,WAAW,IAAI,UAAU;;;;;;CAOhC,YAAY,MAAc;AACxB,OAAK,OAAO,IAAI,EACd,MACD,CAAC;AAEF,MAAI,SAAS,MACX,MAAK,UAAU,KAAK;WAEb,SAAS,WAChB,MAAK,eAAe,KAAK;;;;;;CAQ7B,sBAAsB,iBAAyB;AAC7C,OAAK,wBAAwB,QAAQ,gBAAgB;;;;;;CAOvD,sBAAsB;AACpB,SAAO,KAAK,wBAAwB,YAAY;;;;;;;CAQlD,cAAc,QAAgB,iBAAyB;AACrD,OAAK,gBAAgB,QAAQ,EAC3B,QACD,EAAE,gBAAgB;;;;;;;CAQrB,YAAY,QAAgB;AAC1B,SAAO,KAAK,gBAAgB,WAAW,EACrC,QACD,CAAC;;;;;;;CAQJ,oBAAoB,WAAmB,iBAAyB;AAC9D,OAAK,sBAAsB,QAAQ,EACjC,YAAY,WACb,EAAE,gBAAgB;;;;;;;CAQrB,kBAAkB,WAAmB;AACnC,SAAO,KAAK,sBAAsB,WAAW,EAC3C,YAAY,WACb,CAAC;;;;;;CAOJ,iBAAiB,OAAe;AAC9B,OAAK,WAAW,IAAI,MAAM;;;;;CAM5B,sBAAsB;AACpB,OAAK,WAAW,KAAK;;;;;CAMvB,kBAAkB;AAChB,OAAK,WAAW,IAAI,EAAE;;;;;;CAOxB,mBAAmB,QAAgB,GAAG;AACpC,OAAK,sBAAsB,IAAI,MAAM;;;;;;CAOvC,MAAM,aAA8B;AAClC,SAAO,KAAK,SAAS,SAAS"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/metrics/index.ts"],"sourcesContent":["/**\n * Prometheus metrics for monitoring indexer performance and health\n * Exposes metrics for blocks indexed, queue depth, errors, and processing times\n */\n\nimport {\n collectDefaultMetrics, Counter, Gauge, Histogram, Registry,\n} from \"prom-client\";\n\n/** Prometheus metrics registry */\nexport class IndexerMetrics {\n /** Prometheus registry instance */\n public readonly registry: Registry;\n\n /** Counter for total blocks indexed */\n public readonly blocksIndexed: Counter;\n\n /** Gauge for current block height */\n public readonly currentHeight: Gauge;\n\n /** Gauge for latest chain block height */\n public readonly latestHeight: Gauge;\n\n /** Gauge for blocks behind chain tip */\n public readonly blocksBehind: Gauge;\n\n /** Gauge for block queue depth */\n public readonly queueDepth: Gauge;\n\n /** Counter for total errors */\n public readonly errors: Counter;\n\n /** Counter for RPC errors */\n public readonly rpcErrors: Counter;\n\n /** Counter for block processing errors */\n public readonly processingErrors: Counter;\n\n /** Counter for database errors */\n public readonly databaseErrors: Counter;\n\n /** Histogram for block processing duration */\n public readonly blockProcessingDuration: Histogram;\n\n /** Histogram for RPC call duration */\n public readonly rpcCallDuration: Histogram;\n\n /** Histogram for database query duration */\n public readonly databaseQueryDuration: Histogram;\n\n /** Gauge for retry count */\n public readonly retryCount: Gauge;\n\n /** Counter for total transactions processed */\n public readonly transactionsProcessed: Counter;\n\n constructor() {\n this.registry = new Registry();\n\n // Collect default Node.js metrics (memory, CPU, etc.)\n collectDefaultMetrics({\n register: this.registry,\n });\n\n // Block indexing metrics\n this.blocksIndexed = new Counter({\n name: \"indexer_blocks_indexed_total\",\n help: \"Total number of blocks indexed\",\n registers: [this.registry],\n });\n\n this.currentHeight = new Gauge({\n name: \"indexer_current_height\",\n help: \"Current block height being processed\",\n registers: [this.registry],\n });\n\n this.latestHeight = new Gauge({\n name: \"indexer_latest_chain_height\",\n help: \"Latest block height on the chain\",\n registers: [this.registry],\n });\n\n this.blocksBehind = new Gauge({\n name: \"indexer_blocks_behind\",\n help: \"Number of blocks behind chain tip\",\n registers: [this.registry],\n });\n\n this.queueDepth = new Gauge({\n name: \"indexer_queue_depth\",\n help: \"Current depth of block processing queue\",\n registers: [this.registry],\n });\n\n // Error metrics\n this.errors = new Counter({\n name: \"indexer_errors_total\",\n help: \"Total number of indexer errors\",\n labelNames: [\"type\"],\n registers: [this.registry],\n });\n\n this.rpcErrors = new Counter({\n name: \"indexer_rpc_errors_total\",\n help: \"Total number of RPC errors\",\n registers: [this.registry],\n });\n\n this.processingErrors = new Counter({\n name: \"indexer_processing_errors_total\",\n help: \"Total number of Block Processing errors\",\n registers: [this.registry],\n });\n\n this.databaseErrors = new Counter({\n name: \"indexer_database_errors_total\",\n help: \"Total number of database errors\",\n registers: [this.registry],\n });\n\n // Performance metrics\n this.blockProcessingDuration = new Histogram({\n name: \"indexer_block_processing_duration_seconds\",\n help: \"Time spent processing a single block\",\n buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 2, 5, 10],\n registers: [this.registry],\n });\n\n this.rpcCallDuration = new Histogram({\n name: \"indexer_rpc_call_duration_seconds\",\n help: \"Duration of RPC calls\",\n buckets: [0.01, 0.05, 0.1, 0.5, 1, 2, 5, 10, 100],\n labelNames: [\"method\"],\n registers: [this.registry],\n });\n\n this.databaseQueryDuration = new Histogram({\n name: \"indexer_database_query_duration_seconds\",\n help: \"Duration of database queries\",\n buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 5],\n labelNames: [\"query_type\"],\n registers: [this.registry],\n });\n\n // Operational metrics\n this.retryCount = new Gauge({\n name: \"indexer_retry_count\",\n help: \"Current number of retry attempts\",\n registers: [this.registry],\n });\n\n this.transactionsProcessed = new Counter({\n name: \"indexer_transactions_processed_total\",\n help: \"Total number of transactions processed\",\n registers: [this.registry],\n });\n }\n\n /**\n * Updates block indexing metrics\n * @param currentHeight - Current height being processed\n * @param latestHeight - Latest height on chain\n * @param queueSize - Current queue depth\n */\n updateBlockMetrics(currentHeight: number, latestHeight: number, queueSize: number) {\n this.blocksIndexed.inc();\n this.currentHeight.set(currentHeight);\n this.latestHeight.set(latestHeight);\n this.blocksBehind.set(latestHeight - currentHeight);\n this.queueDepth.set(queueSize);\n }\n\n /**\n * Records an error occurrence\n * @param type - Error type (rpc, database, processing, etc.)\n */\n recordError(type: string) {\n this.errors.inc({\n type,\n });\n\n if (type === \"rpc\") {\n this.rpcErrors.inc();\n }\n else if (type === \"database\") {\n this.databaseErrors.inc();\n }\n else if (type === \"block\") {\n this.processingErrors.inc();\n }\n }\n\n /**\n * Records block processing duration\n * @param durationSeconds - Duration in seconds\n */\n recordBlockProcessing(durationSeconds: number) {\n this.blockProcessingDuration.observe(durationSeconds);\n }\n\n /**\n * Times a block processing operation\n * @returns End timer function to call when operation completes\n */\n timeBlockProcessing() {\n return this.blockProcessingDuration.startTimer();\n }\n\n /**\n * Records RPC call duration\n * @param method - RPC method name\n * @param durationSeconds - Duration in seconds\n */\n recordRpcCall(method: string, durationSeconds: number) {\n this.rpcCallDuration.observe({\n method,\n }, durationSeconds);\n }\n\n /**\n * Times an RPC call operation\n * @param method - RPC method name\n * @returns End timer function to call when operation completes\n */\n timeRpcCall(method: string) {\n return this.rpcCallDuration.startTimer({\n method,\n });\n }\n\n /**\n * Records database query duration\n * @param queryType - Type of query (select, insert, update, delete, etc.)\n * @param durationSeconds - Duration in seconds\n */\n recordDatabaseQuery(queryType: string, durationSeconds: number) {\n this.databaseQueryDuration.observe({\n query_type: queryType,\n }, durationSeconds);\n }\n\n /**\n * Times a database query operation\n * @param queryType - Type of query (select, insert, update, delete, etc.)\n * @returns End timer function to call when operation completes\n */\n timeDatabaseQuery(queryType: string) {\n return this.databaseQueryDuration.startTimer({\n query_type: queryType,\n });\n }\n\n /**\n * Updates the retry count gauge\n * @param count - Current retry count\n */\n updateRetryCount(count: number) {\n this.retryCount.set(count);\n }\n\n /**\n * Increments the retry count gauge by 1\n */\n incrementRetryCount() {\n this.retryCount.inc();\n }\n\n /**\n * Resets the retry count gauge to 0\n */\n resetRetryCount() {\n this.retryCount.set(0);\n }\n\n /**\n * Records transactions processed\n * @param count - Number of transactions to record (defaults to 1)\n */\n recordTransactions(count: number = 1) {\n this.transactionsProcessed.inc(count);\n }\n\n /**\n * Gets metrics in Prometheus format\n * @returns Prometheus metrics string\n */\n async getMetrics(): Promise<string> {\n return this.registry.metrics();\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eclesia/indexer-engine",
3
- "version": "2.11.1",
3
+ "version": "2.12.0",
4
4
  "description": "Core eclesia indexer engine",
5
5
  "files": [
6
6
  "dist/",