Skip to content

Releases

v0.6.2

Choose a tag to compare

@aiiven aiiven released this 05 Nov 23:41
9561a8a

Git tag: v0.6.2. Released 2026-11-06.

  • REST errors that say an order or trigger outcome is unknown now use the
    same non-retryable API error as Connect. Read the order or trigger back
    before retrying: the first request may still apply. Codes added by a newer
    server are treated the same way. A gateway timeout
    without a recognised outcome code remains a retryable transport/server
    failure with an unknown outcome; reconcile before retrying a mutation.

v0.6.1

Choose a tag to compare

@aiiven aiiven released this 05 Nov 22:52
cf300f8

Git tag: v0.6.1. Released 2026-11-06.

  • Service-unavailable responses now raise retryable server errors on Connect
    for orders, withdrawals and internal transfers, matching REST. This includes
    policy and fee lookups, backlogs, operations in progress and temporarily
    unavailable dependencies. Policy denials and permanent precondition failures
    remain non-retryable. Rate-limit errors keep their retry delay, and unknown
    mutation outcomes remain non-retryable even on an unavailable response.
  • Keep the service code and status on Connect server errors, and preserve
    the problem code and HTTP status on REST 502 and 503 server errors.

v0.6.0

Choose a tag to compare

@aiiven aiiven released this 05 Nov 14:00
f65478a

Built on public contract 748066a, the contract of backend 9.2.5. Breaking changes are marked Breaking below; read them before upgrading.

Git tag: v0.6.0. Released 2026-11-05.

  • Breaking: a trailing stop created with an activation price already
    reached now ends FAILED with
    TRIGGER_FAILURE_REASON_TRIGGER_WOULD_TRIGGER_IMMEDIATELY (244).
    ModifyTrigger and order modifies that would make a trailing stop act at
    once are refused with ERROR_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's reserved balance 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-up UNAVAILABLE with the trigger-read policy.
  • 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.
  • 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.

What a trading bot gains. A bot can read the product changelog of the
environment it trades on, with no API key, and find the breaking or
action-required changes published since it last looked. It can wait for a
batch replace to settle and see which items the market refused after
admission, read a trigger back right after changing it, and tell a market halt
from other cancels. It can see why a trigger's fire placed no order, read an
order's exact average price, quote used and fees, tell why an API key was
refused on either transport, and stop all automated trading in one call.

Breaking changes

  • A sub-account owner-role refusal is *errors.SubaccountOwnerRoleLockedError
    rather than *errors.APIError. errors.As with *errors.APIError and
    errors.AuthErrorCode still match it; a direct type assertion does not.
  • A batch replace status item with no successor reports an empty
    ReplacementOrderID instead of "0".
  • A session-only method refusing an API key (AUTH_SESSION_KIND_NOT_ALLOWED)
    is *errors.SessionRequiredError rather than *errors.APIError.
    errors.As with *errors.APIError and errors.AuthErrorCode still match
    it; a direct type assertion does not.
  • errors.AuthErrorCode returns only auth reasons (AUTH_*). It used to
    return any *errors.APIError code, such as an order ERROR_CODE_* or a
    Connect not_found; read APIError.Code for those.
  • SubAccounts.Get takes includeBalances again, after includePolicy:
    Get(ctx, account, subAccountID, includeAPIKeys, includeMembers, includeInvites, includePolicy, includeBalances, invitesDirection). Pass
    false to keep the previous behavior.

Added

  • client.Changelog wraps the public changelog.v1.ChangelogService.
    ListPosts, GetPost and ListChanges return typed
    models.ChangelogPostSummary, ChangelogPost, ChangelogSection,
    ChangelogChange and ChangelogChangeEntry values. Posts and Changes
    iterate over every page, and BreakingChangesSince and
    ActionRequiredSince collect the matching changes published since a time.
    Categories, audiences and surfaces are lowercase labels, and a value newer
    than the SDK reads as unknown(<n>). Change IDs are base58. An unknown slug
    fails with *errors.APIError code not_found.

  • Orders.WaitBatchReplace polls GetBatchReplaceStatus until no item is
    admitted, through the not found a new batch's status reads for a few
    seconds after admission, and stops at the 60-second status window, even
    with a status read in flight, with *errors.BatchReplaceWindowExpiredError
    and the last status: reconcile the orders with order reads then. A canceled
    or expired ctx returns ctx.Err().

  • BatchReplaceStatusItem.ErrorCode names an item's refusal as the
    orders.v1 error code a single modify returns (ERROR_CODE_POST_ONLY_CROSS
    for Code POST_ONLY_CROSS); a code newer than the SDK is kept as sent.

  • Market halts: orders the halt cancels read CancelReason market_halted
    (CANCEL_REASON_MARKET_HALTED, 17) on order reads and the order stream, and
    triggers it ends read CancelReason market_halted
    (TRIGGER_CANCEL_REASON_MARKET_HALTED, 13) on trigger reads, events and
    streams. A trigger refused after a halt reads FailureReason
    unknown(212) until the server reports market_halted.

  • *errors.SubaccountOwnerRoleLockedError and
    errors.IsSubaccountOwnerRoleLocked: a sub-account member call that targets
    the owner (AUTH_SUBACCOUNT_OWNER_ROLE_LOCKED, Connect
    failed_precondition or REST 412). It unwraps to *errors.APIError, so
    errors.AuthErrorCode still reads the code; a direct type assertion to
    *errors.APIError no longer matches it.

  • Trigger events fire_refused (EVENT_FIRE_REFUSED): a fire whose order
    was refused while the trigger stayed live, for the market's state, a
    position below the market's minimums, a rate limit or an account repair.
    It is not terminal. TriggerEvent.FireRefusalReason says why, with the
    FailureReason labels, which gain account_repairing. Decoded on
    Triggers.ListEvents and the trigger event stream; ListEvents filters on
    fire_refused.

  • errors.AuthErrorCode reads the auth reason of either transport: the
    Connect auth.v1.AuthErrorDetail code, or a REST problem code with the
    AUTH_ prefix added (UNAUTHENTICATED reads
    AUTH_AUTHENTICATION_REQUIRED). Constants for the new API-key refusals:
    errors.AuthCodeSignatureInvalid, AuthCodeTimestampSkew,
    AuthCodeMissingHeaders, AuthCodeKeyExpired, AuthCodeKeyDisabled,
    AuthCodeIPNotAllowed, AuthCodeAPIKeyNotAccepted, plus
    AuthCodeAuthenticationRequired and AuthCodeSessionKindNotAllowed.

  • *errors.SessionRequiredError and errors.IsSessionRequired: an API key on
    a method that accepts only a session token, on every service (Connect
    permission_denied with AUTH_SESSION_KIND_NOT_ALLOWED, REST 403).

  • errors.FieldViolation and errors.Violations(err): the fields an order
    refusal names, from the order ErrorDetail, from request validation
    (buf.validate.Violations, which the SDK used to drop) or from a REST
    problem's violations. ValidationError.Violations holds them;
    Metadata keeps its violation.N.* entries. models.OrderFieldViolation
    is now an alias of errors.FieldViolation.

  • Order.AvgPriceE18 and Order.AvgPrice(): the exact average execution
    price at 18 decimals. Order.CumNotional and Order.CumQuote(baseScale):
    the exact quote amount of the fills. Order.FeeTotal
    (models.OrderFeeTotal): the fills' net fee, set on history and
    single-order reads with execution history. Order.QuoteUsed(baseScale) and
    Order.QuoteUnspent(baseScale, quoteScale) say how much of a quote-amount
    buy was used, fee included, once the fee total covers every fill.

  • errors.IsOrderAlreadyTerminal: a cancel of an order that has already
    ended, which a repeat of the cancel that ended it now also answers.

  • client.StopAllTrading (services.StopAllTrading): cancels every live
    trigger in scope (created, armed, running, paused, every page), then all
    open orders. Orders.CancelAll and the dead-man switch cancel open orders
    only, never triggers.

  • Changelog surfaces market_data, quickswap and rewards
    (models.ChangelogSurfaceMarketData, ChangelogSurfaceQuickSwap,
    ChangelogSurfaceRewards), and ChangelogSection.Surface, the product area
    a section covers. ListChanges refuses more than 10 surfaces before
    sending.

  • SubAccounts.Get with includeBalances returns the sub-account's current
    balances in GetSubaccountResult.Balances, a models.BalancesList as
    Balances.List returns. It is nil when not asked for. It needs the
    READ_BALANCES action on the sub-account or fails with PermissionDenied;
    when balances cannot be read right now it fails with the retryable
    AUTH_TEMPORARILY_UNAVAILABLE.

  • CreateOrderRequest.SelfTradePreventionMode (expire_maker, the server
    default, expire_taker or expire_both) on create, preview and batch
    create. It applies to the order's attached take-profit, stop-loss and
    trailing stop orders as well. An unknown mode is refused before sending.
    Order.SelfTradePreventionMode reads it back, and a mode newer than this
    SDK reads as unknown(<n>).

  • Attached exits never trade with the order they protect: an order whose
    exit fired while it still rested ends canceled with CancelReason
    attached_exit_fired, and an exit order that self-trade prevention expired
    against another of the account's resting orders is a fire_refused trigger
    event with FireRefusalReason self_trade_prevented, whose ChildSeq
    names that order; the leg stays armed. RejectReason and order error codes
    read the new SELF_TRADE_PREVENTED code, which no request is answered with.

Changed

  • A trigger the halted market refuses reads FailureReason (and a refused
    fire FireRefusalReason) market_halted on servers on this contract; it
    used to read unknown(212). The SDK has no special case for 212, and any
    unknown reason still reads as unknown(<n>).
  • Docs: a buy sized by a quote amount takes attached risk (no SDK guard ever
    refused it). Order.CumNotional, CumQuote and QuoteUsed are exact when
    the pair's base quantity scale is at most 9, and can exceed the settled
    quote by less than 1e-18 per fill above tha...
Read more

v0.5.1

Choose a tag to compare

@aiiven aiiven released this 02 Nov 14:04
7e36d1d

Git tag: v0.5.1. Released 2026-11-02.

What a trading bot gains. A sell order can carry an attached trailing
stop again. On a sell order the trailing stop buys back, and the server now
requires its maximum buy-back price; TrailingStopInput.LimitPrice sends it.

Breaking changes

  • None in the SDK API.

Fixed

  • TrailingStopInput.LimitPrice sets an attached trailing stop's buy-back
    limit price, the most its exit pays per unit, which also sizes the funds it
    reserves. A sell order's attached trailing stop requires it, and a buy
    order's must leave it nil; creates, previews and batch creates check this
    before sending. It must be positive and at least ActivationPrice when both
    are set. Modify and batch replace send it as given, and the server applies
    the side rule there. Order reads do not return it yet.

v0.5.0

Choose a tag to compare

@aiiven aiiven released this 02 Nov 13:56
5933c45

Git tag: v0.5.0. Released 2026-11-02.

What a trading bot gains. An attached take-profit, stop-loss or trailing
stop now says when it starts protecting the position: its trigger events
include armed, once, when the parent order's first fill makes the leg live.
A bot can wait for it instead of polling the leg's status. Three new error
codes are final refusals: the request did not apply, so do not resend it
unchanged.

An environment reports armed events and the new codes once it runs this
contract: devnet first, then testnet after its next upgrade.

Breaking changes

  • None in the SDK API.

Added

  • Trigger events decode the new armed event type: an attached take-profit,
    stop-loss or trailing-stop leg reports it once, when its parent order's
    first fill makes the leg live (or when a leg paused before that fill
    resumes). It is not terminal. Triggers.ListEvents accepts "armed" as its
    event type filter. Attached trailing stops still report activated when
    they start tracking.
  • Error codes AUTH_SUBACCOUNT_OWNER_ROLE_LOCKED (the sub-account's owner
    cannot be invited, re-roled or removed),
    ERROR_CODE_TRIGGER_SYMBOL_MISMATCH (modify, pause or resume named a listed
    pair other than the trigger's own; name the trigger's pair or omit it) and
    the balance reads' ERROR_CODE_INVALID_SUBACCOUNT_ID (a zero or malformed
    sub-account ID).
  • Generated messages add Subaccount.removed (real-time sub-account updates
    only: the caller lost access, so drop the sub-account),
    TrailingStopPolicy.limit_price_ticks, Checkpoint.opening_value_usd,
    ListMyRewardAwardsResponse.awards_may_change and the Swap reason
    MAX_ORDER_QUANTITY, and the trade WebSocket protobufs follow binary schema
    34.

Server behaviour on this contract

  • Batch replace amends an order in place, keeping its order ID and queue
    priority, when an item keeps the price, does not raise the total quantity
    and keeps the client order ID. Otherwise it replaces the order under a new
    order ID.
  • An attached trailing stop on a selling order buys back, and the server now
    requires its maximum buy-back price. This SDK's AttachedRisk.TrailingStop
    does not send that price yet, so place a selling order with only take-profit
    and stop-loss legs until a later release adds it. A buying order's attached
    trailing stop is unchanged.
  • Ladder outcomes: a ladder is completed once no child order remains open and
    at least one reached the book; it is failed only when every child order was
    rejected before reaching the book.

v0.4.0

Choose a tag to compare

@aiiven aiiven released this 02 Nov 10:07
fb94c53

Git tag: v0.4.0. Released 2026-11-02.

What a trading bot gains. An order now says why it ended, in the same
words everywhere. A rejected order's RejectReason is the error code the
order write API returns for the same refusal, and a canceled order's
CancelReason says why it was canceled, on order reads and on the private
order stream alike. Before, the numeric reason used the matching engine's own
numbering, which clashed with the API's error codes. OrderbookData.Available
tells a bot when a book's levels are unknown rather than empty, so it does not
quote into a book that is being rebuilt. Trigger.Version picks out the
newest copy of a trigger, and nine new error codes are final refusals: the
request did not apply, so do not resend it unchanged.

This release works on devnet now, and on testnet after testnet's next upgrade.

Reason labels in this SDK. RejectReason is the orders.v1.ErrorCode
name without its ERROR_CODE_ prefix, for example POST_ONLY_CROSS.
CancelReason is the orders.v1.CancelReason name without its
CANCEL_REASON_ prefix, in lowercase, for example user_request. The Python
and Rust SDKs format these labels differently.

Breaking changes

  • Client.Whiteboard, Client.Polychart and Client.Layout are removed,
    with codecs.BoardAudienceFromLabel and codecs.BoardRoleFromLabel.
  • The generated orders.v1.Order loses TerminalReasonCode and
    TerminalReason, and the generated privatews.v1.OrderEvent loses
    ReasonCode. Read RejectReason and CancelReason instead.
  • models.OrderEvent.ReasonCode is replaced by RejectReason and
    CancelReason.
  • SubAccounts.Get no longer takes includeBalances.

Breaking

  • Client.Whiteboard, Client.Polychart and Client.Layout are removed,
    because those APIs are no longer part of the public API.
  • codecs.BoardAudienceFromLabel and codecs.BoardRoleFromLabel are
    removed with them.
  • The generated orders.v1.Order loses TerminalReasonCode and
    TerminalReason, and the generated privatews.v1.OrderEvent loses
    ReasonCode. Their numbers used the matching engine's own numbering, which
    collides with ErrorCode. Read the typed RejectReason
    (orders.v1.ErrorCode) and CancelReason (orders.v1.CancelReason)
    instead, or the decoded labels below.
  • models.OrderEvent.ReasonCode is replaced by RejectReason and
    CancelReason. A rejected order's event names its refusal as the order
    write API does (for example POST_ONLY_CROSS). A canceled order's event
    names why it ended (for example user_request), and so does the replaced
    event of the order a replace ended (replaced). Both are empty otherwise.
  • SubAccounts.Get no longer takes includeBalances: a sub-account read no
    longer returns balances. Read them with Balances.List and the sub-account ID.

Added

  • Order.RejectReason and Order.CancelReason, on order reads and on the
    private order stream's snapshot and unit orders. A rejected order's
    RejectReason is the ErrorCode name the order write API returns for the
    same refusal, without its ERROR_CODE_ prefix. A canceled order's
    CancelReason is a lowercase label such as user_request, ioc_remainder,
    stp_expire_maker, replaced, gtd_expired or account_repair. Both
    are empty for every other status. A value newer than this SDK decodes as
    UNKNOWN_ERROR_CODE(N) or unknown(N).
  • decode.OrderCancelReasonLabel names an orders.v1.CancelReason.
  • OrderbookData.Available, from Orderbook.Get and managed order book
    subscriptions. False means the book is being built or was invalidated: its
    levels are unknown, not empty, so request the snapshot again later. An
    environment that does not serve this release yet reports false for every
    book.
  • Trigger.Version: 1 for a trigger's first state, higher for every later
    state change. Keep the copy with the highest version.
  • New order error codes surface as errors.APIError with that code. Each
    has a known outcome: errors.IsRetryable and
    errors.MutationOutcomeUnknown are false, so do not resend the same
    request unchanged.
    • ERROR_CODE_ATTACHED_LEGS_EXCEEDED: the order already carries every
      attached leg it may hold, so another attached leg was refused.
    • ERROR_CODE_FEE_ASSET_INVALID: the trigger's fee asset was not valid.
    • ERROR_CODE_FEE_CEILING_INVALID: the trigger's maximum fee rate was not
      valid.
    • ERROR_CODE_UNSUPPORTED_FIELD_SET: the trigger set a field that must be
      left unset.
    • ERROR_CODE_TRIGGER_FIRE_LIMIT_REACHED: the trigger could not fire
      again.
    • ERROR_CODE_CONDITION_FLAGS_INVALID: the trigger's condition flags were
      not valid.
    • ERROR_CODE_CONDITION_PARAMETER_SET: the trigger set a condition
      parameter its condition does not take.
    • ERROR_CODE_TWAP_CAPACITY_REACHED: the market had no room for another
      TWAP order. It is a capacity refusal, not a rate limit.
    • ERROR_CODE_CHILD_ORDER_INCONSISTENT: the trigger's child order did not
      match the order the trigger requested, so the trigger failed and its
      child order was canceled. Read the trigger and the child order to see
      their final state.

v0.3.0

Choose a tag to compare

@aiiven aiiven released this 31 Oct 06:21
0485894

Git tag: v0.3.0. Released 2026-10-31.

What a trading bot gains. Trade, fill, transfer and trigger-event streams
now deliver every event; before, all but one event of each batch was lost.
MarketData.GetSpotConfig returns a typed config with each pair's order
limits, including the new cap on one market order's notional, so a bot can
size orders before it sends them. Rejections say more: a duplicate client
order ID names the order that already holds it, a clock-skew rejection is the
retryable errors.TimestampSkewError, and an unsupported call is
errors.NotImplementedError. Replacement orders report the quantity they
inherited, and slippage caps match what the API accepts.

This release works on devnet today, and on testnet after testnet's next
upgrade, which brings the new private order stream.

Breaking changes

  • The batched trade, fill, transfer and trigger-event streams emit each event,
    and the single-event decoders (decode.MarketTradeFromBytes,
    UserTradeFromBytes, LedgerTransferFromBytes, TriggerEventFromBytes)
    are replaced by their ...BatchFromBytes versions.
  • decode.SpotConfigFromProto and GetSpotConfig return an error for a spot
    config they cannot decode instead of an empty config.
  • Connect unimplemented maps to errors.NotImplementedError instead of
    errors.APIError.

Added

  • SpotPair.MaxMarketNotionalQuote and PairConstraints.MaxMarketNotionalQuote:
    the largest notional of one market order in quote units, valued at a buy's
    protection price or a sell's reference price. Larger orders are rejected
    with ERROR_CODE_MAX_NOTIONAL. Empty when the pair has no cap; a malformed
    value fails the spot config decode and makes the constraints unavailable.
  • MarketData.GetSpotConfig returns a typed models.SpotConfig: Assets
    (models.SpotAsset), Pairs (models.SpotPair: IDs, assets, scales, tick
    and step size, minimums, orderbook buckets, listing times, status labels
    such as halted, default slippage and reference drift), TsSec and the
    order limits. Each pair has MaxLimitQtyBase, MaxMarketQtyBase and
    MaxOrderNotionalQuote (decimal strings, empty when the pair has no
    maximum) and MaxOpenOrdersPerPair; the config has MaxOpenOrdersTotal.
    The open-order counts are the venue's defaults for a typical account, zero
    when not published; an account may have a lower limit of its own. Raw
    remains the proto-JSON payload Catalogs.HydrateSpotConfig accepts.
  • PairConstraints exposes the same limits (MaxLimitQtyBase /
    MaxLimitQtyScaled, MaxMarketQtyBase / MaxMarketQtyScaled,
    MaxOrderNotionalQuote, MaxOpenOrdersPerPair) and MaxQuoteSlippage /
    MaxQuoteSlippageTicks, the largest absolute slippage cap an order
    accepts. Catalogs.MaxOpenOrdersTotal() returns the account-wide default.
    A malformed limit makes the constraints unavailable rather than guessed.
  • Order.InheritedCumQty: the filled quantity a replacement order inherited
    from its predecessors; CumQty minus it is what that generation executed.
  • BatchReplaceAdmissionItem.ActionTaken and
    BatchReplaceStatusItem.ActionTaken: replaced when a successor was
    admitted, amended for a cancel-only outcome with no successor.
  • APIError.ExistingOrderID and BatchCreateResultItem.ExistingOrderID name
    the order already holding the client order ID on a
    ERROR_CODE_CONFLICT_DUPLICATE_CLIENT_ORDER_ID rejection, when known.
  • errors.TimestampSkewError for the API-key TIMESTAMP_SKEW rejection,
    whether sent as a Connect error or as the gateway's JSON or problem JSON
    body ({"code":"TIMESTAMP_SKEW"}). It carries the HTTP status.
    errors.IsRetryable reports true: the request changed nothing and a retry
    signs it again.
  • errors.NotImplementedError for Connect unimplemented and bare HTTP 501
    responses. A bare 404 is still errors.RouteNotFoundError.
  • LedgerTransfer.TransferID: the unsigned 128-bit decimal transfer ID both
    legs of a transfer share.
  • A trailing stop's TriggerDetails.TriggerPrice is its current threshold
    once armed.
  • realtime.SubscribeProtoBatch, services.SubscribePublicProtoBatch and
    services.SubscribeAccountProtoBatch subscribe to channels whose
    publications batch events.

Changed

  • Breaking: MarketData.SubscribeTrades, Trades.Subscribe,
    Transfers.Subscribe and Triggers.SubscribeEvents decode the batched
    publications the realtime channels now send and emit each event in order.
    Previously a batch decoded as a single event and the rest were lost. The
    single-event decoders decode.MarketTradeFromBytes,
    decode.UserTradeFromBytes, decode.LedgerTransferFromBytes and
    decode.TriggerEventFromBytes are replaced by MarketTradeBatchFromBytes,
    UserTradeBatchFromBytes, LedgerTransferBatchFromBytes and
    TriggerEventBatchFromBytes.
  • Breaking: decode.SpotConfigFromProto returns an error for a response
    it cannot decode instead of an empty config; GetSpotConfig returns it.
  • Breaking: Connect unimplemented responses map to
    errors.NotImplementedError instead of errors.APIError with code
    unimplemented.
  • MarketOverview.CreateSubscription with Symbols drops other markets from
    live and buffered publications too, not only from the snapshot.
  • Triggers.Modify and Triggers.Resume no longer require a symbol. Pass nil
    for symbol and symbolID to target the trigger's own market; a symbol,
    when set, must be that market. An API key limited to specific markets must
    still pass it.
  • A sell market order accepts MaxSlippageBps 1 to 9999; a buy still accepts
    10000. An attached trailing stop accepts 1 to 9999 on either side, and
    Triggers.Modify accepts 1 to 9999 (0 still clears). The backend rejects
    10000 on these with MAX_SLIPPAGE_INVALID.

Internal

  • sdk-capabilities.json no longer carries publicDescriptorSha256 or generatedAt, so a proto publication that only changes gen/ and manifest.json no longer makes it stale; manifest.json stays the single source of the descriptor hash.

v0.2.0

Choose a tag to compare

@aiiven aiiven released this 31 Oct 02:53
b807802

Git tag: v0.2.0. Covers every change since v0.1.0-alpha.56.

Versioning

  • The Go, Python and Rust SDKs now share one version number and are released
    together, starting at 0.2.0. Versions are plain SemVer: Go tags are
    vMAJOR.MINOR.PATCH (v0.2.0), with no alpha/a suffix. Until 1.0.0
    a minor release may change the API; a patch release does not.
  • Install with go get github.com/Fabric-Labs/polyester-sdk-go@v0.2.0. The
    repository is public, so GOPRIVATE / GONOSUMDB settings are no longer
    needed. The older v0.1.0aNN tags were never valid Go module versions;
    v0.1.0-alpha.56 is the previous release.

Added

  • Attached take-profit, stop-loss and trailing-stop legs and standalone
    stop-loss, take-profit and trailing-stop triggers can watch the market's
    index price: set RiskLegInput.TriggerPriceSource or
    TrailingStopInput.TriggerPriceSource, or pass triggerPriceSource to
    Triggers.Create, as "index" (or "last", the default when empty).
    Other values are refused with a validation error. Order reads now report
    each attached leg's TriggerPriceSource with the same labels, so a leg
    read back can be sent again unchanged.

  • CancelAllOrdersResult.ListingStatus: included, or
    not_retained_read_open_orders on a retry with the same request ID within
    120 seconds, which returns the original counts with an empty
    CancelledOrders. An empty retried list does not mean nothing was
    canceled; read open orders for current state.

  • CancelAllAfterResult.EffectiveScope (models.DeadManSwitchScope: account
    ID, symbol ID and side) describes the armed switch; nil when disabled.

  • GetOrderResult.ExecutionsComplete is true when the order's trades across
    every page add up to its filled quantity, and false while a recent
    execution is still being recorded.

  • LifecycleFlowSummary.IsDelayed is true when an open flow has made no
    progress for well beyond its expected step time.

  • realtime.OrderStale.OrderIDs names the orders that are temporarily not
    current when Reason is order_unavailable; the rest of the view stays
    current and units keep arriving. A later OrderStale replaces the reason
    and IDs, and consumers that join a running subscription receive them.

  • errors.AuthCodeTemporarilyUnavailable (AUTH_TEMPORARILY_UNAVAILABLE).

  • Spot config pairs carry the venue's per-order limits in SpotConfig.Raw:
    max_limit_qty_base, max_market_qty_base, max_order_notional_quote
    (each absent when the pair has no maximum) and max_open_orders_per_pair.
    Orders past the open-order limit are rejected with
    ERROR_CODE_MAX_OPEN_ORDERS_PER_PAIR.

Changed

  • Breaking: errors.IsRetryable reports false for every order error code
    ending in _OUTCOME_UNKNOWN (ERROR_CODE_ORDER_CREATE_OUTCOME_UNKNOWN,
    ERROR_CODE_ORDER_CANCEL_OUTCOME_UNKNOWN,
    ERROR_CODE_ORDER_MODIFY_OUTCOME_UNKNOWN,
    ERROR_CODE_TRIGGER_CREATE_OUTCOME_UNKNOWN,
    ERROR_CODE_TRIGGER_CONTROL_OUTCOME_UNKNOWN). It reported true for the
    order cancel and modify codes in v0.1.0-alpha.56. The change may still
    apply, so a blind retry can place a second order: read the order or trigger
    back first. This matches the TypeScript SDK.
  • errors.MutationOutcomeUnknown reports true for every order error code
    ending in _OUTCOME_UNKNOWN, read from the generated orders.v1 codes, so
    a code added to the API is covered when the SDK is regenerated. New in this
    release: ERROR_CODE_ORDER_CREATE_OUTCOME_UNKNOWN,
    ERROR_CODE_TRIGGER_CREATE_OUTCOME_UNKNOWN (a create sent but not confirmed
    in time may have been accepted) and
    ERROR_CODE_TRIGGER_CONTROL_OUTCOME_UNKNOWN (a trigger cancel, pause,
    resume or modify).
  • errors.IsRetryable reports true for AUTH_TEMPORARILY_UNAVAILABLE: the
    request changed nothing; retry the same request.

Fixed

  • The lifecycle reason DEPOSIT_SOURCE_NOT_CONFIRMED reads as
    deposit_source_not_confirmed instead of unknown_reason_400.
  • TestnetEnvironment and EnvironmentFromName("testnet") now use
    https://api.testnet.polyester.com and wss://api.testnet.polyester.com.
    Earlier versions pointed at api-testnet.polyester.com, which does not
    exist, so every testnet call failed with a DNS error. The devnet preset and
    transport.DefaultConfig now use the documented api.devnet.polyester.com
    host instead of api-devnet.polyester.ai.
  • The README no longer claims VIP.GetVIPStatus works with an API key: the
    API refuses API-key callers with permission_denied. VIP tiers, effective
    spot fees and trading rate limits do work with an API key.
  • The User-Agent header reports this SDK's module version
    (polyester-sdk-go/v0.2.0). Earlier versions reported the version of the
    application that imported the SDK.
  • README documentation links point at the public developer docs on
    polyester.com.

v0.1.0a55

Choose a tag to compare

@aiiven aiiven released this 26 Oct 22:05
d6a037b

Changed

  • Breaking: CreateOrderRequest.AttachedRisk is *models.AttachedRiskInput
    instead of map[string]any; the map was always rejected.
  • Breaking: codecs.ModifyOrderToProto takes a new newAttachedRisk *models.AttachedRiskInput parameter after newQty, and
    codecs.BatchReplaceItemToProto encodes BatchReplaceItem.NewAttachedRisk.
    Pass nil to keep an order's attached risk unchanged.
  • Breaking: Orders.Subscribe uses the private WebSocket and returns
    *realtime.Subscription[realtime.OrderStreamEvent] instead of
    *realtime.Subscription[models.Order]. It returns at once and reports the
    handshake as OrderStreamConnected. The previous order realtime channels,
    including the batch-replace order channel, are retired; use
    Orders.GetBatchReplaceStatus and the order stream's revisions for
    batch-replace progress.
  • Breaking: decode.OrderFromBytes, the decoder of the retired order
    realtime publications, is removed. Use decode.OrderFromProto.
  • A sell trailing_stop create given a limitPrice is refused with a
    validation error instead of ignoring it: only a buy has a maximum price.
  • Trigger create and modify refuse both MaxSlippageTicks and
    MaxSlippageBps together (previously one silently won), and a trailing
    stop's MaxSlippageBps is limited to 1 to 9999 on either side.
  • Breaking: codecs.ModifyTriggerOptions.LimitPrice is removed: a
    trigger's child limit price is fixed at create, and the server refuses
    any change to it. Cancel the trigger and create a new one instead.
  • Breaking: trading prices use 9 decimal places. codecs.PriceTickScale
    and the new models.PriceTickScale are 9: one price tick is 1e-9 quote
    units. This applies to order, trigger, trailing, activation, orderbook,
    trade, candle, market-overview and tick-size values. Raw tick values
    built for the previous 6-decimal scale are 1,000 times too small; scale
    them by 1,000 or pass decimal strings. Market-overview USD amounts stay
    at 1e6.
  • Breaking: MaxSlippageTicks on market orders, triggers, trigger
    modifications and trailing-stop reads is int64, matching the 64-bit
    price-delta field in the API.
  • Candle and market-overview base volume now use the base asset
    market_data_volume_scale from GetSpotConfig. Primary candle prices
    use the fixed 9-decimal price scale.
  • Composite reference-candle OHLC uses the pair reference_price_scale.
    GetCandlesWithReference and GetCandlesColumnsWithReference request
    that series. MarketOverviewEntry.Volume24HBase is the decoded decimal
    when the catalog scale is known; Volume24HBaseScaled stays the integer.

Added

  • Orders accept attached take-profit, stop-loss, trailing-stop and OCO
    policies: CreateOrderRequest.AttachedRisk, the new Orders.ModifyWith
    (ModifyParams.NewAttachedRisk), and BatchReplaceItem.NewAttachedRisk
    take a typed models.AttachedRiskInput. Create and modify results expose
    the configured legs' trigger IDs.
  • Trigger events label standalone trailing-stop activation as activated,
    and TriggerEventTypeFromLabel accepts activated as a filter.
  • realtime.Client.SubscribeOrders streams an account's orders over the
    private WebSocket (/v1/ws/private, subprotocol polyester.v1.proto).
    It delivers typed realtime.OrderStreamEvent values: OrderSnapshot
    (the full live view, installed whole), OrderReady (the stream reflects
    every acknowledgement given before the subscribe; wait for it before
    trusting that a missing order does not exist; once per server
    subscription, so again after a resubscribe or reconnect), OrderUnit
    (changed orders, removed order IDs, and order events and command outcomes
    as models.OrderUnitEvent), OrderStale, OrderStreamConnected,
    OrderStreamDisconnected and OrderStreamError. Sequence gaps, expiring
    tokens, heartbeat loss and reconnects resume from the last applied
    position; subscriptions of the same account share one server
    subscription.
  • realtime.ErrClientClosed is returned by SubscribeOrders (and
    Orders.Subscribe) after Client.Close. A Close that races a
    subscribe closes the new stream.
  • errors.RealtimeError carries Code (the server's request error, for
    example FORBIDDEN) and CloseCode (for example 4403) for the private
    order stream.
  • Standalone trailing stops can buy. Triggers.Create with
    trigger_type trailing_stop accepts side buy; its limitPrice is
    the buy's maximum price, the most the child pays per unit, encoded at 9
    decimal places. It is required for a buy, must be positive and at least
    the activation price. Trigger reads project a buy's maximum price as
    Trigger.LimitPrice; Trigger.Side and Details.TroughPrice show the
    side and the lowest price since arming.
  • Stop-loss and take-profit market children carry a slippage cap:
    CreateTriggerOptions.MaxSlippageTicks or MaxSlippageBps is encoded on
    the market child (previously it was dropped and the pair default
    applied). At most one may be set; a buy accepts 1 to 10000 bps, a sell 1
    to 9999; a limit child refuses a cap. Get, list and the trigger stream
    expose it as Trigger.MaxSlippage / Trigger.MaxSlippageBps. A buy
    stop-loss or take-profit may use a market child.
  • Orders.CancelAll returns CancelledOrders (order ID and client order
    ID, oldest first, at most 200), TotalCancelled and Truncated.
  • MarketData.GetTradesAfter walks a symbol's trades gap-free by match ID
    and returns CompleteThroughTradeID, NextAfterTradeID and EpochEnds.
    Start at "0"; both watermarks are always decimal match IDs, "0"
    included, so an empty first page's cursor is valid for the retry.
  • VIPStatus.SettledVolumeQuality and AverageAopQuality report how
    complete each rolling 30-day metric is.
  • errors.MutationOutcomeUnknown reports true for
    ERROR_CODE_ORDER_CANCEL_OUTCOME_UNKNOWN and
    ERROR_CODE_ORDER_MODIFY_OUTCOME_UNKNOWN; errors.IsRetryable reports
    true for them and for ERROR_CODE_ACCOUNT_REPAIRING.

Fixed

  • Labels for enum values newer than this SDK version (for example a new
    trigger failure reason) read unknown(<n>) instead of panicking.
  • Account-scoped subscriptions given no account ID now use the client's
    DefaultAccountID value instead of formatting its pointer.
  • Order reads no longer report an attached-risk leg whose state is
    not_configured; the server sends that state for a leg the order
    does not have.

v0.1.0-alpha.56

Choose a tag to compare

@aiiven aiiven released this 26 Oct 22:29
b8bca16

Changed

  • Release tags now use Go module versions (v0.1.0-alpha.56), so
    go get github.com/Fabric-Labs/polyester-sdk-go@v0.1.0-alpha.56 records
    that version. Earlier tags such as v0.1.0a55 resolve to pseudo-versions.

Fixed

  • Trigger reads report a buy trailing stop's child as OrderType limit
    (time in force ioc) at its maximum price, as the server places it;
    v0.1.0a55 reported market.