Merge branch 'master' of github.com:dfuse-io/solana-go
This commit is contained in:
commit
31f1d42a77
|
@ -1,2 +1,4 @@
|
|||
.idea
|
||||
dist/
|
||||
dist/
|
||||
|
||||
.DS_Store
|
|
@ -29,7 +29,6 @@ type Padding []byte
|
|||
type Hash PublicKey
|
||||
|
||||
///
|
||||
|
||||
type Signature [64]byte
|
||||
|
||||
func SignatureFromBase58(in string) (out Signature, err error) {
|
||||
|
@ -49,6 +48,7 @@ func SignatureFromBase58(in string) (out Signature, err error) {
|
|||
func (p Signature) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(base58.Encode(p[:]))
|
||||
}
|
||||
|
||||
func (p *Signature) UnmarshalJSON(data []byte) (err error) {
|
||||
var s string
|
||||
err = json.Unmarshal(data, &s)
|
||||
|
@ -76,7 +76,6 @@ func (p Signature) String() string {
|
|||
}
|
||||
|
||||
///
|
||||
|
||||
type PublicKey [32]byte
|
||||
|
||||
func (p PublicKey) Equals(pb PublicKey) bool {
|
||||
|
@ -105,6 +104,7 @@ func PublicKeyFromBase58(in string) (out PublicKey, err error) {
|
|||
func (p PublicKey) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(base58.Encode(p[:]))
|
||||
}
|
||||
|
||||
func (p *PublicKey) UnmarshalJSON(data []byte) (err error) {
|
||||
var s string
|
||||
err = json.Unmarshal(data, &s)
|
||||
|
@ -132,7 +132,6 @@ func (p PublicKey) String() string {
|
|||
}
|
||||
|
||||
///
|
||||
|
||||
type Base58 []byte
|
||||
|
||||
func (t Base58) MarshalJSON() ([]byte, error) {
|
||||
|
@ -155,7 +154,6 @@ func (t Base58) String() string {
|
|||
}
|
||||
|
||||
///
|
||||
|
||||
type Data []byte
|
||||
|
||||
func (t Data) MarshalJSON() ([]byte, error) {
|
||||
|
@ -190,7 +188,6 @@ func (t Data) String() string {
|
|||
}
|
||||
|
||||
///
|
||||
|
||||
type ByteWrapper struct {
|
||||
io.Reader
|
||||
}
|
||||
|
|
|
@ -125,7 +125,7 @@ type NewOrderAccounts struct {
|
|||
}
|
||||
|
||||
type InstructionNewOrder struct {
|
||||
Side Side
|
||||
Side uint32
|
||||
LimitPrice uint64
|
||||
MaxQuantity uint64
|
||||
OrderType OrderType
|
||||
|
@ -317,53 +317,3 @@ func (i *InstructionCancelOrderByClientId) SetAccounts(accounts []*solana.Accoun
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
type SideType string
|
||||
|
||||
const (
|
||||
SideLayoutTypeUnknown SideType = "UNKNOWN"
|
||||
SideLayoutTypeBid SideType = "BID"
|
||||
SideLayoutTypeAsk SideType = "ASK"
|
||||
)
|
||||
|
||||
type Side uint32
|
||||
|
||||
func (s Side) getSide() SideType {
|
||||
switch s {
|
||||
case 0:
|
||||
return SideLayoutTypeBid
|
||||
case 1:
|
||||
return SideLayoutTypeAsk
|
||||
}
|
||||
return SideLayoutTypeUnknown
|
||||
}
|
||||
|
||||
func (s Side) String() string {
|
||||
return string(s.getSide())
|
||||
}
|
||||
|
||||
type OrderTypeString string
|
||||
|
||||
const (
|
||||
OrderTypeUnknown OrderTypeString = "UNKNOWN"
|
||||
OrderTypeLimit OrderTypeString = "LIMIT"
|
||||
OrderTypeImmediateOrCancel OrderTypeString = "IMMEDIATE_OR_CANCEL"
|
||||
OrderTypePostOnly OrderTypeString = "POST_ONLY"
|
||||
)
|
||||
|
||||
type OrderType uint32
|
||||
|
||||
func (o OrderType) getOrderType() OrderTypeString {
|
||||
switch o {
|
||||
case 0:
|
||||
return OrderTypeLimit
|
||||
case 1:
|
||||
return OrderTypeImmediateOrCancel
|
||||
case 2:
|
||||
return OrderTypePostOnly
|
||||
}
|
||||
return OrderTypeUnknown
|
||||
}
|
||||
func (t OrderType) String() string {
|
||||
return string(t.getOrderType())
|
||||
}
|
||||
|
|
|
@ -39,10 +39,6 @@ func (m *MarketMeta) quoteSplTokenMultiplier() *big.Int {
|
|||
return solana.DecimalsInBigInt(uint32(m.QuoteMint.Decimals))
|
||||
}
|
||||
|
||||
func divideBnToNumber(numerator, denomiator *big.Float) *big.Float {
|
||||
return F().Quo(numerator, denomiator)
|
||||
}
|
||||
|
||||
func (m *MarketMeta) PriceLotsToNumber(price *big.Int) *big.Float {
|
||||
ratio := I().Mul(I().SetInt64(int64(m.MarketV2.QuoteLotSize)), m.baseSplTokenMultiplier())
|
||||
numerator := F().Mul(F().SetInt(price), F().SetInt(ratio))
|
||||
|
@ -64,10 +60,56 @@ func (m *MarketMeta) PriceNumberToLots(price *big.Int) *big.Float {
|
|||
return F().Quo(F().SetInt(numerator), F().SetInt(denomiator))
|
||||
}
|
||||
|
||||
func I() *big.Int {
|
||||
return new(big.Int)
|
||||
type OpenOrdersMeta struct {
|
||||
OpenOrdersV2 OpenOrdersV2
|
||||
}
|
||||
|
||||
func F() *big.Float {
|
||||
return new(big.Float)
|
||||
|
||||
type Order struct {
|
||||
Limit *big.Int `json:"limit"`
|
||||
Side SideLayout `json:"side"`
|
||||
Price *big.Int `json:"price"`
|
||||
}
|
||||
|
||||
type SideLayoutType string
|
||||
|
||||
const (
|
||||
SideLayoutTypeUnknown SideLayoutType = "UNKNOWN"
|
||||
SideLayoutTypeBid SideLayoutType = "BID"
|
||||
SideLayoutTypeAsk SideLayoutType = "ASK"
|
||||
)
|
||||
|
||||
type SideLayout uint32
|
||||
|
||||
func (s SideLayout) getSide() SideLayoutType {
|
||||
switch s {
|
||||
case 0:
|
||||
return SideLayoutTypeBid
|
||||
case 1:
|
||||
return SideLayoutTypeAsk
|
||||
}
|
||||
return SideLayoutTypeUnknown
|
||||
}
|
||||
|
||||
type OrderType string
|
||||
|
||||
const (
|
||||
OrderTypeUnknown OrderType = "UNKNOWN"
|
||||
OrderTypeLimit OrderType = "LIMIT"
|
||||
OrderTypeImmediateOrCancel OrderType = "IMMEDIATE_OR_CANCEL"
|
||||
OrderTypePostOnly OrderType = "POST_ONLY"
|
||||
)
|
||||
|
||||
type OrderTypeLayout uint32
|
||||
|
||||
func (o OrderTypeLayout) getOrderType() OrderType {
|
||||
switch o {
|
||||
case 0:
|
||||
return OrderTypeLimit
|
||||
case 1:
|
||||
return OrderTypeImmediateOrCancel
|
||||
case 2:
|
||||
return OrderTypePostOnly
|
||||
}
|
||||
return OrderTypeUnknown
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package serum
|
||||
|
||||
import "math/big"
|
||||
|
||||
func I() *big.Int {
|
||||
return new(big.Int)
|
||||
}
|
||||
|
||||
func F() *big.Float {
|
||||
return new(big.Float)
|
||||
}
|
||||
|
||||
func divideBnToNumber(numerator, denomiator *big.Float) *big.Float {
|
||||
return F().Quo(numerator, denomiator)
|
||||
}
|
15
serum/rpc.go
15
serum/rpc.go
|
@ -43,6 +43,21 @@ func KnownMarket() ([]*MarketMeta, error) {
|
|||
return markets, nil
|
||||
}
|
||||
|
||||
func FetchOpenOrders(ctx context.Context, rpcCli *rpc.Client, openOrdersAddr solana.PublicKey) (*OpenOrdersMeta, error) {
|
||||
acctInfo, err := rpcCli.GetAccountInfo(ctx, openOrdersAddr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to get open orders account:%w", err)
|
||||
}
|
||||
|
||||
openOrdersMeta := &OpenOrdersMeta{}
|
||||
|
||||
if err := openOrdersMeta.OpenOrdersV2.Decode(acctInfo.Value.Data); err != nil {
|
||||
return nil, fmt.Errorf("decoding market v2: %w", err)
|
||||
}
|
||||
|
||||
return openOrdersMeta, nil
|
||||
}
|
||||
|
||||
func FetchMarket(ctx context.Context, rpcCli *rpc.Client, marketAddr solana.PublicKey) (*MarketMeta, error) {
|
||||
acctInfo, err := rpcCli.GetAccountInfo(ctx, marketAddr)
|
||||
if err != nil {
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright 2020 dfuse Platform Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package serum
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/dfuse-io/solana-go/rpc"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/dfuse-io/solana-go"
|
||||
)
|
||||
|
||||
func TestFetchMarket(t *testing.T) {
|
||||
rpcURL := os.Getenv("RPC_URL")
|
||||
if rpcURL == "" {
|
||||
t.Skip("Setup 'RPC_URL' to run test")
|
||||
return
|
||||
}
|
||||
|
||||
client := rpc.NewClient(rpcURL)
|
||||
ctx := context.Background()
|
||||
|
||||
openOrderAdd, err := solana.PublicKeyFromBase58("jFoHUkNDC767PyK11cZM4zyNcpjLqFnSjaqEYp5GVBr")
|
||||
require.NoError(t, err)
|
||||
|
||||
openOrders, err := FetchOpenOrders(ctx, client, openOrderAdd)
|
||||
require.NoError(t, err)
|
||||
|
||||
cnt, err := json.MarshalIndent(openOrders.OpenOrdersV2, "", " ")
|
||||
require.NoError(t, err)
|
||||
|
||||
fmt.Println(string(cnt))
|
||||
}
|
|
@ -238,14 +238,6 @@ func (q *EventQueue) Decode(data []byte) error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("event queue: decode header: %w", err)
|
||||
}
|
||||
|
||||
//remainingData := decoder.Remaining()
|
||||
//if remainingData%EventDataLength != 0 {
|
||||
// return fmt.Errorf("event queue: wrong event data length %d", remainingData)
|
||||
//}
|
||||
//
|
||||
//eventCount := remainingData / EventDataLength
|
||||
|
||||
for decoder.Remaining() >= 88 {
|
||||
var e *Event
|
||||
err = decoder.Decode(&e)
|
||||
|
@ -257,3 +249,29 @@ func (q *EventQueue) Decode(data []byte) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
type OpenOrdersV2 struct {
|
||||
SerumPadding [5]byte `json:"-"`
|
||||
AccountFlags bin.Uint64
|
||||
Market solana.PublicKey
|
||||
Owner solana.PublicKey
|
||||
BaseTokenFree bin.Uint64
|
||||
BaseTokenTotal bin.Uint64
|
||||
QuoteTokenFree bin.Uint64
|
||||
QuoteTokenTotal bin.Uint64
|
||||
FreeSlotBits bin.Uint128
|
||||
IsBidBits bin.Uint128
|
||||
Orders [128]bin.Uint128
|
||||
ClientIDs [128]bin.Uint64
|
||||
ReferrerRebatesAccrued bin.Uint64
|
||||
EndPadding [7]byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *OpenOrdersV2) Decode(in []byte) error {
|
||||
decoder := bin.NewDecoder(in)
|
||||
err := decoder.Decode(&m)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unpack: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue