Skip to content

Commit e2060c0

Browse files
authored
Calculate block time interval from recent block headers (#355)
* Calculate block time interval from recent block headers * Update changelog * Handle insufficient data * Fix build issue * Update changelogs from syncing deps
1 parent 193abd6 commit e2060c0

File tree

8 files changed

+57
-15
lines changed

8 files changed

+57
-15
lines changed

packages/common-cosmos/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

77
## [Unreleased]
8+
### Changed
9+
- Updated `@subql/common` (#356)
810

911
## [5.5.0] - 2025-08-26
1012
### Changed

packages/node/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

77
## [Unreleased]
8+
### Changed
9+
- Calculate block interval from block data rather than hard coded value (#355)
10+
- Updated `@subql/node-core` (#356)
811

912
## [5.3.0] - 2025-08-26
1013
### Changed

packages/node/src/blockchain.service.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
} from '@subql/common-cosmos';
1313
import {
1414
DatasourceParams,
15+
getLogger,
1516
Header,
1617
IBlock,
1718
IBlockchainService,
@@ -27,13 +28,10 @@ import { SubqueryProject } from './configure/SubqueryProject';
2728
import { ApiService, CosmosSafeClient } from './indexer/api.service';
2829
import { BlockContent, getBlockSize } from './indexer/types';
2930
import { IIndexerWorker } from './indexer/worker/worker';
30-
import {
31-
cosmosBlockToHeader,
32-
getBlockTimestamp,
33-
calcInterval,
34-
} from './utils/cosmos';
31+
import { cosmosBlockToHeader, getBlockTimestamp } from './utils/cosmos';
3532

3633
const { version: packageVersion } = require('../package.json');
34+
const logger = getLogger('blockchain-service');
3735

3836
const BLOCK_TIME_VARIANCE = 5000; //ms
3937
const INTERVAL_PERCENT = 0.9;
@@ -95,8 +93,13 @@ export class BlockchainService
9593

9694
// eslint-disable-next-line @typescript-eslint/require-await
9795
async getChainInterval(): Promise<number> {
98-
const chainInterval =
99-
calcInterval(this.apiService.unsafeApi) * INTERVAL_PERCENT;
96+
const interval = await this.apiService.unsafeApi
97+
.getBlockInterval()
98+
.catch((e) => {
99+
logger.error(e, 'Failed to get chain interval');
100+
return BLOCK_TIME_VARIANCE;
101+
});
102+
const chainInterval = interval * INTERVAL_PERCENT;
100103

101104
return Math.min(BLOCK_TIME_VARIANCE, chainInterval);
102105
}

packages/node/src/indexer/api.service.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,19 @@ describe('ApiService', () => {
100100
tmpPath = await makeTempDir();
101101
});
102102

103+
it('can get the block time interval', async () => {
104+
const endpoint = 'https://dymension.api.onfinality.io/tendermint/public';
105+
const chainId = 'dymension_1100-1';
106+
107+
await prepareApiService(endpoint, chainId, tmpPath);
108+
const interval = await apiService.api.getBlockInterval();
109+
110+
console.log('INTERVAL', interval);
111+
112+
expect(interval).toBeGreaterThan(0);
113+
expect(interval).toBeLessThan(20_000); // 20 seconds
114+
});
115+
103116
it('Falls back on rpc if kyve fails', async () => {
104117
const endpoint = 'https://rpc.mainnet.archway.io:443';
105118
const chainId = 'archway-1';

packages/node/src/indexer/api.service.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ import { CosmWasmClient, IndexedTx } from '@cosmjs/cosmwasm-stargate';
66
import { toHex } from '@cosmjs/encoding';
77
import { GeneratedType, Registry } from '@cosmjs/proto-signing';
88
import { defaultRegistryTypes, SearchTxQuery } from '@cosmjs/stargate';
9-
import { CometClient } from '@cosmjs/tendermint-rpc';
9+
import {
10+
Comet38Client,
11+
CometClient,
12+
Tendermint34Client,
13+
Tendermint37Client,
14+
} from '@cosmjs/tendermint-rpc';
1015
import { Injectable, OnApplicationShutdown } from '@nestjs/common';
1116
import { EventEmitter2 } from '@nestjs/event-emitter';
1217
import { CosmosProjectNetConfig } from '@subql/common-cosmos';
@@ -203,6 +208,25 @@ export class CosmosClient extends CosmWasmClient {
203208
super(_cometClient as any);
204209
}
205210

211+
async getBlockInterval(): Promise<number> {
212+
const { blockMetas } = await this._cometClient.blockchain();
213+
214+
if (!blockMetas || blockMetas.length < 2) {
215+
throw new Error(
216+
`Insufficient block headers to calculate interval: ${
217+
blockMetas?.length ?? 0
218+
} headers available`,
219+
);
220+
}
221+
222+
const timestamps = blockMetas.map((h) => h.header.time.getTime());
223+
224+
return Math.abs(
225+
timestamps.slice(1).reduce((sum, v, i) => sum + (v - timestamps[i]), 0) /
226+
(timestamps.length - 1),
227+
);
228+
}
229+
206230
// eslint-disable-next-line @typescript-eslint/require-await
207231
async blockInfo(height?: number): Promise<BlockResponse> {
208232
return this._cometClient.block(height);

packages/node/src/indexer/worker/worker.service.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ export class WorkerService extends BaseWorkerService<
5757
return block;
5858
}
5959

60-
protected toBlockResponse(block: BlockContent): FetchBlockResponse {
61-
return cosmosBlockToHeader(block.block.header);
60+
protected toBlockResponse(block: IBlock<BlockContent>): FetchBlockResponse {
61+
return block.getHeader();
6262
}
6363

6464
protected async processFetchedBlock(

packages/node/src/utils/cosmos.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -670,8 +670,3 @@ export class LazyBlockContent implements BlockContent {
670670
return this._wrappedFinalizedBlockEvents;
671671
}
672672
}
673-
674-
export function calcInterval(api: CosmosClient): number {
675-
// TODO find a way to get this from the blockchain
676-
return 6000;
677-
}

packages/types/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

77
## [Unreleased]
8+
### Changed
9+
- Updated `@subql/types-core` (#356)
810

911
## [4.2.0] - 2025-08-26
1012
### Changed

0 commit comments

Comments
 (0)