A convert on Spot balances, step by step
What a user sees and does at /convert on Spot balances, what the server checks at each step, why a quote can expire or be refused at the last moment, and where the result shows up afterwards.
This page walks the user's side of a Spot convert so you can support it. The user-facing version, without the settings, is the help article Converting between your balances.
Where it is
Trading → Convert, at /convert. Converting uses the user's wallet
balances, so a visitor who is not logged in sees the form at rest, disabled,
with Log in to convert and Sign up where the button would be; the
History tab says Log in to see your converts, with Log in and
Sign up. A system account, the house included, is refused with "This
account cannot convert."
If the addon is enabled but no asset is open yet, the page says Convert isn't available right now ("No currencies are open for converting right now. Check back soon; your balances are not affected.") and offers View history. If the asset list cannot be read at all (the addon is disabled, or its licence is not active), the page shows Convert is unavailable with the server's own sentence and a Try again button.
While quoting is paused, or the desk is draining, the page still loads and the history still reads; it is new quotes and converts that are refused. The API answers "Instant Convert is paused. Please try again later." (in drain mode, "Instant Convert is not taking new converts right now. Please try again later."). The widget shows either as Converts are paused for now, and a refused preview turns the button into Try again; only a refusal met inside the two-factor dialog is shown there in the server's own words.
The steps
-
Spot or Ecosystem. When the page lists assets on both wallet types, a toggle at the top picks the wallet type, and a convert never crosses it: both balances and the quote are of one type. Switching starts the form again. When only one wallet type has anything listed there is no toggle, and the widget shows that type alone; a platform with nothing open on Ecosystem balances shows Spot only. See Converting on Ecosystem.
-
From and To. Each picker lists the open assets alphabetically, the ones the user holds first under Your assets, with a search by name or symbol. An asset open in one direction only is greyed out on the other side (Give only or Receive only), and a pair that needs it says so ("BTC can only be given, not received"). The swap button between the fields flips the pair.
-
The amount. The user types either side: what they give, or what they want to receive. Max fills the whole available balance. The Limits & fees panel beside the widget (below it on smaller screens) shows the platform-wide per-convert range (an asset's own minimum or maximum is applied at quote time and not shown there), how much of the daily limit is already used today (it resets at 00:00 UTC) and the fee this user pays.
-
Preview conversion. This asks the server for a quote, which is a priced row written to
convert_quotebefore the answer leaves the server. Nothing is estimated while the user types, because a number the page invented would be a price nobody guaranteed. The quote panel shows:- You pay: everything the user gives, the fee included;
- You receive: what lands in their balance;
- Rate, with a button to show it the other way round;
- Fee, with its rate, as its own line;
- Price held for N seconds, counting down.
-
Convert. The server executes exactly that quote. If the operator requires two-factor on converts, a dialog asks for the code first (Two-factor). On success: Convert complete. Your balances have been updated at the rate you were shown.
Why a quote goes away
Any edit drops it. A held price is for this pair and this amount. Changing either is a different convert, so the preview disappears the moment the field changes.
It expires. After convertQuoteTtlSeconds (default 10) the countdown reads
This price has expired. While the tab is visible the widget asks for a fresh
quote on its own, up to three times in a row, then waits for the user to press
Refresh quote. (Get a new quote is what the button says after the server
itself refused a quote as expired or moved.) The countdown is the quote's
lifetime counted from when the answer arrived in the browser, capped at the
server's own expiry time, so a wrong clock can only shorten it, never lengthen
it: a browser clock running fast can show a live quote as already expired. The
Convert button closes one second before the countdown ends.
The last look refuses it. Just before executing, the server re-reads the
order books (at most two seconds old) and prices the same convert again. If the
held quote has become better for the user than the market by more than
convertMaxExecDriftBps (default 15 bps), the convert is refused with The price
moved. Get a new quote. A move in the user's favour is executed as quoted.
Something closed in between. Everything the quote checked is checked again inside the transaction, under row locks: the user's balance, the house's floor, the daily and hourly caps and the unhedged exposure cap. A quote is only a promise about the price, not about the inventory. The refusal sentences are in Troubleshooting.
What the execute does
In one database transaction, locking every wallet row involved in ascending id order and then the quote row:
| Movement | Wallet | Ledger operation |
|---|---|---|
| The amount given, less the fee | user → house, in the currency given | CONVERT_OUT, CONVERT_HOUSE_IN |
| The amount received | house → user, in the currency received | CONVERT_HOUSE_OUT, CONVERT_IN |
| The fee | user → Super Admin, in the currency given | CONVERT_FEE, plus an admin_profit row of type CONVERT |
The order row is written as COMPLETED and the quote is marked USED. Posting
the same quote again, after a lost response or a double click, answers with the
same order rather than "expired", so a user whose money already moved is never
invited to convert twice.
Afterwards
- History is a tab on the same page, listing the user's converts newest first with their status; the Recent converts panel beside the widget shows the last five, and its View all opens the tab. A balance convert shows Completed at once. A Convert & Send shows its payout's progress instead: Awaiting approval (only while a manual approval holds it), Sending, Sent, then Confirmed, or Failed / Reversed. The list can be filtered by status (Completed, In progress, Failed, Reversed) and sorted newest or oldest first.
- In the platform's transaction history each of these entries has the type
Convert (
CONVERT). - The converted Spot balance is an ordinary Spot balance: tradable, and withdrawable through the normal Spot withdrawal.
Limits that apply to users
| Limit | Default | Setting |
|---|---|---|
| Smallest convert | $10 | convertMinUsd (or the asset's own minimum) |
| Largest convert | $10,000 | convertMaxUsd (or the asset's own maximum) |
| Per user per UTC day | $50,000 | convertUserDailyUsd |
| All users per rolling hour | $250,000 | convertGlobalHourlyUsd |
| Quote requests | 60 per minute per user | fixed |
| Convert requests | 20 per minute per user | fixed |
Converts are classified as trading for identity verification and geographic
restrictions: the user needs whatever KYC level your Trade feature requires,
and a country blocked from trading is blocked here too. An API key needs the
trade scope to call POST /api/convert/order.