Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Oracles-discovery #14

Merged
merged 15 commits into from
Mar 6, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/apps/human-app/server/.env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
HOST=
PORT=
REPUTATION_ORACLE_URL=
REDIS_PORT=
REDIS_HOST=
E2E_TESTING_EMAIL_ADDRESS=
E2E_TESTING_PASSWORD=
12 changes: 12 additions & 0 deletions packages/apps/human-app/server/Dockerfile
macnablocky marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM node:latest
LABEL authors="maciek.nabialek"
WORKDIR /app
COPY package.json yarn.lock ./
COPY packages/apps/human-app/server ./packages/apps/human-app/server

WORKDIR /app/packages/apps/human-app/server

RUN yarn install --frozen-lockfile --ignore-scripts
RUN yarn build
EXPOSE 3000
CMD ["yarn", "start"]
18 changes: 18 additions & 0 deletions packages/apps/human-app/server/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
version: '3.8'
services:
app:
build:
context: ../../../..
dockerfile: packages/apps/human-app/server/Dockerfile
ports:
- "3000:3000"
depends_on:
- redis
environment:
- REDIS_HOST=redis
- REDIS_PORT=6379

redis:
image: redis:latest
ports:
- "6379:6379"
12 changes: 9 additions & 3 deletions packages/apps/human-app/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,33 +23,39 @@
"@automapper/classes": "^8.8.1",
"@automapper/core": "^8.8.1",
"@automapper/nestjs": "^8.8.1",
"@human-protocol/sdk": "^2.0.0",
"@nestjs/axios": "^2.0.0",
"@nestjs/cache-manager": "^2.2.1",
"@nestjs/common": "^10.2.7",
"@nestjs/config": "^3.1.1",
"@nestjs/core": "^10.2.8",
"@nestjs/platform-express": "^10.2.6",
"@nestjs/swagger": "^7.1.13",
"cache-manager": "^5.4.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"ethers": "^6.11.0",
"joi": "^17.12.2",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.2.0"
},
"devDependencies": {
"@nestjs/cache-manager": "^2.2.1",
"@nestjs/cli": "^9.4.3",
"@nestjs/schematics": "^9.2.0",
"@nestjs/testing": "^9.4.3",
"@types/express": "^4.17.13",
macnablocky marked this conversation as resolved.
Show resolved Hide resolved
"@types/jest": "29.5.1",
"@types/node": "20.10.4",
"@types/supertest": "^2.0.15",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"cache-manager-redis-store": "^3.0.1",
"eslint": "^8.55.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.0.0",
"ioredis": "^5.3.2",
"jest": "29.5.0",
"nock": "^13.5.1",
"prettier": "^3.1.1",
"source-map-support": "^0.5.20",
"supertest": "^6.1.3",
"ts-jest": "29.1.1",
"ts-loader": "^9.2.3",
Expand Down
3 changes: 3 additions & 0 deletions packages/apps/human-app/server/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { OperatorModule } from './modules/user-operator/operator.module';
import { OperatorController } from './modules/user-operator/operator.controller';
import { WorkerController } from './modules/user-worker/worker.controller';
import { CommonConfigModule } from './common/config/common-config.module';
import { CacheFactoryConfig } from './common/config/cache-factory.config';
import { CacheModule } from '@nestjs/cache-manager';

@Module({
imports: [
Expand All @@ -22,6 +24,7 @@ import { CommonConfigModule } from './common/config/common-config.module';
AutomapperModule.forRoot({
strategyInitializer: classes(),
}),
CacheModule.registerAsync(CacheFactoryConfig),
HttpModule,
WorkerModule,
OperatorModule,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { CacheModuleAsyncOptions } from '@nestjs/common/cache';
import { ConfigModule } from '@nestjs/config';
import { EnvironmentConfigService } from './environment-config.service';
import { redisStore } from 'cache-manager-redis-store';
export const CacheFactoryConfig: CacheModuleAsyncOptions = {
isGlobal: true,
imports: [ConfigModule],
useFactory: async (configService: EnvironmentConfigService) => {
const store = await redisStore({
socket: {
host: configService.cacheHost,
port: configService.cachePort,
},
});
return {
store: () => store,
};
},
inject: [EnvironmentConfigService],
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ export class EnvironmentConfigService {
get reputationOracleUrl(): string {
return this.configService.get<string>('REPUTATION_ORACLE_URL', '');
}
get cachePort(): number {
return this.configService.get<number>('REDIS_PORT', 6379);
}
get cacheHost(): string {
return this.configService.get<string>('REDIS_HOST', 'localhost');
}
}

export const envValidator = Joi.object({
Expand Down
macnablocky marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { ChainId, IOperator } from '@human-protocol/sdk';
export class OracleDiscoveryDto {
chainId: ChainId;
address: string;
role: string;
}
export class OracleDiscoveryCommand {
chainId: ChainId;
address: string;
role: string;
}

export class OracleDiscoveryData implements IOperator {
address: string;
role?: string;
constructor(address: string, role: string) {
macnablocky marked this conversation as resolved.
Show resolved Hide resolved
this.address = address;
this.role = role;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {
Body,
Controller,
Get,
UsePipes,
ValidationPipe,
} from '@nestjs/common';
import { Mapper } from '@automapper/core';
import { InjectMapper } from '@automapper/nestjs';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { JobDiscoveryService } from './job-discovery.serivce';
import {
OracleDiscoveryCommand,
OracleDiscoveryData,
OracleDiscoveryDto,
} from './interface/oracle-discovery.interface';

@Controller()
export class JobDiscoveryController {
constructor(
private readonly service: JobDiscoveryService,
@InjectMapper() private readonly mapper: Mapper,
) {}
@ApiTags('Oracle-Discovery')
@Get('/oracles')
@ApiOperation({ summary: 'Operator signup' })
@UsePipes(new ValidationPipe())
public signupOperator(
@Body() oracleDiscoveryDto: OracleDiscoveryDto,
): Promise<OracleDiscoveryData[]> {
const oracleDiscoveryCommand = this.mapper.map(
oracleDiscoveryDto,
OracleDiscoveryDto,
OracleDiscoveryCommand,
);
return this.service.processOracleDiscovery(oracleDiscoveryCommand);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Injectable } from '@nestjs/common';
import { AutomapperProfile, InjectMapper } from '@automapper/nestjs';
import { createMap, Mapper } from '@automapper/core';
import {
OracleDiscoveryCommand,
OracleDiscoveryData,
OracleDiscoveryDto,
} from './interface/oracle-discovery.interface';

@Injectable()
export class JobDiscoveryProfile extends AutomapperProfile {
constructor(@InjectMapper() mapper: Mapper) {
super(mapper);
}

override get profile() {
return (mapper: Mapper) => {
createMap(mapper, OracleDiscoveryDto, OracleDiscoveryCommand);
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Module } from '@nestjs/common';
import { ReputationOracleModule } from '../../integrations/reputation-oracle/reputation-oracle.module';
import { OperatorService } from '../user-operator/operator.service';
import { OperatorProfile } from '../user-operator/operator.mapper';
import { JobDiscoveryController } from './job-discovery.controller';
import { JobDiscoveryService } from './job-discovery.serivce';
import { JobDiscoveryProfile } from './job-discovery.mapper';

@Module({
controllers: [JobDiscoveryController],
macnablocky marked this conversation as resolved.
Show resolved Hide resolved
providers: [JobDiscoveryService, JobDiscoveryProfile],
exports: [JobDiscoveryController, JobDiscoveryService],
})
export class JobDiscoveryModule {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Inject, Injectable } from '@nestjs/common';
import { ReputationOracleGateway } from '../../integrations/reputation-oracle/reputation-oracle.gateway';
import {
OracleDiscoveryCommand,
OracleDiscoveryData,
} from './interface/oracle-discovery.interface';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { Cache } from 'cache-manager';
import { IOperator, OperatorUtils } from '@human-protocol/sdk';

@Injectable()
export class JobDiscoveryService {
static readonly TTL_1_DAY = 24 * 60 * 60;
macnablocky marked this conversation as resolved.
Show resolved Hide resolved
constructor(
private reputationOracleGateway: ReputationOracleGateway,
@Inject(CACHE_MANAGER) private cacheManager: Cache,
) {}

async processOracleDiscovery(
command: OracleDiscoveryCommand,
): Promise<OracleDiscoveryData[]> {
const cachedData: OracleDiscoveryData[] | undefined =
await this.cacheManager.get(command.address);
if (cachedData) {
return cachedData;
}
const data: IOperator[] =
await this.getOperatorsForOracleDiscovery(command);
await this.setOperatorsForAddress(command.address, data);
return data;
}
getOperatorsForOracleDiscovery = (
cmd: OracleDiscoveryCommand,
): Promise<OracleDiscoveryData[]> => {
return OperatorUtils.getReputationNetworkOperators(
cmd.chainId,
cmd.address,
cmd.role,
);
};
setOperatorsForAddress = (
address: string,
operators: OracleDiscoveryData[],
): Promise<void> => {
return this.cacheManager.set(
address,
operators,
JobDiscoveryService.TTL_1_DAY,
);
};
}
Loading
Loading