Skip to content
Open
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
270 changes: 49 additions & 221 deletions core/api-doc-config.generated.json

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions core/src/exchanges/baozi/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ import {
const PROGRAM_ERRORS: Record<number, { type: string; message: string }> = {
6000: { type: 'bad_request', message: 'Unauthorized' },
6001: { type: 'bad_request', message: 'Market not found' },
6013: { type: 'bad_request', message: 'Betting is closed' }, // Changed from 6018
6014: { type: 'bad_request', message: 'Betting is frozen' }, // Changed from 6040
6015: { type: 'bad_request', message: 'Market is not open for betting' },
6018: { type: 'bad_request', message: 'Betting is closed' },
6020: { type: 'invalid_order', message: 'Bet amount too small' },
6040: { type: 'bad_request', message: 'Betting is frozen' },
6041: { type: 'invalid_order', message: 'Bet amount too large' },
6023: { type: 'invalid_order', message: 'Bet amount too small' }, // Changed from 6020
6024: { type: 'invalid_order', message: 'Bet amount too large' }, // Changed from 6041
};

/**
Expand Down
163 changes: 38 additions & 125 deletions sdks/python/pmxt/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -843,11 +843,7 @@ def _hosted_cancel_validation_routes(self) -> Tuple[str, Optional[str]]:
return "cancel_polymarket", None
if self.exchange_name == "opinion":
return "cancel_opinion_polygon", "cancel_opinion_bsc_pull"
if self.exchange_name == "limitless":
return "cancel_limitless_polygon", "cancel_limitless_base_pull"
raise NotSupported(
"Hosted trading is only supported for Polymarket, Opinion, and Limitless."
)
raise NotSupported("Hosted trading is only supported for Polymarket and Opinion.")

@staticmethod
def _hosted_typed_data(payload: Dict[str, Any], key: str) -> Dict[str, Any]:
Expand Down Expand Up @@ -1193,7 +1189,7 @@ def has(self) -> Dict[str, Any]:

# Low-Level API Access

def _call_method(self, method_name: str, params: Any = None) -> Any:
def _call_method(self, method_name: str, params: Optional[Dict[str, Any]] = None) -> Any:
"""Call any exchange method on the server by name."""
try:
url = f"{self._resolve_sidecar_host()}/api/{self.exchange_name}/{method_name}"
Expand Down Expand Up @@ -1423,11 +1419,9 @@ def fetch_series(self, params: Optional[dict] = None, **kwargs) -> List[UnifiedS
except ApiException as e:
raise self._parse_api_exception(e) from None

def fetch_market(self, params: Optional[Union[dict, str]] = None, **kwargs) -> UnifiedMarket:
def fetch_market(self, params: Optional[dict] = None, **kwargs) -> UnifiedMarket:
try:
args = []
if isinstance(params, str):
params = {"market_id": params}
if kwargs:
params = {**(params or {}), **kwargs}
if params is not None:
Expand Down Expand Up @@ -1491,7 +1485,7 @@ def fetch_event_metadata(self, event_ticker: str) -> Dict[str, Any]:
except ApiException as e:
raise self._parse_api_exception(e) from None

def fetch_order_book(self, outcome_id: Union[str, "MarketOutcome"] = _UNSET, limit: Optional[float] = None, params: Optional[FetchOrderBookParams] = None, **kwargs) -> Union[OrderBook, List[OrderBook]]:
def fetch_order_book(self, outcome_id: Union[str, "MarketOutcome"] = _UNSET, limit: Optional[float] = None, params: Optional[dict] = None, **kwargs) -> Union[OrderBook, List[OrderBook]]:
try:
args = []
if kwargs:
Expand Down Expand Up @@ -1543,8 +1537,6 @@ def fetch_order_books(self, outcome_ids: List[Union[str, "MarketOutcome"]]) -> D
raise self._parse_api_exception(e) from None

def cancel_order(self, order_id: str) -> Order:
if self.is_hosted:
return self._hosted_cancel_order(order_id)
try:
args = []
args.append(order_id)
Expand All @@ -1565,12 +1557,6 @@ def cancel_order(self, order_id: str) -> Order:
raise self._parse_api_exception(e) from None

def fetch_order(self, order_id: str) -> Order:
if self.is_hosted:
response = self._hosted_request(
"fetch_order",
path_params={"order_id": order_id},
)
return self._hosted_single(response, "order", order_from_v0)
try:
args = []
args.append(order_id)
Expand All @@ -1591,16 +1577,6 @@ def fetch_order(self, order_id: str) -> Order:
raise self._parse_api_exception(e) from None

def fetch_open_orders(self, market_id: Optional[str] = None) -> List[Order]:
if self.is_hosted:
resolved_address = resolve_wallet_address(self, None)
params: Dict[str, Any] = {"address": resolved_address}
if market_id is not None:
params["market_id"] = market_id
response = self._hosted_request(
"fetch_open_orders",
params=params,
)
return self._hosted_collection(response, "orders", order_from_v0)
try:
args = []
if market_id is not None:
Expand All @@ -1622,13 +1598,6 @@ def fetch_open_orders(self, market_id: Optional[str] = None) -> List[Order]:
raise self._parse_api_exception(e) from None

def fetch_my_trades(self, params: Optional[dict] = None, **kwargs) -> List[UserTrade]:
if self.is_hosted:
resolved_address = resolve_wallet_address(self, None)
response = self._hosted_request(
"fetch_my_trades",
path_params={"address": resolved_address},
)
return self._hosted_collection(response, "trades", user_trade_from_v0)
try:
args = []
if kwargs:
Expand All @@ -1652,12 +1621,6 @@ def fetch_my_trades(self, params: Optional[dict] = None, **kwargs) -> List[UserT
raise self._parse_api_exception(e) from None

def fetch_closed_orders(self, params: Optional[dict] = None, **kwargs) -> List[Order]:
if self.is_hosted:
from pmxt.errors import NotSupported
raise NotSupported(
"fetch_closed_orders is not supported in hosted mode; "
"use fetch_my_trades to see executed fills instead.",
)
try:
args = []
if kwargs:
Expand All @@ -1681,12 +1644,6 @@ def fetch_closed_orders(self, params: Optional[dict] = None, **kwargs) -> List[O
raise self._parse_api_exception(e) from None

def fetch_all_orders(self, params: Optional[dict] = None, **kwargs) -> List[Order]:
if self.is_hosted:
from pmxt.errors import NotSupported
raise NotSupported(
"fetch_all_orders is not supported in hosted mode; "
"use fetch_open_orders + fetch_my_trades to reconstruct order history.",
)
try:
args = []
if kwargs:
Expand All @@ -1710,13 +1667,6 @@ def fetch_all_orders(self, params: Optional[dict] = None, **kwargs) -> List[Orde
raise self._parse_api_exception(e) from None

def fetch_positions(self, address: Optional[str] = None) -> List[Position]:
if self.is_hosted:
resolved_address = resolve_wallet_address(self, address)
response = self._hosted_request(
"fetch_positions",
path_params={"address": resolved_address},
)
return self._hosted_collection(response, "positions", position_from_v0)
try:
args = []
if address is not None:
Expand All @@ -1738,13 +1688,6 @@ def fetch_positions(self, address: Optional[str] = None) -> List[Position]:
raise self._parse_api_exception(e) from None

def fetch_balance(self, address: Optional[str] = None) -> List[Balance]:
if self.is_hosted:
resolved_address = resolve_wallet_address(self, address)
response = self._hosted_request(
"fetch_balance",
path_params={"address": resolved_address},
)
return self._hosted_collection(response, "balances", balance_from_v0)
try:
args = []
if address is not None:
Expand All @@ -1767,8 +1710,10 @@ def fetch_balance(self, address: Optional[str] = None) -> List[Balance]:

def unwatch_order_book(self, outcome_id: Union[str, "MarketOutcome"] = _UNSET, **_compat_kwargs) -> None:
try:
args = []
outcome_id = _compat_id(outcome_id, _compat_kwargs)
body: dict = {"args": [_resolve_outcome_id(outcome_id)]}
args.append(_resolve_outcome_id(outcome_id))
body: dict = {"args": args}
creds = self._get_credentials_dict()
if creds:
body["credentials"] = creds
Expand Down Expand Up @@ -2296,7 +2241,7 @@ def fetch_ohlcv(
params_dict[key] = value

args = [outcome_id, params_dict]
query = {"outcomeId": outcome_id, **params_dict}
query = {"id": outcome_id, **params_dict}
data = self._handle_response(
self._sidecar_read_request("fetchOHLCV", query, args)
)
Expand Down Expand Up @@ -2356,7 +2301,7 @@ def fetch_trades(
params_dict[key] = value

args = [outcome_id, params_dict]
query = {"outcomeId": outcome_id, **params_dict}
query = {"id": outcome_id, **params_dict}
data = self._handle_response(
self._sidecar_read_request("fetchTrades", query, args)
)
Expand Down Expand Up @@ -2905,45 +2850,6 @@ def watch_user_transactions(self, callback: Optional[Callable[[Dict[str, Any]],
except ApiException as e:
raise self._parse_api_exception(e) from None

def pre_warm_market(self, outcome_id: str) -> None:
"""
Pre-warm the SDK's internal caches for a market outcome.

Args:
outcome_id: The CLOB Token ID for the outcome

Returns:
None
"""
self._call_method("preWarmMarket", outcome_id)
return None

def get_event_by_id(self, id: str) -> Optional[UnifiedEvent]:
"""
Fetch a single Probable event by its numeric ID.

Args:
id: The numeric event ID

Returns:
The event, or None if not found
"""
data = self._call_method("getEventById", id)
return _convert_event(data) if data is not None else None

def get_event_by_slug(self, slug: str) -> Optional[UnifiedEvent]:
"""
Fetch a single Probable event by its URL slug.

Args:
slug: The event slug

Returns:
The event, or None if not found
"""
data = self._call_method("getEventBySlug", slug)
return _convert_event(data) if data is not None else None

# Trading Methods (require authentication)

def _discover_hosted_account(self) -> dict:
Expand Down Expand Up @@ -3426,31 +3332,38 @@ def get_execution_price_detailed(
Returns:
Detailed execution result
"""
if amount <= 0:
raise ValueError("Amount must be greater than 0")
try:
# Convert order_book to dict for API call
bids = [{"price": b.price, "size": b.size} for b in order_book.bids]
asks = [{"price": a.price, "size": a.size} for a in order_book.asks]
ob_dict = {"bids": bids, "asks": asks, "timestamp": order_book.timestamp}

levels = [level for level in (order_book.asks if side == "buy" else order_book.bids) if level.size > 0]
levels.sort(key=lambda level: level.price, reverse=(side == "sell"))
body = {
"args": [ob_dict, side, amount]
}

if not levels:
return ExecutionPriceResult(price=0, filled_amount=0, fully_filled=False)
creds = self._get_credentials_dict()
if creds:
body["credentials"] = creds

remaining_amount = amount
total_cost = 0.0
filled_amount = 0.0
epsilon = 0.00000001
url = f"{self._resolve_sidecar_host()}/api/{self.exchange_name}/getExecutionPriceDetailed"

for level in levels:
if remaining_amount <= epsilon:
break
headers = {"Content-Type": "application/json", "Accept": "application/json"}
headers.update(self._get_auth_headers())

response = self._fetch_with_retry(
lambda: self._api_client.call_api(
method="POST",
url=url,
body=body,
header_params=headers
)
)

fill_size = min(remaining_amount, level.size)
total_cost += fill_size * level.price
filled_amount += fill_size
remaining_amount -= fill_size
response.read()
data_json = json.loads(response.data)

return ExecutionPriceResult(
price=total_cost / filled_amount if filled_amount > epsilon else 0,
filled_amount=filled_amount,
fully_filled=remaining_amount <= epsilon,
)
data = self._handle_response(data_json)
return _convert_execution_result(data)
except Exception as e:
raise self._parse_api_exception(e) from None
2 changes: 1 addition & 1 deletion sdks/typescript/pmxt/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1747,7 +1747,7 @@ export abstract class Exchange {
}
}

async fetchMatchedMarkets(params?: FetchMatchedMarketClustersParams): Promise<any[]> {
async fetchMatchedMarkets(params?: any): Promise<any[]> {
await this.initPromise;
try {
const args: any[] = [];
Expand Down
Loading