Skip to content

Commit

Permalink
Implement remaining MVP features #10, #11, #12, #13, #15
Browse files Browse the repository at this point in the history
scheduling contract verification #10

performing async verification #11

add init parameters decoding and get verified contract endpoint #12

smart contract all source code endpoint #13

supported compilers endpoint #15

secure verification notification endpoint and fix queue settings
  • Loading branch information
lukeromanowicz committed Jan 14, 2024
1 parent 2332a7a commit 09fadfa
Show file tree
Hide file tree
Showing 53 changed files with 1,542 additions and 134 deletions.
8 changes: 8 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,11 @@ DB_NAME=scv
DB_USERNAME=postgres
DB_PASSWORD=postgres
DB_SYNCHRONIZE=true
MQ_HOST=localhost
MQ_PORT=5672
MQ_USERNAME=rabbitmq
MQ_PASSWORD=rabbitmq
AE_MDW_URL=https://mainnet.aeternity.io/mdw
GATEWAY_API_URL=http://scv-gateway:3000
WORKER_PUB_KEY="-----BEGIN PUBLIC KEY-----\nMIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgFlekfRTWDtwLu0BlUh4VfXq3tvK\nvb6mPncjQ9I/tGkRRo3dojvxWN7B+kQxt56nGsIffKwU6N6fTCvEMVIHR0ykuRrv\nRusE5axYiQI2rpipv9sjDeD5BaHOtdF7ihjxqKQTH7oB5+rxu81zgU/TMcSqPnNg\nUcvClEnXJz7hmxZ9AgMBAAE=\n-----END PUBLIC KEY-----"
WORKER_PRIV_KEY="-----BEGIN RSA PRIVATE KEY-----\nMIICWgIBAAKBgFlekfRTWDtwLu0BlUh4VfXq3tvKvb6mPncjQ9I/tGkRRo3dojvx\nWN7B+kQxt56nGsIffKwU6N6fTCvEMVIHR0ykuRrvRusE5axYiQI2rpipv9sjDeD5\nBaHOtdF7ihjxqKQTH7oB5+rxu81zgU/TMcSqPnNgUcvClEnXJz7hmxZ9AgMBAAEC\ngYAVNc6qEAXGxY89jLyjYHv2S3Hs9CcoUkhM+j+kbJ4iuYjnLozMcTFIXP1KpgoQ\nS1ScceCi7qt9+oyXbo7OCxAupqBXK0y6FD0YxDCeZauZx5WsYDG1gxzZWn241tr9\nDdPQHbEP6xFThnsfWfKM3R/T40eIaVnROQwJmnJ0pU0MeQJBAJ6xooHV0CFzLW9e\nVdL3LfYoRhROYl7PxlcmWMj2l33X0tcWCkZLcOp7ta9Ko2dKJB+1TYunzHbMW8Lz\n+FB5Vo8CQQCQKv3qCVvq7t/uPwG9cyehALBQx3+TjhoFc04XvBgzlEhngKgxTdOq\ngslfQclLqsddnN7Yi2hJ8yPbtneVz6gzAkA3SojmV8rGfMzNyr54XKrk4y9Xj9/y\nTM48Ox4gFtq9e974FbPKvio/aI7q3kSEjm57pb249OPmWFl4WWyhDUW9AkArC6sk\n5gZ77zcNe+KZHnkGqZ37gJWnCRbb6cG3dIIFZJD51oBhuEsq7kISHyJrZWKBoQUo\nwvcwnVhnkePC523hAkBhTmPwXZXBHEu7jnO+j8CSlaQE3kd6QdT6nbp93HMzEbpz\nocxXGMBY01lPlI0UoOVlZnUmp6tfhvQjHNxh0Q8f\n-----END RSA PRIVATE KEY-----"
22 changes: 0 additions & 22 deletions apps/scv-gateway/src/app.controller.spec.ts

This file was deleted.

12 changes: 0 additions & 12 deletions apps/scv-gateway/src/app.controller.ts

This file was deleted.

11 changes: 6 additions & 5 deletions apps/scv-gateway/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@ import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule } from '@nestjs/config';
import { DataSource, DataSourceOptions } from 'typeorm';
import { TypeOrmConfigService } from './database/typeorm-config.service';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ContractsModule } from './contracts/contracts.module';
import { StatusModule } from './status/status.module';
import { VerificationModule } from './verification/verification.module';
import databaseConfig from './config/database.config';
import appConfig from './config/app.config';
import mqConfig from './config/mq.config';
import { ScheduleModule } from '@nestjs/schedule';

@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
load: [databaseConfig, appConfig],
load: [databaseConfig, mqConfig, appConfig],
envFilePath: ['.env'],
}),
TypeOrmModule.forRootAsync({
Expand All @@ -23,10 +24,10 @@ import appConfig from './config/app.config';
return new DataSource(options).initialize();
},
}),
ScheduleModule.forRoot(),
ContractsModule,
StatusModule,
VerificationModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
8 changes: 0 additions & 8 deletions apps/scv-gateway/src/app.service.ts

This file was deleted.

8 changes: 8 additions & 0 deletions apps/scv-gateway/src/config/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@ import { registerAs } from '@nestjs/config';
import { AppConfig } from './config.type';

export default registerAs<AppConfig>('app', () => {
if (!process.env.WORKER_PUB_KEY) {
throw new Error(
'WORKER_PUB_KEY env variable must be a valid PEM public key!',
);
}

return {
nodeEnv: process.env.NODE_ENV || 'development',
aeMdwUrl: process.env.AE_MDW_URL || 'https://mainnet.aeternity.io/mdw',
workerPubKey: process.env.WORKER_PUB_KEY,
};
});
10 changes: 10 additions & 0 deletions apps/scv-gateway/src/config/config.type.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export type AppConfig = {
nodeEnv: string;
aeMdwUrl: string;
workerPubKey: string;
};

export type DatabaseConfig = {
Expand All @@ -11,7 +13,15 @@ export type DatabaseConfig = {
synchronize?: boolean;
};

export type MqConfig = {
host?: string;
port?: number;
username?: string;
password?: string;
};

export type AllConfigType = {
app: AppConfig;
database: DatabaseConfig;
mq: MqConfig;
};
11 changes: 11 additions & 0 deletions apps/scv-gateway/src/config/mq.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { registerAs } from '@nestjs/config';
import { MqConfig } from './config.type';

export default registerAs<MqConfig>('mq', () => {
return {
host: process.env.MQ_HOST,
port: process.env.MQ_PORT ? parseInt(process.env.MQ_PORT, 10) : 5672,
password: process.env.MQ_PASSWORD,
username: process.env.MQ_USERNAME,
};
});
78 changes: 76 additions & 2 deletions apps/scv-gateway/src/contracts/contracts.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,37 @@ import {
HttpStatus,
Param,
Res,
Query,
} from '@nestjs/common';
import { Response } from 'express';
import { FilesInterceptor } from '@nestjs/platform-express';
import { ContractsService } from './contracts.service';
import { ContractSubmissionDto } from './dto/contract-submission.dto';
import { ApiBody, ApiConsumes, ApiParam, ApiResponse } from '@nestjs/swagger';
import {
ApiBody,
ApiConsumes,
ApiParam,
ApiProperty,
ApiQuery,
ApiResponse,
} from '@nestjs/swagger';
import { ContractFilesValidator } from './validators/contract-files.validator';
import { ContractIdDto } from './dto/contract-id.dto';
import { ContractSubmissionStatusDto } from './dto/contract-submission-status.dto';
import { VerificationStatus } from './entities/contract-submission.entity';
import { ContractSubmissionStatusRequestDto } from './dto/contract-submission-status-request.dto';
import { VerificationStatus } from '../verification/verification.types';
import { VerifiedContractDto } from './dto/verified-contract.dto';
import { ContractSourceFileDto } from './dto/contract-source-file.dto';

class ContractSourceFiles {
@ApiProperty({ type: [ContractSourceFileDto] })
source: ContractSourceFileDto[];
}

class Contracts {
@ApiProperty({ type: [VerifiedContractDto] })
contracts: VerifiedContractDto[];
}

@Controller('contracts')
export class ContractsController {
Expand Down Expand Up @@ -86,6 +106,60 @@ export class ContractsController {
);
}

@Get(':contractId')
@ApiResponse({
status: HttpStatus.OK,
description: 'Contract is verified',
type: VerifiedContractDto,
})
@ApiResponse({
status: HttpStatus.NOT_FOUND,
description: 'Contract is not found or not verified',
})
async getVerifiedContract(@Param('contractId') contractId: string) {
return this.contractsService.getVerifiedContract(contractId);
}

@Get('/')
@ApiResponse({
status: HttpStatus.OK,
description: 'Some of the requested contracts are verified',
type: VerifiedContractDto,
})
@ApiQuery({
name: 'ids',
type: [String],
})
@ApiResponse({
status: HttpStatus.NOT_FOUND,
description: 'None of the requested contracts are verified',
})
async getVerifiedContracts(
@Query('ids') contractIds: string[],
): Promise<Contracts> {
return {
contracts: await this.contractsService.getVerifiedContracts(contractIds),
};
}

@Get('/:contractId/source')
@ApiResponse({
status: HttpStatus.OK,
description: 'Contract source code is available',
type: ContractSourceFiles,
})
@ApiResponse({
status: HttpStatus.NOT_FOUND,
description: 'Contract is not found or not verified',
})
async getVerifiedContractSource(
@Param('contractId') contractId: string,
): Promise<ContractSourceFiles> {
return {
source: await this.contractsService.getVerifiedContractSource(contractId),
};
}

@Get(':id/check/:submissionId')
@ApiParam({ name: 'id', type: String })
@ApiParam({ name: 'submissionId', type: String })
Expand Down
5 changes: 5 additions & 0 deletions apps/scv-gateway/src/contracts/contracts.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { ContractSubmission } from './entities/contract-submission.entity';
import { ContractSubmissionSourceFile } from './entities/contract-submission-source-file.entity';
import { ContractSourceFile } from './entities/contract-source-file.entity';
import { Contract } from './entities/contract.entity';
import { HttpModule } from '@nestjs/axios';
import { ConfigModule } from '@nestjs/config';

@Module({
imports: [
Expand All @@ -15,8 +17,11 @@ import { Contract } from './entities/contract.entity';
ContractSourceFile,
Contract,
]),
HttpModule,
ConfigModule,
],
controllers: [ContractsController],
providers: [ContractsService],
exports: [ContractsService],
})
export class ContractsModule {}
Loading

0 comments on commit 09fadfa

Please sign in to comment.