Skip to content

Commit

Permalink
Merge pull request #30 from klayrHQ/search-api
Browse files Browse the repository at this point in the history
search module
  • Loading branch information
Theezr authored Aug 14, 2024
2 parents 0a6d384 + 7f8a5fb commit 6d574c4
Show file tree
Hide file tree
Showing 11 changed files with 195 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,4 @@ pids
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

prisma/db

2 changes: 2 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { ScheduleModule } from '@nestjs/schedule';
import { StateModule } from './state/state.module';
import { GeneratorModule } from './generator/generator.module';
import { DbCacheModule } from './db-cache/db-cache.module';
import { SearchModule } from './search/search.module';

@Module({
imports: [
Expand All @@ -32,6 +33,7 @@ import { DbCacheModule } from './db-cache/db-cache.module';
IndexerModule,
ChainEventModule,
GeneratorModule,
SearchModule,
],
controllers: [],
providers: [],
Expand Down
21 changes: 21 additions & 0 deletions src/block/block-repo.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,25 @@ export class BlockRepoService {
});
}
}

public async searchBlocks(search: string): Promise<{ id: string; height: number }[]> {
const height = Number(search);
const where: Prisma.BlockWhereInput = {
OR: [{ id: { equals: search } }],
};

if (!isNaN(height)) {
where.OR.push({ height: { equals: height } });
}

const blocks = await this.prisma.block.findMany({
where,
select: {
id: true,
height: true,
},
});

return blocks;
}
}
30 changes: 30 additions & 0 deletions src/search/dto/get-search-res.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { ApiResponseOptions } from '@nestjs/swagger';

export class SearchValidators {
name: string;
address: string;
publicKey: string;
rank: number;
}

export class SearchBlocks {
height: number;
id: string;
}

export class SearchTransactions {
id: string;
sender: string;
}

export class GetSearchResponse {
validators: SearchValidators[];
blocks: SearchBlocks[];
transactions: SearchTransactions[];
}

export const getSearchResponse: ApiResponseOptions = {
status: 200,
description: 'The search results have been successfully fetched.',
type: GetSearchResponse,
};
9 changes: 9 additions & 0 deletions src/search/dto/get-search.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { IsString } from 'class-validator';

export class SearchQueryDto {
/**
* The search query to search in blocks, transactions and validators
*/
@IsString()
search: string;
}
58 changes: 58 additions & 0 deletions src/search/search.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Controller, Query, Get, ValidationPipe, UsePipes } from '@nestjs/common';
import { BlockRepoService } from 'src/block/block-repo.service';
import { TransactionRepoService } from 'src/transaction/transaction-repo.service';
import { ValidatorRepoService } from 'src/validator/validator.repo-service';
import { SearchQueryDto } from './dto/get-search.dto';
import { ApiResponse } from '@nestjs/swagger';
import { GetSearchResponse, getSearchResponse } from './dto/get-search-res.dto';
import { getKlayr32AddressFromAddress } from 'src/utils/helpers';
import { HEX_ADDRESS_LENGTH } from 'src/utils/constants';

@Controller('search')
export class SearchController {
constructor(
private readonly blockRepoService: BlockRepoService,
private readonly validatorRepoService: ValidatorRepoService,
private readonly transactionRepoService: TransactionRepoService,
) {}

@Get()
@UsePipes(new ValidationPipe({ transform: true, whitelist: true, forbidNonWhitelisted: true }))
@ApiResponse(getSearchResponse)
async getSearchResults(@Query() query: SearchQueryDto): Promise<GetSearchResponse> {
let { search } = query;

if (search.length === HEX_ADDRESS_LENGTH) {
search = getKlayr32AddressFromAddress(search);
}

const [blocks, validators, transactions] = await Promise.all([
this.blockRepoService.searchBlocks(search),
this.validatorRepoService.searchValidators(search),
this.transactionRepoService.searchTransactions(search),
]);

const formattedBlocks = blocks.map((block) => ({
height: block.height,
id: block.id,
}));

const formattedValidators = validators.map((validator) => ({
name: validator.account.name,
address: validator.address,
publicKey: validator.account.publicKey,
rank: validator.rank,
}));

const formattedTransactions = transactions.map((transaction) => ({
id: transaction.id,
sender: transaction.sender.address,
}));

return {
validators: formattedValidators,
blocks: formattedBlocks,
transactions: formattedTransactions,
};
}
}
11 changes: 11 additions & 0 deletions src/search/search.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';
import { SearchController } from './search.controller';
import { BlockModule } from 'src/block/block.module';
import { ValidatorModule } from 'src/validator/validator.module';
import { TransactionModule } from 'src/transaction/transaction.module';

@Module({
imports: [BlockModule, ValidatorModule, TransactionModule],
controllers: [SearchController],
})
export class SearchModule {}
21 changes: 21 additions & 0 deletions src/transaction/transaction-repo.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,25 @@ export class TransactionRepoService {
});
}
}

public async searchTransactions(search: string): Promise<
Prisma.TransactionGetPayload<{
include: {
sender: true;
};
}>[]
> {
const where: Prisma.TransactionWhereInput = {
id: { contains: search },
};

const transactions = await this.prisma.transaction.findMany({
where,
include: {
sender: true,
},
});

return transactions;
}
}
2 changes: 1 addition & 1 deletion src/transaction/transaction.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { AccountModule } from 'src/account/account.module';
@Module({
imports: [StateModule, NodeApiModule, EventModule, DbCacheModule, AccountModule],
providers: [PrismaService, TransactionRepoService, TransactionService],
exports: [TransactionService],
exports: [TransactionService, TransactionRepoService],
controllers: [TransactionController],
})
export class TransactionModule {}
6 changes: 6 additions & 0 deletions src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,9 @@ export const DEFAULT_VALIDATORS_TO_FETCH = 10;
export const MAX_VALIDATORS_TO_FETCH = 100;
export const MINIMUM_VALIDATOR_WEIGHT = BigInt(1_000e8);
export const ACTIVE_VALIDATORS = 51;

////////////////////////////
/// Search ///
////////////////////////////

export const HEX_ADDRESS_LENGTH = 40;
35 changes: 35 additions & 0 deletions src/validator/validator.repo-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,39 @@ export class ValidatorRepoService {
},
});
}

public async searchValidators(search: string): Promise<
{
address: string;
rank: number;
account: {
name: string;
publicKey: string;
};
}[]
> {
const where: Prisma.ValidatorWhereInput = {
OR: [
{ account: { name: { contains: search } } },
{ address: { equals: search } },
{ account: { publicKey: { equals: search } } },
],
};

const validators = await this.prisma.validator.findMany({
where,
select: {
address: true,
rank: true,
account: {
select: {
name: true,
publicKey: true,
},
},
},
});

return validators;
}
}

0 comments on commit 6d574c4

Please sign in to comment.