Skip to content
Open
Show file tree
Hide file tree
Changes from all 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