Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
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: 1 addition & 1 deletion docker-setup/docker-compose.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ services:
timeout: 5s
retries: 5
volumes:
- graph-node-db-data:/var/lib/postgresql/data:Z
- graph-node-db-data:/var/lib/postgresql:Z
environment:
POSTGRES_USER: *graph_db_user
POSTGRES_PASSWORD: *graph_db_passwrod
Expand Down
4 changes: 4 additions & 0 deletions packages/apps/human-app/server/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ import { OperatorController } from './modules/user-operator/operator.controller'
import { OperatorModule } from './modules/user-operator/operator.module';
import { WorkerController } from './modules/user-worker/worker.controller';
import { WorkerModule } from './modules/user-worker/worker.module';
import { ExchangeApiKeysModule } from './modules/exchange-api-keys/exchange-api-keys.module';
import { ExchangeApiKeysController } from './modules/exchange-api-keys/exchange-api-keys.controller';

const JOI_BOOLEAN_STRING_SCHEMA = Joi.string().valid('true', 'false');

Expand Down Expand Up @@ -147,6 +149,7 @@ const JOI_BOOLEAN_STRING_SCHEMA = Joi.string().valid('true', 'false');
NDAModule,
AbuseModule,
GovernanceModule,
ExchangeApiKeysModule,
],
controllers: [
AppController,
Expand All @@ -162,6 +165,7 @@ const JOI_BOOLEAN_STRING_SCHEMA = Joi.string().valid('true', 'false');
NDAController,
AbuseController,
GovernanceController,
ExchangeApiKeysController,
],
exports: [HttpModule],
providers: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,21 @@ export class GatewayConfigService {
method: HttpMethod.GET,
headers: this.JSON_HEADER,
},
[ReputationOracleEndpoints.EXCHANGE_API_KEYS_ENROLL]: {
endpoint: '/exchange-api-keys',
method: HttpMethod.POST,
headers: this.JSON_HEADER,
},
[ReputationOracleEndpoints.EXCHANGE_API_KEYS_DELETE]: {
endpoint: '/exchange-api-keys',
method: HttpMethod.DELETE,
headers: this.JSON_HEADER,
},
[ReputationOracleEndpoints.EXCHANGE_API_KEYS_RETRIEVE]: {
endpoint: '/exchange-api-keys',
method: HttpMethod.GET,
headers: this.JSON_HEADER,
},
} as Record<ReputationOracleEndpoints, GatewayEndpointConfig>,
},
[ExternalApiName.HCAPTCHA_LABELING_STATS]: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export enum HttpMethod {
GET = 'GET',
POST = 'POST',
DELETE = 'DELETE',
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ export enum ReputationOracleEndpoints {
SIGN_NDA = 'sign_nda',
REPORT_ABUSE = 'report_abuse',
GET_ABUSE_REPORTS = 'get_abuse_reports',
EXCHANGE_API_KEYS_ENROLL = 'exchange_api_keys_enroll',
EXCHANGE_API_KEYS_DELETE = 'exchange_api_keys_delete',
EXCHANGE_API_KEYS_RETRIEVE = 'exchange_api_keys_retrieve',
}
export enum HCaptchaLabelingStatsEndpoints {
USER_STATS = 'user_stats',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export class JwtHttpStrategy extends PassportStrategy(Strategy, 'jwt-http') {
status: string;
wallet_address: string;
reputation_network: string;
is_stake_eligible?: boolean;
qualifications?: string[];
site_key?: string;
email?: string;
Expand All @@ -58,6 +59,7 @@ export class JwtHttpStrategy extends PassportStrategy(Strategy, 'jwt-http') {
wallet_address: payload.wallet_address,
status: payload.status,
reputation_network: payload.reputation_network,
is_stake_eligible: payload.is_stake_eligible,
qualifications: payload.qualifications,
site_key: payload.site_key,
email: payload.email,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export class JwtUserData {
@AutoMap()
reputation_network: string;
@AutoMap()
is_stake_eligible?: boolean;
@AutoMap()
email?: string;
@AutoMap()
qualifications?: string[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ import {
ReportAbuseParams,
ReportedAbuseResponse,
} from '../../modules/abuse/model/abuse.model';
import { HttpMethod } from '../../common/enums/http-method';
import {
EnrollExchangeApiKeysCommand,
EnrollExchangeApiKeysData,
} from '../../modules/exchange-api-keys/model/exchange-api-keys.model';

@Injectable()
export class ReputationOracleGateway {
Expand Down Expand Up @@ -136,6 +141,44 @@ export class ReputationOracleGateway {
const response = await lastValueFrom(this.httpService.request(options));
return response.data as T;
}

async enrollExchangeApiKeys(
command: EnrollExchangeApiKeysCommand,
): Promise<{ id: number }> {
const enrollExchangeApiKeysData = this.mapper.map(
command,
EnrollExchangeApiKeysCommand,
EnrollExchangeApiKeysData,
);
const options = this.getEndpointOptions(
ReputationOracleEndpoints.EXCHANGE_API_KEYS_ENROLL,
enrollExchangeApiKeysData,
command.token,
);
options.url = `${options.url}/${command.exchangeName}`;
return this.handleRequestToReputationOracle<{ id: number }>(options);
}

async deleteExchangeApiKeys(token: string) {
const options = this.getEndpointOptions(
ReputationOracleEndpoints.EXCHANGE_API_KEYS_DELETE,
undefined,
token,
);
options.method = HttpMethod.DELETE;
return this.handleRequestToReputationOracle<void>(options);
}

async retrieveExchangeApiKeys(token: string): Promise<{ apiKey: string }> {
const options = this.getEndpointOptions(
ReputationOracleEndpoints.EXCHANGE_API_KEYS_RETRIEVE,
undefined,
token,
);
return this.handleRequestToReputationOracle<{
apiKey: string;
}>(options);
}
async sendWorkerSignup(command: SignupWorkerCommand): Promise<void> {
const signupWorkerData = this.mapper.map(
command,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ import {
ReportAbuseData,
ReportAbuseParams,
} from '../../modules/abuse/model/abuse.model';
import {
EnrollExchangeApiKeysCommand,
EnrollExchangeApiKeysData,
} from '../../modules/exchange-api-keys/model/exchange-api-keys.model';

@Injectable()
export class ReputationOracleProfile extends AutomapperProfile {
Expand Down Expand Up @@ -166,6 +170,15 @@ export class ReputationOracleProfile extends AutomapperProfile {
destination: new SnakeCaseNamingConvention(),
}),
);
createMap(
mapper,
EnrollExchangeApiKeysCommand,
EnrollExchangeApiKeysData,
namingConventions({
source: new CamelCaseNamingConvention(),
destination: new SnakeCaseNamingConvention(),
}),
);
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import {
Body,
Controller,
Delete,
Get,
HttpCode,
Param,
Post,
Request,
} from '@nestjs/common';
import {
ApiBearerAuth,
ApiBody,
ApiOperation,
ApiResponse,
ApiTags,
} from '@nestjs/swagger';
import { RequestWithUser } from '../../common/interfaces/jwt';
import { ExchangeApiKeysService } from '../../modules/exchange-api-keys/exchange-api-keys.service';
import { InjectMapper } from '@automapper/nestjs';
import { Mapper } from '@automapper/core';
import {
EnrollExchangeApiKeysCommand,
EnrollExchangeApiKeysDto,
RetrieveExchangeApiKeysResponse,
} from './model/exchange-api-keys.model';

@ApiTags('Exchange-Api-Keys')
@ApiBearerAuth()
@Controller('/exchange-api-keys')
export class ExchangeApiKeysController {
constructor(
private readonly service: ExchangeApiKeysService,
@InjectMapper() private readonly mapper: Mapper,
) {}

@ApiOperation({ summary: 'Enroll API keys for exchange' })
@ApiBody({ type: EnrollExchangeApiKeysDto })
@ApiResponse({ status: 200, description: 'Exchange API keys enrolled' })
@HttpCode(200)
@Post('/:exchange_name')
async enroll(
@Param('exchange_name') exchangeName: string,
@Body() dto: EnrollExchangeApiKeysDto,
@Request() req: RequestWithUser,
): Promise<{ id: number }> {
const command = this.mapper.map(
dto,
EnrollExchangeApiKeysDto,
EnrollExchangeApiKeysCommand,
);
command.token = req.token;
command.exchangeName = exchangeName;
return this.service.enroll(command);
}

@ApiOperation({ summary: 'Delete API keys for exchange' })
@ApiResponse({ status: 204, description: 'Exchange API keys deleted' })
@HttpCode(204)
@Delete('/')
async delete(@Request() req: RequestWithUser): Promise<void> {
await this.service.delete(req.token);
}

@ApiOperation({
summary: 'Retrieve API keys for exchange',
})
@Get('/')
async retrieve(
@Request() req: RequestWithUser,
): Promise<RetrieveExchangeApiKeysResponse> {
return this.service.retrieve(req.token);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Mapper, createMap } from '@automapper/core';
import { AutomapperProfile, InjectMapper } from '@automapper/nestjs';
import { Injectable } from '@nestjs/common';
import {
EnrollExchangeApiKeysCommand,
EnrollExchangeApiKeysDto,
} from './model/exchange-api-keys.model';

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

override get profile() {
return (mapper: Mapper) => {
createMap(mapper, EnrollExchangeApiKeysDto, EnrollExchangeApiKeysCommand);
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Module } from '@nestjs/common';
import { ExchangeApiKeysController } from '../../modules/exchange-api-keys/exchange-api-keys.controller';
import { ExchangeApiKeysService } from '../../modules/exchange-api-keys/exchange-api-keys.service';
import { ReputationOracleModule } from '../../integrations/reputation-oracle/reputation-oracle.module';
import { ExchangeApiKeysProfile } from './exchange-api-keys.mapper.profile';

@Module({
imports: [ReputationOracleModule],
controllers: [ExchangeApiKeysController],
providers: [ExchangeApiKeysService, ExchangeApiKeysProfile],
exports: [ExchangeApiKeysService],
})
export class ExchangeApiKeysModule {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Injectable } from '@nestjs/common';
import { ReputationOracleGateway } from '../../integrations/reputation-oracle/reputation-oracle.gateway';
import {
EnrollExchangeApiKeysCommand,
RetrieveExchangeApiKeysResponse,
} from './model/exchange-api-keys.model';

@Injectable()
export class ExchangeApiKeysService {
constructor(private readonly reputationOracle: ReputationOracleGateway) {}

enroll(command: EnrollExchangeApiKeysCommand): Promise<{ id: number }> {
return this.reputationOracle.enrollExchangeApiKeys(command);
}

delete(token: string): Promise<void> {
return this.reputationOracle.deleteExchangeApiKeys(token);
}

retrieve(token: string): Promise<RetrieveExchangeApiKeysResponse> {
return this.reputationOracle.retrieveExchangeApiKeys(token);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { AutoMap } from '@automapper/classes';
import { ApiProperty } from '@nestjs/swagger';
import { IsString } from 'class-validator';

export class EnrollExchangeApiKeysDto {
@AutoMap()
@IsString()
@ApiProperty()
apiKey: string;

@AutoMap()
@IsString()
@ApiProperty()
secretKey: string;
}

export class EnrollExchangeApiKeysCommand {
@AutoMap()
apiKey: string;
@AutoMap()
secretKey: string;
token: string;
exchangeName: string;
}

export class EnrollExchangeApiKeysData {
@AutoMap()
apiKey: string;
@AutoMap()
secretKey: string;
}

export class RetrieveExchangeApiKeysResponse {
apiKey: string;
}
Loading
Loading