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

[마켓] 주문창 gRPC 통신 및 매수, 매도 주문 등록 #89

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from
14 changes: 0 additions & 14 deletions apps/transaction/src/dto/order.limit.response.dto.ts

This file was deleted.

33 changes: 27 additions & 6 deletions apps/transaction/src/transaction.controller.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,33 @@
import { Controller, Get } from '@nestjs/common';
import { Controller, Request, Post, UseGuards, Body } from '@nestjs/common';
import { TransactionService } from './transaction.service';
import { AuthenticatedGuard } from '@app/common/session/authenticated.guard';
import { OrderLimitRequestDto } from './dto/order.limit.request.dto';
import { TransactionGrcpService } from './transaction.grcp.service';
import { OrderRequestDto } from '@app/grpc/dto/order.request.dto';
import { firstValueFrom } from 'rxjs';

@Controller()
@Controller('api/orders')
export class TransactionController {
constructor(private readonly transactionService: TransactionService) {}
constructor(
private readonly transactionService: TransactionService,
private readonly transactionGrcpService: TransactionGrcpService,
) {}

@Get()
getHello(): string {
return this.transactionService.getHello();
@Post('/limit/buy')
@UseGuards(AuthenticatedGuard)
async buyLimitOrder(@Request() req, @Body() buyLimitRequest: OrderLimitRequestDto) {
const userId = req.user.userId;
const orderRequest = new OrderRequestDto(userId, buyLimitRequest);
const response = await firstValueFrom(this.transactionGrcpService.makeBuyOrder(orderRequest));
return await this.transactionService.registerBuyOrder(orderRequest, response);
}

@Post('/limit/sell')
@UseGuards(AuthenticatedGuard)
async sellLimitOrder(@Request() req, @Body() sellLimitRequest: OrderLimitRequestDto) {
const userId = req.user.userId;
const orderRequest = new OrderRequestDto(userId, sellLimitRequest);
const response = await firstValueFrom(this.transactionGrcpService.makeSellOrder(orderRequest));
return await this.transactionService.registerSellOrder(orderRequest, response);
}
}
28 changes: 28 additions & 0 deletions apps/transaction/src/transaction.grcp.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { OrderRequestDto } from '@app/grpc/dto/order.request.dto';
import { OrderResponseDto } from '@app/grpc/dto/order.response.dto';
import { Inject, Injectable, OnModuleInit } from '@nestjs/common';
import { ClientGrpc } from '@nestjs/microservices';
import { Observable } from 'rxjs';

interface OrderService {
makeBuyOrder(buyOrderRequest: OrderRequestDto): Observable<OrderResponseDto>;
makeSellOrder(buyOrderRequest: OrderRequestDto): Observable<OrderResponseDto>;
}

@Injectable()
export class TransactionGrcpService implements OnModuleInit {
private orderService: OrderService;
constructor(@Inject('ORDER_PACKAGE') private readonly client: ClientGrpc) {}

onModuleInit() {
this.orderService = this.client.getService<OrderService>('OrderService');
}

makeBuyOrder(orderRequest: OrderRequestDto): Observable<OrderResponseDto> {
return this.orderService.makeBuyOrder(orderRequest);
}

makeSellOrder(orderRequest: OrderRequestDto): Observable<OrderResponseDto> {
return this.orderService.makeSellOrder(orderRequest);
}
}
24 changes: 22 additions & 2 deletions apps/transaction/src/transaction.module.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,30 @@
import { PassportModule } from '@nestjs/passport';
import { Module } from '@nestjs/common';
import { TransactionController } from './transaction.controller';
import { TransactionService } from './transaction.service';
import { TransactionRepository } from './transaction.repository';
import { SessionSerializer } from '@app/common/session/session.serializer';
import { PrismaModule } from '@app/prisma';
import { ClientsModule, Transport } from '@nestjs/microservices';
import { TransactionGrcpService } from './transaction.grcp.service';

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 여기서는 고쳐졌군여 ㅎㅎ 앞에서 리뷰를 달았는데 머쓱하네요

@Module({
imports: [],
imports: [
PrismaModule,
PassportModule.register({ session: true }),
ClientsModule.register([
{
name: 'ORDER_PACKAGE',
transport: Transport.GRPC,
options: {
package: 'order',
protoPath: '@app/grpc/order.proto',
url: 'localhost:5001',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

localhost 보다는 실제로 필요한 데이터를 환경변수 형태로 넣어주세요!
ex) ${BALANCE_SERVICE_HOST}:${GRPC_PORT}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

환경변수는 docker build 시에 주입해주고 있나요? 환경변수를 어디에 정의해야 적절할지요?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이건 따로 더 얘기해보아요

},
},
]),
],
controllers: [TransactionController],
providers: [TransactionService],
providers: [TransactionService, TransactionRepository, SessionSerializer, TransactionGrcpService],
})
export class TransactionModule {}
34 changes: 34 additions & 0 deletions apps/transaction/src/transaction.repository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Injectable } from '@nestjs/common';
import { PrismaService } from '@app/prisma';
import { OrderRequestDto } from '@app/grpc/dto/order.request.dto';

@Injectable()
export class TransactionRepository {
constructor(private readonly prisma: PrismaService) {}

async createBuyOrder(orderRequest: OrderRequestDto, historyId: string) {
return await this.prisma.buyOrder.create({
data: {
historyId: historyId,
userId: orderRequest.userId,
coinCode: orderRequest.coinCode,
price: String(orderRequest.price),
originalQuote: String(orderRequest.amount),
remainingQuote: String(orderRequest.amount),
},
});
}

async createSellOrder(orderRequest: OrderRequestDto, historyId: string) {
return await this.prisma.sellOrder.create({
data: {
historyId: historyId,
userId: orderRequest.userId,
coinCode: orderRequest.coinCode,
price: String(orderRequest.price),
originalQuote: String(orderRequest.amount),
remainingBase: String(orderRequest.amount),
},
});
}
}
Empty file.
26 changes: 23 additions & 3 deletions apps/transaction/src/transaction.service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
import { Injectable } from '@nestjs/common';
import { Injectable, BadRequestException, InternalServerErrorException } from '@nestjs/common';
import { TransactionRepository } from './transaction.repository';
import { OrderRequestDto } from '@app/grpc/dto/order.request.dto';
import { OrderResponseDto } from '@app/grpc/dto/order.response.dto';
import { GrpcOrderStatusCode } from '@app/common/enums/grpc-status.enum';

@Injectable()
export class TransactionService {
getHello(): string {
return 'Hello World!';
constructor(private transactionRepository: TransactionRepository) {}

async registerBuyOrder(orderRequest: OrderRequestDto, orderResponse: OrderResponseDto) {
if (orderResponse.status === GrpcOrderStatusCode.NO_BALANCE) {
throw new BadRequestException('Not Enough Balance');
} else if (orderResponse.status === GrpcOrderStatusCode.TRANSACTION_ERROR) {
throw new InternalServerErrorException('Internal Server Transaction Error');
}
await this.transactionRepository.createBuyOrder(orderRequest, orderResponse.historyId);
}

async registerSellOrder(orderRequest: OrderRequestDto, orderResponse: OrderResponseDto) {
if (orderResponse.status === GrpcOrderStatusCode.NO_BALANCE) {
throw new BadRequestException('Not Enough Balance');
} else if (orderResponse.status === GrpcOrderStatusCode.TRANSACTION_ERROR) {
throw new InternalServerErrorException('Internal Server Transaction Error');
}
await this.transactionRepository.createSellOrder(orderRequest, orderResponse.historyId);
}
}
9 changes: 9 additions & 0 deletions libs/grpc/src/dto/order.request.dto.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import { OrderLimitRequestDto } from 'apps/transaction/src/dto/order.limit.request.dto';

export class OrderRequestDto {
userId: number;
coinCode: string;
amount: number;
price: number;

constructor(userId: number, orderLimitRequest: OrderLimitRequestDto) {
this.userId = userId;
this.coinCode = orderLimitRequest.coinCode;
this.amount = orderLimitRequest.amount;
this.price = orderLimitRequest.price;
}
}