Skip to content

Commit

Permalink
feat: irec certificates handling
Browse files Browse the repository at this point in the history
  • Loading branch information
ioncreature authored May 30, 2021
2 parents 9ee02af + 0ed2f37 commit fc0cb5e
Show file tree
Hide file tree
Showing 63 changed files with 1,392 additions and 86 deletions.
4 changes: 2 additions & 2 deletions packages/apps/origin-backend-irec-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@
"@energyweb/exchange-io-erc1888": "1.1.1",
"@energyweb/exchange-irec": "1.0.2",
"@energyweb/issuer": "3.2.0",
"@energyweb/issuer-api": "0.2.0",
"@energyweb/issuer-irec-api-wrapper": "0.3.0",
"@energyweb/issuer-irec-api": "0.1.0",
"@energyweb/issuer-irec-api-wrapper": "0.4.0",
"@energyweb/origin-backend": "10.0.1",
"@energyweb/origin-backend-core": "8.0.1",
"@energyweb/origin-backend-utils": "1.5.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { CommandBus, EventBus, QueryBus } from '@nestjs/cqrs';
import {
IrecCertificateService,
CertificationRequestStatusChangedEvent,
GetAllCertificationRequestsQuery,
ApproveCertificationRequestCommand
} from '@energyweb/issuer-irec-api';
import { IssuanceStatus } from '@energyweb/issuer-irec-api-wrapper';

@Injectable()
export class CheckCertificateStateTask {
constructor(
private readonly commandBus: CommandBus,
private readonly irecCertificateService: IrecCertificateService,
private readonly eventBus: EventBus,
private readonly queryBus: QueryBus
) {}

@Cron(CronExpression.EVERY_MINUTE)
async handleCron() {
if (!this.irecCertificateService.isIrecIntegrationEnabled()) {
return;
}

const certificateRequests = await this.queryBus.execute(
new GetAllCertificationRequestsQuery({ approved: false })
);

for (const certificateRequest of certificateRequests) {
const irecIssue = await this.irecCertificateService.getIssue(
certificateRequest.userId,
certificateRequest.irecIssueId
);

if (irecIssue.status === IssuanceStatus.Approved) {
await this.commandBus.execute(
new ApproveCertificationRequestCommand(certificateRequest.id)
);
this.eventBus.publish(
new CertificationRequestStatusChangedEvent(
certificateRequest,
IssuanceStatus.Approved
)
);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export class CheckDeviceStateTask {
private readonly eventBus: EventBus
) {}

@Cron(CronExpression.EVERY_5_MINUTES)
@Cron(CronExpression.EVERY_MINUTE)
async handleCron() {
if (!this.irecDeviceService.isIrecIntegrationEnabled()) {
return;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { IExchangeConfigurationService } from '@energyweb/exchange';
import { ConfigurationService } from '@energyweb/origin-backend';
import { BlockchainPropertiesService } from '@energyweb/issuer-api';
import { BlockchainPropertiesService } from '@energyweb/issuer-irec-api';
import { IDeviceType } from '@energyweb/origin-backend-core';
import { Injectable } from '@nestjs/common';
import { ModuleRef } from '@nestjs/core';
Expand Down
2 changes: 1 addition & 1 deletion packages/apps/origin-backend-irec-app/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export async function startAPI(logger?: LoggerService) {
'@energyweb/origin-backend-irec-app': parsed.version,
'@energyweb/exchange': parsed.dependencies['@energyweb/exchange'],
'@energyweb/origin-backend': parsed.dependencies['@energyweb/origin-backend'],
'@energyweb/issuer-api': parsed.dependencies['@energyweb/issuer-api'],
'@energyweb/issuer-irec-api': parsed.dependencies['@energyweb/issuer-irec-api'],
'@energyweb/origin-organization-irec-api':
parsed.dependencies['@energyweb/origin-organization-irec-api']
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
CertificateRequestApprovedEvent,
GetCertificationRequestQuery
} from '@energyweb/issuer-api';
} from '@energyweb/issuer-irec-api';
import { UserService } from '@energyweb/origin-backend';
import { Role } from '@energyweb/origin-backend-core';
import { DeviceService } from '@energyweb/origin-device-registry-irec-local-api';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AppModule as ExchangeModule, entities as ExchangeEntities } from '@energyweb/exchange';
import { ExchangeErc1888Module } from '@energyweb/exchange-io-erc1888';
import { AppModule as ExchangeIRECModule } from '@energyweb/exchange-irec';
import { AppModule as IssuerModule, entities as IssuerEntities } from '@energyweb/issuer-api';
import { AppModule as IssuerModule, entities as IssuerEntities } from '@energyweb/issuer-irec-api';
import {
AppModule as OriginBackendModule,
entities as OriginBackendEntities,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Test } from '@nestjs/testing';
import request from 'supertest';
import ganache from 'ganache-core';

import { BlockchainPropertiesService } from '@energyweb/issuer-api';
import { BlockchainPropertiesService } from '@energyweb/issuer-irec-api';
import { Contracts } from '@energyweb/issuer';
import { getProviderWithFallback } from '@energyweb/utils-general';
import { OriginAppModule } from '../src/origin-app.module';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"precommit": "lint-staged"
},
"dependencies": {
"@energyweb/issuer-irec-api-wrapper": "0.3.0",
"@energyweb/issuer-irec-api-wrapper": "0.4.0",
"@energyweb/origin-backend-core": "8.0.1",
"@energyweb/origin-backend-utils": "1.5.1",
"@energyweb/origin-device-registry-api": "0.1.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"precommit": "lint-staged"
},
"dependencies": {
"@energyweb/issuer-irec-api-wrapper": "0.3.0",
"@energyweb/issuer-irec-api-wrapper": "0.4.0",
"@energyweb/origin-backend-core": "8.0.1",
"@energyweb/origin-backend-utils": "1.5.1",
"@nestjs/common": "7.6.17",
Expand Down
6 changes: 4 additions & 2 deletions packages/origin-backend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ import { Organization, OrganizationModule } from './pods/organization';
import { User, UserModule } from './pods/user';

export { AppModule } from './app.module';

export * from './pods/configuration';
export * from './pods/email-confirmation/events';
export * from './pods/invitation/events';
export * from './pods/user';
export * from './pods/file';
export * from './pods/organization';
export * from './pods/configuration';
export * from './pods/user';

export const entities = [Configuration, Organization, User, Invitation, EmailConfirmation, File];

Expand Down
2 changes: 1 addition & 1 deletion packages/traceability/issuer-api-client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
<br>
EnergyWeb Origin
<br>
<h2 align="center">Issuer API CLient</h2>
<h2 align="center">Issuer API Client</h2>
<br>
</h1>
2 changes: 1 addition & 1 deletion packages/traceability/issuer-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:mocha": "mocha -r ts-node/register test/*.e2e-spec.ts --timeout 60000 --exit",
"test:e2e": "yarn typeorm:run && concurrently --success first --kill-others -n eth,test \"yarn start-ganache\" \"wait-on tcp:8581 && yarn test:mocha\"",
"test:e2e": "yarn typeorm:run && npx concurrently --success first --kill-others -n eth,test \"yarn start-ganache\" \"npx wait-on tcp:8581 && yarn test:mocha\"",
"start-ganache": "ganache-cli -m 'chalk park staff buzz chair purchase wise oak receive avoid avoid home' -l 8000000 -e 1000000 -a 20 -p 8581 -q",
"clean": "shx rm -rf dist dist-shakeable",
"typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js --config ormconfig-dev.ts",
Expand Down
2 changes: 2 additions & 0 deletions packages/traceability/issuer-api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { CertificationRequest, CertificationRequestModule } from './pods/certifi
export * from './pods/certificate';
export * from './pods/certification-request';
export * from './pods/blockchain';
export * from './utils';
export * from './types';

export { BlockchainPropertiesService } from './pods/blockchain/blockchain-properties.service';
export { AppModule, providers } from './app.module';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,23 @@ import {
Role,
ValidateDeviceOwnershipQuery
} from '@energyweb/origin-backend-core';

import { ApiBearerAuth, ApiBody, ApiResponse, ApiTags } from '@nestjs/swagger';
import { CreateCertificationRequestCommand } from './commands/create-certification-request.command';
import { CreateCertificationRequestDTO } from './commands/create-certification-request.dto';
import { GetAllCertificationRequestsQuery } from './queries/get-all-certification-requests.query';
import { GetCertificationRequestQuery } from './queries/get-certification-request.query';
import { ApproveCertificationRequestCommand } from './commands/approve-certification-request.command';
import { RevokeCertificationRequestCommand } from './commands/revoke-certification-request.command';
import { GetCertificationRequestByCertificateQuery } from './queries/get-certification-request-by-certificate.query';

import {
CreateCertificationRequestCommand,
ApproveCertificationRequestCommand,
RevokeCertificationRequestCommand,
ValidateCertificationRequestCommand,
CertificateBoundToCertificationRequestCommand,
CreateCertificationRequestDTO
} from './commands';
import {
GetAllCertificationRequestsQuery,
GetCertificationRequestQuery,
GetCertificationRequestByCertificateQuery
} from './queries';
import { CertificationRequestDTO } from './certification-request.dto';
import { SuccessResponseDTO } from '../../utils/success-response.dto';
import { ValidateCertificationRequestCommand } from './commands/validate-certification-request.command';
import { CertificateBoundToCertificationRequestCommand } from './commands/certificate-bound-to-certification-request.command';
import { SuccessResponseDTO } from '../../utils';

@ApiTags('certification-requests')
@ApiBearerAuth('access-token')
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from './certificate-request-approved-event';
export * from './certificate-request-approved.event';
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,37 @@ import { concatMap } from 'rxjs/operators';
import { Repository } from 'typeorm';
import { isAddress, getAddress } from 'ethers/lib/utils';

import { BlockchainPropertiesService } from '../../blockchain/blockchain-properties.service';
import { BlockchainPropertiesService } from '../../blockchain';
import { CertificationRequestStatus } from '../certification-request-status.enum';
import { CertificationRequestDTO } from '../certification-request.dto';
import { CertificationRequest } from '../certification-request.entity';
import { CreateCertificationRequestCommand } from '../commands/create-certification-request.command';
import { CreateCertificationRequestCommand } from '../commands';

@CommandHandler(CreateCertificationRequestCommand)
export class CreateCertificationRequestHandler
implements ICommandHandler<CreateCertificationRequestCommand> {
private readonly logger = new Logger(CreateCertificationRequestHandler.name);
implements ICommandHandler<CreateCertificationRequestCommand>
{
readonly logger = new Logger(CreateCertificationRequestHandler.name);

private readonly requestQueue = new Subject<number>();

constructor(
@InjectRepository(CertificationRequest)
private readonly repository: Repository<CertificationRequest>,
private readonly blockchainPropertiesService: BlockchainPropertiesService
readonly repository: Repository<CertificationRequest>,
readonly blockchainPropertiesService: BlockchainPropertiesService
) {
this.requestQueue.pipe(concatMap((id) => this.process(id))).subscribe();
}

async execute({
async execute(params: CreateCertificationRequestCommand): Promise<CertificationRequestDTO> {
const stored = await this.createCertificationRequest(params);

this.addToQueue(stored.id);

return stored;
}

async createCertificationRequest({
to,
energy,
fromTime,
Expand Down Expand Up @@ -56,14 +65,22 @@ export class CreateCertificationRequestHandler
owner: getAddress(to) // it returns checksum address
});

const stored = await this.repository.save(certificationRequest);
return this.repository.save(certificationRequest);
}

this.requestQueue.next(stored.id);
addToQueue(id: number) {
this.requestQueue.next(id);
}

return stored;
async process(requestId: number) {
const request: CertificationRequest = await this.getCertificationRequest(requestId);

if (request) {
await this.mintCertificationRequest(request);
}
}

private async process(requestId: number) {
async getCertificationRequest(requestId: number): Promise<CertificationRequest> {
this.logger.debug(`Processing certification request ${requestId}`);

const request = await this.repository.findOne(requestId);
Expand All @@ -82,10 +99,12 @@ export class CreateCertificationRequestHandler
return;
}

const blockchainProperties = await this.blockchainPropertiesService.get();

const { fromTime, toTime, deviceId, owner } = request;
return request;
}

async mintCertificationRequest(request: CertificationRequest): Promise<void> {
const { id, fromTime, toTime, deviceId, owner } = request;
const blockchainProperties = await this.blockchainPropertiesService.get();
try {
const { created, id } = await CertificationRequestFacade.create(
fromTime,
Expand All @@ -94,9 +113,7 @@ export class CreateCertificationRequestHandler
blockchainProperties.wrap(),
owner
);
this.logger.debug(
`Certification request ${requestId} has been deployed with id ${id} `
);
this.logger.debug(`Certification request ${id} has been deployed with id ${id} `);

await this.repository.update(request.id, {
created,
Expand All @@ -105,7 +122,7 @@ export class CreateCertificationRequestHandler
});
} catch (e) {
this.logger.error(
`Certification request ${requestId} deployment has failed with the error: ${e.message}`
`Certification request ${id} deployment has failed with the error: ${e.message}`
);

await this.repository.update(request.id, {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import { IQueryHandler, QueryHandler } from '@nestjs/cqrs';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { GetAllCertificationRequestsQuery } from '../queries/get-all-certification-requests.query';

import { GetAllCertificationRequestsQuery } from '../queries';
import { CertificationRequest } from '../certification-request.entity';
import { CertificationRequestDTO } from '../certification-request.dto';

@QueryHandler(GetAllCertificationRequestsQuery)
export class GetAllCertificationRequestsHandler
implements IQueryHandler<GetAllCertificationRequestsQuery> {
implements IQueryHandler<GetAllCertificationRequestsQuery>
{
constructor(
@InjectRepository(CertificationRequest)
private readonly repository: Repository<CertificationRequest>
readonly repository: Repository<CertificationRequest>
) {}

async execute(): Promise<CertificationRequest[]> {
return this.repository.find();
async execute({ query }: GetAllCertificationRequestsQuery): Promise<CertificationRequestDTO[]> {
return this.repository.find(query);
}
}
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
import { IQueryHandler, QueryHandler } from '@nestjs/cqrs';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Certificate } from '../../certificate/certificate.entity';
import { Certificate } from '../../certificate';
import { CertificationRequest } from '../certification-request.entity';
import { GetCertificationRequestByCertificateQuery } from '../queries/get-certification-request-by-certificate.query';
import { GetCertificationRequestByCertificateQuery } from '../queries';
import { CertificationRequestDTO } from '../certification-request.dto';

@QueryHandler(GetCertificationRequestByCertificateQuery)
export class GetCertificationRequestByCertificateHandler
implements IQueryHandler<GetCertificationRequestByCertificateQuery> {
implements IQueryHandler<GetCertificationRequestByCertificateQuery>
{
constructor(
@InjectRepository(CertificationRequest)
private readonly repository: Repository<CertificationRequest>,
readonly repository: Repository<CertificationRequest>,
@InjectRepository(Certificate)
private readonly certificateRepository: Repository<Certificate>
readonly certificateRepository: Repository<Certificate>
) {}

async execute({
certificateId
}: GetCertificationRequestByCertificateQuery): Promise<CertificationRequest> {
}: GetCertificationRequestByCertificateQuery): Promise<CertificationRequestDTO> {
const certificate = await this.certificateRepository.findOne(certificateId);
const certificationRequest = await this.repository.findOne({
return await this.repository.findOne({
where: {
issuedCertificateTokenId: certificate.tokenId
}
});

return certificationRequest;
}
}
Loading

0 comments on commit fc0cb5e

Please sign in to comment.