Skip to content

Commit

Permalink
fix: lower casefor module address, add tests, fix interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
Amuhar committed Sep 20, 2023
1 parent 0b22da6 commit e4b1057
Show file tree
Hide file tree
Showing 33 changed files with 330 additions and 1,216 deletions.
2 changes: 1 addition & 1 deletion src/http/common/entities/el-block-snapshot.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ApiProperty } from '@nestjs/swagger';
import { ElMetaEntity } from '../../../storage/el-meta.entity';

export class ELBlockSnapshot {
export class ELBlockSnapshot implements ElMetaEntity {
constructor(meta: ElMetaEntity) {
this.blockNumber = meta.blockNumber;
this.blockHash = meta.blockHash;
Expand Down
10 changes: 3 additions & 7 deletions src/http/common/entities/module-id.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { BadRequestException } from '@nestjs/common';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import { isAddress } from 'ethers/lib/utils';

function toModuleId(moduleId: string): string | number {
if (isContractAddress(moduleId)) {
return moduleId;
if (isAddress(moduleId)) {
return moduleId.toLowerCase();
}

if (Number(moduleId)) {
Expand All @@ -14,11 +15,6 @@ function toModuleId(moduleId: string): string | number {
throw new BadRequestException([`module_id must be a contract address or numeric value`]);
}

export function isContractAddress(address: string): boolean {
const contractAddressRegex = /^0x[0-9a-fA-F]{40}$/;
return contractAddressRegex.test(address);
}

export class ModuleId {
@ApiProperty({
name: 'module_id',
Expand Down
1 change: 0 additions & 1 deletion src/http/common/entities/pubkeys.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsArray, ArrayMinSize, IsString } from 'class-validator';

// TODO: put put it with key query at the same file
export class KeysFindBody {
@ApiProperty({
required: true,
Expand Down
78 changes: 40 additions & 38 deletions src/http/common/entities/sr-module.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import { ApiProperty } from '@nestjs/swagger';
import { STAKING_MODULE_TYPE } from 'staking-router-modules/constants';

Check warning on line 2 in src/http/common/entities/sr-module.ts

View workflow job for this annotation

GitHub Actions / test

'STAKING_MODULE_TYPE' is defined but never used
import { SrModuleEntity } from 'storage/sr-module.entity';

// TODO: this class is okay, as it format data from db for response
// but we use it in staking module service
export class SRModule {
constructor(module: SrModuleEntity) {
this.nonce = module.nonce;
this.type = module.type;
this.id = module.moduleId;
this.stakingModuleAddress = module.stakingModuleAddress;
// TODO: maybe rename field stakingModuleFee
this.moduleFee = module?.stakingModuleFee ?? null;
this.treasuryFee = module?.treasuryFee ?? null;
this.targetShare = module?.targetShare ?? null;
this.status = module?.status ?? null;
this.name = module.name;
this.lastDepositAt = module?.lastDepositAt ?? null;
this.lastDepositBlock = module?.lastDepositBlock ?? null;
export class StakingModuleResponse implements Omit<SrModuleEntity, 'id' | 'moduleId'> {
constructor(stakingModule: SrModuleEntity) {
this.nonce = stakingModule.nonce;
this.type = stakingModule.type;
this.id = stakingModule.moduleId;
this.stakingModuleAddress = stakingModule.stakingModuleAddress;
this.moduleFee = stakingModule.moduleFee;
this.treasuryFee = stakingModule.treasuryFee;
this.targetShare = stakingModule.targetShare;
this.status = stakingModule.status;
this.name = stakingModule.name;
this.lastDepositAt = stakingModule.lastDepositAt;
this.lastDepositBlock = stakingModule.lastDepositBlock;
this.exitedValidatorsCount = stakingModule.exitedValidatorsCount;
this.active = stakingModule.active;
}

@ApiProperty({
Expand All @@ -26,62 +26,64 @@ export class SRModule {
nonce: number;

@ApiProperty({
description: 'type of module',
description: 'Type of module',
})
type: string;
type: string; //STAKING_MODULE_TYPE;

@ApiProperty({
description: 'unique id of the module',
description: 'Unique id of the module',
})
id: number;

@ApiProperty({
description: 'address of module',
nullable: true,
description: 'Address of module',
})
stakingModuleAddress: string;

@ApiProperty({
description: 'reward fee of the module',
nullable: true,
description: 'Reward fee of the module',
})
moduleFee: number | null;
moduleFee: number;

@ApiProperty({
description: 'treasury fee',
nullable: true,
description: 'Treasury fee',
})
treasuryFee: number | null;
treasuryFee: number;

@ApiProperty({
description: 'target percent of total keys in protocol, in BP',
nullable: true,
description: 'Target percent of total keys in protocol, in BP',
})
targetShare: number | null;
targetShare: number;

@ApiProperty({
description:
'module status if module can not accept the deposits or can participate in further reward distribution',
nullable: true,
'Module status if module can not accept the deposits or can participate in further reward distribution',
})
status: number | null;
status: number;

@ApiProperty({
description: 'name of module',
description: 'Name of module',
})
name: string;

@ApiProperty({
description: 'block.timestamp of the last deposit of the module',
nullable: true,
})
lastDepositAt: number | null;
lastDepositAt: number;

@ApiProperty({
description: 'block.number of the last deposit of the module',
nullable: true,
})
lastDepositBlock: number | null;
lastDepositBlock: number;

// exitedValidatorsCount: number;
@ApiProperty({
description: 'Exited validators count',
})
exitedValidatorsCount: number;

@ApiProperty({
description: 'Module activation status',
})
active: boolean;
}
4 changes: 2 additions & 2 deletions src/http/keys/entities/response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import { ELMeta, Key } from '../../common/entities';
export class KeyListResponse {
@ApiProperty({
type: () => [Key],
description: 'List of keys with general fields for all modules and SR module address',
description: 'List of keys for all modules',
})
data!: Key[];

@ApiProperty({
type: () => ELMeta,
nullable: true,
description: 'Meta for keys endpoints',
description: 'Meta',
})
meta!: ELMeta;
}
30 changes: 18 additions & 12 deletions src/http/module.fixture.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { StakingModule } from '../staking-router-modules/interfaces/staking-module.interface';
import { STAKING_MODULE_TYPE } from '../staking-router-modules/constants';
import { StakingModuleResponse } from './common/entities';

export const curatedModule = {
id: 1,
stakingModuleAddress: '0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9',
stakingModuleFee: 100,
export const curatedModule: StakingModule = {
moduleId: 1,
stakingModuleAddress: '0xdc64a140aa3e981100a9beca4e685f962f0cf6c9',
moduleFee: 100,
treasuryFee: 100,
targetShare: 100,
status: 0,
Expand All @@ -15,10 +17,10 @@ export const curatedModule = {
active: true,
};

export const dvtModule = {
id: 2,
stakingModuleAddress: '0x0165878A594ca255338adfa4d48449f69242Eb8F',
stakingModuleFee: 100,
export const dvtModule: StakingModule = {
moduleId: 2,
stakingModuleAddress: '0x0165878a594ca255338adfa4d48449f69242eb8f',
moduleFee: 100,
treasuryFee: 100,
targetShare: 100,
status: 0,
Expand All @@ -32,9 +34,9 @@ export const dvtModule = {

export const srModules = [curatedModule, dvtModule];

export const curatedModuleResp = {
export const curatedModuleResp: StakingModuleResponse = {
id: 1,
stakingModuleAddress: '0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9',
stakingModuleAddress: '0xdc64a140aa3e981100a9beca4e685f962f0cf6c9',
moduleFee: 100,
treasuryFee: 100,
targetShare: 100,
Expand All @@ -44,11 +46,13 @@ export const curatedModuleResp = {
lastDepositAt: 1691500732,
lastDepositBlock: 9,
nonce: 1,
exitedValidatorsCount: 0,
active: true,
};

export const dvtModuleResp = {
export const dvtModuleResp: StakingModuleResponse = {
id: 2,
stakingModuleAddress: '0x0165878A594ca255338adfa4d48449f69242Eb8F',
stakingModuleAddress: '0x0165878a594ca255338adfa4d48449f69242eb8f',
moduleFee: 100,
treasuryFee: 100,
targetShare: 100,
Expand All @@ -58,4 +62,6 @@ export const dvtModuleResp = {
lastDepositAt: 1691500733,
lastDepositBlock: 10,
nonce: 1,
exitedValidatorsCount: 0,
active: true,
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ApiProperty } from '@nestjs/swagger';
import { Key, SRModule, ELMeta } from '../../common/entities/';
import { Key, StakingModuleResponse, ELMeta } from '../../common/entities/';

export class KeyListWithModule {
@ApiProperty({
Expand All @@ -10,9 +10,9 @@ export class KeyListWithModule {

@ApiProperty({
description: 'Detailed Staking Router information',
type: () => SRModule,
type: () => StakingModuleResponse,
})
module!: SRModule;
module!: StakingModuleResponse;
}

export class GroupedByModuleKeyListResponse {
Expand Down
6 changes: 3 additions & 3 deletions src/http/sr-modules-keys/entities/sr-module-keys.response.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ApiProperty, ApiExtraModels } from '@nestjs/swagger';
import { SRModule, Key, ELMeta } from '../../common/entities/';
import { StakingModuleResponse, Key, ELMeta } from '../../common/entities/';

@ApiExtraModels(Key)
export class SRKeyListWithModule {
Expand All @@ -11,9 +11,9 @@ export class SRKeyListWithModule {

@ApiProperty({
description: 'Detailed Staking Router information',
type: () => SRModule,
type: () => StakingModuleResponse,
})
module!: SRModule;
module!: StakingModuleResponse;
}

export class SRModuleKeyListResponse {
Expand Down
22 changes: 11 additions & 11 deletions src/http/sr-modules-keys/sr-modules-keys.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ describe('SRModulesKeysController (e2e)', () => {
});

it('Should return all keys for request without filters', async () => {
const resp = await request(app.getHttpServer()).get(`/v1/modules/${dvtModule.id}/keys`);
const resp = await request(app.getHttpServer()).get(`/v1/modules/${dvtModule.moduleId}/keys`);

expect(resp.status).toEqual(200);
expect(resp.body.data.keys).toEqual(expect.arrayContaining(dvtModuleKeys));
Expand All @@ -140,7 +140,7 @@ describe('SRModulesKeysController (e2e)', () => {

it('Should return 400 error if operatorIndex is not a number', async () => {
const resp = await request(app.getHttpServer())
.get(`/v1/modules/${dvtModule.id}/keys`)
.get(`/v1/modules/${dvtModule.moduleId}/keys`)
.query({ used: false, operatorIndex: 'one' });
expect(resp.status).toEqual(400);
expect(resp.body).toEqual({
Expand All @@ -152,15 +152,15 @@ describe('SRModulesKeysController (e2e)', () => {

it('Should return 400 error if used is not a boolean value', async () => {
const resp = await request(app.getHttpServer())
.get(`/v1/modules/${dvtModule.id}/keys`)
.get(`/v1/modules/${dvtModule.moduleId}/keys`)
.query({ used: 0, operatorIndex: 2 });
expect(resp.status).toEqual(400);
expect(resp.body).toEqual({ error: 'Bad Request', message: ['used must be a boolean value'], statusCode: 400 });
});

it('Should return used keys for operator one', async () => {
const resp = await request(app.getHttpServer())
.get(`/v1/modules/${dvtModule.id}/keys`)
.get(`/v1/modules/${dvtModule.moduleId}/keys`)
.query({ used: true, operatorIndex: 1 });

const expectedKeys = dvtModuleKeys.filter((key) => key.used && key.operatorIndex == 1);
Expand All @@ -179,7 +179,7 @@ describe('SRModulesKeysController (e2e)', () => {

it('Should return unused keys for operator one', async () => {
const resp = await request(app.getHttpServer())
.get(`/v1/modules/${dvtModule.id}/keys`)
.get(`/v1/modules/${dvtModule.moduleId}/keys`)
.query({ used: false, operatorIndex: 1 });

const expectedKeys = dvtModuleKeys.filter((key) => !key.used && key.operatorIndex == 1);
Expand All @@ -198,7 +198,7 @@ describe('SRModulesKeysController (e2e)', () => {

it('Should return empty keys list for non-existent operator', async () => {
const resp = await request(app.getHttpServer())
.get(`/v1/modules/${dvtModule.id}/keys`)
.get(`/v1/modules/${dvtModule.moduleId}/keys`)
.query({ operatorIndex: 777 });

expect(resp.status).toEqual(200);
Expand Down Expand Up @@ -244,7 +244,7 @@ describe('SRModulesKeysController (e2e)', () => {

it('Should return too early response if there are no meta', async () => {
await moduleStorageService.upsert(dvtModule, 1);
const resp = await request(app.getHttpServer()).get(`/v1/modules/${dvtModule.id}/keys`);
const resp = await request(app.getHttpServer()).get(`/v1/modules/${dvtModule.moduleId}/keys`);
expect(resp.status).toEqual(425);
expect(resp.body).toEqual({ message: 'Too early response', statusCode: 425 });
});
Expand All @@ -271,7 +271,7 @@ describe('SRModulesKeysController (e2e)', () => {
const pubkeys = [dvtModuleKeys[0].key, dvtModuleKeys[1].key];

const resp = await request(app.getHttpServer())
.post(`/v1/modules/${dvtModule.id}/keys/find`)
.post(`/v1/modules/${dvtModule.moduleId}/keys/find`)
.set('Content-Type', 'application/json')
.send({ pubkeys });

Expand All @@ -291,7 +291,7 @@ describe('SRModulesKeysController (e2e)', () => {
const pubkeys = ['somerandomkey'];

const resp = await request(app.getHttpServer())
.post(`/v1/modules/${dvtModule.id}/keys/find`)
.post(`/v1/modules/${dvtModule.moduleId}/keys/find`)
.set('Content-Type', 'application/json')
.send({ pubkeys });

Expand All @@ -309,7 +309,7 @@ describe('SRModulesKeysController (e2e)', () => {

it('Should return validation error if pubkeys list was not provided', async () => {
const resp = await request(app.getHttpServer())
.post(`/v1/modules/${dvtModule.id}/keys/find`)
.post(`/v1/modules/${dvtModule.moduleId}/keys/find`)
.set('Content-Type', 'application/json')
.send({ pubkeys: [] });

Expand All @@ -333,7 +333,7 @@ describe('SRModulesKeysController (e2e)', () => {
it('Should return too early response if there are no meta', async () => {
await moduleStorageService.upsert(dvtModule, 1);
const resp = await request(app.getHttpServer())
.post(`/v1/modules/${dvtModule.id}/keys/find`)
.post(`/v1/modules/${dvtModule.moduleId}/keys/find`)
.set('Content-Type', 'application/json')
.send({ pubkeys: ['somerandomkey'] });
expect(resp.status).toEqual(425);
Expand Down
Loading

0 comments on commit e4b1057

Please sign in to comment.