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
6 changes: 6 additions & 0 deletions sdks/python/pmxt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@
PaginatedEventsResult,
Order,
BuiltOrder,
CreateOrderParams,
TxPayload,
Position,
Balance,
MarketFilterCriteria,
Expand All @@ -78,6 +80,7 @@
PriceComparison,
ArbitrageOpportunity,
SubscribedAddressSnapshot,
SubscriptionOption,
ExecutionPriceResult,
MatchRelation,
ClusterSortOption,
Expand Down Expand Up @@ -225,6 +228,8 @@ def restart_server() -> None:
"PaginatedEventsResult",
"Order",
"BuiltOrder",
"CreateOrderParams",
"TxPayload",
"ExecutionPriceResult",
"Position",
"Balance",
Expand All @@ -237,6 +242,7 @@ def restart_server() -> None:
"PriceComparison",
"ArbitrageOpportunity",
"SubscribedAddressSnapshot",
"SubscriptionOption",
"MatchRelation",
"ClusterSortOption",
"MatchedClusterSort",
Expand Down
7 changes: 6 additions & 1 deletion sdks/python/pmxt/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
TradesParams,
FetchOrderBookParams,
SubscribedAddressSnapshot,
SubscriptionOption,
FirehoseEvent,
MatchResult,
EventMatchResult,
Expand Down Expand Up @@ -1683,6 +1684,7 @@ def fetch_trades(
since: Optional[int] = None,
start: Optional[Union[str, int]] = None,
end: Optional[Union[str, int]] = None,
resolution: Optional[str] = None,
**kwargs
) -> List[Trade]:
"""
Expand All @@ -1696,6 +1698,7 @@ def fetch_trades(
since: Return trades since this timestamp (Unix milliseconds)
start: Start of time range (ISO 8601 string or epoch seconds/ms)
end: End of time range (ISO 8601 string or epoch seconds/ms)
resolution: Optional trade resolution/status filter forwarded to the venue
**kwargs: Additional parameters

Returns:
Expand All @@ -1717,6 +1720,8 @@ def fetch_trades(
params_dict["start"] = start
if end is not None:
params_dict["end"] = end
if resolution is not None:
params_dict["resolution"] = resolution

# Add any extra keyword arguments
for key, value in kwargs.items():
Expand Down Expand Up @@ -2078,7 +2083,7 @@ def watch_trades(
def watch_address(
self,
address: str,
types: Optional[List[str]] = None,
types: Optional[List[SubscriptionOption]] = None,
) -> SubscribedAddressSnapshot:
"""
Watch real-time updates of a public wallet via WebSocket.
Expand Down
6 changes: 4 additions & 2 deletions sdks/python/pmxt/feed_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
from dataclasses import dataclass, field
from typing import List, Optional, Dict, Any, Tuple

from .errors import PmxtError


@dataclass(frozen=True)
class Ticker:
Expand Down Expand Up @@ -190,10 +192,10 @@ def _request(self, url: str, params: Optional[Dict[str, Any]] = None) -> Any:
except urllib.error.HTTPError as e:
body = json.loads(e.read()) if e.fp else {}
msg = body.get("error", e.reason)
raise RuntimeError(f"Feed API error ({e.code}): {msg}") from e
raise PmxtError(f"Feed API error ({e.code}): {msg}") from e

if not body.get("success"):
raise RuntimeError(f"Feed API error: {body.get('error', 'unknown')}")
raise PmxtError(f"Feed API error: {body.get('error', 'unknown')}")
return body["data"]

@staticmethod
Expand Down
36 changes: 28 additions & 8 deletions sdks/python/pmxt/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
OrderSide = Literal["buy", "sell"]
OrderType = Literal["market", "limit"]
OutcomeType = Literal["yes", "no", "up", "down"]
SubscriptionOption = Literal["trades", "positions", "balances"]


@dataclass
Expand Down Expand Up @@ -471,7 +472,7 @@ class BuiltOrder:
exchange: str
"""The exchange name this order was built for."""

params: Dict[str, Any]
params: "CreateOrderParams"
"""The original params used to build this order."""

raw: Any
Expand All @@ -480,10 +481,28 @@ class BuiltOrder:
signed_order: Optional[Dict[str, Any]] = None
"""For CLOB exchanges (Polymarket): the EIP-712 signed order."""

tx: Optional[Dict[str, Any]] = None
tx: Optional["TxPayload"] = None
"""For on-chain AMM exchanges: the EVM transaction payload."""


class CreateOrderParams(TypedDict, total=False):
"""Parameters used to build or create an order."""
market_id: str
outcome_id: str
side: OrderSide
type: OrderType
amount: float
price: float
fee: int


class TxPayload(TypedDict):
"""EVM transaction payload returned for on-chain AMM orders."""
to: str
data: str
value: str
chainId: int

@dataclass
class Position:
"""A current position in a market."""
Expand Down Expand Up @@ -701,6 +720,7 @@ class TradesParams(TypedDict, total=False):
until: int
limit: int
cursor: str
resolution: str


class FetchOrderBookParams(TypedDict, total=False):
Expand Down Expand Up @@ -833,12 +853,12 @@ class MatchedMarketCluster:
confidence: float
"""Cluster confidence score."""

volume_24h: float
"""Total 24-hour volume across markets in the cluster."""

category: Optional[str] = None
"""Canonical category selected by the hosted API."""

volume_24h: Optional[float] = None
"""Total 24-hour volume across markets in the cluster."""

raw_matches: Optional[List[Dict[str, Any]]] = None
"""Pairwise match edges used to build the cluster when requested."""

Expand All @@ -862,12 +882,12 @@ class MatchedEventCluster:
confidence: float
"""Cluster confidence score."""

volume_24h: float
"""Total 24-hour volume across events in the cluster."""

category: Optional[str] = None
"""Canonical category selected by the hosted API."""

volume_24h: Optional[float] = None
"""Total 24-hour volume across events in the cluster."""

raw_matches: Optional[List[Dict[str, Any]]] = None
"""Pairwise match edges used to build the cluster when requested."""

Expand Down
3 changes: 3 additions & 0 deletions sdks/typescript/pmxt/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,9 @@ export abstract class Exchange {

async submitOrder(built: BuiltOrder): Promise<Order> {
await this.initPromise;
if (this.isHosted) {
throw new PmxtError("submitOrder is not available in hosted mode. Use createOrder instead.");
}
try {
const args: any[] = [];
args.push(built);
Expand Down
16 changes: 16 additions & 0 deletions sdks/typescript/pmxt/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,8 @@ export class Router extends Exchange {
marketId?: string;
slug?: string;
url?: string;
query?: string;
category?: string;
relation?: MatchRelation;
minConfidence?: number;
limit?: number;
Expand All @@ -234,6 +236,8 @@ export class Router extends Exchange {
marketId?: string;
slug?: string;
url?: string;
query?: string;
category?: string;
relation?: MatchRelation;
minConfidence?: number;
limit?: number;
Expand All @@ -246,6 +250,8 @@ export class Router extends Exchange {
if (marketId) query.marketId = marketId;
if (params.slug ?? params.market?.slug) query.slug = params.slug ?? params.market?.slug;
if (params.url) query.url = params.url;
if (params.query) query.query = params.query;
if (params.category) query.category = params.category;
if (params.relation) query.relation = params.relation;
if (params.minConfidence !== undefined) query.minConfidence = params.minConfidence;
if (params.limit !== undefined) query.limit = params.limit;
Expand Down Expand Up @@ -274,6 +280,8 @@ export class Router extends Exchange {
marketId?: string;
slug?: string;
url?: string;
query?: string;
category?: string;
relation?: MatchRelation;
minConfidence?: number;
limit?: number;
Expand All @@ -284,6 +292,8 @@ export class Router extends Exchange {
marketId?: string;
slug?: string;
url?: string;
query?: string;
category?: string;
relation?: MatchRelation;
minConfidence?: number;
limit?: number;
Expand All @@ -303,6 +313,8 @@ export class Router extends Exchange {
event?: UnifiedEvent;
eventId?: string;
slug?: string;
query?: string;
category?: string;
relation?: MatchRelation;
minConfidence?: number;
limit?: number;
Expand All @@ -312,6 +324,8 @@ export class Router extends Exchange {
event?: UnifiedEvent;
eventId?: string;
slug?: string;
query?: string;
category?: string;
relation?: MatchRelation;
minConfidence?: number;
limit?: number;
Expand All @@ -323,6 +337,8 @@ export class Router extends Exchange {
const eventId = params.eventId ?? (!params.event?.slug ? params.event?.id : undefined);
if (eventId) query.eventId = eventId;
if (params.slug ?? params.event?.slug) query.slug = params.slug ?? params.event?.slug;
if (params.query) query.query = params.query;
if (params.category) query.category = params.category;
if (params.relation) query.relation = params.relation;
if (params.minConfidence !== undefined) query.minConfidence = params.minConfidence;
if (params.limit !== undefined) query.limit = params.limit;
Expand Down
8 changes: 8 additions & 0 deletions sdks/typescript/scripts/generate-client-methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -424,10 +424,18 @@ function generateMethod(name, params, config, sf) {
const argsCode = buildArgsLines(params, sf);
const returnCode = buildReturnLines(config);
const { returnTs } = config;
const localOnlyGuard = name === 'submitOrder'
? [
` if (this.isHosted) {`,
` throw new PmxtError("submitOrder is not available in hosted mode. Use createOrder instead.");`,
` }`,
]
: [];

return [
` async ${name}(${sig}): Promise<${returnTs}> {`,
` await this.initPromise;`,
...localOnlyGuard,
` try {`,
` ${argsCode}`,
` const response = await this.fetchWithRetry(\`\${this.resolveBaseUrl()}/api/\${this.exchangeName}/${name}\`, {`,
Expand Down
Loading