mirror of
https://github.com/luxfi/accel.git
synced 2026-10-30 17:03:45 +00:00
164 lines
3.7 KiB
Go
164 lines
3.7 KiB
Go
package dex
|
|
|
|
import (
|
|
"sort"
|
|
)
|
|
|
|
// CPU fallback implementations
|
|
|
|
func matchOrdersCPU(bids, asks []Order, incoming []Order) ([]Trade, []Order, error) {
|
|
trades := make([]Trade, 0)
|
|
updated := make([]Order, 0)
|
|
|
|
// Sort bids descending by price, asks ascending
|
|
sortedBids := make([]Order, len(bids))
|
|
copy(sortedBids, bids)
|
|
sort.Slice(sortedBids, func(i, j int) bool {
|
|
return sortedBids[i].Price > sortedBids[j].Price
|
|
})
|
|
|
|
sortedAsks := make([]Order, len(asks))
|
|
copy(sortedAsks, asks)
|
|
sort.Slice(sortedAsks, func(i, j int) bool {
|
|
return sortedAsks[i].Price < sortedAsks[j].Price
|
|
})
|
|
|
|
for _, order := range incoming {
|
|
remaining := order.Remaining
|
|
if remaining == 0 {
|
|
remaining = order.Quantity
|
|
}
|
|
|
|
if order.Side == Bid {
|
|
// Match against asks
|
|
for i := range sortedAsks {
|
|
if remaining == 0 {
|
|
break
|
|
}
|
|
ask := &sortedAsks[i]
|
|
if ask.Remaining == 0 || ask.Price > order.Price {
|
|
continue
|
|
}
|
|
|
|
matchQty := min(remaining, ask.Remaining)
|
|
trade := Trade{
|
|
MakerID: ask.ID,
|
|
TakerID: order.ID,
|
|
MakerUserID: ask.UserID,
|
|
TakerUserID: order.UserID,
|
|
Price: ask.Price,
|
|
Quantity: matchQty,
|
|
TakerSide: Bid,
|
|
}
|
|
trades = append(trades, trade)
|
|
|
|
remaining -= matchQty
|
|
ask.Remaining -= matchQty
|
|
}
|
|
} else {
|
|
// Match against bids
|
|
for i := range sortedBids {
|
|
if remaining == 0 {
|
|
break
|
|
}
|
|
bid := &sortedBids[i]
|
|
if bid.Remaining == 0 || bid.Price < order.Price {
|
|
continue
|
|
}
|
|
|
|
matchQty := min(remaining, bid.Remaining)
|
|
trade := Trade{
|
|
MakerID: bid.ID,
|
|
TakerID: order.ID,
|
|
MakerUserID: bid.UserID,
|
|
TakerUserID: order.UserID,
|
|
Price: bid.Price,
|
|
Quantity: matchQty,
|
|
TakerSide: Ask,
|
|
}
|
|
trades = append(trades, trade)
|
|
|
|
remaining -= matchQty
|
|
bid.Remaining -= matchQty
|
|
}
|
|
}
|
|
|
|
if remaining > 0 && order.Type == Limit {
|
|
order.Remaining = remaining
|
|
updated = append(updated, order)
|
|
}
|
|
}
|
|
|
|
return trades, updated, nil
|
|
}
|
|
|
|
func batchMatchCPU(orderBooks [][]Order, incomingBatches [][]Order) ([][]Trade, error) {
|
|
results := make([][]Trade, len(orderBooks))
|
|
for i := range orderBooks {
|
|
bids := make([]Order, 0)
|
|
asks := make([]Order, 0)
|
|
for _, o := range orderBooks[i] {
|
|
if o.Side == Bid {
|
|
bids = append(bids, o)
|
|
} else {
|
|
asks = append(asks, o)
|
|
}
|
|
}
|
|
trades, _, err := matchOrdersCPU(bids, asks, incomingBatches[i])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
results[i] = trades
|
|
}
|
|
return results, nil
|
|
}
|
|
|
|
func aggregateBookCPU(orders []Order, numLevels int) (bids, asks []Level, err error) {
|
|
bidMap := make(map[uint64]*Level)
|
|
askMap := make(map[uint64]*Level)
|
|
|
|
for _, o := range orders {
|
|
if o.Side == Bid {
|
|
if l, ok := bidMap[o.Price]; ok {
|
|
l.Quantity += o.Remaining
|
|
l.OrderCount++
|
|
} else {
|
|
bidMap[o.Price] = &Level{Price: o.Price, Quantity: o.Remaining, OrderCount: 1}
|
|
}
|
|
} else {
|
|
if l, ok := askMap[o.Price]; ok {
|
|
l.Quantity += o.Remaining
|
|
l.OrderCount++
|
|
} else {
|
|
askMap[o.Price] = &Level{Price: o.Price, Quantity: o.Remaining, OrderCount: 1}
|
|
}
|
|
}
|
|
}
|
|
|
|
for _, l := range bidMap {
|
|
bids = append(bids, *l)
|
|
}
|
|
for _, l := range askMap {
|
|
asks = append(asks, *l)
|
|
}
|
|
|
|
// Sort and limit
|
|
sort.Slice(bids, func(i, j int) bool { return bids[i].Price > bids[j].Price })
|
|
sort.Slice(asks, func(i, j int) bool { return asks[i].Price < asks[j].Price })
|
|
|
|
if len(bids) > numLevels {
|
|
bids = bids[:numLevels]
|
|
}
|
|
if len(asks) > numLevels {
|
|
asks = asks[:numLevels]
|
|
}
|
|
|
|
return bids, asks, nil
|
|
}
|
|
|
|
func swapCPU(makerAsset, takerAsset []byte, makerAmount, takerAmount uint64, makerSig, takerSig []byte) ([]byte, error) {
|
|
// CPU atomic swap verification and execution
|
|
// In practice, this validates signatures and creates swap proof
|
|
return nil, nil
|
|
}
|