205 lines
6.8 KiB
Python
205 lines
6.8 KiB
Python
# pylint: disable=redefined-outer-name
|
|
|
|
import pytest
|
|
from solana.account import Account
|
|
from solana.publickey import PublicKey
|
|
from solana.rpc.async_api import AsyncClient
|
|
from solana.rpc.types import TxOpts
|
|
|
|
from pyserum.enums import OrderType, Side
|
|
from pyserum.market import AsyncMarket
|
|
|
|
|
|
@pytest.mark.async_integration
|
|
@pytest.fixture(scope="module")
|
|
def bootstrapped_market(
|
|
async_http_client: AsyncClient, stubbed_market_pk: PublicKey, stubbed_dex_program_pk: PublicKey, event_loop
|
|
) -> AsyncMarket:
|
|
return event_loop.run_until_complete(
|
|
AsyncMarket.load(async_http_client, stubbed_market_pk, stubbed_dex_program_pk, force_use_request_queue=True)
|
|
)
|
|
|
|
|
|
@pytest.mark.async_integration
|
|
@pytest.mark.asyncio
|
|
async def test_bootstrapped_market(
|
|
bootstrapped_market: AsyncMarket,
|
|
stubbed_market_pk: PublicKey,
|
|
stubbed_dex_program_pk: PublicKey,
|
|
stubbed_base_mint: PublicKey,
|
|
stubbed_quote_mint: PublicKey,
|
|
):
|
|
assert isinstance(bootstrapped_market, AsyncMarket)
|
|
assert bootstrapped_market.state.public_key() == stubbed_market_pk
|
|
assert bootstrapped_market.state.program_id() == stubbed_dex_program_pk
|
|
assert bootstrapped_market.state.base_mint() == stubbed_base_mint.public_key()
|
|
assert bootstrapped_market.state.quote_mint() == stubbed_quote_mint.public_key()
|
|
|
|
|
|
@pytest.mark.async_integration
|
|
@pytest.mark.asyncio
|
|
async def test_market_load_bid(bootstrapped_market: AsyncMarket):
|
|
# TODO: test for non-zero order case.
|
|
bids = await bootstrapped_market.load_bids()
|
|
assert sum(1 for _ in bids) == 0
|
|
|
|
|
|
@pytest.mark.async_integration
|
|
@pytest.mark.asyncio
|
|
async def test_market_load_asks(bootstrapped_market: AsyncMarket):
|
|
# TODO: test for non-zero order case.
|
|
asks = await bootstrapped_market.load_asks()
|
|
assert sum(1 for _ in asks) == 0
|
|
|
|
|
|
@pytest.mark.async_integration
|
|
@pytest.mark.asyncio
|
|
async def test_market_load_events(bootstrapped_market: AsyncMarket):
|
|
event_queue = await bootstrapped_market.load_event_queue()
|
|
assert len(event_queue) == 0
|
|
|
|
|
|
@pytest.mark.async_integration
|
|
@pytest.mark.asyncio
|
|
async def test_market_load_requests(bootstrapped_market: AsyncMarket):
|
|
request_queue = await bootstrapped_market.load_request_queue()
|
|
# 2 requests in the request queue in the beginning with one bid and one ask
|
|
assert len(request_queue) == 2
|
|
|
|
|
|
@pytest.mark.async_integration
|
|
@pytest.mark.asyncio
|
|
async def test_match_order(bootstrapped_market: AsyncMarket, stubbed_payer: Account):
|
|
await bootstrapped_market.match_orders(stubbed_payer, 2, TxOpts(skip_confirmation=False))
|
|
|
|
request_queue = await bootstrapped_market.load_request_queue()
|
|
# 0 request after matching.
|
|
assert len(request_queue) == 0
|
|
|
|
event_queue = await bootstrapped_market.load_event_queue()
|
|
# 5 event after the order is matched, including 2 fill events.
|
|
assert len(event_queue) == 5
|
|
|
|
# There should be no bid order.
|
|
bids = await bootstrapped_market.load_bids()
|
|
assert sum(1 for _ in bids) == 0
|
|
|
|
# There should be no ask order.
|
|
asks = await bootstrapped_market.load_asks()
|
|
assert sum(1 for _ in asks) == 0
|
|
|
|
|
|
@pytest.mark.async_integration
|
|
@pytest.mark.asyncio
|
|
async def test_settle_fund(
|
|
bootstrapped_market: AsyncMarket,
|
|
stubbed_payer: Account,
|
|
stubbed_quote_wallet: Account,
|
|
stubbed_base_wallet: Account,
|
|
):
|
|
open_order_accounts = await bootstrapped_market.find_open_orders_accounts_for_owner(stubbed_payer.public_key())
|
|
|
|
with pytest.raises(ValueError):
|
|
# Should not allow base_wallet to be base_vault
|
|
await bootstrapped_market.settle_funds(
|
|
stubbed_payer,
|
|
open_order_accounts[0],
|
|
bootstrapped_market.state.base_vault(),
|
|
stubbed_quote_wallet.public_key(),
|
|
)
|
|
|
|
with pytest.raises(ValueError):
|
|
# Should not allow quote_wallet to be wallet_vault
|
|
await bootstrapped_market.settle_funds(
|
|
stubbed_payer,
|
|
open_order_accounts[0],
|
|
stubbed_base_wallet.public_key(),
|
|
bootstrapped_market.state.quote_vault(),
|
|
)
|
|
|
|
for open_order_account in open_order_accounts:
|
|
assert "error" not in await bootstrapped_market.settle_funds(
|
|
stubbed_payer,
|
|
open_order_account,
|
|
stubbed_base_wallet.public_key(),
|
|
stubbed_quote_wallet.public_key(),
|
|
opts=TxOpts(skip_confirmation=False),
|
|
)
|
|
|
|
# TODO: Check account states after settling funds
|
|
|
|
|
|
@pytest.mark.async_integration
|
|
@pytest.mark.asyncio
|
|
async def test_order_placement_cancellation_cycle(
|
|
bootstrapped_market: AsyncMarket,
|
|
stubbed_payer: Account,
|
|
stubbed_quote_wallet: Account,
|
|
stubbed_base_wallet: Account,
|
|
):
|
|
initial_request_len = len(await bootstrapped_market.load_request_queue())
|
|
await bootstrapped_market.place_order(
|
|
payer=stubbed_quote_wallet.public_key(),
|
|
owner=stubbed_payer,
|
|
side=Side.BUY,
|
|
order_type=OrderType.LIMIT,
|
|
limit_price=1000,
|
|
max_quantity=3000,
|
|
opts=TxOpts(skip_confirmation=False),
|
|
)
|
|
|
|
request_queue = await bootstrapped_market.load_request_queue()
|
|
# 0 request after matching.
|
|
assert len(request_queue) == initial_request_len + 1
|
|
|
|
# There should be no bid order.
|
|
bids = await bootstrapped_market.load_bids()
|
|
assert sum(1 for _ in bids) == 0
|
|
|
|
# There should be no ask order.
|
|
asks = await bootstrapped_market.load_asks()
|
|
assert sum(1 for _ in asks) == 0
|
|
|
|
await bootstrapped_market.place_order(
|
|
payer=stubbed_base_wallet.public_key(),
|
|
owner=stubbed_payer,
|
|
side=Side.SELL,
|
|
order_type=OrderType.LIMIT,
|
|
limit_price=1500,
|
|
max_quantity=3000,
|
|
opts=TxOpts(skip_confirmation=False),
|
|
)
|
|
|
|
# The two order shouldn't get executed since there is a price difference of 1
|
|
await bootstrapped_market.match_orders(
|
|
stubbed_payer,
|
|
2,
|
|
opts=TxOpts(skip_confirmation=False),
|
|
)
|
|
|
|
# There should be 1 bid order that we sent earlier.
|
|
bids = await bootstrapped_market.load_bids()
|
|
assert sum(1 for _ in bids) == 1
|
|
|
|
# There should be 1 ask order that we sent earlier.
|
|
asks = await bootstrapped_market.load_asks()
|
|
assert sum(1 for _ in asks) == 1
|
|
|
|
for bid in bids:
|
|
await bootstrapped_market.cancel_order(stubbed_payer, bid, opts=TxOpts(skip_confirmation=False))
|
|
|
|
await bootstrapped_market.match_orders(stubbed_payer, 1, opts=TxOpts(skip_confirmation=False))
|
|
|
|
# All bid order should have been cancelled.
|
|
bids = await bootstrapped_market.load_bids()
|
|
assert sum(1 for _ in bids) == 0
|
|
|
|
for ask in asks:
|
|
await bootstrapped_market.cancel_order(stubbed_payer, ask, opts=TxOpts(skip_confirmation=False))
|
|
|
|
await bootstrapped_market.match_orders(stubbed_payer, 1, opts=TxOpts(skip_confirmation=False))
|
|
|
|
# All ask order should have been cancelled.
|
|
asks = await bootstrapped_market.load_asks()
|
|
assert sum(1 for _ in asks) == 0
|