solana-go/serum/types.go

172 lines
4.9 KiB
Go
Raw Normal View History

2020-11-05 14:54:08 -08:00
package serum
2020-11-06 08:47:26 -08:00
import (
2020-11-06 13:12:55 -08:00
"bytes"
2020-11-06 08:47:26 -08:00
"fmt"
"github.com/dfuse-io/solana-go"
"github.com/lunixbochs/struc"
)
2020-11-05 14:54:08 -08:00
type MarketV2 struct {
/*
blob(5),
accountFlagsLayout('accountFlags'),
publicKeyLayout('ownAddress'),
u64('vaultSignerNonce'),
publicKeyLayout('baseMint'),
publicKeyLayout('quoteMint'),
publicKeyLayout('baseVault'),
u64('baseDepositsTotal'),
u64('baseFeesAccrued'),
publicKeyLayout('quoteVault'),
u64('quoteDepositsTotal'),
u64('quoteFeesAccrued'),
u64('quoteDustThreshold'),
publicKeyLayout('requestQueue'),
publicKeyLayout('eventQueue'),
publicKeyLayout('bids'),
2020-11-06 13:31:18 -08:00
2020-11-05 14:54:08 -08:00
publicKeyLayout('asks'),
u64('baseLotSize'),
u64('quoteLotSize'),
u64('feeRateBps'),
u64('referrerRebatesAccrued'),
blob(7),
*/
2020-11-06 10:18:04 -08:00
SerumPadding [5]byte `json:"-" struc:"[5]pad"`
2020-11-06 08:47:26 -08:00
AccountFlags solana.U64 `struc:"uint64,little"`
OwnAddress solana.PublicKey `struc:"[32]byte"`
VaultSignerNonce solana.U64 `struc:"uint64,little"`
BaseMint solana.PublicKey `struc:"[32]byte"`
QuoteMint solana.PublicKey `struc:"[32]byte"`
BaseVault solana.PublicKey `struc:"[32]byte"`
BaseDepositsTotal solana.U64 `struc:"uint64,little"`
BaseFeesAccrued solana.U64 `struc:"uint64,little"`
QuoteVault solana.PublicKey `struc:"[32]byte"`
QuoteDepositsTotal solana.U64 `struc:"uint64,little"`
QuoteFeesAccrued solana.U64 `struc:"uint64,little"`
QuoteDustThreshold solana.U64 `struc:"uint64,little"`
RequestQueue solana.PublicKey `struc:"[32]byte"`
EventQueue solana.PublicKey `struc:"[32]byte"`
Bids solana.PublicKey `struc:"[32]byte"`
Asks solana.PublicKey `struc:"[32]byte"`
BaseLotSize solana.U64 `struc:"uint64,little"`
QuoteLotSize solana.U64 `struc:"uint64,little"`
FeeRateBPS solana.U64 `struc:"uint64,little"`
ReferrerRebatesAccrued solana.U64 `struc:"uint64,little"`
2020-11-06 10:18:04 -08:00
EndPadding [7]byte `json:"-" struc:"[7]pad"`
2020-11-06 08:47:26 -08:00
}
2020-11-05 14:54:08 -08:00
2020-11-06 08:47:26 -08:00
type Orderbook struct {
// ORDERBOOK_LAYOUT
2020-11-06 10:18:04 -08:00
SerumPadding [5]byte `json:"-" struc:"[5]pad"`
2020-11-06 08:47:26 -08:00
AccountFlags solana.U64 `struc:"uint64,little"`
// SLAB_LAYOUT
// SLAB_HEADER_LAYOUT
2020-11-06 13:12:55 -08:00
BumpIndex uint32 `struc:"uint32,little,sizeof=Nodes"`
2020-11-06 10:18:04 -08:00
ZeroPaddingA [4]byte `json:"-" struc:"[4]pad"`
2020-11-06 08:47:26 -08:00
FreeListLen uint32 `struc:"uint32,little"`
2020-11-06 10:18:04 -08:00
ZeroPaddingB [4]byte `json:"-" struc:"[4]pad"`
2020-11-06 08:47:26 -08:00
FreeListHead uint32 `struc:"uint32,little"`
Root uint32 `struc:"uint32,little"`
LeafCount uint32 `struc:"uint32,little"`
2020-11-06 10:18:04 -08:00
ZeroPaddingC [4]byte `json:"-" struc:"[4]pad"`
2020-11-06 08:47:26 -08:00
// SLAB_NODE_LAYOUT
Nodes []SlabNode `struc:""`
2020-11-06 08:47:26 -08:00
}
2020-11-05 14:54:08 -08:00
2020-11-06 13:31:18 -08:00
func (o *Orderbook) Items(descending bool, f func(node *SlabLeafNode) error) error {
2020-11-06 10:18:04 -08:00
if o.LeafCount == 0 {
return nil
}
2020-11-07 18:30:28 -08:00
index := uint32(0)
2020-11-06 10:18:04 -08:00
stack := []uint32{o.Root}
2020-11-07 18:30:28 -08:00
for len(stack) > 0 {
index, stack = stack[len(stack)-1], stack[:len(stack)-1]
2020-11-06 10:18:04 -08:00
slab := o.Nodes[index]
2020-11-06 13:14:55 -08:00
impl, err := slab.Variant()
if err != nil {
return err
}
switch s := impl.(type) {
2020-11-06 13:31:18 -08:00
case *SlabInnerNode:
2020-11-06 10:18:04 -08:00
if descending {
stack = append(stack, s.Children[0], s.Children[1])
} else {
stack = append(stack, s.Children[1], s.Children[0])
}
2020-11-06 13:31:18 -08:00
case *SlabLeafNode:
2020-11-06 10:18:04 -08:00
f(s)
}
}
return nil
}
2020-11-06 08:47:26 -08:00
type SlabNode struct {
2020-11-06 13:12:55 -08:00
Type uint32 `struc:"uint32,little"`
Blob []byte `struc:"[68]byte"`
2020-11-06 08:47:26 -08:00
}
2020-11-05 14:54:08 -08:00
2020-11-06 13:12:55 -08:00
func (s *SlabNode) Variant() (interface{}, error) {
var el interface{}
switch s.Type {
case 0:
el = &SlabUninitialized{}
case 1:
el = &SlabInnerNode{}
case 2:
el = &SlabLeafNode{}
case 3:
el = &SlabFreeNode{}
case 4:
el = &SlabLastFreeNode{}
default:
2020-11-06 13:12:55 -08:00
return nil, fmt.Errorf("unsupported SlabNode variant %d", s.Type)
}
2020-11-06 13:12:55 -08:00
if err := struc.Unpack(bytes.NewReader(s.Blob), el); err != nil {
return nil, err
}
return el, nil
}
2020-11-06 08:47:26 -08:00
type SlabUninitialized struct {
}
2020-11-05 14:54:08 -08:00
2020-11-06 08:47:26 -08:00
type SlabInnerNode struct {
PrefixLen uint32 `struc:"uint32,little"`
2020-11-06 10:18:04 -08:00
// this corresponds to the uint128 key
2020-11-07 18:30:28 -08:00
KeySeq solana.U64 `struc:"uint64,little"`
KeyPrice solana.U64 `struc:"uint64,little"`
2020-11-06 10:18:04 -08:00
Children []uint32 `struc:"[2]uint32,little"`
2020-11-05 14:54:08 -08:00
}
type SlabLeafNode struct {
2020-11-06 10:18:04 -08:00
//u8('ownerSlot'), // Index into OPEN_ORDERS_LAYOUT.orders
//u8('feeTier'),
//blob(2),
//u128('key'), // (price, seqNum)
//publicKeyLayout('owner'), // Open orders account
//u64('quantity'), // In units of lot size
//u64('clientOrderId'),
2020-11-06 13:31:18 -08:00
OwnerSlot uint8 `struc:"uint8,little"`
FeeTier uint8 `struc:"uint8,little"`
Padding [2]byte `json:"-" struc:"[2]pad"`
2020-11-07 18:30:28 -08:00
Price solana.U128 `struc:"[16]byte,little"`
//KeySeq solana.U64 `struc:"uint64",little"`
//KeyPrice solana.U64 `struc:"uint64",little"`
2020-11-06 13:31:18 -08:00
2020-11-07 18:30:28 -08:00
Owner solana.PublicKey
Quantity solana.U64 `struc:"uint64,little"`
ClientOrderId solana.U64 `struc:"uint64,little"`
2020-11-06 08:47:26 -08:00
}
2020-11-05 14:54:08 -08:00
2020-11-06 08:47:26 -08:00
type SlabFreeNode struct {
Next uint32 `struc:"uint32,little"`
2020-11-05 14:54:08 -08:00
}
2020-11-06 08:47:26 -08:00
type SlabLastFreeNode struct {
2020-11-05 14:54:08 -08:00
}