Skip to main content

doc/release-0.1.0-binance-pro-preview.md

# Release 0.1.0-binance-pro-preview

Date: 2026-06-11

This is the first productized Elixir target checkpoint for the Binance-first
CCXT Pro work. It is a Hex preview publication candidate for controlled Binance
REST and Binance Pro integration work.

## Release Boundary

This release is scoped to:

- Binance REST raw endpoint generation.
- Binance selected unified REST generation.
- Binance Pro high-level websocket method coverage.
- CCXT-style Pro instance configuration through `Ccxt.Pro.binance/1`.
- OTP-owned websocket lifecycle through `Registry` and `DynamicSupervisor`.
- Public watch, stream, unwatch, cache, parser, telemetry, and cleanup flows.
- Private websocket API signing, request-id routing, response parsing, and
  read-only live smoke.
- Private user-data stream subscription, event routing, cache, snapshot preload,
  and lifecycle helpers.
- Order websocket API mutation support with explicit production risk gates.
- CCXT unified structure normalization and persistence planning helpers.

This release is not scoped to:

- General multi-exchange Elixir Pro support.
- Publishing to Hex.
- Full REST method maturity for every Binance funding/margin/savings mutation.
- Automatic safe execution of withdraw, transfer, borrow, repay, convert, or
  gift-code REST surfaces.
- Always-on live tests that require real fills or private liquidation events.

## Package State

The Elixir package metadata now identifies this target as:

```elixir
version: "0.1.0-binance-pro-preview"
```

Recommended integration after publishing is through the Hex preview version:

```elixir
{:ccxt, "== 0.1.0-binance-pro-preview"}
```

`smoke/consumer_app` verifies the source-checkout consumption model from a
separate Mix project with:

```elixir
{:ccxt, path: "../.."}
```

The package includes:

- `lib`
- `priv`
- `doc`
- `mix.exs`
- `README.md`

Generated ExDoc output is written to `_build/docs` so it does not overwrite the
tracked `doc` source directory.

## Supported User Entrypoints

Main modules:

- `Ccxt.Pro`
- `Ccxt.Pro.Binance`
- `Ccxt.Exchanges.Binance`
- `Ccxt.Raw.Binance`
- `Ccxt.StructureNormalizer`
- `Ccxt.StructurePersistence`
- `Ccxt.StructureSchema`

Production-style examples:

- `examples/pro_ticker_worker.exs`: GenServer + Task.Supervisor public ticker
  worker that stores the latest ticker snapshot and performs explicit websocket
  cleanup.
- `examples/pro_order_event_worker.exs`: GenServer + Task.Supervisor private
  order event worker that authenticates once, reuses `ws_auth`, and consumes
  `stream_orders/4` with `newUpdates: true`.

Primary Pro usage:

```elixir
binance =
  Ccxt.Pro.binance(%{
    apiKey: "...",
    secret: "...",
    binanceEnv: "prod",
    options: %{recvWindow: 5_000}
  })

{:ok, ticker} = Ccxt.Pro.Binance.watch_ticker(binance, "BTC/USDT")
```

Public streams:

```elixir
Ccxt.Pro.Binance.stream_ticker("BTC/USDT",
  binance_env: "prod",
  unwatch_on_halt: true
)
|> Enum.take(10)
```

Connection shutdown:

```elixir
Ccxt.Pro.connections()
|> Enum.each(&Ccxt.Pro.close_connection(&1.pid))
```

## Evidence Snapshot

Latest verified evidence recorded for this release:

- `npm run inspectElixirPro`: `107/107` Binance Pro source methods covered.
- Generated/runtime split: `66` generated and `41` runtime-owned.
- `unsupportedMethods: []`.
- Exchange instance wrappers: `52/52` required callable public methods wrapped.
- Runtime lifecycle coverage: `18/18` required features covered.
- Structure coverage: `44` covered structure rows, `71` classified
  non-structure rows, `0` unclassified rows.
- `npm run checkElixir`: `509 tests, 0 failures (60 excluded)`.
- `mix test --include live --exclude prod_order_live test/ccxt_pro_binance_live_test.exs --timeout 180000`:
  `34 tests, 0 failures`. This refreshed public streams and signed read-only
  private websocket/API paths without enabling production order placement.
- Default long soak: `npm run testElixirProLongSoak` ran for `901.0` seconds
  with `883` ticker updates, `1767` websocket messages, maximum update gap
  `2992` ms, first update latency `2353` ms, `0` disconnects, and
  `0` terminations.
- Production-style worker smoke:
  `CCXT_PRO_WORKER_SECONDS=5 mix run examples/pro_ticker_worker.exs` received
  `3` public ticker updates for `BTC/USDT`, returned a snapshot with
  `last_error: nil`, and then stopped the worker with explicit connection
  cleanup.
- Production order live gate:
  `CCXT_PRO_ENABLE_PROD_ORDER_LIVE=true BINANCE_PROD_ORDER_SYMBOL=BTC/USDT
  BINANCE_PROD_ORDER_AMOUNT=0.0002 mix test --only prod_order_live
  test/ccxt_pro_binance_live_test.exs --timeout 180000` ran `3` tests with
  `0` failures and `31` excluded, covering non-marketable production order
  create, fetch, edit, cancel, and `stream_orders/4` execution-report handling.
- Private order event worker smoke:
  `BINANCE_PRO_ENV=prod CCXT_PRO_ORDER_EVENT_WORKER_SECONDS=90 mix run
  examples/pro_order_event_worker.exs` ran while
  `CCXT_PRO_ENABLE_PROD_ORDER_LIVE=true mix run
  examples/pro_safe_order_lifecycle.exs` created, fetched, edited, and canceled
  a non-marketable `BTC/USDT` order. The worker received `3` private
  execution-report updates (`NEW`, original order `CANCELED`, edited order
  `CANCELED`), retained them in its final snapshot, and exited normally. The
  retry path also surfaced Binance
  `-2035 User Data Stream subscription already active`, which is recorded as an
  exchange lifecycle condition.
- Path dependency consumer smoke:
  `npm run testElixirConsumer` compiled `smoke/consumer_app` with
  `{:ccxt, path: "../.."}` and ran `1` live public Binance Pro test with
  `0` failures, covering `Ccxt.Pro.binance/1`, `watch_ticker/2`,
  `stream_ticker/2`, and `Ccxt.Pro.close_connection/1` from outside the
  package project.
- Hex package dry-run: `npm run buildElixirPackage` built
  `ccxt-0.1.0-binance-pro-preview.tar` with package metadata, runtime
  dependencies (`jason`, `telemetry`, `websockex`), `lib`, `priv`, `doc`,
  `mix.exs`, and `README.md`. `mix hex.build --unpack` also succeeded; the
  unpacked package contained the runtime/docs payload, including
  `doc/real-project-integration.md` and `doc/release-checklist.md`, and
  excluded `test`, `examples`, and `smoke`.
- Hex metadata audit: `mix.exs` keeps the preview version
  `0.1.0-binance-pro-preview`, package name `CCXT Elixir`, MIT license, CCXT
  source/doc links, package files limited to `lib`, `priv`, `doc`, `mix.exs`,
  and `README.md`, and ExDoc extras for the API reference, real project
  integration guide, release checklist, release note, target maturity record,
  cache/lifecycle/structure coverage docs, structure schema guide, and live
  testing plan.
- Packaged consumer smoke: `npm run testElixirPackageConsumer` built and
  unpacked the local Hex package into a temporary directory, copied
  `smoke/consumer_app` into a clean temporary consumer project, pointed
  `CCXT_CONSUMER_CCXT_PATH` at the unpacked package, and ran `1` live public
  Binance Pro test with `0` failures against the package payload.
- Release preview gate: `npm run releaseElixirPreviewCheck` runs
  `checkElixir`, `docsElixir`, and `testElixirPackageConsumer` in order.
  Latest local run completed all three phases, including docs generation and
  the packaged consumer smoke with `1` test and `0` failures.
- Cache parity hardening: `Ccxt.Pro.IndexedArrayCache` adds reusable
  symbol/key-indexed cache semantics and `Ccxt.Pro.OrderCache` now uses it for
  symbol/id order replacement instead of id-only replacement.
- Timestamp cache hardening: `Ccxt.Pro.TimestampArrayCache` adds reusable
  timestamp-indexed replacement semantics and Binance OHLCV public cache uses it
  for raw kline payloads keyed by `k.t`.
- Position cache hardening: `Ccxt.Pro.PositionCache` now preserves Binance
  hedge-mode position updates by `symbol -> side` while keeping the existing
  per-symbol payload shape for `watch_positions/4`.
- New update counter hardening: `Ccxt.Pro.CacheUpdates` owns CCXT Pro
  `getLimit`-style `allNewUpdates`, `newUpdatesBySymbol`, nested id/side, and
  timestamp counter semantics. Public cached watch streams and private list/order
  watchers can opt into that incremental window with `newUpdates: true` or
  `new_updates: true`.

## Risk Policy

Public market data methods are safe to run against production because they do
not require credentials and do not mutate exchange state.

Signed read-only methods require production, testnet, or demo credentials that
match the selected environment.

Order mutation methods are available but must stay gated in automation:

- `create_order_ws/6`
- `edit_order_ws/7`
- `cancel_order_ws/3`
- `cancel_all_orders_ws/2`

Production order tests require `CCXT_PRO_ENABLE_PROD_ORDER_LIVE=true` and use
non-marketable orders with immediate cancel when possible.
`cancel_all_orders_ws/2` remains manual-confirmed only because it can cancel
unrelated user orders.

REST funding and account-mutation surfaces such as withdraw, transfer, borrow,
repay, convert, and gift code are outside the Pro manifest and remain
manual-confirmed/dry-run/signature-only work for this release.

## Known Boundaries

- Binance-only Pro scope.
- The long soak evidence is 15 minutes, not yet 6-hour or 24-hour soak.
- Event-driven private live tests cannot deterministically prove real fills or
  private liquidations without causing actual account events.
- Hex publication metadata exists, but the intended consumption model is still
  local/path dependency.
- Generated modules should not be edited by hand. Update the generator or
  runtime-owned modules instead.

## Release Commands

Normal local gate:

```sh
npm run checkElixir
```

Generate ExDoc output:

```sh
npm run docsElixir
```

Short long-soak sanity:

```sh
CCXT_PRO_LONG_SOAK_SECONDS=5 CCXT_PRO_LONG_SOAK_MIN_UPDATES=1 npm run testElixirProLongSoak
```

Default long soak:

```sh
npm run testElixirProLongSoak
```