Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
plugin
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
link33
plugin
Commits
3ffe72e7
Commit
3ffe72e7
authored
Dec 23, 2019
by
harrylee
Committed by
vipwzw
Dec 26, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ajust code for exchange
parent
f28a7e39
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
476 additions
and
431 deletions
+476
-431
README.md
plugin/dapp/exchange/executor/README.md
+20
-0
exchange.go
plugin/dapp/exchange/executor/exchange.go
+1
-1
exchange_test.go
plugin/dapp/exchange/executor/exchange_test.go
+19
-24
exchangedb.go
plugin/dapp/exchange/executor/exchangedb.go
+223
-161
exec_local.go
plugin/dapp/exchange/executor/exec_local.go
+133
-171
query.go
plugin/dapp/exchange/executor/query.go
+2
-5
tables.go
plugin/dapp/exchange/executor/tables.go
+2
-2
exchange.proto
plugin/dapp/exchange/proto/exchange.proto
+9
-7
exchange.go
plugin/dapp/exchange/types/exchange.go
+2
-2
exchange.pb.go
plugin/dapp/exchange/types/exchange.pb.go
+65
-58
No files found.
plugin/dapp/exchange/executor/README.md
View file @
3ffe72e7
...
@@ -28,3 +28,23 @@ QueryOrderList|根据用户地址和订单状态(ordered,completed,revoked),
...
@@ -28,3 +28,23 @@ QueryOrderList|根据用户地址和订单状态(ordered,completed,revoked),
4|价格相同按先进先出的原则进行撮合
4|价格相同按先进先出的原则进行撮合
5|出于系统安全考虑,最大撮合深度为100单,单笔挂单最小为1e8,就是一个bty
5|出于系统安全考虑,最大撮合深度为100单,单笔挂单最小为1e8,就是一个bty
**表结构说明**
表名|主键|索引|用途|说明
---|---|---|---|---
depth|price|nil|动态记录市场深度|主键price是复合主键由{leftAsset}:{rightAsset}:{op}:{price}构成
order|orderID|market_order,addr_status|实时动态维护更新市场上的挂单|market_order是复合索引由{leftAsset}:{rightAsset}:{op}:{price}:{orderID},addr_status是复合索引由{addr}:{status},当订单成交或者撤回时,该条订单记录和索引会从order表中自动删除
history|index|name,addr_status|实时记录某资产交易对下面最新完成的订单信息(revoked状态的交易也会记录)|name是复合索引由{leftAsset}:{rightAsset}构成, addr_status是复合索引由{addr}:{status}
**表中相关参数说明**
参数名|说明
----|----
leftAsset|交易对左边资产名称
rightAsset|交易对右边资产名称
op|买卖操作 1为买,2为卖
status|挂单状态,0 ordered, 1 completed,2 revoked
price|挂单价格,占位16 %016d,为了兼容不同架构的系统,这里设计为整型,由原有浮点型乘以1e8。 比如某交易对在中心化交易所上面是0.25,这里就变成25000000,price取值范围为1<=price<=1e16的整数
orderID|单号,由系统自动生成,整型,占位22 %022d
index|系统自动生成的index,占位22 %022d
plugin/dapp/exchange/executor/exchange.go
View file @
3ffe72e7
...
@@ -60,7 +60,7 @@ func (e *exchange) CheckTx(tx *types.Transaction, index int) error {
...
@@ -60,7 +60,7 @@ func (e *exchange) CheckTx(tx *types.Transaction, index int) error {
limitOrder
:=
exchange
.
GetLimitOrder
()
limitOrder
:=
exchange
.
GetLimitOrder
()
left
:=
limitOrder
.
GetLeftAsset
()
left
:=
limitOrder
.
GetLeftAsset
()
right
:=
limitOrder
.
GetRightAsset
()
right
:=
limitOrder
.
GetRightAsset
()
price
:=
Truncate
(
limitOrder
.
GetPrice
()
)
price
:=
limitOrder
.
GetPrice
(
)
amount
:=
limitOrder
.
GetAmount
()
amount
:=
limitOrder
.
GetAmount
()
op
:=
limitOrder
.
GetOp
()
op
:=
limitOrder
.
GetOp
()
if
!
CheckExchangeAsset
(
left
,
right
)
{
if
!
CheckExchangeAsset
(
left
,
right
)
{
...
...
plugin/dapp/exchange/executor/exchange_test.go
View file @
3ffe72e7
...
@@ -105,7 +105,7 @@ func TestExchange(t *testing.T) {
...
@@ -105,7 +105,7 @@ func TestExchange(t *testing.T) {
tx
,
err
=
types
.
FormatTx
(
cfg
,
et
.
ExchangeX
,
tx
)
tx
,
err
=
types
.
FormatTx
(
cfg
,
et
.
ExchangeX
,
tx
)
assert
.
Nil
(
t
,
err
)
assert
.
Nil
(
t
,
err
)
tx
,
err
=
signTx
(
tx
,
PrivKeyA
)
tx
,
err
=
signTx
(
tx
,
PrivKeyA
)
t
.
Log
(
tx
)
//
t.Log(tx)
assert
.
Nil
(
t
,
err
)
assert
.
Nil
(
t
,
err
)
exec
:=
newExchange
()
exec
:=
newExchange
()
e
:=
exec
.
(
*
exchange
)
e
:=
exec
.
(
*
exchange
)
...
@@ -317,7 +317,7 @@ func TestExchange(t *testing.T) {
...
@@ -317,7 +317,7 @@ func TestExchange(t *testing.T) {
//反向测试
//反向测试
// orderlimit bty:CCNY 卖bty
// orderlimit bty:CCNY 卖bty
tx
,
err
=
ety
.
Create
(
"LimitOrder"
,
&
et
.
LimitOrder
{
LeftAsset
:
&
et
.
Asset
{
Symbol
:
"bty"
,
Execer
:
"coins"
},
tx
,
err
=
ety
.
Create
(
"LimitOrder"
,
&
et
.
LimitOrder
{
LeftAsset
:
&
et
.
Asset
{
Symbol
:
"bty"
,
Execer
:
"coins"
},
RightAsset
:
&
et
.
Asset
{
Execer
:
"paracross"
,
Symbol
:
"coins.bty"
},
Price
:
0.5
,
Amount
:
10
*
types
.
Coin
,
Op
:
et
.
OpSell
})
RightAsset
:
&
et
.
Asset
{
Execer
:
"paracross"
,
Symbol
:
"coins.bty"
},
Price
:
50000000
,
Amount
:
10
*
types
.
Coin
,
Op
:
et
.
OpSell
})
assert
.
Nil
(
t
,
err
)
assert
.
Nil
(
t
,
err
)
tx
,
err
=
types
.
FormatTx
(
cfg
,
et
.
ExchangeX
,
tx
)
tx
,
err
=
types
.
FormatTx
(
cfg
,
et
.
ExchangeX
,
tx
)
assert
.
Nil
(
t
,
err
)
assert
.
Nil
(
t
,
err
)
...
@@ -365,7 +365,7 @@ func TestExchange(t *testing.T) {
...
@@ -365,7 +365,7 @@ func TestExchange(t *testing.T) {
t
.
Log
(
reply
)
t
.
Log
(
reply
)
tx
,
err
=
ety
.
Create
(
"LimitOrder"
,
&
et
.
LimitOrder
{
LeftAsset
:
&
et
.
Asset
{
Symbol
:
"bty"
,
Execer
:
"coins"
},
tx
,
err
=
ety
.
Create
(
"LimitOrder"
,
&
et
.
LimitOrder
{
LeftAsset
:
&
et
.
Asset
{
Symbol
:
"bty"
,
Execer
:
"coins"
},
RightAsset
:
&
et
.
Asset
{
Execer
:
"paracross"
,
Symbol
:
"coins.bty"
},
Price
:
0.5
,
Amount
:
10
*
types
.
Coin
,
Op
:
et
.
OpSell
})
RightAsset
:
&
et
.
Asset
{
Execer
:
"paracross"
,
Symbol
:
"coins.bty"
},
Price
:
50000000
,
Amount
:
10
*
types
.
Coin
,
Op
:
et
.
OpSell
})
assert
.
Nil
(
t
,
err
)
assert
.
Nil
(
t
,
err
)
tx
,
err
=
types
.
FormatTx
(
cfg
,
et
.
ExchangeX
,
tx
)
tx
,
err
=
types
.
FormatTx
(
cfg
,
et
.
ExchangeX
,
tx
)
assert
.
Nil
(
t
,
err
)
assert
.
Nil
(
t
,
err
)
...
@@ -434,7 +434,7 @@ func TestExchange(t *testing.T) {
...
@@ -434,7 +434,7 @@ func TestExchange(t *testing.T) {
assert
.
Equal
(
t
,
orderID4
,
reply2
.
List
[
0
]
.
OrderID
)
assert
.
Equal
(
t
,
orderID4
,
reply2
.
List
[
0
]
.
OrderID
)
tx
,
err
=
ety
.
Create
(
"LimitOrder"
,
&
et
.
LimitOrder
{
LeftAsset
:
&
et
.
Asset
{
Symbol
:
"bty"
,
Execer
:
"coins"
},
tx
,
err
=
ety
.
Create
(
"LimitOrder"
,
&
et
.
LimitOrder
{
LeftAsset
:
&
et
.
Asset
{
Symbol
:
"bty"
,
Execer
:
"coins"
},
RightAsset
:
&
et
.
Asset
{
Execer
:
"paracross"
,
Symbol
:
"coins.bty"
},
Price
:
0.5
,
Amount
:
20
*
types
.
Coin
,
Op
:
et
.
OpBuy
})
RightAsset
:
&
et
.
Asset
{
Execer
:
"paracross"
,
Symbol
:
"coins.bty"
},
Price
:
50000000
,
Amount
:
20
*
types
.
Coin
,
Op
:
et
.
OpBuy
})
assert
.
Nil
(
t
,
err
)
assert
.
Nil
(
t
,
err
)
tx
,
err
=
types
.
FormatTx
(
cfg
,
et
.
ExchangeX
,
tx
)
tx
,
err
=
types
.
FormatTx
(
cfg
,
et
.
ExchangeX
,
tx
)
assert
.
Nil
(
t
,
err
)
assert
.
Nil
(
t
,
err
)
...
@@ -504,7 +504,7 @@ func TestExchange(t *testing.T) {
...
@@ -504,7 +504,7 @@ func TestExchange(t *testing.T) {
// orderlimit bty:CCNY ,先挂买单,然后低于市场价格卖出
// orderlimit bty:CCNY ,先挂买单,然后低于市场价格卖出
tx
,
err
=
ety
.
Create
(
"LimitOrder"
,
&
et
.
LimitOrder
{
LeftAsset
:
&
et
.
Asset
{
Symbol
:
"bty"
,
Execer
:
"coins"
},
tx
,
err
=
ety
.
Create
(
"LimitOrder"
,
&
et
.
LimitOrder
{
LeftAsset
:
&
et
.
Asset
{
Symbol
:
"bty"
,
Execer
:
"coins"
},
RightAsset
:
&
et
.
Asset
{
Execer
:
"token"
,
Symbol
:
"CCNY"
},
Price
:
4
,
Amount
:
5
*
types
.
Coin
,
Op
:
et
.
OpBuy
})
RightAsset
:
&
et
.
Asset
{
Execer
:
"token"
,
Symbol
:
"CCNY"
},
Price
:
4
00000000
,
Amount
:
5
*
types
.
Coin
,
Op
:
et
.
OpBuy
})
assert
.
Nil
(
t
,
err
)
assert
.
Nil
(
t
,
err
)
tx
,
err
=
types
.
FormatTx
(
cfg
,
et
.
ExchangeX
,
tx
)
tx
,
err
=
types
.
FormatTx
(
cfg
,
et
.
ExchangeX
,
tx
)
assert
.
Nil
(
t
,
err
)
assert
.
Nil
(
t
,
err
)
...
@@ -555,7 +555,7 @@ func TestExchange(t *testing.T) {
...
@@ -555,7 +555,7 @@ func TestExchange(t *testing.T) {
}
}
tx
,
err
=
ety
.
Create
(
"LimitOrder"
,
&
et
.
LimitOrder
{
LeftAsset
:
&
et
.
Asset
{
Symbol
:
"bty"
,
Execer
:
"coins"
},
tx
,
err
=
ety
.
Create
(
"LimitOrder"
,
&
et
.
LimitOrder
{
LeftAsset
:
&
et
.
Asset
{
Symbol
:
"bty"
,
Execer
:
"coins"
},
RightAsset
:
&
et
.
Asset
{
Execer
:
"token"
,
Symbol
:
"CCNY"
},
Price
:
3
,
Amount
:
10
*
types
.
Coin
,
Op
:
et
.
OpSell
})
RightAsset
:
&
et
.
Asset
{
Execer
:
"token"
,
Symbol
:
"CCNY"
},
Price
:
3
00000000
,
Amount
:
10
*
types
.
Coin
,
Op
:
et
.
OpSell
})
assert
.
Nil
(
t
,
err
)
assert
.
Nil
(
t
,
err
)
tx
,
err
=
types
.
FormatTx
(
cfg
,
et
.
ExchangeX
,
tx
)
tx
,
err
=
types
.
FormatTx
(
cfg
,
et
.
ExchangeX
,
tx
)
assert
.
Nil
(
t
,
err
)
assert
.
Nil
(
t
,
err
)
...
@@ -638,7 +638,7 @@ func TestExchange(t *testing.T) {
...
@@ -638,7 +638,7 @@ func TestExchange(t *testing.T) {
// orderlimit bty:CCNY ,先挂卖单,然后高于市场价格买入, 买家获利原则
// orderlimit bty:CCNY ,先挂卖单,然后高于市场价格买入, 买家获利原则
tx
,
err
=
ety
.
Create
(
"LimitOrder"
,
&
et
.
LimitOrder
{
LeftAsset
:
&
et
.
Asset
{
Symbol
:
"bty"
,
Execer
:
"coins"
},
tx
,
err
=
ety
.
Create
(
"LimitOrder"
,
&
et
.
LimitOrder
{
LeftAsset
:
&
et
.
Asset
{
Symbol
:
"bty"
,
Execer
:
"coins"
},
RightAsset
:
&
et
.
Asset
{
Execer
:
"token"
,
Symbol
:
"CCNY"
},
Price
:
4
,
Amount
:
5
*
types
.
Coin
,
Op
:
et
.
OpSell
})
RightAsset
:
&
et
.
Asset
{
Execer
:
"token"
,
Symbol
:
"CCNY"
},
Price
:
4
00000000
,
Amount
:
5
*
types
.
Coin
,
Op
:
et
.
OpSell
})
assert
.
Nil
(
t
,
err
)
assert
.
Nil
(
t
,
err
)
tx
,
err
=
types
.
FormatTx
(
cfg
,
et
.
ExchangeX
,
tx
)
tx
,
err
=
types
.
FormatTx
(
cfg
,
et
.
ExchangeX
,
tx
)
assert
.
Nil
(
t
,
err
)
assert
.
Nil
(
t
,
err
)
...
@@ -678,7 +678,7 @@ func TestExchange(t *testing.T) {
...
@@ -678,7 +678,7 @@ func TestExchange(t *testing.T) {
orderID8
:=
orderList
.
List
[
0
]
.
OrderID
orderID8
:=
orderList
.
List
[
0
]
.
OrderID
tx
,
err
=
ety
.
Create
(
"LimitOrder"
,
&
et
.
LimitOrder
{
LeftAsset
:
&
et
.
Asset
{
Symbol
:
"bty"
,
Execer
:
"coins"
},
tx
,
err
=
ety
.
Create
(
"LimitOrder"
,
&
et
.
LimitOrder
{
LeftAsset
:
&
et
.
Asset
{
Symbol
:
"bty"
,
Execer
:
"coins"
},
RightAsset
:
&
et
.
Asset
{
Execer
:
"token"
,
Symbol
:
"CCNY"
},
Price
:
5
,
Amount
:
5
*
types
.
Coin
,
Op
:
et
.
OpSell
})
RightAsset
:
&
et
.
Asset
{
Execer
:
"token"
,
Symbol
:
"CCNY"
},
Price
:
5
00000000
,
Amount
:
5
*
types
.
Coin
,
Op
:
et
.
OpSell
})
assert
.
Nil
(
t
,
err
)
assert
.
Nil
(
t
,
err
)
tx
,
err
=
types
.
FormatTx
(
cfg
,
et
.
ExchangeX
,
tx
)
tx
,
err
=
types
.
FormatTx
(
cfg
,
et
.
ExchangeX
,
tx
)
assert
.
Nil
(
t
,
err
)
assert
.
Nil
(
t
,
err
)
...
@@ -717,7 +717,7 @@ func TestExchange(t *testing.T) {
...
@@ -717,7 +717,7 @@ func TestExchange(t *testing.T) {
orderList
=
msg
.
(
*
et
.
OrderList
)
orderList
=
msg
.
(
*
et
.
OrderList
)
orderID9
:=
orderList
.
List
[
0
]
.
OrderID
orderID9
:=
orderList
.
List
[
0
]
.
OrderID
tx
,
err
=
ety
.
Create
(
"LimitOrder"
,
&
et
.
LimitOrder
{
LeftAsset
:
&
et
.
Asset
{
Symbol
:
"bty"
,
Execer
:
"coins"
},
tx
,
err
=
ety
.
Create
(
"LimitOrder"
,
&
et
.
LimitOrder
{
LeftAsset
:
&
et
.
Asset
{
Symbol
:
"bty"
,
Execer
:
"coins"
},
RightAsset
:
&
et
.
Asset
{
Execer
:
"token"
,
Symbol
:
"CCNY"
},
Price
:
4
.5
,
Amount
:
15
*
types
.
Coin
,
Op
:
et
.
OpBuy
})
RightAsset
:
&
et
.
Asset
{
Execer
:
"token"
,
Symbol
:
"CCNY"
},
Price
:
4
50000000
,
Amount
:
15
*
types
.
Coin
,
Op
:
et
.
OpBuy
})
assert
.
Nil
(
t
,
err
)
assert
.
Nil
(
t
,
err
)
tx
,
err
=
types
.
FormatTx
(
cfg
,
et
.
ExchangeX
,
tx
)
tx
,
err
=
types
.
FormatTx
(
cfg
,
et
.
ExchangeX
,
tx
)
assert
.
Nil
(
t
,
err
)
assert
.
Nil
(
t
,
err
)
...
@@ -812,22 +812,11 @@ func signTx(tx *types.Transaction, hexPrivKey string) (*types.Transaction, error
...
@@ -812,22 +812,11 @@ func signTx(tx *types.Transaction, hexPrivKey string) (*types.Transaction, error
return
tx
,
nil
return
tx
,
nil
}
}
func
TestTruncate
(
t
*
testing
.
T
)
{
a
:=
float64
(
1.00000212000000000001
)
b
:=
float64
(
0.34567
)
c
:=
float64
(
1234567
)
t
.
Log
(
Truncate
(
a
))
t
.
Log
(
Truncate
(
b
))
t
.
Log
(
Truncate
(
c
))
t
.
Log
(
float64
(
1.00000212000000000001
))
t
.
Logf
(
"%f"
,
Truncate
(
float64
(
1e8
)))
t
.
Log
(
Truncate
(
float64
(
1e-8
)))
}
func
TestCheckPrice
(
t
*
testing
.
T
)
{
func
TestCheckPrice
(
t
*
testing
.
T
)
{
t
.
Log
(
CheckPrice
(
Truncate
(
float64
(
1e8
))))
t
.
Log
(
CheckPrice
(
1e8
))
t
.
Log
(
CheckPrice
(
Truncate
(
float64
(
1e-8
))))
t
.
Log
(
CheckPrice
(
-
1
))
t
.
Log
(
CheckPrice
(
Truncate
(
float64
(
1e-9
))))
t
.
Log
(
CheckPrice
(
1e17
))
t
.
Log
(
CheckPrice
(
0
))
}
}
func
TestRawMeta
(
t
*
testing
.
T
)
{
func
TestRawMeta
(
t
*
testing
.
T
)
{
...
@@ -843,3 +832,9 @@ func TestKV(t *testing.T) {
...
@@ -843,3 +832,9 @@ func TestKV(t *testing.T) {
a
:=
&
types
.
KeyValue
{
Key
:
[]
byte
(
"1111111"
),
Value
:
nil
}
a
:=
&
types
.
KeyValue
{
Key
:
[]
byte
(
"1111111"
),
Value
:
nil
}
t
.
Log
(
a
.
Key
,
a
.
Value
)
t
.
Log
(
a
.
Key
,
a
.
Value
)
}
}
func
TestSafeMul
(
t
*
testing
.
T
)
{
t
.
Log
(
SafeMul
(
1e8
,
1e7
))
t
.
Log
(
SafeMul
(
1e10
,
1e16
))
t
.
Log
(
SafeMul
(
1e7
,
1e6
))
}
plugin/dapp/exchange/executor/exchangedb.go
View file @
3ffe72e7
...
@@ -2,7 +2,7 @@ package executor
...
@@ -2,7 +2,7 @@ package executor
import
(
import
(
"fmt"
"fmt"
"math"
"math
/big
"
"github.com/33cn/chain33/account"
"github.com/33cn/chain33/account"
"github.com/33cn/chain33/client"
"github.com/33cn/chain33/client"
...
@@ -59,16 +59,16 @@ func (a *Action) OpSwap(op int32) int32 {
...
@@ -59,16 +59,16 @@ func (a *Action) OpSwap(op int32) int32 {
}
}
//计算实际花费
//计算实际花费
func
(
a
*
Action
)
calcActualCost
(
op
int32
,
amount
int64
,
price
floa
t64
)
int64
{
func
(
a
*
Action
)
calcActualCost
(
op
int32
,
amount
int64
,
price
in
t64
)
int64
{
if
op
==
et
.
OpBuy
{
if
op
==
et
.
OpBuy
{
return
int64
(
float64
(
amount
)
*
Truncate
(
price
)
)
return
SafeMul
(
amount
,
price
)
}
}
return
amount
return
amount
}
}
//price 精度允许范围
小数点后面8位数,0<price<1e8
//price 精度允许范围
1<=price<=1e16 整数
func
CheckPrice
(
price
floa
t64
)
bool
{
func
CheckPrice
(
price
in
t64
)
bool
{
if
(
Truncate
(
price
)
>=
1e8
)
||
(
Truncate
(
price
)
*
float64
(
1e8
)
<
1
)
{
if
price
>
1e16
||
price
<
1
{
return
false
return
false
}
}
return
true
return
true
...
@@ -145,7 +145,7 @@ func (a *Action) LimitOrder(payload *et.LimitOrder) (*types.Receipt, error) {
...
@@ -145,7 +145,7 @@ func (a *Action) LimitOrder(payload *et.LimitOrder) (*types.Receipt, error) {
}
}
//先检查账户余额
//先检查账户余额
if
payload
.
GetOp
()
==
et
.
OpBuy
{
if
payload
.
GetOp
()
==
et
.
OpBuy
{
amount
:=
int64
(
float64
(
payload
.
GetAmount
())
*
Truncate
(
payload
.
GetPrice
()
))
amount
:=
SafeMul
(
payload
.
GetAmount
(),
payload
.
GetPrice
(
))
rightAccount
:=
rightAssetDB
.
LoadExecAccount
(
a
.
fromaddr
,
a
.
execaddr
)
rightAccount
:=
rightAssetDB
.
LoadExecAccount
(
a
.
fromaddr
,
a
.
execaddr
)
if
rightAccount
.
Balance
<
amount
{
if
rightAccount
.
Balance
<
amount
{
elog
.
Error
(
"LimitOrder.BalanceCheck"
,
"addr"
,
a
.
fromaddr
,
"execaddr"
,
a
.
execaddr
,
"amount"
,
amount
,
"err"
,
et
.
ErrAssetBalance
.
Error
())
elog
.
Error
(
"LimitOrder.BalanceCheck"
,
"addr"
,
a
.
fromaddr
,
"execaddr"
,
a
.
execaddr
,
"amount"
,
amount
,
"err"
,
et
.
ErrAssetBalance
.
Error
())
...
@@ -260,6 +260,7 @@ func (a *Action) matchLimitOrder(payload *et.LimitOrder, leftAccountDB, rightAcc
...
@@ -260,6 +260,7 @@ func (a *Action) matchLimitOrder(payload *et.LimitOrder, leftAccountDB, rightAcc
Value
:
&
et
.
Order_LimitOrder
{
LimitOrder
:
payload
},
Value
:
&
et
.
Order_LimitOrder
{
LimitOrder
:
payload
},
Ty
:
et
.
TyLimitOrderAction
,
Ty
:
et
.
TyLimitOrderAction
,
Executed
:
0
,
Executed
:
0
,
AVGPrice
:
0
,
Balance
:
payload
.
GetAmount
(),
Balance
:
payload
.
GetAmount
(),
Status
:
et
.
Ordered
,
Status
:
et
.
Ordered
,
Addr
:
a
.
fromaddr
,
Addr
:
a
.
fromaddr
,
...
@@ -274,16 +275,17 @@ func (a *Action) matchLimitOrder(payload *et.LimitOrder, leftAccountDB, rightAcc
...
@@ -274,16 +275,17 @@ func (a *Action) matchLimitOrder(payload *et.LimitOrder, leftAccountDB, rightAcc
//单笔交易最多撮合100笔历史订单,最大可撮合得深度,系统得自我防护
//单笔交易最多撮合100笔历史订单,最大可撮合得深度,系统得自我防护
//迭代已有挂单价格
//迭代已有挂单价格
for
{
for
{
if
count
>
et
.
MaxCount
{
//当撮合深度大于最大深度时跳出
if
count
>
et
.
MaxMatchCount
{
break
break
}
}
//获取现有市场挂单价格信息
marketDepthList
,
err
:=
QueryMarketDepth
(
a
.
localDB
,
payload
.
GetLeftAsset
(),
payload
.
GetRightAsset
(),
a
.
OpSwap
(
payload
.
Op
),
priceKey
,
et
.
Count
)
marketDepthList
,
err
:=
QueryMarketDepth
(
a
.
localDB
,
payload
.
GetLeftAsset
(),
payload
.
GetRightAsset
(),
a
.
OpSwap
(
payload
.
Op
),
priceKey
,
et
.
Count
)
if
err
==
types
.
ErrNotFound
{
if
err
==
types
.
ErrNotFound
{
break
break
}
}
//elog.Info("matchLimitOrder.QueryMarketDepth", "marketList", marketDepthList)
for
_
,
marketDepth
:=
range
marketDepthList
.
List
{
for
_
,
marketDepth
:=
range
marketDepthList
.
List
{
if
count
>
et
.
MaxCount
{
if
count
>
et
.
Max
Match
Count
{
break
break
}
}
// 卖单价大于买单价
// 卖单价大于买单价
...
@@ -296,162 +298,43 @@ func (a *Action) matchLimitOrder(payload *et.LimitOrder, leftAccountDB, rightAcc
...
@@ -296,162 +298,43 @@ func (a *Action) matchLimitOrder(payload *et.LimitOrder, leftAccountDB, rightAcc
}
}
//根据价格进行迭代
//根据价格进行迭代
for
{
for
{
//当撮合深度大于最大深度时跳出
if
count
>
et
.
MaxMatchCount
{
break
}
orderList
,
err
:=
findOrderIDListByPrice
(
a
.
localDB
,
payload
.
GetLeftAsset
(),
payload
.
GetRightAsset
(),
marketDepth
.
Price
,
a
.
OpSwap
(
payload
.
Op
),
et
.
ListASC
,
orderKey
)
orderList
,
err
:=
findOrderIDListByPrice
(
a
.
localDB
,
payload
.
GetLeftAsset
(),
payload
.
GetRightAsset
(),
marketDepth
.
Price
,
a
.
OpSwap
(
payload
.
Op
),
et
.
ListASC
,
orderKey
)
if
err
==
types
.
ErrNotFound
{
if
err
==
types
.
ErrNotFound
{
break
break
}
}
for
_
,
matchorder
:=
range
orderList
.
List
{
for
_
,
matchorder
:=
range
orderList
.
List
{
//当撮合深度大于最大深度时跳出
if
count
>
et
.
MaxMatchCount
{
break
}
//同地址不能交易
//同地址不能交易
if
matchorder
.
Addr
==
a
.
fromaddr
{
if
matchorder
.
Addr
==
a
.
fromaddr
{
continue
continue
}
}
//TODO 这里得逻辑是否需要调整?当匹配的单数过多,会导致receipt日志数量激增,理论上存在日志存储攻击,需要加下最大匹配深度,防止这种攻击发生
//撮合,指针传递
if
matchorder
.
GetBalance
()
>=
or
.
GetBalance
()
{
log
,
kv
,
err
:=
a
.
matchModel
(
leftAccountDB
,
rightAccountDB
,
payload
,
matchorder
,
or
,
re
)
if
payload
.
Op
==
et
.
OpSell
{
if
err
!=
nil
{
//转移冻结资产
return
nil
,
err
receipt
,
err
:=
rightAccountDB
.
ExecTransferFrozen
(
matchorder
.
Addr
,
a
.
fromaddr
,
a
.
execaddr
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
or
.
GetBalance
(),
payload
.
Price
))
}
if
err
!=
nil
{
logs
=
append
(
logs
,
log
...
)
elog
.
Error
(
"matchLimitOrder.ExecTransferFrozen"
,
"addr"
,
matchorder
.
Addr
,
"execaddr"
,
a
.
execaddr
,
"amount"
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
or
.
GetBalance
(),
payload
.
Price
),
"err"
,
err
.
Error
())
kvs
=
append
(
kvs
,
kv
...
)
return
nil
,
err
//订单完成,直接返回,如果没有完成,则继续撮合,直到count等于
}
if
or
.
Status
==
et
.
Completed
{
logs
=
append
(
logs
,
receipt
.
Logs
...
)
kvs
=
append
(
kvs
,
receipt
.
KV
...
)
//解冻多余资金
if
payload
.
Price
<
matchorder
.
GetLimitOrder
()
.
Price
{
receipt
,
err
:=
rightAccountDB
.
ExecActive
(
matchorder
.
Addr
,
a
.
execaddr
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
or
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
-
payload
.
Price
))
if
err
!=
nil
{
elog
.
Error
(
"matchLimitOrder.ExecActive"
,
"addr"
,
matchorder
.
Addr
,
"execaddr"
,
a
.
execaddr
,
"amount"
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
or
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
-
payload
.
Price
),
"err"
,
err
.
Error
())
return
nil
,
err
}
logs
=
append
(
logs
,
receipt
.
Logs
...
)
kvs
=
append
(
kvs
,
receipt
.
KV
...
)
}
//将达成交易的相应资产结算
receipt
,
err
=
leftAccountDB
.
ExecTransfer
(
a
.
fromaddr
,
matchorder
.
Addr
,
a
.
execaddr
,
a
.
calcActualCost
(
payload
.
Op
,
or
.
GetBalance
(),
payload
.
Price
))
if
err
!=
nil
{
elog
.
Error
(
"matchLimitOrder.ExecTransfer"
,
"addr"
,
a
.
fromaddr
,
"execaddr"
,
a
.
execaddr
,
"amount"
,
a
.
calcActualCost
(
payload
.
Op
,
or
.
GetBalance
(),
payload
.
Price
),
"err"
,
err
.
Error
())
return
nil
,
err
}
logs
=
append
(
logs
,
receipt
.
Logs
...
)
kvs
=
append
(
kvs
,
receipt
.
KV
...
)
}
if
payload
.
Op
==
et
.
OpBuy
{
//转移冻结资产
receipt
,
err
:=
leftAccountDB
.
ExecTransferFrozen
(
matchorder
.
Addr
,
a
.
fromaddr
,
a
.
execaddr
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
or
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
))
if
err
!=
nil
{
elog
.
Error
(
"matchLimitOrder.ExecTransferFrozen"
,
"addr"
,
matchorder
.
Addr
,
"execaddr"
,
a
.
execaddr
,
"amount"
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
or
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
),
"err"
,
err
.
Error
())
return
nil
,
err
}
logs
=
append
(
logs
,
receipt
.
Logs
...
)
kvs
=
append
(
kvs
,
receipt
.
KV
...
)
//将达成交易的相应资产结算
receipt
,
err
=
rightAccountDB
.
ExecTransfer
(
a
.
fromaddr
,
matchorder
.
Addr
,
a
.
execaddr
,
a
.
calcActualCost
(
payload
.
Op
,
or
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
))
if
err
!=
nil
{
elog
.
Error
(
"matchLimitOrder.ExecTransfer"
,
"addr"
,
a
.
fromaddr
,
"execaddr"
,
a
.
execaddr
,
"amount"
,
a
.
calcActualCost
(
payload
.
Op
,
or
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
),
"err"
,
err
.
Error
())
return
nil
,
err
}
logs
=
append
(
logs
,
receipt
.
Logs
...
)
kvs
=
append
(
kvs
,
receipt
.
KV
...
)
}
// match receiptorder,涉及赋值先手顺序,代码顺序不可变
matchorder
.
Status
=
func
(
a
,
b
int64
)
int32
{
if
a
>
b
{
return
et
.
Ordered
}
return
et
.
Completed
}(
matchorder
.
GetBalance
(),
or
.
GetBalance
())
matchorder
.
Balance
=
matchorder
.
GetBalance
()
-
or
.
GetBalance
()
//记录本次成交得量
matchorder
.
Executed
=
or
.
GetBalance
()
a
.
updateStateDBCache
(
matchorder
)
kvs
=
append
(
kvs
,
a
.
GetKVSet
(
matchorder
)
...
)
or
.
Executed
=
or
.
Executed
+
or
.
GetBalance
()
or
.
Status
=
et
.
Completed
or
.
Balance
=
0
//update receipt order
re
.
Order
=
or
re
.
MatchOrders
=
append
(
re
.
MatchOrders
,
matchorder
)
a
.
updateStateDBCache
(
or
)
kvs
=
append
(
kvs
,
a
.
GetKVSet
(
or
)
...
)
//statedb 更新
receiptlog
:=
&
types
.
ReceiptLog
{
Ty
:
et
.
TyLimitOrderLog
,
Log
:
types
.
Encode
(
re
)}
receiptlog
:=
&
types
.
ReceiptLog
{
Ty
:
et
.
TyLimitOrderLog
,
Log
:
types
.
Encode
(
re
)}
logs
=
append
(
logs
,
receiptlog
)
logs
=
append
(
logs
,
receiptlog
)
receipts
:=
&
types
.
Receipt
{
Ty
:
types
.
ExecOk
,
KV
:
kvs
,
Logs
:
logs
}
receipts
:=
&
types
.
Receipt
{
Ty
:
types
.
ExecOk
,
KV
:
kvs
,
Logs
:
logs
}
return
receipts
,
nil
return
receipts
,
nil
}
}
if
payload
.
Op
==
et
.
OpSell
{
//TODO 这里得逻辑是否需要调整?当匹配的单数过多,会导致receipt日志数量激增,理论上存在日志存储攻击,需要加下最大匹配深度,防止这种攻击发生
//转移冻结资产
receipt
,
err
:=
rightAccountDB
.
ExecTransferFrozen
(
matchorder
.
Addr
,
a
.
fromaddr
,
a
.
execaddr
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
matchorder
.
GetBalance
(),
payload
.
Price
))
if
err
!=
nil
{
elog
.
Error
(
"matchLimitOrder.ExecTransferFrozen"
,
"addr"
,
matchorder
.
Addr
,
"execaddr"
,
a
.
execaddr
,
"amount"
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
matchorder
.
GetBalance
(),
payload
.
Price
),
"err"
,
err
.
Error
())
return
nil
,
err
}
logs
=
append
(
logs
,
receipt
.
Logs
...
)
kvs
=
append
(
kvs
,
receipt
.
KV
...
)
//解冻成交部分 多余资金
if
payload
.
Price
<
matchorder
.
GetLimitOrder
()
.
Price
{
receipt
,
err
:=
rightAccountDB
.
ExecActive
(
matchorder
.
Addr
,
a
.
execaddr
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
matchorder
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
-
payload
.
Price
))
if
err
!=
nil
{
elog
.
Error
(
"matchLimitOrder.ExecActive"
,
"addr"
,
matchorder
.
Addr
,
"execaddr"
,
a
.
execaddr
,
"amount"
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
or
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
-
payload
.
Price
),
"err"
,
err
.
Error
())
return
nil
,
err
}
logs
=
append
(
logs
,
receipt
.
Logs
...
)
kvs
=
append
(
kvs
,
receipt
.
KV
...
)
}
//将达成交易的相应资产结算
receipt
,
err
=
leftAccountDB
.
ExecTransfer
(
a
.
fromaddr
,
matchorder
.
Addr
,
a
.
execaddr
,
a
.
calcActualCost
(
payload
.
Op
,
matchorder
.
GetBalance
(),
payload
.
Price
))
if
err
!=
nil
{
elog
.
Error
(
"matchLimitOrder.ExecTransfer"
,
"addr"
,
a
.
fromaddr
,
"execaddr"
,
a
.
execaddr
,
"amount"
,
a
.
calcActualCost
(
payload
.
Op
,
matchorder
.
GetBalance
(),
payload
.
Price
),
"err"
,
err
.
Error
())
return
nil
,
err
}
logs
=
append
(
logs
,
receipt
.
Logs
...
)
kvs
=
append
(
kvs
,
receipt
.
KV
...
)
}
if
payload
.
Op
==
et
.
OpBuy
{
//转移冻结资产
receipt
,
err
:=
leftAccountDB
.
ExecTransferFrozen
(
matchorder
.
Addr
,
a
.
fromaddr
,
a
.
execaddr
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
matchorder
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
))
if
err
!=
nil
{
elog
.
Error
(
"matchLimitOrder.ExecTransferFrozen"
,
"addr"
,
matchorder
.
Addr
,
"execaddr"
,
a
.
execaddr
,
"amount"
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
matchorder
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
),
"err"
,
err
.
Error
())
return
nil
,
err
}
logs
=
append
(
logs
,
receipt
.
Logs
...
)
kvs
=
append
(
kvs
,
receipt
.
KV
...
)
//将达成交易的相应资产结算
receipt
,
err
=
rightAccountDB
.
ExecTransfer
(
a
.
fromaddr
,
matchorder
.
Addr
,
a
.
execaddr
,
a
.
calcActualCost
(
payload
.
Op
,
matchorder
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
))
if
err
!=
nil
{
elog
.
Error
(
"matchLimitOrder.ExecTransfer"
,
"addr"
,
a
.
fromaddr
,
"execaddr"
,
a
.
execaddr
,
"amount"
,
a
.
calcActualCost
(
payload
.
Op
,
matchorder
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
),
"err"
,
err
.
Error
())
return
nil
,
err
}
logs
=
append
(
logs
,
receipt
.
Logs
...
)
kvs
=
append
(
kvs
,
receipt
.
KV
...
)
}
//涉及赋值先后顺序,不可颠倒
or
.
Balance
=
or
.
Balance
-
matchorder
.
Balance
or
.
Executed
=
or
.
Executed
+
matchorder
.
Balance
or
.
Status
=
et
.
Ordered
a
.
updateStateDBCache
(
or
)
// match receiptorder
matchorder
.
Executed
=
matchorder
.
Balance
matchorder
.
Status
=
et
.
Completed
matchorder
.
Balance
=
0
a
.
updateStateDBCache
(
matchorder
)
kvs
=
append
(
kvs
,
a
.
GetKVSet
(
matchorder
)
...
)
re
.
Order
=
or
re
.
MatchOrders
=
append
(
re
.
MatchOrders
,
matchorder
)
//撮合深度计数
//撮合深度计数
count
=
count
+
1
count
=
count
+
1
}
}
//查询数据不满足
5
条说明没有了,跳出循环
//查询数据不满足
10
条说明没有了,跳出循环
if
orderList
.
PrimaryKey
==
""
{
if
orderList
.
PrimaryKey
==
""
{
break
break
}
}
...
@@ -459,14 +342,14 @@ func (a *Action) matchLimitOrder(payload *et.LimitOrder, leftAccountDB, rightAcc
...
@@ -459,14 +342,14 @@ func (a *Action) matchLimitOrder(payload *et.LimitOrder, leftAccountDB, rightAcc
}
}
}
}
//查询
数据不满足5条说明没有
了,跳出循环
//查询
的数据如果没有primaryKey说明没有后续数据
了,跳出循环
if
marketDepthList
.
PrimaryKey
==
""
{
if
marketDepthList
.
PrimaryKey
==
""
{
break
break
}
}
priceKey
=
marketDepthList
.
PrimaryKey
priceKey
=
marketDepthList
.
PrimaryKey
}
}
//冻结剩余未成交的资金
//
未完成的订单需要
冻结剩余未成交的资金
if
payload
.
Op
==
et
.
OpBuy
{
if
payload
.
Op
==
et
.
OpBuy
{
receipt
,
err
:=
rightAccountDB
.
ExecFrozen
(
a
.
fromaddr
,
a
.
execaddr
,
a
.
calcActualCost
(
et
.
OpBuy
,
or
.
Balance
,
payload
.
Price
))
receipt
,
err
:=
rightAccountDB
.
ExecFrozen
(
a
.
fromaddr
,
a
.
execaddr
,
a
.
calcActualCost
(
et
.
OpBuy
,
or
.
Balance
,
payload
.
Price
))
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -493,6 +376,173 @@ func (a *Action) matchLimitOrder(payload *et.LimitOrder, leftAccountDB, rightAcc
...
@@ -493,6 +376,173 @@ func (a *Action) matchLimitOrder(payload *et.LimitOrder, leftAccountDB, rightAcc
return
receipts
,
nil
return
receipts
,
nil
}
}
//交易撮合模型
func
(
a
*
Action
)
matchModel
(
leftAccountDB
,
rightAccountDB
*
account
.
DB
,
payload
*
et
.
LimitOrder
,
matchorder
*
et
.
Order
,
or
*
et
.
Order
,
re
*
et
.
ReceiptExchange
)
([]
*
types
.
ReceiptLog
,
[]
*
types
.
KeyValue
,
error
)
{
var
logs
[]
*
types
.
ReceiptLog
var
kvs
[]
*
types
.
KeyValue
//TODO 这里得逻辑是否需要调整?当匹配的单数过多,会导致receipt日志数量激增,理论上存在日志存储攻击,需要加下最大匹配深度,防止这种攻击发生
//先判断挂单得额度够不够,只有两种状态,大于等于,或者小于
if
matchorder
.
GetBalance
()
>=
or
.
GetBalance
()
{
if
payload
.
Op
==
et
.
OpSell
{
//转移冻结资产
receipt
,
err
:=
rightAccountDB
.
ExecTransferFrozen
(
matchorder
.
Addr
,
a
.
fromaddr
,
a
.
execaddr
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
or
.
GetBalance
(),
payload
.
Price
))
if
err
!=
nil
{
elog
.
Error
(
"matchLimitOrder.ExecTransferFrozen"
,
"addr"
,
matchorder
.
Addr
,
"execaddr"
,
a
.
execaddr
,
"amount"
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
or
.
GetBalance
(),
payload
.
Price
),
"err"
,
err
.
Error
())
return
nil
,
nil
,
err
}
logs
=
append
(
logs
,
receipt
.
Logs
...
)
kvs
=
append
(
kvs
,
receipt
.
KV
...
)
//解冻多余资金
if
payload
.
Price
<
matchorder
.
GetLimitOrder
()
.
Price
{
receipt
,
err
:=
rightAccountDB
.
ExecActive
(
matchorder
.
Addr
,
a
.
execaddr
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
or
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
-
payload
.
Price
))
if
err
!=
nil
{
elog
.
Error
(
"matchLimitOrder.ExecActive"
,
"addr"
,
matchorder
.
Addr
,
"execaddr"
,
a
.
execaddr
,
"amount"
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
or
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
-
payload
.
Price
),
"err"
,
err
.
Error
())
return
nil
,
nil
,
err
}
logs
=
append
(
logs
,
receipt
.
Logs
...
)
kvs
=
append
(
kvs
,
receipt
.
KV
...
)
}
//将达成交易的相应资产结算
receipt
,
err
=
leftAccountDB
.
ExecTransfer
(
a
.
fromaddr
,
matchorder
.
Addr
,
a
.
execaddr
,
a
.
calcActualCost
(
payload
.
Op
,
or
.
GetBalance
(),
payload
.
Price
))
if
err
!=
nil
{
elog
.
Error
(
"matchLimitOrder.ExecTransfer"
,
"addr"
,
a
.
fromaddr
,
"execaddr"
,
a
.
execaddr
,
"amount"
,
a
.
calcActualCost
(
payload
.
Op
,
or
.
GetBalance
(),
payload
.
Price
),
"err"
,
err
.
Error
())
return
nil
,
nil
,
err
}
logs
=
append
(
logs
,
receipt
.
Logs
...
)
kvs
=
append
(
kvs
,
receipt
.
KV
...
)
//卖单成交得平均价格始终与自身挂单价格相同
or
.
AVGPrice
=
payload
.
Price
//计算matchOrder平均成交价格
matchorder
.
AVGPrice
=
caclAVGPrice
(
matchorder
,
payload
.
Price
,
payload
.
Amount
)
}
if
payload
.
Op
==
et
.
OpBuy
{
//转移冻结资产
receipt
,
err
:=
leftAccountDB
.
ExecTransferFrozen
(
matchorder
.
Addr
,
a
.
fromaddr
,
a
.
execaddr
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
or
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
))
if
err
!=
nil
{
elog
.
Error
(
"matchLimitOrder.ExecTransferFrozen"
,
"addr"
,
matchorder
.
Addr
,
"execaddr"
,
a
.
execaddr
,
"amount"
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
or
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
),
"err"
,
err
.
Error
())
return
nil
,
nil
,
err
}
logs
=
append
(
logs
,
receipt
.
Logs
...
)
kvs
=
append
(
kvs
,
receipt
.
KV
...
)
//将达成交易的相应资产结算
receipt
,
err
=
rightAccountDB
.
ExecTransfer
(
a
.
fromaddr
,
matchorder
.
Addr
,
a
.
execaddr
,
a
.
calcActualCost
(
payload
.
Op
,
or
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
))
if
err
!=
nil
{
elog
.
Error
(
"matchLimitOrder.ExecTransfer"
,
"addr"
,
a
.
fromaddr
,
"execaddr"
,
a
.
execaddr
,
"amount"
,
a
.
calcActualCost
(
payload
.
Op
,
or
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
),
"err"
,
err
.
Error
())
return
nil
,
nil
,
err
}
logs
=
append
(
logs
,
receipt
.
Logs
...
)
kvs
=
append
(
kvs
,
receipt
.
KV
...
)
//买单得话,价格选取卖单的价格
or
.
AVGPrice
=
matchorder
.
GetLimitOrder
()
.
Price
//计算matchOrder平均成交价格
matchorder
.
AVGPrice
=
caclAVGPrice
(
matchorder
,
matchorder
.
GetLimitOrder
()
.
Price
,
payload
.
Amount
)
}
// match receiptorder,涉及赋值先手顺序,代码顺序不可变
matchorder
.
Status
=
func
(
a
,
b
int64
)
int32
{
if
a
>
b
{
return
et
.
Ordered
}
return
et
.
Completed
}(
matchorder
.
GetBalance
(),
or
.
GetBalance
())
matchorder
.
Balance
=
matchorder
.
GetBalance
()
-
or
.
GetBalance
()
//记录本次成交得量
matchorder
.
Executed
=
or
.
GetBalance
()
a
.
updateStateDBCache
(
matchorder
)
kvs
=
append
(
kvs
,
a
.
GetKVSet
(
matchorder
)
...
)
or
.
Executed
=
or
.
Executed
+
or
.
GetBalance
()
or
.
Status
=
et
.
Completed
or
.
Balance
=
0
//update receipt order
re
.
Order
=
or
re
.
MatchOrders
=
append
(
re
.
MatchOrders
,
matchorder
)
a
.
updateStateDBCache
(
or
)
kvs
=
append
(
kvs
,
a
.
GetKVSet
(
or
)
...
)
return
logs
,
kvs
,
nil
}
if
payload
.
Op
==
et
.
OpSell
{
//转移冻结资产
receipt
,
err
:=
rightAccountDB
.
ExecTransferFrozen
(
matchorder
.
Addr
,
a
.
fromaddr
,
a
.
execaddr
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
matchorder
.
GetBalance
(),
payload
.
Price
))
if
err
!=
nil
{
elog
.
Error
(
"matchLimitOrder.ExecTransferFrozen"
,
"addr"
,
matchorder
.
Addr
,
"execaddr"
,
a
.
execaddr
,
"amount"
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
matchorder
.
GetBalance
(),
payload
.
Price
),
"err"
,
err
.
Error
())
return
nil
,
nil
,
err
}
logs
=
append
(
logs
,
receipt
.
Logs
...
)
kvs
=
append
(
kvs
,
receipt
.
KV
...
)
//解冻成交部分 多余资金
if
payload
.
Price
<
matchorder
.
GetLimitOrder
()
.
Price
{
receipt
,
err
:=
rightAccountDB
.
ExecActive
(
matchorder
.
Addr
,
a
.
execaddr
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
matchorder
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
-
payload
.
Price
))
if
err
!=
nil
{
elog
.
Error
(
"matchLimitOrder.ExecActive"
,
"addr"
,
matchorder
.
Addr
,
"execaddr"
,
a
.
execaddr
,
"amount"
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
or
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
-
payload
.
Price
),
"err"
,
err
.
Error
())
return
nil
,
nil
,
err
}
logs
=
append
(
logs
,
receipt
.
Logs
...
)
kvs
=
append
(
kvs
,
receipt
.
KV
...
)
}
//将达成交易的相应资产结算
receipt
,
err
=
leftAccountDB
.
ExecTransfer
(
a
.
fromaddr
,
matchorder
.
Addr
,
a
.
execaddr
,
a
.
calcActualCost
(
payload
.
Op
,
matchorder
.
GetBalance
(),
payload
.
Price
))
if
err
!=
nil
{
elog
.
Error
(
"matchLimitOrder.ExecTransfer"
,
"addr"
,
a
.
fromaddr
,
"execaddr"
,
a
.
execaddr
,
"amount"
,
a
.
calcActualCost
(
payload
.
Op
,
matchorder
.
GetBalance
(),
payload
.
Price
),
"err"
,
err
.
Error
())
return
nil
,
nil
,
err
}
logs
=
append
(
logs
,
receipt
.
Logs
...
)
kvs
=
append
(
kvs
,
receipt
.
KV
...
)
//买单得话,价格选取卖单的价格
or
.
AVGPrice
=
payload
.
Price
//计算matchOrder平均成交价格
matchorder
.
AVGPrice
=
caclAVGPrice
(
matchorder
,
payload
.
Price
,
matchorder
.
GetBalance
())
}
if
payload
.
Op
==
et
.
OpBuy
{
//转移冻结资产
receipt
,
err
:=
leftAccountDB
.
ExecTransferFrozen
(
matchorder
.
Addr
,
a
.
fromaddr
,
a
.
execaddr
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
matchorder
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
))
if
err
!=
nil
{
elog
.
Error
(
"matchLimitOrder.ExecTransferFrozen"
,
"addr"
,
matchorder
.
Addr
,
"execaddr"
,
a
.
execaddr
,
"amount"
,
a
.
calcActualCost
(
matchorder
.
GetLimitOrder
()
.
Op
,
matchorder
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
),
"err"
,
err
.
Error
())
return
nil
,
nil
,
err
}
logs
=
append
(
logs
,
receipt
.
Logs
...
)
kvs
=
append
(
kvs
,
receipt
.
KV
...
)
//将达成交易的相应资产结算
receipt
,
err
=
rightAccountDB
.
ExecTransfer
(
a
.
fromaddr
,
matchorder
.
Addr
,
a
.
execaddr
,
a
.
calcActualCost
(
payload
.
Op
,
matchorder
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
))
if
err
!=
nil
{
elog
.
Error
(
"matchLimitOrder.ExecTransfer"
,
"addr"
,
a
.
fromaddr
,
"execaddr"
,
a
.
execaddr
,
"amount"
,
a
.
calcActualCost
(
payload
.
Op
,
matchorder
.
GetBalance
(),
matchorder
.
GetLimitOrder
()
.
Price
),
"err"
,
err
.
Error
())
return
nil
,
nil
,
err
}
logs
=
append
(
logs
,
receipt
.
Logs
...
)
kvs
=
append
(
kvs
,
receipt
.
KV
...
)
//买单得话,价格选取卖单的价格
or
.
AVGPrice
=
matchorder
.
GetLimitOrder
()
.
Price
//计算matchOrder平均成交价格
matchorder
.
AVGPrice
=
caclAVGPrice
(
matchorder
,
matchorder
.
GetLimitOrder
()
.
Price
,
matchorder
.
GetBalance
())
}
//涉及赋值先后顺序,不可颠倒
or
.
Balance
=
or
.
Balance
-
matchorder
.
Balance
or
.
Executed
=
or
.
Executed
+
matchorder
.
Balance
or
.
Status
=
et
.
Ordered
a
.
updateStateDBCache
(
or
)
// match receiptorder
matchorder
.
Executed
=
matchorder
.
Balance
matchorder
.
Status
=
et
.
Completed
matchorder
.
Balance
=
0
a
.
updateStateDBCache
(
matchorder
)
kvs
=
append
(
kvs
,
a
.
GetKVSet
(
matchorder
)
...
)
re
.
Order
=
or
re
.
MatchOrders
=
append
(
re
.
MatchOrders
,
matchorder
)
return
logs
,
kvs
,
nil
}
//根据订单号查询,分为两步,优先去localdb中查询,如没有则再去状态数据库中查询
//根据订单号查询,分为两步,优先去localdb中查询,如没有则再去状态数据库中查询
// 1.挂单中得订单信会根据orderID在localdb中存储
// 1.挂单中得订单信会根据orderID在localdb中存储
// 2.订单撤销,或者成交后,根据orderID在localdb中存储得数据会被删除,这时只能到状态数据库中查询
// 2.订单撤销,或者成交后,根据orderID在localdb中存储得数据会被删除,这时只能到状态数据库中查询
...
@@ -518,9 +568,9 @@ func findOrderByOrderID(statedb dbm.KV, localdb dbm.KV, orderID int64) (*et.Orde
...
@@ -518,9 +568,9 @@ func findOrderByOrderID(statedb dbm.KV, localdb dbm.KV, orderID int64) (*et.Orde
}
}
func
findOrderIDListByPrice
(
localdb
dbm
.
KV
,
left
,
right
*
et
.
Asset
,
price
floa
t64
,
op
,
direction
int32
,
primaryKey
string
)
(
*
et
.
OrderList
,
error
)
{
func
findOrderIDListByPrice
(
localdb
dbm
.
KV
,
left
,
right
*
et
.
Asset
,
price
in
t64
,
op
,
direction
int32
,
primaryKey
string
)
(
*
et
.
OrderList
,
error
)
{
table
:=
NewMarketOrderTable
(
localdb
)
table
:=
NewMarketOrderTable
(
localdb
)
prefix
:=
[]
byte
(
fmt
.
Sprintf
(
"%s:%s:%d:%016d"
,
left
.
GetSymbol
(),
right
.
GetSymbol
(),
op
,
int64
(
Truncate
(
price
*
float64
(
1e8
)))
))
prefix
:=
[]
byte
(
fmt
.
Sprintf
(
"%s:%s:%d:%016d"
,
left
.
GetSymbol
(),
right
.
GetSymbol
(),
op
,
price
))
var
rows
[]
*
tab
.
Row
var
rows
[]
*
tab
.
Row
var
err
error
var
err
error
...
@@ -555,7 +605,7 @@ func Direction(op int32) int32 {
...
@@ -555,7 +605,7 @@ func Direction(op int32) int32 {
return
et
.
ListASC
return
et
.
ListASC
}
}
//这里primaryKey当作主键索引来用,首次查询不需要填值
//这里primaryKey当作主键索引来用,首次查询不需要填值
,买单按价格由高往低,卖单按价格由低往高查询
func
QueryMarketDepth
(
localdb
dbm
.
KV
,
left
,
right
*
et
.
Asset
,
op
int32
,
primaryKey
string
,
count
int32
)
(
*
et
.
MarketDepthList
,
error
)
{
func
QueryMarketDepth
(
localdb
dbm
.
KV
,
left
,
right
*
et
.
Asset
,
op
int32
,
primaryKey
string
,
count
int32
)
(
*
et
.
MarketDepthList
,
error
)
{
table
:=
NewMarketDepthTable
(
localdb
)
table
:=
NewMarketDepthTable
(
localdb
)
prefix
:=
[]
byte
(
fmt
.
Sprintf
(
"%s:%s:%d"
,
left
.
GetSymbol
(),
right
.
GetSymbol
(),
op
))
prefix
:=
[]
byte
(
fmt
.
Sprintf
(
"%s:%s:%d"
,
left
.
GetSymbol
(),
right
.
GetSymbol
(),
op
))
...
@@ -585,7 +635,7 @@ func QueryMarketDepth(localdb dbm.KV, left, right *et.Asset, op int32, primaryKe
...
@@ -585,7 +635,7 @@ func QueryMarketDepth(localdb dbm.KV, left, right *et.Asset, op int32, primaryKe
return
&
list
,
nil
return
&
list
,
nil
}
}
//QueryHistoryOrderList
//QueryHistoryOrderList
只返回成交的订单信息
func
QueryHistoryOrderList
(
localdb
dbm
.
KV
,
left
,
right
*
et
.
Asset
,
primaryKey
string
,
count
,
direction
int32
)
(
types
.
Message
,
error
)
{
func
QueryHistoryOrderList
(
localdb
dbm
.
KV
,
left
,
right
*
et
.
Asset
,
primaryKey
string
,
count
,
direction
int32
)
(
types
.
Message
,
error
)
{
table
:=
NewHistoryOrderTable
(
localdb
)
table
:=
NewHistoryOrderTable
(
localdb
)
prefix
:=
[]
byte
(
fmt
.
Sprintf
(
"%s:%s"
,
left
.
Symbol
,
right
.
Symbol
))
prefix
:=
[]
byte
(
fmt
.
Sprintf
(
"%s:%s"
,
left
.
Symbol
,
right
.
Symbol
))
...
@@ -632,7 +682,7 @@ HERE:
...
@@ -632,7 +682,7 @@ HERE:
}
}
//QueryOrderList,默认展示最新的
//QueryOrderList,默认展示最新的
func
QueryOrderList
(
localdb
dbm
.
KV
,
statedb
dbm
.
KV
,
addr
string
,
status
,
count
,
direction
int32
,
primaryKey
string
)
(
types
.
Message
,
error
)
{
func
QueryOrderList
(
localdb
dbm
.
KV
,
addr
string
,
status
,
count
,
direction
int32
,
primaryKey
string
)
(
types
.
Message
,
error
)
{
var
table
*
tab
.
Table
var
table
*
tab
.
Table
if
status
==
et
.
Completed
||
status
==
et
.
Revoked
{
if
status
==
et
.
Completed
||
status
==
et
.
Revoked
{
table
=
NewHistoryOrderTable
(
localdb
)
table
=
NewHistoryOrderTable
(
localdb
)
...
@@ -669,9 +719,9 @@ func QueryOrderList(localdb dbm.KV, statedb dbm.KV, addr string, status, count,
...
@@ -669,9 +719,9 @@ func QueryOrderList(localdb dbm.KV, statedb dbm.KV, addr string, status, count,
return
&
orderList
,
nil
return
&
orderList
,
nil
}
}
func
queryMarketDepth
(
localdb
dbm
.
KV
,
left
,
right
*
et
.
Asset
,
op
int32
,
price
floa
t64
)
(
*
et
.
MarketDepth
,
error
)
{
func
queryMarketDepth
(
localdb
dbm
.
KV
,
left
,
right
*
et
.
Asset
,
op
int32
,
price
in
t64
)
(
*
et
.
MarketDepth
,
error
)
{
table
:=
NewMarketDepthTable
(
localdb
)
table
:=
NewMarketDepthTable
(
localdb
)
primaryKey
:=
[]
byte
(
fmt
.
Sprintf
(
"%s:%s:%d:%016d"
,
left
.
GetSymbol
(),
right
.
GetSymbol
(),
op
,
int64
(
Truncate
(
price
)
*
float64
(
1e8
))
))
primaryKey
:=
[]
byte
(
fmt
.
Sprintf
(
"%s:%s:%d:%016d"
,
left
.
GetSymbol
(),
right
.
GetSymbol
(),
op
,
price
))
row
,
err
:=
table
.
GetData
(
primaryKey
)
row
,
err
:=
table
.
GetData
(
primaryKey
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -679,7 +729,19 @@ func queryMarketDepth(localdb dbm.KV, left, right *et.Asset, op int32, price flo
...
@@ -679,7 +729,19 @@ func queryMarketDepth(localdb dbm.KV, left, right *et.Asset, op int32, price flo
return
row
.
Data
.
(
*
et
.
MarketDepth
),
nil
return
row
.
Data
.
(
*
et
.
MarketDepth
),
nil
}
}
//截取小数点后8位
//math库中的安全大数乘法,防溢出
func
Truncate
(
price
float64
)
float64
{
func
SafeMul
(
x
,
y
int64
)
int64
{
return
math
.
Trunc
(
float64
(
1e8
)
*
price
)
/
float64
(
1e8
)
res
:=
big
.
NewInt
(
0
)
.
Mul
(
big
.
NewInt
(
x
),
big
.
NewInt
(
y
))
res
=
big
.
NewInt
(
0
)
.
Div
(
res
,
big
.
NewInt
(
types
.
Coin
))
return
res
.
Int64
()
}
//计算平均成交价格
func
caclAVGPrice
(
order
*
et
.
Order
,
price
int64
,
amount
int64
)
int64
{
x
:=
big
.
NewInt
(
0
)
.
Mul
(
big
.
NewInt
(
order
.
AVGPrice
),
big
.
NewInt
(
order
.
GetLimitOrder
()
.
Amount
-
order
.
GetBalance
()))
y
:=
big
.
NewInt
(
0
)
.
Mul
(
big
.
NewInt
(
price
),
big
.
NewInt
(
amount
))
total
:=
big
.
NewInt
(
0
)
.
Add
(
x
,
y
)
div
:=
big
.
NewInt
(
0
)
.
Add
(
big
.
NewInt
(
order
.
GetLimitOrder
()
.
Amount
-
order
.
GetBalance
()),
big
.
NewInt
(
amount
))
avg
:=
big
.
NewInt
(
0
)
.
Div
(
total
,
div
)
return
avg
.
Int64
()
}
}
plugin/dapp/exchange/executor/exec_local.go
View file @
3ffe72e7
package
executor
package
executor
import
(
import
(
"github.com/33cn/chain33/common/db/table"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/types"
ety
"github.com/33cn/plugin/plugin/dapp/exchange/types"
ety
"github.com/33cn/plugin/plugin/dapp/exchange/types"
)
)
...
@@ -77,12 +78,60 @@ func (e *exchange) updateIndex(receipt *ety.ReceiptExchange) (kvs []*types.KeyVa
...
@@ -77,12 +78,60 @@ func (e *exchange) updateIndex(receipt *ety.ReceiptExchange) (kvs []*types.KeyVa
orderTable
:=
NewMarketOrderTable
(
e
.
GetLocalDB
())
orderTable
:=
NewMarketOrderTable
(
e
.
GetLocalDB
())
switch
receipt
.
Order
.
Status
{
switch
receipt
.
Order
.
Status
{
case
ety
.
Ordered
:
case
ety
.
Ordered
:
left
:=
receipt
.
GetOrder
()
.
GetLimitOrder
()
.
GetLeftAsset
()
err
:=
e
.
updateOrder
(
marketTable
,
orderTable
,
historyTable
,
receipt
.
GetOrder
(),
receipt
.
GetIndex
())
right
:=
receipt
.
GetOrder
()
.
GetLimitOrder
()
.
GetRightAsset
()
if
err
!=
nil
{
op
:=
receipt
.
GetOrder
()
.
GetLimitOrder
()
.
GetOp
()
return
nil
price
:=
receipt
.
GetOrder
()
.
GetLimitOrder
()
.
GetPrice
()
}
order
:=
receipt
.
GetOrder
()
err
=
e
.
updateMatchOrders
(
marketTable
,
orderTable
,
historyTable
,
receipt
.
GetOrder
(),
receipt
.
GetMatchOrders
(),
receipt
.
GetIndex
())
index
:=
receipt
.
GetIndex
()
if
err
!=
nil
{
return
nil
}
case
ety
.
Completed
:
err
:=
e
.
updateOrder
(
marketTable
,
orderTable
,
historyTable
,
receipt
.
GetOrder
(),
receipt
.
GetIndex
())
if
err
!=
nil
{
return
nil
}
err
=
e
.
updateMatchOrders
(
marketTable
,
orderTable
,
historyTable
,
receipt
.
GetOrder
(),
receipt
.
GetMatchOrders
(),
receipt
.
GetIndex
())
if
err
!=
nil
{
return
nil
}
case
ety
.
Revoked
:
err
:=
e
.
updateOrder
(
marketTable
,
orderTable
,
historyTable
,
receipt
.
GetOrder
(),
receipt
.
GetIndex
())
if
err
!=
nil
{
return
nil
}
}
//刷新KV
kv
,
err
:=
marketTable
.
Save
()
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"marketTable.Save"
,
err
.
Error
())
return
nil
}
kvs
=
append
(
kvs
,
kv
...
)
kv
,
err
=
orderTable
.
Save
()
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"orderTable.Save"
,
err
.
Error
())
return
nil
}
kvs
=
append
(
kvs
,
kv
...
)
kv
,
err
=
historyTable
.
Save
()
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"historyTable.Save"
,
err
.
Error
())
return
nil
}
kvs
=
append
(
kvs
,
kv
...
)
return
}
func
(
e
*
exchange
)
updateOrder
(
marketTable
,
orderTable
,
historyTable
*
table
.
Table
,
order
*
ety
.
Order
,
index
int64
)
error
{
left
:=
order
.
GetLimitOrder
()
.
GetLeftAsset
()
right
:=
order
.
GetLimitOrder
()
.
GetRightAsset
()
op
:=
order
.
GetLimitOrder
()
.
GetOp
()
price
:=
order
.
GetLimitOrder
()
.
GetPrice
()
switch
order
.
Status
{
case
ety
.
Ordered
:
var
markDepth
ety
.
MarketDepth
var
markDepth
ety
.
MarketDepth
depth
,
err
:=
queryMarketDepth
(
e
.
GetLocalDB
(),
left
,
right
,
op
,
price
)
depth
,
err
:=
queryMarketDepth
(
e
.
GetLocalDB
(),
left
,
right
,
op
,
price
)
if
err
==
types
.
ErrNotFound
{
if
err
==
types
.
ErrNotFound
{
...
@@ -90,169 +139,34 @@ func (e *exchange) updateIndex(receipt *ety.ReceiptExchange) (kvs []*types.KeyVa
...
@@ -90,169 +139,34 @@ func (e *exchange) updateIndex(receipt *ety.ReceiptExchange) (kvs []*types.KeyVa
markDepth
.
LeftAsset
=
left
markDepth
.
LeftAsset
=
left
markDepth
.
RightAsset
=
right
markDepth
.
RightAsset
=
right
markDepth
.
Op
=
op
markDepth
.
Op
=
op
markDepth
.
Amount
=
receipt
.
O
rder
.
Balance
markDepth
.
Amount
=
o
rder
.
Balance
}
else
{
}
else
{
markDepth
.
Price
=
price
markDepth
.
Price
=
price
markDepth
.
LeftAsset
=
left
markDepth
.
LeftAsset
=
left
markDepth
.
RightAsset
=
right
markDepth
.
RightAsset
=
right
markDepth
.
Op
=
op
markDepth
.
Op
=
op
markDepth
.
Amount
=
depth
.
Amount
+
receipt
.
O
rder
.
Balance
markDepth
.
Amount
=
depth
.
Amount
+
o
rder
.
Balance
}
}
//marketDepth
//marketDepth
err
=
marketTable
.
Replace
(
&
markDepth
)
err
=
marketTable
.
Replace
(
&
markDepth
)
if
err
!=
nil
{
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"marketTable.Replace"
,
err
.
Error
())
elog
.
Error
(
"updateIndex"
,
"marketTable.Replace"
,
err
.
Error
())
return
nil
return
err
}
}
err
=
orderTable
.
Replace
(
order
)
err
=
orderTable
.
Replace
(
order
)
if
err
!=
nil
{
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"orderTable.Replace"
,
err
.
Error
())
elog
.
Error
(
"updateIndex"
,
"orderTable.Replace"
,
err
.
Error
())
return
nil
return
err
}
}
if
len
(
receipt
.
MatchOrders
)
>
0
{
//撮合交易更新
cache
:=
make
(
map
[
float64
]
int64
)
for
i
,
matchOrder
:=
range
receipt
.
MatchOrders
{
if
matchOrder
.
Status
==
ety
.
Completed
{
// 删除原有状态orderID
matchOrder
.
Status
=
ety
.
Ordered
err
=
orderTable
.
DelRow
(
matchOrder
)
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"orderTable.DelRow"
,
err
.
Error
())
return
nil
}
//索引index,改为当前的index
matchOrder
.
Status
=
ety
.
Completed
matchOrder
.
Index
=
index
+
int64
(
i
+
1
)
err
=
historyTable
.
Replace
(
matchOrder
)
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"historyTable.Replace"
,
err
.
Error
())
return
nil
}
}
if
matchOrder
.
Status
==
ety
.
Ordered
{
//更新数据
err
=
orderTable
.
Replace
(
matchOrder
)
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"orderTable.Replace"
,
err
.
Error
())
return
nil
}
}
executed
:=
cache
[
matchOrder
.
GetLimitOrder
()
.
Price
]
executed
=
executed
+
matchOrder
.
Executed
cache
[
matchOrder
.
GetLimitOrder
()
.
Price
]
=
executed
}
//更改匹配市场深度
for
pr
,
executed
:=
range
cache
{
var
matchDepth
ety
.
MarketDepth
depth
,
err
:=
queryMarketDepth
(
e
.
GetLocalDB
(),
left
,
right
,
OpSwap
(
op
),
pr
)
if
err
==
types
.
ErrNotFound
{
continue
}
else
{
matchDepth
.
Price
=
pr
matchDepth
.
LeftAsset
=
left
matchDepth
.
RightAsset
=
right
matchDepth
.
Op
=
OpSwap
(
op
)
matchDepth
.
Amount
=
depth
.
Amount
-
executed
}
//marketDepth
err
=
marketTable
.
Replace
(
&
matchDepth
)
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"marketTable.Replace"
,
err
.
Error
())
return
nil
}
if
matchDepth
.
Amount
<=
0
{
//删除
err
=
marketTable
.
DelRow
(
&
matchDepth
)
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"marketTable.DelRow"
,
err
.
Error
())
return
nil
}
}
}
}
case
ety
.
Completed
:
case
ety
.
Completed
:
left
:=
receipt
.
GetOrder
()
.
GetLimitOrder
()
.
GetLeftAsset
()
err
:=
historyTable
.
Replace
(
order
)
right
:=
receipt
.
GetOrder
()
.
GetLimitOrder
()
.
GetRightAsset
()
op
:=
receipt
.
GetOrder
()
.
GetLimitOrder
()
.
GetOp
()
index
:=
receipt
.
GetIndex
()
err
:=
historyTable
.
Replace
(
receipt
.
GetOrder
())
if
err
!=
nil
{
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"historyTable.Replace"
,
err
.
Error
())
elog
.
Error
(
"updateIndex"
,
"historyTable.Replace"
,
err
.
Error
())
return
nil
return
err
}
cache
:=
make
(
map
[
float64
]
int64
)
if
len
(
receipt
.
MatchOrders
)
>
0
{
//撮合交易更新
for
i
,
matchOrder
:=
range
receipt
.
MatchOrders
{
if
matchOrder
.
Status
==
ety
.
Completed
{
// 删除原有状态orderID
matchOrder
.
Status
=
ety
.
Ordered
err
=
orderTable
.
DelRow
(
matchOrder
)
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"orderTable.DelRow"
,
err
.
Error
())
return
nil
}
//索引index,改为当前的index
matchOrder
.
Status
=
ety
.
Completed
matchOrder
.
Index
=
index
+
int64
(
i
+
1
)
err
=
historyTable
.
Replace
(
matchOrder
)
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"historyTable.Replace"
,
err
.
Error
())
return
nil
}
}
if
matchOrder
.
Status
==
ety
.
Ordered
{
//更新数据
err
=
orderTable
.
Replace
(
matchOrder
)
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"orderTable.Replace"
,
err
.
Error
())
return
nil
}
}
executed
:=
cache
[
matchOrder
.
GetLimitOrder
()
.
Price
]
executed
=
executed
+
matchOrder
.
Executed
cache
[
matchOrder
.
GetLimitOrder
()
.
Price
]
=
executed
}
//更改match市场深度
for
pr
,
executed
:=
range
cache
{
var
matchDepth
ety
.
MarketDepth
depth
,
err
:=
queryMarketDepth
(
e
.
GetLocalDB
(),
left
,
right
,
OpSwap
(
op
),
pr
)
if
err
==
types
.
ErrNotFound
{
continue
}
else
{
matchDepth
.
Price
=
pr
matchDepth
.
LeftAsset
=
left
matchDepth
.
RightAsset
=
right
matchDepth
.
Op
=
OpSwap
(
op
)
matchDepth
.
Amount
=
depth
.
Amount
-
executed
}
//marketDepth
err
=
marketTable
.
Replace
(
&
matchDepth
)
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"marketTable.Replace"
,
err
.
Error
())
return
nil
}
if
matchDepth
.
Amount
<=
0
{
//删除
err
=
marketTable
.
DelRow
(
&
matchDepth
)
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"marketTable.DelRow"
,
err
.
Error
())
return
nil
}
}
}
}
}
case
ety
.
Revoked
:
case
ety
.
Revoked
:
//只有状态时ordered状态的订单才能被撤回
//只有状态时ordered状态的订单才能被撤回
left
:=
receipt
.
GetOrder
()
.
GetLimitOrder
()
.
GetLeftAsset
()
right
:=
receipt
.
GetOrder
()
.
GetLimitOrder
()
.
GetRightAsset
()
op
:=
receipt
.
GetOrder
()
.
GetLimitOrder
()
.
GetOp
()
price
:=
receipt
.
GetOrder
()
.
GetLimitOrder
()
.
GetPrice
()
order
:=
receipt
.
GetOrder
()
index
:=
receipt
.
GetIndex
()
var
marketDepth
ety
.
MarketDepth
var
marketDepth
ety
.
MarketDepth
depth
,
err
:=
queryMarketDepth
(
e
.
GetLocalDB
(),
left
,
right
,
op
,
price
)
depth
,
err
:=
queryMarketDepth
(
e
.
GetLocalDB
(),
left
,
right
,
op
,
price
)
if
err
==
nil
{
if
err
==
nil
{
...
@@ -265,7 +179,7 @@ func (e *exchange) updateIndex(receipt *ety.ReceiptExchange) (kvs []*types.KeyVa
...
@@ -265,7 +179,7 @@ func (e *exchange) updateIndex(receipt *ety.ReceiptExchange) (kvs []*types.KeyVa
err
=
marketTable
.
Replace
(
&
marketDepth
)
err
=
marketTable
.
Replace
(
&
marketDepth
)
if
err
!=
nil
{
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"marketTable.Replace"
,
err
.
Error
())
elog
.
Error
(
"updateIndex"
,
"marketTable.Replace"
,
err
.
Error
())
return
nil
return
err
}
}
}
}
if
marketDepth
.
Amount
<=
0
{
if
marketDepth
.
Amount
<=
0
{
...
@@ -273,7 +187,7 @@ func (e *exchange) updateIndex(receipt *ety.ReceiptExchange) (kvs []*types.KeyVa
...
@@ -273,7 +187,7 @@ func (e *exchange) updateIndex(receipt *ety.ReceiptExchange) (kvs []*types.KeyVa
err
=
marketTable
.
DelRow
(
&
marketDepth
)
err
=
marketTable
.
DelRow
(
&
marketDepth
)
if
err
!=
nil
{
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"marketTable.DelRow"
,
err
.
Error
())
elog
.
Error
(
"updateIndex"
,
"marketTable.DelRow"
,
err
.
Error
())
return
nil
return
err
}
}
}
}
//删除原有状态orderID
//删除原有状态orderID
...
@@ -281,7 +195,7 @@ func (e *exchange) updateIndex(receipt *ety.ReceiptExchange) (kvs []*types.KeyVa
...
@@ -281,7 +195,7 @@ func (e *exchange) updateIndex(receipt *ety.ReceiptExchange) (kvs []*types.KeyVa
err
=
orderTable
.
DelRow
(
order
)
err
=
orderTable
.
DelRow
(
order
)
if
err
!=
nil
{
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"orderTable.DelRow"
,
err
.
Error
())
elog
.
Error
(
"updateIndex"
,
"orderTable.DelRow"
,
err
.
Error
())
return
nil
return
err
}
}
order
.
Status
=
ety
.
Revoked
order
.
Status
=
ety
.
Revoked
order
.
Index
=
index
order
.
Index
=
index
...
@@ -289,32 +203,80 @@ func (e *exchange) updateIndex(receipt *ety.ReceiptExchange) (kvs []*types.KeyVa
...
@@ -289,32 +203,80 @@ func (e *exchange) updateIndex(receipt *ety.ReceiptExchange) (kvs []*types.KeyVa
err
=
historyTable
.
Replace
(
order
)
err
=
historyTable
.
Replace
(
order
)
if
err
!=
nil
{
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"historyTable.Replace"
,
err
.
Error
())
elog
.
Error
(
"updateIndex"
,
"historyTable.Replace"
,
err
.
Error
())
return
nil
return
err
}
}
}
}
return
nil
}
func
(
e
*
exchange
)
updateMatchOrders
(
marketTable
,
orderTable
,
historyTable
*
table
.
Table
,
order
*
ety
.
Order
,
matchOrders
[]
*
ety
.
Order
,
index
int64
)
error
{
left
:=
order
.
GetLimitOrder
()
.
GetLeftAsset
()
right
:=
order
.
GetLimitOrder
()
.
GetRightAsset
()
op
:=
order
.
GetLimitOrder
()
.
GetOp
()
if
len
(
matchOrders
)
>
0
{
//撮合交易更新
cache
:=
make
(
map
[
int64
]
int64
)
for
i
,
matchOrder
:=
range
matchOrders
{
if
matchOrder
.
Status
==
ety
.
Completed
{
// 删除原有状态orderID
matchOrder
.
Status
=
ety
.
Ordered
err
:=
orderTable
.
DelRow
(
matchOrder
)
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"orderTable.DelRow"
,
err
.
Error
())
return
err
}
//索引index,改为当前的index
matchOrder
.
Status
=
ety
.
Completed
matchOrder
.
Index
=
index
+
int64
(
i
+
1
)
err
=
historyTable
.
Replace
(
matchOrder
)
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"historyTable.Replace"
,
err
.
Error
())
return
err
}
}
if
matchOrder
.
Status
==
ety
.
Ordered
{
//更新数据
err
:=
orderTable
.
Replace
(
matchOrder
)
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"orderTable.Replace"
,
err
.
Error
())
return
err
}
}
executed
:=
cache
[
matchOrder
.
GetLimitOrder
()
.
Price
]
executed
=
executed
+
matchOrder
.
Executed
cache
[
matchOrder
.
GetLimitOrder
()
.
Price
]
=
executed
}
kv
,
err
:=
marketTable
.
Save
()
//更改匹配市场深度
if
err
!=
nil
{
for
pr
,
executed
:=
range
cache
{
elog
.
Error
(
"updateIndex"
,
"marketTable.Save"
,
err
.
Error
())
var
matchDepth
ety
.
MarketDepth
return
nil
depth
,
err
:=
queryMarketDepth
(
e
.
GetLocalDB
(),
left
,
right
,
OpSwap
(
op
),
pr
)
}
if
err
==
types
.
ErrNotFound
{
kvs
=
append
(
kvs
,
kv
...
)
continue
kv
,
err
=
orderTable
.
Save
()
}
else
{
if
err
!=
nil
{
matchDepth
.
Price
=
pr
elog
.
Error
(
"updateIndex"
,
"orderTable.Save"
,
err
.
Error
())
matchDepth
.
LeftAsset
=
left
return
nil
matchDepth
.
RightAsset
=
right
}
matchDepth
.
Op
=
OpSwap
(
op
)
kvs
=
append
(
kvs
,
kv
...
)
matchDepth
.
Amount
=
depth
.
Amount
-
executed
kv
,
err
=
historyTable
.
Save
()
}
if
err
!=
nil
{
//marketDepth
elog
.
Error
(
"updateIndex"
,
"historyTable.Save"
,
err
.
Error
())
err
=
marketTable
.
Replace
(
&
matchDepth
)
return
nil
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"marketTable.Replace"
,
err
.
Error
())
return
err
}
if
matchDepth
.
Amount
<=
0
{
//删除
err
=
marketTable
.
DelRow
(
&
matchDepth
)
if
err
!=
nil
{
elog
.
Error
(
"updateIndex"
,
"marketTable.DelRow"
,
err
.
Error
())
return
err
}
}
}
}
}
kvs
=
append
(
kvs
,
kv
...
)
return
nil
return
}
}
func
OpSwap
(
op
int32
)
int32
{
func
OpSwap
(
op
int32
)
int32
{
if
op
==
ety
.
OpBuy
{
if
op
==
ety
.
OpBuy
{
return
ety
.
OpSell
return
ety
.
OpSell
...
...
plugin/dapp/exchange/executor/query.go
View file @
3ffe72e7
...
@@ -10,9 +10,6 @@ func (s *exchange) Query_QueryMarketDepth(in *et.QueryMarketDepth) (types.Messag
...
@@ -10,9 +10,6 @@ func (s *exchange) Query_QueryMarketDepth(in *et.QueryMarketDepth) (types.Messag
if
!
CheckCount
(
in
.
Count
)
{
if
!
CheckCount
(
in
.
Count
)
{
return
nil
,
et
.
ErrCount
return
nil
,
et
.
ErrCount
}
}
if
in
.
Count
==
0
{
in
.
Count
=
10
}
if
!
CheckExchangeAsset
(
in
.
LeftAsset
,
in
.
RightAsset
)
{
if
!
CheckExchangeAsset
(
in
.
LeftAsset
,
in
.
RightAsset
)
{
return
nil
,
et
.
ErrAsset
return
nil
,
et
.
ErrAsset
}
}
...
@@ -28,7 +25,7 @@ func (s *exchange) Query_QueryHistoryOrderList(in *et.QueryHistoryOrderList) (ty
...
@@ -28,7 +25,7 @@ func (s *exchange) Query_QueryHistoryOrderList(in *et.QueryHistoryOrderList) (ty
if
!
CheckExchangeAsset
(
in
.
LeftAsset
,
in
.
RightAsset
)
{
if
!
CheckExchangeAsset
(
in
.
LeftAsset
,
in
.
RightAsset
)
{
return
nil
,
et
.
ErrAsset
return
nil
,
et
.
ErrAsset
}
}
if
in
.
Count
>
20
{
if
!
CheckCount
(
in
.
Count
)
{
return
nil
,
et
.
ErrCount
return
nil
,
et
.
ErrCount
}
}
...
@@ -62,5 +59,5 @@ func (s *exchange) Query_QueryOrderList(in *et.QueryOrderList) (types.Message, e
...
@@ -62,5 +59,5 @@ func (s *exchange) Query_QueryOrderList(in *et.QueryOrderList) (types.Message, e
if
in
.
Address
==
""
{
if
in
.
Address
==
""
{
return
nil
,
et
.
ErrAddr
return
nil
,
et
.
ErrAddr
}
}
return
QueryOrderList
(
s
.
GetLocalDB
(),
s
.
GetStateDB
(),
in
.
Address
,
in
.
Status
,
in
.
Count
,
in
.
Direction
,
in
.
PrimaryKey
)
return
QueryOrderList
(
s
.
GetLocalDB
(),
in
.
Address
,
in
.
Status
,
in
.
Count
,
in
.
Direction
,
in
.
PrimaryKey
)
}
}
plugin/dapp/exchange/executor/tables.go
View file @
3ffe72e7
...
@@ -107,7 +107,7 @@ func (r *OrderRow) Get(key string) ([]byte, error) {
...
@@ -107,7 +107,7 @@ func (r *OrderRow) Get(key string) ([]byte, error) {
if
key
==
"orderID"
{
if
key
==
"orderID"
{
return
[]
byte
(
fmt
.
Sprintf
(
"%022d"
,
r
.
OrderID
)),
nil
return
[]
byte
(
fmt
.
Sprintf
(
"%022d"
,
r
.
OrderID
)),
nil
}
else
if
key
==
"market_order"
{
}
else
if
key
==
"market_order"
{
return
[]
byte
(
fmt
.
Sprintf
(
"%s:%s:%d:%016d"
,
r
.
GetLimitOrder
()
.
LeftAsset
.
GetSymbol
(),
r
.
GetLimitOrder
()
.
RightAsset
.
GetSymbol
(),
r
.
GetLimitOrder
()
.
Op
,
int64
(
Truncate
(
r
.
GetLimitOrder
()
.
Price
*
float64
(
1e8
)))
)),
nil
return
[]
byte
(
fmt
.
Sprintf
(
"%s:%s:%d:%016d"
,
r
.
GetLimitOrder
()
.
LeftAsset
.
GetSymbol
(),
r
.
GetLimitOrder
()
.
RightAsset
.
GetSymbol
(),
r
.
GetLimitOrder
()
.
Op
,
r
.
GetLimitOrder
()
.
Price
)),
nil
}
else
if
key
==
"addr_status"
{
}
else
if
key
==
"addr_status"
{
return
[]
byte
(
fmt
.
Sprintf
(
"%s:%d"
,
r
.
Addr
,
r
.
Status
)),
nil
return
[]
byte
(
fmt
.
Sprintf
(
"%s:%d"
,
r
.
Addr
,
r
.
Status
)),
nil
}
}
...
@@ -175,7 +175,7 @@ func (m *MarketDepthRow) SetPayload(data types.Message) error {
...
@@ -175,7 +175,7 @@ func (m *MarketDepthRow) SetPayload(data types.Message) error {
//Get 按照indexName 查询 indexValue
//Get 按照indexName 查询 indexValue
func
(
m
*
MarketDepthRow
)
Get
(
key
string
)
([]
byte
,
error
)
{
func
(
m
*
MarketDepthRow
)
Get
(
key
string
)
([]
byte
,
error
)
{
if
key
==
"price"
{
if
key
==
"price"
{
return
[]
byte
(
fmt
.
Sprintf
(
"%s:%s:%d:%016d"
,
m
.
LeftAsset
.
GetSymbol
(),
m
.
RightAsset
.
GetSymbol
(),
m
.
Op
,
int64
(
Truncate
(
m
.
Price
)
*
float64
(
1e8
))
)),
nil
return
[]
byte
(
fmt
.
Sprintf
(
"%s:%s:%d:%016d"
,
m
.
LeftAsset
.
GetSymbol
(),
m
.
RightAsset
.
GetSymbol
(),
m
.
Op
,
m
.
Price
)),
nil
}
}
return
nil
,
types
.
ErrNotFound
return
nil
,
types
.
ErrNotFound
}
}
plugin/dapp/exchange/proto/exchange.proto
View file @
3ffe72e7
...
@@ -19,7 +19,7 @@ message LimitOrder {
...
@@ -19,7 +19,7 @@ message LimitOrder {
//交易对
//交易对
asset
rightAsset
=
2
;
asset
rightAsset
=
2
;
//价格
//价格
double
price
=
3
;
int64
price
=
3
;
//总量
//总量
int64
amount
=
4
;
int64
amount
=
4
;
//操作, 1为买,2为卖
//操作, 1为买,2为卖
...
@@ -60,16 +60,18 @@ message Order {
...
@@ -60,16 +60,18 @@ message Order {
int32
ty
=
4
;
int32
ty
=
4
;
//已经成交的数量
//已经成交的数量
int64
executed
=
5
;
int64
executed
=
5
;
//成交均价
int64
AVG_price
=
6
;
//余额
//余额
int64
balance
=
6
;
int64
balance
=
7
;
//状态,0 挂单中ordered, 1 完成completed, 2撤回 revoked
//状态,0 挂单中ordered, 1 完成completed, 2撤回 revoked
int32
status
=
7
;
int32
status
=
8
;
//用户地址
//用户地址
string
addr
=
8
;
string
addr
=
9
;
//更新时间
//更新时间
int64
updateTime
=
9
;
int64
updateTime
=
10
;
//索引
//索引
int64
index
=
1
0
;
int64
index
=
1
1
;
}
}
//查询接口
//查询接口
...
@@ -92,7 +94,7 @@ message MarketDepth {
...
@@ -92,7 +94,7 @@ message MarketDepth {
//资产2
//资产2
asset
rightAsset
=
2
;
asset
rightAsset
=
2
;
//价格
//价格
double
price
=
3
;
int64
price
=
3
;
//总量
//总量
int64
amount
=
4
;
int64
amount
=
4
;
//操作, 1为买,2为卖
//操作, 1为买,2为卖
...
...
plugin/dapp/exchange/types/exchange.go
View file @
3ffe72e7
...
@@ -59,9 +59,9 @@ const (
...
@@ -59,9 +59,9 @@ const (
const
(
const
(
//单次list还回条数
//单次list还回条数
Count
=
int32
(
5
)
Count
=
int32
(
10
)
//系统最大撮合深度
//系统最大撮合深度
MaxCount
=
100
Max
Match
Count
=
100
)
)
var
(
var
(
...
...
plugin/dapp/exchange/types/exchange.pb.go
View file @
3ffe72e7
...
@@ -26,15 +26,12 @@ It has these top-level messages:
...
@@ -26,15 +26,12 @@ It has these top-level messages:
*/
*/
package
types
package
types
import
(
import
proto
"github.com/golang/protobuf/proto"
fmt
"fmt"
import
fmt
"fmt"
import
math
"math"
proto
"github.com/golang/protobuf/proto"
math
"math"
import
(
context
"golang.org/x/net/context"
context
"golang.org/x/net/context"
grpc
"google.golang.org/grpc"
grpc
"google.golang.org/grpc"
)
)
...
@@ -224,7 +221,7 @@ type LimitOrder struct {
...
@@ -224,7 +221,7 @@ type LimitOrder struct {
// 交易对
// 交易对
RightAsset
*
Asset
`protobuf:"bytes,2,opt,name=rightAsset" json:"rightAsset,omitempty"`
RightAsset
*
Asset
`protobuf:"bytes,2,opt,name=rightAsset" json:"rightAsset,omitempty"`
// 价格
// 价格
Price
float64
`protobuf:"fixed64
,3,opt,name=price" json:"price,omitempty"`
Price
int64
`protobuf:"varint
,3,opt,name=price" json:"price,omitempty"`
// 总量
// 总量
Amount
int64
`protobuf:"varint,4,opt,name=amount" json:"amount,omitempty"`
Amount
int64
`protobuf:"varint,4,opt,name=amount" json:"amount,omitempty"`
// 操作, 1为买,2为卖
// 操作, 1为买,2为卖
...
@@ -250,7 +247,7 @@ func (m *LimitOrder) GetRightAsset() *Asset {
...
@@ -250,7 +247,7 @@ func (m *LimitOrder) GetRightAsset() *Asset {
return
nil
return
nil
}
}
func
(
m
*
LimitOrder
)
GetPrice
()
floa
t64
{
func
(
m
*
LimitOrder
)
GetPrice
()
in
t64
{
if
m
!=
nil
{
if
m
!=
nil
{
return
m
.
Price
return
m
.
Price
}
}
...
@@ -370,16 +367,18 @@ type Order struct {
...
@@ -370,16 +367,18 @@ type Order struct {
Ty
int32
`protobuf:"varint,4,opt,name=ty" json:"ty,omitempty"`
Ty
int32
`protobuf:"varint,4,opt,name=ty" json:"ty,omitempty"`
// 已经成交的数量
// 已经成交的数量
Executed
int64
`protobuf:"varint,5,opt,name=executed" json:"executed,omitempty"`
Executed
int64
`protobuf:"varint,5,opt,name=executed" json:"executed,omitempty"`
// 成交均价
AVGPrice
int64
`protobuf:"varint,6,opt,name=AVG_price,json=AVGPrice" json:"AVG_price,omitempty"`
// 余额
// 余额
Balance
int64
`protobuf:"varint,
6
,opt,name=balance" json:"balance,omitempty"`
Balance
int64
`protobuf:"varint,
7
,opt,name=balance" json:"balance,omitempty"`
// 状态,0 挂单中ordered, 1 完成completed, 2撤回 revoked
// 状态,0 挂单中ordered, 1 完成completed, 2撤回 revoked
Status
int32
`protobuf:"varint,
7
,opt,name=status" json:"status,omitempty"`
Status
int32
`protobuf:"varint,
8
,opt,name=status" json:"status,omitempty"`
// 用户地址
// 用户地址
Addr
string
`protobuf:"bytes,
8
,opt,name=addr" json:"addr,omitempty"`
Addr
string
`protobuf:"bytes,
9
,opt,name=addr" json:"addr,omitempty"`
// 更新时间
// 更新时间
UpdateTime
int64
`protobuf:"varint,
9
,opt,name=updateTime" json:"updateTime,omitempty"`
UpdateTime
int64
`protobuf:"varint,
10
,opt,name=updateTime" json:"updateTime,omitempty"`
// 索引
// 索引
Index
int64
`protobuf:"varint,1
0
,opt,name=index" json:"index,omitempty"`
Index
int64
`protobuf:"varint,1
1
,opt,name=index" json:"index,omitempty"`
}
}
func
(
m
*
Order
)
Reset
()
{
*
m
=
Order
{}
}
func
(
m
*
Order
)
Reset
()
{
*
m
=
Order
{}
}
...
@@ -443,6 +442,13 @@ func (m *Order) GetExecuted() int64 {
...
@@ -443,6 +442,13 @@ func (m *Order) GetExecuted() int64 {
return
0
return
0
}
}
func
(
m
*
Order
)
GetAVGPrice
()
int64
{
if
m
!=
nil
{
return
m
.
AVGPrice
}
return
0
}
func
(
m
*
Order
)
GetBalance
()
int64
{
func
(
m
*
Order
)
GetBalance
()
int64
{
if
m
!=
nil
{
if
m
!=
nil
{
return
m
.
Balance
return
m
.
Balance
...
@@ -613,7 +619,7 @@ type MarketDepth struct {
...
@@ -613,7 +619,7 @@ type MarketDepth struct {
// 资产2
// 资产2
RightAsset
*
Asset
`protobuf:"bytes,2,opt,name=rightAsset" json:"rightAsset,omitempty"`
RightAsset
*
Asset
`protobuf:"bytes,2,opt,name=rightAsset" json:"rightAsset,omitempty"`
// 价格
// 价格
Price
float64
`protobuf:"fixed64
,3,opt,name=price" json:"price,omitempty"`
Price
int64
`protobuf:"varint
,3,opt,name=price" json:"price,omitempty"`
// 总量
// 总量
Amount
int64
`protobuf:"varint,4,opt,name=amount" json:"amount,omitempty"`
Amount
int64
`protobuf:"varint,4,opt,name=amount" json:"amount,omitempty"`
// 操作, 1为买,2为卖
// 操作, 1为买,2为卖
...
@@ -639,7 +645,7 @@ func (m *MarketDepth) GetRightAsset() *Asset {
...
@@ -639,7 +645,7 @@ func (m *MarketDepth) GetRightAsset() *Asset {
return
nil
return
nil
}
}
func
(
m
*
MarketDepth
)
GetPrice
()
floa
t64
{
func
(
m
*
MarketDepth
)
GetPrice
()
in
t64
{
if
m
!=
nil
{
if
m
!=
nil
{
return
m
.
Price
return
m
.
Price
}
}
...
@@ -927,46 +933,47 @@ var _Exchange_serviceDesc = grpc.ServiceDesc{
...
@@ -927,46 +933,47 @@ var _Exchange_serviceDesc = grpc.ServiceDesc{
func
init
()
{
proto
.
RegisterFile
(
"exchange.proto"
,
fileDescriptor0
)
}
func
init
()
{
proto
.
RegisterFile
(
"exchange.proto"
,
fileDescriptor0
)
}
var
fileDescriptor0
=
[]
byte
{
var
fileDescriptor0
=
[]
byte
{
// 644 bytes of a gzipped FileDescriptorProto
// 667 bytes of a gzipped FileDescriptorProto
0x1f
,
0x8b
,
0x08
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0xff
,
0xb4
,
0x55
,
0xcd
,
0x6e
,
0xd3
,
0x40
,
0x1f
,
0x8b
,
0x08
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0xff
,
0xb4
,
0x55
,
0xdd
,
0x6e
,
0xd3
,
0x4a
,
0x10
,
0xae
,
0xed
,
0xb8
,
0xa9
,
0x27
,
0x28
,
0x85
,
0x15
,
0x20
,
0x0b
,
0x21
,
0x14
,
0xf9
,
0x50
,
0x2a
,
0x10
,
0xae
,
0xed
,
0x38
,
0xa9
,
0x27
,
0x47
,
0xe9
,
0x39
,
0xab
,
0x73
,
0x8e
,
0x2c
,
0x40
,
0xa8
,
0xf2
,
0x84
,
0x72
,
0x68
,
0x25
,
0x38
,
0x17
,
0x15
,
0xa9
,
0x88
,
0x56
,
0x88
,
0x15
,
0x17
,
0x8e
,
0xae
,
0x3d
,
0x45
,
0xa9
,
0x10
,
0xca
,
0x45
,
0x2b
,
0xc1
,
0x75
,
0x50
,
0x51
,
0x8b
,
0x68
,
0x05
,
0xac
,
0x50
,
0x25
,
0x34
,
0xab
,
0x26
,
0xb1
,
0xb5
,
0x5e
,
0x57
,
0xb5
,
0x78
,
0x08
,
0x6e
,
0x3c
,
0x01
,
0xbc
,
0x00
,
0x2f
,
0xae
,
0x90
,
0x6b
,
0x0f
,
0xcd
,
0xaa
,
0x49
,
0x6c
,
0xad
,
0x37
,
0x55
,
0x2d
,
0x1e
,
0x82
,
0x3b
,
0x9e
,
0xc0
,
0x89
,
0x2b
,
0xcf
,
0x84
,
0x76
,
0x76
,
0x1d
,
0x6f
,
0xd2
,
0xa2
,
0x56
,
0xa0
,
0xdc
,
0xfc
,
0xcd
,
0x00
,
0x5e
,
0x80
,
0x77
,
0xe0
,
0x96
,
0x27
,
0xe0
,
0x61
,
0xd0
,
0xce
,
0xae
,
0xe3
,
0x4d
,
0x5b
,
0xd4
,
0x9f
,
0xbf
,
0x99
,
0xf9
,
0x76
,
0x17
,
0x86
,
0x78
,
0x99
,
0x4d
,
0xd2
,
0xf9
,
0x19
,
0x8e
,
0x4b
,
0x59
,
0x0a
,
0x94
,
0x3b
,
0x7f
,
0xf3
,
0xb3
,
0xfe
,
0x66
,
0xe6
,
0x9b
,
0x5d
,
0x18
,
0xe0
,
0x45
,
0x36
,
0x4e
,
0xa8
,
0x82
,
0x85
,
0xaa
,
0x29
,
0xb1
,
0x4a
,
0x00
,
0xb6
,
0x5e
,
0x5b
,
0x47
,
0xf2
,
0xdb
,
0x83
,
0x61
,
0x67
,
0xa7
,
0x38
,
0x2c
,
0x65
,
0xa1
,
0x0a
,
0x16
,
0xaa
,
0xba
,
0xc4
,
0x2a
,
0x01
,
0x58
,
0x7f
,
0x66
,
0x0b
,
0x0e
,
0x32
,
0x25
,
0x8a
,
0x39
,
0xdb
,
0x07
,
0x98
,
0x8a
,
0x99
,
0x50
,
0xef
,
0x64
,
0x8e
,
0x32
,
0x1d
,
0xc9
,
0x77
,
0x0f
,
0x06
,
0x0d
,
0x18
,
0x65
,
0x4a
,
0x14
,
0x33
,
0xb6
,
0x0b
,
0x30
,
0x11
,
0x53
,
0xf6
,
0x46
,
0xde
,
0xee
,
0x60
,
0xef
,
0xde
,
0x98
,
0x52
,
0xc7
,
0xc7
,
0x0b
,
0xc7
,
0xd1
,
0x06
,
0x77
,
0xa1
,
0x5e
,
0xca
,
0x1c
,
0x65
,
0xec
,
0x6d
,
0x7a
,
0xdb
,
0xfd
,
0x9d
,
0x7f
,
0x86
,
0x94
,
0x3a
,
0x3c
,
0xc2
,
0xd8
,
0x0b
,
0x18
,
0xcc
,
0x52
,
0x79
,
0x8e
,
0x36
,
0xcb
,
0xa7
,
0x2c
,
0x66
,
0xb3
,
0x4e
,
0x3a
,
0x5c
,
0x38
,
0x0e
,
0xd6
,
0xb8
,
0x13
,
0xc6
,
0x1e
,
0x43
,
0x7f
,
0x9a
,
0xca
,
0x33
,
0xb4
,
0x59
,
0x3e
,
0xcf
,
0xd1
,
0x06
,
0x77
,
0x03
,
0x75
,
0x9e
,
0xc4
,
0x8b
,
0xe2
,
0x1c
,
0x4d
,
0x5e
,
0xb0
,
0x94
,
0xc7
,
0x65
,
0x31
,
0x9b
,
0x75
,
0xd4
,
0x7a
,
0x0e
,
0xd6
,
0xb8
,
0x1b
,
0xa8
,
0xf3
,
0x24
,
0x9e
,
0x17
,
0x67
,
0x3b
,
0x8f
,
0xce
,
0x73
,
0x02
,
0xd9
,
0x10
,
0x7c
,
0xd5
,
0xc4
,
0x9b
,
0x23
,
0x6f
,
0x37
,
0xe4
,
0xbe
,
0x68
,
0xf2
,
0x82
,
0xa5
,
0x3c
,
0xde
,
0x7a
,
0x74
,
0x9e
,
0x13
,
0xc8
,
0x06
,
0xe0
,
0xab
,
0x3a
,
0xee
,
0x6a
,
0x5e
,
0xf5
,
0x21
,
0xbc
,
0x48
,
0xa7
,
0x35
,
0x26
,
0xdf
,
0x3c
,
0x80
,
0x8e
,
0x25
,
0x7b
,
0x06
,
0x6e
,
0x7a
,
0xdb
,
0x21
,
0xf7
,
0x55
,
0xfd
,
0xb4
,
0x07
,
0xe1
,
0x79
,
0x3a
,
0x99
,
0x63
,
0xf2
,
0xd9
,
0xd1
,
0x14
,
0x3f
,
0xa9
,
0x83
,
0xaa
,
0x42
,
0x65
,
0x7b
,
0xb9
,
0x63
,
0xab
,
0xa7
,
0xda
,
0xc6
,
0x3b
,
0x03
,
0x68
,
0x59
,
0xb2
,
0x87
,
0x10
,
0x4d
,
0xf0
,
0xbd
,
0x1a
,
0x55
,
0x15
,
0x2a
,
0x5b
,
0xcb
,
0x5f
,
0x37
,
0x7b
,
0x0e
,
0x20
,
0xc5
,
0xd9
,
0xc4
,
0x06
,
0xfb
,
0xd7
,
0x04
,
0x3b
,
0x7e
,
0x76
,
0x1f
,
0xc2
,
0xf6
,
0xf4
,
0x54
,
0xdb
,
0x78
,
0xeb
,
0x66
,
0x8f
,
0x00
,
0xa4
,
0x38
,
0x1d
,
0xdb
,
0x60
,
0xff
,
0x9a
,
0x52
,
0x8a
,
0x0c
,
0x89
,
0xb3
,
0xc7
,
0x0d
,
0x60
,
0x0f
,
0x61
,
0x33
,
0x9d
,
0x15
,
0xf5
,
0x5c
,
0xc5
,
0x60
,
0xc7
,
0xcf
,
0xfe
,
0x85
,
0xb0
,
0x94
,
0x22
,
0x43
,
0xe2
,
0x1c
,
0x70
,
0x03
,
0xd8
,
0xff
,
0xd0
,
0xbd
,
0x91
,
0xb7
,
0x1b
,
0x70
,
0x8b
,
0x34
,
0xdf
,
0xa2
,
0x8c
,
0x43
,
0xc3
,
0xb7
,
0x28
,
0x93
,
0x2f
,
0x4d
,
0xa7
,
0xc5
,
0x7c
,
0xa6
,
0xe2
,
0x0e
,
0x99
,
0x2d
,
0xd2
,
0x7c
,
0x8b
,
0x32
,
0x0e
,
0x0d
,
0xdf
,
0x1e
,
0x0c
,
0x9c
,
0xb1
,
0xac
,
0x91
,
0x67
,
0xc7
,
0x28
,
0xb8
,
0x86
,
0x51
,
0x6f
,
0xc1
,
0xe8
,
0x29
,
0xa2
,
0x4c
,
0x3e
,
0x7a
,
0xd0
,
0x77
,
0xda
,
0xb2
,
0x42
,
0x9e
,
0x2d
,
0xa3
,
0xe0
,
0x1a
,
0x46
,
0x9d
,
0x0c
,
0x9c
,
0x79
,
0xb3
,
0x18
,
0xfa
,
0x85
,
0xfe
,
0x78
,
0x73
,
0x48
,
0x74
,
0x02
,
0xde
,
0xc2
,
0xe4
,
0x05
,
0xa3
,
0x07
,
0xd0
,
0x77
,
0xfa
,
0xcd
,
0x62
,
0xe8
,
0x15
,
0xfa
,
0xe3
,
0xf9
,
0x1e
,
0xd1
,
0x09
,
0x25
,
0x84
,
0x69
,
0x5b
,
0x19
,
0x2f
,
0x31
,
0xb3
,
0x22
,
0x89
,
0xb8
,
0x45
,
0xda
,
0x5e
,
0x35
,
0xb3
,
0x78
,
0x03
,
0x93
,
0x27
,
0x10
,
0xa6
,
0xcd
,
0xc9
,
0x78
,
0x81
,
0x99
,
0x15
,
0x49
,
0xc4
,
0x2d
,
0xd2
,
0xd3
,
0x62
,
0x4a
,
0xdc
,
0x22
,
0x6e
,
0x51
,
0xf2
,
0xd3
,
0x87
,
0xf0
,
0x86
,
0xe2
,
0x2b
,
0xe2
,
0xf3
,
0xf6
,
0xaa
,
0x9e
,
0x9e
,
0x14
,
0x13
,
0xe2
,
0x16
,
0x71
,
0x8b
,
0x92
,
0x1f
,
0x3e
,
0x84
,
0x37
,
0x1c
,
0xff
,
0x49
,
0x7c
,
0xc1
,
0x6d
,
0xc5
,
0x67
,
0x44
,
0xd4
,
0x6b
,
0x45
,
0xc4
,
0x1e
,
0xc1
,
0x96
,
0x6e
,
0x7e
,
0x49
,
0x7c
,
0xfe
,
0x6f
,
0x89
,
0x2f
,
0xb8
,
0xad
,
0xf8
,
0x8c
,
0x88
,
0x3a
,
0x8d
,
0x88
,
0xd8
,
0xa1
,
0x56
,
0x98
,
0xd3
,
0xaa
,
0x02
,
0xbe
,
0xc0
,
0x9a
,
0xf2
,
0x69
,
0x3a
,
0x4d
,
0xe7
,
0x19
,
0x92
,
0x1d
,
0x58
,
0xd7
,
0x25
,
0xcc
,
0x15
,
0xe6
,
0x34
,
0xaa
,
0x80
,
0x2f
,
0x30
,
0xbb
,
0x0b
,
0xd1
,
0xe8
,
0xea
,
0x02
,
0xde
,
0x42
,
0x6a
,
0x57
,
0xa5
,
0xaa
,
0xae
,
0xe2
,
0x3e
,
0x55
,
0xb2
,
0x88
,
0x31
,
0xe8
,
0x78
,
0xff
,
0x9d
,
0x19
,
0x79
,
0xd7
,
0x38
,
0x47
,
0xc7
,
0xfb
,
0xaf
,
0x68
,
0xea
,
0x31
,
0xf4
,
0x4e
,
0xa5
,
0x79
,
0x2e
,
0xe3
,
0x2d
,
0x1a
,
0x02
,
0x7d
,
0xb3
,
0x27
,
0x00
,
0x75
,
0x99
,
0xa7
,
0x0a
,
0x3f
,
0xd2
,
0x49
,
0x3a
,
0xcb
,
0x30
,
0xee
,
0x99
,
0x7a
,
0x2c
,
0xa4
,
0x5e
,
0xa8
,
0x54
,
0xcd
,
0xab
,
0x78
,
0x88
,
0x19
,
0xc6
,
0x11
,
0x15
,
0x72
,
0x2c
,
0x5a
,
0x54
,
0x62
,
0x9e
,
0xe3
,
0x65
,
0x0c
,
0xe4
,
0x32
,
0x9d
,
0x7e
,
0x63
,
0x11
,
0x63
,
0xd0
,
0x49
,
0xf3
,
0x5c
,
0xc6
,
0x11
,
0x75
,
0x88
,
0xbe
,
0xd9
,
0x7d
,
0xa0
,
0x13
,
0xf7
,
0x0f
,
0x0f
,
0xee
,
0xbe
,
0xaf
,
0x51
,
0x36
,
0xa6
,
0xa9
,
0x43
,
0x2c
,
0xd5
,
0x64
,
0x80
,
0x79
,
0x99
,
0xa7
,
0x0a
,
0xdf
,
0x88
,
0x29
,
0xc6
,
0x40
,
0x07
,
0x39
,
0x16
,
0xad
,
0x38
,
0x31
,
0x8d
,
0xd2
,
0x31
,
0x12
,
0x09
,
0x5a
,
0x89
,
0x68
,
0xf6
,
0xa5
,
0x14
,
0xb3
,
0x54
,
0x36
,
0x6f
,
0xd1
,
0xcb
,
0xf1
,
0x22
,
0xee
,
0x1b
,
0xc5
,
0x11
,
0x68
,
0x95
,
0xff
,
0xd5
,
0x83
,
0xbf
,
0x5f
,
0xcf
,
0x51
,
0xcc
,
0x2d
,
0xe2
,
0x8e
,
0x45
,
0xb3
,
0xcf
,
0x48
,
0x69
,
0x46
,
0xe7
,
0x06
,
0x24
,
0xdf
,
0x17
,
0x52
,
0xd6
,
0xa6
,
0xe2
,
0x3d
,
0x2c
,
0xd5
,
0x78
,
0x85
,
0xba
,
0x32
,
0xfa
,
0x09
,
0x1a
,
0xfd
,
0x68
,
0xf6
,
0x5f
,
0x37
,
0xdf
,
0xff
,
0x3b
,
0x92
,
0x1f
,
0x61
,
0xdb
,
0xa1
,
0x79
,
0x2c
,
0x2a
,
0xc5
,
0x76
,
0xa0
,
0xa5
,
0x14
,
0xd3
,
0x54
,
0xd6
,
0x2f
,
0xd0
,
0x34
,
0x35
,
0xe2
,
0x8e
,
0x45
,
0xb3
,
0xcf
,
0x48
,
0x86
,
0x37
,
0x15
,
0x95
,
0x66
,
0x19
,
0x5c
,
0x51
,
0x14
,
0x45
,
0x71
,
0xf2
,
0xaf
,
0x0c
,
0xc6
,
0x5f
,
0x1d
,
0x66
,
0x09
,
0x0c
,
0x48
,
0xbe
,
0x2c
,
0xf6
,
0x60
,
0xd5
,
0x7c
,
0xff
,
0x6c
,
0x5f
,
0xdf
,
0xc2
,
0x86
,
0x4c
,
0xf2
,
0xcb
,
0x83
,
0x07
,
0xb4
,
0xb7
,
0x23
,
0x51
,
0xa9
,
0x42
,
0x36
,
0x24
,
0x3f
,
0xfa
,
0xc3
,
0x43
,
0xf3
,
0x50
,
0x54
,
0x8a
,
0x6d
,
0x41
,
0x67
,
0x22
,
0x2a
,
0xcd
,
0x32
,
0xb8
,
0x22
,
0x37
,
0x8a
,
0xfa
,
0x86
,
0xb1
,
0xcc
,
0x29
,
0xf8
,
0xfb
,
0xb2
,
0x7a
,
0xce
,
0xb2
,
0xd8
,
0x63
,
0x88
,
0x72
,
0x21
,
0xe2
,
0xe4
,
0xbf
,
0xd4
,
0x18
,
0xff
,
0x72
,
0x63
,
0x92
,
0x6f
,
0x1e
,
0xfc
,
0x47
,
0x73
,
0x3b
,
0x10
,
0x91
,
0x5e
,
0x02
,
0x3b
,
0x9b
,
0xce
,
0x90
,
0xec
,
0x00
,
0x50
,
0x1b
,
0x37
,
0x5d
,
0x11
,
0x5f
,
0x3d
,
0x95
,
0x2a
,
0x64
,
0x4d
,
0xda
,
0xa4
,
0x3f
,
0xac
,
0xae
,
0x19
,
0xcb
,
0x9c
,
0x82
,
0x5f
,
0x0f
,
0xab
,
0x18
,
0x76
,
0x81
,
0xd4
,
0x68
,
0x77
,
0x4a
,
0xbc
,
0xa5
,
0x53
,
0x12
,
0x43
,
0x5f
,
0x9f
,
0x0c
,
0xac
,
0xe3
,
0x0c
,
0x8b
,
0xdd
,
0x83
,
0x28
,
0x17
,
0x12
,
0xe9
,
0x99
,
0xb0
,
0xbd
,
0x69
,
0x0d
,
0xc9
,
0x16
,
0x2a
,
0x3b
,
0xb7
,
0x16
,
0xae
,
0xa5
,
0x81
,
0x13
,
0x88
,
0x3a
,
0x4a
,
0xa3
,
0xa5
,
0xed
,
0xb6
,
0x93
,
0x00
,
0x95
,
0x71
,
0xd3
,
0xfd
,
0xf1
,
0xc9
,
0x83
,
0x41
,
0x1b
,
0x48
,
0x85
,
0xb6
,
0x5b
,
0xe2
,
0x2d
,
0x24
,
0xff
,
0x2d
,
0xf7
,
0xfa
,
0x19
,
0xb6
,
0x39
,
0x66
,
0x28
,
0x4a
,
0xd5
,
0xbe
,
0xa1
,
0x2c
,
0x81
,
0x6d
,
0x49
,
0x0c
,
0x3d
,
0xbd
,
0x19
,
0x58
,
0x55
,
0xb6
,
0x6f
,
0x0d
,
0x5c
,
0x49
,
0x01
,
0x47
,
0x10
,
0xb0
,
0x70
,
0x1e
,
0xce
,
0xe5
,
0xaa
,
0xc6
,
0xc5
,
0xc6
,
0xfa
,
0xbe
,
0x52
,
0xd9
,
0x84
,
0x8c
,
0xba
,
0xb5
,
0x94
,
0x36
,
0x97
,
0xa6
,
0xdb
,
0x74
,
0x92
,
0xfc
,
0xb7
,
0x9c
,
0xeb
,
0x07
,
0xd8
,
0xe0
,
0x98
,
0xef
,
0xab
,
0xff
,
0x77
,
0x03
,
0xba
,
0x5b
,
0x21
,
0x70
,
0x6e
,
0x85
,
0x3d
,
0xd0
,
0xb7
,
0x95
,
0xf9
,
0xa1
,
0x28
,
0x55
,
0xf3
,
0xc0
,
0xb2
,
0x04
,
0xc2
,
0xc2
,
0x79
,
0x55
,
0x97
,
0x4f
,
0x35
,
0x2e
,
0x36
,
0xeb
,
0xe9
,
0x26
,
0x3d
,
0xf0
,
0xfb
,
0x7f
,
0x02
,
0x00
,
0x00
,
0xff
,
0xff
,
0x99
,
0xd7
,
0x24
,
0x52
,
0xd4
,
0x97
,
0x99
,
0xca
,
0xc6
,
0x64
,
0xd4
,
0x75
,
0x5f
,
0xfd
,
0xbf
,
0x1b
,
0xd0
,
0xde
,
0x0a
,
0x81
,
0xf2
,
0x07
,
0x00
,
0x00
,
0x73
,
0x2b
,
0xec
,
0x80
,
0xbe
,
0xca
,
0xcc
,
0x5f
,
0x4f
,
0xba
,
0xf4
,
0xfa
,
0xef
,
0xfe
,
0x0c
,
0x00
,
0x00
,
0xff
,
0xff
,
0xf2
,
0x3c
,
0xac
,
0xed
,
0x0f
,
0x08
,
0x00
,
0x00
,
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment