Skip to main content

doc/binance-pro-api-reference.md

# Binance Pro API Reference

This reference describes the supported Elixir surface for the Binance-first
CCXT Pro preview. The canonical implementation remains generated from
`ts/src/pro/binance.ts`; this document explains how to call the generated target
from Elixir code.

## Entrypoints

`Ccxt.Pro.binance/1` creates a CCXT-style Binance Pro instance:

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

`Ccxt.Pro.Binance.new/1` is the exchange-specific constructor behind
`Ccxt.Pro.binance/1`.

Accepted config keys:

| Key | Meaning |
| --- | --- |
| `apiKey` / `api_key` | Binance API key for signed Pro methods |
| `secret` / `api_secret` | Binance API secret for signed Pro methods |
| `binanceEnv` / `binance_env` | `"prod"`, `"testnet"`, `"sandbox"`, or `"demo"` |
| `options` | Default call options merged into generated methods |

Per-call options override instance options.

## Watch Semantics

Generated `watch_*` methods follow CCXT Pro's one-message async model. In
Elixir they return `{:ok, value}` or `{:error, reason}`:

```elixir
{:ok, ticker} =
  Ccxt.Pro.Binance.watch_ticker("BTC/USDT",
    binance_env: "prod",
    timeout: 30_000
  )
```

The websocket subscription remains open on the shared connection after a
successful `watch_*` call. Call the same `watch_*` method again to wait for the
next update.

Most public methods also accept an instance as their first argument:

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

## Stream Semantics

Elixir `stream_*` methods are convenience wrappers over repeated `watch_*`
calls. They return an `Enumerable` that yields `{:ok, value}` or
`{:error, reason}`:

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

`unwatch_on_halt: true` sends the matching public unwatch request when the
enumerable halts. Private stream wrappers do not imply private unwatch support;
close the connection explicitly when private user-data streams should stop.

## Connection Lifecycle

`Ccxt.Pro` owns the runtime websocket topology:

| Function | Purpose |
| --- | --- |
| `Ccxt.Pro.ensure_started/0` | Starts the Pro supervisor if needed |
| `Ccxt.Pro.connection/2` | Returns one supervised websocket process per URL |
| `Ccxt.Pro.connections/0` | Lists active Pro websocket connections |
| `Ccxt.Pro.connection_info/1` | Returns connection state, waiters, channels, and caches |
| `Ccxt.Pro.close_connection/1` | Terminates a connection by URL or pid |
| `Ccxt.Pro.attach_debug_logger/0` | Prints Pro telemetry events in IEx |
| `Ccxt.Pro.detach_debug_logger/0` | Detaches the debug logger |

`unwatch_*` methods only send Binance unsubscribe messages and wait for ACK.
They do not close the underlying websocket connection. Use
`Ccxt.Pro.close_connection/1` for shutdown.

## Production Worker Pattern

For an OTP-style integration, keep blocking stream consumption out of business
process callbacks. The included `examples/pro_ticker_worker.exs` demonstrates
the public stream shape:

```elixir
children = [
  {Task.Supervisor, name: Ccxt.Pro.Examples.BinanceTickerWorker.TaskSupervisor},
  {Ccxt.Pro.Examples.BinanceTickerWorker,
   symbol: "BTC/USDT", binance_env: "prod", print?: false}
]

Supervisor.start_link(children, strategy: :one_for_one)
```

The worker uses a `GenServer` to own the latest ticker snapshot and a
`Task.Supervisor` child to consume `Ccxt.Pro.Binance.stream_ticker/2`. On stop,
the worker terminates the stream task and calls `Ccxt.Pro.close_connection/1`.

Run the standalone example from `ccxt/elixir`:

```sh
CCXT_PRO_WORKER_SECONDS=10 mix run examples/pro_ticker_worker.exs
```

`examples/pro_order_event_worker.exs` uses the same `GenServer` +
`Task.Supervisor` shape for private order events. It authenticates once, reuses
the returned `ws_auth` for `Ccxt.Pro.Binance.stream_orders/4`, and requests
incremental private windows with `newUpdates: true`:

```sh
CCXT_PRO_ORDER_EVENT_WORKER_SECONDS=30 mix run examples/pro_order_event_worker.exs
```

Because stream consumption runs in a `Task.Supervisor.async_nolink/2` child, a
production worker must handle both the task result message (`{ref, result}`) and
the matching `:DOWN` monitor message. The example demonitor-flushes the matched
task result, closes the private websocket connection, records the last error,
and restarts through the normal retry path.

## Public Market Methods

Public market methods do not require credentials.

| Method | Return shape |
| --- | --- |
| `watch_ticker/2` | ticker map |
| `watch_tickers/2` | map of ticker maps |
| `watch_bids_asks/2` | map of bid/ask ticker maps |
| `watch_mark_price/2` | ticker map |
| `watch_mark_prices/2` | map of ticker maps |
| `watch_trades/4` | list of trade maps |
| `watch_trades_for_symbols/4` | list of trade maps |
| `watch_order_book/3` | order book map |
| `watch_order_book_for_symbols/3` | order book map |
| `watch_ohlcv/5` | list of OHLCV arrays |
| `watch_ohlcv_for_symbols/4` | list of OHLCV arrays |
| `watch_liquidations/4` | list of liquidation maps |
| `watch_liquidations_for_symbols/4` | list of liquidation maps |
| `fetch_ticker_ws/2` | ticker map via websocket API |
| `fetch_trades_ws/4` | list of trade maps via websocket API |
| `fetch_order_book_ws/3` | order book map via websocket API |
| `fetch_ohlcv_ws/5` | list of OHLCV arrays via websocket API |

Public stream wrappers:

| Stream | Underlying watch |
| --- | --- |
| `stream_ticker/2` | `watch_ticker/2` |
| `stream_trades/4` | `watch_trades/4` |
| `stream_order_book/3` | `watch_order_book/3` |
| `stream_ohlcv/5` | `watch_ohlcv/5` |

Public unwatch methods:

| Method | Scope |
| --- | --- |
| `unwatch_ticker/2` | single ticker |
| `unwatch_tickers/2` | multi ticker |
| `unwatch_mark_price/2` | single mark price |
| `unwatch_mark_prices/2` | multi mark price |
| `unwatch_trades/2` | single trade stream |
| `unwatch_trades_for_symbols/2` | multi trade stream |
| `unwatch_order_book/2` | single order book |
| `unwatch_order_book_for_symbols/2` | multi order book |
| `unwatch_ohlcv/3` | single OHLCV stream |
| `unwatch_ohlcv_for_symbols/2` | multi OHLCV stream |

## Private Websocket API Methods

Signed read-only methods:

| Method | Return shape |
| --- | --- |
| `fetch_balance_ws/1` | CCXT balance map |
| `fetch_position_ws/2` | position map |
| `fetch_positions_ws/2` | list of position maps |
| `fetch_order_ws/3` | order map |
| `fetch_orders_ws/4` | list of order maps |
| `fetch_open_orders_ws/4` | list of order maps |
| `fetch_closed_orders_ws/4` | list of order maps |
| `fetch_my_trades_ws/4` | list of trade maps |

Signed order mutation methods:

| Method | Risk policy |
| --- | --- |
| `create_order_ws/6` | Requires explicit live gate for production tests |
| `edit_order_ws/7` | Requires explicit live gate for production tests |
| `cancel_order_ws/3` | Safe only for known test-created order ids |
| `cancel_all_orders_ws/2` | Manual-confirmed only |

Order mutation tests use non-marketable production orders and immediate cleanup
where possible. They are not part of normal `mix test`.

## Private User Data Stream Methods

Private event-driven methods:

| Method | Return shape |
| --- | --- |
| `watch_balance/1` | CCXT balance map |
| `watch_orders/4` | list of order maps |
| `watch_positions/4` | list of position maps |
| `watch_my_trades/4` | list of trade maps |
| `watch_my_liquidations/4` | list of liquidation maps |
| `watch_my_liquidations_for_symbols/4` | list of liquidation maps |

Private stream wrappers:

| Stream | Underlying watch |
| --- | --- |
| `stream_balance/1` | `watch_balance/1` |
| `stream_orders/4` | `watch_orders/4` |
| `stream_positions/4` | `watch_positions/4` |
| `stream_my_trades/4` | `watch_my_trades/4` |

User-data stream helpers:

| Function | Purpose |
| --- | --- |
| `authenticate/1` | Authenticates a private websocket connection |
| `user_data_stream_status/1` | Calls `session.status` |
| `user_data_stream_subscriptions/1` | Calls `session.subscriptions` |
| `unsubscribe_user_data_stream/2` | Calls `userDataStream.unsubscribe` |
| `renew_listen_token/1` | Renews listen-token based private sessions where applicable |
| `keep_alive_listen_key/3` | Keeps listen-key based sessions alive |

## Options

Common options:

| Option | Meaning |
| --- | --- |
| `:binance_env` | `"prod"`, `"testnet"`, `"sandbox"`, or `"demo"` |
| `:timeout` | Receive timeout in milliseconds |
| `:verbose` | Enables per-connection websocket logging |
| `:cache_limit` | Per-message-hash cache limit |
| `:unwatch_on_halt` | Stream wrapper sends public unwatch on halt |
| `:api_key` | Per-call API key |
| `:api_secret` | Per-call API secret |
| `:recvWindow` / `:recv_window` | Binance signed request receive window |
| `:type` | Market type hint such as `"spot"`, `"future"`, `"delivery"`, or `"papi"` |

Private snapshot options:

| Option | Meaning |
| --- | --- |
| `:fetch_balance_snapshot` / `:fetchBalanceSnapshot` | Preload private balance state |
| `:fetch_positions_snapshot` / `:fetchPositionsSnapshot` | Preload private position state |
| `:snapshot_fetcher` | Injectable snapshot function for tests or custom integration |
| `:rest_fetcher` | Injectable REST fallback function |

## Unified Structures

Generated parsers return CCXT-style maps for ticker, trade, order, balance,
position, order book, OHLCV, and liquidation structures. Raw exchange payloads
remain available under each structure's `:info` field.

The structure-to-database planning layer is documented in:

- `doc/ccxt-structure-schema.md`
- `doc/ccxt-pro-structure-coverage.md`

The persistence helper modules are intentionally adapter-like. They normalize
CCXT structures into stable row maps; they do not require a specific Ecto
schema or database migration.

## Environment Variables

Production Pro credentials:

```sh
BINANCE_PROD_API_KEY=...
BINANCE_PROD_API_SECRET=...
BINANCE_PRO_ENV=prod
```

Testnet Pro credentials:

```sh
BINANCE_TESTNET_API_KEY=...
BINANCE_TESTNET_API_SECRET=...
BINANCE_PRO_ENV=testnet
```

Demo Pro credentials:

```sh
BINANCE_DEMO_API_KEY=...
BINANCE_DEMO_API_SECRET=...
BINANCE_PRO_ENV=demo
```

REST/manual smoke credentials:

```sh
BINANCE_API_KEY=...
BINANCE_API_SECRET=...
BINANCE_ENV=prod
```

Production, testnet, and demo keys are separate Binance key families.

## Validation Commands

Normal gate:

```sh
npm run checkElixir
```

Generate API documentation:

```sh
npm run docsElixir
```

Build a local Hex package dry-run:

```sh
npm run buildElixirPackage
```

Run the path dependency consumer smoke:

```sh
npm run testElixirConsumer
```

Run the packaged consumer smoke:

```sh
npm run testElixirPackageConsumer
```

Run the release preview gate:

```sh
npm run releaseElixirPreviewCheck
```

Short public soak:

```sh
CCXT_PRO_SOAK_SECONDS=5 CCXT_PRO_SOAK_MIN_UPDATES=1 npm run testElixirProSoak
```

Default long public soak:

```sh
npm run testElixirProLongSoak
```