Repository navigation
v0.7.0
Built on public contract 748066a, the contract of backend 9.2.5. Breaking changes are marked Breaking below; read them before upgrading.
Package version: 0.7.0. Git tag: v0.7.0. Released 2026-11-05. Built on
public contract 748066a.
- Breaking: a trailing stop created with an activation price already
reached now endsFAILEDwith
TRIGGER_FAILURE_REASON_TRIGGER_WOULD_TRIGGER_IMMEDIATELY(244).
ModifyTriggerand order modifies that would make a trailing stop act at
once are refused withERROR_CODE_TRIGGER_WOULD_TRIGGER_IMMEDIATELY(302),
leaving the existing state unchanged. To start trailing from the market,
clear the activation price with a present zero. - Breaking: remove the public holds-list method, hold models and decoders.
Read aggregate held trading funds from each asset'sreservedbalance in
the balances API. Individual hold IDs and expiry times have no replacement. - Breaking: listing events for an unreadable trigger now returns the same
not-found error as reading that trigger, instead of an empty history.
Events reads retry a catching-upUNAVAILABLEwith the trigger-read policy. - Breaking:
SpotFeeRategains public fields, so exhaustive struct literals
must initialize them.SpotFeeRateandSpotFeeRatesListno longer implementEq. - Expose reserve fee rates, the next scheduled change and the full fee
breakdown. Omitted optional components remain absent and omitted account
discounts decode as an empty list. - Breaking:
Error::PermissionDenied,Error::ApiKeyRejected,
Error::TimestampSkewandError::SessionRequiredgain
optional problem metadata. Include..in variant patterns when ignoring it. - Preserve REST problem status, code, detail and canonical type on realtime
authorization and early gateway authentication errors. - Pin execution-history continuation pages to the returned exchange order ID
so reuse of a client order ID cannot change generations between pages.
Attached-exit self-trade prevention, sub-account balances (contract
54dc59d). Breaking for code that builds Order, GetSubaccountResult or
GetSubaccountOpts with a struct literal naming every field.
GetSubaccountOpts::include_balancesasks a sub-account read for the
sub-account's balances, andGetSubaccountResult.balancesreturns them as a
BalancesList, the shape ofbalances.list.Noneunless asked for; an
empty list when the sub-account holds none. It needs theREAD_BALANCES
action on the sub-account, or the read fails withPermissionDenied; a
root-scoped API key cannot read a sub-account's balances. A read that
cannot reach the balances right now fails with the retryable
AUTH_TEMPORARILY_UNAVAILABLE.Order.self_trade_prevention_modereports the order's mode
(expire_taker,expire_maker,expire_both,UNKNOWN(<n>)for a newer
one). The order's attached take-profit, stop-loss and trailing-stop exits
use it; set it withCreateOrderParams.self_trade_prevention.- An attached exit never trades with the order it protects. When it fires
while that order still rests, the order's unfilled rest is canceled first
and the order ends withcancel_reasonCANCEL_REASON_ATTACHED_EXIT_FIRED
(on reads and on the private order stream). - A self-trade prevention block of an attached exit is a refused fire, not an
end: afire_refusedtrigger event withfire_refusal_reason
self_trade_prevented, whosechild_seqnames the child order self-trade
prevention expired. The leg stays armed. Reject reason
ERROR_CODE_SELF_TRADE_PREVENTEDdecodes too; no request is answered with
it. - A trigger a halted market refuses now reads
market_haltedas its
failure_reasonorfire_refusal_reason, never the unnamed
UNKNOWN_TRIGGER_FAILURE_REASON(212). Unknown reasons still decode with
their number. - A buy sized by a quote amount can carry attached exits; the server checks
the legs against the pair's minimums. - Docs:
Order.cum_notional,cum_quote()andquote_used()are exactly the
settled quote when the pair'sbase_quantity_scaleis at most 9; above
that they can exceed it by less than 1e-18 per fill.
Exact order totals, refused trigger fires, API-key refusal reasons
(contract e96897c). Breaking for code that builds these types with struct
literals or matches Error exhaustively.
Order::avg_price()is the exact average execution price from the new
Order.avg_price_e18(18 decimals;avg_pxstays rounded down to 1e-9).
Order.cum_notional/Order::cum_quote(base_quantity_scale)is the exact
quote amount of the fills before fees, andOrder.fee_total
(OrderFeeTotal:amount_e18/amount(),is_rebate,qty) their fee
net of rebates.Order::quote_used(base_scale)and
Order::quote_unspent(base_scale, quote_scale)tell how much of a
quote-sized buy's amount the fills used;Noneuntil the fee total covers
every fill. All exactDecimals, zero with no fills, andNonerather
than a rounded value when a result needs more digits than aDecimal
holds.- Trigger events:
fire_refused(also alist_eventsfilter) for a fire
refused while the trigger stays live, with the new
TriggerEvent.fire_refusal_reason(rate_limited,account_repairing,
market_halted,min_notional, ...). It is not terminal. The failure reason
account_repairingis named. Unknown event types and reasons still read as
UNKNOWN(<n>)/UNKNOWN_TRIGGER_FAILURE_REASON(<n>). Error::auth_code()returns the typedauth.v1.AuthErrorCodeof a refusal
on ConnectRPC (AuthErrorDetail) and REST (codewithAUTH_added,
UNAUTHENTICATEDasAUTH_AUTHENTICATION_REQUIRED);
errors::auth_codes::from_rest_codemaps a REST code, andauth_codesnames
the seven new values (SIGNATURE_INVALID,MISSING_HEADERS,KEY_EXPIRED,
KEY_DISABLED,IP_NOT_ALLOWED,API_KEY_NOT_ACCEPTED, plus the existing
TIMESTAMP_SKEW).- Changed: a ConnectRPC
AUTH_TIMESTAMP_SKEWdetail is the retryable
Error::TimestampSkew, and the other API-key reasons are
Error::ApiKeyRejectedwith the REST form of the code (SIGNATURE_INVALID),
the same errors the API gateway's answers map to. They wereError::Api. - New
Error::SessionRequired(is_session_required()) for
AUTH_SESSION_KIND_NOT_ALLOWED: a session-only method called with an
account API key, read from the Connectpermission_denieddetail and the
REST 403codealike. It wasError::Apion Connect and
Error::ApiKeyRejectedon REST. Error::Apigainsviolations(Error::violations()): the request fields
an order refusal names, with ConnectRPC field paths. A missing or wrong
attached trailing-stop maximum on create, preview or batch create is now
refused before sending with the server's code, rule ID and field path
(ERROR_CODE_BAD_PRICE/sell_unsetorbuy_at_least_activation,
ERROR_CODE_TRIGGER_BUY_REQUIRES_LIMIT/buy_required) asError::Api
instead ofError::Validation; a modify namesnew_attached_risk...and
a batch replace itemitems[N].new_attached_risk....Error::is_order_already_terminal()and
order_codes::ORDER_ALREADY_TERMINAL/ORDER_UNKNOWN: a cancel of an order
that has already ended, a repeat of the cancel that ended it included, is
now always refused withERROR_CODE_ORDER_ALREADY_TERMINAL. Treat it as
"already done".client.stop_all_trading(scope)cancels every live trigger, then every open
order. Cancel-all and the dead-man switch cancel orders only, never
triggers;cancel_all,cancel_all_afterandcanceldocument it.- Fixed: with
WireFormat::Json, a response naming an enum value newer than
this SDK (a new changelog surface, for example) failed the whole call with
a retryableError::Server. The value now reads as unset (and is dropped
from a repeated field), as protojson'sDiscardUnknowndoes; binary
responses keep the value's number. - Changelog: surface labels
market_data,quickswapandrewards;
ChangelogSection.surfacenames the product area a section covers;
list_changesrefuses more than 10surfacesbefore sending. - Docs: an API key's
permission_deniedmessage names the missing policy
action and reaches the caller as is; a quote-sized buy that spent its amount
endsfilled; a ladder whose levels were all canceled before any filled
endscancelled.
New: public product changelog (client.changelog). Read the changelog of
the environment you call without an API key. It is available on
devnet now and on testnet with its next release.
list_posts,get_postandlist_changeswrap
changelog.v1.ChangelogService;postsandchangesstream every page.breaking_changes_since(t)andaction_required_since(t)collect the
matching changes published sincet.- Typed models
ChangelogPostSummary,ChangelogPost,ChangelogSection,
ChangelogChangeandChangelogChangeEntry. Enums are lowercase labels and
unknown values read asunknown(<n>); change ids are base58. - The generated module tree now compiles
changelog.v1.
Batch replace refusals, trigger read-your-writes, owner role lock.
orders.wait_batch_replace(batch_request_id, subaccount_id, timeout)polls
get_batch_replace_statuswith a short backoff until no item is
admitted, polling through thenot_foundandunavailableanswers of the
first seconds after admission. It stops at the 60-second status window (or
an earliertimeout) withError::Transport: reconcile through the orders
then.BatchReplaceStatusItem::error_code()turns an item'scode
(POST_ONLY_CROSS) into the orders error code (ERROR_CODE_POST_ONLY_CROSS),
keeping a code this SDK does not know unchanged;
errors::order_codes::from_status_codedoes the same for any string.- Fixed:
get_batch_replace_statusfailed withError::ResponseContractfor
an item admitted and then refused when applied (phaserejected, still
counted inaccepted_count). It now decodes; an item rejected at admission
must still readrejected. - A status item with no successor, every
rejecteditem included, has an
emptyreplacement_order_id(was"0"). The admission's planned
replacement_order_idis not proof of an order. triggers.getandtriggers.list(andget_by_id,list_with) retry
unavailable/ HTTP 503 with the same request: 25 ms, doubling, at most
500 ms, giving up after about 2 s. The server answers it right after a
trigger change until the change is readable.errors::auth_codes::SUBACCOUNT_OWNER_ROLE_LOCKEDand
Error::is_subaccount_owner_role_locked(): a member call targeting the
sub-account's owner. A REST 412 problem with that code now maps to the same
Error::Apias the ConnectRPCfailed_preconditionanswer.- Docs: batch replace items amend in place or replace, as the trading
WebSocket schema now states; market-halt cancel reasons on orders
(CANCEL_REASON_MARKET_HALTED) and triggers (market_halted).