diff --git a/src/modules/staking/enums/staking-endpoints.enum.ts b/src/modules/staking/enums/staking-endpoints.enum.ts index 47b002b..407cd24 100644 --- a/src/modules/staking/enums/staking-endpoints.enum.ts +++ b/src/modules/staking/enums/staking-endpoints.enum.ts @@ -7,4 +7,5 @@ export enum StakingEndpoints { VALIDATORS_BY_ADDRESS = '/validators/:address', VALIDATORS_UPTIME = '/validators/:address/uptime', VALIDATORS_RECENTLY_PROPOSED_BLOCKS = '/validators/:address/recently-proposed-blocks', + RECENTLY_PROPOSED_BLOCKS = '/recently-proposed-blocks', } diff --git a/src/modules/staking/services/staking.cache.ts b/src/modules/staking/services/staking.cache.ts index 3478891..5093068 100644 --- a/src/modules/staking/services/staking.cache.ts +++ b/src/modules/staking/services/staking.cache.ts @@ -80,12 +80,12 @@ export class StakingCache { return signatures.map(signature => JSON.parse(signature!)); } - async setRecentlyProposedBlock(address: string, block: unknown) { + async setValidatorRecentlyProposedBlock(address: string, block: unknown) { const key = this.createRedisKey(this.createRedisKey(StakingCachePrefix.VALIDATOR_RECENTLY_PROPOSED_BLOCKS, address), v4()); this.redisService.setWithTTL(key, JSON.stringify(block), config.cache.validatorRecentlyProposedBlock); } - async getRecentlyProposedBlock(address: string) { + async getValidatorRecentlyProposedBlocks(address: string) { const pattern = this.createRedisKey(this.createRedisKey(StakingCachePrefix.VALIDATOR_RECENTLY_PROPOSED_BLOCKS, address), '*'); const keys = await this.redisService.keys(pattern); const recentlyProposedBlocks = await Promise.all(keys.map((key: string) => this.redisService.get(key))); @@ -93,6 +93,14 @@ export class StakingCache { return recentlyProposedBlocks.map(block => JSON.parse(block!)); } + async getRecentlyProposedBlocks() { + const pattern = this.createRedisKey(this.createRedisKey(StakingCachePrefix.VALIDATOR_RECENTLY_PROPOSED_BLOCKS), '*'); + const keys = await this.redisService.keys(pattern); + const recentlyProposedBlocks = await Promise.all(keys.map((key: string) => this.redisService.get(key))); + + return recentlyProposedBlocks.map(block => JSON.parse(block!)); + } + async setLastBlock(block: unknown) { this.redisService.set(this.createRedisKey(StakingCachePrefix.LAST_BLOCK), JSON.stringify(block)); } diff --git a/src/modules/staking/services/staking.service.ts b/src/modules/staking/services/staking.service.ts index fcbcc45..7a301bb 100644 --- a/src/modules/staking/services/staking.service.ts +++ b/src/modules/staking/services/staking.service.ts @@ -342,11 +342,7 @@ export class StakingService implements OnModuleInit { } async getValidatorByAddress(address: string) { - const validators: ValidatorsViewDto[] = await this.getValidators(); - const validator = validators.find( - (validator) => validator.address === address - ); - + const validator = await this.findSingleValidator(address); if (!validator) { throw new BadRequestException(StakingError.VALIDATOR_ADDRESS_NOT_EXISTS); } @@ -354,6 +350,13 @@ export class StakingService implements OnModuleInit { return validator; } + private async findSingleValidator(address: string) { + const validators: ValidatorsViewDto[] = await this.getValidators(); + return validators.find( + (validator) => validator.address === address + ); + } + async newBlock(res: BlocksResponse) { try { // Create a map of validator addresses to their public keys @@ -379,16 +382,21 @@ export class StakingService implements OnModuleInit { signature.validator_address === res.block.header.proposer_address ) { signatureView.status = SignatureViewStatus.PROPOSED; - + const validator = await this.findSingleValidator(validatorAddress); + const blockWithValidatorInfo = { + ...blockView, + img: validator?.logo, + name: validator?.description.moniker + } // Cache the recently proposed block and emit an event - await this.cache.setRecentlyProposedBlock( + await this.cache.setValidatorRecentlyProposedBlock( validatorAddress, - blockView + blockWithValidatorInfo ); this.eventEmitter.emit( Event.BLOCK_CACHED, validatorAddress, - blockView + blockWithValidatorInfo ); } @@ -510,7 +518,7 @@ export class StakingService implements OnModuleInit { private async getSortedRecentlyProposedBlocks(address: string) { try { const recentlyBlocks: RecentlyProposedBlockDto[] = - await this.cache.getRecentlyProposedBlock(address); + await this.cache.getValidatorRecentlyProposedBlocks(address); return recentlyBlocks.sort( (a, b) => Number.parseFloat(b.height) - Number.parseFloat(a.height) ); @@ -541,4 +549,9 @@ export class StakingService implements OnModuleInit { return []; } + + async getRecentlyProposedBlocks() { + const recentlyProposedBlocks = await this.cache.getRecentlyProposedBlocks(); + return recentlyProposedBlocks || []; + } } diff --git a/src/modules/staking/staking.controller.ts b/src/modules/staking/staking.controller.ts index 83a4f42..8665e21 100644 --- a/src/modules/staking/staking.controller.ts +++ b/src/modules/staking/staking.controller.ts @@ -74,4 +74,9 @@ export class StakingController { ) { return this.service.getValidatorRecentlyProposedBlocks(address); } + + @Get(StakingEndpoints.RECENTLY_PROPOSED_BLOCKS) + async getRecentlyProposedBlocks() { + return this.service.getRecentlyProposedBlocks(); + } } diff --git a/src/modules/staking/staking.gateway.ts b/src/modules/staking/staking.gateway.ts index 0e3b2f2..e2d68a1 100644 --- a/src/modules/staking/staking.gateway.ts +++ b/src/modules/staking/staking.gateway.ts @@ -19,5 +19,6 @@ export class StakingGateway { @OnEvent(Event.BLOCK_CACHED) async blockUpdate(addr: string, block: unknown) { this.server.emit(`proposed_block.${addr}`, block); + this.server.emit(`proposed_block`, block); } }