Skip to content

Commit

Permalink
[Relay] Implement endpoints that provide the information needed for p…
Browse files Browse the repository at this point in the history
…ayment
  • Loading branch information
MichaelKim20 committed Oct 30, 2023
1 parent 708d1b6 commit bbccb53
Show file tree
Hide file tree
Showing 11 changed files with 199 additions and 8 deletions.
2 changes: 1 addition & 1 deletion packages/contracts/src/utils/Amount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class Amount {
/**
* If entered an amount that is BOA, save it as BigNumber considering the decimal point
*/
public static make(boa: string | number, decimal: number): Amount {
public static make(boa: string | number, decimal: number = 18): Amount {
if (decimal < 0) throw new Error("Invalid decimal");
const amount = boa.toString();
if (amount === "") return new Amount(BigNumber.from("0"), decimal);
Expand Down
2 changes: 1 addition & 1 deletion packages/faker/src/common/Amount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export class Amount {
/**
* If entered an amount that is BOA, save it as BigNumber considering the decimal point
*/
public static make(boa: string | number, decimal: number): Amount {
public static make(boa: string | number, decimal: number = 18): Amount {
if (decimal < 0) throw new Error("Invalid decimal");
const amount = boa.toString();
if (amount === "") return new Amount(BigNumber.from("0"), decimal);
Expand Down
1 change: 1 addition & 0 deletions packages/relay/config/config.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ logging:
relay:
managerKeys:
- ${MANAGER_KEY1}
accessKey: ${ACCESS_KEY}

contracts:
tokenAddress : ${TOKEN_CONTRACT_ADDRESS}
Expand Down
1 change: 1 addition & 0 deletions packages/relay/config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ relay:
- ${MANAGER_KEY3}
- ${MANAGER_KEY4}
- ${MANAGER_KEY5}
accessKey: ${ACCESS_KEY}

contracts:
tokenAddress : ${TOKEN_CONTRACT_ADDRESS}
Expand Down
1 change: 1 addition & 0 deletions packages/relay/config/config_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ relay:
- ${MANAGER_KEY3}
- ${MANAGER_KEY4}
- ${MANAGER_KEY5}
accessKey: ${ACCESS_KEY}

contracts:
tokenAddress : ${TOKEN_CONTRACT_ADDRESS}
Expand Down
4 changes: 4 additions & 0 deletions packages/relay/env/.env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,12 @@ MANAGER_KEY4=0xce6f45e7a4ae40cac075b1a04b4b4ad31af6a524871fd52080166e959e5929c4
# 0xEaeB90D77f7756fBf177D6E0E1BB794639e6097f
MANAGER_KEY5=0xc645ef34a5428f3b00f2d4b8cc647380f0b939d4ae5ccb7a04ead77ab0a8628d

ACCESS_KEY=0x2c93e943c0d7f6f1a42f53e116c52c40fe5c1b428506dc04b290f2a77580a342

TOKEN_CONTRACT_ADDRESS=0xFDa3d1ff3C570c2f76c2157Ef7A8640A75794eD9
LEDGER_CONTRACT_ADDRESS=0x12c316e0358d914A211A3d477db912A503cFCc21
PHONE_LINKER_CONTRACT_ADDRESS=0xaE7018CaF086EB2Ca62eAA7b91B61dDA6b046F70
SHOP_CONTRACT_ADDRESS=0x979a62090BDCff36F2e140F6915fbAdA7510cb6a
CURRENCY_RATE_CONTRACT_ADDRESS=0xF396e42687C4ba2d1E2A65792B7165Ee8010Fdfe

REPORT_GAS=true
2 changes: 1 addition & 1 deletion packages/relay/src/common/Amount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export class Amount {
/**
* If entered an amount that is BOA, save it as BigNumber considering the decimal point
*/
public static make(boa: string | number, decimal: number): Amount {
public static make(boa: string | number, decimal: number = 18): Amount {
if (decimal < 0) throw new Error("Invalid decimal");
const amount = boa.toString();
if (amount === "") return new Amount(BigNumber.from("0"), decimal);
Expand Down
9 changes: 9 additions & 0 deletions packages/relay/src/common/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ export class RelayConfig implements IRelayConfig {
* 계정의 비밀키 또는 키파일
*/
public managerKeys: string[];
public accessKey: string;

/**
* Constructor
Expand All @@ -166,6 +167,7 @@ export class RelayConfig implements IRelayConfig {
const defaults = RelayConfig.defaultValue();

this.managerKeys = defaults.managerKeys;
this.accessKey = defaults.accessKey;
}

/**
Expand All @@ -180,6 +182,7 @@ export class RelayConfig implements IRelayConfig {
process.env.MANAGER_KEY4 || "",
process.env.MANAGER_KEY5 || "",
],
accessKey: process.env.ACCESS_SECRET || "",
};
}

Expand All @@ -189,6 +192,7 @@ export class RelayConfig implements IRelayConfig {
*/
public readFromObject(config: IRelayConfig) {
if (config.managerKeys !== undefined) this.managerKeys = config.managerKeys;
if (config.accessKey !== undefined) this.accessKey = config.accessKey;
}
}

Expand All @@ -200,6 +204,7 @@ export class ContractsConfig implements IContractsConfig {
public ledgerAddress: string;
public phoneLinkerAddress: string;
public shopAddress: string;
public currencyRateAddress: string;

/**
* Constructor
Expand All @@ -211,6 +216,7 @@ export class ContractsConfig implements IContractsConfig {
this.ledgerAddress = defaults.ledgerAddress;
this.phoneLinkerAddress = defaults.phoneLinkerAddress;
this.shopAddress = defaults.shopAddress;
this.currencyRateAddress = defaults.currencyRateAddress;
}

/**
Expand All @@ -222,6 +228,7 @@ export class ContractsConfig implements IContractsConfig {
ledgerAddress: process.env.LEDGER_CONTRACT_ADDRESS || "",
phoneLinkerAddress: process.env.PHONE_LINKER_CONTRACT_ADDRESS || "",
shopAddress: process.env.SHOP_CONTRACT_ADDRESS || "",
currencyRateAddress: process.env.CURRENCY_RATE_CONTRACT_ADDRESS || "",
};
}

Expand Down Expand Up @@ -325,13 +332,15 @@ export interface ILoggingConfig {

export interface IRelayConfig {
managerKeys: string[];
accessKey: string;
}

export interface IContractsConfig {
tokenAddress: string;
ledgerAddress: string;
phoneLinkerAddress: string;
shopAddress: string;
currencyRateAddress: string;
}
/**
* The interface of main config
Expand Down
116 changes: 113 additions & 3 deletions packages/relay/src/routers/DefaultRouter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Ledger, PhoneLinkCollection, ShopCollection, Token } from "../../typechain-types";
import { CurrencyRate, Ledger, PhoneLinkCollection, ShopCollection, Token } from "../../typechain-types";
import { Config } from "../common/Config";
import { logger } from "../common/Logger";
import { GasPriceManager } from "../contract/GasPriceManager";
Expand All @@ -7,11 +7,12 @@ import { ContractUtils } from "../utils/ContractUtils";
import { Validation } from "../validation";

import { NonceManager } from "@ethersproject/experimental";
import { Signer, Wallet } from "ethers";
import { BigNumber, Signer, Wallet } from "ethers";
import { body, query, validationResult } from "express-validator";
import * as hre from "hardhat";

import express from "express";
import { LoyaltyType } from "../types";

interface ISignerItem {
index: number;
Expand Down Expand Up @@ -58,6 +59,12 @@ export class DefaultRouter {
*/
private _phoneLinkerContract: PhoneLinkCollection | undefined;

/**
* 환률 컨트랙트
* @private
*/
private _currencyRateContract: CurrencyRate | undefined;

/**
*
* @param service WebService
Expand Down Expand Up @@ -173,6 +180,19 @@ export class DefaultRouter {
return this._phoneLinkerContract;
}

/**
* 환률 컨트랙트를 리턴한다.
* 컨트랙트의 객체가 생성되지 않았다면 컨트랙트 주소를 이용하여 컨트랙트 객체를 생성한 후 반환한다.
* @private
*/
private async getCurrencyRateContract(): Promise<CurrencyRate> {
if (this._currencyRateContract === undefined) {
const factory = await hre.ethers.getContractFactory("CurrencyRate");
this._currencyRateContract = factory.attach(this._config.contracts.currencyRateAddress);
}
return this._currencyRateContract;
}

/**
* Make the response data
* @param code The result code
Expand Down Expand Up @@ -348,6 +368,15 @@ export class DefaultRouter {
[query("account").exists().trim().isEthereumAddress()],
this.user_balance.bind(this)
);

this.app.post(
"/payment/info",
[body("accessKey").exists()],
[body("account").exists().trim().isEthereumAddress()],
[body("amount").exists().custom(Validation.isAmount)],
[body("currency").exists()],
this.payment_info.bind(this)
);
}

private async getHealthStatus(req: express.Request, res: express.Response) {
Expand Down Expand Up @@ -868,7 +897,7 @@ export class DefaultRouter {
const account: string = String(req.query.account).trim();
const loyaltyType = await (await this.getLedgerContract()).loyaltyTypeOf(account);
const balance =
loyaltyType === 0
loyaltyType === LoyaltyType.POINT
? await (await this.getLedgerContract()).pointBalanceOf(account)
: await (await this.getLedgerContract()).tokenBalanceOf(account);
return res
Expand All @@ -885,4 +914,85 @@ export class DefaultRouter {
);
}
}

/**
* 결제 / 결제정보를 제공한다
* GET /payment/info
* @private
*/
private async payment_info(req: express.Request, res: express.Response) {
logger.http(`GET /payment/info`);

const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(200).json(
this.makeResponseData(501, undefined, {
message: "Failed to check the validity of parameters.",
validation: errors.array(),
})
);
}

try {
const accessKey: string = String(req.body.accessKey).trim();
if (accessKey !== this._config.relay.accessKey) {
return res.json(
this.makeResponseData(400, undefined, {
message: "The access key entered is not valid.",
})
);
}

const account: string = String(req.body.account).trim();
const amount: BigNumber = BigNumber.from(req.body.amount);
const currency: string = String(req.body.currency).trim();
const loyaltyType = await (await this.getLedgerContract()).loyaltyTypeOf(account);

const feeRate = await (await this.getLedgerContract()).fee();
const rate = await (await this.getCurrencyRateContract()).get(currency.toLowerCase());
const multiple = await (await this.getCurrencyRateContract()).MULTIPLE();

let balance: BigNumber;
let purchaseAmount: BigNumber;
let feeAmount: BigNumber;
let totalAmount: BigNumber;

if (loyaltyType === LoyaltyType.POINT) {
balance = await (await this.getLedgerContract()).pointBalanceOf(account);
purchaseAmount = amount.mul(rate).div(multiple);
feeAmount = purchaseAmount.mul(feeRate).div(100);
totalAmount = purchaseAmount.add(feeAmount);
} else {
balance = await (await this.getLedgerContract()).tokenBalanceOf(account);
const symbol = await (await this.getTokenContract()).symbol();
const tokenRate = await (await this.getCurrencyRateContract()).get(symbol);
purchaseAmount = amount.mul(rate).div(tokenRate);
feeAmount = purchaseAmount.mul(feeRate).div(100);
totalAmount = purchaseAmount.add(feeAmount);
}

return res.status(200).json(
this.makeResponseData(200, {
account,
loyaltyType,
balance: balance.toString(),
purchaseAmount: purchaseAmount.toString(),
feeAmount: feeAmount.toString(),
totalAmount: totalAmount.toString(),
amount: amount.toString(),
currency,
feeRate: feeRate / 100,
})
);
} catch (error: any) {
let message = ContractUtils.cacheEVMError(error as any);
if (message === "") message = "Failed /payment/info";
logger.error(`GET /payment/info :`, message);
return res.status(200).json(
this.makeResponseData(500, undefined, {
message,
})
);
}
}
}
4 changes: 4 additions & 0 deletions packages/relay/src/types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum LoyaltyType {
POINT,
TOKEN,
}
Loading

0 comments on commit bbccb53

Please sign in to comment.