diff --git a/packages/common-cosmos/CHANGELOG.md b/packages/common-cosmos/CHANGELOG.md index 6e09a75e3..b7d6da063 100644 --- a/packages/common-cosmos/CHANGELOG.md +++ b/packages/common-cosmos/CHANGELOG.md @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Changed +- Update deps (#282) ## [5.0.2] - 2024-08-12 ### Changed diff --git a/packages/common-cosmos/package.json b/packages/common-cosmos/package.json index 35e7c49ba..2f7596da0 100644 --- a/packages/common-cosmos/package.json +++ b/packages/common-cosmos/package.json @@ -22,7 +22,7 @@ "@protobufs/google": "^0.0.10", "@protobufs/ibc": "^0.1.0", "@protobufs/tendermint": "^0.0.10", - "@subql/common": "^5.1.0", + "@subql/common": "^5.1.1", "@subql/types-cosmos": "workspace:*", "@subql/x-cosmology-telescope": "^1.4.14", "fs-extra": "^11.1.1", diff --git a/packages/common-cosmos/tsconfig.json b/packages/common-cosmos/tsconfig.json index 0519f60d0..b3866a63d 100644 --- a/packages/common-cosmos/tsconfig.json +++ b/packages/common-cosmos/tsconfig.json @@ -4,8 +4,7 @@ "rootDir": "src", "tsBuildInfoFile": "dist/.tsbuildinfo", "outDir": "dist", - "noImplicitAny": true, - "strict": true + "noImplicitAny": true }, "references": [{"path": "../types"}], "include": ["src/**/*"] diff --git a/packages/node/CHANGELOG.md b/packages/node/CHANGELOG.md index 90d410d0e..5b8d9a040 100644 --- a/packages/node/CHANGELOG.md +++ b/packages/node/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Fixed - Filter out transactions that can't be decoded (#280) +### Changed +- Enable strict ts setting (#282) +- Update deps (#282) ## [4.1.0] - 2024-08-12 ### Added diff --git a/packages/node/package.json b/packages/node/package.json index 0438224e5..56bff9ffa 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -29,8 +29,9 @@ "@nestjs/event-emitter": "^2.0.0", "@nestjs/platform-express": "^9.4.0", "@nestjs/schedule": "^3.0.1", + "@subql/common": "^5.1.1", "@subql/common-cosmos": "workspace:*", - "@subql/node-core": "^14.1.1", + "@subql/node-core": "^14.1.2", "@subql/types-cosmos": "workspace:*", "lodash": "^4.17.21", "protobufjs": "^6.11.4", diff --git a/packages/node/src/indexer/api.service.test.ts b/packages/node/src/indexer/api.service.test.ts index 4f484e12d..8fcd832bb 100644 --- a/packages/node/src/indexer/api.service.test.ts +++ b/packages/node/src/indexer/api.service.test.ts @@ -38,7 +38,7 @@ function testCosmosProject( schema: new GraphQLSchema({}), templates: [], tempDir: fileCacheDir, - } as SubqueryProject; + } as unknown as SubqueryProject; } jest.setTimeout(200000); @@ -64,22 +64,32 @@ describe('ApiService', () => { }, { provide: NodeConfig, - useFactory: () => ({}), + useFactory: () => + new NodeConfig( + { + kyveEndpoint: 'https://api-us-1.kyve.network', + kyveStorageUrl: 'https://arweave.net', + } as any, + true, + ), }, EventEmitter2, - ApiService, - NodeConfig, + { + provide: ApiService, + useFactory: ApiService.create.bind(ApiService), + inject: [ + 'ISubqueryProject', + ConnectionPoolService, + EventEmitter2, + NodeConfig, + ], + }, ], imports: [EventEmitterModule.forRoot()], }).compile(); app = module.createNestApplication(); await app.init(); apiService = app.get(ApiService); - (apiService as any).nodeConfig._config.kyveEndpoint = - 'https://api-us-1.kyve.network'; - (apiService as any).nodeConfig._config.kyveStorageUrl = - 'https://arweave.net'; - await apiService.init(); }; const ENDPOINT = 'https://rpc-juno.itastakers.com/'; @@ -89,6 +99,7 @@ describe('ApiService', () => { beforeAll(async () => { tmpPath = await makeTempDir(); }); + it('Falls back on rpc if kyve fails', async () => { const endpoint = 'https://rpc.mainnet.archway.io:443'; const chainId = 'archway-1'; diff --git a/packages/node/src/indexer/api.service.ts b/packages/node/src/indexer/api.service.ts index 201edc603..e24b1658f 100644 --- a/packages/node/src/indexer/api.service.ts +++ b/packages/node/src/indexer/api.service.ts @@ -1,13 +1,14 @@ // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors // SPDX-License-Identifier: GPL-3.0 +import assert from 'assert'; import { CosmWasmClient, IndexedTx } from '@cosmjs/cosmwasm-stargate'; import { toHex } from '@cosmjs/encoding'; import { Uint53 } from '@cosmjs/math'; import { GeneratedType, Registry } from '@cosmjs/proto-signing'; import { Block, defaultRegistryTypes, SearchTxQuery } from '@cosmjs/stargate'; import { CometClient, toRfc3339WithNanoseconds } from '@cosmjs/tendermint-rpc'; -import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; +import { Injectable, OnApplicationShutdown } from '@nestjs/common'; import { EventEmitter2 } from '@nestjs/event-emitter'; import { CosmosProjectNetConfig } from '@subql/common-cosmos'; import { @@ -43,23 +44,19 @@ export class ApiService extends BaseApiService[]> implements OnApplicationShutdown { - private fetchBlocksBatches = CosmosUtil.fetchBlocksBatches; - private nodeConfig: CosmosNodeConfig; - private kyveApi?: KyveApi; - registry: Registry; - - constructor( - @Inject('ISubqueryProject') private project: SubqueryProject, + private constructor( connectionPoolService: ConnectionPoolService, eventEmitter: EventEmitter2, - nodeConfig: NodeConfig, + public registry: Registry, + private kyveApi?: KyveApi, ) { super(connectionPoolService, eventEmitter); - this.nodeConfig = new CosmosNodeConfig(nodeConfig); } - private async buildRegistry(): Promise { - const chaintypes = await this.getChainType(this.project.network); + private static async buildRegistry( + network: Partial, + ): Promise { + const chaintypes = await this.getChainType(network); const wasmTypes: ReadonlyArray<[string, GeneratedType]> = [ ['/cosmwasm.wasm.v1.MsgClearAdmin', MsgClearAdmin], @@ -83,32 +80,33 @@ export class ApiService await this.connectionPoolService.onApplicationShutdown(); } - async init(): Promise { - const { network } = this.project; + static async create( + project: SubqueryProject, + connectionPoolService: ConnectionPoolService, + eventEmitter: EventEmitter2, + nodeConfig: NodeConfig, + ): Promise { + const { network } = project; + const cosmosNodeConfig = new CosmosNodeConfig(nodeConfig); - this.registry = await this.buildRegistry(); + const registry = await this.buildRegistry(network); - await this.createConnections(network, (endpoint, config) => - CosmosClientConnection.create( - endpoint, - this.fetchBlocksBatches, - this.registry, - config, - ), - ); + let kyveApi: KyveApi | undefined; if ( - this.nodeConfig.kyveEndpoint && - this.nodeConfig.kyveEndpoint !== 'false' + cosmosNodeConfig.kyveEndpoint && + cosmosNodeConfig.kyveEndpoint !== 'false' ) { try { - this.kyveApi = await KyveApi.create( + // TODO test + assert(project.tempDir, 'Expected temp dir to exist for using Kyve'); + kyveApi = await KyveApi.create( network.chainId, - this.nodeConfig.kyveEndpoint, - this.nodeConfig.kyveStorageUrl, - this.nodeConfig.kyveChainId, - this.project.tempDir, - KYVE_BUFFER_RANGE * this.nodeConfig.batchSize, + cosmosNodeConfig.kyveEndpoint, + cosmosNodeConfig.kyveStorageUrl, + cosmosNodeConfig.kyveChainId, + project.tempDir, + KYVE_BUFFER_RANGE * nodeConfig.batchSize, ); } catch (e) { logger.warn(`Kyve Api is not connected. ${e}`); @@ -117,7 +115,23 @@ export class ApiService logger.info(`Kyve not connected`); } - return this; + const apiService = new ApiService( + connectionPoolService, + eventEmitter, + registry, + kyveApi, + ); + + await apiService.createConnections(network, (endpoint, config) => + CosmosClientConnection.create( + endpoint, + CosmosUtil.fetchBlocksBatches, + registry, + config, + ), + ); + + return apiService; } // Overrides the super function because of the kyve integration @@ -129,7 +143,7 @@ export class ApiService if (this.kyveApi) { try { return await this.kyveApi.fetchBlocksBatches(this.registry, heights); - } catch (e) { + } catch (e: any) { logger.warn( e, `Failed to fetch blocks: ${JSON.stringify( @@ -154,7 +168,7 @@ export class ApiService } // eslint-disable-next-line @typescript-eslint/require-await - async getChainType( + private static async getChainType( network: Partial, ): Promise> { if (!network.chaintypes) { diff --git a/packages/node/src/indexer/blockDispatcher/cosmos-block-dispatcher.ts b/packages/node/src/indexer/blockDispatcher/cosmos-block-dispatcher.ts index 093d6ce5a..81e54de27 100644 --- a/packages/node/src/indexer/blockDispatcher/cosmos-block-dispatcher.ts +++ b/packages/node/src/indexer/blockDispatcher/cosmos-block-dispatcher.ts @@ -5,5 +5,7 @@ import { IBlockDispatcher } from '@subql/node-core'; import { BlockContent } from '../types'; export interface ICosmosBlockDispatcher extends IBlockDispatcher { - init(onDynamicDsCreated: (height: number) => Promise): Promise; + init( + onDynamicDsCreated: (height: number) => void | Promise, + ): Promise; } diff --git a/packages/node/src/indexer/blockDispatcher/worker-block-dispatcher.service.ts b/packages/node/src/indexer/blockDispatcher/worker-block-dispatcher.service.ts index 7b60e637a..1e3e5880a 100644 --- a/packages/node/src/indexer/blockDispatcher/worker-block-dispatcher.service.ts +++ b/packages/node/src/indexer/blockDispatcher/worker-block-dispatcher.service.ts @@ -94,7 +94,7 @@ export class WorkerBlockDispatcherService height: number, ): Promise { // const start = new Date(); - await worker.fetchBlock(height, null); + await worker.fetchBlock(height, 0 /* Value is not used with cosmos*/); // const end = new Date(); // const waitTime = end.getTime() - start.getTime(); diff --git a/packages/node/src/indexer/cosmosClient.connection.ts b/packages/node/src/indexer/cosmosClient.connection.ts index 5357a553d..1264d2fab 100644 --- a/packages/node/src/indexer/cosmosClient.connection.ts +++ b/packages/node/src/indexer/cosmosClient.connection.ts @@ -67,19 +67,19 @@ export class CosmosClientConnection IBlock[] > { - private cometClient: CometClient; - private registry: Registry; readonly networkMeta: NetworkMetadataPayload; private constructor( public unsafeApi: CosmosClient, private fetchBlocksBatches: FetchFunc, chainId: string, + private cometClient: CometClient, + private registry: Registry, ) { this.networkMeta = { chain: chainId, - specName: undefined, - genesisHash: undefined, + specName: undefined as any, + genesisHash: undefined as any, // Cant always get the genesis hash because of pruning }; } @@ -115,9 +115,9 @@ export class CosmosClientConnection api, fetchBlocksBatches, await api.getChainId(), + cometClient, + registry, ); - connection.cometClient = cometClient; - connection.setRegistry(registry); logger.info(`connected to ${endpoint}`); @@ -128,10 +128,6 @@ export class CosmosClientConnection return new CosmosSafeClient(this.cometClient, height); } - private setRegistry(registry: Registry): void { - this.registry = registry; - } - // eslint-disable-next-line @typescript-eslint/require-await async apiConnect(): Promise { this.unsafeApi = new CosmosClient(this.cometClient, this.registry); diff --git a/packages/node/src/indexer/dictionary/v1/dictionaryV1.ts b/packages/node/src/indexer/dictionary/v1/dictionaryV1.ts index 0f70962b1..e4b3735e6 100644 --- a/packages/node/src/indexer/dictionary/v1/dictionaryV1.ts +++ b/packages/node/src/indexer/dictionary/v1/dictionaryV1.ts @@ -1,6 +1,7 @@ // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors // SPDX-License-Identifier: GPL-3.0 +import assert from 'assert'; import { Inject, Injectable } from '@nestjs/common'; import { CosmosDataSource, @@ -11,26 +12,24 @@ import { NodeConfig, DictionaryV1 as BaseDictionaryV1 } from '@subql/node-core'; import { DictionaryQueryEntry, DictionaryQueryCondition, - DsProcessor, } from '@subql/types-core'; import { CosmosBlockFilter, CosmosCustomHandler, CosmosDatasource, CosmosEventFilter, - CosmosEventHandler, CosmosHandler, CosmosHandlerFilter, CosmosHandlerKind, CosmosMessageFilter, - CosmosMessageHandler, CosmosRuntimeHandler, } from '@subql/types-cosmos'; import { setWith, sortBy, uniqBy } from 'lodash'; import { SubqueryProject } from '../../../configure/SubqueryProject'; import { isBaseHandler, isCustomHandler } from '../../../utils/project'; +import { DsProcessorService } from '../../ds-processor.service'; -type GetDsProcessor = (ds: CosmosDatasource) => DsProcessor; +type GetDsProcessor = DsProcessorService['getDsProcessor']; export function eventFilterToQueryEntry( filter: CosmosEventFilter, @@ -64,7 +63,7 @@ function getBaseHandlerKind( ds: CosmosDataSource, handler: CosmosHandler, getDsProcessor: GetDsProcessor, -): CosmosHandlerKind { +): CosmosHandlerKind | undefined { if (isRuntimeCosmosDs(ds) && isBaseHandler(handler)) { return (handler as CosmosRuntimeHandler).kind; } else if (isCustomCosmosDs(ds) && isCustomHandler(handler)) { @@ -105,12 +104,14 @@ function buildDictionaryQueryEntries( const plugin = isCustomCosmosDs(ds) ? getDsProcessor(ds) : undefined; for (const handler of ds.mapping.handlers) { const baseHandlerKind = getBaseHandlerKind(ds, handler, getDsProcessor); - let filterList: CosmosHandlerFilter[]; + let filterList: CosmosHandlerFilter[] = []; if (isCustomCosmosDs(ds)) { + assert(plugin, 'plugin should be defined'); const processor = plugin.handlerProcessors[handler.kind]; - if (processor.dictionaryQuery) { + const filter = (handler as CosmosCustomHandler).filter; + if (processor.dictionaryQuery && filter) { const queryEntry = processor.dictionaryQuery( - (handler as CosmosCustomHandler).filter, + filter, ds, ) as DictionaryQueryEntry; if (queryEntry) { @@ -123,13 +124,11 @@ function buildDictionaryQueryEntries( handler.kind, getDsProcessor, ); - } else { - filterList = [ - (handler as CosmosEventHandler | CosmosMessageHandler).filter, - ]; + } else if (handler.filter) { + filterList = [handler.filter as CosmosHandlerFilter]; } // Filter out any undefined - filterList = filterList.filter(Boolean); + filterList = filterList.filter((f) => !f); if (!filterList.length) return []; switch (baseHandlerKind) { case CosmosHandlerKind.Block: @@ -188,8 +187,7 @@ export function messageFilterToQueryEntry( const nested = {}; // convert nested filters from `msg.swap.input_token` to { msg: { swap: { input_token: 'Token2' } } } - Object.keys(filter.values).map((key) => { - const value = filter.values[key]; + Object.entries(filter.values).map((key, value) => { setWith(nested, key, value); }); @@ -211,7 +209,7 @@ export class DictionaryV1 extends BaseDictionaryV1 { @Inject('ISubqueryProject') protected project: SubqueryProject, nodeConfig: NodeConfig, private getDsProcessor: GetDsProcessor, - dictionaryUrl?: string, + dictionaryUrl: string, ) { super(dictionaryUrl, project.network.chainId, nodeConfig, [ 'lastProcessedHeight', diff --git a/packages/node/src/indexer/dynamic-ds.service.spec.ts b/packages/node/src/indexer/dynamic-ds.service.spec.ts index ca82bd1ca..7e3f04151 100644 --- a/packages/node/src/indexer/dynamic-ds.service.spec.ts +++ b/packages/node/src/indexer/dynamic-ds.service.spec.ts @@ -76,7 +76,7 @@ describe('Creating dynamic ds', () => { }, ], } as unknown as SubqueryProject; - dynamiDsService = new DynamicDsService(null, project); + dynamiDsService = new DynamicDsService(null as any, project); await dynamiDsService.init(getMetadata()); }); diff --git a/packages/node/src/indexer/fetch.module.ts b/packages/node/src/indexer/fetch.module.ts index 6924ef0b5..7532bbf04 100644 --- a/packages/node/src/indexer/fetch.module.ts +++ b/packages/node/src/indexer/fetch.module.ts @@ -13,6 +13,7 @@ import { IProjectUpgradeService, InMemoryCacheService, MonitorService, + ConnectionPoolService, } from '@subql/node-core'; import { SubqueryProject } from '../configure/SubqueryProject'; import { ApiService } from './api.service'; @@ -32,7 +33,16 @@ import { UnfinalizedBlocksService } from './unfinalizedBlocks.service'; @Module({ imports: [CoreModule], providers: [ - ApiService, + { + provide: ApiService, + useFactory: ApiService.create.bind(ApiService), + inject: [ + 'ISubqueryProject', + ConnectionPoolService, + EventEmitter2, + NodeConfig, + ], + }, IndexerManager, { provide: 'IBlockDispatcher', diff --git a/packages/node/src/indexer/indexer.manager.ts b/packages/node/src/indexer/indexer.manager.ts index fc8060200..a797a0af5 100644 --- a/packages/node/src/indexer/indexer.manager.ts +++ b/packages/node/src/indexer/indexer.manager.ts @@ -1,7 +1,7 @@ // Copyright 2020-2024 SubQuery Pte Ltd authors & contributors // SPDX-License-Identifier: GPL-3.0 -import { Inject, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { isBlockHandlerProcessor, isTransactionHandlerProcessor, @@ -111,7 +111,7 @@ export class IndexerManager extends BaseIndexerManager< ): Promise { await this.indexBlockContent(blockContent, dataSources, getVM); - for (const evt of blockContent.beginBlockEvents) { + for (const evt of blockContent.beginBlockEvents ?? []) { await this.indexEvent(evt, dataSources, getVM); } @@ -132,7 +132,7 @@ export class IndexerManager extends BaseIndexerManager< } } - for (const evt of blockContent.endBlockEvents) { + for (const evt of blockContent.endBlockEvents ?? []) { await this.indexEvent(evt, dataSources, getVM); } } diff --git a/packages/node/src/indexer/rpc-clients/HttpClient.ts b/packages/node/src/indexer/rpc-clients/HttpClient.ts index 8f859fcc5..597df1ef1 100644 --- a/packages/node/src/indexer/rpc-clients/HttpClient.ts +++ b/packages/node/src/indexer/rpc-clients/HttpClient.ts @@ -28,13 +28,14 @@ export async function httpRequest( export class HttpClient implements RpcClient { protected readonly url: string; - protected readonly headers: Record | undefined; + protected readonly headers: Record; connection: AxiosInstance; constructor(endpoint: string | HttpEndpoint) { if (typeof endpoint === 'string') { // accept host.name:port and assume http protocol this.url = hasProtocol(endpoint) ? endpoint : `http://${endpoint}`; + this.headers = {}; } else { this.url = endpoint.url; this.headers = endpoint.headers; @@ -43,8 +44,9 @@ export class HttpClient implements RpcClient { const { searchParams } = new URL(this.url); // Support OnFinality api keys - if (searchParams.get('apikey')) { - this.headers.apikey = searchParams.get('apikey'); + const apiKey = searchParams.get('apikey'); + if (apiKey) { + this.headers.apikey = apiKey; this.url = this.url.slice(0, this.url.indexOf('?apikey')); } diff --git a/packages/node/src/indexer/worker/worker-fetch.module.ts b/packages/node/src/indexer/worker/worker-fetch.module.ts index b1beed11f..55d3edc92 100644 --- a/packages/node/src/indexer/worker/worker-fetch.module.ts +++ b/packages/node/src/indexer/worker/worker-fetch.module.ts @@ -10,9 +10,7 @@ import { NodeConfig, WorkerUnfinalizedBlocksService, } from '@subql/node-core'; -import { SubqueryProject } from '../../configure/SubqueryProject'; import { ApiService } from '../api.service'; -import { CosmosClientConnection } from '../cosmosClient.connection'; import { DsProcessorService } from '../ds-processor.service'; import { DynamicDsService } from '../dynamic-ds.service'; import { IndexerManager } from '../indexer.manager'; @@ -26,21 +24,7 @@ import { WorkerService } from './worker.service'; IndexerManager, { provide: ApiService, - useFactory: async ( - project: SubqueryProject, - connectionPoolService: ConnectionPoolService, - eventEmitter: EventEmitter2, - nodeConfig: NodeConfig, - ) => { - const apiService = new ApiService( - project, - connectionPoolService, - eventEmitter, - nodeConfig, - ); - await apiService.init(); - return apiService; - }, + useFactory: ApiService.create.bind(ApiService), inject: [ 'ISubqueryProject', ConnectionPoolService, diff --git a/packages/node/src/indexer/worker/worker.ts b/packages/node/src/indexer/worker/worker.ts index db7128a69..d7eb92116 100644 --- a/packages/node/src/indexer/worker/worker.ts +++ b/packages/node/src/indexer/worker/worker.ts @@ -31,10 +31,10 @@ import { WorkerService } from './worker.service'; const logger = getLogger(`worker #${threadId}`); -async function initWorker(startHeight: number): Promise { +async function initWorker(startHeight?: number): Promise { try { const app = await NestFactory.create(WorkerModule, { - logger: new NestLogger(!!argv.debug), // TIP: If the worker is crashing comment out this line for better logging + logger: new NestLogger(!!argv.debug), // TIP: If the worker is crashing comment out this line for better logging }); await app.init(); @@ -46,7 +46,7 @@ async function initWorker(startHeight: number): Promise { const workerService = app.get(WorkerService); initWorkerServices(app, workerService); - } catch (e) { + } catch (e: any) { console.log('Failed to start worker', e); logger.error(e, 'Failed to start worker'); throw e; diff --git a/packages/node/src/init.ts b/packages/node/src/init.ts index 811515f4d..5cffcb8ee 100644 --- a/packages/node/src/init.ts +++ b/packages/node/src/init.ts @@ -10,7 +10,6 @@ import { NestLogger, } from '@subql/node-core'; import { AppModule } from './app.module'; -import { ApiService } from './indexer/api.service'; import { FetchService } from './indexer/fetch.service'; import { ProjectService } from './indexer/project.service'; import { yargsOptions } from './yargs'; @@ -41,10 +40,8 @@ export async function bootstrap(): Promise { const projectService: ProjectService = app.get('IProjectService'); const fetchService = app.get(FetchService); - const apiService = app.get(ApiService); // Initialise async services, we do this here rather than in factories, so we can capture one off events - await apiService.init(); await projectService.init(); await fetchService.init(projectService.startHeight); diff --git a/packages/node/src/subcommands/testing.module.ts b/packages/node/src/subcommands/testing.module.ts index aaaea2f3e..d125c6f73 100644 --- a/packages/node/src/subcommands/testing.module.ts +++ b/packages/node/src/subcommands/testing.module.ts @@ -18,9 +18,7 @@ import { SandboxService, } from '@subql/node-core'; import { ConfigureModule } from '../configure/configure.module'; -import { SubqueryProject } from '../configure/SubqueryProject'; import { ApiService } from '../indexer/api.service'; -import { CosmosClientConnection } from '../indexer/cosmosClient.connection'; import { DsProcessorService } from '../indexer/ds-processor.service'; import { DynamicDsService } from '../indexer/dynamic-ds.service'; import { IndexerManager } from '../indexer/indexer.manager'; @@ -47,21 +45,7 @@ import { UnfinalizedBlocksService } from '../indexer/unfinalizedBlocks.service'; }, { provide: ApiService, - useFactory: async ( - project: SubqueryProject, - connectionPoolService: ConnectionPoolService, - eventEmitter: EventEmitter2, - nodeConfig: NodeConfig, - ) => { - const apiService = new ApiService( - project, - connectionPoolService, - eventEmitter, - nodeConfig, - ); - await apiService.init(); - return apiService; - }, + useFactory: ApiService.create.bind(ApiService), inject: [ 'ISubqueryProject', ConnectionPoolService, @@ -73,7 +57,7 @@ import { UnfinalizedBlocksService } from '../indexer/unfinalizedBlocks.service'; TestRunner, { provide: 'IApi', - useClass: ApiService, + useExisting: ApiService, }, { provide: 'IIndexerManager', diff --git a/packages/node/src/utils/cosmos.ts b/packages/node/src/utils/cosmos.ts index a9ed6a659..2c11672d8 100644 --- a/packages/node/src/utils/cosmos.ts +++ b/packages/node/src/utils/cosmos.ts @@ -56,7 +56,7 @@ export function decodeMsg( decodedMsg.msg = JSON.parse(new TextDecoder().decode(decodedMsg.msg)); } return decodedMsg; - } catch (e) { + } catch (e: any) { logger.error(e, 'Failed to decode message'); throw e; } @@ -192,10 +192,10 @@ export function filterEvent( } for (const filterKey in filter.attributes) { + const fValue = filter.attributes[filterKey]; if ( !event.event.attributes.find( - ({ key, value }) => - key === filterKey && value === filter.attributes[filterKey], + ({ key, value }) => key === filterKey && value === fValue, ) ) { return false; @@ -330,14 +330,14 @@ export function wrapBlockBeginAndEndEvents( ): CosmosEvent[] { return events.map( (event) => - { + ({ idx: idxOffset++, event: fromTendermintEvent(event), block: block, msg: null, tx: null, log: null, - }, + } as unknown as CosmosEvent), ); } @@ -468,7 +468,7 @@ export async function fetchBlocksBatches( return formatBlockUtil( new LazyBlockContent(blockInfo, blockResults, api.registry), ); - } catch (e) { + } catch (e: any) { logger.error( e, `Failed to fetch and prepare block ${blockInfo.block.header.height}`, @@ -479,12 +479,12 @@ export async function fetchBlocksBatches( } export class LazyBlockContent implements BlockContent { - private _wrappedBlock: CosmosBlock; - private _wrappedTransaction: CosmosTransaction[]; - private _wrappedMessage: CosmosMessage[]; - private _wrappedEvent: CosmosEvent[]; - private _wrappedBeginBlockEvents: CosmosEvent[]; - private _wrappedEndBlockEvents: CosmosEvent[]; + private _wrappedBlock?: CosmosBlock; + private _wrappedTransaction?: CosmosTransaction[]; + private _wrappedMessage?: CosmosMessage[]; + private _wrappedEvent?: CosmosEvent[]; + private _wrappedBeginBlockEvents?: CosmosEvent[]; + private _wrappedEndBlockEvents?: CosmosEvent[]; private _eventIdx = 0; //To maintain a valid count over begin block events, tx events and end block events constructor( @@ -493,7 +493,7 @@ export class LazyBlockContent implements BlockContent { private _registry: Registry, ) {} - get block() { + get block(): CosmosBlock { if (!this._wrappedBlock) { this._wrappedBlock = wrapBlock(this._blockInfo, [ ...this._results.results, @@ -502,14 +502,14 @@ export class LazyBlockContent implements BlockContent { return this._wrappedBlock; } - get transactions() { + get transactions(): CosmosTransaction[] { if (!this._wrappedTransaction) { this._wrappedTransaction = wrapTx(this.block, [...this._results.results]); } return this._wrappedTransaction; } - get messages() { + get messages(): CosmosMessage[] { if (!this._wrappedMessage) { this._wrappedMessage = wrapMsg( this.block, @@ -520,7 +520,7 @@ export class LazyBlockContent implements BlockContent { return this._wrappedMessage; } - get events() { + get events(): CosmosEvent[] { if (!this._wrappedEvent) { this._wrappedEvent = wrapEvent( this.block, @@ -533,7 +533,7 @@ export class LazyBlockContent implements BlockContent { return this._wrappedEvent; } - get beginBlockEvents() { + get beginBlockEvents(): CosmosEvent[] { if (!this._wrappedBeginBlockEvents) { this._wrappedBeginBlockEvents = wrapBlockBeginAndEndEvents( this.block, @@ -546,7 +546,7 @@ export class LazyBlockContent implements BlockContent { return this._wrappedBeginBlockEvents; } - get endBlockEvents() { + get endBlockEvents(): CosmosEvent[] { if (!this._wrappedEndBlockEvents) { this._wrappedEndBlockEvents = wrapBlockBeginAndEndEvents( this.block, diff --git a/packages/node/src/utils/kyve/kyve.spec.ts b/packages/node/src/utils/kyve/kyve.spec.ts index 28aefd41f..2ed20c985 100644 --- a/packages/node/src/utils/kyve/kyve.spec.ts +++ b/packages/node/src/utils/kyve/kyve.spec.ts @@ -523,8 +523,8 @@ describe('KyveApi', () => { kyveLazyBlockContent = new LazyBlockContent(bi, br, registry); }); it('wrapTransaction', () => { - expect(kyveLazyBlockContent.transactions[0].tx.data.length).toBe( - rpcLazyBlockContent.transactions[0].tx.data.length, + expect(kyveLazyBlockContent.transactions[0].tx.data!.length).toBe( + rpcLazyBlockContent.transactions[0].tx.data!.length, ); expect(kyveLazyBlockContent.transactions[0].tx.events.length).toBe( rpcLazyBlockContent.transactions[0].tx.events.length, diff --git a/packages/node/src/utils/kyve/kyve.ts b/packages/node/src/utils/kyve/kyve.ts index ea9d07598..2ac1c4d85 100644 --- a/packages/node/src/utils/kyve/kyve.ts +++ b/packages/node/src/utils/kyve/kyve.ts @@ -100,14 +100,15 @@ export class KyveApi { for (const p of poolsResponse.pools) { try { + assert(p.data, 'Pool data is missing'); const config = JSON.parse(p.data.config); if (config.network === chainId) { return p.id; // Return the matching pool ID } } catch (error) { - throw new Error( - `Error parsing JSON for pool with id ${p.id}: ${error}`, - ); + throw new Error(`Error parsing JSON for pool with id ${p.id}`, { + cause: error, + }); } } @@ -429,9 +430,9 @@ export class KyveApi { files .filter((file) => KyveApi.isBundleFile(file, this.poolId)) .map((file) => { - const id = parseDecimal( - file.match(BUNDLE_FILE_ID_REG(this.poolId))[1], - ); + const m = file.match(BUNDLE_FILE_ID_REG(this.poolId)); + assert(m, `No matching bundle files for pool ${this.poolId}`); + const id = parseDecimal(m[1]); return this.getBundleById(id); }), ); @@ -447,6 +448,8 @@ export class KyveApi { } const currentBundle = await this.getBundleFromCache(height); + if (!currentBundle) return []; + const bundles = await Promise.all(Object.values(cachedBundles)); return bundles.filter((b) => { @@ -485,6 +488,10 @@ export class KyveApi { ): Promise<[BlockResponse, BlockResultsResponse]> { const blocks = await this.updateCurrentBundleAndDetails(height); const blockData = this.findBlockByHeight(height, blocks); + if (!blockData) { + throw new Error(`Unable to find block ${height}`); + } + return [ this.decodeBlock(blockData.value.block), this.injectLogs(this.decodeBlockResult(blockData.value.block_results)), diff --git a/packages/node/tsconfig.json b/packages/node/tsconfig.json index 4ef8b2161..7667ef88c 100644 --- a/packages/node/tsconfig.json +++ b/packages/node/tsconfig.json @@ -5,7 +5,6 @@ "tsBuildInfoFile": "dist/.tsbuildinfo", "rootDir": "src", "outDir": "./dist" - // "strict": true, }, "references": [{ "path": "../common-cosmos" }, { "path": "../types" }], "include": ["src/**/*"] diff --git a/packages/types/tsconfig.json b/packages/types/tsconfig.json index 0bfb9b541..b9875beb3 100644 --- a/packages/types/tsconfig.json +++ b/packages/types/tsconfig.json @@ -5,8 +5,7 @@ "noImplicitAny": true, "tsBuildInfoFile": "dist/.tsbuildinfo", "rootDir": "src", - "outDir": "dist", - "strict": true + "outDir": "dist" }, "include": ["src/**/*"] } diff --git a/tsconfig.json b/tsconfig.json index 27e182d5f..5c42659b1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,7 +23,8 @@ "@subql/types-cosmos": ["packages/types/src"], "@subql/types-cosmos/*": ["packages/types/src/*"] }, - "skipLibCheck": true + "skipLibCheck": true, + "strict": true }, "references": [ {"path": "packages/common-cosmos"}, diff --git a/yarn.lock b/yarn.lock index a458833b9..094b758be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6380,7 +6380,7 @@ __metadata: "@protobufs/google": ^0.0.10 "@protobufs/ibc": ^0.1.0 "@protobufs/tendermint": ^0.0.10 - "@subql/common": ^5.1.0 + "@subql/common": ^5.1.1 "@subql/types-cosmos": "workspace:*" "@subql/x-cosmology-telescope": ^1.4.14 "@types/bn.js": 4.11.6 @@ -6403,9 +6403,9 @@ __metadata: languageName: unknown linkType: soft -"@subql/common@npm:5.1.0, @subql/common@npm:^5.1.0": - version: 5.1.0 - resolution: "@subql/common@npm:5.1.0" +"@subql/common@npm:5.1.1, @subql/common@npm:^5.1.1": + version: 5.1.1 + resolution: "@subql/common@npm:5.1.1" dependencies: "@subql/types-core": 1.1.1 axios: ^0.28.0 @@ -6415,21 +6415,21 @@ __metadata: reflect-metadata: ^0.1.14 semver: ^7.6.3 update-notifier: ^5.1.0 - checksum: 6b568f1c43ffe16991038393c2f9305dd502467f897b858f76e5be119dd6ae5b294624b1bec2d58d87a3ecbc8097927dda2fc87f8c96eecdb94101234dfcd2f9 + checksum: 7e8eeb5bb0242c178df8f68d38f078799d896837bd260804abcdf44eaa8b2ea1f28823d611d3b1a271e5216d0fc1b4a764a417ad9ac83b5c061e9761cc838ffc languageName: node linkType: hard -"@subql/node-core@npm:^14.1.1": - version: 14.1.1 - resolution: "@subql/node-core@npm:14.1.1" +"@subql/node-core@npm:^14.1.2": + version: 14.1.2 + resolution: "@subql/node-core@npm:14.1.2" dependencies: "@apollo/client": ^3.11.2 "@nestjs/common": ^9.4.0 "@nestjs/event-emitter": ^2.0.0 "@nestjs/schedule": ^3.0.1 - "@subql/common": 5.1.0 + "@subql/common": 5.1.1 "@subql/testing": 2.2.1 - "@subql/types": 3.11.1 + "@subql/types": 3.11.2 "@subql/utils": 2.14.0 "@willsoto/nestjs-prometheus": ^5.4.0 async-mutex: ^0.5.0 @@ -6447,7 +6447,7 @@ __metadata: toposort-class: ^1.0.1 vm2: ^3.9.19 yargs: ^16.2.0 - checksum: 82b831b01f3e12623835ebf8b1b999daf8d086911226dd21ad0db6438d1534993247de7af1aa1cc0ea391f4676dda3c16c747623d5f9cdcbc03992500d5bc5df + checksum: 6d56fcf203f9d0a54aafd519ed1ba526b23aa798850f2dfc984ded8f5fed4cc17d778f8ba6684e823236da5b2356dad4e6c75ba767101febeeeb2ced80e86c8b languageName: node linkType: hard @@ -6467,8 +6467,9 @@ __metadata: "@nestjs/schedule": ^3.0.1 "@nestjs/schematics": ^9.2.0 "@nestjs/testing": ^9.4.0 + "@subql/common": ^5.1.1 "@subql/common-cosmos": "workspace:*" - "@subql/node-core": ^14.1.1 + "@subql/node-core": ^14.1.2 "@subql/types-cosmos": "workspace:*" "@types/express": ^4.17.13 "@types/jest": ^27.4.0 @@ -6526,14 +6527,14 @@ __metadata: languageName: unknown linkType: soft -"@subql/types@npm:3.11.1": - version: 3.11.1 - resolution: "@subql/types@npm:3.11.1" +"@subql/types@npm:3.11.2": + version: 3.11.2 + resolution: "@subql/types@npm:3.11.2" dependencies: "@subql/types-core": 1.1.1 peerDependencies: "@polkadot/api": ^12 - checksum: 35c9f2bd86dcddc0d5541f85b0332470da2c4f4cf8d3e60b7962c6746b5cf272bbeb0f2242b659c5bf4101702ac85087bed75c1dfd67084674367d0d0469af7d + checksum: ef8e9f6bd73e9071ec267cb90259472d9ecb595d02bf52e44e4f93e90016ed0a897f09f6c8496455368b7ecb42a9a5aac7fc715ac5df5697936e8c1c1956e13f languageName: node linkType: hard