Added support for init and close open_orders_accounts instructions (#99)

* added support for init and close open_orders_accounts instructions

* removed unused variables
This commit is contained in:
quazzuk 2021-12-23 10:16:09 +00:00 committed by GitHub
parent 6f3ba279da
commit d0938e9149
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 176 additions and 32 deletions

View File

@ -1,9 +1,9 @@
"""Layouts for dex instructions data."""
from enum import IntEnum
from construct import Switch
from construct import Bytes, Const, Int8ul, Int16ul, Int32ul, Int64ul, Pass
from construct import Struct as cStruct
from construct import Switch
from .slab import KEY
@ -19,6 +19,8 @@ class InstructionType(IntEnum):
NEW_ORDER_V3 = 10
CANCEL_ORDER_V2 = 11
CANCEL_ORDER_BY_CLIENT_ID_V2 = 12
CLOSE_OPEN_ORDERS = 14
INIT_OPEN_ORDERS = 15
_VERSION = 0
@ -70,6 +72,9 @@ _CANCEL_ORDER_V2 = cStruct(
_CANCEL_ORDER_BY_CLIENTID_V2 = cStruct("client_id" / Int64ul)
_CLOSE_OPEN_ORDERS = cStruct()
_INIT_OPEN_ORDERS = cStruct()
INSTRUCTIONS_LAYOUT = cStruct(
"version" / Const(_VERSION, Int8ul),
"instruction_type" / Int32ul,
@ -87,6 +92,8 @@ INSTRUCTIONS_LAYOUT = cStruct(
InstructionType.NEW_ORDER_V3: _NEW_ORDER_V3,
InstructionType.CANCEL_ORDER_V2: _CANCEL_ORDER_V2,
InstructionType.CANCEL_ORDER_BY_CLIENT_ID_V2: _CANCEL_ORDER_BY_CLIENTID_V2,
InstructionType.CLOSE_OPEN_ORDERS: _CLOSE_OPEN_ORDERS,
InstructionType.INIT_OPEN_ORDERS: _INIT_OPEN_ORDERS,
},
),
)

View File

@ -1,4 +1,5 @@
from construct import Bytes, Int64ul, Padding, Struct as cStruct
from construct import Bytes, Int64ul, Padding
from construct import Struct as cStruct
from .account_flags import ACCOUNT_FLAGS_LAYOUT

View File

@ -1,4 +1,4 @@
from construct import BitStruct, BitsInteger, BitsSwapped, Bytes, Const, Flag, Int8ul, Int32ul, Int64ul, Padding
from construct import BitsInteger, BitsSwapped, BitStruct, Bytes, Const, Flag, Int8ul, Int32ul, Int64ul, Padding
from construct import Struct as cStruct
from .account_flags import ACCOUNT_FLAGS_LAYOUT

View File

@ -3,8 +3,9 @@ from __future__ import annotations
from enum import IntEnum
from construct import Switch, Bytes, Int8ul, Int32ul, Int64ul, Padding
from construct import Bytes, Int8ul, Int32ul, Int64ul, Padding
from construct import Struct as cStruct
from construct import Switch
from .account_flags import ACCOUNT_FLAGS_LAYOUT

View File

@ -1,9 +1,10 @@
from typing import List
import httpx
from solana.rpc.async_api import AsyncClient as async_conn # pylint: disable=unused-import # noqa:F401
from .market.types import MarketInfo, TokenInfo
from .connection import LIVE_MARKETS_URL, TOKEN_MINTS_URL, parse_live_markets, parse_token_mints
from .market.types import MarketInfo, TokenInfo
async def get_live_markets(httpx_client: httpx.AsyncClient) -> List[MarketInfo]:

View File

@ -1,10 +1,11 @@
from __future__ import annotations
from typing import List
from solana.rpc.async_api import AsyncClient
from solana.publickey import PublicKey
from solana.rpc.types import Commitment
from solana.rpc.async_api import AsyncClient
from solana.rpc.commitment import Recent
from solana.rpc.types import Commitment
from .async_utils import load_bytes_data
from .open_orders_account import _OpenOrdersAccountCore

View File

@ -1,9 +1,9 @@
from typing import List, Dict, Any
from typing import Any, Dict, List
import requests
from solana.rpc.api import Client as conn # pylint: disable=unused-import # noqa:F401
from solana.publickey import PublicKey
from solana.rpc.api import Client as conn # pylint: disable=unused-import # noqa:F401
from .market.types import MarketInfo, TokenInfo
LIVE_MARKETS_URL = "https://raw.githubusercontent.com/project-serum/serum-ts/master/packages/serum/src/markets.json"

View File

@ -1,12 +1,12 @@
"""Serum Dex Instructions."""
from typing import Dict, List, NamedTuple, Optional
from construct import Container
from solana.publickey import PublicKey
from solana.sysvar import SYSVAR_RENT_PUBKEY
from solana.transaction import AccountMeta, TransactionInstruction
from solana.utils.validate import validate_instruction_keys, validate_instruction_type
from spl.token.constants import TOKEN_PROGRAM_ID
from construct import Container
from ._layouts.instructions import INSTRUCTIONS_LAYOUT, InstructionType
from .enums import OrderType, SelfTradeBehavior, Side
@ -268,6 +268,36 @@ class CancelOrderByClientIDV2Params(NamedTuple):
""""""
class CloseOpenOrdersParams(NamedTuple):
"""Cancel order by client ID params."""
open_orders: PublicKey
""""""
owner: PublicKey
""""""
sol_wallet: PublicKey
""""""
market: PublicKey
""""""
program_id: PublicKey = DEFAULT_DEX_PROGRAM_ID
""""""
class InitOpenOrdersParams(NamedTuple):
"""Cancel order by client ID params."""
open_orders: PublicKey
""""""
owner: PublicKey
""""""
market: PublicKey
""""""
market_authority: Optional[PublicKey] = None
""""""
program_id: PublicKey = DEFAULT_DEX_PROGRAM_ID
""""""
def __parse_and_validate_instruction(
instruction: TransactionInstruction, instruction_type: InstructionType
) -> Container:
@ -282,6 +312,8 @@ def __parse_and_validate_instruction(
InstructionType.NEW_ORDER_V3: 12,
InstructionType.CANCEL_ORDER_V2: 6,
InstructionType.CANCEL_ORDER_BY_CLIENT_ID_V2: 6,
InstructionType.CLOSE_OPEN_ORDERS: 4,
InstructionType.INIT_OPEN_ORDERS: 3,
}
validate_instruction_keys(instruction, instruction_type_to_length_map[instruction_type])
data = INSTRUCTIONS_LAYOUT.parse(instruction.data)
@ -289,7 +321,9 @@ def __parse_and_validate_instruction(
return data
def decode_initialize_market(instruction: TransactionInstruction) -> InitializeMarketParams:
def decode_initialize_market(
instruction: TransactionInstruction,
) -> InitializeMarketParams:
"""Decode an instialize market instruction and retrieve the instruction params."""
data = __parse_and_validate_instruction(instruction, InstructionType.INITIALIZE_MARKET)
return InitializeMarketParams(
@ -382,7 +416,9 @@ def decode_settle_funds(instruction: TransactionInstruction) -> SettleFundsParam
)
def decode_cancel_order_by_client_id(instruction: TransactionInstruction) -> CancelOrderByClientIDParams:
def decode_cancel_order_by_client_id(
instruction: TransactionInstruction,
) -> CancelOrderByClientIDParams:
data = __parse_and_validate_instruction(instruction, InstructionType.CANCEL_ORDER_BY_CLIENT_ID)
return CancelOrderByClientIDParams(
market=instruction.keys[0].pubkey,
@ -445,6 +481,29 @@ def decode_cancel_order_by_client_id_v2(instruction: TransactionInstruction) ->
)
def decode_close_open_orders(
instruction: TransactionInstruction,
) -> CloseOpenOrdersParams:
return CloseOpenOrdersParams(
open_orders=instruction.keys[0].pubkey,
owner=instruction.keys[1].pubkey,
sol_wallet=instruction.keys[2].pubkey,
market=instruction.keys[3].pubkey,
)
def decode_init_open_orders(
instruction: TransactionInstruction,
) -> InitOpenOrdersParams:
market_authority = instruction.keys[3].pubkey if len(instruction.keys) == 4 else None
return InitOpenOrdersParams(
open_orders=instruction.keys[0].pubkey,
owner=instruction.keys[1].pubkey,
market=instruction.keys[2].pubkey,
market_authority=market_authority,
)
def initialize_market(params: InitializeMarketParams) -> TransactionInstruction:
"""Generate a transaction instruction to initialize a Serum market."""
return TransactionInstruction(
@ -519,7 +578,10 @@ def match_orders(params: MatchOrdersParams) -> TransactionInstruction:
],
program_id=params.program_id,
data=INSTRUCTIONS_LAYOUT.build(
dict(instruction_type=InstructionType.MATCH_ORDER, args=dict(limit=params.limit))
dict(
instruction_type=InstructionType.MATCH_ORDER,
args=dict(limit=params.limit),
)
),
)
@ -534,7 +596,10 @@ def consume_events(params: ConsumeEventsParams) -> TransactionInstruction:
keys=keys,
program_id=params.program_id,
data=INSTRUCTIONS_LAYOUT.build(
dict(instruction_type=InstructionType.CONSUME_EVENTS, args=dict(limit=params.limit))
dict(
instruction_type=InstructionType.CONSUME_EVENTS,
args=dict(limit=params.limit),
)
),
)
@ -582,7 +647,9 @@ def settle_funds(params: SettleFundsParams) -> TransactionInstruction:
)
def cancel_order_by_client_id(params: CancelOrderByClientIDParams) -> TransactionInstruction:
def cancel_order_by_client_id(
params: CancelOrderByClientIDParams,
) -> TransactionInstruction:
"""Generate a transaction instruction to cancel order by client id."""
return TransactionInstruction(
keys=[
@ -668,7 +735,9 @@ def cancel_order_v2(params: CancelOrderV2Params) -> TransactionInstruction:
)
def cancel_order_by_client_id_v2(params: CancelOrderByClientIDV2Params) -> TransactionInstruction:
def cancel_order_by_client_id_v2(
params: CancelOrderByClientIDV2Params,
) -> TransactionInstruction:
"""Generate a transaction instruction to cancel order by client id."""
return TransactionInstruction(
keys=[
@ -689,3 +758,35 @@ def cancel_order_by_client_id_v2(params: CancelOrderByClientIDV2Params) -> Trans
)
),
)
def close_open_orders(params: CloseOpenOrdersParams) -> TransactionInstruction:
"""Generate a transaction instruction to close open orders account."""
return TransactionInstruction(
keys=[
AccountMeta(pubkey=params.open_orders, is_signer=False, is_writable=True),
AccountMeta(pubkey=params.owner, is_signer=True, is_writable=False),
AccountMeta(pubkey=params.sol_wallet, is_signer=False, is_writable=True),
AccountMeta(pubkey=params.market, is_signer=False, is_writable=False),
],
program_id=params.program_id,
data=INSTRUCTIONS_LAYOUT.build(dict(instruction_type=InstructionType.CLOSE_OPEN_ORDERS, args=dict())),
)
def init_open_orders(params: InitOpenOrdersParams) -> TransactionInstruction:
"""Generate a transaction instruction to initialize open orders account."""
touched_keys = [
AccountMeta(pubkey=params.open_orders, is_signer=False, is_writable=True),
AccountMeta(pubkey=params.owner, is_signer=True, is_writable=False),
AccountMeta(pubkey=params.market, is_signer=False, is_writable=False),
]
if params.market_authority:
touched_keys.append(
AccountMeta(pubkey=params.market_authority, is_signer=False, is_writable=False),
)
return TransactionInstruction(
keys=touched_keys,
program_id=params.program_id,
data=INSTRUCTIONS_LAYOUT.build(dict(instruction_type=InstructionType.INIT_OPEN_ORDERS, args=dict())),
)

View File

@ -1,4 +1,4 @@
from .market import Market # noqa: F401
from .async_market import AsyncMarket # noqa: F401
from .market import Market # noqa: F401
from .orderbook import OrderBook # noqa: F401
from .state import MarketState as State # noqa: F401

View File

@ -9,17 +9,17 @@ from solana.rpc.async_api import AsyncClient
from solana.rpc.types import RPCResponse, TxOpts
from solana.transaction import Transaction
from pyserum import instructions
import pyserum.market.types as t
from pyserum import instructions
from .._layouts.open_orders import OPEN_ORDERS_LAYOUT
from ..enums import OrderType, Side
from ..async_open_orders_account import AsyncOpenOrdersAccount
from ..async_utils import load_bytes_data
from ..enums import OrderType, Side
from ._internal.queue import decode_event_queue, decode_request_queue
from .core import MarketCore
from .orderbook import OrderBook
from .state import MarketState
from .core import MarketCore
LAMPORTS_PER_SOL = 1000000000

View File

@ -11,15 +11,14 @@ from solana.rpc.types import RPCResponse
from solana.system_program import CreateAccountParams, create_account
from solana.transaction import Transaction, TransactionInstruction
from spl.token.constants import ACCOUNT_LEN, TOKEN_PROGRAM_ID, WRAPPED_SOL_MINT
from spl.token.instructions import CloseAccountParams
from spl.token.instructions import InitializeAccountParams, close_account, initialize_account
from spl.token.instructions import CloseAccountParams, InitializeAccountParams, close_account, initialize_account
from pyserum import instructions
import pyserum.market.types as t
from pyserum import instructions
from ..async_open_orders_account import AsyncOpenOrdersAccount
from ..enums import OrderType, SelfTradeBehavior, Side
from ..open_orders_account import OpenOrdersAccount, make_create_account_instruction
from ..async_open_orders_account import AsyncOpenOrdersAccount
from ._internal.queue import decode_event_queue
from .orderbook import OrderBook
from .state import MarketState

View File

@ -9,17 +9,17 @@ from solana.rpc.api import Client
from solana.rpc.types import RPCResponse, TxOpts
from solana.transaction import Transaction
from pyserum import instructions
import pyserum.market.types as t
from pyserum import instructions
from .._layouts.open_orders import OPEN_ORDERS_LAYOUT
from ..enums import OrderType, Side
from ..open_orders_account import OpenOrdersAccount
from ..utils import load_bytes_data
from ._internal.queue import decode_event_queue, decode_request_queue
from .core import MarketCore
from .orderbook import OrderBook
from .state import MarketState
from .core import MarketCore
LAMPORTS_PER_SOL = 1000000000

View File

@ -7,7 +7,7 @@ from solana.publickey import PublicKey
from solana.rpc.api import Client
from solana.rpc.async_api import AsyncClient
from pyserum import utils, async_utils
from pyserum import async_utils, utils
from .._layouts.market import MARKET_LAYOUT
from .types import AccountFlags

View File

@ -1,7 +1,7 @@
from __future__ import annotations
import base64
from typing import List, NamedTuple, TypeVar, Type, Tuple
from typing import List, NamedTuple, Tuple, Type, TypeVar
from solana.publickey import PublicKey
from solana.rpc.api import Client

View File

@ -1,5 +1,5 @@
from typing import Dict
import asyncio
from typing import Dict
import pytest
from solana.keypair import Keypair
@ -7,8 +7,8 @@ from solana.publickey import PublicKey
from solana.rpc.api import Client
from solana.rpc.async_api import AsyncClient
from pyserum.connection import conn
from pyserum.async_connection import async_conn
from pyserum.connection import conn
@pytest.mark.integration

View File

@ -1,6 +1,6 @@
# pylint: disable=R0801
import pytest
import httpx
import pytest
from pyserum.async_connection import get_live_markets, get_token_mints
from pyserum.market.types import MarketInfo, TokenInfo

View File

@ -113,3 +113,36 @@ def test_settle_funds():
)
instruction = inlib.settle_funds(params)
assert inlib.decode_settle_funds(instruction) == params
def test_close_open_orders():
"""Test settle funds."""
params = inlib.CloseOpenOrdersParams(
open_orders=PublicKey(0),
owner=PublicKey(1),
sol_wallet=PublicKey(2),
market=PublicKey(3),
)
instruction = inlib.close_open_orders(params)
assert inlib.decode_close_open_orders(instruction) == params
def test_init_open_orders():
"""Test settle funds."""
params = inlib.InitOpenOrdersParams(
open_orders=PublicKey(0), owner=PublicKey(1), market=PublicKey(2), market_authority=None
)
instruction = inlib.init_open_orders(params)
assert inlib.decode_init_open_orders(instruction) == params
def test_init_open_orders_with_authority():
"""Test settle funds."""
params = inlib.InitOpenOrdersParams(
open_orders=PublicKey(0),
owner=PublicKey(1),
market=PublicKey(2),
market_authority=PublicKey(3),
)
instruction = inlib.init_open_orders(params)
assert inlib.decode_init_open_orders(instruction) == params