Skip to content

Commit ee3cdb8

Browse files
committed
release: 2.50.6 — delete /sql page + contradiction sweep (HIGH-severity SDK/docs mismatches)
1 parent 1d7c759 commit ee3cdb8

10 files changed

Lines changed: 56 additions & 238 deletions

changelog.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,26 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [2.50.6] - 2026-06-18
6+
7+
### Docs
8+
9+
- **Deleted `docs/sql.mdx`.** Removed from Get Started in `docs/docs.json` and from the API Reference Enterprise group. The `POST /v0/sql` endpoint reference page stays. One inbound link in `docs/concepts/catalog-uuid-vs-venue-id.mdx:56` retargeted from `[SQL endpoint](/sql)` to a plain `POST /v0/sql` reference.
10+
- **Contradiction sweep — round 1.** Three audit agents (SDK-truth-vs-docs, inter-page contradictions, stale-feature-status) found 60+ candidate findings; fixed every HIGH-severity item that didn't require a product call. Skipped items flagged separately at the end of this note.
11+
- **`docs/introduction.mdx`**: "11 venue integrations" → "15+ venue integrations" — `core/src/server/exchange-factory.ts` registers 16 (excluding test/demo/mock the customer count is ~14, "15+" is the honest marketing number).
12+
- **`docs/concepts/prediction-markets-101.mdx`**: USDC entry was misleading — said "Polymarket-native USDC". Actual settlement asset is **USDC.e** (bridged) at `0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174`, which is what Polymarket's CTF exchange uses. The migrate-to-hosted-trading guide already had this right; the 101 was contradicting it. Same edit confirms native Polygon USDC and bridged USDC on other chains are not interchangeable with USDC.e.
13+
- **`docs/concepts/hosted-trading.mdx`**: `client.escrow.deposit()` / `.withdraw()` — neither method exists. The Escrow class exposes `approve_tx` / `deposit_tx` / `withdraw_tx` / `withdrawals` (`sdks/python/pmxt/escrow.py:114-184`). Replaced with the actual call shape including the `withdraw_tx("request" | "claim" | "cancel", ...)` argument signature.
14+
- **`docs/guides/escrow-lifecycle.mdx`**: `fetch_balance` returns `List[Balance]`, not a single `Balance` (`sdks/python/pmxt/client.py:1643`). The "Confirm the deposit" example unpacked `balance.free / .used / .total` directly, which would `AttributeError` on a list. Fixed to `balances = client.fetch_balance(); usdc = balances[0]; ...`. The `trading-quickstart` already used the list form correctly; this brought escrow-lifecycle in line.
15+
- **`docs/guides/signing.mdx`**: The "Advanced: bring your own signer" example used three attributes that don't exist on the SDK's `BuiltOrder` dataclass — `built.typed_data`, `built.built_order_id`, and a kwargs-style `submit_order(built_order_id=, signature=)`. The actual Python signature is `submit_order(built: BuiltOrder)` (`sdks/python/pmxt/client.py:3183`); typed-data lives at `built.raw["typed_data"]`; the signature attaches as `built.signed_order` before submit. Rewrote both Python and TypeScript examples to match. The TS `submitOrder({ builtOrderId, signature })` shape was also wrong — TS `submitOrder` accepts the `BuiltOrder` object too.
16+
- **`docs/guides/hosted-errors.mdx`** (two fixes in one page):
17+
- The "BuiltOrderExpired retry" example had the same wrong `built.typed_data` / `built.built_order_id` / kwargs `submit_order` shape as the signing guide. Rewrote both Python and TS to use the real attribute paths and the object-shape `submit_order(built)` / `submitOrder(built)` call.
18+
- The stale "`fetch_markets` returns venue-native IDs, but `create_order` needs catalog UUIDs" warning was the same lie that 2.50.3 and 2.50.5 fixed in `hosted-trading.mdx` and `prediction-markets-101.mdx`. Hosted-errors.mdx was the third place it lived. Rewrote the `OutcomeNotFound` Quick check to describe the real failure modes — outcome resolved against a different `exchange_name`, or removed from the catalog — and dropped the venue-native-ID accusation entirely.
19+
- The `NoLiquidity` recovery example told callers to fall back to a hosted limit order. Hosted limit orders return 501 (`docs/trading-quickstart.mdx:165`) — the advice was internally inconsistent and would crash any caller who followed it. Rewrote the recovery to "wait, switch outcome, or run self-hosted for resting limits."
20+
- **Skipped — needs your call before I touch them:**
21+
- **Limitless hosted writes.** The SDK's hosted routing tables (`sdks/typescript/pmxt/hosted-routing.ts:24-28`, `sdks/python/pmxt/_hosted_routing.py:19`) include `limitless` in `HOSTED_TRADING_VENUES`, and `client.py:829-838` routes the schemas. But the SDK's own `NotSupported` error string at `hosted-routing.ts:75` still says "only supported for Polymarket and Opinion" — and every doc page asserts the same. Either Limitless hosted writes are prod-ready (six doc pages need updating and the error string is wrong) or they're partially wired (no doc change, error string is right). I don't have enough signal to decide.
22+
- **Operator multisig.** `docs/concepts/hosted-trading.mdx:89` says "A multisig replacement is planned but not yet deployed" while line 93 says the operator address is `immutable`. Both can be true (replacement = new contract deployment + migration), but the wording reads like an in-place rotation. Wanted your call on the phrasing.
23+
- **`trade.pmxt.dev` vs `api.pmxt.dev` terminology drift.** Introduction splits hosted into two hostnames (reads on `api.pmxt.dev`, writes on `trade.pmxt.dev`); `authentication.mdx` and `rate-limits.mdx` only mention `api.pmxt.dev`. A builder reading auth in isolation won't know `trade.pmxt.dev` is a thing. Not a wrong claim, just incomplete coverage on auth/rate-limits.
24+
525
## [2.50.5] - 2026-06-18
626

727
### Docs

docs/concepts/catalog-uuid-vs-venue-id.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ clusters = router.fetch_matched_market_clusters(
5353
catalog_uuid = clusters[0].market_id
5454
```
5555

56-
For batch workflows, the [SQL endpoint](/sql) gives you direct access to `prediction_markets.markets` and `prediction_markets.outcomes` with the canonical UUID alongside the venue-native fields (`venue_market_id`, `venue_outcome_id` / `token_id`).
56+
For batch workflows, `POST /v0/sql` gives you direct access to `prediction_markets.markets` and `prediction_markets.outcomes` with the canonical UUID alongside the venue-native fields (`venue_market_id`, `venue_outcome_id` / `token_id`).
5757

5858
## Examples (the two ids for one market)
5959

docs/concepts/hosted-trading.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ The SDK accepts either form. Outcomes returned by `pmxt.Polymarket(...).fetch_ma
6969
- **Polymarket** is on Polygon. Escrow-held USDC is spent directly via Polymarket's CTF exchange — same-chain settlement.
7070
- **Opinion** is on BSC (chainId 56). Escrow-held USDC funds a cross-chain settlement leg into a BSC-side `VenueEscrow` that holds Opinion [outcome](/concepts/prediction-markets-101#event-market-outcome) tokens. The user never deposits to or signs on BSC — PMXT operates the cross-chain hop, still gated by the user's signature on the Polygon side.
7171

72-
All EIP-712 order signatures use the Polygon `PreFundedEscrow` domain regardless of venue. The user's wallet retains beneficial ownership at all times. Funds enter via `client.escrow.deposit()`, exit via `client.escrow.withdraw()`. Both are unsigned-tx builders — your wallet signs and submits them. See [Escrow Lifecycle](/guides/escrow-lifecycle).
72+
All EIP-712 order signatures use the Polygon `PreFundedEscrow` domain regardless of venue. The user's wallet retains beneficial ownership at all times. Funds enter via `client.escrow.deposit_tx(amount)`, exit via `client.escrow.withdraw_tx("request" | "claim" | "cancel", ...)`. Both build unsigned txs — your wallet signs and submits them. See [Escrow Lifecycle](/guides/escrow-lifecycle).
7373

7474
### Deployed contracts
7575

docs/concepts/prediction-markets-101.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ A specific EVM-compatible chain (chainId 137). PMXT's `PreFundedEscrow` contract
3939

4040
### USDC
4141

42-
A US-dollar-pegged stablecoin (1 USDC ≈ $1) issued on many chains. PMXT uses the **Polygon-native** USDC for hosted trading. Bridged versions on other chains are not interchangeable.
42+
A US-dollar-pegged stablecoin (1 USDC ≈ $1) issued on many chains. PMXT hosted trading settles in **USDC.e on Polygon** (`0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174`) — the bridged token Polymarket's CTF exchange uses. Native Polygon USDC and bridged USDC on other chains are not interchangeable.
4343

4444
### EIP-712
4545

docs/docs.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,7 @@
6060
"authentication",
6161
"mcp",
6262
"security",
63-
"rate-limits",
64-
"sql"
63+
"rate-limits"
6564
]
6665
},
6766
{
@@ -225,7 +224,6 @@
225224
"group": "Enterprise",
226225
"openapi": "api-reference/openapi-hosted.json",
227226
"pages": [
228-
"sql",
229227
"POST /v0/sql"
230228
]
231229
}

docs/guides/escrow-lifecycle.mdx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,15 @@ After the deposit transaction confirms on-chain, the balance shows up in escrow.
113113

114114
<CodeGroup>
115115
```python Python
116-
balance = client.fetch_balance()
117-
print(f"Free: {balance.free}, Used: {balance.used}, Total: {balance.total}")
116+
balances = client.fetch_balance()
117+
usdc = balances[0]
118+
print(f"Free: {usdc.free}, Used: {usdc.used}, Total: {usdc.total}")
118119
```
119120

120121
```typescript TypeScript
121-
const balance = await client.fetchBalance();
122-
console.log(`Free: ${balance.free}, Used: ${balance.used}, Total: ${balance.total}`);
122+
const balances = await client.fetchBalance();
123+
const usdc = balances[0];
124+
console.log(`Free: ${usdc.free}, Used: ${usdc.used}, Total: ${usdc.total}`);
123125
```
124126
</CodeGroup>
125127

docs/guides/hosted-errors.mdx

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,9 @@ from pmxt._hosted_errors import BuiltOrderExpired
154154
def submit_with_retry(client, *, market_id, outcome_id, **kwargs):
155155
for attempt in range(2):
156156
built = client.build_order(market_id=market_id, outcome_id=outcome_id, **kwargs)
157-
sig = signer.sign_typed_data(built.typed_data)
157+
built.signed_order = signer.sign_typed_data(built.raw["typed_data"])
158158
try:
159-
return client.submit_order(
160-
built_order_id=built.built_order_id,
161-
signature=sig,
162-
)
159+
return client.submit_order(built)
163160
except BuiltOrderExpired:
164161
if attempt == 1:
165162
raise
@@ -172,16 +169,14 @@ import { BuiltOrderExpired } from "pmxtjs";
172169
async function submitWithRetry(client, params) {
173170
for (let attempt = 0; attempt < 2; attempt++) {
174171
const built = await client.buildOrder(params);
175-
const sig = await signer.signTypedData(
176-
built.typedData.domain,
177-
built.typedData.types,
178-
built.typedData.message,
172+
const typedData = built.raw.typed_data;
173+
built.signedOrder = await signer.signTypedData(
174+
typedData.domain,
175+
typedData.types,
176+
typedData.message,
179177
);
180178
try {
181-
return await client.submitOrder({
182-
builtOrderId: built.builtOrderId,
183-
signature: sig,
184-
});
179+
return await client.submitOrder(built);
185180
} catch (e) {
186181
if (e instanceof BuiltOrderExpired && attempt === 0) continue;
187182
throw e;
@@ -199,7 +194,7 @@ async function submitWithRetry(client, params) {
199194

200195
**Parent classes:** `InvalidOrder`, `HostedTradingError`.
201196

202-
**Recovery:** wait for liquidity, post a limit order instead of a market order, or pick a different outcome.
197+
**Recovery:** wait for liquidity, pick a different outcome, or run [self-hosted](/guides/self-hosted) for resting limit orders (hosted limit orders are not yet available).
203198

204199
<CodeGroup>
205200
```python Python
@@ -208,8 +203,8 @@ from pmxt._hosted_errors import NoLiquidity
208203
try:
209204
client.create_order(order_type="market", ...)
210205
except NoLiquidity:
211-
# Fall back to a limit order at a price you'd accept
212-
client.create_order(order_type="limit", price=0.50, ...)
206+
# Wait, retry against a different outcome, or post limits via self-hosted.
207+
pass
213208
```
214209

215210
```typescript TypeScript
@@ -219,7 +214,7 @@ try {
219214
await client.createOrder({ orderType: "market", ... });
220215
} catch (e) {
221216
if (e instanceof NoLiquidity) {
222-
await client.createOrder({ orderType: "limit", price: 0.5, ... });
217+
// Wait, retry against a different outcome, or post limits via self-hosted.
223218
} else {
224219
throw e;
225220
}
@@ -234,7 +229,7 @@ try {
234229
</Warning>
235230

236231
<Warning>
237-
**`fetch_markets` returns venue-native IDs**, but `create_order` needs catalog UUIDs. If you see `OutcomeNotFound` despite having a valid-looking ID, you are almost certainly passing a venue-native ID to a hosted endpoint. See [Catalog UUID vs venue ID](/concepts/catalog-uuid-vs-venue-id).
232+
If you see `OutcomeNotFound` despite having a valid-looking ID, the SDK could not resolve it on either the catalog UUID or `(venue, venue_outcome_id)` path. Most commonly: the outcome was resolved against a different venue than the client's `exchange_name`, or the outcome has since been removed from the catalog. See [Catalog UUID vs venue ID](/concepts/catalog-uuid-vs-venue-id).
238233
</Warning>
239234

240235
## Catching everything hosted

docs/guides/signing.mdx

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -92,16 +92,14 @@ built = client.build_order(
9292
slippage_pct=30.0,
9393
)
9494

95+
typed_data = built.raw["typed_data"]
9596
signature = my_custom_signer.sign_typed_data(
96-
domain=built.typed_data["domain"],
97-
types=built.typed_data["types"],
98-
message=built.typed_data["message"],
99-
)
100-
101-
order = client.submit_order(
102-
built_order_id=built.built_order_id,
103-
signature=signature,
97+
domain=typed_data["domain"],
98+
types=typed_data["types"],
99+
message=typed_data["message"],
104100
)
101+
built.signed_order = signature # attach signature for submit
102+
order = client.submit_order(built)
105103
```
106104

107105
```typescript TypeScript
@@ -121,16 +119,14 @@ const built = await client.buildOrder({
121119
slippagePct: 30,
122120
});
123121

122+
const typedData = built.raw.typed_data;
124123
const signature = await myCustomSigner.signTypedData(
125-
built.typedData.domain,
126-
built.typedData.types,
127-
built.typedData.message,
124+
typedData.domain,
125+
typedData.types,
126+
typedData.message,
128127
);
129-
130-
const order = await client.submitOrder({
131-
builtOrderId: built.builtOrderId,
132-
signature,
133-
});
128+
built.signedOrder = signature;
129+
const order = await client.submitOrder(built);
134130
```
135131
</CodeGroup>
136132

docs/introduction.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ Polymarket or Kalshi.
111111

112112
Without PMXT, getting cross-venue prediction market data means:
113113

114-
- **11 venue integrations** — each with its own auth, pagination, field
114+
- **15+ venue integrations** — each with its own auth, pagination, field
115115
names, and rate limits. Polymarket uses CLOB token IDs. Kalshi uses
116116
tickers. Smarkets uses contract IDs. You normalize all of it.
117117
- **A data pipeline** — to ingest, deduplicate, and keep fresh as markets

0 commit comments

Comments
 (0)