Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ async def run_example():

assert builder_id, "`builder_id` is not set"

markets_dict = await rest_client.markets_info.get_markets_dict()
markets_dict = await rest_client.info.get_markets_dict()
fees = await rest_client.account.get_fees(market_names=[MARKET_NAME], builder_id=builder_id)
builder_fee = fees.data[0].builder_fee_rate

Expand Down
39 changes: 39 additions & 0 deletions examples/cases/buildercode/get_builder_trades.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import logging.handlers
from asyncio import run

from examples.utils import create_rest_client, init_env

LOGGER = logging.getLogger()

PAGE_LIMIT = 100


async def run_example():
init_env()
rest_client = create_rest_client()

LOGGER.info("Fetching builder trades (limit=%s)...", PAGE_LIMIT)

response = await rest_client.builder.get_trades(limit=PAGE_LIMIT)
trades = response.data or []

LOGGER.info("Fetched %s trade(s)", len(trades))

for trade in trades:
LOGGER.info("Trade: %s", trade.to_pretty_json())

# Fetch the next page using the cursor returned in the pagination block.
if response.pagination and response.pagination.cursor:
next_cursor = response.pagination.cursor

LOGGER.info("Fetching next page (cursor=%s)...", next_cursor)

next_response = await rest_client.builder.get_trades(cursor=next_cursor, limit=PAGE_LIMIT)

LOGGER.info("Fetched %s trade(s) on the next page", len(next_response.data or []))

await rest_client.close()


if __name__ == "__main__":
run(main=run_example())
4 changes: 2 additions & 2 deletions examples/cases/createorder/create_market_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@

async def run_example():
rest_client = create_rest_client()
markets_dict = await rest_client.markets_info.get_markets_dict()
market_stats = await rest_client.markets_info.get_market_statistics(market_name=MARKET_NAME)
markets_dict = await rest_client.info.get_markets_dict()
market_stats = await rest_client.info.get_market_statistics(market_name=MARKET_NAME)

market = markets_dict[MARKET_NAME]

Expand Down
22 changes: 22 additions & 0 deletions x10/clients/rest/modules/builder_module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from typing import List, Optional

from x10.clients.rest.modules.base_module import BaseModule
from x10.models.trade import BuilderTradeModel
from x10.utils.http import WrappedApiResponseModel, send_get_request


class BuilderModule(BaseModule):
async def get_trades(
self,
cursor: Optional[int] = None,
limit: Optional[int] = None,
) -> WrappedApiResponseModel[List[BuilderTradeModel]]:
"""
Returns the trades attributed to the authenticated builder, newest first.
The response is paginated by trade id via the `cursor`.
"""

url = self._get_url("/builder/trades", query={"cursor": cursor, "limit": limit})
return await send_get_request(
await self._get_session(), url, List[BuilderTradeModel], api_key=self._get_api_key()
)
8 changes: 8 additions & 0 deletions x10/clients/rest/rest_api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from typing import Dict, Optional

from x10.clients.rest.modules.account_module import AccountModule
from x10.clients.rest.modules.builder_module import BuilderModule
from x10.clients.rest.modules.info_module import InfoModule
from x10.clients.rest.modules.order_management_module import OrderManagementModule
from x10.clients.rest.modules.testnet_module import TestnetModule
Expand Down Expand Up @@ -41,6 +42,7 @@ class RestApiClient:
__order_management_module: OrderManagementModule
__vault_module: VaultModule
__testnet_module: TestnetModule
__builder_module: BuilderModule

async def place_order(
self,
Expand Down Expand Up @@ -106,6 +108,7 @@ async def close(self):
await self.__order_management_module.close_session()
await self.__vault_module.close_session()
await self.__testnet_module.close_session()
await self.__builder_module.close_session()

async def __aenter__(self):
return self
Expand All @@ -131,6 +134,7 @@ def __init__(self, config: Config, stark_account: StarkPerpetualAccount | None =
api_key=api_key,
)
self.__testnet_module = TestnetModule(config, api_key=api_key, account_module=self.__account_module)
self.__builder_module = BuilderModule(config, api_key=api_key)

@property
def config(self):
Expand Down Expand Up @@ -159,3 +163,7 @@ def testnet(self):
@property
def vault(self):
return self.__vault_module

@property
def builder(self):
return self.__builder_module
20 changes: 20 additions & 0 deletions x10/models/trade.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from decimal import Decimal
from typing import Optional

from pydantic import AliasChoices, Field
from strenum import StrEnum
Expand Down Expand Up @@ -36,3 +37,22 @@ class AccountTradeModel(X10BaseModel):
is_taker: bool
trade_type: TradeType
created_time: int


class BuilderTradeModel(X10BaseModel):
"""
A trade as seen by a builder. Only the side (maker/taker) that belongs to the
requesting builder is populated; the counterparty side is masked with `None`.
"""

id: int
time: int
volume: Decimal
maker_id: Optional[int] = None
taker_id: Optional[int] = None
maker_builder_id: Optional[int] = None
taker_builder_id: Optional[int] = None
maker_fee: Optional[Decimal] = None
taker_fee: Optional[Decimal] = None
maker_builder_fee: Optional[Decimal] = None
taker_builder_fee: Optional[Decimal] = None
Loading