Unverified Commit 754b2b90 authored by vipwzw's avatar vipwzw Committed by GitHub

Merge pull request #770 from linj-disanbo/trade-query-use-localdb2

Trade query use localdb2
parents 232133ee bd5de82f
...@@ -3,7 +3,7 @@ module github.com/33cn/plugin ...@@ -3,7 +3,7 @@ module github.com/33cn/plugin
go 1.12 go 1.12
require ( require (
github.com/33cn/chain33 v0.0.0-20200114070319-ef01c7b69d82 github.com/33cn/chain33 v0.0.0-20200115085731-38f06ce8411c
github.com/BurntSushi/toml v0.3.1 github.com/BurntSushi/toml v0.3.1
github.com/NebulousLabs/Sia v1.3.7 github.com/NebulousLabs/Sia v1.3.7
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
......
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/33cn/chain33 v0.0.0-20200114070319-ef01c7b69d82 h1:iTNQWEYAek9YmLcGScdBo2mODy+JOe7gOJl+PgpKjO8= github.com/33cn/chain33 v0.0.0-20200115085731-38f06ce8411c h1:ePkHv1GhUGsEubK1mxtrCe0ricOc66QNAN11hOWH6ps=
github.com/33cn/chain33 v0.0.0-20200114070319-ef01c7b69d82/go.mod h1:lhZbNbCnCGsiiapxGZcSxfxKdIAdCK0UzHgpp65XMlM= github.com/33cn/chain33 v0.0.0-20200115085731-38f06ce8411c/go.mod h1:lhZbNbCnCGsiiapxGZcSxfxKdIAdCK0UzHgpp65XMlM=
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7 h1:PqzgE6kAMi81xWQA2QIVxjWkFHptGgC547vchpUbtFo= github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7 h1:PqzgE6kAMi81xWQA2QIVxjWkFHptGgC547vchpUbtFo=
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
......
...@@ -231,7 +231,7 @@ func (store *privacyStore) getWalletPrivacyTxDetails(param *privacytypes.ReqPriv ...@@ -231,7 +231,7 @@ func (store *privacyStore) getWalletPrivacyTxDetails(param *privacytypes.ReqPriv
} else { } else {
keyPrefix = calcRecvPrivacyTxKey(param.Tokenname, param.Address, "") keyPrefix = calcRecvPrivacyTxKey(param.Tokenname, param.Address, "")
} }
txkeybytes := list.IteratorScanFromLast(keyPrefix, param.Count) txkeybytes := list.IteratorScanFromLast(keyPrefix, param.Count, db.ListDESC)
for _, keybyte := range txkeybytes { for _, keybyte := range txkeybytes {
value, err := store.Get(keybyte) value, err := store.Get(keybyte)
if err != nil { if err != nil {
......
...@@ -36,7 +36,7 @@ func (t *trade) ExecDelLocal_RevokeBuy(revoke *pty.TradeForRevokeBuy, tx *types. ...@@ -36,7 +36,7 @@ func (t *trade) ExecDelLocal_RevokeBuy(revoke *pty.TradeForRevokeBuy, tx *types.
func (t *trade) localDelLog(tx *types.Transaction, receipt *types.ReceiptData, index int, tradedBoardlot int64) (*types.LocalDBSet, error) { func (t *trade) localDelLog(tx *types.Transaction, receipt *types.ReceiptData, index int, tradedBoardlot int64) (*types.LocalDBSet, error) {
var set types.LocalDBSet var set types.LocalDBSet
table := NewOrderTable(t.GetLocalDB()) table := NewOrderTableV2(t.GetLocalDB())
txIndex := dapp.HeightIndexStr(t.GetHeight(), int64(index)) txIndex := dapp.HeightIndexStr(t.GetHeight(), int64(index))
for i := 0; i < len(receipt.Logs); i++ { for i := 0; i < len(receipt.Logs); i++ {
...@@ -47,51 +47,46 @@ func (t *trade) localDelLog(tx *types.Transaction, receipt *types.ReceiptData, i ...@@ -47,51 +47,46 @@ func (t *trade) localDelLog(tx *types.Transaction, receipt *types.ReceiptData, i
if err != nil { if err != nil {
panic(err) //数据错误了,已经被修改了 panic(err) //数据错误了,已经被修改了
} }
kv := t.deleteSell(receipt.Base, item.Ty, tx, txIndex, table, tradedBoardlot) t.deleteSell(receipt.Base, item.Ty, tx, txIndex, table, tradedBoardlot)
set.KV = append(set.KV, kv...)
} else if item.Ty == pty.TyLogTradeSellRevoke { } else if item.Ty == pty.TyLogTradeSellRevoke {
var receipt pty.ReceiptTradeSellRevoke var receipt pty.ReceiptTradeSellRevoke
err := types.Decode(item.Log, &receipt) err := types.Decode(item.Log, &receipt)
if err != nil { if err != nil {
panic(err) //数据错误了,已经被修改了 panic(err) //数据错误了,已经被修改了
} }
kv := t.deleteSell(receipt.Base, item.Ty, tx, txIndex, table, tradedBoardlot) t.deleteSell(receipt.Base, item.Ty, tx, txIndex, table, tradedBoardlot)
set.KV = append(set.KV, kv...)
} else if item.Ty == pty.TyLogTradeBuyMarket { } else if item.Ty == pty.TyLogTradeBuyMarket {
var receipt pty.ReceiptTradeBuyMarket var receipt pty.ReceiptTradeBuyMarket
err := types.Decode(item.Log, &receipt) err := types.Decode(item.Log, &receipt)
if err != nil { if err != nil {
panic(err) //数据错误了,已经被修改了 panic(err) //数据错误了,已经被修改了
} }
kv := t.deleteBuy(receipt.Base, txIndex, table) t.deleteBuy(receipt.Base, txIndex, table)
set.KV = append(set.KV, kv...)
} else if item.Ty == pty.TyLogTradeBuyRevoke { } else if item.Ty == pty.TyLogTradeBuyRevoke {
var receipt pty.ReceiptTradeBuyRevoke var receipt pty.ReceiptTradeBuyRevoke
err := types.Decode(item.Log, &receipt) err := types.Decode(item.Log, &receipt)
if err != nil { if err != nil {
panic(err) //数据错误了,已经被修改了 panic(err) //数据错误了,已经被修改了
} }
kv := t.deleteBuyLimit(receipt.Base, item.Ty, tx, txIndex, table, tradedBoardlot) t.deleteBuyLimit(receipt.Base, item.Ty, tx, txIndex, table, tradedBoardlot)
set.KV = append(set.KV, kv...)
} else if item.Ty == pty.TyLogTradeBuyLimit { } else if item.Ty == pty.TyLogTradeBuyLimit {
var receipt pty.ReceiptTradeBuyLimit var receipt pty.ReceiptTradeBuyLimit
err := types.Decode(item.Log, &receipt) err := types.Decode(item.Log, &receipt)
if err != nil { if err != nil {
panic(err) //数据错误了,已经被修改了 panic(err) //数据错误了,已经被修改了
} }
kv := t.deleteBuyLimit(receipt.Base, item.Ty, tx, txIndex, table, tradedBoardlot) t.deleteBuyLimit(receipt.Base, item.Ty, tx, txIndex, table, tradedBoardlot)
set.KV = append(set.KV, kv...)
} else if item.Ty == pty.TyLogTradeSellMarket { } else if item.Ty == pty.TyLogTradeSellMarket {
var receipt pty.ReceiptSellMarket var receipt pty.ReceiptSellMarket
err := types.Decode(item.Log, &receipt) err := types.Decode(item.Log, &receipt)
if err != nil { if err != nil {
panic(err) //数据错误了,已经被修改了 panic(err) //数据错误了,已经被修改了
} }
kv := t.deleteSellMarket(receipt.Base, txIndex, table) t.deleteSellMarket(receipt.Base, txIndex, table)
set.KV = append(set.KV, kv...)
} }
} }
newKvs, err := table.Save() newKvs, err := table.Save()
debugTableKV(newKvs, "exec_del_local orderV2 kvs")
if err != nil { if err != nil {
tradelog.Error("trade table.Save failed", "error", err) tradelog.Error("trade table.Save failed", "error", err)
return nil, err return nil, err
......
...@@ -36,9 +36,8 @@ func (t *trade) ExecLocal_RevokeBuy(revoke *pty.TradeForRevokeBuy, tx *types.Tra ...@@ -36,9 +36,8 @@ func (t *trade) ExecLocal_RevokeBuy(revoke *pty.TradeForRevokeBuy, tx *types.Tra
func (t *trade) localAddLog(tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error) { func (t *trade) localAddLog(tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error) {
var set types.LocalDBSet var set types.LocalDBSet
table := NewOrderTable(t.GetLocalDB()) table := NewOrderTableV2(t.GetLocalDB())
txIndex := dapp.HeightIndexStr(t.GetHeight(), int64(index)) txIndex := dapp.HeightIndexStr(t.GetHeight(), int64(index))
for i := 0; i < len(receipt.Logs); i++ { for i := 0; i < len(receipt.Logs); i++ {
item := receipt.Logs[i] item := receipt.Logs[i]
if item.Ty == pty.TyLogTradeSellLimit { if item.Ty == pty.TyLogTradeSellLimit {
...@@ -47,24 +46,21 @@ func (t *trade) localAddLog(tx *types.Transaction, receipt *types.ReceiptData, i ...@@ -47,24 +46,21 @@ func (t *trade) localAddLog(tx *types.Transaction, receipt *types.ReceiptData, i
if err != nil { if err != nil {
panic(err) //数据错误了,已经被修改了 panic(err) //数据错误了,已经被修改了
} }
kv := t.saveSell(receipt.Base, item.Ty, tx, txIndex, table) t.saveSell(receipt.Base, item.Ty, tx, txIndex, table)
set.KV = append(set.KV, kv...)
} else if item.Ty == pty.TyLogTradeSellRevoke { } else if item.Ty == pty.TyLogTradeSellRevoke {
var receipt pty.ReceiptTradeSellRevoke var receipt pty.ReceiptTradeSellRevoke
err := types.Decode(item.Log, &receipt) err := types.Decode(item.Log, &receipt)
if err != nil { if err != nil {
panic(err) //数据错误了,已经被修改了 panic(err) //数据错误了,已经被修改了
} }
kv := t.saveSell(receipt.Base, item.Ty, tx, txIndex, table) t.saveSell(receipt.Base, item.Ty, tx, txIndex, table)
set.KV = append(set.KV, kv...)
} else if item.Ty == pty.TyLogTradeBuyMarket { } else if item.Ty == pty.TyLogTradeBuyMarket {
var receipt pty.ReceiptTradeBuyMarket var receipt pty.ReceiptTradeBuyMarket
err := types.Decode(item.Log, &receipt) err := types.Decode(item.Log, &receipt)
if err != nil { if err != nil {
panic(err) //数据错误了,已经被修改了 panic(err) //数据错误了,已经被修改了
} }
kv := t.saveBuy(receipt.Base, tx, txIndex, table) t.saveBuy(receipt.Base, tx, txIndex, table)
set.KV = append(set.KV, kv...)
} else if item.Ty == pty.TyLogTradeBuyRevoke { } else if item.Ty == pty.TyLogTradeBuyRevoke {
var receipt pty.ReceiptTradeBuyRevoke var receipt pty.ReceiptTradeBuyRevoke
err := types.Decode(item.Log, &receipt) err := types.Decode(item.Log, &receipt)
...@@ -72,8 +68,7 @@ func (t *trade) localAddLog(tx *types.Transaction, receipt *types.ReceiptData, i ...@@ -72,8 +68,7 @@ func (t *trade) localAddLog(tx *types.Transaction, receipt *types.ReceiptData, i
panic(err) //数据错误了,已经被修改了 panic(err) //数据错误了,已经被修改了
} }
kv := t.saveBuyLimit(receipt.Base, item.Ty, tx, txIndex, table) t.saveBuyLimit(receipt.Base, item.Ty, tx, txIndex, table)
set.KV = append(set.KV, kv...)
} else if item.Ty == pty.TyLogTradeBuyLimit { } else if item.Ty == pty.TyLogTradeBuyLimit {
var receipt pty.ReceiptTradeBuyLimit var receipt pty.ReceiptTradeBuyLimit
err := types.Decode(item.Log, &receipt) err := types.Decode(item.Log, &receipt)
...@@ -81,20 +76,18 @@ func (t *trade) localAddLog(tx *types.Transaction, receipt *types.ReceiptData, i ...@@ -81,20 +76,18 @@ func (t *trade) localAddLog(tx *types.Transaction, receipt *types.ReceiptData, i
panic(err) //数据错误了,已经被修改了 panic(err) //数据错误了,已经被修改了
} }
kv := t.saveBuyLimit(receipt.Base, item.Ty, tx, txIndex, table) t.saveBuyLimit(receipt.Base, item.Ty, tx, txIndex, table)
set.KV = append(set.KV, kv...)
} else if item.Ty == pty.TyLogTradeSellMarket { } else if item.Ty == pty.TyLogTradeSellMarket {
var receipt pty.ReceiptSellMarket var receipt pty.ReceiptSellMarket
err := types.Decode(item.Log, &receipt) err := types.Decode(item.Log, &receipt)
if err != nil { if err != nil {
panic(err) //数据错误了,已经被修改了 panic(err) //数据错误了,已经被修改了
} }
kv := t.saveSellMarket(receipt.Base, tx, txIndex, table) t.saveSellMarket(receipt.Base, tx, txIndex, table)
//tradelog.Info("saveSellMarket", "kv", kv)
set.KV = append(set.KV, kv...)
} }
} }
newKvs, err := table.Save() newKvs, err := table.Save()
debugTableKV(newKvs, "exec_local orderV2 kvs")
if err != nil { if err != nil {
tradelog.Error("trade table.Save failed", "error", err) tradelog.Error("trade table.Save failed", "error", err)
return nil, err return nil, err
...@@ -106,3 +99,10 @@ func (t *trade) localAddLog(tx *types.Transaction, receipt *types.ReceiptData, i ...@@ -106,3 +99,10 @@ func (t *trade) localAddLog(tx *types.Transaction, receipt *types.ReceiptData, i
} }
return &set, nil return &set, nil
} }
func debugTableKV(kvs []*types.KeyValue, msg string) {
tradelog.Debug("table save debug:"+msg, "count", len(kvs))
for i, kv := range kvs {
tradelog.Debug("table save debug:"+msg, "i", i, "key", string(kv.Key), "value", string(kv.Value))
}
}
...@@ -4,74 +4,11 @@ ...@@ -4,74 +4,11 @@
package executor package executor
import (
"fmt"
"strconv"
"github.com/33cn/chain33/types"
pty "github.com/33cn/plugin/plugin/dapp/trade/types"
)
const ( const (
sellOrderSHTAS = "LODB-trade-sellorder-shtas:" sellIDPrefix = "mavl-trade-sell-"
sellOrderASTS = "LODB-trade-sellorder-asts:" buyIDPrefix = "mavl-trade-buy-"
sellOrderATSS = "LODB-trade-sellorder-atss:"
sellOrderTSPAS = "LODB-trade-sellorder-tspas:"
buyOrderSHTAS = "LODB-trade-buyorder-shtas:"
buyOrderASTS = "LODB-trade-buyorder-asts:"
buyOrderATSS = "LODB-trade-buyorder-atss:"
buyOrderTSPAS = "LODB-trade-buyorder-tspas:"
sellIDPrefix = "mavl-trade-sell-"
buyIDPrefix = "mavl-trade-buy-"
// Addr-Status-Type-Height-Key
orderASTHK = "LODB-trade-order-asthk:"
) )
// sell order 4 key, 4prefix
// 特定状态下的卖单
func calcTokenSellOrderKey(token string, addr string, status int32, sellOrderID string, height int64) []byte {
key := fmt.Sprintf(sellOrderSHTAS+"%d:%d:%s:%s:%s", status, height, token, addr, sellOrderID)
return []byte(key)
}
// 特定账户下特定状态的卖单
func calcOnesSellOrderKeyStatus(token string, addr string, status int32, sellOrderID string) []byte {
key := fmt.Sprintf(sellOrderASTS+"%s:%d:%s:%s", addr, status, token, sellOrderID)
return []byte(key)
}
// 特定账户下特定token的卖单
func calcOnesSellOrderKeyToken(token string, addr string, status int32, sellOrderID string) []byte {
key := fmt.Sprintf(sellOrderATSS+"%s:%s:%d:%s", addr, token, status, sellOrderID)
return []byte(key)
}
// 指定token的卖单, 带上价格方便排序
func calcTokensSellOrderKeyStatus(token string, status int32, price int64, addr string, sellOrderID string) []byte {
key := fmt.Sprintf(sellOrderTSPAS+"%s:%d:%016d:%s:%s", token, status, price, addr, sellOrderID)
return []byte(key)
}
func calcTokensSellOrderPrefixStatus(token string, status int32) []byte {
prefix := fmt.Sprintf(sellOrderTSPAS+"%s:%d:", token, status)
return []byte(prefix)
}
// 特定账户下指定token的卖单
func calcOnesSellOrderPrefixToken(token string, addr string) []byte {
key := fmt.Sprintf(sellOrderATSS+"%s:%s", addr, token)
return []byte(key)
}
// 特定账户下的卖单
func calcOnesSellOrderPrefixAddr(addr string) []byte {
return []byte(fmt.Sprintf(sellOrderASTS+"%s", addr))
}
func calcOnesSellOrderPrefixStatus(addr string, status int32) []byte {
return []byte(fmt.Sprintf(sellOrderASTS+"%s:%d", addr, status))
}
// ids // ids
func calcTokenSellID(hash string) string { func calcTokenSellID(hash string) string {
return sellIDPrefix + hash return sellIDPrefix + hash
...@@ -81,104 +18,6 @@ func calcTokenBuyID(hash string) string { ...@@ -81,104 +18,6 @@ func calcTokenBuyID(hash string) string {
return buyIDPrefix + hash return buyIDPrefix + hash
} }
// buy limit order 4 key, 4prefix
// 特定状态下的买单
func calcTokenBuyOrderKey(token string, addr string, status int32, orderID string, height int64) []byte {
key := fmt.Sprintf(buyOrderSHTAS+"%d:%d:%s:%s:%s", status, height, token, addr, orderID)
return []byte(key)
}
// 特定账户下特定状态的买单
func calcOnesBuyOrderKeyStatus(token string, addr string, status int32, orderID string) []byte {
key := fmt.Sprintf(buyOrderASTS+"%s:%d:%s:%s", addr, status, token, orderID)
return []byte(key)
}
// 特定账户下特定token的买单
func calcOnesBuyOrderKeyToken(token string, addr string, status int32, orderID string) []byte {
key := fmt.Sprintf(buyOrderATSS+"%s:%s:%d:%s", addr, token, status, orderID)
return []byte(key)
}
// 指定token的卖单, 带上价格方便排序
func calcTokensBuyOrderKeyStatus(token string, status int32, price int64, addr string, orderID string) []byte {
key := fmt.Sprintf(buyOrderTSPAS+"%s:%d:%016d:%s:%s", token, status, price, addr, orderID)
return []byte(key)
}
func calcTokensBuyOrderPrefixStatus(token string, status int32) []byte {
prefix := fmt.Sprintf(buyOrderTSPAS+"%s:%d:", token, status)
return []byte(prefix)
}
// 特定账户下指定token的买单
func calcOnesBuyOrderPrefixToken(token string, addr string) []byte {
key := fmt.Sprintf(buyOrderATSS+"%s:%s", addr, token)
return []byte(key)
}
// 特定账户下的买单
func calcOnesBuyOrderPrefixAddr(addr string) []byte {
return []byte(fmt.Sprintf(buyOrderASTS+"%s", addr))
}
func calcOnesBuyOrderPrefixStatus(addr string, status int32) []byte {
return []byte(fmt.Sprintf(buyOrderASTS+"%s:%d", addr, status))
}
// 特定帐号下的订单
// 这里状态进行转化, 分成 状态和类型, 状态三种, 类型 两种
// on: OnSale OnBuy
// done: Soldout boughtOut
// revoke: RevokeSell RevokeBuy
// buy/sell 两种类型
// 目前页面是按addr, 状态来
func calcOnesOrderKey(addr string, status int32, ty int32, height int64, key string) []byte {
return []byte(fmt.Sprintf(orderASTHK+"%s:%d:%010d:%d:%s", addr, status, height, ty, key))
}
// 特定状态下的买单
//func calcTokenBuyOrderPrefixStatus(status int32) []byte {
// return []byte(fmt.Sprintf(buyOrderSHTAS+"%d", status))
//}
func genSellMarketOrderKeyValue(kv []*types.KeyValue, receipt *pty.ReceiptSellBase, status int32,
height int64, value []byte) []*types.KeyValue {
keyID := receipt.TxHash
newkey := calcTokenSellOrderKey(receipt.TokenSymbol, receipt.Owner, status, keyID, height)
kv = append(kv, &types.KeyValue{Key: newkey, Value: value})
newkey = calcOnesSellOrderKeyStatus(receipt.TokenSymbol, receipt.Owner, status, keyID)
kv = append(kv, &types.KeyValue{Key: newkey, Value: value})
newkey = calcOnesSellOrderKeyToken(receipt.TokenSymbol, receipt.Owner, status, keyID)
kv = append(kv, &types.KeyValue{Key: newkey, Value: value})
priceBoardlot, err := strconv.ParseFloat(receipt.PricePerBoardlot, 64)
if err != nil {
panic(err)
}
priceBoardlotInt64 := int64(priceBoardlot * float64(types.TokenPrecision))
AmountPerBoardlot, err := strconv.ParseFloat(receipt.AmountPerBoardlot, 64)
if err != nil {
panic(err)
}
AmountPerBoardlotInt64 := int64(AmountPerBoardlot * float64(types.Coin))
price := calcPriceOfToken(priceBoardlotInt64, AmountPerBoardlotInt64)
newkey = calcTokensSellOrderKeyStatus(receipt.TokenSymbol, status,
price, receipt.Owner, keyID)
kv = append(kv, &types.KeyValue{Key: newkey, Value: value})
st, ty := fromStatus(status)
newkey = calcOnesOrderKey(receipt.Owner, st, ty, height, keyID)
kv = append(kv, &types.KeyValue{Key: newkey, Value: value})
return kv
}
// make a number as token's price whether cheap or dear // make a number as token's price whether cheap or dear
// support 1e8 bty pre token or 1/1e8 bty pre token, [1Coins, 1e16Coins] // support 1e8 bty pre token or 1/1e8 bty pre token, [1Coins, 1e16Coins]
// the number in key is used to sort buy orders and pages // the number in key is used to sort buy orders and pages
......
...@@ -171,6 +171,7 @@ func NewOrderTable(kvdb dbm.KV) *table.Table { ...@@ -171,6 +171,7 @@ func NewOrderTable(kvdb dbm.KV) *table.Table {
return t return t
} }
// gen order from tx and receipt
func (t *trade) genSellLimit(tx *types.Transaction, sell *pty.ReceiptSellBase, func (t *trade) genSellLimit(tx *types.Transaction, sell *pty.ReceiptSellBase,
sellorder *pty.SellOrder, txIndex string) *pty.LocalOrder { sellorder *pty.SellOrder, txIndex string) *pty.LocalOrder {
...@@ -272,7 +273,6 @@ func parseOrderPriceFloat(s string) int64 { ...@@ -272,7 +273,6 @@ func parseOrderPriceFloat(s string) int64 {
} }
func (t *trade) genSellMarket(tx *types.Transaction, sell *pty.ReceiptSellBase, txIndex string) *pty.LocalOrder { func (t *trade) genSellMarket(tx *types.Transaction, sell *pty.ReceiptSellBase, txIndex string) *pty.LocalOrder {
order := &pty.LocalOrder{ order := &pty.LocalOrder{
AssetSymbol: sell.TokenSymbol, AssetSymbol: sell.TokenSymbol,
TxIndex: txIndex, TxIndex: txIndex,
...@@ -300,7 +300,6 @@ func (t *trade) genSellMarket(tx *types.Transaction, sell *pty.ReceiptSellBase, ...@@ -300,7 +300,6 @@ func (t *trade) genSellMarket(tx *types.Transaction, sell *pty.ReceiptSellBase,
} }
func (t *trade) genBuyLimit(tx *types.Transaction, buy *pty.ReceiptBuyBase, txIndex string) *pty.LocalOrder { func (t *trade) genBuyLimit(tx *types.Transaction, buy *pty.ReceiptBuyBase, txIndex string) *pty.LocalOrder {
order := &pty.LocalOrder{ order := &pty.LocalOrder{
AssetSymbol: buy.TokenSymbol, AssetSymbol: buy.TokenSymbol,
TxIndex: txIndex, TxIndex: txIndex,
...@@ -375,7 +374,6 @@ func (t *trade) rollbackBuyLimit(tx *types.Transaction, buy *pty.ReceiptBuyBase, ...@@ -375,7 +374,6 @@ func (t *trade) rollbackBuyLimit(tx *types.Transaction, buy *pty.ReceiptBuyBase,
} }
func (t *trade) genBuyMarket(tx *types.Transaction, buy *pty.ReceiptBuyBase, txIndex string) *pty.LocalOrder { func (t *trade) genBuyMarket(tx *types.Transaction, buy *pty.ReceiptBuyBase, txIndex string) *pty.LocalOrder {
order := &pty.LocalOrder{ order := &pty.LocalOrder{
AssetSymbol: buy.TokenSymbol, AssetSymbol: buy.TokenSymbol,
TxIndex: txIndex, TxIndex: txIndex,
...@@ -392,7 +390,7 @@ func (t *trade) genBuyMarket(tx *types.Transaction, buy *pty.ReceiptBuyBase, txI ...@@ -392,7 +390,7 @@ func (t *trade) genBuyMarket(tx *types.Transaction, buy *pty.ReceiptBuyBase, txI
Height: buy.Height, Height: buy.Height,
Key: calcTokenBuyID(hex.EncodeToString(tx.Hash())), Key: calcTokenBuyID(hex.EncodeToString(tx.Hash())),
BlockTime: t.GetBlockTime(), BlockTime: t.GetBlockTime(),
IsSellOrder: true, IsSellOrder: false,
AssetExec: buy.AssetExec, AssetExec: buy.AssetExec,
IsFinished: true, IsFinished: true,
PriceExec: buy.PriceExec, PriceExec: buy.PriceExec,
...@@ -400,63 +398,3 @@ func (t *trade) genBuyMarket(tx *types.Transaction, buy *pty.ReceiptBuyBase, txI ...@@ -400,63 +398,3 @@ func (t *trade) genBuyMarket(tx *types.Transaction, buy *pty.ReceiptBuyBase, txI
} }
return order return order
} }
func list(db dbm.KVDB, indexName string, data *pty.LocalOrder, count, direction int32) ([]*table.Row, error) {
query := NewOrderTable(db).GetQuery(db)
var primary []byte
if len(data.TxIndex) > 0 {
primary = []byte(data.TxIndex)
}
cur := &OrderRow{LocalOrder: data}
index, err := cur.Get(indexName)
if err != nil {
tradelog.Error("query List failed", "key", string(primary), "param", data, "err", err)
return nil, err
}
tradelog.Debug("query List dbg", "indexName", indexName, "index", string(index), "primary", primary, "count", count, "direction", direction)
rows, err := query.ListIndex(indexName, index, primary, count, direction)
if err != nil {
tradelog.Error("query List failed", "key", string(primary), "param", data, "err", err)
return nil, err
}
if len(rows) == 0 {
return nil, types.ErrNotFound
}
return rows, nil
}
/*
按 资产 查询 :
按 资产 & 地址 查询
按 地址
排序和分类
1. 时间顺序 txindex
1. 分类, 不同的状态 & 不同的性质: 买/卖
交易 -> 订单 按订单来 (交易和订单是多对多的关系,不适合joinTable)
交易 T1 Create -> T2 part-take -> T3 Revoke
订单左为进行中, 右为完成,
订单 (C1) | () -> (C1m) | (C2) -> () | (C2, C1r)
查询交易 / 查询订单
C -> C/M -> C/D
\
\ ->R
状态 1, TradeOrderStatusOnSale, 在售
状态 2: TradeOrderStatusSoldOut,售完
状态 3: TradeOrderStatusRevoked, 卖单被撤回
状态 4: TradeOrderStatusExpired, 订单超时(目前不支持订单超时)
状态 5: TradeOrderStatusOnBuy, 求购
状态 6: TradeOrderStatusBoughtOut, 购买完成
状态 7: TradeOrderStatusBuyRevoked, 买单被撤回
*/
...@@ -13,7 +13,7 @@ import ( ...@@ -13,7 +13,7 @@ import (
) )
var order1 = &pty.LocalOrder{ var order1 = &pty.LocalOrder{
AssetSymbol: "A", AssetSymbol: "bty",
Owner: "O1", Owner: "O1",
AmountPerBoardlot: 1, AmountPerBoardlot: 1,
MinBoardlot: 1, MinBoardlot: 1,
...@@ -28,13 +28,15 @@ var order1 = &pty.LocalOrder{ ...@@ -28,13 +28,15 @@ var order1 = &pty.LocalOrder{
Key: "B1", Key: "B1",
BlockTime: 1, BlockTime: 1,
IsSellOrder: false, IsSellOrder: false,
AssetExec: "a", AssetExec: "coins",
TxIndex: dapp.HeightIndexStr(1, 1), TxIndex: dapp.HeightIndexStr(1, 1),
IsFinished: false, IsFinished: false,
PriceExec: "token",
PriceSymbol: "CCNY",
} }
var order2 = &pty.LocalOrder{ var order2 = &pty.LocalOrder{
AssetSymbol: "A", AssetSymbol: "bty",
Owner: "O1", Owner: "O1",
AmountPerBoardlot: 1, AmountPerBoardlot: 1,
MinBoardlot: 1, MinBoardlot: 1,
...@@ -49,9 +51,32 @@ var order2 = &pty.LocalOrder{ ...@@ -49,9 +51,32 @@ var order2 = &pty.LocalOrder{
Key: "B2", Key: "B2",
BlockTime: 2, BlockTime: 2,
IsSellOrder: false, IsSellOrder: false,
AssetExec: "a", AssetExec: "coins",
TxIndex: dapp.HeightIndexStr(2, 1), TxIndex: dapp.HeightIndexStr(2, 1),
IsFinished: false, IsFinished: false,
PriceExec: "token",
PriceSymbol: "CCNY",
}
// 两个fork前的数据
var order3 = &pty.LocalOrder{
AssetSymbol: "CCNY",
Owner: "O1",
AmountPerBoardlot: 1,
MinBoardlot: 1,
PricePerBoardlot: 1,
TotalBoardlot: 10,
TradedBoardlot: 0,
BuyID: "B2",
Status: pty.TradeOrderStatusOnBuy,
SellID: "",
TxHash: nil,
Height: 3,
Key: "B2",
BlockTime: 3,
IsSellOrder: false,
TxIndex: dapp.HeightIndexStr(3, 1),
IsFinished: false,
} }
func TestListAll(t *testing.T) { func TestListAll(t *testing.T) {
...@@ -65,3 +90,15 @@ func TestListAll(t *testing.T) { ...@@ -65,3 +90,15 @@ func TestListAll(t *testing.T) {
t.Log(kvs) t.Log(kvs)
ldb.Close() ldb.Close()
} }
func TestListV2All(t *testing.T) {
dir, ldb, tdb := util.CreateTestDB()
t.Log(dir, ldb, tdb)
odb := NewOrderTableV2(tdb)
odb.Add(order1)
odb.Add(order2)
kvs, err := odb.Save()
assert.Nil(t, err)
t.Log(kvs)
ldb.Close()
}
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package executor
import (
"fmt"
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/common/db/table"
"github.com/33cn/chain33/types"
pty "github.com/33cn/plugin/plugin/dapp/trade/types"
)
// 本地数据版本
// 1. v0 手动生成
// 2. v1 用table生成 LocalOrder
// 3. v2 用table生成 LocalOrderV2 比v1 用更多的索引,支持v0需要的数据索引,即将v2 包含 v0 v1 数据
// 预期在6.4升级后 v0 格式将不存在
/*
现有接口
1. 查询地址对应的买单 (无分页)
1.1 只指定地址 -> owner
1.2 同时指定地址和token -> owner_asset
1.3 显示一个用户成交的所有买单 -> owner
1.4 显示一个用户成交的指定一个或者多个token所有买单 -> owner_asset 不支持多个
2. 分状态查询地址的买单: 状态 地址 (无分页) -> owner_status
3. 显示一个token 指定数量的买单 GetTokenBuyOrderByStatus -> asset_inBuy_status
4. 显示指定token出售者的一个或多个token 或 不指定token 的卖单 (无分页) -> owner_asset/owner_asset_isSell 不支持多个
5. 显示指定状态下的某地址卖单 (无分页) -> owner_isSell_status
6. 显示一个token 指定数量的卖单 -> asset_isSell
7. 根据状态分页列出某地址的订单(包括买单卖单) owner_status
*/
//
var optV2 = &table.Option{
Prefix: "LODB-trade",
Name: "order_v2",
Primary: "txIndex",
// asset 指定交易对 price_exec + price_symbol + asset_exec+asset_symbol
// status: 设计为可以同时查询几种的并集 , 存储为前缀, 需要提前设计需要合并的, 用前缀表示
// 进行中, 撤销, 部分成交 , 全部成交, 完成状态统一前缀. 数字和原来不一样
// 00 10 11 12 1*
// 排序特点: 在不用key排序时,需要生成排序用的组合索引, 前面n个索引用来区分前缀, 后一个索引用来排序
Index: []string{
"key", // 内部查询用
"asset", // 按资产统计订单
"asset_isSell_status", // 接口 3
// "asset_status", 可能需求, 用于资产的交易历史
// "asset_isSell",
"owner", // 接口 1.1, 1.3
"owner_asset", // 接口 1.2, 1.4, 4, 7
"owner_asset_isSell", // 接口 4
"owner_asset_status", // 新需求, 在
"owner_isSell", // 接口 6
// "owner_isSell_statusPrefix", // 状态可以定制组合, 成交历史需求
"owner_status", // 接口 2
"assset_isSell_isFinished", // 用 isFinish, 进行订单是否完成的列表功能
"owner_asset_isFinished",
"owner_isFinished",
// "owner_statusPrefix", // 状态可以定制组合 , 成交历史需求
// 增加更多的key, 把老接口的数据的key 也生成,可以去掉老接口的实现
// https://chain.33.cn/document/105 文档1.8 sell & asset-price & status, order by price
// https://chain.33.cn/document/105 文档1.3 buy & asset-price & status, order by price
"asset_isSell_status_price",
// 文档1.2 文档1.5 按 用户状态来 addr-status buy or sell
"owner_isSell_status",
},
}
// OrderV2Row order row
type OrderV2Row struct {
*pty.LocalOrder
}
// NewOrderV2Row create row
func NewOrderV2Row() *OrderV2Row {
return &OrderV2Row{LocalOrder: nil}
}
// CreateRow create row
func (r *OrderV2Row) CreateRow() *table.Row {
return &table.Row{Data: &pty.LocalOrder{}}
}
// SetPayload set payload
func (r *OrderV2Row) SetPayload(data types.Message) error {
if d, ok := data.(*pty.LocalOrder); ok {
r.LocalOrder = d
return nil
}
return types.ErrTypeAsset
}
// Get get index key
func (r *OrderV2Row) Get(key string) ([]byte, error) {
switch key {
case "txIndex":
return []byte(r.TxIndex), nil
case "key":
return []byte(r.Key), nil
case "asset":
return []byte(r.asset()), nil
case "asset_isSell_status":
return []byte(fmt.Sprintf("%s_%d_%s", r.asset(), r.isSell(), r.status())), nil
case "owner":
return []byte(r.Owner), nil
case "owner_asset":
return []byte(fmt.Sprintf("%s_%s", r.Owner, r.asset())), nil
case "owner_asset_isSell":
return []byte(fmt.Sprintf("%s_%s_%d", r.Owner, r.asset(), r.isSell())), nil
case "owner_asset_status":
return []byte(fmt.Sprintf("%s_%s_%s", r.Owner, r.asset(), r.status())), nil
case "owner_isSell":
return []byte(fmt.Sprintf("%s_%d", r.Owner, r.isSell())), nil
case "owner_isSell_status":
return []byte(fmt.Sprintf("%s_%d_%s", r.Owner, r.isSell(), r.status())), nil
case "owner_status":
return []byte(fmt.Sprintf("%s_%s", r.Owner, r.status())), nil
//case "owner_statusPrefix":
// return []byte(fmt.Sprintf("%s_%d", r.Owner, r.isSell())), nil
case "assset_isSell_isFinished":
return []byte(fmt.Sprintf("%s_%d_%d", r.Owner, r.isSell(), r.isFinished())), nil
case "owner_asset_isFinished":
return []byte(fmt.Sprintf("%s_%s_%d", r.Owner, r.asset(), r.isFinished())), nil
case "owner_isFinished":
return []byte(fmt.Sprintf("%s_%d", r.Owner, r.isFinished())), nil
case "asset_isSell_status_price":
return []byte(fmt.Sprintf("%s_%d_%s_%s", r.asset(), r.isSell(), r.status(), r.price())), nil
default:
return nil, types.ErrNotFound
}
}
// 老接口查询参数: Price 用主币
func (r *OrderV2Row) asset() string {
return r.LocalOrder.PriceExec + "." + r.LocalOrder.PriceSymbol + "_" + r.LocalOrder.AssetExec + "." + r.LocalOrder.AssetSymbol
}
func (r *OrderV2Row) isSell() int {
if r.IsSellOrder {
return 1
}
return 0
}
func (r *OrderV2Row) isFinished() int {
if r.IsFinished {
return 1
}
return 0
}
func (r *OrderV2Row) price() string {
// 在计算前缀时,返回空
if r.AmountPerBoardlot == 0 {
return ""
}
p := calcPriceOfToken(r.PricePerBoardlot, r.AmountPerBoardlot)
return fmt.Sprintf("%018d", p)
}
// status: 设计为可以同时查询几种的并集 , 存储为前缀, 需要提前设计需要合并的, 用前缀表示
// 进行中, 撤销, 部分成交 , 全部成交, 完成状态统一前缀. 数字和原来不一样
// 01 10 11 12 19 -> 1*
func (r *OrderV2Row) status() string {
if r.Status == pty.TradeOrderStatusOnBuy || r.Status == pty.TradeOrderStatusOnSale {
return "01" // 试图用1 可以匹配所有完成的
} else if r.Status == pty.TradeOrderStatusSoldOut || r.Status == pty.TradeOrderStatusBoughtOut {
return "12"
} else if r.Status == pty.TradeOrderStatusRevoked || r.Status == pty.TradeOrderStatusBuyRevoked {
return "10"
} else if r.Status == pty.TradeOrderStatusSellHalfRevoked || r.Status == pty.TradeOrderStatusBuyHalfRevoked {
return "11"
} else if r.Status == pty.TradeOrderStatusGroupComplete {
return "1" // 1* match complete
}
return "XX"
}
// NewOrderTableV2 create order table
func NewOrderTableV2(kvdb dbm.KV) *table.Table {
rowMeta := NewOrderV2Row()
rowMeta.SetPayload(&pty.LocalOrder{})
t, err := table.NewTable(rowMeta, kvdb, optV2)
if err != nil {
panic(err)
}
return t
}
func listV2(db dbm.KVDB, indexName string, data *pty.LocalOrder, count, direction int32) ([]*table.Row, error) {
query := NewOrderTableV2(db).GetQuery(db)
var primary []byte
if len(data.TxIndex) > 0 {
primary = []byte(data.TxIndex)
}
cur := &OrderV2Row{LocalOrder: data}
index, err := cur.Get(indexName)
if err != nil {
tradelog.Error("query List failed", "key", string(primary), "param", data, "err", err)
return nil, err
}
tradelog.Debug("query List dbg", "indexName", indexName, "index", string(index), "primary", primary, "count", count, "direction", direction)
rows, err := query.ListIndex(indexName, index, primary, count, direction)
if err != nil {
tradelog.Error("query List failed", "key", string(primary), "param", data, "err", err)
return nil, err
}
if len(rows) == 0 {
return nil, types.ErrNotFound
}
return rows, nil
}
package executor package executor
import ( import (
"strconv" dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
pty "github.com/33cn/plugin/plugin/dapp/trade/types" pty "github.com/33cn/plugin/plugin/dapp/trade/types"
"github.com/pkg/errors"
) )
// 将手动生成的local db 的代码和用table 生成的local db的代码分离出来 const (
// 手动生成的local db, 将不生成任意资产标价的数据, 保留用coins 生成交易的数据, 来兼容为升级的app 应用 tradeLocaldbVersioin = "LODB-trade-version"
// 希望有全量数据的, 需要调用新的rpc )
// sell limit
func genSaveSellKv(sellorder *pty.SellOrder) []*types.KeyValue {
if sellorder.PriceExec != "" && sellorder.PriceExec != defaultPriceExec {
return nil
}
status := sellorder.Status
var kv []*types.KeyValue
kv = saveSellOrderKeyValue(kv, sellorder, status)
if pty.TradeOrderStatusSoldOut == status || pty.TradeOrderStatusRevoked == status {
tradelog.Debug("trade saveSell ", "remove old status onsale to soldout or revoked with sellid", sellorder.SellID)
kv = deleteSellOrderKeyValue(kv, sellorder, pty.TradeOrderStatusOnSale)
}
return kv
}
func saveSellOrderKeyValue(kv []*types.KeyValue, sellorder *pty.SellOrder, status int32) []*types.KeyValue {
sellID := []byte(sellorder.SellID)
return genSellOrderKeyValue(kv, sellorder, status, sellID)
}
func deleteSellOrderKeyValue(kv []*types.KeyValue, sellorder *pty.SellOrder, status int32) []*types.KeyValue {
return genSellOrderKeyValue(kv, sellorder, status, nil)
}
func genSellOrderKeyValue(kv []*types.KeyValue, sellorder *pty.SellOrder, status int32, value []byte) []*types.KeyValue {
newkey := calcTokenSellOrderKey(sellorder.TokenSymbol, sellorder.Address, status, sellorder.SellID, sellorder.Height)
kv = append(kv, &types.KeyValue{Key: newkey, Value: value})
newkey = calcOnesSellOrderKeyStatus(sellorder.TokenSymbol, sellorder.Address, status, sellorder.SellID)
kv = append(kv, &types.KeyValue{Key: newkey, Value: value})
newkey = calcOnesSellOrderKeyToken(sellorder.TokenSymbol, sellorder.Address, status, sellorder.SellID)
kv = append(kv, &types.KeyValue{Key: newkey, Value: value})
newkey = calcTokensSellOrderKeyStatus(sellorder.TokenSymbol, status,
calcPriceOfToken(sellorder.PricePerBoardlot, sellorder.AmountPerBoardlot), sellorder.Address, sellorder.SellID)
kv = append(kv, &types.KeyValue{Key: newkey, Value: value})
st, ty := fromStatus(status) // 由于数据库精简需要保存具体数据
newkey = calcOnesOrderKey(sellorder.Address, st, ty, sellorder.Height, sellorder.SellID) // 生成 key -> id 格式的本地数据库数据, 在下个版本这个文件可以全部删除
kv = append(kv, &types.KeyValue{Key: newkey, Value: value}) // 下个版本可以删除
const (
sellOrderSHTAS = "LODB-trade-sellorder-shtas:"
sellOrderASTS = "LODB-trade-sellorder-asts:"
sellOrderATSS = "LODB-trade-sellorder-atss:"
sellOrderTSPAS = "LODB-trade-sellorder-tspas:"
buyOrderSHTAS = "LODB-trade-buyorder-shtas:"
buyOrderASTS = "LODB-trade-buyorder-asts:"
buyOrderATSS = "LODB-trade-buyorder-atss:"
buyOrderTSPAS = "LODB-trade-buyorder-tspas:"
// Addr-Status-Type-Height-Key
orderASTHK = "LODB-trade-order-asthk:"
)
return kv // Upgrade 实现升级接口
func (t *trade) Upgrade() error {
localDB := t.GetLocalDB()
// 获得默认的coins symbol, 更新数据时用
coinSymbol := t.GetAPI().GetConfig().GetCoinSymbol()
err := UpgradeLocalDBV2(localDB, coinSymbol)
if err != nil {
tradelog.Error("Upgrade failed", "err", err)
return errors.Cause(err)
}
return nil
} }
// buy market // UpgradeLocalDBV2 trade 本地数据库升级
func saveBuyMarketOrderKeyValue(kv []*types.KeyValue, receipt *pty.ReceiptBuyBase, status int32, height int64) []*types.KeyValue { // from 1 to 2
if receipt.PriceExec != "" && receipt.PriceExec != defaultPriceExec { func UpgradeLocalDBV2(localDB dbm.KVDB, coinSymbol string) error {
toVersion := 2
tradelog.Info("UpgradeLocalDBV2 upgrade start", "to_version", toVersion)
version, err := getVersion(localDB)
if err != nil {
return errors.Wrap(err, "UpgradeLocalDBV2 get version")
}
if version >= toVersion {
tradelog.Debug("UpgradeLocalDBV2 not need to upgrade", "current_version", version, "to_version", toVersion)
return nil return nil
} }
txhash := []byte(receipt.TxHash) err = UpgradeLocalDBPart2(localDB, coinSymbol)
return genBuyMarketOrderKeyValue(kv, receipt, status, height, txhash) if err != nil {
} return errors.Wrap(err, "UpgradeLocalDBV2 UpgradeLocalDBPart2")
}
func genBuyMarketOrderKeyValue(kv []*types.KeyValue, receipt *pty.ReceiptBuyBase,
status int32, height int64, value []byte) []*types.KeyValue {
keyID := receipt.TxHash
newkey := calcTokenBuyOrderKey(receipt.TokenSymbol, receipt.Owner, status, keyID, height)
kv = append(kv, &types.KeyValue{Key: newkey, Value: value})
newkey = calcOnesBuyOrderKeyStatus(receipt.TokenSymbol, receipt.Owner, status, keyID)
kv = append(kv, &types.KeyValue{Key: newkey, Value: value})
newkey = calcOnesBuyOrderKeyToken(receipt.TokenSymbol, receipt.Owner, status, keyID)
kv = append(kv, &types.KeyValue{Key: newkey, Value: value})
priceBoardlot, err := strconv.ParseFloat(receipt.PricePerBoardlot, 64) err = UpgradeLocalDBPart1(localDB)
if err != nil { if err != nil {
panic(err) return errors.Wrap(err, "UpgradeLocalDBV2 UpgradeLocalDBPart1")
} }
priceBoardlotInt64 := int64(priceBoardlot * float64(types.TokenPrecision)) err = setVersion(localDB, toVersion)
AmountPerBoardlot, err := strconv.ParseFloat(receipt.AmountPerBoardlot, 64)
if err != nil { if err != nil {
panic(err) return errors.Wrap(err, "UpgradeLocalDBV2 setVersion")
} }
AmountPerBoardlotInt64 := int64(AmountPerBoardlot * float64(types.Coin))
price := calcPriceOfToken(priceBoardlotInt64, AmountPerBoardlotInt64)
newkey = calcTokensBuyOrderKeyStatus(receipt.TokenSymbol, status, tradelog.Info("UpgradeLocalDBV2 upgrade done")
price, receipt.Owner, keyID) return nil
kv = append(kv, &types.KeyValue{Key: newkey, Value: value})
st, ty := fromStatus(status)
newkey = calcOnesOrderKey(receipt.Owner, st, ty, height, keyID)
kv = append(kv, &types.KeyValue{Key: newkey, Value: value})
return kv
} }
// buy limit // UpgradeLocalDBPart1 手动生成KV,需要在原有数据库中删除
func genSaveBuyLimitKv(buyOrder *pty.BuyLimitOrder) []*types.KeyValue { func UpgradeLocalDBPart1(localDB dbm.KVDB) error {
if buyOrder.PriceExec != "" && buyOrder.PriceExec != defaultPriceExec { prefixes := []string{
return nil sellOrderSHTAS,
sellOrderASTS,
sellOrderATSS,
sellOrderTSPAS,
buyOrderSHTAS,
buyOrderASTS,
buyOrderATSS,
buyOrderTSPAS,
orderASTHK,
} }
status := buyOrder.Status for _, prefix := range prefixes {
var kv []*types.KeyValue err := delOnePrefix(localDB, prefix)
kv = saveBuyLimitOrderKeyValue(kv, buyOrder, status) if err != nil {
if pty.TradeOrderStatusBoughtOut == status || pty.TradeOrderStatusBuyRevoked == status { return errors.Wrapf(err, "UpdateLocalDBPart1 delOnePrefix: %s", prefix)
tradelog.Debug("trade saveBuyLimit ", "remove old status with Buyid", buyOrder.BuyID) }
kv = deleteBuyLimitKeyValue(kv, buyOrder, pty.TradeOrderStatusOnBuy)
} }
return kv return nil
} }
func saveBuyLimitOrderKeyValue(kv []*types.KeyValue, buyOrder *pty.BuyLimitOrder, status int32) []*types.KeyValue { // delOnePrefix 删除指定前缀的记录
buyID := []byte(buyOrder.BuyID) func delOnePrefix(localDB dbm.KVDB, prefix string) error {
return genBuyLimitOrderKeyValue(kv, buyOrder, status, buyID) start := []byte(prefix)
} keys, err := localDB.List(start, nil, 0, dbm.ListASC|dbm.ListKeyOnly)
if err != nil {
if err == types.ErrNotFound {
return nil
}
return err
}
tradelog.Debug("delOnePrefix", "len", len(keys), "prefix", prefix)
for _, key := range keys {
err = localDB.Set(key, nil)
if err != nil {
return err
}
}
func deleteBuyLimitKeyValue(kv []*types.KeyValue, buyOrder *pty.BuyLimitOrder, status int32) []*types.KeyValue { return nil
return genBuyLimitOrderKeyValue(kv, buyOrder, status, nil)
} }
func genBuyLimitOrderKeyValue(kv []*types.KeyValue, buyOrder *pty.BuyLimitOrder, status int32, value []byte) []*types.KeyValue { // UpgradeLocalDBPart2 升级order
newkey := calcTokenBuyOrderKey(buyOrder.TokenSymbol, buyOrder.Address, status, buyOrder.BuyID, buyOrder.Height) // order 从 v1 升级到 v2
kv = append(kv, &types.KeyValue{Key: newkey, Value: value}) // 通过tableV1 删除, 通过tableV2 添加, 无需通过每个区块扫描对应的交易
func UpgradeLocalDBPart2(kvdb dbm.KVDB, coinSymbol string) error {
newkey = calcOnesBuyOrderKeyStatus(buyOrder.TokenSymbol, buyOrder.Address, status, buyOrder.BuyID) return upgradeOrder(kvdb, coinSymbol)
kv = append(kv, &types.KeyValue{Key: newkey, Value: value}) }
newkey = calcOnesBuyOrderKeyToken(buyOrder.TokenSymbol, buyOrder.Address, status, buyOrder.BuyID)
kv = append(kv, &types.KeyValue{Key: newkey, Value: value})
newkey = calcTokensBuyOrderKeyStatus(buyOrder.TokenSymbol, status,
calcPriceOfToken(buyOrder.PricePerBoardlot, buyOrder.AmountPerBoardlot), buyOrder.Address, buyOrder.BuyID)
kv = append(kv, &types.KeyValue{Key: newkey, Value: value})
st, ty := fromStatus(status) func upgradeOrder(kvdb dbm.KVDB, coinSymbol string) (err error) {
newkey = calcOnesOrderKey(buyOrder.Address, st, ty, buyOrder.Height, buyOrder.BuyID) tab2 := NewOrderTableV2(kvdb)
kv = append(kv, &types.KeyValue{Key: newkey, Value: value}) tab := NewOrderTable(kvdb)
q1 := tab.GetQuery(kvdb)
return kv var order1 pty.LocalOrder
} rows, err := q1.List("key", &order1, []byte(""), 0, 0)
if err != nil {
if err == types.ErrNotFound {
return nil
}
return errors.Wrap(err, "upgradeOrder list from order v1 table")
}
// sell market tradelog.Debug("upgradeOrder", "len", len(rows))
func saveSellMarketOrderKeyValue(kv []*types.KeyValue, receipt *pty.ReceiptSellBase, status int32, height int64) []*types.KeyValue { for _, row := range rows {
if receipt.PriceExec != "" && receipt.PriceExec != defaultPriceExec { o1, ok := row.Data.(*pty.LocalOrder)
return nil if !ok {
return errors.Wrap(types.ErrTypeAsset, "decode order v1")
}
o2 := types.Clone(o1).(*pty.LocalOrder)
upgradeLocalOrder(o2, coinSymbol)
err = tab2.Add(o2)
if err != nil {
return errors.Wrap(err, "upgradeOrder add to order v2 table")
}
err = tab.Del([]byte(o1.TxIndex))
if err != nil {
return errors.Wrapf(err, "upgradeOrder del from order v1 table, key: %s", o1.TxIndex)
}
} }
txhash := []byte(receipt.TxHash)
return genSellMarketOrderKeyValue(kv, receipt, status, height, txhash)
}
// delete part kvs, err := tab2.Save()
// sell limit if err != nil {
func genDeleteSellKv(sellorder *pty.SellOrder) []*types.KeyValue { return errors.Wrap(err, "upgradeOrder save-add to order v2 table")
if sellorder.PriceExec != "" && sellorder.PriceExec != defaultPriceExec {
return nil
} }
status := sellorder.Status kvs2, err := tab.Save()
var kv []*types.KeyValue if err != nil {
kv = deleteSellOrderKeyValue(kv, sellorder, status) return errors.Wrap(err, "upgradeOrder save-del to order v1 table")
if pty.TradeOrderStatusSoldOut == status || pty.TradeOrderStatusRevoked == status { }
tradelog.Debug("trade saveSell ", "remove old status onsale to soldout or revoked with sellID", sellorder.SellID) kvs = append(kvs, kvs2...)
kv = saveSellOrderKeyValue(kv, sellorder, pty.TradeOrderStatusOnSale)
for _, kv := range kvs {
tradelog.Debug("upgradeOrder", "KEY", string(kv.GetKey()))
err = kvdb.Set(kv.GetKey(), kv.GetValue())
if err != nil {
return errors.Wrapf(err, "upgradeOrder set localdb key: %s", string(kv.GetKey()))
}
} }
return kv
return nil
} }
// buy market // upgradeLocalOrder 处理两个fork前的升级数据
func deleteBuyMarketOrderKeyValue(kv []*types.KeyValue, receipt *pty.ReceiptBuyBase, status int32, height int64) []*types.KeyValue { // 1. 支持任意资产
if receipt.PriceExec != "" && receipt.PriceExec != defaultPriceExec { // 2. 支持任意资产定价
return nil func upgradeLocalOrder(order *pty.LocalOrder, coinSymbol string) {
if order.AssetExec == "" {
order.AssetExec = defaultAssetExec
}
if order.PriceExec == "" {
order.PriceExec = defaultPriceExec
order.PriceSymbol = coinSymbol
} }
return genBuyMarketOrderKeyValue(kv, receipt, status, height, nil)
} }
// buy limit // localdb Version
func genDeleteBuyLimitKv(buyOrder *pty.BuyLimitOrder) []*types.KeyValue { func getVersion(kvdb dbm.KV) (int, error) {
if buyOrder.PriceExec != "" && buyOrder.PriceExec != defaultPriceExec { value, err := kvdb.Get([]byte(tradeLocaldbVersioin))
return nil if err != nil && err != types.ErrNotFound {
return 1, err
} }
status := buyOrder.Status if err == types.ErrNotFound {
var kv []*types.KeyValue return 1, nil
kv = deleteBuyLimitKeyValue(kv, buyOrder, status)
if pty.TradeOrderStatusBoughtOut == status || pty.TradeOrderStatusBuyRevoked == status {
tradelog.Debug("trade saveSell ", "remove old status onsale to soldout or revoked with sellid", buyOrder.BuyID)
kv = saveBuyLimitOrderKeyValue(kv, buyOrder, pty.TradeOrderStatusOnBuy)
} }
return kv var v types.Int32
err = types.Decode(value, &v)
if err != nil {
return 1, err
}
return int(v.Data), nil
} }
// sell market func setVersion(kvdb dbm.KV, version int) error {
func deleteSellMarketOrderKeyValue(kv []*types.KeyValue, receipt *pty.ReceiptSellBase, status int32, height int64) []*types.KeyValue { v := types.Int32{Data: int32(version)}
if receipt.PriceExec != "" && receipt.PriceExec != defaultPriceExec { x := types.Encode(&v)
return nil return kvdb.Set([]byte(tradeLocaldbVersioin), x)
}
return genSellMarketOrderKeyValue(kv, receipt, status, height, nil)
} }
...@@ -81,23 +81,12 @@ func (t *trade) GetOnesOrderWithStatus(req *pty.ReqAddrAssets) (types.Message, e ...@@ -81,23 +81,12 @@ func (t *trade) GetOnesOrderWithStatus(req *pty.ReqAddrAssets) (types.Message, e
if len(req.FromKey) > 0 { if len(req.FromKey) > 0 {
order.TxIndex = req.FromKey order.TxIndex = req.FromKey
} }
rows, err := list(t.GetLocalDB(), "owner_isFinished", &order, req.Count, req.Direction) rows, err := listV2(t.GetLocalDB(), "owner_isFinished", &order, req.Count, req.Direction)
if err != nil { if err != nil {
tradelog.Error("GetOnesOrderWithStatus", "err", err) tradelog.Error("GetOnesOrderWithStatus", "err", err)
return nil, err return nil, err
} }
var replys pty.ReplyTradeOrders return t.toTradeOrders(rows)
cfg := t.GetAPI().GetConfig()
for _, row := range rows {
o, ok := row.Data.(*pty.LocalOrder)
if !ok {
tradelog.Error("GetOnesOrderWithStatus", "err", "bad row type")
return nil, types.ErrTypeAsset
}
reply := fmtReply(cfg, o)
replys.Orders = append(replys.Orders, reply)
}
return &replys, nil
} }
func fmtReply(cfg *types.Chain33Config, order *pty.LocalOrder) *pty.ReplyTradeOrder { func fmtReply(cfg *types.Chain33Config, order *pty.LocalOrder) *pty.ReplyTradeOrder {
...@@ -131,7 +120,7 @@ func fmtReply(cfg *types.Chain33Config, order *pty.LocalOrder) *pty.ReplyTradeOr ...@@ -131,7 +120,7 @@ func fmtReply(cfg *types.Chain33Config, order *pty.LocalOrder) *pty.ReplyTradeOr
} }
func (t *trade) GetOneOrder(req *pty.ReqAddrAssets) (types.Message, error) { func (t *trade) GetOneOrder(req *pty.ReqAddrAssets) (types.Message, error) {
query := NewOrderTable(t.GetLocalDB()) query := NewOrderTableV2(t.GetLocalDB())
tradelog.Debug("query GetData dbg", "primary", req.FromKey) tradelog.Debug("query GetData dbg", "primary", req.FromKey)
row, err := query.GetData([]byte(req.FromKey)) row, err := query.GetData([]byte(req.FromKey))
if err != nil { if err != nil {
......
package executor package executor
import ( import (
"strconv" "github.com/33cn/chain33/common/db/table"
"strings"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
pty "github.com/33cn/plugin/plugin/dapp/trade/types" pty "github.com/33cn/plugin/plugin/dapp/trade/types"
) )
// 1.8 根据token 分页显示未完成成交卖单 // 文档 1.8 根据token 分页显示未完成成交卖单
func (t *trade) Query_GetTokenSellOrderByStatus(req *pty.ReqTokenSellOrder) (types.Message, error) { func (t *trade) Query_GetTokenSellOrderByStatus(req *pty.ReqTokenSellOrder) (types.Message, error) {
return t.GetTokenSellOrderByStatus(req, req.Status) return t.GetTokenSellOrderByStatus(req, req.Status)
} }
// GetTokenSellOrderByStatus by status // GetTokenSellOrderByStatus by status
// sell & TokenSymbol & status sort by price
func (t *trade) GetTokenSellOrderByStatus(req *pty.ReqTokenSellOrder, status int32) (types.Message, error) { func (t *trade) GetTokenSellOrderByStatus(req *pty.ReqTokenSellOrder, status int32) (types.Message, error) {
return t.GetTokenOrderByStatus(true, req, status)
}
func (t *trade) GetTokenOrderByStatus(isSell bool, req *pty.ReqTokenSellOrder, status int32) (types.Message, error) {
if req.Count <= 0 || (req.Direction != 1 && req.Direction != 0) { if req.Count <= 0 || (req.Direction != 1 && req.Direction != 0) {
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
} }
fromKey := []byte("") var order pty.LocalOrder
if len(req.FromKey) != 0 { if len(req.FromKey) > 0 {
sell := t.replyReplySellOrderfromID([]byte(req.FromKey)) order.TxIndex = req.FromKey
if sell == nil {
tradelog.Error("GetTokenSellOrderByStatus", "key not exist", req.FromKey)
return nil, types.ErrInvalidParam
}
fromKey = calcTokensSellOrderKeyStatus(sell.TokenSymbol, sell.Status,
calcPriceOfToken(sell.PricePerBoardlot, sell.AmountPerBoardlot), sell.Owner, sell.Key)
} }
values, err := t.GetLocalDB().List(calcTokensSellOrderPrefixStatus(req.TokenSymbol, status), fromKey, req.Count, req.Direction)
t.setQueryAsset(&order, req.TokenSymbol)
order.IsSellOrder = isSell
order.Status = req.Status
rows, err := listV2(t.GetLocalDB(), "asset_isSell_status_price", &order, req.Count, req.Direction)
if err != nil { if err != nil {
tradelog.Error("GetOnesOrderWithStatus", "err", err)
return nil, err return nil, err
} }
var replys pty.ReplyTradeOrders
for _, key := range values { return t.toTradeOrders(rows)
reply := t.loadOrderFromKey(key)
if reply == nil {
continue
}
replys.Orders = append(replys.Orders, reply)
}
return &replys, nil
} }
// 1.3 根据token 分页显示未完成成交买单 // 1.3 根据token 分页显示未完成成交买单
...@@ -54,39 +49,18 @@ func (t *trade) Query_GetTokenBuyOrderByStatus(req *pty.ReqTokenBuyOrder) (types ...@@ -54,39 +49,18 @@ func (t *trade) Query_GetTokenBuyOrderByStatus(req *pty.ReqTokenBuyOrder) (types
} }
// GetTokenBuyOrderByStatus by status // GetTokenBuyOrderByStatus by status
// buy & TokenSymbol & status buy sort by price
func (t *trade) GetTokenBuyOrderByStatus(req *pty.ReqTokenBuyOrder, status int32) (types.Message, error) { func (t *trade) GetTokenBuyOrderByStatus(req *pty.ReqTokenBuyOrder, status int32) (types.Message, error) {
if req.Count <= 0 || (req.Direction != 1 && req.Direction != 0) {
return nil, types.ErrInvalidParam
}
fromKey := []byte("")
if len(req.FromKey) != 0 {
buy := t.replyReplyBuyOrderfromID([]byte(req.FromKey))
if buy == nil {
tradelog.Error("GetTokenBuyOrderByStatus", "key not exist", req.FromKey)
return nil, types.ErrInvalidParam
}
fromKey = calcTokensBuyOrderKeyStatus(buy.TokenSymbol, buy.Status,
calcPriceOfToken(buy.PricePerBoardlot, buy.AmountPerBoardlot), buy.Owner, buy.Key)
}
tradelog.Debug("GetTokenBuyOrderByStatus", "fromKey ", fromKey)
// List Direction 是升序, 买单是要降序, 把高价买的放前面, 在下一页操作时, 显示买价低的。 // List Direction 是升序, 买单是要降序, 把高价买的放前面, 在下一页操作时, 显示买价低的。
direction := 1 - req.Direction direction := 1 - req.Direction
values, err := t.GetLocalDB().List(calcTokensBuyOrderPrefixStatus(req.TokenSymbol, status), fromKey, req.Count, direction) req2 := pty.ReqTokenSellOrder{
if err != nil { TokenSymbol: req.TokenSymbol,
return nil, err FromKey: req.FromKey,
} Count: req.Count,
var replys pty.ReplyTradeOrders Direction: direction,
for _, key := range values { Status: req.Status,
reply := t.loadOrderFromKey(key)
if reply == nil {
continue
}
tradelog.Debug("trade Query", "getSellOrderFromID", string(key))
replys.Orders = append(replys.Orders, reply)
} }
return &replys, nil return t.GetTokenOrderByStatus(false, &req2, status)
} }
// addr part // addr part
...@@ -102,500 +76,106 @@ func (t *trade) Query_GetOnesBuyOrder(req *pty.ReqAddrAssets) (types.Message, er ...@@ -102,500 +76,106 @@ func (t *trade) Query_GetOnesBuyOrder(req *pty.ReqAddrAssets) (types.Message, er
// GetOnesSellOrder by address or address-token // GetOnesSellOrder by address or address-token
func (t *trade) GetOnesSellOrder(addrTokens *pty.ReqAddrAssets) (types.Message, error) { func (t *trade) GetOnesSellOrder(addrTokens *pty.ReqAddrAssets) (types.Message, error) {
var keys [][]byte return t.GetOnesOrder(true, addrTokens)
if 0 == len(addrTokens.Token) {
values, err := t.GetLocalDB().List(calcOnesSellOrderPrefixAddr(addrTokens.Addr), nil, 0, 0)
if err != nil {
return nil, err
}
if len(values) != 0 {
tradelog.Debug("trade Query", "get number of sellID", len(values))
keys = append(keys, values...)
}
} else {
for _, token := range addrTokens.Token {
values, err := t.GetLocalDB().List(calcOnesSellOrderPrefixToken(token, addrTokens.Addr), nil, 0, 0)
tradelog.Debug("trade Query", "Begin to list addr with token", token, "got values", len(values))
if err != nil && err != types.ErrNotFound {
return nil, err
}
if len(values) != 0 {
keys = append(keys, values...)
}
}
}
var replys pty.ReplyTradeOrders
for _, key := range keys {
reply := t.loadOrderFromKey(key)
if reply == nil {
continue
}
tradelog.Debug("trade Query", "getSellOrderFromID", string(key))
replys.Orders = append(replys.Orders, reply)
}
return &replys, nil
} }
// GetOnesBuyOrder by address or address-token // GetOnesBuyOrder by address or address-token
func (t *trade) GetOnesBuyOrder(addrTokens *pty.ReqAddrAssets) (types.Message, error) { func (t *trade) GetOnesBuyOrder(addrTokens *pty.ReqAddrAssets) (types.Message, error) {
var keys [][]byte return t.GetOnesOrder(false, addrTokens)
}
// GetOnesSellOrder by address or address-token
func (t *trade) GetOnesOrder(isSell bool, addrTokens *pty.ReqAddrAssets) (types.Message, error) {
var order pty.LocalOrder
order.Owner = addrTokens.Addr
order.IsSellOrder = isSell
if 0 == len(addrTokens.Token) { if 0 == len(addrTokens.Token) {
values, err := t.GetLocalDB().List(calcOnesBuyOrderPrefixAddr(addrTokens.Addr), nil, 0, 0) rows, err := listV2(t.GetLocalDB(), "owner_isSell", &order, 0, 0)
if err != nil { if err != nil {
tradelog.Error("GetOnesSellOrder", "err", err)
return nil, err return nil, err
} }
if len(values) != 0 { return t.toTradeOrders(rows)
tradelog.Debug("trade Query", "get number of buy keys", len(values))
keys = append(keys, values...)
}
} else {
for _, token := range addrTokens.Token {
values, err := t.GetLocalDB().List(calcOnesBuyOrderPrefixToken(token, addrTokens.Addr), nil, 0, 0)
tradelog.Debug("trade Query", "Begin to list addr with token", token, "got values", len(values))
if err != nil && err != types.ErrNotFound {
return nil, err
}
if len(values) != 0 {
keys = append(keys, values...)
}
}
} }
var replys pty.ReplyTradeOrders var replys pty.ReplyTradeOrders
for _, key := range keys { for _, token := range addrTokens.Token {
reply := t.loadOrderFromKey(key) t.setQueryAsset(&order, token)
if reply == nil { rows, err := listV2(t.GetLocalDB(), "owner_asset_isSell", &order, 0, 0)
if err != nil && err != types.ErrNotFound {
return nil, err
}
if len(rows) == 0 {
continue continue
} }
tradelog.Debug("trade Query", "getSellOrderFromID", string(key)) rs, err := t.toTradeOrders(rows)
replys.Orders = append(replys.Orders, reply) if err != nil {
} return nil, err
}
replys.Orders = append(replys.Orders, rs.Orders...)
}
return &replys, nil return &replys, nil
} }
// 1.5 没找到 // Query_GetOnesBuyOrderWithStatus 1.5 没找到
// 按 用户状态来 addr-status // 按 用户状态来 addr-status
func (t *trade) Query_GetOnesSellOrderWithStatus(req *pty.ReqAddrAssets) (types.Message, error) { func (t *trade) Query_GetOnesSellOrderWithStatus(req *pty.ReqAddrAssets) (types.Message, error) {
return t.GetOnesSellOrdersWithStatus(req) return t.GetOnesSellOrdersWithStatus(req)
} }
// 1.2 按 用户状态来 addr-status // Query_GetOnesBuyOrderWithStatus 1.2 按 用户状态来 addr-status
func (t *trade) Query_GetOnesBuyOrderWithStatus(req *pty.ReqAddrAssets) (types.Message, error) { func (t *trade) Query_GetOnesBuyOrderWithStatus(req *pty.ReqAddrAssets) (types.Message, error) {
return t.GetOnesBuyOrdersWithStatus(req) return t.GetOnesBuyOrdersWithStatus(req)
} }
// GetOnesSellOrdersWithStatus by address-status // GetOnesSellOrdersWithStatus by address-status
func (t *trade) GetOnesSellOrdersWithStatus(req *pty.ReqAddrAssets) (types.Message, error) { func (t *trade) GetOnesSellOrdersWithStatus(req *pty.ReqAddrAssets) (types.Message, error) {
var sellIDs [][]byte return t.GetOnesStatusOrder(true, req)
values, err := t.GetLocalDB().List(calcOnesSellOrderPrefixStatus(req.Addr, req.Status), nil, 0, 0)
if err != nil {
return nil, err
}
if len(values) != 0 {
tradelog.Debug("trade Query", "get number of sellID", len(values))
sellIDs = append(sellIDs, values...)
}
var replys pty.ReplyTradeOrders
for _, key := range sellIDs {
reply := t.loadOrderFromKey(key)
if reply == nil {
continue
}
tradelog.Debug("trade Query", "getSellOrderFromID", string(key))
replys.Orders = append(replys.Orders, reply)
}
return &replys, nil
} }
// GetOnesBuyOrdersWithStatus by address-status // GetOnesBuyOrdersWithStatus by address-status
func (t *trade) GetOnesBuyOrdersWithStatus(req *pty.ReqAddrAssets) (types.Message, error) { func (t *trade) GetOnesBuyOrdersWithStatus(req *pty.ReqAddrAssets) (types.Message, error) {
var sellIDs [][]byte return t.GetOnesStatusOrder(false, req)
values, err := t.GetLocalDB().List(calcOnesBuyOrderPrefixStatus(req.Addr, req.Status), nil, 0, 0)
if err != nil {
return nil, err
}
if len(values) != 0 {
tradelog.Debug("trade Query", "get number of buy keys", len(values))
sellIDs = append(sellIDs, values...)
}
var replys pty.ReplyTradeOrders
for _, key := range sellIDs {
reply := t.loadOrderFromKey(key)
if reply == nil {
continue
}
tradelog.Debug("trade Query", "getSellOrderFromID", string(key))
replys.Orders = append(replys.Orders, reply)
}
return &replys, nil
} }
// utils // GetOnesStatusOrder Get Ones Status Order
func (t *trade) loadOrderFromKey(key []byte) *pty.ReplyTradeOrder { func (t *trade) GetOnesStatusOrder(isSell bool, req *pty.ReqAddrAssets) (types.Message, error) {
tradelog.Debug("trade Query", "id", string(key), "check-prefix", sellIDPrefix) var order pty.LocalOrder
if strings.HasPrefix(string(key), sellIDPrefix) { order.Owner = req.Addr
txHash := strings.Replace(string(key), sellIDPrefix, "0x", 1) order.Status = req.Status
txResult, err := getTx([]byte(txHash), t.GetLocalDB(), t.GetAPI()) order.IsSellOrder = isSell
tradelog.Debug("loadOrderFromKey ", "load txhash", txResult)
if err != nil {
return nil
}
reply := limitOrderTxResult2Order(txResult)
sellOrder, err := getSellOrderFromID(key, t.GetStateDB()) rows, err := listV2(t.GetLocalDB(), "owner_isSell_status", &order, 0, 0)
tradelog.Debug("trade Query", "getSellOrderFromID", string(key))
if err != nil {
return nil
}
reply.TradedBoardlot = sellOrder.SoldBoardlot
reply.Status = sellOrder.Status
return reply
} else if strings.HasPrefix(string(key), buyIDPrefix) {
txHash := strings.Replace(string(key), buyIDPrefix, "0x", 1)
txResult, err := getTx([]byte(txHash), t.GetLocalDB(), t.GetAPI())
tradelog.Debug("loadOrderFromKey ", "load txhash", txResult)
if err != nil {
return nil
}
reply := limitOrderTxResult2Order(txResult)
buyOrder, err := getBuyOrderFromID(key, t.GetStateDB())
if err != nil {
return nil
}
reply.TradedBoardlot = buyOrder.BoughtBoardlot
reply.Status = buyOrder.Status
return reply
}
txResult, err := getTx(key, t.GetLocalDB(), t.GetAPI())
tradelog.Debug("loadOrderFromKey ", "load txhash", string(key))
if err != nil { if err != nil {
return nil tradelog.Error("GetOnesStatusOrder", "err", err)
} return nil, err
return txResult2OrderReply(txResult)
}
func limitOrderTxResult2Order(txResult *types.TxResult) *pty.ReplyTradeOrder {
logs := txResult.Receiptdate.Logs
tradelog.Debug("txResult2sellOrderReply", "show logs", logs)
for _, log := range logs {
if log.Ty == pty.TyLogTradeSellLimit {
var receipt pty.ReceiptTradeSellLimit
err := types.Decode(log.Log, &receipt)
if err != nil {
tradelog.Error("txResult2sellOrderReply", "decode receipt", err)
return nil
}
tradelog.Debug("txResult2sellOrderReply", "show logs 1 ", receipt)
return sellBase2Order(receipt.Base, common.ToHex(txResult.GetTx().Hash()), txResult.Blocktime)
} else if log.Ty == pty.TyLogTradeBuyLimit {
var receipt pty.ReceiptTradeBuyLimit
err := types.Decode(log.Log, &receipt)
if err != nil {
tradelog.Error("txResult2sellOrderReply", "decode receipt", err)
return nil
}
tradelog.Debug("txResult2sellOrderReply", "show logs 1 ", receipt)
return buyBase2Order(receipt.Base, common.ToHex(txResult.GetTx().Hash()), txResult.Blocktime)
}
}
return nil
}
func txResult2OrderReply(txResult *types.TxResult) *pty.ReplyTradeOrder {
logs := txResult.Receiptdate.Logs
tradelog.Debug("txResult2sellOrderReply", "show logs", logs)
for _, log := range logs {
if log.Ty == pty.TyLogTradeBuyMarket {
var receipt pty.ReceiptTradeBuyMarket
err := types.Decode(log.Log, &receipt)
if err != nil {
tradelog.Error("txResult2sellOrderReply", "decode receipt", err)
return nil
}
tradelog.Debug("txResult2sellOrderReply", "show logs 1 ", receipt)
return buyBase2Order(receipt.Base, common.ToHex(txResult.GetTx().Hash()), txResult.Blocktime)
} else if log.Ty == pty.TyLogTradeBuyRevoke {
var receipt pty.ReceiptTradeBuyRevoke
err := types.Decode(log.Log, &receipt)
if err != nil {
tradelog.Error("txResult2sellOrderReply", "decode receipt", err)
return nil
}
tradelog.Debug("txResult2sellOrderReply", "show logs 1 ", receipt)
return buyBase2Order(receipt.Base, common.ToHex(txResult.GetTx().Hash()), txResult.Blocktime)
} else if log.Ty == pty.TyLogTradeSellRevoke {
var receipt pty.ReceiptTradeSellRevoke
err := types.Decode(log.Log, &receipt)
if err != nil {
tradelog.Error("txResult2sellOrderReply", "decode receipt", err)
return nil
}
tradelog.Debug("txResult2sellOrderReply", "show revoke 1 ", receipt)
return sellBase2Order(receipt.Base, common.ToHex(txResult.GetTx().Hash()), txResult.Blocktime)
} else if log.Ty == pty.TyLogTradeSellMarket {
var receipt pty.ReceiptSellMarket
err := types.Decode(log.Log, &receipt)
if err != nil {
tradelog.Error("txResult2sellOrderReply", "decode receipt", err)
return nil
}
tradelog.Debug("txResult2sellOrderReply", "show logs 1 ", receipt)
return sellBase2Order(receipt.Base, common.ToHex(txResult.GetTx().Hash()), txResult.Blocktime)
}
}
return nil
}
// SellMarkMarket BuyMarket 没有tradeOrder 需要调用这个函数进行转化
// BuyRevoke, SellRevoke 也需要
// SellLimit/BuyLimit 有order 但order 里面没有 bolcktime, 直接访问 order 还需要再次访问 block, 还不如直接访问交易
func buyBase2Order(base *pty.ReceiptBuyBase, txHash string, blockTime int64) *pty.ReplyTradeOrder {
amount, err := strconv.ParseFloat(base.AmountPerBoardlot, 64)
if err != nil {
tradelog.Error("txResult2sellOrderReply", "decode receipt", err)
return nil
}
price, err := strconv.ParseFloat(base.PricePerBoardlot, 64)
if err != nil {
tradelog.Error("txResult2sellOrderReply", "decode receipt", err)
return nil
}
key := txHash
if len(base.BuyID) > 0 {
key = base.BuyID
}
//txhash := common.ToHex(txResult.GetTx().Hash())
reply := &pty.ReplyTradeOrder{
TokenSymbol: base.TokenSymbol,
Owner: base.Owner,
AmountPerBoardlot: int64(amount * float64(types.TokenPrecision)),
MinBoardlot: base.MinBoardlot,
PricePerBoardlot: int64(price * float64(types.Coin)),
TotalBoardlot: base.TotalBoardlot,
TradedBoardlot: base.BoughtBoardlot,
BuyID: base.BuyID,
Status: pty.SellOrderStatus2Int[base.Status],
SellID: base.SellID,
TxHash: txHash,
Height: base.Height,
Key: key,
BlockTime: blockTime,
IsSellOrder: false,
AssetExec: base.AssetExec,
}
tradelog.Debug("txResult2sellOrderReply", "show reply", reply)
return reply
}
func sellBase2Order(base *pty.ReceiptSellBase, txHash string, blockTime int64) *pty.ReplyTradeOrder {
amount, err := strconv.ParseFloat(base.AmountPerBoardlot, 64)
if err != nil {
tradelog.Error("txResult2sellOrderReply", "decode receipt", err)
return nil
}
price, err := strconv.ParseFloat(base.PricePerBoardlot, 64)
if err != nil {
tradelog.Error("txResult2sellOrderReply", "decode receipt", err)
return nil
}
//txhash := common.ToHex(txResult.GetTx().Hash())
key := txHash
if len(base.SellID) > 0 {
key = base.SellID
}
reply := &pty.ReplyTradeOrder{
TokenSymbol: base.TokenSymbol,
Owner: base.Owner,
AmountPerBoardlot: int64(amount * float64(types.TokenPrecision)),
MinBoardlot: base.MinBoardlot,
PricePerBoardlot: int64(price * float64(types.Coin)),
TotalBoardlot: base.TotalBoardlot,
TradedBoardlot: base.SoldBoardlot,
BuyID: base.BuyID,
Status: pty.SellOrderStatus2Int[base.Status],
SellID: base.SellID,
TxHash: txHash,
Height: base.Height,
Key: key,
BlockTime: blockTime,
IsSellOrder: true,
AssetExec: base.AssetExec,
}
tradelog.Debug("txResult2sellOrderReply", "show reply", reply)
return reply
}
func (t *trade) replyReplySellOrderfromID(key []byte) *pty.ReplySellOrder {
tradelog.Debug("trade Query", "id", string(key), "check-prefix", sellIDPrefix)
if strings.HasPrefix(string(key), sellIDPrefix) {
if sellorder, err := getSellOrderFromID(key, t.GetStateDB()); err == nil {
tradelog.Debug("trade Query", "getSellOrderFromID", string(key))
return sellOrder2reply(sellorder)
}
} else { // txhash as key
txResult, err := getTx(key, t.GetLocalDB(), t.GetAPI())
tradelog.Debug("GetOnesSellOrder ", "load txhash", string(key))
if err != nil {
return nil
}
return txResult2sellOrderReply(txResult)
}
return nil
}
func (t *trade) replyReplyBuyOrderfromID(key []byte) *pty.ReplyBuyOrder {
tradelog.Debug("trade Query", "id", string(key), "check-prefix", buyIDPrefix)
if strings.HasPrefix(string(key), buyIDPrefix) {
if buyOrder, err := getBuyOrderFromID(key, t.GetStateDB()); err == nil {
tradelog.Debug("trade Query", "getSellOrderFromID", string(key))
return buyOrder2reply(buyOrder)
}
} else { // txhash as key
txResult, err := getTx(key, t.GetLocalDB(), t.GetAPI())
tradelog.Debug("replyReplyBuyOrderfromID ", "load txhash", string(key))
if err != nil {
return nil
}
return txResult2buyOrderReply(txResult)
}
return nil
}
func sellOrder2reply(sellOrder *pty.SellOrder) *pty.ReplySellOrder {
reply := &pty.ReplySellOrder{
TokenSymbol: sellOrder.TokenSymbol,
Owner: sellOrder.Address,
AmountPerBoardlot: sellOrder.AmountPerBoardlot,
MinBoardlot: sellOrder.MinBoardlot,
PricePerBoardlot: sellOrder.PricePerBoardlot,
TotalBoardlot: sellOrder.TotalBoardlot,
SoldBoardlot: sellOrder.SoldBoardlot,
BuyID: "",
Status: sellOrder.Status,
SellID: sellOrder.SellID,
TxHash: strings.Replace(sellOrder.SellID, sellIDPrefix, "0x", 1),
Height: sellOrder.Height,
Key: sellOrder.SellID,
AssetExec: sellOrder.AssetExec,
}
return reply
}
func txResult2sellOrderReply(txResult *types.TxResult) *pty.ReplySellOrder {
logs := txResult.Receiptdate.Logs
tradelog.Debug("txResult2sellOrderReply", "show logs", logs)
for _, log := range logs {
if log.Ty == pty.TyLogTradeSellMarket {
var receipt pty.ReceiptSellMarket
err := types.Decode(log.Log, &receipt)
if err != nil {
tradelog.Error("txResult2sellOrderReply", "decode receipt", err)
return nil
}
tradelog.Debug("txResult2sellOrderReply", "show logs 1 ", receipt)
amount, err := strconv.ParseFloat(receipt.Base.AmountPerBoardlot, 64)
if err != nil {
tradelog.Error("txResult2sellOrderReply", "decode receipt", err)
return nil
}
price, err := strconv.ParseFloat(receipt.Base.PricePerBoardlot, 64)
if err != nil {
tradelog.Error("txResult2sellOrderReply", "decode receipt", err)
return nil
}
txhash := common.ToHex(txResult.GetTx().Hash())
reply := &pty.ReplySellOrder{
TokenSymbol: receipt.Base.TokenSymbol,
Owner: receipt.Base.Owner,
AmountPerBoardlot: int64(amount * float64(types.TokenPrecision)),
MinBoardlot: receipt.Base.MinBoardlot,
PricePerBoardlot: int64(price * float64(types.Coin)),
TotalBoardlot: receipt.Base.TotalBoardlot,
SoldBoardlot: receipt.Base.SoldBoardlot,
BuyID: receipt.Base.BuyID,
Status: pty.SellOrderStatus2Int[receipt.Base.Status],
SellID: "",
TxHash: txhash,
Height: receipt.Base.Height,
Key: txhash,
AssetExec: receipt.Base.AssetExec,
}
tradelog.Debug("txResult2sellOrderReply", "show reply", reply)
return reply
}
} }
return nil return t.toTradeOrders(rows)
} }
func buyOrder2reply(buyOrder *pty.BuyLimitOrder) *pty.ReplyBuyOrder { // util
reply := &pty.ReplyBuyOrder{ // 在老版本中,默认查询token相关的订单
TokenSymbol: buyOrder.TokenSymbol, func (t *trade) setQueryAsset(order *pty.LocalOrder, tokenSymbol string) {
Owner: buyOrder.Address, order.AssetSymbol = tokenSymbol
AmountPerBoardlot: buyOrder.AmountPerBoardlot, order.AssetExec = defaultAssetExec
MinBoardlot: buyOrder.MinBoardlot, order.PriceSymbol = t.GetAPI().GetConfig().GetCoinSymbol()
PricePerBoardlot: buyOrder.PricePerBoardlot, order.PriceExec = defaultPriceExec
TotalBoardlot: buyOrder.TotalBoardlot,
BoughtBoardlot: buyOrder.BoughtBoardlot,
BuyID: buyOrder.BuyID,
Status: buyOrder.Status,
SellID: "",
TxHash: strings.Replace(buyOrder.BuyID, buyIDPrefix, "0x", 1),
Height: buyOrder.Height,
Key: buyOrder.BuyID,
AssetExec: buyOrder.AssetExec,
}
return reply
} }
func txResult2buyOrderReply(txResult *types.TxResult) *pty.ReplyBuyOrder { // 转换数据结构, 输出前调用
logs := txResult.Receiptdate.Logs func (t *trade) toTradeOrders(rows []*table.Row) (*pty.ReplyTradeOrders, error) {
tradelog.Debug("txResult2sellOrderReply", "show logs", logs) var replys pty.ReplyTradeOrders
for _, log := range logs { cfg := t.GetAPI().GetConfig()
if log.Ty == pty.TyLogTradeBuyMarket { for _, row := range rows {
var receipt pty.ReceiptTradeBuyMarket o, ok := row.Data.(*pty.LocalOrder)
err := types.Decode(log.Log, &receipt) if !ok {
if err != nil { tradelog.Error("toTradeOrders", "err", "bad row type")
tradelog.Error("txResult2sellOrderReply", "decode receipt", err) return nil, types.ErrTypeAsset
return nil }
} reply := fmtReply(cfg, o)
tradelog.Debug("txResult2sellOrderReply", "show logs 1 ", receipt) replys.Orders = append(replys.Orders, reply)
amount, err := strconv.ParseFloat(receipt.Base.AmountPerBoardlot, 64)
if err != nil {
tradelog.Error("txResult2sellOrderReply", "decode receipt", err)
return nil
}
price, err := strconv.ParseFloat(receipt.Base.PricePerBoardlot, 64)
if err != nil {
tradelog.Error("txResult2sellOrderReply", "decode receipt", err)
return nil
}
txhash := common.ToHex(txResult.GetTx().Hash())
reply := &pty.ReplyBuyOrder{
TokenSymbol: receipt.Base.TokenSymbol,
Owner: receipt.Base.Owner,
AmountPerBoardlot: int64(amount * float64(types.TokenPrecision)),
MinBoardlot: receipt.Base.MinBoardlot,
PricePerBoardlot: int64(price * float64(types.Coin)),
TotalBoardlot: receipt.Base.TotalBoardlot,
BoughtBoardlot: receipt.Base.BoughtBoardlot,
BuyID: "",
Status: pty.SellOrderStatus2Int[receipt.Base.Status],
SellID: receipt.Base.SellID,
TxHash: txhash,
Height: receipt.Base.Height,
Key: txhash,
AssetExec: receipt.Base.AssetExec,
}
tradelog.Debug("txResult2sellOrderReply", "show reply", reply)
return reply
}
} }
return nil return &replys, nil
} }
...@@ -73,7 +73,8 @@ func (t *trade) getSellOrderFromDb(sellID []byte) *pty.SellOrder { ...@@ -73,7 +73,8 @@ func (t *trade) getSellOrderFromDb(sellID []byte) *pty.SellOrder {
return &sellorder return &sellorder
} }
func (t *trade) saveSell(base *pty.ReceiptSellBase, ty int32, tx *types.Transaction, txIndex string, ldb *table.Table) []*types.KeyValue { // sell limit
func (t *trade) saveSell(base *pty.ReceiptSellBase, ty int32, tx *types.Transaction, txIndex string, ldb *table.Table) {
sellorder := t.getSellOrderFromDb([]byte(base.SellID)) sellorder := t.getSellOrderFromDb([]byte(base.SellID))
if ty == pty.TyLogTradeSellLimit && sellorder.SoldBoardlot == 0 { if ty == pty.TyLogTradeSellLimit && sellorder.SoldBoardlot == 0 {
...@@ -83,33 +84,25 @@ func (t *trade) saveSell(base *pty.ReceiptSellBase, ty int32, tx *types.Transact ...@@ -83,33 +84,25 @@ func (t *trade) saveSell(base *pty.ReceiptSellBase, ty int32, tx *types.Transact
} else { } else {
t.updateSellLimit(tx, base, sellorder, txIndex, ldb) t.updateSellLimit(tx, base, sellorder, txIndex, ldb)
} }
return genSaveSellKv(sellorder)
} }
func (t *trade) deleteSell(base *pty.ReceiptSellBase, ty int32, tx *types.Transaction, txIndex string, ldb *table.Table, tradedBoardlot int64) []*types.KeyValue { func (t *trade) deleteSell(base *pty.ReceiptSellBase, ty int32, tx *types.Transaction, txIndex string, ldb *table.Table, tradedBoardlot int64) {
sellorder := t.getSellOrderFromDb([]byte(base.SellID)) sellorder := t.getSellOrderFromDb([]byte(base.SellID))
if ty == pty.TyLogTradeSellLimit && sellorder.SoldBoardlot == 0 { if ty == pty.TyLogTradeSellLimit && sellorder.SoldBoardlot == 0 {
ldb.Del([]byte(txIndex)) ldb.Del([]byte(txIndex))
} else { } else {
t.rollBackSellLimit(tx, base, sellorder, txIndex, ldb, tradedBoardlot) t.rollBackSellLimit(tx, base, sellorder, txIndex, ldb, tradedBoardlot)
} }
return genDeleteSellKv(sellorder)
} }
func (t *trade) saveBuy(receiptTradeBuy *pty.ReceiptBuyBase, tx *types.Transaction, txIndex string, ldb *table.Table) []*types.KeyValue { func (t *trade) saveBuy(receiptTradeBuy *pty.ReceiptBuyBase, tx *types.Transaction, txIndex string, ldb *table.Table) {
//tradelog.Info("save", "buy", receiptTradeBuy)
var kv []*types.KeyValue
order := t.genBuyMarket(tx, receiptTradeBuy, txIndex) order := t.genBuyMarket(tx, receiptTradeBuy, txIndex)
tradelog.Debug("trade BuyMarket save local", "order", order) tradelog.Debug("trade BuyMarket save local", "order", order)
ldb.Add(order) ldb.Add(order)
return saveBuyMarketOrderKeyValue(kv, receiptTradeBuy, pty.TradeOrderStatusBoughtOut, t.GetHeight())
} }
func (t *trade) deleteBuy(receiptTradeBuy *pty.ReceiptBuyBase, txIndex string, ldb *table.Table) []*types.KeyValue { func (t *trade) deleteBuy(receiptTradeBuy *pty.ReceiptBuyBase, txIndex string, ldb *table.Table) {
var kv []*types.KeyValue
ldb.Del([]byte(txIndex)) ldb.Del([]byte(txIndex))
return deleteBuyMarketOrderKeyValue(kv, receiptTradeBuy, pty.TradeOrderStatusBoughtOut, t.GetHeight())
} }
// BuyLimit Local // BuyLimit Local
...@@ -123,7 +116,7 @@ func (t *trade) getBuyOrderFromDb(buyID []byte) *pty.BuyLimitOrder { ...@@ -123,7 +116,7 @@ func (t *trade) getBuyOrderFromDb(buyID []byte) *pty.BuyLimitOrder {
return &buyOrder return &buyOrder
} }
func (t *trade) saveBuyLimit(buy *pty.ReceiptBuyBase, ty int32, tx *types.Transaction, txIndex string, ldb *table.Table) []*types.KeyValue { func (t *trade) saveBuyLimit(buy *pty.ReceiptBuyBase, ty int32, tx *types.Transaction, txIndex string, ldb *table.Table) {
buyOrder := t.getBuyOrderFromDb([]byte(buy.BuyID)) buyOrder := t.getBuyOrderFromDb([]byte(buy.BuyID))
tradelog.Debug("Table", "buy-add", buyOrder) tradelog.Debug("Table", "buy-add", buyOrder)
if buyOrder.Status == pty.TradeOrderStatusOnBuy && buy.BoughtBoardlot == 0 { if buyOrder.Status == pty.TradeOrderStatusOnBuy && buy.BoughtBoardlot == 0 {
...@@ -133,31 +126,25 @@ func (t *trade) saveBuyLimit(buy *pty.ReceiptBuyBase, ty int32, tx *types.Transa ...@@ -133,31 +126,25 @@ func (t *trade) saveBuyLimit(buy *pty.ReceiptBuyBase, ty int32, tx *types.Transa
} else { } else {
t.updateBuyLimit(tx, buy, buyOrder, txIndex, ldb) t.updateBuyLimit(tx, buy, buyOrder, txIndex, ldb)
} }
return genSaveBuyLimitKv(buyOrder)
} }
func (t *trade) deleteBuyLimit(buy *pty.ReceiptBuyBase, ty int32, tx *types.Transaction, txIndex string, ldb *table.Table, traded int64) []*types.KeyValue { func (t *trade) deleteBuyLimit(buy *pty.ReceiptBuyBase, ty int32, tx *types.Transaction, txIndex string, ldb *table.Table, traded int64) {
buyOrder := t.getBuyOrderFromDb([]byte(buy.BuyID)) buyOrder := t.getBuyOrderFromDb([]byte(buy.BuyID))
if ty == pty.TyLogTradeBuyLimit && buy.BoughtBoardlot == 0 { if ty == pty.TyLogTradeBuyLimit && buy.BoughtBoardlot == 0 {
ldb.Del([]byte(txIndex)) ldb.Del([]byte(txIndex))
} else { } else {
t.rollbackBuyLimit(tx, buy, buyOrder, txIndex, ldb, traded) t.rollbackBuyLimit(tx, buy, buyOrder, txIndex, ldb, traded)
} }
return genDeleteBuyLimitKv(buyOrder)
} }
func (t *trade) saveSellMarket(receiptTradeBuy *pty.ReceiptSellBase, tx *types.Transaction, txIndex string, ldb *table.Table) []*types.KeyValue { func (t *trade) saveSellMarket(receiptTradeBuy *pty.ReceiptSellBase, tx *types.Transaction, txIndex string, ldb *table.Table) {
var kv []*types.KeyValue
order := t.genSellMarket(tx, receiptTradeBuy, txIndex) order := t.genSellMarket(tx, receiptTradeBuy, txIndex)
ldb.Add(order) ldb.Add(order)
return saveSellMarketOrderKeyValue(kv, receiptTradeBuy, pty.TradeOrderStatusSoldOut, t.GetHeight())
} }
func (t *trade) deleteSellMarket(receiptTradeBuy *pty.ReceiptSellBase, txIndex string, ldb *table.Table) []*types.KeyValue { func (t *trade) deleteSellMarket(receiptTradeBuy *pty.ReceiptSellBase, txIndex string, ldb *table.Table) {
var kv []*types.KeyValue
ldb.Del([]byte(txIndex)) ldb.Del([]byte(txIndex))
return deleteSellMarketOrderKeyValue(kv, receiptTradeBuy, pty.TradeOrderStatusSoldOut, t.GetHeight())
} }
// CheckReceiptExecOk return true to check if receipt ty is ok // CheckReceiptExecOk return true to check if receipt ty is ok
......
...@@ -9,7 +9,6 @@ import ( ...@@ -9,7 +9,6 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/33cn/chain33/types"
pty "github.com/33cn/plugin/plugin/dapp/trade/types" pty "github.com/33cn/plugin/plugin/dapp/trade/types"
) )
...@@ -68,51 +67,11 @@ var ( ...@@ -68,51 +67,11 @@ var (
} }
) )
func init() { // TODO 几个测试数据 linter 不报错, 修改好后写测试可能需要用
func Test_Order(t *testing.T) {
} assert.NotNil(t, &sellorderOnsale)
assert.NotNil(t, &sellorderSoldOut)
// 分叉不好构造, 直接生成对应的kv 记录进行对比 assert.NotNil(t, &sellorderRevoked)
// 在save时有值的, 需要在del 时设置为空;或save 时设置为空, 在del 时有值的
func check(t *testing.T, kvSave, kvDel []*types.KeyValue) {
kvmapSave := map[string]string{}
for _, kv := range kvSave {
if string(kv.Value) != "IAMSELLID" && kv.Value != nil {
t.Error("onsale error")
}
kvmapSave[string(kv.Key)] = string(kv.Value)
}
for _, kv := range kvDel {
v, ok := kvmapSave[string(kv.Key)]
if !ok {
t.Error("error 1")
}
if len(v) == 0 && len(kv.Value) == 0 {
t.Error("error 2")
}
if len(v) != 0 && len(kv.Value) != 0 {
t.Error("error 3")
}
}
}
func TestOnsaleSaveDel(t *testing.T) {
kvOnsale := genSaveSellKv(&sellorderOnsale)
kvOnsaleDel := genDeleteSellKv(&sellorderOnsale)
check(t, kvOnsale, kvOnsaleDel)
}
func TestSoldOutSaveDel(t *testing.T) {
kv := genSaveSellKv(&sellorderSoldOut)
kvDel := genDeleteSellKv(&sellorderSoldOut)
check(t, kv, kvDel)
}
func TestRevokeSaveDel(t *testing.T) {
kv := genSaveSellKv(&sellorderRevoked)
kvDel := genDeleteSellKv(&sellorderRevoked)
check(t, kv, kvDel)
} }
func TestPriceCheck(t *testing.T) { func TestPriceCheck(t *testing.T) {
......
...@@ -12,7 +12,6 @@ import ( ...@@ -12,7 +12,6 @@ import (
"strings" "strings"
"github.com/33cn/chain33/client" "github.com/33cn/chain33/client"
"github.com/33cn/chain33/common"
dbm "github.com/33cn/chain33/common/db" dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/system/dapp" "github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
...@@ -116,27 +115,6 @@ func getSellOrderFromID(sellID []byte, db dbm.KV) (*pty.SellOrder, error) { ...@@ -116,27 +115,6 @@ func getSellOrderFromID(sellID []byte, db dbm.KV) (*pty.SellOrder, error) {
return &sellOrder, nil return &sellOrder, nil
} }
func getTx(txHash []byte, db dbm.KV, api client.QueueProtocolAPI) (*types.TxResult, error) {
hash, err := common.FromHex(string(txHash))
if err != nil {
return nil, err
}
value, err := api.QueryTx(&types.ReqHash{Hash: hash})
if err != nil {
tradelog.Error("getTx", "Failed to get value from db with getTx", string(txHash))
return nil, err
}
txResult := types.TxResult{
Height: value.Height,
Index: int32(value.Index),
Tx: value.Tx,
Receiptdate: value.Receipt,
Blocktime: value.Blocktime,
ActionName: value.ActionName,
}
return &txResult, nil
}
func (selldb *sellDB) getKVSet() (kvset []*types.KeyValue) { func (selldb *sellDB) getKVSet() (kvset []*types.KeyValue) {
value := types.Encode(&selldb.SellOrder) value := types.Encode(&selldb.SellOrder)
key := []byte(selldb.SellID) key := []byte(selldb.SellID)
......
package executor
import (
"bytes"
"testing"
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/util"
"github.com/stretchr/testify/assert"
)
func Test_Upgrade(t *testing.T) {
dir, db, localdb := util.CreateTestDB()
defer util.CloseTestDB(dir, db)
assert.NotNil(t, localdb)
// test empty db
err := callUpgradeLocalDBV2(localdb)
assert.Nil(t, err)
// test again
setVersion(localdb, 1)
err = callUpgradeLocalDBV2(localdb)
assert.Nil(t, err)
// test with data
// create for test
prefixes := []string{
sellOrderSHTAS,
sellOrderASTS,
sellOrderATSS,
sellOrderTSPAS,
buyOrderSHTAS,
buyOrderASTS,
buyOrderATSS,
buyOrderTSPAS,
orderASTHK,
}
localdb.Set([]byte(prefixes[0]+"xxxx1"), []byte("xx1"))
localdb.Set([]byte(prefixes[0]+"xxxx2"), []byte("xx2"))
localdb.Set([]byte(prefixes[0]+"xxxx3"), []byte("xx3"))
localdb.Set([]byte(prefixes[1]+"xxxx3"), []byte("xx3"))
//tabV2 := NewOrderTableV2(localdb)
tabV1 := NewOrderTable(localdb)
tabV1.Add(order1)
tabV1.Add(order2)
tabV1.Add(order3)
kvs, err := tabV1.Save()
assert.Nil(t, err)
for _, kv := range kvs {
localdb.Set(kv.Key, kv.Value)
}
// 初次升级
setVersion(localdb, 1)
err = callUpgradeLocalDBV2(localdb)
assert.Nil(t, err)
// 已经是升级后的版本了, 不需要再升级
err = callUpgradeLocalDBV2(localdb)
assert.Nil(t, err)
// 先修改版本去升级,但数据已经升级了, 所以处理数据量为0
setVersion(localdb, 1)
err = callUpgradeLocalDBV2(localdb)
assert.Nil(t, err)
// just print log
//assert.NotNil(t, nil)
}
func callUpgradeLocalDBV2(localdb dbm.KVDB) error {
return UpgradeLocalDBV2(localdb, "bty")
}
// 测试更新后是否删除完全, asset 设置
func Test_UpgradeOrderAsset(t *testing.T) {
dir, db, localdb := util.CreateTestDB()
defer util.CloseTestDB(dir, db)
assert.NotNil(t, localdb)
tabV1 := NewOrderTable(localdb)
tabV1.Add(order3)
kvs, err := tabV1.Save()
assert.Nil(t, err)
for _, kv := range kvs {
localdb.Set(kv.Key, kv.Value)
}
err = callUpgradeLocalDBV2(localdb)
assert.Nil(t, err)
v1, err := localdb.List([]byte("LODB-trade-order"), nil, 0, dbm.ListASC|dbm.ListWithKey)
assert.Nil(t, err)
assert.NotNil(t, v1)
primaryKey := "000000000000300001"
prefix := "LODB-trade-order_v2"
for _, v := range v1 {
var kv types.KeyValue
err := types.Decode(v, &kv)
assert.Nil(t, err)
// 前缀都是v2, 删除完成测试
if !bytes.Equal([]byte("LODB-trade-order_v2-d-000000000000300001"), kv.Key) {
assert.Equal(t, []byte(primaryKey), kv.Value)
assert.True(t, bytes.HasPrefix(kv.Key, []byte(prefix)))
}
}
// assert 前缀测试
v, err := localdb.Get([]byte("LODB-trade-order_v2-m-asset-coins.bty_token.CCNY-000000000000300001"))
assert.Nil(t, err)
assert.Equal(t, primaryKey, string(v))
// just print log
//assert.NotNil(t, nil)
}
...@@ -437,7 +437,7 @@ func (mvccs *KVMVCCStore) GetHashRdm(hash []byte, height int64) ([]byte, error) ...@@ -437,7 +437,7 @@ func (mvccs *KVMVCCStore) GetHashRdm(hash []byte, height int64) ([]byte, error)
func (mvccs *KVMVCCStore) GetFirstHashRdm(hash []byte) ([]byte, error) { func (mvccs *KVMVCCStore) GetFirstHashRdm(hash []byte) ([]byte, error) {
prefix := append(rdmHashPrefix, hash...) prefix := append(rdmHashPrefix, hash...)
list := dbm.NewListHelper(mvccs.db) list := dbm.NewListHelper(mvccs.db)
values := list.IteratorScanFromFirst(prefix, 1) values := list.IteratorScanFromFirst(prefix, 1, dbm.ListASC)
if len(values) == 1 { if len(values) == 1 {
return values[0], nil return values[0], nil
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment