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
ef710316
Commit
ef710316
authored
Dec 06, 2019
by
harrylee
Committed by
vipwzw
Dec 26, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add exchange dapp
parent
f3fe57bb
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
890 additions
and
0 deletions
+890
-0
Makefile
plugin/dapp/exchange/cmd/Makefile
+3
-0
build.sh
plugin/dapp/exchange/cmd/build.sh
+11
-0
commands.go
plugin/dapp/exchange/commands/commands.go
+23
-0
exchange.go
plugin/dapp/exchange/executor/exchange.go
+85
-0
exchange_test.go
plugin/dapp/exchange/executor/exchange_test.go
+15
-0
exchangedb.go
plugin/dapp/exchange/executor/exchangedb.go
+0
-0
exec.go
plugin/dapp/exchange/executor/exec.go
+29
-0
exec_del_local.go
plugin/dapp/exchange/executor/exec_del_local.go
+20
-0
exec_local.go
plugin/dapp/exchange/executor/exec_local.go
+190
-0
kv.go
plugin/dapp/exchange/executor/kv.go
+72
-0
query.go
plugin/dapp/exchange/executor/query.go
+69
-0
plugin.go
plugin/dapp/exchange/plugin.go
+23
-0
Makefile
plugin/dapp/exchange/proto/Makefile
+2
-0
create_protobuf.sh
plugin/dapp/exchange/proto/create_protobuf.sh
+4
-0
exchange.proto
plugin/dapp/exchange/proto/exchange.proto
+161
-0
rpc.go
plugin/dapp/exchange/rpc/rpc.go
+7
-0
types.go
plugin/dapp/exchange/rpc/types.go
+34
-0
errors.go
plugin/dapp/exchange/types/errors.go
+18
-0
exchange.go
plugin/dapp/exchange/types/exchange.go
+123
-0
exchange.pb.go
plugin/dapp/exchange/types/exchange.pb.go
+0
-0
init.go
plugin/dapp/init/init.go
+1
-0
No files found.
plugin/dapp/exchange/cmd/Makefile
0 → 100644
View file @
ef710316
all
:
chmod
+x ./build.sh
./build.sh
$(OUT)
$(FLAG)
plugin/dapp/exchange/cmd/build.sh
0 → 100755
View file @
ef710316
#!/bin/sh
# 官方ci集成脚本
strpwd
=
$(
pwd
)
strcmd
=
${
strpwd
##*dapp/
}
strapp
=
${
strcmd
%/cmd*
}
OUT_DIR
=
"
${
1
}
/
$strapp
"
#FLAG=$2
mkdir
-p
"
${
OUT_DIR
}
"
cp
./build/
*
"
${
OUT_DIR
}
"
plugin/dapp/exchange/commands/commands.go
0 → 100644
View file @
ef710316
/*Package commands implement dapp client commands*/
package
commands
import
(
"github.com/spf13/cobra"
)
/*
* 实现合约对应客户端
*/
// Cmd exchange client command
func
Cmd
()
*
cobra
.
Command
{
cmd
:=
&
cobra
.
Command
{
Use
:
"exchange"
,
Short
:
"exchange command"
,
Args
:
cobra
.
MinimumNArgs
(
1
),
}
cmd
.
AddCommand
(
//add sub command
)
return
cmd
}
plugin/dapp/exchange/executor/exchange.go
0 → 100644
View file @
ef710316
package
executor
import
(
log
"github.com/33cn/chain33/common/log/log15"
drivers
"github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
exchangetypes
"github.com/33cn/plugin/plugin/dapp/exchange/types"
)
/*
* 执行器相关定义
* 重载基类相关接口
*/
var
(
//日志
elog
=
log
.
New
(
"module"
,
"exchange.executor"
)
)
var
driverName
=
exchangetypes
.
ExchangeX
// Init register dapp
func
Init
(
name
string
,
cfg
*
types
.
Chain33Config
,
sub
[]
byte
)
{
drivers
.
Register
(
cfg
,
GetName
(),
newExchange
,
cfg
.
GetDappFork
(
driverName
,
"Enable"
))
InitExecType
()
}
// InitExecType Init Exec Type
func
InitExecType
()
{
ety
:=
types
.
LoadExecutorType
(
driverName
)
ety
.
InitFuncList
(
types
.
ListMethod
(
&
exchange
{}))
}
type
exchange
struct
{
drivers
.
DriverBase
}
func
newExchange
()
drivers
.
Driver
{
t
:=
&
exchange
{}
t
.
SetChild
(
t
)
t
.
SetExecutorType
(
types
.
LoadExecutorType
(
driverName
))
return
t
}
// GetName get driver name
func
GetName
()
string
{
return
newExchange
()
.
GetName
()
}
func
(
e
*
exchange
)
GetDriverName
()
string
{
return
driverName
}
// CheckTx 实现自定义检验交易接口,供框架调用
func
(
e
*
exchange
)
CheckTx
(
tx
*
types
.
Transaction
,
index
int
)
error
{
//发送交易的时候就检查payload,做严格的参数检查
var
exchange
exchangetypes
.
ExchangeAction
types
.
Decode
(
tx
.
GetPayload
(),
&
exchange
)
if
exchange
.
Ty
==
exchangetypes
.
TyLimitOrderAction
{
limitOrder
:=
exchange
.
GetLimitOrder
()
left
:=
limitOrder
.
GetLeftAsset
()
right
:=
limitOrder
.
GetRightAsset
()
price
:=
Truncate
(
limitOrder
.
GetPrice
())
amount
:=
limitOrder
.
GetAmount
()
op
:=
limitOrder
.
GetOp
()
if
!
CheckExchangeAsset
(
left
,
right
)
{
return
exchangetypes
.
ErrAsset
}
if
!
CheckPrice
(
price
)
{
return
exchangetypes
.
ErrAssetPrice
}
if
!
types
.
CheckAmount
(
amount
)
{
return
exchangetypes
.
ErrAssetAmount
}
if
!
CheckOp
(
op
)
{
return
exchangetypes
.
ErrAssetOp
}
}
return
nil
}
// GetPayloadValue get payload value
func
(
e
*
exchange
)
GetPayloadValue
()
types
.
Message
{
return
&
exchangetypes
.
ExchangeAction
{}
}
plugin/dapp/exchange/executor/exchange_test.go
0 → 100644
View file @
ef710316
package
executor
import
(
"testing"
)
func
TestTruncate
(
t
*
testing
.
T
)
{
a
:=
float32
(
1.00000212000000000001
)
b
:=
float32
(
0.34567
)
c
:=
float32
(
1234
)
t
.
Log
(
Truncate
(
a
))
t
.
Log
(
Truncate
(
b
))
t
.
Log
(
Truncate
(
c
))
}
\ No newline at end of file
plugin/dapp/exchange/executor/exchangedb.go
0 → 100644
View file @
ef710316
This diff is collapsed.
Click to expand it.
plugin/dapp/exchange/executor/exec.go
0 → 100644
View file @
ef710316
package
executor
import
(
"github.com/33cn/chain33/types"
exchangetypes
"github.com/33cn/plugin/plugin/dapp/exchange/types"
)
/*
* 实现交易的链上执行接口
* 关键数据上链(statedb)并生成交易回执(log)
*/
func
(
e
*
exchange
)
Exec_LimitOrder
(
payload
*
exchangetypes
.
LimitOrder
,
tx
*
types
.
Transaction
,
index
int
)
(
*
types
.
Receipt
,
error
)
{
var
receipt
*
types
.
Receipt
//implement code
return
receipt
,
nil
}
func
(
e
*
exchange
)
Exec_MarketOrder
(
payload
*
exchangetypes
.
MarketOrder
,
tx
*
types
.
Transaction
,
index
int
)
(
*
types
.
Receipt
,
error
)
{
var
receipt
*
types
.
Receipt
//implement code
return
receipt
,
nil
}
func
(
e
*
exchange
)
Exec_RevokeOrder
(
payload
*
exchangetypes
.
RevokeOrder
,
tx
*
types
.
Transaction
,
index
int
)
(
*
types
.
Receipt
,
error
)
{
var
receipt
*
types
.
Receipt
//implement code
return
receipt
,
nil
}
plugin/dapp/exchange/executor/exec_del_local.go
0 → 100644
View file @
ef710316
package
executor
import
(
"github.com/33cn/chain33/types"
)
/*
* 实现区块回退时本地执行的数据清除
*/
// ExecDelLocal 回退自动删除,重写基类
func
(
e
*
exchange
)
ExecDelLocal
(
tx
*
types
.
Transaction
,
receipt
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
)
{
kvs
,
err
:=
e
.
DelRollbackKV
(
tx
,
tx
.
Execer
)
if
err
!=
nil
{
return
nil
,
err
}
dbSet
:=
&
types
.
LocalDBSet
{}
dbSet
.
KV
=
append
(
dbSet
.
KV
,
kvs
...
)
return
dbSet
,
nil
}
plugin/dapp/exchange/executor/exec_local.go
0 → 100644
View file @
ef710316
package
executor
import
(
"github.com/33cn/chain33/types"
exchangetypes
"github.com/33cn/plugin/plugin/dapp/exchange/types"
)
/*
* 实现交易相关数据本地执行,数据不上链
* 非关键数据,本地存储(localDB), 用于辅助查询,效率高
*/
func
(
e
*
exchange
)
ExecLocal_LimitOrder
(
payload
*
exchangetypes
.
LimitOrder
,
tx
*
types
.
Transaction
,
receiptData
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
)
{
dbSet
:=
&
types
.
LocalDBSet
{}
if
receiptData
.
Ty
==
types
.
ExecOk
{
for
_
,
log
:=
range
receiptData
.
Logs
{
switch
log
.
Ty
{
case
exchangetypes
.
TyLimitOrderLog
:
receipt
:=
&
exchangetypes
.
ReceiptExchange
{}
if
err
:=
types
.
Decode
(
log
.
Log
,
receipt
);
err
!=
nil
{
return
nil
,
err
}
kv
:=
e
.
updateIndex
(
receipt
)
dbSet
.
KV
=
append
(
dbSet
.
KV
,
kv
...
)
}
}
}
return
e
.
addAutoRollBack
(
tx
,
dbSet
.
KV
),
nil
}
func
(
e
*
exchange
)
ExecLocal_MarketOrder
(
payload
*
exchangetypes
.
MarketOrder
,
tx
*
types
.
Transaction
,
receiptData
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
)
{
dbSet
:=
&
types
.
LocalDBSet
{}
//implement code
return
e
.
addAutoRollBack
(
tx
,
dbSet
.
KV
),
nil
}
func
(
e
*
exchange
)
ExecLocal_RevokeOrder
(
payload
*
exchangetypes
.
RevokeOrder
,
tx
*
types
.
Transaction
,
receiptData
*
types
.
ReceiptData
,
index
int
)
(
*
types
.
LocalDBSet
,
error
)
{
dbSet
:=
&
types
.
LocalDBSet
{}
//implement code
return
e
.
addAutoRollBack
(
tx
,
dbSet
.
KV
),
nil
}
//设置自动回滚
func
(
e
*
exchange
)
addAutoRollBack
(
tx
*
types
.
Transaction
,
kv
[]
*
types
.
KeyValue
)
*
types
.
LocalDBSet
{
dbSet
:=
&
types
.
LocalDBSet
{}
dbSet
.
KV
=
e
.
AddRollbackKV
(
tx
,
tx
.
Execer
,
kv
)
return
dbSet
}
func
(
e
*
exchange
)
updateIndex
(
receipt
*
exchangetypes
.
ReceiptExchange
)
(
kvs
[]
*
types
.
KeyValue
)
{
switch
receipt
.
Order
.
Status
{
case
exchangetypes
.
Ordered
:
left
:=
receipt
.
GetOrder
()
.
GetLimitOrder
()
.
GetLeftAsset
()
right
:=
receipt
.
GetOrder
()
.
GetLimitOrder
()
.
GetRightAsset
()
op
:=
receipt
.
GetOrder
()
.
GetLimitOrder
()
.
GetOp
()
price
:=
receipt
.
GetOrder
()
.
GetLimitOrder
()
.
GetPrice
()
oderID
:=
receipt
.
GetOrder
()
.
OrderID
index
:=
receipt
.
GetIndex
()
addr
:=
receipt
.
GetOrder
()
.
Addr
var
markDepth
exchangetypes
.
MarketDepth
err
:=
findObject
(
e
.
GetLocalDB
(),
calcMarketDepthKey
(
left
,
right
,
op
,
price
),
&
markDepth
)
if
err
==
types
.
ErrNotFound
{
markDepth
.
Price
=
price
markDepth
.
LeftAsset
=
left
markDepth
.
RightAsset
=
right
markDepth
.
Op
=
op
markDepth
.
Amount
=
receipt
.
Order
.
Balance
}
markDepth
.
Amount
=
markDepth
.
Amount
+
receipt
.
Order
.
Balance
//marketDepth
kvs
=
append
(
kvs
,
&
types
.
KeyValue
{
Key
:
calcMarketDepthKey
(
left
,
right
,
op
,
price
),
Value
:
types
.
Encode
(
&
markDepth
)})
//orderID
kvs
=
append
(
kvs
,
&
types
.
KeyValue
{
Key
:
calcMarketDepthOrderKey
(
left
,
right
,
op
,
price
,
receipt
.
Index
),
Value
:
types
.
Encode
(
&
exchangetypes
.
OrderID
{
ID
:
oderID
,
Index
:
index
})})
//addr orderID
kvs
=
append
(
kvs
,
&
types
.
KeyValue
{
Key
:
calcUserOrderIDKey
(
exchangetypes
.
Ordered
,
addr
,
index
),
Value
:
types
.
Encode
(
&
exchangetypes
.
OrderID
{
ID
:
oderID
,
Index
:
index
})})
if
len
(
receipt
.
MatchOrders
)
>
0
{
//撮合交易更新
var
balance
int64
for
_
,
matchOrder
:=
range
receipt
.
MatchOrders
{
if
matchOrder
.
Status
==
exchangetypes
.
Completed
{
// 删除原有状态orderID
kvs
=
append
(
kvs
,
&
types
.
KeyValue
{
Key
:
calcMarketDepthOrderKey
(
left
,
right
,
matchOrder
.
GetLimitOrder
()
.
Op
,
price
,
matchOrder
.
Index
),
Value
:
nil
})
//删除原有状态orderID
kvs
=
append
(
kvs
,
&
types
.
KeyValue
{
Key
:
calcUserOrderIDKey
(
exchangetypes
.
Ordered
,
matchOrder
.
Addr
,
matchOrder
.
Index
),
Value
:
nil
})
//更新状态为已完成,索引index,改为当前的index
kvs
=
append
(
kvs
,
&
types
.
KeyValue
{
Key
:
calcUserOrderIDKey
(
exchangetypes
.
Completed
,
matchOrder
.
Addr
,
index
),
Value
:
types
.
Encode
(
&
exchangetypes
.
OrderID
{
ID
:
matchOrder
.
OrderID
,
Index
:
index
})})
//calcCompletedOrderKey
kvs
=
append
(
kvs
,
&
types
.
KeyValue
{
Key
:
calcCompletedOrderKey
(
left
,
right
,
index
),
Value
:
types
.
Encode
(
&
exchangetypes
.
OrderID
{
ID
:
matchOrder
.
OrderID
,
Index
:
index
})})
}
if
matchOrder
.
Status
==
exchangetypes
.
Ordered
{
//只需统一更改市场深度状态,其他不需要处理
balance
=
balance
+
matchOrder
.
Balance
}
}
//更改市场深度
var
matchDepth
exchangetypes
.
MarketDepth
err
=
findObject
(
e
.
GetLocalDB
(),
calcMarketDepthKey
(
left
,
right
,
OpSwap
(
op
),
price
),
&
matchDepth
)
if
err
==
types
.
ErrNotFound
{
matchDepth
.
Price
=
price
matchDepth
.
LeftAsset
=
left
matchDepth
.
RightAsset
=
right
matchDepth
.
Op
=
OpSwap
(
op
)
matchDepth
.
Amount
=
balance
}
matchDepth
.
Amount
=
matchDepth
.
Amount
-
receipt
.
Order
.
Executed
//marketDepth
kvs
=
append
(
kvs
,
&
types
.
KeyValue
{
Key
:
calcMarketDepthKey
(
left
,
right
,
OpSwap
(
op
),
price
),
Value
:
types
.
Encode
(
&
matchDepth
)})
}
return
case
exchangetypes
.
Completed
:
left
:=
receipt
.
GetOrder
()
.
GetLimitOrder
()
.
GetLeftAsset
()
right
:=
receipt
.
GetOrder
()
.
GetLimitOrder
()
.
GetRightAsset
()
op
:=
receipt
.
GetOrder
()
.
GetLimitOrder
()
.
GetOp
()
price
:=
receipt
.
GetOrder
()
.
GetLimitOrder
()
.
GetPrice
()
oderID
:=
receipt
.
GetOrder
()
.
OrderID
index
:=
receipt
.
GetIndex
()
addr
:=
receipt
.
GetOrder
()
.
Addr
//user orderID
kvs
=
append
(
kvs
,
&
types
.
KeyValue
{
Key
:
calcUserOrderIDKey
(
exchangetypes
.
Completed
,
addr
,
index
),
Value
:
types
.
Encode
(
&
exchangetypes
.
OrderID
{
ID
:
oderID
,
Index
:
index
})})
if
len
(
receipt
.
MatchOrders
)
>
0
{
//撮合交易更新
var
balance
int64
for
_
,
matchOrder
:=
range
receipt
.
MatchOrders
{
if
matchOrder
.
Status
==
exchangetypes
.
Completed
{
// 删除原有状态orderID
kvs
=
append
(
kvs
,
&
types
.
KeyValue
{
Key
:
calcMarketDepthOrderKey
(
left
,
right
,
matchOrder
.
GetLimitOrder
()
.
Op
,
price
,
matchOrder
.
Index
),
Value
:
nil
})
//删除原有状态orderID
kvs
=
append
(
kvs
,
&
types
.
KeyValue
{
Key
:
calcUserOrderIDKey
(
exchangetypes
.
Ordered
,
matchOrder
.
Addr
,
matchOrder
.
Index
),
Value
:
nil
})
//更新状态为已完成,更新索引
kvs
=
append
(
kvs
,
&
types
.
KeyValue
{
Key
:
calcUserOrderIDKey
(
exchangetypes
.
Completed
,
matchOrder
.
Addr
,
index
),
Value
:
types
.
Encode
(
&
exchangetypes
.
OrderID
{
ID
:
matchOrder
.
OrderID
,
Index
:
index
})})
//calcCompletedOrderKey
kvs
=
append
(
kvs
,
&
types
.
KeyValue
{
Key
:
calcCompletedOrderKey
(
left
,
right
,
index
),
Value
:
types
.
Encode
(
&
exchangetypes
.
OrderID
{
ID
:
matchOrder
.
OrderID
,
Index
:
index
})})
}
if
matchOrder
.
Status
==
exchangetypes
.
Ordered
{
//只需统一更改市场深度状态,其他不需要处理
balance
=
balance
+
matchOrder
.
Balance
}
}
//更改match市场深度
var
matchDepth
exchangetypes
.
MarketDepth
err
:=
findObject
(
e
.
GetLocalDB
(),
calcMarketDepthKey
(
left
,
right
,
OpSwap
(
op
),
price
),
&
matchDepth
)
if
err
==
types
.
ErrNotFound
{
matchDepth
.
Price
=
price
matchDepth
.
LeftAsset
=
left
matchDepth
.
RightAsset
=
right
matchDepth
.
Op
=
OpSwap
(
op
)
matchDepth
.
Amount
=
balance
}
matchDepth
.
Amount
=
matchDepth
.
Amount
-
receipt
.
Order
.
Executed
//marketDepth
kvs
=
append
(
kvs
,
&
types
.
KeyValue
{
Key
:
calcMarketDepthKey
(
left
,
right
,
OpSwap
(
op
),
price
),
Value
:
types
.
Encode
(
&
matchDepth
)})
}
return
case
exchangetypes
.
Revoked
:
//只有状态时ordered状态的订单才能被撤回
left
:=
receipt
.
GetOrder
()
.
GetLimitOrder
()
.
GetLeftAsset
()
right
:=
receipt
.
GetOrder
()
.
GetLimitOrder
()
.
GetRightAsset
()
op
:=
receipt
.
GetOrder
()
.
GetLimitOrder
()
.
GetOp
()
price
:=
receipt
.
GetOrder
()
.
GetLimitOrder
()
.
GetPrice
()
oderID
:=
receipt
.
GetOrder
()
.
OrderID
index
:=
receipt
.
GetIndex
()
addr
:=
receipt
.
GetOrder
()
.
Addr
var
marketDepth
exchangetypes
.
MarketDepth
err
:=
findObject
(
e
.
GetLocalDB
(),
calcMarketDepthKey
(
left
,
right
,
op
,
price
),
&
marketDepth
)
if
err
==
nil
{
//marketDepth
marketDepth
.
Amount
=
marketDepth
.
Amount
-
receipt
.
GetOrder
()
.
Balance
kvs
=
append
(
kvs
,
&
types
.
KeyValue
{
Key
:
calcMarketDepthKey
(
left
,
right
,
op
,
price
),
Value
:
types
.
Encode
(
&
marketDepth
)})
}
// 删除原有状态orderID
kvs
=
append
(
kvs
,
&
types
.
KeyValue
{
Key
:
calcMarketDepthOrderKey
(
left
,
right
,
op
,
price
,
receipt
.
GetOrder
()
.
Index
),
Value
:
nil
})
//删除原有状态orderID
kvs
=
append
(
kvs
,
&
types
.
KeyValue
{
Key
:
calcUserOrderIDKey
(
exchangetypes
.
Ordered
,
addr
,
receipt
.
GetOrder
()
.
Index
),
Value
:
nil
})
//添加撤销的订单
kvs
=
append
(
kvs
,
&
types
.
KeyValue
{
Key
:
calcUserOrderIDKey
(
exchangetypes
.
Revoked
,
addr
,
index
),
Value
:
types
.
Encode
(
&
exchangetypes
.
OrderID
{
ID
:
oderID
,
Index
:
index
})})
}
return
}
func
OpSwap
(
op
int32
)
int32
{
if
op
==
exchangetypes
.
OpBuy
{
return
exchangetypes
.
OpSell
}
else
{
return
exchangetypes
.
OpBuy
}
}
plugin/dapp/exchange/executor/kv.go
0 → 100644
View file @
ef710316
package
executor
import
(
"fmt"
"github.com/33cn/plugin/plugin/dapp/exchange/types"
)
/*
* 用户合约存取kv数据时,key值前缀需要满足一定规范
* 即key = keyPrefix + userKey
* 需要字段前缀查询时,使用’-‘作为分割符号
*/
var
(
//KeyPrefixStateDB state db key必须前缀
KeyPrefixStateDB
=
"mavl-exchange-"
//KeyPrefixLocalDB local db的key必须前缀
KeyPrefixLocalDB
=
"LODB-exchange-"
)
//状态数据库中存储具体挂单信息
func
calcOrderKey
(
orderID
string
)
[]
byte
{
key
:=
fmt
.
Sprintf
(
"%s"
+
"orderID:%s"
,
KeyPrefixStateDB
,
orderID
)
return
[]
byte
(
key
)
}
func
calcMarketDepthPrefix
(
left
,
right
*
types
.
Asset
,
op
int32
)
[]
byte
{
key
:=
fmt
.
Sprintf
(
"%s"
+
"depth-%s-%s-%d:"
,
KeyPrefixLocalDB
,
left
.
GetSymbol
(),
right
.
GetSymbol
(),
op
)
return
[]
byte
(
key
)
}
//市场深度
func
calcMarketDepthKey
(
left
,
right
*
types
.
Asset
,
op
int32
,
price
float32
)
[]
byte
{
// 设置精度为1e8
key
:=
fmt
.
Sprintf
(
"%s"
+
"depth-%s-%s-%d:%016d"
,
KeyPrefixLocalDB
,
left
.
GetSymbol
(),
right
.
GetSymbol
(),
op
,
int64
(
Truncate
(
price
)
*
float32
(
1e8
)))
return
[]
byte
(
key
)
}
func
calcMarketDepthOrderPrefix
(
left
,
right
*
types
.
Asset
,
op
int32
,
price
float32
)
[]
byte
{
// 设置精度为1e8
key
:=
fmt
.
Sprintf
(
"%s"
+
"order-%s-%s-%d:%016d"
,
KeyPrefixLocalDB
,
left
.
GetSymbol
(),
right
.
GetSymbol
(),
op
,
int64
(
Truncate
(
price
)
*
float32
(
1e8
)))
return
[]
byte
(
key
)
}
// localdb中存储市场挂单ID
func
calcMarketDepthOrderKey
(
left
,
right
*
types
.
Asset
,
op
int32
,
price
float32
,
index
int64
)
[]
byte
{
// 设置精度为1e8
key
:=
fmt
.
Sprintf
(
"%s"
+
"order-%s-%s-%d:%016d:%018d"
,
KeyPrefixLocalDB
,
left
.
GetSymbol
(),
right
.
GetSymbol
(),
op
,
int64
(
Truncate
(
price
)
*
float32
(
1e8
)),
index
)
return
[]
byte
(
key
)
}
//最新已经成交的订单,这里状态固定都是完成状态,这个主要给外部使用,可以查询最新得成交信息
func
calcCompletedOrderKey
(
left
,
right
*
types
.
Asset
,
index
int64
)
[]
byte
{
// 设置精度为1e8
key
:=
fmt
.
Sprintf
(
"%s"
+
"completed-%s-%s-%d:%018d"
,
KeyPrefixLocalDB
,
left
.
GetSymbol
(),
right
.
GetSymbol
(),
types
.
Completed
,
index
)
return
[]
byte
(
key
)
}
func
calcCompletedOrderPrefix
(
left
,
right
*
types
.
Asset
)
[]
byte
{
// 设置精度为1e8
key
:=
fmt
.
Sprintf
(
"%s"
+
"completed-%s-%s-%d:"
,
KeyPrefixLocalDB
,
left
.
GetSymbol
(),
right
.
GetSymbol
(),
types
.
Completed
)
return
[]
byte
(
key
)
}
//根据地址和订单状态,去查询订单列表,包含所有交易对
func
calcUserOrderIDPrefix
(
status
int32
,
addr
string
)
[]
byte
{
key
:=
fmt
.
Sprintf
(
"%s"
+
"addr:%s:%d:"
,
KeyPrefixLocalDB
,
addr
,
status
)
return
[]
byte
(
key
)
}
func
calcUserOrderIDKey
(
status
int32
,
addr
string
,
index
int64
)
[]
byte
{
key
:=
fmt
.
Sprintf
(
"%s"
+
"addr:%s:%d:%018d"
,
KeyPrefixLocalDB
,
addr
,
status
,
index
)
return
[]
byte
(
key
)
}
plugin/dapp/exchange/executor/query.go
0 → 100644
View file @
ef710316
package
executor
import
(
"github.com/33cn/chain33/types"
et
"github.com/33cn/plugin/plugin/dapp/exchange/types"
)
//查询市场深度
func
(
s
*
exchange
)
Query_QueryMarketDepth
(
in
*
et
.
QueryMarketDepth
)
(
types
.
Message
,
error
)
{
if
!
CheckCount
(
in
.
Count
)
{
return
nil
,
et
.
ErrCount
}
if
in
.
Count
==
0
{
in
.
Count
=
10
}
if
!
CheckExchangeAsset
(
in
.
LeftAsset
,
in
.
RightAsset
)
{
return
nil
,
et
.
ErrAsset
}
if
!
CheckPrice
(
in
.
Price
)
{
return
nil
,
et
.
ErrAssetPrice
}
if
!
CheckOp
(
in
.
Op
)
{
return
nil
,
et
.
ErrAssetOp
}
return
QueryMarketDepth
(
s
.
GetLocalDB
(),
in
.
LeftAsset
,
in
.
RightAsset
,
in
.
Op
,
in
.
Price
,
in
.
Count
)
}
//查询已经完成得订单
func
(
s
*
exchange
)
Query_QueryCompletedOrderList
(
in
*
et
.
QueryCompletedOrderList
)
(
types
.
Message
,
error
)
{
if
!
CheckExchangeAsset
(
in
.
LeftAsset
,
in
.
RightAsset
)
{
return
nil
,
et
.
ErrAsset
}
if
in
.
Count
>
20
{
return
nil
,
et
.
ErrCount
}
if
!
CheckDirection
(
in
.
Direction
)
{
return
nil
,
et
.
ErrDirection
}
return
QueryCompletedOrderList
(
s
.
GetLocalDB
(),
s
.
GetStateDB
(),
in
.
LeftAsset
,
in
.
RightAsset
,
in
.
Index
,
in
.
Count
,
in
.
Direction
)
}
//根据orderID查询订单信息
func
(
s
*
exchange
)
Query_QueryOrder
(
in
*
et
.
QueryOrder
)
(
types
.
Message
,
error
)
{
if
in
.
OrderID
==
""
{
return
nil
,
et
.
ErrOrderID
}
return
findOrderByOrderID
(
s
.
GetStateDB
(),
in
.
OrderID
)
}
//根据订单状态,查询订单信息(这里面包含所有交易对)
func
(
s
*
exchange
)
Query_QueryOrderList
(
in
*
et
.
QueryOrderList
)
(
types
.
Message
,
error
)
{
if
!
CheckStatus
(
in
.
Status
)
{
return
nil
,
et
.
ErrStatus
}
if
!
CheckCount
(
in
.
Count
)
{
return
nil
,
et
.
ErrCount
}
if
!
CheckDirection
(
in
.
Direction
)
{
return
nil
,
et
.
ErrDirection
}
if
in
.
Address
==
""
{
return
nil
,
et
.
ErrAddr
}
return
QueryOrderList
(
s
.
GetLocalDB
(),
s
.
GetStateDB
(),
in
.
Address
,
in
.
Status
,
in
.
Count
,
in
.
Direction
,
in
.
Index
)
}
plugin/dapp/exchange/plugin.go
0 → 100644
View file @
ef710316
package
types
import
(
"github.com/33cn/chain33/pluginmgr"
"github.com/33cn/plugin/plugin/dapp/exchange/commands"
"github.com/33cn/plugin/plugin/dapp/exchange/executor"
"github.com/33cn/plugin/plugin/dapp/exchange/rpc"
exchangetypes
"github.com/33cn/plugin/plugin/dapp/exchange/types"
)
/*
* 初始化dapp相关的组件
*/
func
init
()
{
pluginmgr
.
Register
(
&
pluginmgr
.
PluginBase
{
Name
:
exchangetypes
.
ExchangeX
,
ExecName
:
executor
.
GetName
(),
Exec
:
executor
.
Init
,
Cmd
:
commands
.
Cmd
,
RPC
:
rpc
.
Init
,
})
}
plugin/dapp/exchange/proto/Makefile
0 → 100644
View file @
ef710316
all
:
./create_protobuf.sh
plugin/dapp/exchange/proto/create_protobuf.sh
0 → 100644
View file @
ef710316
#!/bin/sh
# proto生成命令,将pb.go文件生成到types/目录下, chain33_path支持引用chain33框架的proto文件
chain33_path
=
$(
go list
-f
'{{.Dir}}'
"github.com/33cn/chain33"
)
protoc
--go_out
=
plugins
=
grpc:../types ./
*
.proto
--proto_path
=
.
--proto_path
=
"
${
chain33_path
}
/types/proto/"
plugin/dapp/exchange/proto/exchange.proto
0 → 100644
View file @
ef710316
syntax
=
"proto3"
;
package
types
;
message
Exchange
{
}
message
ExchangeAction
{
oneof
value
{
LimitOrder
limitOrder
=
1
;
// MarketOrder marketOrder = 2;
RevokeOrder
revokeOrder
=
3
;
}
int32
ty
=
6
;
}
//限价订单
message
LimitOrder
{
//交易对
Asset
leftAsset
=
1
;
//交易对
Asset
rightAsset
=
2
;
//价格
float
price
=
3
;
//总量
int64
amount
=
4
;
//操作, 1为买,2为卖
int32
op
=
5
;
}
//市价委托
message
MarketOrder
{
//资产1
Asset
leftAsset
=
1
;
//资产2
Asset
rightAsset
=
2
;
//总量
int64
amount
=
3
;
//操作, 1为买,2为卖
int32
op
=
4
;
}
//撤回订单
message
RevokeOrder
{
//订单号
string
orderID
=
1
;
}
//资产类型
message
Asset
{
string
execer
=
1
;
string
symbol
=
2
;
}
//订单信息
message
Order
{
string
orderID
=
1
;
oneof
value
{
LimitOrder
limitOrder
=
2
;
MarketOrder
marketOrder
=
3
;
}
//挂单类型
int32
ty
=
4
;
//已经成交的数量
int64
executed
=
5
;
//余额
int64
balance
=
6
;
//状态,0 挂单中ordered, 1 完成completed, 2撤回 revoked
int32
status
=
7
;
//用户地址
string
addr
=
8
;
//更新时间
int64
updateTime
=
9
;
//索引
int64
index
=
10
;
}
//挂单价
message
OrderPrice
{
float
price
=
1
;
int64
index
=
2
;
}
//单号
message
OrderID
{
string
ID
=
1
;
int64
index
=
2
;
}
//查询接口
message
QueryMarketDepth
{
//资产1
Asset
leftAsset
=
1
;
//资产2
Asset
rightAsset
=
2
;
//操作, 1为买,2为卖
int32
op
=
3
;
// 这里用价格作为索引值
float
price
=
4
;
//单页返回多少条记录,默认返回10条,为了系统安全最多单次只能返回20条
int32
count
=
5
;
}
//市场深度
message
MarketDepth
{
//资产1
Asset
leftAsset
=
1
;
//资产2
Asset
rightAsset
=
2
;
//价格
float
price
=
3
;
//总量
int64
amount
=
4
;
//操作, 1为买,2为卖
int32
op
=
5
;
}
//查询接口返回的市场深度列表
message
MarketDepthList
{
repeated
MarketDepth
list
=
1
;
}
//查询最新得成交信息,外部接口
message
QueryCompletedOrderList
{
//资产1
Asset
leftAsset
=
1
;
//资产2
Asset
rightAsset
=
2
;
// 索引值
int64
index
=
3
;
//单页返回多少条记录,默认返回10条,为了系统安全最多单次只能返回20条
int32
count
=
4
;
// 0降序,1升序,默认降序
int32
direction
=
5
;
}
//根据orderID去查询订单信息
message
QueryOrder
{
string
orderID
=
1
;
}
//根据地址,状态查询用户自己的挂单信息
message
QueryOrderList
{
//挂单状态必填(默认是0,只查询ordered挂单中的)
int32
status
=
1
;
//用户地址信息,必填
string
address
=
2
;
// 索引值
int64
index
=
3
;
//单页返回多少条记录,默认返回10条,为了系统安全最多单次只能返回20条
int32
count
=
4
;
// 0降序,1升序,默认降序
int32
direction
=
5
;
}
//订单列表
message
OrderList
{
repeated
Order
list
=
1
;
}
//exchange执行票据日志
message
ReceiptExchange
{
Order
order
=
1
;
repeated
Order
matchOrders
=
2
;
int64
index
=
3
;
}
service
exchange
{
}
plugin/dapp/exchange/rpc/rpc.go
0 → 100644
View file @
ef710316
package
rpc
/*
* 实现json rpc和grpc service接口
* json rpc用Jrpc结构作为接收实例
* grpc使用channelClient结构作为接收实例
*/
plugin/dapp/exchange/rpc/types.go
0 → 100644
View file @
ef710316
package
rpc
import
(
rpctypes
"github.com/33cn/chain33/rpc/types"
exchangetypes
"github.com/33cn/plugin/plugin/dapp/exchange/types"
)
/*
* rpc相关结构定义和初始化
*/
// 实现grpc的service接口
type
channelClient
struct
{
rpctypes
.
ChannelClient
}
// Jrpc 实现json rpc调用实例
type
Jrpc
struct
{
cli
*
channelClient
}
// Grpc grpc
type
Grpc
struct
{
*
channelClient
}
// Init init rpc
func
Init
(
name
string
,
s
rpctypes
.
RPCServer
)
{
cli
:=
&
channelClient
{}
grpc
:=
&
Grpc
{
channelClient
:
cli
}
cli
.
Init
(
name
,
s
,
&
Jrpc
{
cli
:
cli
},
grpc
)
//存在grpc service时注册grpc server,需要生成对应的pb.go文件
exchangetypes
.
RegisterExchangeServer
(
s
.
GRPC
(),
grpc
)
}
plugin/dapp/exchange/types/errors.go
0 → 100644
View file @
ef710316
package
types
import
"fmt"
// some errors definition
var
(
ErrAssetAmount
=
fmt
.
Errorf
(
"%s"
,
"The asset amount is not valid!"
)
ErrAssetPrice
=
fmt
.
Errorf
(
"%s"
,
"The asset price is not valid!"
)
ErrAssetOp
=
fmt
.
Errorf
(
"%s"
,
"The asset op is not define!"
)
ErrAssetBalance
=
fmt
.
Errorf
(
"%s"
,
"Insufficient balance!"
)
ErrOrderSatus
=
fmt
.
Errorf
(
"%s"
,
"The order status is reovked or completed!"
)
ErrAddr
=
fmt
.
Errorf
(
"%s"
,
"Wrong Addr!"
)
ErrAsset
=
fmt
.
Errorf
(
"%s"
,
"The asset's execer or symbol can't be nil,The same assets cannot be exchanged!"
)
ErrCount
=
fmt
.
Errorf
(
"%s"
,
"The param count can't large 20"
)
ErrDirection
=
fmt
.
Errorf
(
"%s"
,
"The direction only 0 or 1!"
)
ErrStatus
=
fmt
.
Errorf
(
"%s"
,
"The status only in 0 , 1, 2!"
)
ErrOrderID
=
fmt
.
Errorf
(
"%s"
,
"Wrong OrderID!"
)
)
plugin/dapp/exchange/types/exchange.go
0 → 100644
View file @
ef710316
package
types
import
(
log
"github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/types"
)
/*
* 交易相关类型定义
* 交易action通常有对应的log结构,用于交易回执日志记录
* 每一种action和log需要用id数值和name名称加以区分
*/
// action类型id和name,这些常量可以自定义修改
const
(
TyUnknowAction
=
iota
+
200
TyLimitOrderAction
TyMarketOrderAction
TyRevokeOrderAction
NameLimitOrderAction
=
"LimitOrder"
NameMarketOrderAction
=
"MarketOrder"
NameRevokeOrderAction
=
"RevokeOrder"
FuncNameQueryMarketDepth
=
"QueryMarketDepth"
FuncNameQueryCompletedOrderList
=
"QueryCompletedOrderList"
FuncNameQueryOrder
=
"QueryOrder"
FuncNameQueryOrderList
=
"QueryOrderList"
)
// log类型id值
const
(
TyUnknownLog
=
iota
+
200
TyLimitOrderLog
TyMarketOrderLog
TyRevokeOrderLog
)
// OP
const
(
OpBuy
=
iota
+
1
OpSell
)
//order status
const
(
Ordered
=
iota
Completed
Revoked
)
//const
const
(
ListDESC
=
int32
(
0
)
ListASC
=
int32
(
1
)
ListSeek
=
int32
(
2
)
)
//单次list还回条数
const
(
Count
=
int32
(
5
)
MaxCount
=
int32
(
20
)
)
var
(
//ExchangeX 执行器名称定义
ExchangeX
=
"exchange"
//定义actionMap
actionMap
=
map
[
string
]
int32
{
NameLimitOrderAction
:
TyLimitOrderAction
,
NameMarketOrderAction
:
TyMarketOrderAction
,
NameRevokeOrderAction
:
TyRevokeOrderAction
,
}
//定义log的id和具体log类型及名称,填入具体自定义log类型
logMap
=
map
[
int64
]
*
types
.
LogInfo
{
//LogID: {Ty: reflect.TypeOf(LogStruct), Name: LogName},
}
tlog
=
log
.
New
(
"module"
,
"exchange.types"
)
)
// init defines a register function
func
init
()
{
types
.
AllowUserExec
=
append
(
types
.
AllowUserExec
,
[]
byte
(
ExchangeX
))
//注册合约启用高度
types
.
RegFork
(
ExchangeX
,
InitFork
)
types
.
RegExec
(
ExchangeX
,
InitExecutor
)
}
// InitFork defines register fork
func
InitFork
(
cfg
*
types
.
Chain33Config
)
{
cfg
.
RegisterDappFork
(
ExchangeX
,
"Enable"
,
0
)
}
// InitExecutor defines register executor
func
InitExecutor
(
cfg
*
types
.
Chain33Config
)
{
types
.
RegistorExecutor
(
ExchangeX
,
NewType
(
cfg
))
}
type
exchangeType
struct
{
types
.
ExecTypeBase
}
func
NewType
(
cfg
*
types
.
Chain33Config
)
*
exchangeType
{
c
:=
&
exchangeType
{}
c
.
SetChild
(
c
)
c
.
SetConfig
(
cfg
)
return
c
}
// GetPayload 获取合约action结构
func
(
e
*
exchangeType
)
GetPayload
()
types
.
Message
{
return
&
ExchangeAction
{}
}
// GeTypeMap 获取合约action的id和name信息
func
(
e
*
exchangeType
)
GetTypeMap
()
map
[
string
]
int32
{
return
actionMap
}
// GetLogMap 获取合约log相关信息
func
(
e
*
exchangeType
)
GetLogMap
()
map
[
int64
]
*
types
.
LogInfo
{
return
logMap
}
plugin/dapp/exchange/types/exchange.pb.go
0 → 100644
View file @
ef710316
This diff is collapsed.
Click to expand it.
plugin/dapp/init/init.go
View file @
ef710316
...
...
@@ -7,6 +7,7 @@ import (
_
"github.com/33cn/plugin/plugin/dapp/dposvote"
//auto gen
_
"github.com/33cn/plugin/plugin/dapp/echo"
//auto gen
_
"github.com/33cn/plugin/plugin/dapp/evm"
//auto gen
_
"github.com/33cn/plugin/plugin/dapp/exchange"
//auto gen
_
"github.com/33cn/plugin/plugin/dapp/game"
//auto gen
_
"github.com/33cn/plugin/plugin/dapp/guess"
//auto gen
_
"github.com/33cn/plugin/plugin/dapp/hashlock"
//auto gen
...
...
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