}
func calcTradePairKey(fromAssetID, toAssetID *bc.AssetID) []byte {
- key := append(ordersPreFix, fromAssetID.Bytes()...)
+ key := append(tradePairPreFix, fromAssetID.Bytes()...)
return append(key, toAssetID.Bytes()...)
}
-type DexTradeOrderDB struct {
+type DexStore struct {
db dbm.DB
}
-func (d *DexTradeOrderDB) GetTradePairsWithStart(fromAssetID, toAssetID *bc.AssetID) ([]*common.TradePair, error) {
- startKey := []byte{}
- if fromAssetID != nil && toAssetID != nil {
- startKey = calcTradePairKey(fromAssetID, toAssetID)
+func NewDexStore(db dbm.DB) *DexStore {
+ return &DexStore{db: db}
+}
+
+func (d *DexStore) ListOrders(fromAssetID, toAssetID *bc.AssetID, rateAfter float64) ([]*common.Order, error) {
+ if fromAssetID == nil || toAssetID == nil {
+ return nil, errors.New("assetID is nil")
}
+ ordersPreFixLen := len(ordersPreFix)
+ orders := []*common.Order{}
- tradePairs := []*common.TradePair{}
- preFixLen := len(tradePairPreFix)
- itr := d.db.IteratorPrefixWithStart(tradePairPreFix, startKey, false)
+ orderPreFix := append(ordersPreFix, fromAssetID.Bytes()...)
+ orderPreFix = append(orderPreFix, toAssetID.Bytes()...)
+
+ var startKey []byte
+ if rateAfter > 0 {
+ buf := make([]byte, 8)
+ binary.BigEndian.PutUint64(buf, math.Float64bits(rateAfter))
+ copy(startKey, orderPreFix)
+ startKey = append(startKey, buf...)
+ }
+
+ itr := d.db.IteratorPrefixWithStart(orderPreFix, startKey, false)
defer itr.Release()
- for txNum := tradePairsNum; itr.Next() && txNum > 0; {
+ for txNum := ordersNum; itr.Next() && txNum > 0; {
key := itr.Key()
b := [32]byte{}
- fromAssetIDPos := preFixLen
+ fromAssetIDPos := ordersPreFixLen
copy(b[:], key[fromAssetIDPos:fromAssetIDPos+32])
fromAssetID := bc.NewAssetID(b)
- toAssetIDPos := preFixLen + 32
+ toAssetIDPos := ordersPreFixLen + 32
copy(b[:], key[toAssetIDPos:toAssetIDPos+32])
toAssetID := bc.NewAssetID(b)
- count := binary.BigEndian.Uint64(itr.Value())
-
- tradePairs = append(tradePairs, &common.TradePair{FromAssetID: &fromAssetID, ToAssetID: &toAssetID, Count: count})
-
- txNum--
- }
-
- return tradePairs, nil
-}
-
-func (d *DexTradeOrderDB) addTradePair(fromAssetID, toAssetID *bc.AssetID) error {
- count := uint64(0)
- key := calcTradePairKey(fromAssetID, toAssetID)
- if value := d.db.Get(key); value != nil {
- count = binary.BigEndian.Uint64(value)
- }
-
- count++
-
- value := [8]byte{}
- binary.BigEndian.PutUint64(value[:], count)
- d.db.Set(key, value[:])
- return nil
-}
+ ratePos := ordersPreFixLen + 32*2
+ rate := math.Float64frombits(binary.BigEndian.Uint64(key[ratePos : ratePos+8]))
-func (d *DexTradeOrderDB) deleteTradePair(fromAssetID, toAssetID *bc.AssetID) error {
- key := calcTradePairKey(fromAssetID, toAssetID)
- if value := d.db.Get(key); value != nil {
- count := binary.BigEndian.Uint64(value) - 1
+ dexUtxo := &common.DexUtxo{}
+ if err := json.Unmarshal(itr.Value(), dexUtxo); err != nil {
+ return nil, err
+ }
- if count > 0 {
- value := [8]byte{}
- binary.BigEndian.PutUint64(value[:], count)
- d.db.Set(key, value[:])
- } else {
- d.db.Delete(key)
+ order := &common.Order{
+ FromAssetID: &fromAssetID,
+ ToAssetID: &toAssetID,
+ Rate: rate,
+ Utxo: dexUtxo,
}
- return nil
+
+ orders = append(orders, order)
+ txNum--
}
- return errors.New("don't find trade pair")
+ return orders, nil
}
-func (d *DexTradeOrderDB) ProcessOrders(addOrders []*common.Order, delOreders []*common.Order, height uint64, blockHash *bc.Hash) error {
+func (d *DexStore) ProcessOrders(addOrders []*common.Order, delOreders []*common.Order, height uint64, blockHash *bc.Hash) error {
batch := d.db.NewBatch()
if err := d.addOrders(batch, addOrders); err != nil {
return nil
}
-func (d *DexTradeOrderDB) addOrders(batch dbm.Batch, orders []*common.Order) error {
+func (d *DexStore) addOrders(batch dbm.Batch, orders []*common.Order) error {
+ tradePairMap := make(map[common.TradePair]uint64)
for _, order := range orders {
data, err := json.Marshal(order.Utxo)
if err != nil {
return err
}
+
utxoHash := bc.NewHash(sha3.Sum256(data))
key := calcOrdersKey(order.FromAssetID, order.ToAssetID, &utxoHash, order.Rate)
batch.Set(key, data)
- if err := d.addTradePair(order.FromAssetID, order.ToAssetID); err != nil {
- return err
+ tradePair := common.TradePair{
+ FromAssetID: order.FromAssetID,
+ ToAssetID: order.ToAssetID,
}
+ tradePairMap[tradePair] += 1
+ }
+
+ if err := d.addTradePair(batch, tradePairMap); err != nil {
+ return err
}
return nil
}
-func (d *DexTradeOrderDB) deleteOrder(batch dbm.Batch, orders []*common.Order) error {
+func (d *DexStore) deleteOrder(batch dbm.Batch, orders []*common.Order) error {
+ tradePairMap := make(map[common.TradePair]uint64)
for _, order := range orders {
data, err := json.Marshal(order.Utxo)
if err != nil {
return err
}
+
utxoHash := bc.NewHash(sha3.Sum256(data))
key := calcOrdersKey(order.FromAssetID, order.ToAssetID, &utxoHash, order.Rate)
batch.Delete(key)
-
- if err := d.deleteTradePair(order.FromAssetID, order.ToAssetID); err != nil {
- return err
+ tradePair := common.TradePair{
+ FromAssetID: order.FromAssetID,
+ ToAssetID: order.ToAssetID,
}
+ tradePairMap[tradePair] += 1
+ }
+
+ if err := d.deleteTradePair(batch, tradePairMap); err != nil {
+ return err
}
return nil
}
-func (d *DexTradeOrderDB) ListOrders(fromAssetID, toAssetID *bc.AssetID, rateAfter float64) ([]*common.Order, error) {
- ordersPreFixLen := len(ordersPreFix)
- orders := []*common.Order{}
+func (d *DexStore) GetDexDatabaseState() (*common.DexDatabaseState, error) {
+ value := d.db.Get(bestMatchStore)
+ if value != nil {
+ return nil, errors.New("don't find state of dex-database")
+ }
- orderPreFix := append(ordersPreFix, fromAssetID.Bytes()...)
- orderPreFix = append(orderPreFix, toAssetID.Bytes()...)
+ state := &common.DexDatabaseState{}
+ if err := json.Unmarshal(value, state); err != nil {
+ return nil, err
+ }
- startKey := []byte{}
- buf := make([]byte, 8)
- binary.BigEndian.PutUint64(buf, math.Float64bits(rateAfter))
- copy(startKey, orderPreFix)
- startKey = append(startKey, buf...)
+ return state, nil
+}
- itr := d.db.IteratorPrefixWithStart(orderPreFix, startKey, false)
+func (d *DexStore) ListTradePairsWithStart(fromAssetID, toAssetID *bc.AssetID) ([]*common.TradePair, error) {
+ var startKey []byte
+ if fromAssetID != nil && toAssetID != nil {
+ startKey = calcTradePairKey(fromAssetID, toAssetID)
+ }
+
+ tradePairs := []*common.TradePair{}
+ preFixLen := len(tradePairPreFix)
+ itr := d.db.IteratorPrefixWithStart(tradePairPreFix, startKey, false)
defer itr.Release()
- for txNum := ordersNum; itr.Next() && txNum > 0; {
+ for txNum := tradePairsNum; itr.Next() && txNum > 0; {
key := itr.Key()
b := [32]byte{}
- fromAssetIDPos := ordersPreFixLen
+ fromAssetIDPos := preFixLen
copy(b[:], key[fromAssetIDPos:fromAssetIDPos+32])
fromAssetID := bc.NewAssetID(b)
- toAssetIDPos := ordersPreFixLen + 32
+ toAssetIDPos := preFixLen + 32
copy(b[:], key[toAssetIDPos:toAssetIDPos+32])
toAssetID := bc.NewAssetID(b)
- ratePos := ordersPreFixLen + 32*2
- rate := math.Float64frombits(binary.BigEndian.Uint64(key[ratePos : ratePos+8]))
-
- dexUtxo := &common.DexUtxo{}
- if err := json.Unmarshal(itr.Value(), dexUtxo); err != nil {
- return nil, err
- }
+ count := binary.BigEndian.Uint64(itr.Value())
- order := &common.Order{
- FromAssetID: &fromAssetID,
- ToAssetID: &toAssetID,
- Rate: rate,
- Utxo: dexUtxo,
- }
+ tradePairs = append(tradePairs, &common.TradePair{FromAssetID: &fromAssetID, ToAssetID: &toAssetID, Count: count})
- orders = append(orders, order)
txNum--
}
- return orders, nil
+ return tradePairs, nil
}
-func (d *DexTradeOrderDB) GetDexDatabaseState() (*common.DexDatabaseState, error) {
- value := d.db.Get(bestMatchStore)
- if value != nil {
- return nil, errors.New("don't find state of dex-database")
+func (d *DexStore) addTradePair(batch dbm.Batch, tradePairMap map[common.TradePair]uint64) error {
+ for k, v := range tradePairMap {
+ count := uint64(0)
+ key := calcTradePairKey(k.FromAssetID, k.ToAssetID)
+ if value := d.db.Get(key); value != nil {
+ count = binary.BigEndian.Uint64(value)
+ }
+
+ count += v
+
+ value := [8]byte{}
+ binary.BigEndian.PutUint64(value[:], count)
+ batch.Set(key, value[:])
}
+ return nil
+}
- state := &common.DexDatabaseState{}
- if err := json.Unmarshal(value, state); err != nil {
- return nil, err
+func (d *DexStore) deleteTradePair(batch dbm.Batch, tradePairMap map[common.TradePair]uint64) error {
+ for k, v := range tradePairMap {
+ key := calcTradePairKey(k.FromAssetID, k.ToAssetID)
+ value := d.db.Get(key)
+ if value == nil {
+ return errors.New("don't find trade pair")
+ }
+ count := binary.BigEndian.Uint64(value) - v
+
+ if count > 0 {
+ value := [8]byte{}
+ binary.BigEndian.PutUint64(value[:], count)
+ batch.Set(key, value[:])
+ } else {
+ batch.Delete(key)
+ }
}
- return state, nil
+ return nil
}
-func (d *DexTradeOrderDB) saveDexDatabaseState(batch dbm.Batch, state *common.DexDatabaseState) error {
+func (d *DexStore) saveDexDatabaseState(batch dbm.Batch, state *common.DexDatabaseState) error {
value, err := json.Marshal(state)
if err != nil {
return err