XT Exchange Provider

Back your platform's spot markets with XT liquidity — how the provider layer works, what it powers, the one-active-provider rule, and the XT-specific quirks that cost operators money.

5 min readUpdated 3 August 2026xt, exchange, spot, provider, ccxt

The XT Exchange Provider is one of three interchangeable back-ends for Bicrypto's spot trading stack. With it installed and enabled, everything a customer sees on /market and /trade — the tickers, the order book, the candles, the fills — comes from XT, and every order they place is a real order on your XT account.

This is a provider, not a market. You are not running an exchange. You are running an interface in front of one, and XT holds the coins.

A SPOT wallet balance in Bicrypto is a database row that mirrors what your XT account holds. Deposits go to an XT address, orders are placed on XT's book, and withdrawals are XT withdrawals initiated over the API. If XT freezes the account the API key belongs to, your customers' spot balances are frozen with it and nothing in this platform can release them.

What it requires

Requirement Why If it is missing
Bicrypto core The provider is a licensed entry in the core's exchange table and uses the core's spot wallets, orders and cron worker There is nothing to enable it into
An XT account with API access Every price, order and withdrawal is an authenticated call against it The provider enables but reports "API credentials are missing"
A server XT will accept connections from XT geo-blocks a long list of countries and does not whitelist IPv6 Every call fails with HTTP 451, and it looks like a credential fault
Redis Already mandatory for the core; the provider uses it for the exchange ban switch Covered by the core requirement

Nothing else. It does not need Ecosystem, ScyllaDB, or any blockchain addon.

It is also not a substitute for them. Ecosystem is the opposite architecture — your own matching engine, your own on-chain custody, your own keys. An install can run both at once: XT-backed SPOT markets and self-custodied ECO markets sit in separate wallet types and separate market lists, and the balances never mix.

Only one provider is ever active

Binance, KuCoin and XT are three rows in the same exchange table, and the platform reads exactly one of them:

const provider = await models.exchange.findOne({ where: { status: true } });

Enabling XT is therefore a switch, not an addition. The status endpoint sets status = false on every other row inside the same transaction, and activating an XT licence does the same thing again. There is no configuration in which both Binance and XT serve spot traffic.

Currencies, markets, precisions and maker/taker fees in your database were imported from the previous provider. Symbols, network names and withdrawal minimums differ between exchanges. After a switch you must re-import both currencies and markets, and any SPOT wallet balance recorded while a different exchange held the coins is now a claim against an account that does not have them. Do not switch a provider on a live install with customer balances without a settlement plan.

What the provider actually powers

Market data. Tickers stream over /api/exchange/ticker and per-symbol ticker, candle, trade and order-book streams over /api/exchange/market, all via ccxt Pro's WebSocket transport (watchTickers, watchOHLCV, watchTrades, watchOrderBook — XT supports all four). Historical candles come from fetchOHLCV, cached by the chart builder.

Order placement. A spot order validates against your stored market metadata (precision, min/max amount, min/max cost), debits the SPOT wallet, then calls exchange.createOrder. Fees are taken from your stored maker/taker rate, not XT's — the taker rate applies to buys and the maker rate to sells.

Reconciliation. The processPendingSpotOrders cron runs every 60 seconds and settles open orders against XT: full fills, partial fills, cancellations and rejections all land back in the wallet through it.

Prices. processCurrenciesPrices refreshes every stored currency price every 120 seconds from XT's tickers. This is what values a customer's portfolio.

Deposits and withdrawals. Deposit addresses are XT's addresses, fetched per currency and network. Withdrawals call exchange.withdraw on your account. Both paths carry XT-specific network-name translation — see Deposits and withdrawals, because this is where the platform most often looks healthy while a customer's money is nowhere.

XT-specific behaviour worth knowing on day zero

These are not bugs to report. They are shapes in XT's API that the platform already compensates for, and knowing them explains most surprising output.

XT needs a key and a secret, and nothing else. Unlike KuCoin there is no passphrase. APP_XT_API_PASSPHRASE is read by the shared loader but XT declares password: false in its required credentials, so setting it changes nothing.

Connections are forced onto IPv4. The shared HTTPS agent sets family: 4 specifically because XT's API-key IP whitelist does not accept IPv6 addresses. If you route XT traffic through a proxy instead, that override no longer applies — whitelist the proxy's address, and make sure it is an IPv4 one.

XT publishes no active flag. Every currency and every network comes back with active: undefined. The platform treats only an explicit false as disabled and reads deposit/withdraw as the real signal. Do not read a blank active column as "XT has disabled this asset".

XT reports no memo information. Every imported network row is stored with withdrawMemo: false, because XT's currency payload carries nothing to derive it from. Memo-requiring assets need operator judgement rather than the imported flag.

Filled buy quantities arrive in the quote asset. For a BUY, XT's info.executedQty is the amount spent, not the amount bought, so the platform divides it by info.avgPrice before crediting. This is why an XT-backed install has a provider branch in the order adjuster that the other providers do not.

Ticker volume arrives as a string in info.q. The ticker WebSocket coerces it to a number for XT specifically; a raw string reaching the browser used to crash the trade page.

Where to start

Install

Licence, credentials, enabling the provider, and the two imports that must run before anyone can trade.

API keys and network access

Creating the key on XT, the permissions to grant, IP whitelisting, geo-blocking and the proxy path.

Currencies and markets

The two importers, what they delete, and how fees and precision are decided.

Deposits and withdrawals

Three different network-name tables, the verification loop, and the withdrawal status mapping.

Reference

Every variable, endpoint, permission and cron the provider touches.

Troubleshooting

Symptom-first diagnosis, including the two failure modes that report green.

Three facts that catch operators out

A missing licence file blocks enabling, silently. The status endpoint checks for lic/54510301.lic on disk before it will set status = true, and answers 403 with licenseRequired if it is absent. Activating the licence in the admin panel writes that file.

Credentials are read from .env at connection time, and the connection is cached for the process lifetime. Editing APP_XT_API_KEY does nothing until the backend restarts. There is no reload button.

A rate-limit ban silences the entire spot stack while everything reports green. When XT rate-limits you, the platform writes an unblock time to the Redis key exchange:ban_status, and while that key is set every spot path — prices, order reconciliation, deposits, withdrawals, routes — returns without doing anything. It self-clears on a TTL, capped at 24 hours. Nothing in the admin UI shows it; the backend log line is Exchange is banned for … more.