Start sketching out the orderbook app

Co-authored-by: samricotta <samricotta@users.noreply.github.com>
This commit is contained in:
Callum Waters
2022-10-06 09:31:50 +02:00
parent abbeb919df
commit e7e48024ca
7 changed files with 1211 additions and 0 deletions

View File

@@ -0,0 +1,220 @@
package orderbook
import (
"errors"
"fmt"
"github.com/cosmos/gogoproto/proto"
dbm "github.com/tendermint/tm-db"
"github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/ed25519"
)
var _ types.Application = (*StateMachine)(nil)
//TO DO: Error codes
type StateMachine struct {
// persisted state
db dbm.DB
// in-memory state
accounts map[uint64]*Account
commodities map[uint64]*Commodity
// app-side mempool
markets map[string]*Market // i.e. ATOM/USDC
}
func New() *StateMachine {
return &StateMachine{}
}
func (sm *StateMachine) Info(req types.RequestInfo) types.ResponseInfo {
return types.ResponseInfo{}
}
func (sm *StateMachine) DeliverTx(req types.RequestDeliverTx) types.ResponseDeliverTx {
return types.ResponseDeliverTx{Code: 0}
}
// CheckTx to be stateless
func (sm *StateMachine) CheckTx(req types.RequestCheckTx) types.ResponseCheckTx {
var msg = new(Msg)
err := proto.Unmarshal(req.Tx, msg)
if err != nil {
return types.ResponseCheckTx{Code: 1} // decoding error
}
// validations for each msg below
switch m := msg.Sum.(type) {
case *Msg_MsgRegisterPair:
//mustnt already have the same pair
// inbound can also be outbound for pair
case *Msg_MsgCreateAccount:
if m.MsgCreateAccount.ValidateBasic(); err != nil {
return types.ResponseCheckTx{Code: 3}
}
//check there is no other account with the same public key
case *Msg_MsgPlaceOrder:
if err := m.MsgPlaceOrder.ValidateBasic(); err != nil {
return types.ResponseCheckTx{Code: 3, Log: err.Error()}
}
// check if account exists
if _, ok := sm.accounts[m.MsgPlaceOrder.Order.Owner]; !ok {
return types.ResponseCheckTx{Code: 4}
}
// check the commodity exists
if _, ok := sm.commodities[m.MsgPlaceOrder.Order.QuantityOutbound]; !ok {
return types.ResponseCheckTx{Code: 4}
}
// check the commodity has a high enough quantity
if err := sm.commodities[m.MsgPlaceOrder.Pair].Quantity >= m.MsgPlaceOrder.Order.QuantityOutbound; !ok {
}
// check if pair is registered
if _, ok := sm.markets[m.MsgPlaceOrder.Pair.String()]; !ok {
return types.ResponseCheckTx{Code: 4}
}
default:
return types.ResponseCheckTx{Code: 2} // unknown message type
}
return types.ResponseCheckTx{Code: 0}
}
func (sm *StateMachine) Commit() types.ResponseCommit {
return types.ResponseCommit{}
}
func (sm *StateMachine) Query(req types.RequestQuery) types.ResponseQuery {
return types.ResponseQuery{Code: 0}
}
func (sm *StateMachine) InitChain(req types.RequestInitChain) types.ResponseInitChain {
return types.ResponseInitChain{}
}
func (sm *StateMachine) BeginBlock(req types.RequestBeginBlock) types.ResponseBeginBlock {
return types.ResponseBeginBlock{}
}
func (sm *StateMachine) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock {
return types.ResponseEndBlock{}
}
func (sm *StateMachine) ListSnapshots(req types.RequestListSnapshots) types.ResponseListSnapshots {
return types.ResponseListSnapshots{}
}
func (sm *StateMachine) OfferSnapshot(req types.RequestOfferSnapshot) types.ResponseOfferSnapshot {
return types.ResponseOfferSnapshot{}
}
func (sm *StateMachine) LoadSnapshotChunk(req types.RequestLoadSnapshotChunk) types.ResponseLoadSnapshotChunk {
return types.ResponseLoadSnapshotChunk{}
}
func (sm *StateMachine) ApplySnapshotChunk(req types.RequestApplySnapshotChunk) types.ResponseApplySnapshotChunk {
return types.ResponseApplySnapshotChunk{}
}
func (sm *StateMachine) PrepareProposal(req types.RequestPrepareProposal) types.ResponsePrepareProposal {
txs := make([][]byte, 0, len(req.Txs))
var totalBytes int64
for _, tx := range req.Txs {
totalBytes += int64(len(tx))
if totalBytes > req.MaxTxBytes {
break
}
txs = append(txs, tx)
}
return types.ResponsePrepareProposal{Txs: txs}
}
func (sm *StateMachine) ProcessProposal(req types.RequestProcessProposal) types.ResponseProcessProposal {
return types.ResponseProcessProposal{
Status: types.ResponseProcessProposal_ACCEPT}
}
func (msg *MsgPlaceOrder) ValidateBasic() error {
if err := msg.Order.ValidateBasic(); err != nil {
return err
}
if err := msg.Pair.ValidateBasic(); err != nil {
return err
}
if len(msg.Signature) != ed25519.SignatureSize {
return errors.New("invalid signature size")
}
return nil
}
func (msg *MsgCreateAccount) ValidateBasic() error {
if len(msg.PublicKey) != ed25519.PubKeySize {
return errors.New("invalid pub key size")
}
uniqueMap := make(map[string]struct{}, len(msg.Commodities))
for _, c := range msg.Commodities {
if err := c.ValidateBasic(); err != nil {
return err
}
if _, ok := uniqueMap[c.Denom]; ok {
return fmt.Errorf("commodity %s declared twice", c.Denom)
}
uniqueMap[c.Denom] = struct{}{}
}
return nil
}
func (msg *MsgRegisterPair) ValidateBasic() error {
return msg.Pair.ValidateBasic()
}
func (c *Commodity) ValidateBasic() error {
if c.Quantity <= 0 {
return errors.New("quantity must be greater than zero")
}
}
func (p *Pair) ValidateBasic() error {
if p.InboundCommodityDenom == "" || p.OutboundCommodityDenom == "" {
return errors.New("inbound and outbound commodities must be present")
}
if p.InboundCommodityDenom == p.OutboundCommodityDenom {
return errors.New("commodities must not be the same")
}
return nil
}
func (o *Order) ValidateBasic() error {
if o.QuantityOutbound == 0 {
return errors.New("quantity outbound must be non zero")
}
if o.MinPrice <= 0 {
return errors.New("min price must be greater than 0")
}
return nil
}

View File

@@ -0,0 +1,4 @@
//go:generate go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
//go:generate protoc -I. -I../.. --go_out=. --go_opt=paths=source_relative wire.proto msgs.proto
package orderbook

View File

@@ -0,0 +1,67 @@
package orderbook
import (
"container/heap"
)
type Market struct {
pair Pair // i.e. EUR/USD (a market is bidirectional)
buyingOrders HighestPriceOrderList // i.e. buying EUR for USD
sellingOrders LowestPriceOrderList // i.e. selling EUR for USD or buying USD for EUR
}
func (m *Market) AddOrder(o Order) error {
}
func (m *Market) Match()
type LowestPriceOrderList []*Order
func (l LowestPriceOrderList) Less(i, j int) bool {
return l[i].MinPrice < l[j].MinPrice
}
func (l LowestPriceOrderList) Swap(i, j int) {
l[i], l[j] = l[j], l[i]
}
func (l *LowestPriceOrderList) Push(x any) {
item := x.(*Order)
*l = append(*l, item)
}
func (l *LowestPriceOrderList) Pop() any {
old := *l
n := len(old)
item := old[n-1]
old[n-1] = nil
*l = old[0 : n-1]
return item
}
type HighestPriceOrderList []*Order
func (l HighestPriceOrderList) Less(i, j int) bool {
return l[i].MinPrice > l[j].MinPrice
}
func (l HighestPriceOrderList) Swap(i, j int) {
l[i], l[j] = l[j], l[i]
}
func (l *HighestPriceOrderList) Push(x any) {
item := x.(*Order)
*l = append(*l, item)
}
func (l *HighestPriceOrderList) Pop() any {
old := *l
n := len(old)
item := old[n-1]
old[n-1] = nil
*l = old[0 : n-1]
return item
}

View File

@@ -0,0 +1,444 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.1
// protoc v3.18.1
// source: msgs.proto
package orderbook
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type MsgPlaceOrder struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Pair *Pair `protobuf:"bytes,1,opt,name=pair,proto3" json:"pair,omitempty"`
Order *Order `protobuf:"bytes,2,opt,name=order,proto3" json:"order,omitempty"`
Signature [][]byte `protobuf:"bytes,3,rep,name=signature,proto3" json:"signature,omitempty"`
}
func (x *MsgPlaceOrder) Reset() {
*x = MsgPlaceOrder{}
if protoimpl.UnsafeEnabled {
mi := &file_msgs_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *MsgPlaceOrder) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*MsgPlaceOrder) ProtoMessage() {}
func (x *MsgPlaceOrder) ProtoReflect() protoreflect.Message {
mi := &file_msgs_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use MsgPlaceOrder.ProtoReflect.Descriptor instead.
func (*MsgPlaceOrder) Descriptor() ([]byte, []int) {
return file_msgs_proto_rawDescGZIP(), []int{0}
}
func (x *MsgPlaceOrder) GetPair() *Pair {
if x != nil {
return x.Pair
}
return nil
}
func (x *MsgPlaceOrder) GetOrder() *Order {
if x != nil {
return x.Order
}
return nil
}
func (x *MsgPlaceOrder) GetSignature() [][]byte {
if x != nil {
return x.Signature
}
return nil
}
type MsgCreateAccount struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
PublicKey [][]byte `protobuf:"bytes,1,rep,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"`
Commodities []*Commodity `protobuf:"bytes,2,rep,name=commodities,proto3" json:"commodities,omitempty"`
}
func (x *MsgCreateAccount) Reset() {
*x = MsgCreateAccount{}
if protoimpl.UnsafeEnabled {
mi := &file_msgs_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *MsgCreateAccount) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*MsgCreateAccount) ProtoMessage() {}
func (x *MsgCreateAccount) ProtoReflect() protoreflect.Message {
mi := &file_msgs_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use MsgCreateAccount.ProtoReflect.Descriptor instead.
func (*MsgCreateAccount) Descriptor() ([]byte, []int) {
return file_msgs_proto_rawDescGZIP(), []int{1}
}
func (x *MsgCreateAccount) GetPublicKey() [][]byte {
if x != nil {
return x.PublicKey
}
return nil
}
func (x *MsgCreateAccount) GetCommodities() []*Commodity {
if x != nil {
return x.Commodities
}
return nil
}
type MsgRegisterPair struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Pair *Pair `protobuf:"bytes,1,opt,name=pair,proto3" json:"pair,omitempty"`
}
func (x *MsgRegisterPair) Reset() {
*x = MsgRegisterPair{}
if protoimpl.UnsafeEnabled {
mi := &file_msgs_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *MsgRegisterPair) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*MsgRegisterPair) ProtoMessage() {}
func (x *MsgRegisterPair) ProtoReflect() protoreflect.Message {
mi := &file_msgs_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use MsgRegisterPair.ProtoReflect.Descriptor instead.
func (*MsgRegisterPair) Descriptor() ([]byte, []int) {
return file_msgs_proto_rawDescGZIP(), []int{2}
}
func (x *MsgRegisterPair) GetPair() *Pair {
if x != nil {
return x.Pair
}
return nil
}
type Msg struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
//a Msg has to be one of the below
//
// Types that are assignable to Sum:
// *Msg_MsgPlaceOrder
// *Msg_MsgRegisterPair
// *Msg_MsgCreateAccount
Sum isMsg_Sum `protobuf_oneof:"sum"`
}
func (x *Msg) Reset() {
*x = Msg{}
if protoimpl.UnsafeEnabled {
mi := &file_msgs_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Msg) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Msg) ProtoMessage() {}
func (x *Msg) ProtoReflect() protoreflect.Message {
mi := &file_msgs_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Msg.ProtoReflect.Descriptor instead.
func (*Msg) Descriptor() ([]byte, []int) {
return file_msgs_proto_rawDescGZIP(), []int{3}
}
func (m *Msg) GetSum() isMsg_Sum {
if m != nil {
return m.Sum
}
return nil
}
func (x *Msg) GetMsgPlaceOrder() *MsgPlaceOrder {
if x, ok := x.GetSum().(*Msg_MsgPlaceOrder); ok {
return x.MsgPlaceOrder
}
return nil
}
func (x *Msg) GetMsgRegisterPair() *MsgRegisterPair {
if x, ok := x.GetSum().(*Msg_MsgRegisterPair); ok {
return x.MsgRegisterPair
}
return nil
}
func (x *Msg) GetMsgCreateAccount() *MsgCreateAccount {
if x, ok := x.GetSum().(*Msg_MsgCreateAccount); ok {
return x.MsgCreateAccount
}
return nil
}
type isMsg_Sum interface {
isMsg_Sum()
}
type Msg_MsgPlaceOrder struct {
MsgPlaceOrder *MsgPlaceOrder `protobuf:"bytes,1,opt,name=msg_place_order,json=msgPlaceOrder,proto3,oneof"`
}
type Msg_MsgRegisterPair struct {
MsgRegisterPair *MsgRegisterPair `protobuf:"bytes,2,opt,name=msg_register_pair,json=msgRegisterPair,proto3,oneof"`
}
type Msg_MsgCreateAccount struct {
MsgCreateAccount *MsgCreateAccount `protobuf:"bytes,3,opt,name=msg_create_account,json=msgCreateAccount,proto3,oneof"`
}
func (*Msg_MsgPlaceOrder) isMsg_Sum() {}
func (*Msg_MsgRegisterPair) isMsg_Sum() {}
func (*Msg_MsgCreateAccount) isMsg_Sum() {}
var File_msgs_proto protoreflect.FileDescriptor
var file_msgs_proto_rawDesc = []byte{
0x0a, 0x0a, 0x6d, 0x73, 0x67, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x6f, 0x72,
0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x1a, 0x0a, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x22, 0x7a, 0x0a, 0x0d, 0x4d, 0x73, 0x67, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x4f,
0x72, 0x64, 0x65, 0x72, 0x12, 0x23, 0x0a, 0x04, 0x70, 0x61, 0x69, 0x72, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x50,
0x61, 0x69, 0x72, 0x52, 0x04, 0x70, 0x61, 0x69, 0x72, 0x12, 0x26, 0x0a, 0x05, 0x6f, 0x72, 0x64,
0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6f, 0x72, 0x64, 0x65, 0x72,
0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x05, 0x6f, 0x72, 0x64, 0x65,
0x72, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x03,
0x20, 0x03, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22,
0x69, 0x0a, 0x10, 0x4d, 0x73, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f,
0x75, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65,
0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b,
0x65, 0x79, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x64, 0x69, 0x74, 0x69, 0x65,
0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62,
0x6f, 0x6f, 0x6b, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x64, 0x69, 0x74, 0x79, 0x52, 0x0b, 0x63,
0x6f, 0x6d, 0x6d, 0x6f, 0x64, 0x69, 0x74, 0x69, 0x65, 0x73, 0x22, 0x36, 0x0a, 0x0f, 0x4d, 0x73,
0x67, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, 0x61, 0x69, 0x72, 0x12, 0x23, 0x0a,
0x04, 0x70, 0x61, 0x69, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6f, 0x72,
0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x70, 0x61,
0x69, 0x72, 0x22, 0xe7, 0x01, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x12, 0x42, 0x0a, 0x0f, 0x6d, 0x73,
0x67, 0x5f, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x2e,
0x4d, 0x73, 0x67, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x48, 0x00, 0x52,
0x0d, 0x6d, 0x73, 0x67, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x48,
0x0a, 0x11, 0x6d, 0x73, 0x67, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x70,
0x61, 0x69, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6f, 0x72, 0x64, 0x65,
0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
0x72, 0x50, 0x61, 0x69, 0x72, 0x48, 0x00, 0x52, 0x0f, 0x6d, 0x73, 0x67, 0x52, 0x65, 0x67, 0x69,
0x73, 0x74, 0x65, 0x72, 0x50, 0x61, 0x69, 0x72, 0x12, 0x4b, 0x0a, 0x12, 0x6d, 0x73, 0x67, 0x5f,
0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b,
0x2e, 0x4d, 0x73, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e,
0x74, 0x48, 0x00, 0x52, 0x10, 0x6d, 0x73, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63,
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x05, 0x0a, 0x03, 0x73, 0x75, 0x6d, 0x42, 0x39, 0x5a, 0x37,
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x65, 0x6e, 0x64, 0x65,
0x72, 0x6d, 0x69, 0x6e, 0x74, 0x2f, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x74,
0x2f, 0x61, 0x62, 0x63, 0x69, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x6f, 0x72,
0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_msgs_proto_rawDescOnce sync.Once
file_msgs_proto_rawDescData = file_msgs_proto_rawDesc
)
func file_msgs_proto_rawDescGZIP() []byte {
file_msgs_proto_rawDescOnce.Do(func() {
file_msgs_proto_rawDescData = protoimpl.X.CompressGZIP(file_msgs_proto_rawDescData)
})
return file_msgs_proto_rawDescData
}
var file_msgs_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_msgs_proto_goTypes = []interface{}{
(*MsgPlaceOrder)(nil), // 0: orderbook.MsgPlaceOrder
(*MsgCreateAccount)(nil), // 1: orderbook.MsgCreateAccount
(*MsgRegisterPair)(nil), // 2: orderbook.MsgRegisterPair
(*Msg)(nil), // 3: orderbook.Msg
(*Pair)(nil), // 4: orderbook.Pair
(*Order)(nil), // 5: orderbook.Order
(*Commodity)(nil), // 6: orderbook.Commodity
}
var file_msgs_proto_depIdxs = []int32{
4, // 0: orderbook.MsgPlaceOrder.pair:type_name -> orderbook.Pair
5, // 1: orderbook.MsgPlaceOrder.order:type_name -> orderbook.Order
6, // 2: orderbook.MsgCreateAccount.commodities:type_name -> orderbook.Commodity
4, // 3: orderbook.MsgRegisterPair.pair:type_name -> orderbook.Pair
0, // 4: orderbook.Msg.msg_place_order:type_name -> orderbook.MsgPlaceOrder
2, // 5: orderbook.Msg.msg_register_pair:type_name -> orderbook.MsgRegisterPair
1, // 6: orderbook.Msg.msg_create_account:type_name -> orderbook.MsgCreateAccount
7, // [7:7] is the sub-list for method output_type
7, // [7:7] is the sub-list for method input_type
7, // [7:7] is the sub-list for extension type_name
7, // [7:7] is the sub-list for extension extendee
0, // [0:7] is the sub-list for field type_name
}
func init() { file_msgs_proto_init() }
func file_msgs_proto_init() {
if File_msgs_proto != nil {
return
}
file_wire_proto_init()
if !protoimpl.UnsafeEnabled {
file_msgs_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*MsgPlaceOrder); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_msgs_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*MsgCreateAccount); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_msgs_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*MsgRegisterPair); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_msgs_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Msg); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_msgs_proto_msgTypes[3].OneofWrappers = []interface{}{
(*Msg_MsgPlaceOrder)(nil),
(*Msg_MsgRegisterPair)(nil),
(*Msg_MsgCreateAccount)(nil),
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_msgs_proto_rawDesc,
NumEnums: 0,
NumMessages: 4,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_msgs_proto_goTypes,
DependencyIndexes: file_msgs_proto_depIdxs,
MessageInfos: file_msgs_proto_msgTypes,
}.Build()
File_msgs_proto = out.File
file_msgs_proto_rawDesc = nil
file_msgs_proto_goTypes = nil
file_msgs_proto_depIdxs = nil
}

View File

@@ -0,0 +1,40 @@
syntax = "proto3";
package orderbook;
option go_package = "github.com/tendermint/tendermint/abci/example/orderbook";
import "wire.proto";
message MsgBid {
Pair pair = 1;
double max_price = 2;
double quantity = 3;
uint64 account_id = 4;
repeated bytes signature = 4;
}
message MsgAsk {
Pair pair = 1;
double min_price = 2;
double quantity = 3;
uint64 account_id = 4;
repeated bytes signature = 5;
}
message MsgCreateAccount {
repeated bytes public_key = 1;
repeated Commodity commodities = 2;
}
message MsgRegisterPair {
Pair pair = 1;
}
message Msg {
//a Msg has to be one of the below
oneof sum {
MsgPlaceOrder msg_place_order = 1;
MsgRegisterPair msg_register_pair = 2;
MsgCreateAccount msg_create_account = 3;
}
}

View File

@@ -0,0 +1,397 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.1
// protoc v3.18.1
// source: wire.proto
package orderbook
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type Order struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
QuantityOutbound uint64 `protobuf:"varint,1,opt,name=quantity_outbound,json=quantityOutbound,proto3" json:"quantity_outbound,omitempty"`
MinPrice float64 `protobuf:"fixed64,2,opt,name=min_price,json=minPrice,proto3" json:"min_price,omitempty"`
Owner uint64 `protobuf:"varint,3,opt,name=owner,proto3" json:"owner,omitempty"`
}
func (x *Order) Reset() {
*x = Order{}
if protoimpl.UnsafeEnabled {
mi := &file_wire_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Order) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Order) ProtoMessage() {}
func (x *Order) ProtoReflect() protoreflect.Message {
mi := &file_wire_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Order.ProtoReflect.Descriptor instead.
func (*Order) Descriptor() ([]byte, []int) {
return file_wire_proto_rawDescGZIP(), []int{0}
}
func (x *Order) GetQuantityOutbound() uint64 {
if x != nil {
return x.QuantityOutbound
}
return 0
}
func (x *Order) GetMinPrice() float64 {
if x != nil {
return x.MinPrice
}
return 0
}
func (x *Order) GetOwner() uint64 {
if x != nil {
return x.Owner
}
return 0
}
type Pair struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
InboundCommodityDenom string `protobuf:"bytes,1,opt,name=inbound_commodity_denom,json=inboundCommodityDenom,proto3" json:"inbound_commodity_denom,omitempty"`
OutboundCommodityDenom string `protobuf:"bytes,2,opt,name=outbound_commodity_denom,json=outboundCommodityDenom,proto3" json:"outbound_commodity_denom,omitempty"`
}
func (x *Pair) Reset() {
*x = Pair{}
if protoimpl.UnsafeEnabled {
mi := &file_wire_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Pair) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Pair) ProtoMessage() {}
func (x *Pair) ProtoReflect() protoreflect.Message {
mi := &file_wire_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Pair.ProtoReflect.Descriptor instead.
func (*Pair) Descriptor() ([]byte, []int) {
return file_wire_proto_rawDescGZIP(), []int{1}
}
func (x *Pair) GetInboundCommodityDenom() string {
if x != nil {
return x.InboundCommodityDenom
}
return ""
}
func (x *Pair) GetOutboundCommodityDenom() string {
if x != nil {
return x.OutboundCommodityDenom
}
return ""
}
type Commodity struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"`
Quantity uint64 `protobuf:"varint,2,opt,name=quantity,proto3" json:"quantity,omitempty"`
}
func (x *Commodity) Reset() {
*x = Commodity{}
if protoimpl.UnsafeEnabled {
mi := &file_wire_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Commodity) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Commodity) ProtoMessage() {}
func (x *Commodity) ProtoReflect() protoreflect.Message {
mi := &file_wire_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Commodity.ProtoReflect.Descriptor instead.
func (*Commodity) Descriptor() ([]byte, []int) {
return file_wire_proto_rawDescGZIP(), []int{2}
}
func (x *Commodity) GetDenom() string {
if x != nil {
return x.Denom
}
return ""
}
func (x *Commodity) GetQuantity() uint64 {
if x != nil {
return x.Quantity
}
return 0
}
type Account struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Index uint64 `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"`
PublicKey [][]byte `protobuf:"bytes,2,rep,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"`
Commodities []*Commodity `protobuf:"bytes,3,rep,name=commodities,proto3" json:"commodities,omitempty"`
}
func (x *Account) Reset() {
*x = Account{}
if protoimpl.UnsafeEnabled {
mi := &file_wire_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Account) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Account) ProtoMessage() {}
func (x *Account) ProtoReflect() protoreflect.Message {
mi := &file_wire_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Account.ProtoReflect.Descriptor instead.
func (*Account) Descriptor() ([]byte, []int) {
return file_wire_proto_rawDescGZIP(), []int{3}
}
func (x *Account) GetIndex() uint64 {
if x != nil {
return x.Index
}
return 0
}
func (x *Account) GetPublicKey() [][]byte {
if x != nil {
return x.PublicKey
}
return nil
}
func (x *Account) GetCommodities() []*Commodity {
if x != nil {
return x.Commodities
}
return nil
}
var File_wire_proto protoreflect.FileDescriptor
var file_wire_proto_rawDesc = []byte{
0x0a, 0x0a, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x6f, 0x72,
0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x22, 0x67, 0x0a, 0x05, 0x4f, 0x72, 0x64, 0x65, 0x72,
0x12, 0x2b, 0x0a, 0x11, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x6f, 0x75, 0x74,
0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x71, 0x75, 0x61,
0x6e, 0x74, 0x69, 0x74, 0x79, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x1b, 0x0a,
0x09, 0x6d, 0x69, 0x6e, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01,
0x52, 0x08, 0x6d, 0x69, 0x6e, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x77,
0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72,
0x22, 0x78, 0x0a, 0x04, 0x50, 0x61, 0x69, 0x72, 0x12, 0x36, 0x0a, 0x17, 0x69, 0x6e, 0x62, 0x6f,
0x75, 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x64, 0x69, 0x74, 0x79, 0x5f, 0x64, 0x65,
0x6e, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x69, 0x6e, 0x62, 0x6f, 0x75,
0x6e, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x64, 0x69, 0x74, 0x79, 0x44, 0x65, 0x6e, 0x6f, 0x6d,
0x12, 0x38, 0x0a, 0x18, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x63, 0x6f, 0x6d,
0x6d, 0x6f, 0x64, 0x69, 0x74, 0x79, 0x5f, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x16, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6d, 0x6d,
0x6f, 0x64, 0x69, 0x74, 0x79, 0x44, 0x65, 0x6e, 0x6f, 0x6d, 0x22, 0x3d, 0x0a, 0x09, 0x43, 0x6f,
0x6d, 0x6d, 0x6f, 0x64, 0x69, 0x74, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x6e, 0x6f, 0x6d,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x64, 0x65, 0x6e, 0x6f, 0x6d, 0x12, 0x1a, 0x0a,
0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52,
0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x22, 0x76, 0x0a, 0x07, 0x41, 0x63, 0x63,
0x6f, 0x75, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20,
0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75,
0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09,
0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6f, 0x6d,
0x6d, 0x6f, 0x64, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14,
0x2e, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f,
0x64, 0x69, 0x74, 0x79, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x64, 0x69, 0x74, 0x69, 0x65,
0x73, 0x42, 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
0x74, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x74, 0x2f, 0x74, 0x65, 0x6e, 0x64, 0x65,
0x72, 0x6d, 0x69, 0x6e, 0x74, 0x2f, 0x61, 0x62, 0x63, 0x69, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70,
0x6c, 0x65, 0x2f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
}
var (
file_wire_proto_rawDescOnce sync.Once
file_wire_proto_rawDescData = file_wire_proto_rawDesc
)
func file_wire_proto_rawDescGZIP() []byte {
file_wire_proto_rawDescOnce.Do(func() {
file_wire_proto_rawDescData = protoimpl.X.CompressGZIP(file_wire_proto_rawDescData)
})
return file_wire_proto_rawDescData
}
var file_wire_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_wire_proto_goTypes = []interface{}{
(*Order)(nil), // 0: orderbook.Order
(*Pair)(nil), // 1: orderbook.Pair
(*Commodity)(nil), // 2: orderbook.Commodity
(*Account)(nil), // 3: orderbook.Account
}
var file_wire_proto_depIdxs = []int32{
2, // 0: orderbook.Account.commodities:type_name -> orderbook.Commodity
1, // [1:1] is the sub-list for method output_type
1, // [1:1] is the sub-list for method input_type
1, // [1:1] is the sub-list for extension type_name
1, // [1:1] is the sub-list for extension extendee
0, // [0:1] is the sub-list for field type_name
}
func init() { file_wire_proto_init() }
func file_wire_proto_init() {
if File_wire_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_wire_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Order); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_wire_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Pair); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_wire_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Commodity); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_wire_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Account); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_wire_proto_rawDesc,
NumEnums: 0,
NumMessages: 4,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_wire_proto_goTypes,
DependencyIndexes: file_wire_proto_depIdxs,
MessageInfos: file_wire_proto_msgTypes,
}.Build()
File_wire_proto = out.File
file_wire_proto_rawDesc = nil
file_wire_proto_goTypes = nil
file_wire_proto_depIdxs = nil
}

View File

@@ -0,0 +1,39 @@
syntax = "proto3";
package orderbook;
option go_package = "github.com/tendermint/tendermint/abci/example/orderbook";
message Order {
uint64 quantity_outbound = 1;
double limit_price = 2;
uint64 owner = 3;
}
message Pair {
string inbound_commodity_denom = 1;
string outbound_commodity_denom = 2;
}
message Commodity {
string denom = 1;
uint64 quantity = 2;
}
message Account {
uint64 index = 1;
repeated bytes public_key = 2;
repeated Commodity commodities = 3;
}
message TradeSet {
Pair pair = 1; // ATOM/USDC
repeated MatchedOrder matched_orders = 2;
}
message MatchedOrder {
Order buy_order = 1;
repeated bytes buyer_signature = 2;
Order sell_order = 3;
repeated bytes seller_signature = 4;
}