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
26 changes: 21 additions & 5 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,29 @@

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

## [2.49.2] - 2026-06-09

Terminology cleanup. Per the 2026-05-27 ADR "Avoid Sidecar Terminology" in the company brain, user-facing references to the local PMXT runtime should not use the word "sidecar" — preferred phrasing is **"local PMXT service"** (or **"local service"** when context is unambiguous). Recent docs/READMEs/changelog entries shipped in 2.49.0 / 2.49.1 used "sidecar" reflexively; this patch rewrites every user-facing occurrence to the canonical terms. Historical changelog entries from earlier releases are intentionally left as-is — they describe what shipped at the time. Internal implementation identifiers (`_resolve_sidecar_host`, `ServerManager`, etc.) are also untouched per the ADR's scope.

### Changed

- **READMEs (`readme.md`, `sdks/python/README.md`, `sdks/typescript/README.md`)**: Every user-visible "sidecar" reference replaced with "local PMXT service" or "local service" depending on context. The Quick Start, "How it works (self-hosted)", and "Self-hosted trading (advanced)" sections now use the canonical terms.
- **Docs (`docs/concepts/hosted-vs-self-hosted.mdx`)**: "...or run a sidecar" → "...or run a local PMXT service" in the "When hosted is the right choice" list.
- **Changelog 2.49.0 / 2.49.1 entries**: prose rewritten to use the canonical terms ("local PMXT service", "local-service path", etc.) where they previously used "sidecar".

### Not changed (deliberate)

- **Internal implementation identifiers** (`_resolve_sidecar_host`, `_kill_orphan_sidecars`, `sidecarReadRequest`, `pmxt-ensure-server`, etc.) — per the ADR's scope ("Existing internal implementation identifiers may remain unchanged unless they are user-visible in generated outputs").
- **Historical changelog entries** for 2.48.x and earlier — they accurately describe what shipped at the time using the terms in use then.
- **Auto-generated files** (`docs/api-reference/openapi.json`, `docs/llms-full.txt`, `docs/llms.txt`) — these are emitted by the generator pipeline. The terminology fix flows through the next regeneration via the source files; not hand-editing the artifacts here.

## [2.49.1] - 2026-06-08

Positioning-shift patch on top of 2.49.0 — the hosted trading mode shipped in 2.49.0 but the docs, READMEs, and OpenAPI schemas still defaulted to the self-hosted sidecar path. This release flips the default everywhere the SDK + docs surface a customer hits: hosted PMXT is the primary experience; self-hosting becomes the advanced escape hatch. No SDK runtime behavior changes — pure documentation, schema, and copy work. Marketing-site changes ship separately in a sibling pmxt-website PR.
Positioning-shift patch on top of 2.49.0 — the hosted trading mode shipped in 2.49.0 but the docs, READMEs, and OpenAPI schemas still defaulted to the self-hosted local-service path. This release flips the default everywhere the SDK + docs surface a customer hits: hosted PMXT is the primary experience; self-hosting becomes the advanced escape hatch. No SDK runtime behavior changes — pure documentation, schema, and copy work. Marketing-site changes ship separately in a sibling pmxt-website PR.

### Added

- **Docs**: 11 new MDX pages on the Mintlify site covering the hosted trading mode end-to-end — `trading-quickstart` (60-second walkthrough), `concepts/hosted-trading` (feature landing), `concepts/hosted-vs-self-hosted` (one-pager comparison), `concepts/catalog-uuid-vs-venue-id` (the UUID/venue-id gotcha), `guides/escrow-lifecycle` (PreFundedEscrow walkthrough), `guides/signing` (EthAccountSigner / EthersSigner + EIP-712), `guides/hosted-errors` (the 5 most-common subclasses with `try/except` cookbook), `guides/migrate-to-hosted-trading` (ported `MIGRATION.md` content with language tabs), `guides/self-hosted` (consolidated local-sidecar story), `api-reference/errors` (full `HostedTradingError` tree with dual-parent semantic-map), `api-reference/configuration` (`ExchangeOptions` + env vars + base-URL resolution).
- **Docs**: 11 new MDX pages on the Mintlify site covering the hosted trading mode end-to-end — `trading-quickstart` (60-second walkthrough), `concepts/hosted-trading` (feature landing), `concepts/hosted-vs-self-hosted` (one-pager comparison), `concepts/catalog-uuid-vs-venue-id` (the UUID/venue-id gotcha), `guides/escrow-lifecycle` (PreFundedEscrow walkthrough), `guides/signing` (EthAccountSigner / EthersSigner + EIP-712), `guides/hosted-errors` (the 5 most-common subclasses with `try/except` cookbook), `guides/migrate-to-hosted-trading` (ported `MIGRATION.md` content with language tabs), `guides/self-hosted` (consolidated local-service story), `api-reference/errors` (full `HostedTradingError` tree with dual-parent semantic-map), `api-reference/configuration` (`ExchangeOptions` + env vars + base-URL resolution).
- **Docs**: New "Hosted Trading" and "Self-host" sidebar groups in `docs.json`, plus a "Reference" group at the top of the API Reference tab. `sdk/server` moved out of the previous "SDK" group into "Self-host" (without slug rename — link-stability preserved for this release).
- **Core**: New `ExchangeOptions` component schema in `core/src/server/openapi.yaml` documenting constructor-level options (`pmxtApiKey`, `walletAddress`, `signer`, `privateKey`, `baseUrl`, etc.) — previously only `ExchangeCredentials` (per-request body credentials) existed at the schema level.
- **Core**: `BuiltOrder.expiry` field added to the OpenAPI schema (the TTL that triggers `BuiltOrderExpired` at submit time was implicit in the SDK and undocumented at the spec level).
Expand Down Expand Up @@ -38,7 +54,7 @@ Positioning-shift patch on top of 2.49.0 — the hosted trading mode shipped in

### Added

- **SDK (Python + TypeScript)**: Hosted trading mode now works end-to-end against `trade.pmxt.dev`. Constructing the client with a `pmxt_api_key` / `pmxtApiKey` switches every Group A public method — `create_order` / `createOrder`, `build_order` / `buildOrder`, `submit_order` / `submitOrder`, `cancel_order` / `cancelOrder`, `fetch_balance` / `fetchBalance`, `fetch_positions` / `fetchPositions`, `fetch_open_orders` / `fetchOpenOrders`, `fetch_my_trades` / `fetchMyTrades`, `fetch_order` / `fetchOrder` — to dispatch through PMXT's PreFundedEscrow custody on `trade.pmxt.dev/v0/*` instead of the local sidecar. Read methods that require a wallet raise `MissingWalletAddress` locally before any network call when neither an explicit `address` argument nor `wallet_address` on the client is set. `fetch_closed_orders` and `fetch_all_orders` raise `NotSupported` in hosted mode (settled orders are modeled as trades; callers should use `fetch_my_trades`). Both SDKs auto-wrap a raw `private_key` / `privateKey` into the venue signer (`EthAccountSigner` for Python via `eth-account`, `EthersSigner` for TypeScript via the optional `ethers >= 6` peer dep) so the user never has to construct a signer manually.
- **SDK (Python + TypeScript)**: Hosted trading mode now works end-to-end against `trade.pmxt.dev`. Constructing the client with a `pmxt_api_key` / `pmxtApiKey` switches every Group A public method — `create_order` / `createOrder`, `build_order` / `buildOrder`, `submit_order` / `submitOrder`, `cancel_order` / `cancelOrder`, `fetch_balance` / `fetchBalance`, `fetch_positions` / `fetchPositions`, `fetch_open_orders` / `fetchOpenOrders`, `fetch_my_trades` / `fetchMyTrades`, `fetch_order` / `fetchOrder` — to dispatch through PMXT's PreFundedEscrow custody on `trade.pmxt.dev/v0/*` instead of the local PMXT service. Read methods that require a wallet raise `MissingWalletAddress` locally before any network call when neither an explicit `address` argument nor `wallet_address` on the client is set. `fetch_closed_orders` and `fetch_all_orders` raise `NotSupported` in hosted mode (settled orders are modeled as trades; callers should use `fetch_my_trades`). Both SDKs auto-wrap a raw `private_key` / `privateKey` into the venue signer (`EthAccountSigner` for Python via `eth-account`, `EthersSigner` for TypeScript via the optional `ethers >= 6` peer dep) so the user never has to construct a signer manually.
- **SDK (Python + TypeScript)**: New `Escrow` namespace on hosted-mode Polymarket clients (`client.escrow.build_approve_tx(...)`, `build_deposit_tx`, `build_withdraw_tx`, `withdrawals(...)`) for the PreFundedEscrow deposit/withdraw flow. Mirrors the `/v0/escrow/*` surface; only instantiated on hosted-trading-allowlisted venues.
- **SDK (Python + TypeScript)**: New hosted-mode error hierarchy (`HostedTradingError`, `InsufficientEscrowBalance`, `OrderSizeTooSmall`, `InvalidApiKey`, `OutcomeNotFound`, `CatalogUnavailable`, `BuiltOrderExpired`, `InvalidSignature`, `NoLiquidity`, `MissingWalletAddress`). Each hosted error keeps a semantic parent so existing catch-sites still work — e.g. `InsufficientEscrowBalance` extends `InsufficientFunds`, `OutcomeNotFound` extends `NotFoundError`, `CatalogUnavailable` extends `ExchangeNotAvailable`. Python uses true multi-inheritance; TypeScript uses a `static isHostedError = true` flag plus an `isHostedError(e)` helper to compensate for single-inheritance. The mapper (`raise_from_response` / `raiseFromResponse`) translates `trade.pmxt.dev` status codes and detail strings to the right subclass.
- **SDK (Python)**: New `tests/e2e/hosted_driver.py` — runnable live driver that proves URL routing against prod. Hits `trade.pmxt.dev/v0/*` with a deliberately-bogus key so the server returns 401, captures the URL for every public method via an `httpx`-level transport hook, and asserts each URL starts with `https://trade.pmxt.dev/v0/`. Also verifies local-only failure paths (`MissingWalletAddress`, `NotSupported`, `InvalidOrder`, `InvalidSignature`) raise before any network call.
Expand All @@ -48,7 +64,7 @@ Positioning-shift patch on top of 2.49.0 — the hosted trading mode shipped in

### Changed

- **SDK (Python)**: `pmxt` 2.17.1 → 2.18.0. New constructor kwargs `wallet_address: str | None` and `signer: Signer | None` on every Exchange subclass; both are pass-through to the base class. Existing non-hosted (sidecar) callers see no behavior change.
- **SDK (Python)**: `pmxt` 2.17.1 → 2.18.0. New constructor kwargs `wallet_address: str | None` and `signer: Signer | None` on every Exchange subclass; both are pass-through to the base class. Existing non-hosted (local PMXT service) callers see no behavior change.
- **SDK (TypeScript)**: `pmxtjs` 2.17.1 → 2.18.0. New `walletAddress` / `signer` / `privateKey` fields on `ExchangeOptions`. `ethers >= 6.0.0 < 7.0.0` declared as an optional `peerDependency` (only required for hosted writes; hosted reads work without it).
- **SDK (Python + TypeScript)**: `Order`, `UserTrade`, `Position`, and `Balance` now carry optional `tx_hash` / `txHash`, `chain`, and `block_number` / `blockNumber` fields, populated in hosted mode after the trade settles on-chain. Non-hosted callers see `None` / `undefined` for these — unchanged behavior.
- **SDK (Python + TypeScript)**: `Position` mark-to-market fields (`outcome_label`, `entry_price`, `current_price`, `current_value`) are now all `Optional`. Hosted endpoints populate `outcome_label` and `entry_price` from operator-side cost-basis enrichment when available, but downstream consumers must handle the missing case rather than relying on fabricated defaults.
Expand All @@ -68,7 +84,7 @@ Positioning-shift patch on top of 2.49.0 — the hosted trading mode shipped in
- **SDK (TypeScript)**: `_hostedBuildOrderBody` was writing the user's wallet to `body["wallet_address"]`, but `trade.pmxt.dev`'s `BuildOrderV0Req` expects the field as `user_address`. Every `createOrder` / `buildOrder` via the TS SDK previously 422-ed on a "missing user_address" Pydantic validation error before reaching the chain. Python SDK was already correct.
- **SDK (TypeScript)**: Nine `HOSTED_METHOD_ROUTES.get("…")` lookups in `client.ts` used snake_case keys (`"submit_order"`, `"fetch_balance"`, etc.) against a Map whose keys are camelCase (`"submitOrder"`, `"fetchBalance"`, etc.). Every hosted call would have thrown `TypeError: Cannot read properties of undefined (reading 'method')` at runtime. `tsc` and Jest didn't catch this because the existing unit tests stub out the lookup. Fixed by switching all nine sites to the camelCase keys actually defined in the map.
- **SDK (TypeScript)**: Removed the `errors.ts → hosted-errors.ts` re-export block that created a circular import. `tsc` and `ts-jest` tolerated the cycle, but `tsx` / Node CJS crashed at module load with `ReferenceError: Cannot access 'PmxtError' before initialization` because `errors.ts`'s body re-exports from `hosted-errors.ts`, which extends `PmxtError` defined later in the same `errors.ts` body. Hosted error classes are now re-exported once from `index.ts` instead of via `errors.ts`. The public surface is unchanged for consumers importing from `pmxtjs`.
- **Server (Python sidecar)**: Bare and overly-broad `except:` handlers in the sidecar manager tightened to specific exception types, so genuine bugs surface instead of getting swallowed and reported as opaque "server failed to start" errors. Closes #813-#821. (#871)
- **Server (local PMXT service, Python)**: Bare and overly-broad `except:` handlers in the local PMXT service manager tightened to specific exception types, so genuine bugs surface instead of getting swallowed and reported as opaque "server failed to start" errors. Closes #813-#821. (#871)
- **Server**: WebSocket and feed-client hygiene issues surfaced rather than swallowed — disconnects, malformed frames, and feed-side errors now propagate to the caller instead of silently dropping events. (#870)
- **Core**: Exchange normalizers across all venues realigned with current live payload shapes; addresses cumulative drift that had been quietly producing inconsistent unified objects between SDKs and the server. (#873)
- **Kalshi**: Pagination capped to prevent unbounded scrolling on `fetchMarkets` / `fetchEvents`, and `status=all` is now serialized as a single value rather than the array form that some Kalshi endpoints reject. (#874)
Expand Down
2 changes: 1 addition & 1 deletion docs/concepts/hosted-vs-self-hosted.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ PMXT runs two ways. **Hosted** is the default — it's what `pmxt.Polymarket(pmx
- You're building a **web or mobile app** and want to keep `pmxt_api_key` server-side while end users keep their private keys client-side.
- You want **one HTTP surface** across Polymarket and Opinion without learning each venue's order schema.
- You want **PreFundedEscrow custody** instead of managing venue-native accounts.
- You don't want to operate the pmxt-core process, manage upgrades, or run a sidecar.
- You don't want to operate the pmxt-core process, manage upgrades, or run a local PMXT service.

## When self-hosted is the right choice

Expand Down
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ exchange = pmxt.Limitless(

## Self-hosted

To self-host pmxt-core on your own machine: `pip install pmxt-core` (Python) or `npm install pmxt-core` (Node.js), then construct any venue client without `pmxt_api_key`. The SDK spawns a local sidecar process; you supply venue credentials directly. See the [self-hosted guide](https://pmxt.dev/docs/guides/self-hosted) for details.
To self-host pmxt-core on your own machine: `pip install pmxt-core` (Python) or `npm install pmxt-core` (Node.js), then construct any venue client without `pmxt_api_key`. The SDK spawns a local PMXT service; you supply venue credentials directly. See the [self-hosted guide](https://pmxt.dev/docs/guides/self-hosted) for details.

## Documentation

Expand Down
8 changes: 4 additions & 4 deletions sdks/python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

A unified Python interface for prediction market exchanges (Polymarket, Kalshi, Limitless, Opinion, and more).

> **Note**: Use with a PMXT API key (hosted, recommended) or self-host the sidecar locally. Get a key at [pmxt.dev/dashboard](https://pmxt.dev/dashboard).
> **Note**: Use with a PMXT API key (hosted, recommended) or run a local PMXT service. Get a key at [pmxt.dev/dashboard](https://pmxt.dev/dashboard).

## Installation

```bash
pip install pmxt
```

**Requirements**: Python >= 3.8. The sidecar server is bundled automatically via the `pmxt-core` dependency — only needed when self-hosting.
**Requirements**: Python >= 3.8. The local PMXT service is bundled automatically via the `pmxt-core` dependency — only needed when self-hosting.

## Quick Start

Expand Down Expand Up @@ -61,7 +61,7 @@ When you pass `pmxt_api_key`, the SDK talks to the PMXT hosted services:

### How it works (self-hosted)

When you omit `pmxt_api_key`, the Python SDK manages the PMXT sidecar server for you:
When you omit `pmxt_api_key`, the Python SDK manages the local PMXT service for you:

1. **First API call**: Checks if server is running
2. **Auto-start**: Starts server if needed (takes ~1-2 seconds)
Expand Down Expand Up @@ -128,7 +128,7 @@ See the full [hosted trading guide](https://pmxt.dev/docs/concepts/hosted-tradin

### Self-hosted trading (advanced)

When self-hosting, you supply venue credentials directly — no `pmxt_api_key`. The SDK spawns a local sidecar process.
When self-hosting, you supply venue credentials directly — no `pmxt_api_key`. The SDK spawns a local PMXT service.

#### Polymarket

Expand Down
6 changes: 3 additions & 3 deletions sdks/typescript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

A unified TypeScript/Node.js SDK for prediction markets — The ccxt for prediction markets.

> **Note**: Use with a PMXT API key (hosted, recommended) or self-host the sidecar locally. Get a key at [pmxt.dev/dashboard](https://pmxt.dev/dashboard).
> **Note**: Use with a PMXT API key (hosted, recommended) or run a local PMXT service. Get a key at [pmxt.dev/dashboard](https://pmxt.dev/dashboard).

## Installation

Expand Down Expand Up @@ -53,7 +53,7 @@ When you pass `pmxtApiKey`, the SDK talks to PMXT's hosted services: catalog req

### How it works (self-hosted)

Omit `pmxtApiKey` to use the local sidecar. Install `pmxt-core` from npm and supply venue credentials directly. See [Self-hosted trading (advanced)](#self-hosted-trading-advanced) below.
Omit `pmxtApiKey` to use the local PMXT service. Install `pmxt-core` from npm and supply venue credentials directly. See [Self-hosted trading (advanced)](#self-hosted-trading-advanced) below.

## Core Methods

Expand Down Expand Up @@ -139,7 +139,7 @@ See the full [hosted trading guide](https://pmxt.dev/docs/concepts/hosted-tradin

### Self-hosted trading (advanced)

When self-hosting, supply venue credentials directly — no `pmxtApiKey`. The SDK spawns a local sidecar process.
When self-hosting, supply venue credentials directly — no `pmxtApiKey`. The SDK spawns a local PMXT service.

**Polymarket:**
```typescript
Expand Down
Loading