diff --git a/mango/instructionreporter.py b/mango/instructionreporter.py index 7dc21df..eb1f16d 100644 --- a/mango/instructionreporter.py +++ b/mango/instructionreporter.py @@ -16,7 +16,7 @@ import typing -from pyserum._layouts.instructions import InstructionType as SerumInstructionType +from pyserum._layouts.instructions import InstructionType as PySerumInstructionType from solana.publickey import PublicKey from solana.transaction import TransactionInstruction @@ -56,7 +56,7 @@ class SerumInstructionReporter(InstructionReporter): def report(self, instruction: TransactionInstruction) -> str: initial = layouts.SERUM_INSTRUCTION_VARIANT_FINDER.parse(instruction.data) - instruction_type = SerumInstructionType(initial.variant) + instruction_type = PySerumInstructionType(initial.variant) return f"« Serum Instruction: {instruction_type.name}: " + "".join("{:02x}".format(x) for x in instruction.data) + "»" diff --git a/mango/instructions.py b/mango/instructions.py index 70f4be9..08dd004 100644 --- a/mango/instructions.py +++ b/mango/instructions.py @@ -18,10 +18,11 @@ import pyserum.enums import typing from decimal import Decimal -from pyserum.enums import OrderType as SerumOrderType, Side as SerumSide -from pyserum.instructions import settle_funds, SettleFundsParams +from pyserum._layouts.instructions import INSTRUCTIONS_LAYOUT as PYSERUM_INSTRUCTIONS_LAYOUT, InstructionType as PySerumInstructionType +from pyserum.enums import OrderType as PySerumOrderType, Side as PySerumSide +from pyserum.instructions import settle_funds as pyserum_settle_funds, SettleFundsParams as PySerumSettleFundsParams from pyserum.market import Market as PySerumMarket -from pyserum.open_orders_account import make_create_account_instruction +from pyserum.open_orders_account import make_create_account_instruction as pyserum_make_create_account_instruction from solana.account import Account as SolanaAccount from solana.publickey import PublicKey from solana.system_program import CreateAccountParams, create_account @@ -29,7 +30,6 @@ from solana.sysvar import SYSVAR_RENT_PUBKEY from solana.transaction import AccountMeta, TransactionInstruction from spl.token.constants import ACCOUNT_LEN, TOKEN_PROGRAM_ID from spl.token.instructions import CloseAccountParams, InitializeAccountParams, Transfer2Params, close_account, create_associated_token_account, initialize_account, transfer2 -from pyserum._layouts.instructions import INSTRUCTIONS_LAYOUT, InstructionType from .account import Account from .combinableinstructions import CombinableInstructions @@ -132,7 +132,7 @@ def build_close_spl_account_instructions(context: Context, wallet: Wallet, addre def build_create_serum_open_orders_instructions(context: Context, wallet: Wallet, market: PySerumMarket) -> CombinableInstructions: new_open_orders_account = SolanaAccount() minimum_balance = context.client.get_minimum_balance_for_rent_exemption(layouts.OPEN_ORDERS.sizeof()) - instruction = make_create_account_instruction( + instruction = pyserum_make_create_account_instruction( owner_address=wallet.address, new_account_address=new_open_orders_account.public_key(), lamports=minimum_balance, @@ -148,8 +148,8 @@ def build_create_serum_open_orders_instructions(context: Context, wallet: Wallet # def build_serum_place_order_instructions(context: Context, wallet: Wallet, market: PySerumMarket, source: PublicKey, open_orders_address: PublicKey, order_type: OrderType, side: Side, price: Decimal, quantity: Decimal, client_id: int, fee_discount_address: typing.Optional[PublicKey]) -> CombinableInstructions: - serum_order_type: SerumOrderType = SerumOrderType.POST_ONLY if order_type == OrderType.POST_ONLY else SerumOrderType.IOC if order_type == OrderType.IOC else SerumOrderType.LIMIT - serum_side: SerumSide = SerumSide.SELL if side == Side.SELL else SerumSide.BUY + serum_order_type: PySerumOrderType = PySerumOrderType.POST_ONLY if order_type == OrderType.POST_ONLY else PySerumOrderType.IOC if order_type == OrderType.IOC else PySerumOrderType.LIMIT + serum_side: PySerumSide = PySerumSide.SELL if side == Side.SELL else PySerumSide.BUY instruction = market.make_place_order_instruction( source, @@ -178,8 +178,8 @@ def build_serum_consume_events_instructions(context: Context, market_address: Pu for pubkey in [*open_orders_addresses, market_address, event_queue_address] ], program_id=context.dex_program_id, - data=INSTRUCTIONS_LAYOUT.build( - dict(instruction_type=InstructionType.CONSUME_EVENTS, args=dict(limit=limit)) + data=PYSERUM_INSTRUCTIONS_LAYOUT.build( + dict(instruction_type=PySerumInstructionType.CONSUME_EVENTS, args=dict(limit=limit)) ), ) @@ -201,8 +201,8 @@ def build_serum_settle_instructions(context: Context, wallet: Wallet, market: Py [bytes(market.state.public_key()), market.state.vault_signer_nonce().to_bytes(8, byteorder="little")], market.state.program_id(), ) - instruction = settle_funds( - SettleFundsParams( + instruction = pyserum_settle_funds( + PySerumSettleFundsParams( market=market.state.public_key(), open_orders=open_orders_address, owner=wallet.address, @@ -764,8 +764,8 @@ def build_mango_settle_instructions(context: Context, wallet: Wallet, market: Py [bytes(market.state.public_key()), market.state.vault_signer_nonce().to_bytes(8, byteorder="little")], market.state.program_id(), ) - instruction = settle_funds( - SettleFundsParams( + instruction = pyserum_settle_funds( + PySerumSettleFundsParams( market=market.state.public_key(), open_orders=open_orders_address, owner=wallet.address, diff --git a/mango/openorders.py b/mango/openorders.py index 7bf35b2..efded48 100644 --- a/mango/openorders.py +++ b/mango/openorders.py @@ -17,7 +17,7 @@ import typing from decimal import Decimal -from pyserum.open_orders_account import OpenOrdersAccount +from pyserum.open_orders_account import OpenOrdersAccount as PySerumOpenOrdersAccount from solana.publickey import PublicKey from solana.rpc.types import MemcmpOpts @@ -54,9 +54,9 @@ class OpenOrders(AddressableAccount): self.placed_orders: typing.Sequence[PlacedOrder] = placed_orders self.referrer_rebate_accrued: Decimal = referrer_rebate_accrued - # Sometimes pyserum wants to take its own OpenOrdersAccount as a parameter (e.g. in settle_funds()) - def to_pyserum(self) -> OpenOrdersAccount: - return OpenOrdersAccount.from_bytes(self.address, self.account_info.data) + # Sometimes pyserum wants to take its own PySerumOpenOrdersAccount as a parameter (e.g. in settle_funds()) + def to_pyserum(self) -> PySerumOpenOrdersAccount: + return PySerumOpenOrdersAccount.from_bytes(self.address, self.account_info.data) @staticmethod def from_layout(layout: layouts.OPEN_ORDERS, account_info: AccountInfo, diff --git a/mango/orderbookside.py b/mango/orderbookside.py index cb1c1f0..898ec8d 100644 --- a/mango/orderbookside.py +++ b/mango/orderbookside.py @@ -79,7 +79,7 @@ class OrderBookSide(AddressableAccount): raise Exception(f"OrderBookSide account not found at address '{address}'") return OrderBookSide.parse(context, account_info, perp_market_details) - def orders(self): + def orders(self) -> typing.Generator[Order, None, None]: if self.leaf_count == 0: return diff --git a/mango/orders.py b/mango/orders.py index 871cb26..b832297 100644 --- a/mango/orders.py +++ b/mango/orders.py @@ -20,7 +20,7 @@ import pyserum.enums import typing from decimal import Decimal -from pyserum.market.types import Order as SerumOrder +from pyserum.market.types import Order as PySerumOrder from solana.publickey import PublicKey from .constants import SYSTEM_PROGRAM_ADDRESS @@ -123,7 +123,7 @@ class Order(typing.NamedTuple): client_id=client_id, owner=self.owner, order_type=self.order_type) @staticmethod - def from_serum_order(serum_order: SerumOrder) -> "Order": + def from_serum_order(serum_order: PySerumOrder) -> "Order": price = Decimal(serum_order.info.price) quantity = Decimal(serum_order.info.size) side = Side.from_value(serum_order.side) diff --git a/mango/serummarket.py b/mango/serummarket.py index 3ef118a..f27be8c 100644 --- a/mango/serummarket.py +++ b/mango/serummarket.py @@ -17,7 +17,7 @@ import itertools import typing from pyserum.market import Market as PySerumMarket -from pyserum.market.orderbook import OrderBook as SerumOrderBook +from pyserum.market.orderbook import OrderBook as PySerumOrderBook from solana.publickey import PublicKey from .accountinfo import AccountInfo @@ -45,8 +45,8 @@ class SerumMarket(Market): raw_market = self.underlying_serum_market [bids_info, asks_info] = AccountInfo.load_multiple( context, [raw_market.state.bids(), raw_market.state.asks()]) - bids_orderbook = SerumOrderBook.from_bytes(raw_market.state, bids_info.data) - asks_orderbook = SerumOrderBook.from_bytes(raw_market.state, asks_info.data) + bids_orderbook = PySerumOrderBook.from_bytes(raw_market.state, bids_info.data) + asks_orderbook = PySerumOrderBook.from_bytes(raw_market.state, asks_info.data) return list(map(Order.from_serum_order, itertools.chain(bids_orderbook.orders(), asks_orderbook.orders()))) diff --git a/mango/serummarketinstructionbuilder.py b/mango/serummarketinstructionbuilder.py index c63f223..9991dde 100644 --- a/mango/serummarketinstructionbuilder.py +++ b/mango/serummarketinstructionbuilder.py @@ -18,7 +18,7 @@ import pyserum.enums import typing from decimal import Decimal -from pyserum.market import Market +from pyserum.market import Market as PySerumMarket from solana.publickey import PublicKey from .combinableinstructions import CombinableInstructions @@ -42,12 +42,12 @@ from .wallet import Wallet # on initial setup in the `load()` method. # class SerumMarketInstructionBuilder(MarketInstructionBuilder): - def __init__(self, context: Context, wallet: Wallet, serum_market: SerumMarket, raw_market: Market, base_token_account: TokenAccount, quote_token_account: TokenAccount, open_orders_address: typing.Optional[PublicKey], fee_discount_token_address: typing.Optional[PublicKey]): + def __init__(self, context: Context, wallet: Wallet, serum_market: SerumMarket, raw_market: PySerumMarket, base_token_account: TokenAccount, quote_token_account: TokenAccount, open_orders_address: typing.Optional[PublicKey], fee_discount_token_address: typing.Optional[PublicKey]): super().__init__() self.context: Context = context self.wallet: Wallet = wallet self.serum_market: SerumMarket = serum_market - self.raw_market: Market = raw_market + self.raw_market: PySerumMarket = raw_market self.base_token_account: TokenAccount = base_token_account self.quote_token_account: TokenAccount = quote_token_account self.open_orders_address: typing.Optional[PublicKey] = open_orders_address @@ -55,7 +55,8 @@ class SerumMarketInstructionBuilder(MarketInstructionBuilder): @staticmethod def load(context: Context, wallet: Wallet, serum_market: SerumMarket) -> "SerumMarketInstructionBuilder": - raw_market: Market = Market.load(context.client.compatible_client, serum_market.address, context.dex_program_id) + raw_market: PySerumMarket = PySerumMarket.load( + context.client.compatible_client, serum_market.address, context.dex_program_id) fee_discount_token_address: typing.Optional[PublicKey] = None srm_token = context.token_lookup.find_by_symbol("SRM") diff --git a/mango/spotmarket.py b/mango/spotmarket.py index e220348..90e86d8 100644 --- a/mango/spotmarket.py +++ b/mango/spotmarket.py @@ -17,7 +17,7 @@ import itertools import typing from pyserum.market import Market as PySerumMarket -from pyserum.market.orderbook import OrderBook as SerumOrderBook +from pyserum.market.orderbook import OrderBook as PySerumOrderBook from solana.publickey import PublicKey from .accountinfo import AccountInfo @@ -47,8 +47,8 @@ class SpotMarket(Market): raw_market = self.underlying_serum_market [bids_info, asks_info] = AccountInfo.load_multiple( context, [raw_market.state.bids(), raw_market.state.asks()]) - bids_orderbook = SerumOrderBook.from_bytes(raw_market.state, bids_info.data) - asks_orderbook = SerumOrderBook.from_bytes(raw_market.state, asks_info.data) + bids_orderbook = PySerumOrderBook.from_bytes(raw_market.state, bids_info.data) + asks_orderbook = PySerumOrderBook.from_bytes(raw_market.state, asks_info.data) return list(map(Order.from_serum_order, itertools.chain(bids_orderbook.orders(), asks_orderbook.orders()))) diff --git a/mango/spotmarketinstructionbuilder.py b/mango/spotmarketinstructionbuilder.py index 6ca126b..a25df2b 100644 --- a/mango/spotmarketinstructionbuilder.py +++ b/mango/spotmarketinstructionbuilder.py @@ -16,7 +16,7 @@ import typing from decimal import Decimal -from pyserum.market import Market +from pyserum.market import Market as PySerumMarket from solana.publickey import PublicKey from .account import Account @@ -42,14 +42,14 @@ from .wallet import Wallet # class SpotMarketInstructionBuilder(MarketInstructionBuilder): - def __init__(self, context: Context, wallet: Wallet, group: Group, account: Account, spot_market: SpotMarket, raw_market: Market, market_index: int, fee_discount_token_address: typing.Optional[PublicKey]): + def __init__(self, context: Context, wallet: Wallet, group: Group, account: Account, spot_market: SpotMarket, raw_market: PySerumMarket, market_index: int, fee_discount_token_address: typing.Optional[PublicKey]): super().__init__() self.context: Context = context self.wallet: Wallet = wallet self.group: Group = group self.account: Account = account self.spot_market: SpotMarket = spot_market - self.raw_market: Market = raw_market + self.raw_market: PySerumMarket = raw_market self.market_index: int = market_index self.fee_discount_token_address: typing.Optional[PublicKey] = fee_discount_token_address @@ -57,7 +57,8 @@ class SpotMarketInstructionBuilder(MarketInstructionBuilder): @staticmethod def load(context: Context, wallet: Wallet, group: Group, account: Account, spot_market: SpotMarket) -> "SpotMarketInstructionBuilder": - raw_market: Market = Market.load(context.client.compatible_client, spot_market.address, context.dex_program_id) + raw_market: PySerumMarket = PySerumMarket.load( + context.client.compatible_client, spot_market.address, context.dex_program_id) fee_discount_token_address: typing.Optional[PublicKey] = None srm_token = context.token_lookup.find_by_symbol("SRM") diff --git a/tests/fakes.py b/tests/fakes.py index ca1a78d..935763a 100644 --- a/tests/fakes.py +++ b/tests/fakes.py @@ -2,8 +2,8 @@ import datetime import mango from decimal import Decimal -from pyserum import market -from pyserum.market.state import MarketState +from pyserum.market import Market as PySerumMarket +from pyserum.market.state import MarketState as PySerumMarketState from solana.account import Account from solana.publickey import PublicKey from solana.rpc.types import RPCResponse @@ -66,10 +66,10 @@ def fake_context() -> mango.Context: return context -def fake_market() -> market.Market: +def fake_market() -> PySerumMarket: Container = NamedTuple("Container", [("own_address", PublicKey), ("vault_signer_nonce", int)]) container = Container(own_address=fake_seeded_public_key("market address"), vault_signer_nonce=2) - state = MarketState(container, fake_seeded_public_key("program ID"), 6, 6) + state = PySerumMarketState(container, fake_seeded_public_key("program ID"), 6, 6) state.base_vault = lambda: fake_seeded_public_key("base vault") state.quote_vault = lambda: fake_seeded_public_key("quote vault") state.event_queue = lambda: fake_seeded_public_key("event queue") @@ -78,7 +78,7 @@ def fake_market() -> market.Market: state.asks = lambda: fake_seeded_public_key("asks") state.base_lot_size = lambda: 1 state.quote_lot_size = lambda: 1 - return market.Market(None, state) + return PySerumMarket(None, state) def fake_spot_market_stub() -> mango.SpotMarketStub: diff --git a/tests/test_instructions.py b/tests/test_instructions.py index f49f594..628cb4e 100644 --- a/tests/test_instructions.py +++ b/tests/test_instructions.py @@ -4,8 +4,8 @@ from .context import mango from .fakes import fake_context, fake_market, fake_seeded_public_key, fake_token, fake_wallet from decimal import Decimal -from pyserum.enums import OrderType, Side -from pyserum.market.market import Market +from pyserum.enums import OrderType as PySerumOrderType, Side as PySerumSide +from pyserum.market.market import Market as PySerumMarket from solana.publickey import PublicKey from solana.transaction import TransactionInstruction @@ -66,7 +66,7 @@ def test_build_close_spl_account_instructions(): def test_build_create_serum_open_orders_instructions(): context: mango.Context = fake_context() wallet: mango.Wallet = fake_wallet() - market: Market = fake_market() + market: PySerumMarket = fake_market() actual = mango.build_create_serum_open_orders_instructions(context, wallet, market) assert actual is not None assert len(actual.signers) == 1 @@ -78,11 +78,11 @@ def test_build_create_serum_open_orders_instructions(): def test_build_serum_place_order_instructions(): context: mango.Context = fake_context() wallet: mango.Wallet = fake_wallet() - market: Market = fake_market() + market: PySerumMarket = fake_market() source: PublicKey = fake_seeded_public_key("source") open_orders_address: PublicKey = fake_seeded_public_key("open orders account") - order_type: OrderType = OrderType.IOC - side: Side = Side.BUY + order_type: PySerumOrderType = PySerumOrderType.IOC + side: PySerumSide = PySerumSide.BUY price: Decimal = Decimal(72) quantity: Decimal = Decimal("0.05") client_id: int = 53