Added new instructions

This commit is contained in:
Julien Cassis 2020-12-21 09:59:46 -05:00
parent ffd9fc2e14
commit fd950b41cc
7 changed files with 198 additions and 36 deletions

View File

@ -65,7 +65,7 @@ var getSPLTokenCmd = &cobra.Command{
text.EncoderColorCyan.Print("Address: ")
fmt.Println(keyedAcct.Pubkey.String())
text.EncoderColorCyan.Print("Owner: ")
text.EncoderColorCyan.Print("OpenOrders: ")
fmt.Println(keyedAcct.Account.Owner.String())
text.EncoderColorCyan.Print("Lamports: ")

View File

@ -76,6 +76,9 @@ var InstructionDefVariant = bin.NewVariantDefinition(bin.Uint32TypeIDEncoding, [
{"cancel_order", (*InstructionCancelOrder)(nil)},
{"settle_funds", (*InstructionSettleFunds)(nil)},
{"cancel_order_by_client_id", (*InstructionCancelOrderByClientId)(nil)},
{"disable_market", (*InstructionDisableMarketAccounts)(nil)},
{"sweep_fees", (*InstructionSweepFees)(nil)},
{"new_order_v2", (*InstructionNewOrderV2)(nil)},
})
type InitializeMarketAccounts struct {
@ -115,7 +118,7 @@ type NewOrderAccounts struct {
OpenOrders *solana.AccountMeta `text:"linear,notype"`
RequestQueue *solana.AccountMeta `text:"linear,notype"`
Payer *solana.AccountMeta `text:"linear,notype"`
Owner *solana.AccountMeta `text:"linear,notype"`
Owner *solana.AccountMeta `text:"linear,notype"` // The owner of the open orders, i.e. the trader
CoinVault *solana.AccountMeta `text:"linear,notype"`
PCVault *solana.AccountMeta `text:"linear,notype"`
SPLTokenProgram *solana.AccountMeta `text:"linear,notype"`
@ -124,7 +127,7 @@ type NewOrderAccounts struct {
}
type InstructionNewOrder struct {
Side uint32
Side Side
LimitPrice uint64
MaxQuantity uint64
OrderType OrderType
@ -300,7 +303,7 @@ type CancelOrderByClientIdAccounts struct {
type InstructionCancelOrderByClientId struct {
ClientID uint64
Accounts *CancelOrderByClientIdAccounts
Accounts *CancelOrderByClientIdAccounts `bin:"-"`
}
func (i *InstructionCancelOrderByClientId) SetAccounts(accounts []*solana.AccountMeta, instructionActIdx []uint8) error {
@ -316,3 +319,107 @@ func (i *InstructionCancelOrderByClientId) SetAccounts(accounts []*solana.Accoun
return nil
}
type DisableMarketAccounts struct {
Market *solana.AccountMeta `text:"linear,notype"`
DisableAuthority *solana.AccountMeta `text:"linear,notype"`
}
type InstructionDisableMarketAccounts struct {
Accounts *DisableMarketAccounts `bin:"-"`
}
func (i *InstructionDisableMarketAccounts) SetAccounts(accounts []*solana.AccountMeta, instructionActIdx []uint8) error {
if len(instructionActIdx) < 2 {
return fmt.Errorf("insuficient account, Disable Market requires at-least 2 accounts not %d", len(accounts))
}
i.Accounts = &DisableMarketAccounts{
Market: accounts[instructionActIdx[0]],
DisableAuthority: accounts[instructionActIdx[1]],
}
return nil
}
type SweepFeesAccounts struct {
Market *solana.AccountMeta `text:"linear,notype"`
PCVault *solana.AccountMeta `text:"linear,notype"`
FeeSweepingAuthority *solana.AccountMeta `text:"linear,notype"`
FeeReceivableAccount *solana.AccountMeta `text:"linear,notype"`
VaultSigner *solana.AccountMeta `text:"linear,notype"`
SPLTokenProgram *solana.AccountMeta `text:"linear,notype"`
}
type InstructionSweepFees struct {
Accounts *SweepFeesAccounts `bin:"-"`
}
func (i *InstructionSweepFees) SetAccounts(accounts []*solana.AccountMeta, instructionActIdx []uint8) error {
if len(instructionActIdx) < 6 {
return fmt.Errorf("insuficient account, Sweep Fees requires at-least 6 accounts not %d", len(accounts))
}
i.Accounts = &SweepFeesAccounts{
Market: accounts[instructionActIdx[0]],
PCVault: accounts[instructionActIdx[1]],
FeeSweepingAuthority: accounts[instructionActIdx[2]],
FeeReceivableAccount: accounts[instructionActIdx[3]],
VaultSigner: accounts[instructionActIdx[4]],
SPLTokenProgram: accounts[instructionActIdx[5]],
}
return nil
}
type NewOrderV2Accounts struct {
Market *solana.AccountMeta `text:"linear,notype"` // the market
OpenOrders *solana.AccountMeta `text:"linear,notype"` // the OpenOrders account to use
RequestQueue *solana.AccountMeta `text:"linear,notype"` // the request queue
Payer *solana.AccountMeta `text:"linear,notype"` // the (coin or price currency) account paying for the order
Owner *solana.AccountMeta `text:"linear,notype"` // owner of the OpenOrders account
CoinVault *solana.AccountMeta `text:"linear,notype"` // coin vault
PCVault *solana.AccountMeta `text:"linear,notype"` // pc vault
SPLTokenProgram *solana.AccountMeta `text:"linear,notype"` // spl token program
RentSysvar *solana.AccountMeta `text:"linear,notype"` // the rent sysvar
FeeDiscount *solana.AccountMeta `text:"linear,notype"` // (optional) the (M)SRM account used for fee discounts
}
type SelfTradeBehavior uint32
const (
SelfTradeBehaviorDecrementTake = iota
SelfTradeBehaviorCancelProvide
)
type InstructionNewOrderV2 struct {
Side Side
LimitPrice uint64
MaxQuantity uint64
OrderType OrderType
ClientID uint64
SelfTradeBehavior SelfTradeBehavior
Accounts *NewOrderV2Accounts `bin:"-"`
}
func (i *InstructionNewOrderV2) SetAccounts(accounts []*solana.AccountMeta, instructionActIdx []uint8) error {
if len(instructionActIdx) < 10 {
return fmt.Errorf("insuficient account, New Order V2 requires at-least 10 accounts not %d", len(accounts))
}
i.Accounts = &NewOrderV2Accounts{
Market: accounts[instructionActIdx[0]],
OpenOrders: accounts[instructionActIdx[1]],
RequestQueue: accounts[instructionActIdx[2]],
Payer: accounts[instructionActIdx[3]],
Owner: accounts[instructionActIdx[4]],
CoinVault: accounts[instructionActIdx[5]],
PCVault: accounts[instructionActIdx[6]],
SPLTokenProgram: accounts[instructionActIdx[7]],
RentSysvar: accounts[instructionActIdx[8]],
FeeDiscount: accounts[instructionActIdx[9]],
}
return nil
}

View File

@ -4,18 +4,68 @@ import (
"encoding/hex"
"testing"
"github.com/stretchr/testify/assert"
bin "github.com/dfuse-io/binary"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestDecodeInstruction(t *testing.T) {
x := `00020000000500`
data, err := hex.DecodeString(x)
require.NoError(t, err)
var instruction *Instruction
err = bin.NewDecoder(data).Decode(&instruction)
require.NoError(t, err)
assert.Equal(t, instruction.Version, uint8(0))
tests := []struct {
name string
hexData string
expectInstruction *Instruction
}{
{
name: "New Order",
hexData: "000900000001000000b80600000000000010eb09000000000000000000168106e091da511601000000",
expectInstruction: &Instruction{
BaseVariant: bin.BaseVariant{
TypeID: 9,
Impl: &InstructionNewOrderV2{
Side: SideAsk,
LimitPrice: 1720,
MaxQuantity: 650000,
OrderType: OrderTypeLimit,
ClientID: 1608306862011613462,
SelfTradeBehavior: SelfTradeBehaviorCancelProvide,
},
},
Version: 0,
},
},
{
name: "Match Order",
hexData: "0002000000ffff",
expectInstruction: &Instruction{
BaseVariant: bin.BaseVariant{
TypeID: 2,
Impl: &InstructionMatchOrder{
Limit: 65535,
},
},
Version: 0,
},
},
{
name: "Settle Funds",
hexData: "0005000000",
expectInstruction: &Instruction{
BaseVariant: bin.BaseVariant{
TypeID: 5,
Impl: &InstructionSettleFunds{},
},
Version: 0,
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
data, err := hex.DecodeString(test.hexData)
require.NoError(t, err)
var instruction *Instruction
err = bin.NewDecoder(data).Decode(&instruction)
require.NoError(t, err)
assert.Equal(t, test.expectInstruction, instruction)
})
}
}

View File

@ -90,25 +90,10 @@ func (s SideLayout) getSide() SideLayoutType {
return SideLayoutTypeUnknown
}
type OrderType string
type OrderType uint32
const (
OrderTypeUnknown OrderType = "UNKNOWN"
OrderTypeLimit OrderType = "LIMIT"
OrderTypeImmediateOrCancel OrderType = "IMMEDIATE_OR_CANCEL"
OrderTypePostOnly OrderType = "POST_ONLY"
OrderTypeLimit = OrderType(0)
OrderTypeImmediateOrCancel
OrderTypePostOnly
)
type OrderTypeLayout uint32
func (o OrderTypeLayout) getOrderType() OrderType {
switch o {
case 0:
return OrderTypeLimit
case 1:
return OrderTypeImmediateOrCancel
case 2:
return OrderTypePostOnly
}
return OrderTypeUnknown
}

View File

@ -55,11 +55,20 @@ type Request struct {
Padding [4]byte `json:"-"`
MaxCoinQtyOrCancelId bin.Uint64
NativePCQtyLocked bin.Uint64
OrderId bin.Uint128
Owner [4]bin.Uint64
OrderID bin.Uint128
OpenOrders [4]bin.Uint64 // this is the openOrder address
ClientOrderID bin.Uint64
}
func (r *Request) Equal(other *Request) bool {
//return (r.OrderID.Hi == other.OrderID.Hi && r.OrderID.Lo == other.OrderID.Lo) &&
// (r.MaxCoinQtyOrCancelId == other.MaxCoinQtyOrCancelId) &&
// (r.NativePCQtyLocked == other.NativePCQtyLocked)
return (r.OrderID.Hi == other.OrderID.Hi && r.OrderID.Lo == other.OrderID.Lo) &&
(r.MaxCoinQtyOrCancelId == other.MaxCoinQtyOrCancelId) &&
(r.NativePCQtyLocked == other.NativePCQtyLocked)
}
type EventQueue struct {
SerumPadding [5]byte `json:"-"`
@ -80,7 +89,7 @@ func (q *EventQueue) Decode(data []byte) error {
type EventFlag uint8
const (
EventFlagFill = RequestFlag(1 << iota)
EventFlagFill = EventFlag(1 << iota)
EventFlagOut
EventFlagBid
EventFlagMaker
@ -106,6 +115,10 @@ type Event struct {
ClientOrderID uint64
}
func (e *Event) Equal(other *Event) bool {
return e.OrderID.Hi == other.OrderID.Hi && e.OrderID.Lo == other.OrderID.Lo
}
func (e *Event) Side() EventSide {
if Has(uint8(e.Flag), uint8(EventFlagBid)) {
return EventSideBid

View File

@ -61,6 +61,13 @@ func (a *AccountFlag) String() string {
return fmt.Sprintf("%s %s", status, account_type)
}
type Side uint32
const (
SideBid = iota
SideAsk
)
type MarketV2 struct {
SerumPadding [5]byte `json:"-"`
AccountFlags AccountFlag

View File

@ -45,7 +45,7 @@ func Test_AccountSubscribe(t *testing.T) {
return
}
text.NewEncoder(os.Stdout).Encode(data, nil)
fmt.Println("Owner: ", data.(*AccountResult).Value.Account.Owner)
fmt.Println("OpenOrders: ", data.(*AccountResult).Value.Account.Owner)
fmt.Println("data: ", data.(*AccountResult).Value.Account.Data)
return