CCXT

CCXT vs the Extended (x10) Python SDK

CCXT and x10-python-trading-starknet compared on StarkNet order signing, onboarding, streaming, rate limits and portability across seven languages.

Extended is a perpetuals exchange settled on StarkNet. Its API takes an ordinary X-Api-Key header for authentication, but that is not what makes an order valid: every order, transfer and withdrawal carries a settlement signed with a Stark private key over a Poseidon hash, and the exchange settles what that key signed.

Two ways to talk to it: the official x10xchange/python_sdk, published as x10-python-trading-starknet, or CCXT, which computes the same message hashes and Stark signatures and exposes Extended behind the API it uses for 103 other venues.

The question that decides it: is Extended your only venue, in Python?

TL;DR

  • Pick the official SDK if Extended is your only venue and you work in Python. Its Rust-backed Stark signing, its onboarding flow that derives a Stark key pair from an Ethereum account, and its vault and builder-code modules have no CCXT equivalent.
  • Pick CCXT if you want create_order to mean the same thing on Extended, Hyperliquid, Binance and Bybit, in any of seven languages, with the Poseidon hashing, Stark signing and account lookup already written.
  • Signing is not the thing you give up. CCXT takes apiKey and privateKey as credentials, fetches your L2 vault and Stark key from the account endpoint, builds the settlement and signs it — the same path in Python, Go, C#, PHP, Java, JavaScript and TypeScript.

At a glance

CCXTx10-python-trading-starknet
Venues covered104 (Extended is one of them)Extended only
LanguagesTypeScript, JavaScript, Python, PHP, C#/.NET, Go, Java — one APIPython 3.10+
Packages to install1 (ccxt)the SDK plus a compiled Rust Stark-crypto wrapper
Unified market data + trading APIyes — 53 unified capabilities, 31 fetch* methodsno — Extended's own request and response models
Instrument addressingunified symbols: 'BTC/USDC:USDC'market names: BTC-USD
Stark signingdone for you from apiKey + privateKeydone for you, from a StarkPerpetualAccount
Credentials neededapiKey, privateKey — the L2 vault and Stark public key are fetchedapi_key, public_key, private_key, vault
Onboarding from an Ethereum accountnot modelledyes — EIP-712 signature, Stark key derivation
WebSocketsyes — 10 watch* methods, same shapes as fetch*yes — a stream client per topic, plus a multiplexed RPC stream client
Raw endpoint accessyes — 51 endpoints as implicit methodsyes, and the OpenAPI specs ship in the repo
Built-in rate limiteryes, on by default (rateLimit 600 ms, CCXT's setting for Extended's default request tier)manual
Unified error typesyes — 41 typed exceptions in one hierarchyExtended's numeric error codes
Testnetexchange.set_sandbox_mode(True) — swaps in api.starknet.sepolia.extended.exchangeTESTNET_CONFIG
Popularity43.8k GitHub stars · 4.8M PyPI + 494k npm installs/month (one package, every venue)39 GitHub stars
Latest releasecontinuous2.6.0, uploaded August 2026
LicenceMITMIT
SupportDiscord, Telegram, GitHub issues — usually same-dayGitHub issues, Discord

Figures verified September 2026 against CCXT v4.5.77, the x10xchange/python_sdk repository, its README and examples, the x10-python-trading-starknet PyPI metadata, and install counts from npm and PyPI.

The same job, written both ways

Fetch a ticker

import ccxt

exchange = ccxt.extended()
ticker = exchange.fetch_ticker('BTC/USDC:USDC')
print(ticker['last'], ticker['baseVolume'])

The SDK gives you Extended-shaped typed models — market.trading_config.min_order_size, market.market_stats.bid_price, market.trading_config.round_price(...). CCXT gives you a unified ticker structure and a unified market structure, with the same keys, types and units as on every other exchange, and unified symbols: 'BTC/USDC:USDC' rather than BTC-USD.

Place a limit order

import ccxt

exchange = ccxt.extended({'apiKey': '...', 'privateKey': '0x...'})
order = exchange.create_order('BTC/USDC:USDC', 'limit', 'buy', 0.001, 60000, {
    'postOnly': True,
})
print(order['id'], order['status'])
exchange.cancel_order(order['id'], 'BTC/USDC:USDC')

Both sign. The SDK builds the order object first — passing the account, the StarkNet signing domain and the market so the settlement can be constructed — then posts it. CCXT does the same work inside create_order: it fetches your account's l2Key and l2Vault, converts amount and price into Stark-resolution integers, assembles the settlement (baseAssetId, baseAmount, quoteAssetId, quoteAmount, feeAssetId, feeAmount, expiration, salt), computes the SNIP-12 Poseidon message hash and produces the Stark signature — then returns a unified order structure.

The practical difference is the credential surface: the SDK asks for four values (api_key, public_key, private_key, vault); CCXT asks for two and reads the rest from the account endpoint.

Stream an order book

import ccxt.pro
import asyncio

async def main():
    exchange = ccxt.pro.extended()
    while True:
        orderbook = await exchange.watch_order_book('BTC/USDC:USDC')
        print(orderbook['bids'][0], orderbook['asks'][0])

asyncio.run(main())

Both are await-shaped and both are reasonable. The difference is what a stream returns: the SDK hands you the message it received, sequence number included, and the SDK's plain streaming client opens one WebSocket connection per topic (a separate RPC streaming client multiplexes several topics onto one socket). CCXT keeps one connection per URL, merges the book itself, and returns the same structure fetch_order_book returns, so a polling loop becomes a streaming loop by changing one word.

CCXT's ten streaming methods for Extended are watchOrderBook, watchTrades, watchOHLCV, watchMarkPrice, watchIndexPrice, watchFundingRate, watchBalance, watchOrders, watchMyTrades and watchPositions.

Where the differences actually bite

Seven languages, one API — signing included

This is the largest practical gap. The official SDK is Python, and its Stark signing is accelerated by a compiled Rust wrapper with per-platform wheels (Linux glibc and musl on x86 and arm64, macOS arm64, Windows x86; Windows arm64 is marked experimental). Porting that to Go or C# is not a translation exercise, it is a cryptography project.

CCXT implements extendedStarknetSign, the Poseidon hash and the selector derivation in its base class in every language it ships, so the same order-signing path exists in TypeScript, JavaScript, Python, PHP, C#, Go and Java.

import ccxt from 'ccxt';
const exchange = new ccxt.extended ({ apiKey: '...', privateKey: '0x...' });
const ticker = await exchange.fetchTicker ('BTC/USDC:USDC');

One API for perp DEXes and CEXes

Extended signs a Stark settlement. Hyperliquid signs EIP-712 typed data. dYdX signs a Cosmos transaction. Binance signs an HMAC over a query string. Their symbols, order payloads, error codes and stream dialects have nothing in common. CCXT already absorbed that:

for exchange_id, symbol in [('extended', 'BTC/USDC:USDC'), ('hyperliquid', 'BTC/USDC:USDC'),
                            ('binance', 'BTC/USDT:USDT'), ('bybit', 'BTC/USDT:USDT')]:
    exchange = getattr(ccxt, exchange_id)()
    print(exchange_id, exchange.fetch_ticker(symbol)['last'])

The derivatives surface is unified

Fifty-three unified capabilities cover more than order entry: fetchPositions, fetchPosition, fetchPositionsHistory, fetchFundingRateHistory, fetchFundingHistory, fetchOpenInterestHistory, fetchMarkOHLCV, fetchIndexOHLCV, fetchLeverage, setLeverage, fetchTradingFee, fetchTradingFees, fetchLedger, fetchTransfers, transfer and fetchAccounts. Order management includes editOrder, cancelOrders, cancelAllOrders and cancelAllOrdersAfter — the dead-man's-switch that cancels everything if your process stops calling in.

exchange.cancel_all_orders_after(30000)   # cancel everything if I go quiet for 30s

Rate limits and precision

CCXT ships a throttler that is on by default, with rateLimit set to 600 ms for Extended's default request tier and per-endpoint weights in the exchange definition. Precision is handled by amount_to_precision and price_to_precision, backed by the Precise string-arithmetic class — which matters more than usual here, because the Stark settlement encodes amounts as integers at the instrument's resolution and a rounding error changes the hash you signed.

amount = exchange.amount_to_precision('BTC/USDC:USDC', 0.0012345678)
price = exchange.price_to_precision('BTC/USDC:USDC', 61234.56789)

Testnet without a second code path

exchange = ccxt.extended({'apiKey': '...', 'privateKey': '0x...'})
exchange.set_sandbox_mode(True)   # api.starknet.sepolia.extended.exchange

One flag swaps the REST and WebSocket hosts. Extended's testnet accounts and keys are separate from mainnet, as they are with the SDK's TESTNET_CONFIG.

Nothing is hidden — the implicit API

Alongside the unified methods, all 51 Extended endpoints are generated as callable implicit methods, with the API-key header, rate limiting and error mapping applied. Browse them on the Extended implicit API page.

What the official Extended SDK does better

Real advantages, not padding:

  • Onboarding from an Ethereum account. The SDK derives a Stark key pair from an Ethereum signature over an EIP-712 AccountCreation struct, and creates the account and API keys for you. CCXT starts from credentials you already hold.
  • Rust-accelerated Stark crypto. Signing and hashing go through a compiled wrapper rather than pure Python, which matters when you are signing at quoting frequency.
  • Vaults and builder codes. Vault public data and user vault token management, plus builder-specific data, are first-class modules. CCXT does not model either.
  • A multiplexed RPC streaming client. Alongside the per-topic stream client, the SDK offers a single-connection client that carries many topics, and a blocking trading client for synchronous code.
  • The OpenAPI specs ship in the repository. specs/ gives you the machine-readable definition to generate against, which is useful whether or not you use the SDK.
  • An experimental MCP server. x10-mcp exposes the SDK to Model Context Protocol clients, with the appropriate warnings about executing real transactions.

If Extended is your only venue and you are writing Python — especially if you are onboarding programmatically or running vault strategies — the official SDK is the better fit.

Migrating from the x10 SDK to CCXT

What you are doingx10 Python SDKCCXT
Marketsrest_client.markets_info.get_markets_dict()load_markets()
SymbolsBTC-USD'BTC/USDC:USDC'
CredentialsStarkPerpetualAccount(api_key, public_key, private_key, vault){'apiKey': ..., 'privateKey': ...}
Tickermarket.market_statsfetch_ticker() / fetch_tickers()
Order bookthe order-book endpoint or streamfetch_order_book()
Candlesthe candles endpointfetch_ohlcv()
New ordercreate_order_object(...) then orders.place_order(order=...)create_order()
Cancelorders cancelcancel_order() / cancel_orders() / cancel_all_orders()
Open ordersthe account order endpointsfetch_open_orders()
Positionsthe account position endpointsfetch_positions() / fetch_positions_history()
Balancethe account balance endpointfetch_balance()
Leveragethe account leverage endpointset_leverage() / fetch_leverage()
Streamsstream_client.subscribe_to_*watch_* on ccxt.pro.extended
Vaults, builder codes, onboardingvault, builder, auth modulesnot unified — call the implicit endpoints

Start with Install, then the Manual, then the extended unified API reference.

FAQ

Does CCXT sign Extended orders itself, or do I need the x10 SDK? CCXT signs them itself. It builds the order settlement, computes the SNIP-12 Poseidon message hash and produces the Stark-curve signature in its base class — implemented natively in all seven CCXT languages, with no Rust wrapper to install.

What credentials does CCXT need for Extended? apiKey and privateKey. Your L2 vault id and Stark public key are read from the account endpoint on first use, so you do not pass them in. The official SDK asks for all four up front.

Can CCXT onboard a new Extended account from an Ethereum wallet? No. Account creation and the Ethereum-to-Stark key derivation are SDK features. Create the account and API key through Extended's interface or the SDK, then use CCXT with the resulting credentials.

Does CCXT stream private Extended data? Yes — watchBalance, watchOrders, watchMyTrades and watchPositions, alongside watchOrderBook, watchTrades, watchOHLCV, watchMarkPrice, watchIndexPrice and watchFundingRate.

Do I need CCXT Pro separately for WebSockets? No. CCXT Pro is included in the ccxt package. Use ccxt.pro.extended and call watch* methods.

Is CCXT free? Yes. MIT-licensed, WebSocket support included, no paid tier.

Next steps

On this page