Skip to content

Pydantic v2 upgrade + WebSockets + API parity (v2.0.0)#35

Merged
jeuryink merged 3 commits into
mainfrom
v2
Jun 22, 2026
Merged

Pydantic v2 upgrade + WebSockets + API parity (v2.0.0)#35
jeuryink merged 3 commits into
mainfrom
v2

Conversation

@jeuryink

@jeuryink jeuryink commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

Overview

This PR upgrades nado-protocol to Pydantic v2, adds WebSocket support, and closes most of the API-coverage gap against the TypeScript SDK (nado-typescript-sdk @ 6f2a9501). Version bumped 0.3.5 → 2.0.0.

Tests: 161 (v1 baseline) → 242 passing on Pydantic v2. flake8 nado_protocol tests is clean.

Reviewer note: the only hard dependency change for consumers is pydantic <2.0^2.7. The public surface (model .dict()/.json(), client construction, wire shapes) is unchanged.

1. Pydantic v1 → v2 migration

Mechanical migration across the package: model_dump/model_dump_json, @field_validator/@model_validator, ConfigDict, explicit = None on ~95 Optional fields, annotated type: discriminators, conlist length args, AnyUrl→validated str, parse_objmodel_validate.

Four subtle v1→v2 behavior differences are deliberately preserved on NadoBaseModel (and pinned by tests):

  • serialize_as_any=True — request models swap a field's value for a differently-shaped TxRequest in a validator; v2 would otherwise serialize by declared type and drop fields.
  • coerce_numbers_to_str=True — the server returns numbers for some string-typed fields (chain_id, nonces).
  • revalidate_instances="always" — restores v1 parse_obj copy semantics (otherwise place_order caches a stale signature across calls).
  • URL fields validate format but preserve the exact string (no AnyUrl trailing-slash normalization).

2. WebSocket support (nado_protocol.ws)

  • NadoWebSocketClient/ws (query + execute over a socket).
  • NadoSubscriptionClient/subscribe (11 stream types + subscribe/unsubscribe/list/ping/time/authenticate).
  • Pure, independently-testable message builders; sync transport over websocket-client.
  • Byte-exact to nado-core subscription.rs / engine.rs.

3. New HTTP coverage (all verified live against nado-core)

Engine — executes place_orders, transfer_quote, withdraw_collateral_v2 (incl. new WithdrawCollateralV2 EIP-712 type); queries get_market_prices, get_insurance, get_max_nlp_burnable, get_nlp_pool_info, get_nlp_locked_balances, get_edge_all_products; new EngineEdgeQueryClient (cached prices/symbols/contracts/status/all-products/edge-all-products/health-groups/bbo-history + ping/time) and EngineWebClient (/ip, /cf-check, /time).

Indexerget_ink_airdrop, get_sequencer_backlog, get_subaccount_dda, get_points, get_private_alpha_choice, get_multi_perp_prices, get_multi_product_snapshots, get_nlp_snapshots, get_fast_withdrawal_signature, get_edge_candlesticks, get_edge_market_snapshots, get_v2_symbols; full leaderboard read suite + list_social_accounts; EIP-712 signed writes register_leaderboard / connect_social_account / revoke_social_account (new indexer signing path); pagination get_paginated_subaccount_orders / get_paginated_subaccount_events.

High-level APIsspot.withdraw_v2, spot.transfer_quote, market.get_latest_market_prices.

4. Docs

  • Relocated the out-of-place root margin-manager.mddocs/guides/margin-manager.md.
  • New docs/guides/v2.md (migration + new features) and docs/guides/feature-parity.md (live coverage tracker).
  • Wired ws / web / edge modules into the Sphinx API reference.

TODO

Done ✅

  • Pydantic v2 migration (+ behavior-preservation guard tests)
  • WebSocket /ws + /subscribe clients, streams, builders
  • Engine executes: place_orders, transfer_quote, withdraw_collateral_v2
  • Engine queries: market_prices (batch), insurance, max_nlp_burnable, nlp_pool_info (fully typed), nlp_locked_balances (fully typed), edge_all_products
  • EngineEdgeQueryClient (incl. cached_nlp_pool_info) + EngineWebClient
  • Indexer: ink_airdrop, backlog, dda, points, private_alpha_choice, multi-perp-prices, multi-product-snapshots, nlp_snapshots, fast_withdrawal_signature, edge candlesticks/snapshots, v2 symbols
  • Indexer leaderboard (read) + social list + EIP-712 signed writes (register/connect/revoke)
  • Indexer pagination: orders, events (+ collateral/nlp/settlement/liquidation subsets), match, interest-funding, leaderboard
  • High-level spot/market passthroughs
  • Sanity scripts extended with the new endpoints (engine + indexer)
  • Docs: relocate margin-manager, add v2.md + feature-parity.md, API reference
  • 247 tests pass; flake8, mypy clean; poetry.lock regenerated (CI green)

Verification

  • Everything is unit-tested with mocked transport (offline), including all EIP-712 signed paths (they actually sign).
  • For live verification against a running gateway/engine/indexer, run the sanity scripts — the engine + indexer scripts exercise the new v2.0.0 endpoints at the end of their runs:
    poetry run engine-sanity
    poetry run indexer-sanity
    

Intentionally omitted (not implemented server-side)

  • validate_orderengine/src/matching/query.rs:query_validate_order is commented out and returns NotImplemented.
  • referral_code / maker_statistics — no live route in the nado-core Query enum.

Testing notes

  • v1 baseline captured green (161) before migration; v2 is green (247) with no package-level deprecation warnings.
  • Verified each new endpoint maps to a real, implemented nado-core handler (not an enum stub).

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings June 22, 2026 20:55

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR upgrades the SDK to Pydantic v2, adds synchronous WebSocket support (/ws + /subscribe), and expands HTTP API coverage (engine queries/executes, indexer queries, edge/web helper clients) toward parity with the TypeScript SDK, with accompanying regression + parity tests and documentation updates.

Changes:

  • Migrates models/validators/config to Pydantic v2 while preserving v1 serialization semantics via NadoBaseModel.
  • Adds WebSocket message builders, stream models, and synchronous clients (NadoWebSocketClient, NadoSubscriptionClient).
  • Adds new engine/indexer endpoints (including signed EIP-712 paths), edge/web helper clients, and extensive unit tests + docs.

Reviewed changes

Copilot reviewed 48 out of 50 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/ws/test_ws.py Adds unit tests for WS stream serialization, message builders, URL conversion, and mocked transport roundtrips.
tests/ws/init.py Adds WS test package marker.
tests/utils/test_order_appendix.py Tightens assertions and removes unused variables in appendix tests.
tests/trigger_client/test_place_trigger_order.py Removes an unused import from trigger-order tests.
tests/test_pydantic_v2_migration.py Adds regression tests pinning preserved v1→v2 semantics in NadoBaseModel and key models.
tests/test_parity_additions.py Adds tests for new engine/indexer endpoints, pagination helpers, and signing flows.
tests/engine_client/test_web_client.py Adds tests for EngineWebClient gateway connectivity helpers.
tests/engine_client/test_edge_client.py Adds tests for EngineEdgeQueryClient cached query behavior and request shapes.
tests/conftest.py Updates fixtures for v2 URL handling and removes duplicated fixtures/imports.
pyproject.toml Bumps version to 0.4.0, upgrades to Pydantic v2, and adds websocket-client.
nado_protocol/ws/streams.py Introduces WS stream subscription parameter models.
nado_protocol/ws/messages.py Introduces pure WS wire-message builders for /ws and /subscribe.
nado_protocol/ws/client.py Adds synchronous WS clients and URL derivation helper.
nado_protocol/ws/init.py Exposes WS APIs via package exports.
nado_protocol/utils/subaccount.py Fixes v2 Optional defaulting (subaccount_owner = None).
nado_protocol/utils/model.py Updates NadoBaseModel for v2 (ConfigDict, model_dump*, serialization defaults).
nado_protocol/utils/margin_manager.py Migrates Pydantic config patterns and Optional defaults for v2.
nado_protocol/utils/execute.py Migrates validators/config to v2 and centralizes sender serialization helper.
nado_protocol/utils/backend.py Reworks URL validation/cleaning for v2 while preserving string URLs and adds linked-signer model validation.
nado_protocol/trigger_client/types/query.py Migrates trigger query param models/validators to v2 and fixes discriminator typing.
nado_protocol/trigger_client/types/models.py Adds explicit Optional defaults for v2 behavior.
nado_protocol/trigger_client/types/execute.py Migrates trigger execute request validators to v2.
nado_protocol/trigger_client/query.py Migrates trigger query client parsing (model_validate).
nado_protocol/trigger_client/execute.py Migrates trigger execute client parsing (model_validate) and keeps execute helpers.
nado_protocol/indexer_client/types/query.py Adds many new indexer query params/requests/data models + v2 config/typing updates.
nado_protocol/indexer_client/types/models.py Adds v2 Optional defaults in indexer response models.
nado_protocol/indexer_client/types/init.py Migrates IndexerClientOpts URL handling to shared clean_url with v2 validators.
nado_protocol/indexer_client/query.py Adds new indexer endpoints (reads, signed writes, pagination, v2 symbols, edge snapshots) and v2 parsing updates.
nado_protocol/engine_client/web.py Adds EngineWebClient for gateway connectivity/geo endpoints.
nado_protocol/engine_client/types/query.py Adds new engine queries + migrates validators/discriminators/Optional defaults to v2.
nado_protocol/engine_client/types/models.py Migrates constrained list typing and Optional defaults to v2.
nado_protocol/engine_client/types/execute.py Adds new execute params/requests (batch place orders, transfer_quote, withdraw_collateral_v2) and v2 validator migration.
nado_protocol/engine_client/query.py Adds new engine query methods and migrates .parse_obj.model_validate.
nado_protocol/engine_client/execute.py Adds new engine execute methods (batch place orders, transfer_quote, withdraw_collateral_v2) and migrates .parse_obj.model_validate.
nado_protocol/engine_client/edge.py Adds EngineEdgeQueryClient for cached/edge query endpoint + control calls.
nado_protocol/engine_client/init.py Exports new engine helper clients (web, edge).
nado_protocol/contracts/types.py Migrates URL fields to validated str, adds execute types, and v2 Optional defaults.
nado_protocol/contracts/eip712/types.py Adds new EIP-712 struct definitions and migrates model config to v2.
nado_protocol/contracts/eip712/sign.py Migrates EIP-712 serialization to model_dump() under v2.
nado_protocol/contracts/init.py Migrates .parse_obj.model_validate and v2 Optional defaults in contracts context.
nado_protocol/client/context.py Migrates URL option types to validated str and adds v2 Optional defaults.
nado_protocol/client/apis/spot/execute.py Adds high-level passthroughs for withdraw_v2 and transfer_quote.
nado_protocol/client/apis/rewards/execute.py Migrates .parse_obj.model_validate in claim validation.
nado_protocol/client/apis/market/query.py Adds multi-product latest market prices passthrough.
nado_protocol/client/apis/market/execute.py Migrates dependency parsing to model_validate.
nado_protocol/client/init.py Migrates context option parsing to v2 and removes AnyUrl/parse_obj_as usage.
docs/source/api-reference.rst Wires new modules (ws, engine_client.web, engine_client.edge) into Sphinx API reference.
docs/guides/v2.md Adds v2 migration + feature overview documentation.
docs/guides/margin-manager.md Relocates/adds detailed margin-manager reference doc.
docs/guides/feature-parity.md Adds a parity tracker document for Python vs TypeScript SDK coverage.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread nado_protocol/engine_client/execute.py
Comment thread nado_protocol/indexer_client/query.py
Comment thread nado_protocol/trigger_client/execute.py
Comment thread nado_protocol/ws/client.py Outdated
@jeuryink jeuryink changed the title Pydantic v2 upgrade + WebSockets + API parity (v0.4.0) Pydantic v2 upgrade + WebSockets + API parity (v2.0.0) Jun 22, 2026
@jeuryink jeuryink force-pushed the v2 branch 2 times, most recently from 9336ad6 to 54c0897 Compare June 22, 2026 21:53
Upgrade the SDK to Pydantic v2, add WebSocket support, and close most of
the API-coverage gap against the TypeScript SDK.

- Pydantic v1 -> v2 migration across the whole package; pin pydantic ^2.7.
  Preserves v1 wire behavior via serialize_as_any, coerce_numbers_to_str,
  revalidate_instances on the base model. Bump version 0.3.5 -> 2.0.0.
- WebSockets: new nado_protocol.ws package for the /ws (query + execute) and
  /subscribe (streaming + control) gateway endpoints.
- New engine endpoints: place_orders, transfer_quote, withdraw_collateral_v2,
  batch market_prices, insurance, max_nlp_burnable, nlp_pool_info,
  nlp_locked_balances, edge_all_products; new EngineEdgeQueryClient and
  EngineWebClient.
- New indexer endpoints: ink_airdrop, backlog, direct_deposit_address, points,
  private_alpha_choice, multi-product perp prices + snapshots, nlp_snapshots,
  fast_withdrawal_signature, edge candlesticks/market-snapshots, v2 symbols,
  leaderboard read suite + social list, EIP-712 signed writes
  (register_leaderboard, connect/revoke social account), and pagination helpers.
- Relocate margin-manager.md into docs/guides; add docs/guides/v2.md and
  feature-parity.md.
- CI: regenerate poetry.lock for the new deps; mypy and flake8 clean.

161 -> 242 tests passing on Pydantic v2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
jeuryink and others added 2 commits June 22, 2026 18:19
…handshake

The gateway requires permessage-deflate compression on the WS handshake
(returns 403 otherwise). websocket-client cannot negotiate it; switch the WS
transport to the websockets library's sync client, which does. Verified live
against testnet (/subscribe streaming + /ws query).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jeuryink jeuryink merged commit 15e8d93 into main Jun 22, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants