이 챕터에서는 order book을 구현한다. 구매, 판매 주문을 올릴 수 있는 order book을 만들 것이다. 토큰 한 쌍을 위한 order book은 등록을 먼저 해야 한다. 등록 후에 구매, 판매 주문을 등록할 수 있다. 판매 주문 예약을 구현하기 위해 sell_order_book.go 파일을 생성한다. 판매 주문서에는 토큰 액면가 데이터와 토큰 판매를 위해 제안하는 가격이 포함된 판매 주문이 포함되어 있다. 구매 주문서를 구현하여 buy_order_book.go 파일을 생성한다. 구매 주문서에는 토큰 액면가 데이터와 토큰 구매를 위해 제안한 가격이 포함된 구매 주문이 포함되어 있다. 구매 주문과 판매 주문은 서로 다른 블록체인 앱에서 실행된다. 매수 주문과 매도 주문이 일치하면 거래소가 실행된다.
// x/ibcdex/types/buy_order_book.go
package types
// NewBuyOrderBook 새로운 BuyOrderBook 생성
func NewBuyOrderBook(AmountDenom string, PriceDenom string) BuyOrderBook {
book := NewOrderBook()
return BuyOrderBook{
AmountDenom: AmountDenom,
PriceDenom: PriceDenom,
Book: &book,
}
}
// AppendOrder BuyOrderBook에 Order 추가
func (b *BuyOrderBook) AppendOrder(creator string, amount int32, price int32) (int32, error) {
return b.Book.appendOrder(creator, amount, price, Increasing)
}
// LiquidateFromSellOrder SellOrder에 맞는 가장 적합한 BuyOrder를 찾아 거래한다
// 가장 높은 가격에 팔 수 있는 BuyOrder를 찾아 거래한다
// 적합한 BuyOrder가 없으면 false를 반환한다
func (b *BuyOrderBook) LiquidateFromSellOrder(order Order) (
remainingSellOrder Order,
liquidatedBuyOrder Order,
gain int32,
match bool,
filled bool,
) {
remainingSellOrder = order
// No match if no order
orderCount := len(b.Book.Orders)
if orderCount == 0 {
return order, liquidatedBuyOrder, gain, false, false
}
// Check if match
highestBid := b.Book.Orders[orderCount-1]
if order.Price > highestBid.Price {
return order, liquidatedBuyOrder, gain, false, false
}
liquidatedBuyOrder = *highestBid
// Check if sell order can be entirely filled
if highestBid.Amount >= order.Amount {
remainingSellOrder.Amount = 0
liquidatedBuyOrder.Amount = order.Amount
gain = order.Amount * highestBid.Price
// Remove highest bid if it has been entirely liquidated
highestBid.Amount -= order.Amount
if highestBid.Amount == 0 {
b.Book.Orders = b.Book.Orders[:orderCount-1]
} else {
b.Book.Orders[orderCount-1] = highestBid
}
return remainingSellOrder, liquidatedBuyOrder, gain, true, true
}
// Not entirely filled
gain = highestBid.Amount * highestBid.Price
b.Book.Orders = b.Book.Orders[:orderCount-1]
remainingSellOrder.Amount -= highestBid.Amount
return remainingSellOrder, liquidatedBuyOrder, gain, true, false
}
// FillSellOrder SellOrder에 팔려는 수량을 채울 때까지 BuyOrderBook에서 BuyOrder를 찾아 거래한다.
func (b *BuyOrderBook) FillSellOrder(order Order) (
remainingSellOrder Order,
liquidated []Order,
gain int32,
filled bool,
) {
var liquidatedList []Order
totalGain := int32(0)
remainingSellOrder = order
// Liquidate as long as there is match
for {
var match bool
var liquidation Order
remainingSellOrder, liquidation, gain, match, filled = b.LiquidateFromSellOrder(
remainingSellOrder,
)
if !match {
break
}
// Update gains
totalGain += gain
// Update liquidated
liquidatedList = append(liquidatedList, liquidation)
if filled {
break
}
}
return remainingSellOrder, liquidatedList, totalGain, filled
}