Skip to content

Commit

Permalink
Add Time() to Prefix and thus all orders,
Browse files Browse the repository at this point in the history
Tweak UTXO interface so TxHash() matches asset package.

Add UTXO data to tests, and include Force.

Specify that BaseAsset and QuoteAsset MUST be 0 in a CancelOrder,
although order validation is not implemented here.
  • Loading branch information
chappjc committed Aug 29, 2019
1 parent f11a188 commit bf1bd30
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 43 deletions.
13 changes: 9 additions & 4 deletions server/market/order/order.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func calcOrderID(order Order) OrderID {
// UTXO is the interface required to be satisfied by any asset's implementation
// of a UTXO type.
type UTXO interface {
TxHash() string
TxHash() []byte
Vout() uint32
Serialize() []byte
SerializeSize() int
Expand All @@ -94,8 +94,8 @@ type UTXO interface {
// Prefix is the order prefix containing data fields common to all orders.
type Prefix struct {
AccountID account.AccountID
BaseAsset uint32 // unused for CancelOrder?
QuoteAsset uint32 // unused for CancelOrder
BaseAsset uint32 // must be 0 for CancelOrder
QuoteAsset uint32 // must be 0 for CancelOrder
OrderType OrderType
ClientTime time.Time
ServerTime time.Time
Expand All @@ -109,6 +109,11 @@ func (p *Prefix) SerializeSize() int {
return PrefixLen
}

// Time returns the order prefix's server time as a UNIX epoch time.
func (p *Prefix) Time() int64 {
return p.ServerTime.Unix()
}

// Serialize marshals the Prefix into a []byte.
// TODO: Deserialize.
func (p *Prefix) Serialize() []byte {
Expand Down Expand Up @@ -317,5 +322,5 @@ func (o *CancelOrder) Remaining() uint64 {
return 0
}

// Ensure LimitOrder is an Order.
// Ensure CancelOrder is an Order.
var _ Order = (*CancelOrder)(nil)
149 changes: 110 additions & 39 deletions server/market/order/order_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package order

import (
"encoding/binary"
"encoding/hex"
"reflect"
"testing"
Expand All @@ -23,11 +24,49 @@ var acct0 = account.AccountID{
0x46, 0x34, 0xe9, 0x1c, 0xec, 0x25, 0xd5, 0x40,
}

// var acctX = account.AccountID{
// 0x12, 0x4c, 0xba, 0xaa, 0xfa, 0x80, 0xbf, 0x3b, 0xd1, 0xff, 0x73, 0x15,
// 0x90, 0xbc, 0xbd, 0xda, 0x5a, 0x76, 0xf9, 0x1e, 0x60, 0xa1, 0x56, 0x99,
// 0x46, 0x34, 0xe9, 0x1c, 0xec, 0x25, 0xd5, 0x41,
// }

const (
AssetDCR uint32 = iota
AssetBTC
)

type utxo struct {
txHash []byte
vout uint32
}

func (u *utxo) Serialize() []byte {
b := make([]byte, u.SerializeSize())
copy(b, u.txHash)
binary.LittleEndian.PutUint32(b[len(u.txHash):], u.vout)
return b
}

func (u *utxo) SerializeSize() int {
return len(u.txHash) + 4
}

func (u *utxo) TxHash() []byte {
return u.txHash
}

func (u *utxo) Vout() uint32 {
return u.vout
}

func newUtxo(txid string, vout uint32) *utxo {
hash, err := hex.DecodeString(txid)
if err != nil {
panic(err)
}
return &utxo{hash, vout}
}

func TestPrefix_Serialize(t *testing.T) {
type fields struct {
AccountID account.AccountID
Expand Down Expand Up @@ -83,7 +122,7 @@ func TestPrefix_Serialize(t *testing.T) {
}
}

func TestMarketOrder_Serialize(t *testing.T) {
func TestMarketOrder_Serialize_SerializeSize(t *testing.T) {
type fields struct {
Prefix Prefix
UTXOs []UTXO
Expand All @@ -107,22 +146,29 @@ func TestMarketOrder_Serialize(t *testing.T) {
ClientTime: time.Unix(1566497653, 0),
ServerTime: time.Unix(1566497656, 0),
},
UTXOs: []UTXO{},
UTXOs: []UTXO{
newUtxo("aed8e9b2b889bf0a78e559684796800144cd76dc8faac2aeac44fbd1c310124b", 1),
newUtxo("45b82138ca90e665a1c8793aa901aa232dd82be41b8e630dd621f24e717fc13a", 2),
},
Sell: false,
Quantity: 132413241324,
Address: "DcqXswjTPnUcd4FRCkX4vRJxmVtfgGVa5ui",
},
[]byte{0x22, 0x4c, 0xba, 0xaa, 0xfa, 0x80, 0xbf, 0x3b, 0xd1, 0xff,
0x73, 0x15, 0x90, 0xbc, 0xbd, 0xda, 0x5a, 0x76, 0xf9, 0x1e,
0x60, 0xa1, 0x56, 0x99, 0x46, 0x34, 0xe9, 0x1c, 0xec, 0x25,
0xd5, 0x40, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
0x1, 0x75, 0xdb, 0x5e, 0x5d, 0x0, 0x0, 0x0, 0x0, 0x78,
0xdb, 0x5e, 0x5d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xec,
0xb7, 0x71, 0xd4, 0x1e, 0x0, 0x0, 0x0, 0x44, 0x63, 0x71,
0x58, 0x73, 0x77, 0x6a, 0x54, 0x50, 0x6e, 0x55, 0x63, 0x64,
0x34, 0x46, 0x52, 0x43, 0x6b, 0x58, 0x34, 0x76, 0x52, 0x4a,
0x78, 0x6d, 0x56, 0x74, 0x66, 0x67, 0x47, 0x56, 0x61, 0x35,
0x75, 0x69},
[]byte{0x22, 0x4c, 0xba, 0xaa, 0xfa, 0x80, 0xbf, 0x3b, 0xd1, 0xff, 0x73, 0x15,
0x90, 0xbc, 0xbd, 0xda, 0x5a, 0x76, 0xf9, 0x1e, 0x60, 0xa1, 0x56, 0x99,
0x46, 0x34, 0xe9, 0x1c, 0xec, 0x25, 0xd5, 0x40, 0x0, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0x1, 0x75, 0xdb, 0x5e, 0x5d, 0x0, 0x0, 0x0,
0x0, 0x78, 0xdb, 0x5e, 0x5d, 0x0, 0x0, 0x0, 0x0, 0x2, 0xae, 0xd8,
0xe9, 0xb2, 0xb8, 0x89, 0xbf, 0xa, 0x78, 0xe5, 0x59, 0x68, 0x47, 0x96,
0x80, 0x1, 0x44, 0xcd, 0x76, 0xdc, 0x8f, 0xaa, 0xc2, 0xae, 0xac, 0x44,
0xfb, 0xd1, 0xc3, 0x10, 0x12, 0x4b, 0x1, 0x0, 0x0, 0x0, 0x45, 0xb8,
0x21, 0x38, 0xca, 0x90, 0xe6, 0x65, 0xa1, 0xc8, 0x79, 0x3a, 0xa9, 0x1,
0xaa, 0x23, 0x2d, 0xd8, 0x2b, 0xe4, 0x1b, 0x8e, 0x63, 0xd, 0xd6, 0x21,
0xf2, 0x4e, 0x71, 0x7f, 0xc1, 0x3a, 0x2, 0x0, 0x0, 0x0, 0x0, 0xec,
0xb7, 0x71, 0xd4, 0x1e, 0x0, 0x0, 0x0, 0x44, 0x63, 0x71, 0x58, 0x73,
0x77, 0x6a, 0x54, 0x50, 0x6e, 0x55, 0x63, 0x64, 0x34, 0x46, 0x52, 0x43,
0x6b, 0x58, 0x34, 0x76, 0x52, 0x4a, 0x78, 0x6d, 0x56, 0x74, 0x66, 0x67,
0x47, 0x56, 0x61, 0x35, 0x75, 0x69},
},
}
for _, tt := range tests {
Expand All @@ -147,7 +193,7 @@ func TestMarketOrder_Serialize(t *testing.T) {
}
}

func TestLimitOrder_Serialize(t *testing.T) {
func TestLimitOrder_Serialize_SerializeSize(t *testing.T) {
type fields struct {
MarketOrder MarketOrder
Rate float64
Expand All @@ -170,33 +216,41 @@ func TestLimitOrder_Serialize(t *testing.T) {
ClientTime: time.Unix(1566497653, 0),
ServerTime: time.Unix(1566497656, 0),
},
UTXOs: []UTXO{},
UTXOs: []UTXO{
newUtxo("d186e4b6625c9c94797cc494f535fc150177e0619e2303887e0a677f29ef1bab", 0),
newUtxo("11d9580e19ad65a875a5bc558d600e96b2916062db9e8b65cbc2bb905207c1ad", 16),
},
Sell: false,
Quantity: 132413241324,
Address: "DcqXswjTPnUcd4FRCkX4vRJxmVtfgGVa5ui",
},
Rate: 0.13241324,
Force: StandingTiF,
},
[]byte{0x22, 0x4c, 0xba, 0xaa, 0xfa, 0x80, 0xbf, 0x3b, 0xd1, 0xff,
0x73, 0x15, 0x90, 0xbc, 0xbd, 0xda, 0x5a, 0x76, 0xf9, 0x1e,
0x60, 0xa1, 0x56, 0x99, 0x46, 0x34, 0xe9, 0x1c, 0xec, 0x25,
0xd5, 0x40, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0,
0x0, 0x75, 0xdb, 0x5e, 0x5d, 0x0, 0x0, 0x0, 0x0, 0x78,
0xdb, 0x5e, 0x5d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xec,
0xb7, 0x71, 0xd4, 0x1e, 0x0, 0x0, 0x0, 0x44, 0x63, 0x71,
0x58, 0x73, 0x77, 0x6a, 0x54, 0x50, 0x6e, 0x55, 0x63, 0x64,
0x34, 0x46, 0x52, 0x43, 0x6b, 0x58, 0x34, 0x76, 0x52, 0x4a,
0x78, 0x6d, 0x56, 0x74, 0x66, 0x67, 0x47, 0x56, 0x61, 0x35,
0x75, 0x69, 0x40, 0xbf, 0xad, 0xc3, 0xea, 0xf2, 0xc0, 0x3f,
0x0},
[]byte{0x22, 0x4c, 0xba, 0xaa, 0xfa, 0x80, 0xbf, 0x3b, 0xd1, 0xff, 0x73, 0x15,
0x90, 0xbc, 0xbd, 0xda, 0x5a, 0x76, 0xf9, 0x1e, 0x60, 0xa1, 0x56, 0x99,
0x46, 0x34, 0xe9, 0x1c, 0xec, 0x25, 0xd5, 0x40, 0x0, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0x0, 0x75, 0xdb, 0x5e, 0x5d, 0x0, 0x0, 0x0,
0x0, 0x78, 0xdb, 0x5e, 0x5d, 0x0, 0x0, 0x0, 0x0, 0x2, 0xd1, 0x86,
0xe4, 0xb6, 0x62, 0x5c, 0x9c, 0x94, 0x79, 0x7c, 0xc4, 0x94, 0xf5, 0x35,
0xfc, 0x15, 0x1, 0x77, 0xe0, 0x61, 0x9e, 0x23, 0x3, 0x88, 0x7e, 0xa,
0x67, 0x7f, 0x29, 0xef, 0x1b, 0xab, 0x0, 0x0, 0x0, 0x0, 0x11, 0xd9,
0x58, 0xe, 0x19, 0xad, 0x65, 0xa8, 0x75, 0xa5, 0xbc, 0x55, 0x8d, 0x60,
0xe, 0x96, 0xb2, 0x91, 0x60, 0x62, 0xdb, 0x9e, 0x8b, 0x65, 0xcb, 0xc2,
0xbb, 0x90, 0x52, 0x7, 0xc1, 0xad, 0x10, 0x0, 0x0, 0x0, 0x0, 0xec,
0xb7, 0x71, 0xd4, 0x1e, 0x0, 0x0, 0x0, 0x44, 0x63, 0x71, 0x58, 0x73,
0x77, 0x6a, 0x54, 0x50, 0x6e, 0x55, 0x63, 0x64, 0x34, 0x46, 0x52, 0x43,
0x6b, 0x58, 0x34, 0x76, 0x52, 0x4a, 0x78, 0x6d, 0x56, 0x74, 0x66, 0x67,
0x47, 0x56, 0x61, 0x35, 0x75, 0x69, 0x40, 0xbf, 0xad, 0xc3, 0xea, 0xf2,
0xc0, 0x3f, 0x1},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
o := &LimitOrder{
MarketOrder: tt.fields.MarketOrder,
Rate: tt.fields.Rate,
Force: tt.fields.Force,
}
got := o.Serialize()
if !reflect.DeepEqual(got, tt.want) {
Expand Down Expand Up @@ -267,7 +321,7 @@ func TestCancelOrder_Serialize(t *testing.T) {
}

func TestMarketOrder_ID(t *testing.T) {
orderID0, _ := hex.DecodeString("5e68ca2f5c9d31e1e4d61d92e2c427969ac6bd6a99830774efbd3e35fc1405d0")
orderID0, _ := hex.DecodeString("93f565294da3e939f90b1d41288c55dfd21d2f5947001942a9773fd627b5dfbe")
var orderID OrderID
copy(orderID[:], orderID0)

Expand All @@ -294,8 +348,10 @@ func TestMarketOrder_ID(t *testing.T) {
ClientTime: time.Unix(1566497653, 0),
ServerTime: time.Unix(1566497656, 0),
},
UTXOs: []UTXO{},
Sell: false,
UTXOs: []UTXO{
newUtxo("a985d8df97571b130ce30a049a76ffedaa79b6e69b173ff81b1bf9fc07f063c7", 1),
},
Sell: true,
Quantity: 132413241324,
Address: "DcqXswjTPnUcd4FRCkX4vRJxmVtfgGVa5ui",
},
Expand All @@ -311,15 +367,20 @@ func TestMarketOrder_ID(t *testing.T) {
Quantity: tt.fields.Quantity,
Address: tt.fields.Address,
}
remaining := o.Remaining()
if remaining != o.Quantity-o.Filled {
t.Errorf("MarketOrder.Remaining incorrect, got %d, expected %d",
remaining, o.Quantity-o.Filled)
}
if got := o.ID(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("MarketOrder.ID() = %x, want %x", got, tt.want)
t.Errorf("MarketOrder.ID() = %v, want %v", got, tt.want)
}
})
}
}

func TestLimitOrder_ID(t *testing.T) {
orderID0, _ := hex.DecodeString("0e41e1122fb63c84335547f1eb829844ab8e41a804f97201b2b5ddbdf4174850")
orderID0, _ := hex.DecodeString("9158e76a36999a0f5194dd30fb6f01508355d213defc08e9c11b8d8efe9afbe1")
var orderID OrderID
copy(orderID[:], orderID0)

Expand All @@ -345,7 +406,9 @@ func TestLimitOrder_ID(t *testing.T) {
ClientTime: time.Unix(1566497653, 0),
ServerTime: time.Unix(1566497656, 0),
},
UTXOs: []UTXO{},
UTXOs: []UTXO{
newUtxo("01516d9c7ffbe260b811dc04462cedd3f8969ce3a3ffe6231ae870775a92e9b0", 1),
},
Sell: false,
Quantity: 132413241324,
Address: "DcqXswjTPnUcd4FRCkX4vRJxmVtfgGVa5ui",
Expand All @@ -361,20 +424,26 @@ func TestLimitOrder_ID(t *testing.T) {
o := &LimitOrder{
MarketOrder: tt.fields.MarketOrder,
Rate: tt.fields.Rate,
Force: tt.fields.Force,
}
remaining := o.Remaining()
if remaining != o.Quantity-o.Filled {
t.Errorf("LimitOrder.Remaining incorrect, got %d, expected %d",
remaining, o.Quantity-o.Filled)
}
if got := o.ID(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("LimitOrder.ID() = %x, want %x", got, tt.want)
t.Errorf("LimitOrder.ID() = %v, want %v", got, tt.want)
}
})
}
}

func TestCancelOrder_ID(t *testing.T) {
limitOrderID0, _ := hex.DecodeString("0e41e1122fb63c84335547f1eb829844ab8e41a804f97201b2b5ddbdf4174850")
limitOrderID0, _ := hex.DecodeString("9158e76a36999a0f5194dd30fb6f01508355d213defc08e9c11b8d8efe9afbe1")
var limitOrderID OrderID
copy(limitOrderID[:], limitOrderID0)

orderID0, _ := hex.DecodeString("61632e28f841581b811ec995e8f7e3738d7e45a87c354719760bf29c4861449c")
orderID0, _ := hex.DecodeString("84733c6860a373f67a5c63fc124240a6635b8a99cda0f3b9ddfe6c5c8175792e")
var orderID OrderID
copy(orderID[:], orderID0)

Expand All @@ -392,8 +461,6 @@ func TestCancelOrder_ID(t *testing.T) {
fields{
Prefix: Prefix{
AccountID: acct0,
BaseAsset: AssetDCR,
QuoteAsset: AssetBTC,
OrderType: CancelOrderType,
ClientTime: time.Unix(1566497693, 0),
ServerTime: time.Unix(1566497696, 0),
Expand All @@ -409,8 +476,12 @@ func TestCancelOrder_ID(t *testing.T) {
Prefix: tt.fields.Prefix,
TargetOrderID: tt.fields.TargetOrderID,
}
remaining := o.Remaining()
if remaining != 0 {
t.Errorf("CancelOrder.Remaining should be 0, got %d", remaining)
}
if got := o.ID(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("CancelOrder.ID() = %x, want %x", got, tt.want)
t.Errorf("CancelOrder.ID() = %v, want %v", got, tt.want)
}
})
}
Expand Down

0 comments on commit bf1bd30

Please sign in to comment.