CCXT Elixir
Elixir target for CCXT, generated from the upstream TypeScript sources.
Current package status: 0.1.0-binance-pro-preview. The mature slice is
Binance-first: REST raw/unified generation exists for Binance, and the CCXT Pro
websocket target covers Binance Pro high-level methods with generated or
runtime-owned semantics.
This preview package is ready for controlled Binance REST and Binance Pro integration work. It is not yet a broad multi-exchange Elixir release.
What Is Included
- Binance unified REST methods in the Ccxt.Exchanges.Binance module, generated from
ts/src/binance.tsthrough the AST/IR Elixir target. - Binance raw REST endpoint metadata in the Ccxt.Raw.Binance module, generated from
describe().api. - Runtime HTTP execution through the Ccxt.HttpExecutor module.
- Binance Pro websocket methods in the Ccxt.Pro.Binance module, with generated methods plus runtime-owned websocket/cache/auth lifecycle semantics.
- CCXT-style Pro instance configuration through
Ccxt.Pro.binance/1. - Structure normalization and database planning helpers through
Ccxt.StructureSchema,Ccxt.StructureNormalizer,Ccxt.StructurePersistence, andCcxt.RawPayload. - Release, live testing, production integration, cache parity, lifecycle, and
structure coverage docs under
doc/.
Install
Use the published preview package from a consuming project:
def deps do
[
{:ccxt, "== 0.1.0-binance-pro-preview"}
]
end
Then fetch and compile from the consuming project:
mix deps.get
mix compile
When working from a local CCXT checkout before publishing, use a path dependency instead:
def deps do
[
{:ccxt, path: "../ccxt/elixir"}
]
end
When working inside the CCXT checkout itself:
cd ccxt/elixir
mix deps.get
mix compile
Binance REST Quick Start
Public REST calls can be made directly through the generated Binance REST module:
{:ok, timestamp} = Ccxt.Exchanges.Binance.fetch_time()
{:ok, ticker} =
Ccxt.Exchanges.Binance.fetch_ticker("BTC/USDT",
binance_env: "prod"
)
IO.inspect({timestamp, ticker.symbol, ticker.last})
Private REST calls use the active Binance credential environment:
BINANCE_API_KEY=...
BINANCE_API_SECRET=...
BINANCE_ENV=prod
{:ok, balance} =
Ccxt.Exchanges.Binance.fetch_balance(%{},
# optional per-request routing override
binance_env: "prod"
)
BINANCE_ENV defaults to production. Supported aliases are:
- production:
prod,production,mainnet - testnet:
test,testnet,sandbox - demo:
demo
Per-call binance_env: "demo" or binance_env: "testnet" overrides the
process environment for generated REST calls.
Raw REST Endpoints
Use the raw Binance endpoint module when you need direct Binance endpoint metadata instead of a CCXT unified parser:
{:ok, endpoint} = Ccxt.Raw.Binance.public_get_time()
{:ok, body} = Ccxt.HttpExecutor.fetch(endpoint, %{}, binance_env: "prod")
For signed raw endpoints, pass params to the generated raw endpoint and keep credentials in the process environment:
{:ok, endpoint} = Ccxt.Raw.Binance.private_get_account(recvWindow: 10_000)
{:ok, account} = Ccxt.HttpExecutor.fetch(endpoint, %{}, binance_env: "prod")
Raw endpoint helpers return %Ccxt.RawEndpoint{} metadata. Ccxt.HttpExecutor
owns URL routing, signing, timestamp, recvWindow, and response decoding.
REST Risk Boundary
Read-only REST methods are suitable for ordinary live smoke with read-only
keys. State-changing methods such as withdraw, transfer, borrow, repay,
convert, gift-code, and production-only order paths require the risk policy in
doc/binance-live-testing.md. Demo/testnet should be used where Binance
supports the namespace; production-only mutations should be dry-run or manually
confirmed first.
Binance Pro Quick Start
Public Binance Pro streams do not require API keys:
{:ok, ticker} =
Ccxt.Pro.Binance.watch_ticker("BTC/USDT",
binance_env: "prod",
timeout: 30_000
)
IO.inspect({ticker.symbol, ticker.last, ticker.datetime})
watch_* methods follow CCXT Pro semantics: each call waits for and returns the
next matching message. The websocket subscription remains active on the shared
connection after the call returns.
For repeated Elixir consumption, use stream_* wrappers:
Ccxt.Pro.Binance.stream_ticker("BTC/USDT",
binance_env: "prod",
timeout: 30_000,
unwatch_on_halt: true
)
|> Enum.take(10)
|> Enum.each(fn
{:ok, ticker} -> IO.inspect({ticker.symbol, ticker.last, ticker.datetime})
{:error, reason} -> IO.inspect(reason, label: "ticker_error")
end)
Close a shared websocket connection explicitly when you want to release it:
url = Ccxt.Pro.Binance.get_ws_url("spot", "public", "prod") <> "/stream"
:ok = Ccxt.Pro.close_connection(url)
Or inspect all active Pro connections:
Ccxt.Pro.connections()
Instance Configuration
The generated Pro target supports a CCXT-style instance model through
Ccxt.Pro.binance/1:
binance =
Ccxt.Pro.binance(%{
apiKey: System.fetch_env!("BINANCE_PROD_API_KEY"),
secret: System.fetch_env!("BINANCE_PROD_API_SECRET"),
binanceEnv: "prod",
options: %{recvWindow: 5_000}
})
{:ok, balance} = Ccxt.Pro.Binance.fetch_balance_ws(binance)
Instance credentials and options are merged into each call. Per-call options override instance options:
{:ok, ticker} =
Ccxt.Pro.Binance.watch_ticker(binance, "BTC/USDT",
timeout: 30_000,
binance_env: "prod"
)
Accepted config keys:
apiKeyorapi_keysecretorapi_secretbinanceEnvorbinance_envoptions
Binance Pro Credentials
For private Pro methods, prefer explicit instance credentials. Environment credentials are also supported for tests and examples:
BINANCE_PROD_API_KEY=...
BINANCE_PROD_API_SECRET=...
BINANCE_TESTNET_API_KEY=...
BINANCE_TESTNET_API_SECRET=...
BINANCE_DEMO_API_KEY=...
BINANCE_DEMO_API_SECRET=...
BINANCE_PRO_ENV=prod
BINANCE_PRO_ENV selects the default Pro environment used by examples and
live tests. Method calls can also pass binance_env: "prod", "testnet",
"sandbox", or "demo".
Private Pro credential lookup is environment-specific. It does not silently fall back from production keys to demo keys or from demo keys to production keys.
Public Market Streams
Common public methods:
watch_ticker/2,watch_tickers/2watch_trades/4,watch_trades_for_symbols/4watch_order_book/3,watch_order_book_for_symbols/3watch_ohlcv/5,watch_ohlcv_for_symbols/4watch_bids_asks/2watch_mark_price/2,watch_mark_prices/2watch_liquidations/4,watch_liquidations_for_symbols/4
Elixir stream wrappers:
stream_ticker/2stream_trades/4stream_order_book/3stream_ohlcv/5
Use unwatch_on_halt: true when a stream should send the matching Binance
unsubscribe request as the enumerable halts. Use Ccxt.Pro.close_connection/1
when the whole websocket connection should be shut down.
Private Websocket API
Read-only signed websocket API methods include:
fetch_balance_ws/1fetch_position_ws/2fetch_positions_ws/2fetch_order_ws/3fetch_orders_ws/4fetch_closed_orders_ws/4fetch_open_orders_ws/4fetch_my_trades_ws/4
Order mutation websocket API methods are available but require explicit risk control in live testing:
create_order_ws/6edit_order_ws/7cancel_order_ws/3cancel_all_orders_ws/2
Production order tests are gated behind CCXT_PRO_ENABLE_PROD_ORDER_LIVE=true
and use non-marketable orders with immediate cancel where possible.
cancel_all_orders_ws/2 remains manual-confirmed only because it can cancel
unrelated user orders on the same symbol.
Private Event Streams
Private user-data stream methods include:
watch_balance/1watch_orders/4watch_positions/4watch_my_trades/4watch_my_liquidations/4watch_my_liquidations_for_symbols/4
Elixir stream wrappers:
stream_balance/1stream_orders/4stream_positions/4stream_my_trades/4
These wrappers repeat the generated private watch_* calls. They do not imply
a private unwatch_* API. Use Ccxt.Pro.close_connection/1 for explicit
private connection shutdown.
Telemetry And Debugging
Attach a simple IEx logger:
:ok = Ccxt.Pro.attach_debug_logger()
Detach it:
:ok = Ccxt.Pro.detach_debug_logger()
The runtime emits telemetry under [:ccxt, :pro, ...] for connection lifecycle,
subscription sends, request resolution/rejection, message receive, cache append,
message-hash routing, and explicit close operations.
Examples
Run examples from ccxt/elixir:
mix run examples/pro_watch_ticker.exs
mix run examples/pro_unwatch_ticker.exs
mix run examples/pro_stream_ticker.exs
mix run examples/pro_ticker_worker.exs
mix run examples/pro_public_market_streams.exs
mix run examples/pro_connection_info.exs
mix run examples/pro_close_connection.exs
mix run examples/pro_debug_logger.exs
mix run examples/pro_private_readonly.exs
mix run examples/pro_safe_order_lifecycle.exs
mix run examples/pro_order_event_stream.exs
mix run examples/pro_order_event_worker.exs
mix run examples/pro_soak_smoke.exs
mix run examples/pro_structure_persistence.exs
Public examples do not require API keys. Private examples load ../../.env
when it exists and require the matching Binance environment credentials.
pro_ticker_worker.exs is the production-style OTP example. It defines a
GenServer that owns the latest ticker state and a supervised stream task that
consumes Ccxt.Pro.Binance.stream_ticker/2. Run a short public session with:
CCXT_PRO_WORKER_SECONDS=10 mix run examples/pro_ticker_worker.exs
In a real application, put its Task.Supervisor and worker in your supervision
tree and set print?: false; the worker can then expose latest/1 or
snapshot/1 to the rest of the app.
pro_order_event_worker.exs is the matching private-stream OTP example. It
authenticates a Binance user-data stream once, passes the resulting ws_auth
into Ccxt.Pro.Binance.stream_orders/4, and consumes private order updates with
newUpdates: true:
CCXT_PRO_ORDER_EVENT_WORKER_SECONDS=30 mix run examples/pro_order_event_worker.exs
It does not place orders by itself. Run it while another process creates, edits, or cancels orders if you want to see order events arrive.
Manual Binance Testing
The REST Elixir runtime reads Binance credentials from process environment variables:
BINANCE_API_KEY=...
BINANCE_API_SECRET=...
BINANCE_ENV=prod
BINANCE_ENV is optional and defaults to production. Supported aliases are
prod, production, and mainnet for production; test, testnet, and
sandbox for Binance testnet; and demo for Binance demo URLs.
The same routing can also be selected per request with the :binance_env
option:
Ccxt.Exchanges.Binance.fetch_time([], binance_env: "demo")
Ccxt.Exchanges.Binance.fetch_balance([], binance_env: "testnet")
For private methods, use API keys created for the selected Binance environment. Production keys, testnet keys, and demo keys are not interchangeable.
Consumer Smoke
smoke/consumer_app is a minimal external Mix project that depends on this
package exactly like a real application. By default it uses the repository path:
{:ccxt, path: "../.."}
It verifies that a consumer project can fetch dependencies, compile, start an
application, instantiate Ccxt.Pro.binance/1, call public watch_ticker/2,
consume public stream_ticker/2, and close the shared websocket connection.
Run the path dependency smoke from the CCXT repository root:
npm run testElixirConsumer
Run the packaged consumer smoke before a release:
npm run testElixirPackageConsumer
That gate builds the local Hex package, unpacks it into a temporary directory,
copies smoke/consumer_app into a clean temporary consumer project, points the
consumer dependency at the unpacked package with CCXT_CONSUMER_CCXT_PATH, and
runs the same public Binance Pro watch/stream/close smoke against the package
payload.
The smoke uses public Binance market data and does not require API keys. It is
tagged as :live inside the consumer app so plain mix test in that app does
not hit the network by accident.
Validation Gates
From the CCXT repository root:
npm run pre-transpile-elixir
npm run transpileElixir
npm run transpileElixirPro
npm run assertElixirIR
npm run assertElixirGenerated
npm run assertElixirPro
npm run assertElixirStructureSchemas
npm run checkElixir
npm run docsElixir
npm run buildElixirPackage
npm run testElixirConsumer
npm run testElixirPackageConsumer
npm run releaseElixirPreviewCheck
npm run testElixirProSoak
npm run testElixirProLongSoak
The normal gate is:
npm run checkElixir
Build a local Hex package dry-run without publishing:
npm run buildElixirPackage
Run the release preview gate before handing off a package:
npm run releaseElixirPreviewCheck
This runs checkElixir, regenerates docs, builds and unpacks the package in a
temporary directory, and runs the packaged consumer smoke against public Binance
market data.
Soak gates are opt-in. The long soak defaults to 900 seconds:
npm run testElixirProLongSoak
For a short sanity run:
CCXT_PRO_LONG_SOAK_SECONDS=5 CCXT_PRO_LONG_SOAK_MIN_UPDATES=1 npm run testElixirProLongSoak
API Reference And Release Notes
doc/binance-pro-api-reference.mddocuments the supported public surface and return shapes.doc/real-project-integration.mdshows the OTP supervision, credentials, telemetry, retry, and database integration shape for application projects.doc/release-checklist.mdrecords the final local, live, package, soak, and evidence gates to run before release.doc/release-0.1.0-binance-pro-preview.mdrecords the preview release boundary, validation evidence, and known limitations.doc/ccxt-pro-elixir-target.mdis the traceability and maturity record.doc/ccxt-pro-cache-parity.mdtracks CCXT Pro cache-class parity.doc/ccxt-pro-lifecycle-coverage.mdanddoc/ccxt-pro-structure-coverage.mdare generated coverage matrices.doc/ccxt-structure-schema.mdexplains the raw payload, unified structure, Ecto template, and persistence-planning layer.doc/binance-live-testing.mdrecords REST/live-test environment coverage and production-only mutation policy.