Changelog
Notable changes to the Arca platform, SDKs, and API. Breaking changes are marked with a ⚠️ icon.
2026-04-29
- P&L and aggregation responses now expose mid-price freshness.
/objects/pnlresponses include anendingMidPriceobject and/objects/aggregateresponses include amidPriceobject. Both carrymarketDataAsOf(the timestamp of the freshest mid the engine consulted),ageSeconds,source("snapshot"|"cache"|"none"),staleAfterSeconds, and a derivedstaleflag. Clients can detect when upstream market data has stalled and surface a freshness indicator instead of silently rendering frozen valuations. Internal records remain the authority for equity computation; this change is purely informational. - Sim-exchange writes are now EIP-712 signed. Every per-account sim-exchange write (PlaceOrder, CancelOrder, SetLeverage, Withdraw, Deposit, LiquidateAll, DeleteAccount) now carries an EIP-712 envelope signed by the account's bound wallet, matching production Hyperliquid behaviour. Operator RPCs (DeleteAccountsByRealm, ResetAll, SweepFees, FundAccount) sign with a separate platform operator wallet verified against an env-injected allowlist. This change is internal — the SDK and REST surface are unchanged for builders. The rollout proceeds in shadow mode by default; flipping
SIM_REQUIRE_SIGNED_WRITES=trueon sim-exchange enables enforcement and any unsigned/invalid request is rejected withSIGNATURE_MISSING,SIGNATURE_INVALID,WALLET_NOT_BOUND,NONCE_REUSED,TIMESTAMP_SKEW, orOPERATOR_NOT_ALLOWED.
2026-04-28
- ⚠️ Realms: realm types are now
developmentorproduction. The legacydemo,testing, andstagingrealm types have been removed from the API, SDKs, CLI, and portal. Existing non-production realms are migrated todevelopment; new create requests must usedevelopmentorproduction. - History charts: V1 fallback retired. Equity and P&L history now serve both legacy-shaped
prefixrequests and currenttarget/kindrequests from the V2 snapshot read path. The old delta/path-cache fallback and object-balance snapshot writer have been removed.
2026-04-27
- Swift SDK: operation type decoding is forward-resilient.
OperationTypenow includesvenue_closeand preserves unknown future operation type strings asunknown(String), so operation-carrying REST responses and WebSocket events continue decoding when the platform adds a new operation type. - WebSocket mids: batch-level freshness.
mids.updatedevents now expose a single polishedmarketDataAsOftimestamp for the oldest mid in the update instead of sending per-coin source-time diagnostics by default. - History charts: per-bucket position revaluation for exchange objects. Equity and P&L history endpoints now mark-to-market open exchange positions at every bucket, not just at fill / funding events. Charts that previously stayed flat between cash-impacting events now move with the underlying market mid the same way the live equity panel does. Buckets where a position lacks a mid are returned with
status: "incomplete". Read-time only — no schema changes, no backfill required. - History charts: denser default resolutions for longer ranges. Explorer history charts now request more samples and the aggregation ladder includes a new
4hrung, so expanded charts target5mfor 1D,1hfor 1M,4hfor 3M, and1dfor 12M. The consolidated history path projects stored balance-change snapshots into the requested bucket size at read time, so the new rung does not require a separate per-resolution4hbackfill. - SDK: V2 equity and P&L chart streams recover from chart snapshot pushes.
watchEquityChartandwatchPnlChartnow preserve V2 history metadata (status, resolution details, and server timing) and subscribe to the newchart.snapshot.updatedWebSocket signal. On reconnects or delivery-sequence gaps, the SDK refetches the visible V2 history window so missed sealed/carried buckets converge to the server rows instead of relying only on local rollover guesses.
2026-04-20
- ⚠️ SDK:
orderBreakdownliquidation estimate is now cross-margin.Arca.orderBreakdown'sestimatedLiquidationPricepreviously used an isolated single-position formula that ignored every other position and the rest of the account's collateral, so the value drifted from the actual liquidation price the user would see post-fill. It now uses the same cross-margin formula the sim-exchange backend uses (marginAvailable = equity − maintenanceMargin, thenliq = price ∓ marginAvailable / size) and applies the same merge rules to any existing same-coin position (same-side blends entry, opposite-side reduces or flips). To compute this faithfully,OrderBreakdownOptionsnow requires anaccountContextfield (account equity, maintenance margin from positions in other coins, and any existing same-coin position) whenevermaintenanceMarginRateis provided. This is a source-breaking change for existing callers usingmaintenanceMarginRate; callers that don't need a liquidation estimate can omit both fields. In Swift, use the new initializer overload that accepts bothmaintenanceMarginRateandaccountContext.
2026-04-16
- SDK:
orderBreakdownestimates liquidation price. TheArca.orderBreakdownfunction now returns anestimatedLiquidationPricewhen the new optionalmaintenanceMarginRateparameter is provided. This isolated estimate assumes the order is the only open position. To support this,ActiveAssetData(returned bygetActiveAssetDataandwatchMaxOrderSize) now includes amaintenanceMarginRatefield, populated from the asset's base margin tier or a global default. This is fully backward-compatible: omitting the new parameter yields the same breakdown as before. - SDK:
watchMaxOrderSizeresolves dynamicmaintenanceMarginRate.ActiveAssetData.maintenanceMarginRateemitted bywatchMaxOrderSizepreviously defaulted to"0.03"on every recompute, which fed an incorrect value intoorderBreakdown's liquidation estimate for tiered assets (e.g. BTC, where the true base MMR is"0.01"). The TypeScript and Swift SDKs now auto-fetch the per-asset MMR once viagetActiveAssetDataand thread it through every recomputation. Callers can also passmaintenanceMarginRatedirectly viaMaxOrderSizeWatchOptionsto skip the lookup. - Swift SDK: bounded buffers on real-time watch streams. All snapshot-style watch streams (
watchPrices,watchExchangeState,watchObject,watchObjects,watchAggregation,watchMaxOrderSize,watchCandleChart) now use abufferingNewest(1)policy on their underlyingAsyncStream. If a consumer is slower than the producer (for example, hopping toMainActoron every tick to update a SwiftUI@Published), intermediate updates are dropped in favor of the latest value rather than accumulating in memory. Previously, the default unbounded buffer caused linear memory growth (~700 MB OOM after 80 s of an idlewatchPrices()consumer with 392 coins).watchPricesadditionally skips the yield entirely when the incoming mids snapshot contains no actual change. TheSendableBox.onChangepush-based API remains available and is unaffected. - Market metadata:
logoSourcesarray.getMarketMetaandasset(coin)now include alogoSourcesarray with pre-rendered raster variants (128, 256, 512 width) in WebP and PNG formats. The existinglogoUrlstring remains for backward compatibility, now pointing to the 128px WebP. Use the new array to pick the smallest size that fits your rendering target, saving significant memory when rendering lists. - SDK:
watchPricesergonomics.arca.watchPrices()now accepts an options object:coinsnarrows the subscription to specific canonical market IDs (multiple narrow subscribers share one WebSocket subscription via set-union), andreadyTimeoutMsbounds the initial snapshot wait (rejects with the newWatchStreamReadyTimeoutError). The returnedPriceWatchStreamexposesget(coin)andgetNumber(coin)convenience accessors..pricesnow returns a fresh object reference on every tick, so reference-equality checks (React state, Zustand selectors) correctly detect changes. The legacy positionalwatchPrices(exchange)call still works.WatchStream.ready()also accepts atimeoutMsargument so app startup can degrade gracefully when the backend is unreachable. The React hookuseArcaPricesnow surfaces'reconnecting'status and accepts all the same options. - Authentication: Google-only Auth. Email and password authentication has been removed from the platform in favor of a simpler, more secure Google-only OAuth flow. The
/api/v1/auth/signupand/api/v1/auth/signinendpoints have been removed. Use/api/v1/auth/googlefor all authentication. The CLI no longer supports the--no-browserflag, as authentication now strictly requires a browser for the Google OAuth consent screen. - Swift SDK: diagnostics & structured logging.
Arca.initnow acceptslogLevel(defaults to.warning) and an optionallogHandler. The SDK emits records to Apple's unified logging system (subsystemio.arcaos.sdk) and, if set, to the host handler — making it easy to forward to Datadog, Sentry, Crashlytics, or a custom backend. REST errors inside background tasks (watch snapshots, gap-recovery refetches, candle retries, CDN fallbacks) that were previously swallowed bytry?now surface as warning-level records. WebSocket lifecycle events — server errors, delivery gaps, reconnect backoff, heartbeat stalls, token refresh failures — are also logged. Builders upgrading will immediately see previously hidden warnings in Xcode. See Logging & diagnostics for Datadog, Sentry, Crashlytics, and custom adapter examples. The threeprint("[ArcaSDK] …")sites have been replaced by structured records.
2026-04-21
- SDK: true historical equity for equity-anchored charts. The
watchPnlChart(anchor: 'equity')method in both the Swift and TypeScript SDKs now populates thevalueUsdfield using the server's authoritative historicalequityUsdfor each point, rather than applying a fixed offset derived from current live equity. This provides a true point-in-time portfolio value view that accurately reflects historical balances and flows.
2026-04-15
- SDK: cached market metadata lookup. New
asset(coin)method on both TypeScript and Swift SDKs returns theSimMetaAssetfor a canonical coin ID (symbol, display name, logo, leverage limits, fee scale, etc.). Metadata is lazily fetched on first call and cached for the session. UsepreloadMarketMeta()to warm the cache at startup, orrefreshMarketMeta()to force re-fetch after new assets are listed. Concurrent calls coalesce into a single API request. - Transfers: per-command fee override. The
transfer()SDK method,POST /api/v1/transferAPI endpoint, andarca transferCLI command now accept an optionalfeeOverrideparameter. Set to"0"to disable the $0.05 platform fee for a specific transfer, or any non-negative decimal for a custom fee. Only permitted in development realms. Production realms always use the standard fee. - WebSocket: real-time market trade streaming. New
subscribe_trades/unsubscribe_tradesWebSocket actions deliver a live trade tape per coin. Trades arrive as batchedtrades.batchmessages. SDK addswatchTrades(coins)which returns aTradeWatchStream, and lower-levelacquireTrades/releaseTrades/onTradeExecutedon the WebSocket manager.
2026-04-14
- Trading: Tiered margin tables support. Sim-exchange now dynamically enforces margin and leverage limits based on these tier definitions.
2026-04-09
- WebSocket: per-message compression enabled. All WebSocket connections now negotiate
permessage-deflatewith context takeover (RFC 7692). Repeated JSON structure compresses 3-5x with no SDK or client changes required. - WebSocket: batched candle delivery. The SDK now sends
batch: truewithsubscribe_candles, and the server coalesces allcandle.updatedevents in a tick into a singlecandles.updatedmessage. This reduces WebSocket frame count from N to 1 per batch.candle.closedevents are always sent individually. The SDK handles this transparently —onUpdatecallbacks still fire per candle. Raw WebSocket users can opt in by addingbatch: trueto thesubscribe_candlesmessage; without it, the old per-event format is used.
2026-04-08
- Trade summary: fee breakdown, funding totals, and position-level cost attribution.
tradeSummary()now returns per-fee-type breakdown (totalExchangeFees,totalPlatformFees,totalBuilderFees), cumulative funding (totalFundingPaid/totalFundingReceived), and anopenPositionCostsobject per market with costs attributed to the current open position using proportional close-out accounting. Existing fields are unchanged. - Swift SDK: new fields and methods. Added
platformFeeonSimFill,cumulativeFundingonSimPosition,getAssetFees(objectId:builderFeeBps:)for per-asset fee rates, andenableAutoTracking(operations:balances:exchange:)for optimistic UI updates. Also addedAssetFeeEntrytype. - Swift SDK: PaymentLinkView now uses WKWebView.
PaymentLinkView/.paymentLinkSheet()now usesWKWebViewinstead ofSFSafariViewController, enablingwindow.close()support forreturnStrategy: "close". - TypeScript SDK: aggregation revaluation includes perp entries.
revalueAggregation()now revaluesperpbreakdown entries using fresh mid prices, keeping aggregation equity in sync with per-object valuations between server pushes. - Platform: object creation response includes timestamps.
createObjectresponses now populatecreatedAtandupdatedAtimmediately, enabling deterministic ordering of newly created objects without waiting for background workflow completion. - Docs: clarified
fundAccountbehavior by realm type and documented thatwatchCandleChartcountis best-effort (sets time window, actual count depends on asset history). - Platform: realm listing now returns realms across all org memberships.
GET /api/v1/realmsnow returns realms from all of the builder's organizations, not just the first resolved org. Builders with multiple org memberships will now see all their realms. When a preferred org header is set, results are scoped to that org only. - API:
nextFundingTimenow populated on market tickers.MarketTicker.nextFundingTimeis now returned as a Unix-ms timestamp from the/api/v1/exchange/market/tickersendpoint and SDKgetMarketTickers()calls. - Fix: P&L chart no longer double-counts initial deposit. When a chart window started before the account's first deposit, the deposit was counted both in
startingEquityUsd(via leading-zero trimming) and in cumulative inflows, producing an inflated loss.getPnlHistorynow returns aneffectiveFromfield, andwatchPnlChartuses it to alignflowsSincecorrectly. Affects both TypeScript and Swift SDKs. - Fix: portal exchange positions now revalue on live mid prices. The portal's exchange detail panel previously displayed stale unrealized P&L from the sim-exchange snapshot. It now revalues cached exchange positions on every WebSocket mid-price update, matching the SDK's behavior.
2026-04-07
- Platform + API + Portal: builder operation signing keys. Builders can now register Ed25519 signing keys and sign API requests for cryptographic non-repudiation. New endpoints:
POST /api/v1/signing-keys(register),GET /api/v1/signing-keys(list),DELETE /api/v1/signing-keys/:id(revoke),POST /api/v1/signing-keys/:id/cancel(cancel pending),GET /api/v1/signing-keys/:id/events(audit log). The server verifiesX-Arca-Key-Id,X-Arca-Signature, andX-Arca-Timestampheaders and records signatures on operations. Signing is optional in this release; it will become required for production realms in a future release. A new portal page under Manage → Signing Keys provides key registration, revocation, and lifecycle visibility. Key lifecycle events are recorded in a hash-chained, tamper-evident audit log.
2026-04-06
- Objects + exchange processing: stricter object path validation and more robust venue account lookup. Object creation now rejects path segments containing whitespace or control characters, preventing malformed identities from entering the system, and exchange account resolution now accepts both
venueAccountIdand legacysimAccountIdmetadata when mapping sim-exchange events back to Arca objects. - SDK + streaming: candle WebSocket events now include optional delivery timestamps. Candle subscriptions still emit the same
coin,interval, andcandlepayload, and now may also includepublishedAt,platformReceivedAt, andwsSentAtfor delivery attribution and latency debugging. - SDK: client-side recovery key generation. New static method
Arca.generateRecoveryKey()creates a 12-word BIP-39 mnemonic and derives the Ethereum address at the standard BIP-44 path, entirely client-side. Usescrypto.getRandomValuesfor entropy and zeroes all intermediate key material after derivation. Recovery key docs now cover a two-path UX model: “use an existing wallet” (recommended) or “generate a new one”, with platform-specific backup guidance for iOS, Android, and web.
2026-04-05
- Explorer + SDK + API: path-level isolation zones. The explorer browse response now includes path entries and isolation metadata so the portal can mark boundary roots and paths contained within a boundary. A new
POST /api/v1/isolation-zonesendpoint andarca.createIsolationZone({ path })SDK method let builders declare an isolation zone before any object exists under that path, fixing the empty-path race for zone-first explorer workflows. - Explorer + SDK + API: Phase 1 audit evidence export. Operation detail now accepts
includeEvidence=true, returning journal-backed evidence, proof references, chain transaction metadata, and integrity annotations for a single operation. A newGET /api/v1/operations/exportendpoint exports the same evidence bundle across a realm and time range, the TypeScript SDK addsgetOperation(id, { includeEvidence: true })andexportOperationEvidence(...), and the portal Explorer now supports copy/download of per-operation JSON plus realm-scoped evidence export. - Objects: full withdrawals now terminate the object path. When a non-exchange Arca is fully withdrawn, its status becomes
withdrawnand the response includeswithdrawnAt. Withdrawn paths remain visible in history, show a zero-cliff in aggregation after the withdrawal timestamp, and cannot be reused for a new object generation. - Objects: deleted generations now expose tombstone
displayName. Object responses now include an optionaldisplayNamefield. Active objects usually leave it unset, while deleted objects receive a tombstone label likewallet.deleted.YYYY.MM.DD.SSSSSso explorer and version-history views can distinguish repeated deleted generations at the same canonical path. - SDK: custody contract integration. New methods for reading on-chain custody state (
getCustodyStatus,getBoundary,listBoundaries,listExchangeArcas), registering recovery keys (registerRecoveryKey), and preparing unsigned sovereignty transactions (prepareLockBoundary,prepareWithdraw,prepareAssignRecoveryKey, etc.). Recovery keys give users non-custodial control over their isolation boundaries: lock, unlock, withdraw, and emergency recovery. - API: custody endpoints. New REST endpoints for custody contract state:
GET /custody/status(full aggregated view including boundaries, exchange arcas, and venue halts),GET /custody/boundaries,GET /custody/exchange-arcas(with optionalboundaryIdfilter), andPOST /custody/recovery-key. The/custody/statusresponse now includescontractAddress,chainId, and all nested state in a single call. - ⚠️ Backend: balance ledger writes fully migrated to journal. All balance-affecting write paths in the worker service now commit exclusively through the unified journal (
journal_entries/journal_legs). Legacyarca_balance_ledgerwrites have been removed from all activities. All read paths (forensics, aggregation, explorer snapshots, balance ledger compatibility layer) have been migrated to source data from the journal tables.
2026-04-03
- Swift SDK: fixed live P&L chart discontinuity in
watchPnlChart. The live tail point now correctly accounts for deposits and withdrawals. Previously, the Swift SDK's flow accounting was non-functional — deposits appeared as profit and withdrawals as losses, causing a massive jump at the chart's live edge (especially visible withanchor: .equity). The fix uses server-authoritative cumulative flow values via the newflowsSinceparameter onwatchAggregation. - Swift SDK:
watchAggregationnow acceptsflowsSince. Pass an ISO 8601 timestamp to receive cumulative inflow/outflow values computed from that point forward.PathAggregationnow includescumInflowsUsdandcumOutflowsUsdfields. - SDK: reduced chart discontinuity on reload. Both TypeScript and Swift SDKs now trim trailing server-generated live points from historical chart data, preventing small jumps where the server's HTTP-time equity diverged from the WebSocket-time equity.
2026-04-02
- Market data: guaranteed sparklines via background pre-computation. Sparkline data is now pre-computed every ~5 minutes by a background process and stored in Redis. All tracked coins are always included — no more missing sparklines due to timeouts or computation pressure. The serving path is a single Redis read, making it faster and more reliable across all replicas. Sparkline data may be up to 5 minutes behind real-time; for live price information, use mid prices (
watchPrices) or candle subscriptions (subscribeCandles). - ⚠️ Sparklines:
intervalandpointsparameters removed. The sparkline endpoint now always returns 24 hourly close prices. The query parameters are still accepted for backward compatibility but ignored. Previously, requesting a non-default interval/points combination would return empty data because only the default (1h/24) was pre-computed. UsegetCandlesfor custom intervals. - Trading: TWAP (Time-Weighted Average Price) orders. Execute large trades over time by placing market orders at regular intervals. TWAPs support durations up to 30 days, configurable intervals (10s–1h), and automatic catch-up if slices are missed. New SDK methods:
placeTwap(),cancelTwap(),getTwap(),listTwaps(),getTwapLimits(). API endpoints:POST /api/v1/objects/{id}/exchange/twap,GET .../twap/{operationId},DELETE .../twap/{operationId},GET .../twaps. New event types:twap.started,twap.progress,twap.completed,twap.cancelled,twap.failed. Active TWAPs are automatically cancelled on account liquidation. - Market data: candle CDN publish schedule reduced to daily. The CDN publish workflow now runs at 00:05 and 00:35 UTC (retry window) instead of every 5 minutes. Missing closed chunks discovered during API reads are repaired asynchronously via a fire-and-forget checker that verifies GCS and enqueues a Temporal repair workflow when needed, with 30-minute cooldown deduplication.
2026-04-01
- Trading: deleted exchange accounts now disappear cleanly from live trading. The API no longer allows place/cancel order requests or live exchange reads against a soft-deleted exchange object ID. The portal also invalidates its trading caches when an exchange object is deleted, fixing the stale state where a just-deleted account could still show cached cash while reporting zero buying power.
- Market infrastructure: Bright Data-managed Hyperliquid proxy routing. The Hyperliquid
/infotransport now supports backend-managed Bright Data datacenter routing. Instead of hand-maintained proxy URLs, the backend can use a Bright Data API key to reconcile a zone, mint managed proxy identities, and feed them into the shared HL router with direct fallback and per-lane telemetry. The current rollout sends all Hyperliquid read traffic through the sharedarca_hl_read_onlyrotating zone first, so the direct Hyperliquid rate limiter is only consumed when the proxy path fails. - API: candle fetch cancellations and timeouts now use specific HTTP error types.
GET /api/v1/exchange/market/candles/{coin}no longer flattens every downstream market-data failure into502 EXCHANGE_ERROR. Client-aborted candle requests now return499 REQUEST_CANCELED, downstream deadline overruns return504 EXCHANGE_TIMEOUT, and502is reserved for genuine upstream failures. - SDK: equity-anchored P&L charts.
watchPnlChartnow accepts ananchoroption. Setanchor: 'equity'to shift the P&L chart so the live (rightmost) value equals the current account equity — a portfolio value view. Each point includes avalueUsdfield for the chart y-axis. The offset is stable during price movements; historical points never wiggle. Available in both the TypeScript and Swift SDKs.
2026-03-31
- Portal: default exchange selection now prefers the newest persisted account. When multiple active exchange objects are present, the portal now orders them by
createdAtdescending instead of raw path order, with a deterministicidtie-breaker. The SDK and API docs now also clarify thatlistObjectsandbrowseObjectsalways return authoritative timestamps for persisted objects, while the immediate create response may briefly leave those fields empty until async creation completes. - SDK: candle chart range loads now coalesce overlapping requests. Repeated
ensureRangecalls on the same candle chart stream no longer drop gesture-driven history loads while an earlier fetch is in flight. The TypeScript and Swift SDKs now merge overlapping pending ranges, and failed gaps stay retryable instead of being marked covered. This fixes charts that could appear frozen after rapid pan/zoom interactions. - Fix: repeated exchange order cancels now return deterministic API errors. Repeating
DELETE /api/v1/objects/{id}/exchange/orders/{orderId}now reuses the original cancel operation instead of surfacing an internal server error from a duplicate implicit operation path. Already-cancelled orders now return409 ORDER_FAILEDinstead of a generic upstream/internal-style failure. - Exchange state: removed the legacy 5s sim-exchange heartbeat. The sim-exchange no longer emits a periodic equity ticker that forced a full clearinghouse refresh every five seconds for active accounts. Structural exchange updates now come from mutation-driven account events and venue reconciliation. The TypeScript SDK, Swift SDK, and portal were hardened to refetch exchange state when an
exchange.updatednotification arrives without inlineexchangeState, so watch streams and explorer views still converge without relying on the old heartbeat. - Fix: aggregation watch
flowsSincenow accepts standard RFC 3339 timestamps. The platform had started requiring exactly six fractional digits forflowsSince, which caused valid client timestamps like2026-01-01T00:00:00Zand2026-01-01T00:00:00.000Zto be rejected when creating aggregation watches over HTTP or WebSocket. The parser now accepts RFC 3339 variants and normalizes them to UTC while responses continue to use the canonical microsecond format. - Fix: P&L chart no longer shows a momentary spike on deposits. The aggregation watch response now includes
cumInflowsUsdandcumOutflowsUsdfields, computed from the balance ledger. The SDK'sPnlChartStreamuses these server-provided values instead of tracking flows client-side fromoperation.updatedevents, ensuring equity and flow data are always derived from the same source. - Fix: P&L flow tracking no longer double-counts or misses flows. The
watchAggregationmethod now accepts an optionalflowsSinceparameter.watchPnlChartpasses the chart'sfromtime so the server computes cumulative flows over the entire chart window — eliminating the gap/overlap between historical and watch-creation time windows. - Market data: first-class HIP-3 (builder-deployed perp) coverage. All HIP-3 markets now receive the same trade, candle, and sparkline data coverage as native Hyperliquid perps. Previously, HIP-3 markets could have gaps in sparkline and candle data because their trade feeds were demand-driven. Now all discovered markets — native and HIP-3 — are automatically subscribed to trade and order book streams at startup. The fallback data provider also supplements trades for markets that the primary data source hasn't seen, closing coverage gaps during data source transitions.
- Perf: Payment link page now loads instantly. The
/pay/page is now a self-contained static HTML file instead of loading the full portal SPA. Previously, opening a payment link downloaded ~1.4MB of JavaScript (React, charts, markdown, OAuth, etc.) before showing a simple payment card. The standalone page is ~16KB with zero external dependencies and loads in under 200ms. All features preserved: branding, dark mode, polling, return strategies. - Platform: white-label payment portal branding. Realms can now configure custom branding for the payment portal via
PATCH /api/v1/realms/:id/settingswith abrandingobject. Supported fields:displayName,accentColor(hex),logoUrl(HTTPS),hideExpiryTimer, andenvironmentBannerText. When configured, the payment page renders the builder's branding instead of the default Arca logo and name. The “Powered by Arca” footer always remains. - Swift SDK: fix
watchCandleCharthang on rapid interval switching. Switching candle intervals quickly (e.g. tapping 1D → 1M → 3M) could cause the SDK to hang indefinitely when loading large candle counts. The cancelled task's CDN chunk fetches were falling back to the REST API instead of exiting, saturating the HTTP client queue and blocking the new request. Cancelled tasks now bail out immediately at every async boundary. - SDK:
watchPnlChart()andwatchEquityChart()now documented. Live chart streams for P&L and equity are now fully documented in the SDK reference with usage examples.watchPnlChartmerges historical P&L data with real-time aggregation updates and automatically adjusts for deposits, withdrawals, and transfers that cross the path boundary — no client-side workarounds needed. Both methods are available in TypeScript and Swift SDKs. - Platform: atomic event delivery for related events. Operations that produce multiple related events (e.g.
operation.updated+balance.updated) now deliver them as a single atomic batch over the WebSocket connection. Previously, these events were published as separate messages with potential inter-message gaps. Affects deposits, withdrawals, transfers, and deletions. - SDK:
watchEquityChart()cache invalidation on deposit. The equity chart stream now detects when live equity diverges significantly from the last historical data point (e.g. after a deposit) and automatically invalidates the cached history so subsequent chart opens fetch fresh data. - Fix:
resultingPosition.leveragein fill events. Theleveragefield infill.recordedevents andlistFillsresults now correctly reflects the per-coin leverage setting used at fill time. Previously, it always returned1for new positions because the worker defaulted to the pre-fill platform leverage instead of reading the venue's actual leverage. - Market metadata:
displayName,isHip3,deployerDisplayName.getMarketMetanow returns three new fields per asset:displayName(human-readable name, e.g. “Crude Oil” for BRENTOIL),isHip3(whether the asset is a HIP-3 deployer market), anddeployerDisplayName(the deployer's full name for HIP-3 assets). Available in TypeScript, Swift, and CLI. - Docs: sparklines freshness model. SDK and API docs now document the sparkline freshness guarantee: data is pre-computed every ~5 minutes with all tracked coins always included. For real-time prices, use mid prices or candle subscriptions.
- Fix:
watchMaxOrderSizenot updating after position close. The investment slider / max order size stream was not reflecting freed margin after selling a position. A prematureexchange.updatedevent emitted at order placement time poisoned the event bus dedup cache, silently suppressing the real post-fill event that carried the updated exchange state. The TypeScript SDK also lackedwatchPath/unwatchPathcalls (the Swift SDK already had them), which prevented event delivery on standalone WebSocket connections. Both issues are now fixed.
2026-03-30
- Market metadata:
logoUrlandfeeScaleadded.getMarketMetanow includeslogoUrl(CDN URL for the asset logo) andfeeScale(HIP-3 fee multiplier, defaults to 1.0 for standard perps). Together with the previously addeddisplayName,isHip3, anddeployerDisplayName, the market meta response now provides full display metadata for all assets.displayNameandlogoUrlare curated and managed via the admin panel. Available in TypeScript, Swift, and CLI. - SDK: CDN candle history enabled by default. The
candleCdnBaseUrlconfig now defaults to the production CDN. Historical candle data for longer intervals (1d,4h,1h) is now served from the CDN automatically — no configuration needed. Passnullor""""to disable CDN and use the REST API exclusively (e.g. for local development). Affects both TypeScript and Swift SDKs. - Fix:
watchCandleChartsparse initial data handling. When the initial fast-path fetch (skipBackfill) returns fewer candles than expected, the SDK now detects this as sparse data and retries with a full backfill in the background. Previously, a single cached candle would mark the entire requested range as covered, preventing further loads. The retry now also requires the result to have more candles than the initial load to count as successful, preventing premature stop. Affects both TypeScript and Swift SDKs. - Fix: Explorer equity column now populated on initial load. The watch snapshot now includes per-object valuations for multi-object watches, so the Explorer table displays equity values immediately without waiting for a state change event.
- ⚠️ Breaking:
availableToTradeis now a single USD string.ActiveAssetData.availableToTradechanged from[string, string](buy/sell token pair) to a singlestringrepresenting raw available margin in USD (equity minus margin in use). This is direction-agnostic — usemaxBuyUsd/maxSellUsdfor per-side max exposure. Affects both TypeScript and Swift SDKs, the REST API, and client-side derivation. - SDK: New
Arca.orderBreakdown()static helper. Pure calculator (no network call) that converts between three order input modes:spend(total from balance),notional(position exposure), andtokens(token count). Returnstokens,notionalUsd,marginRequired,estimatedFee,totalSpend,price, andfeeRate. Available in both TypeScript and Swift SDKs. Dollar values are estimates at the provided price. - SDK:
sizeToleranceonplaceOrder. New parameter that allows the server to reduce order size by up to the specified percentage if a margin check fails due to price drift. Only reduces, never increases. Works with or withoutuseMax. Recommended: 0.01 (1%) for interactive flows, 0.02 (2%) for retail.maxSizeToleranceis deprecated but still works as an alias. - SDK:
feeRateis all-in.ActiveAssetData.feeRateincludes exchange taker fee (HIP-3 scaled), platform fee, and builder fee (whenbuilderFeeBpsis passed togetActiveAssetData). No need to add builder fees separately. - SDK:
getActiveAssetDatanow accepts optionalleverage. Both TypeScript and Swift SDKs now pass an optionalleverageparameter to the server. When provided, the server uses this value instead of the stored per-coin leverage setting (which defaults to 1x ifupdateLeveragehasn't been called). This ensuresgetActiveAssetDatareturns max order sizes consistent with the intended leverage, even if there's a timing gap betweenupdateLeverageand the query. For live max-size streaming, continue usingwatchMaxOrderSize()which computes client-side with the leverage from options. - ⚠️ Breaking:
computedfield removed from valuations. Thecomputedboolean has been removed fromObjectValuationandPathAggregationin both TypeScript and Swift SDKs, and from the corresponding API responses. The server now guarantees accurate data by using last-known mid prices as a fallback when market data is temporarily unavailable. When a mid price is genuinely unavailable for a position, price-derived fields (unrealizedPnl,valueUsd,markPrice) are omitted from that position rather than sending placeholder zeros. These fields onPositionValueare now optional in both SDKs. - ⚠️ Breaking:
PathAggregationno longer includesobjects. Theobjects: ObjectValuation[]field has been removed fromPathAggregation(TypeScript SDK),PathAggregationResponse(Go API), and the matching SwiftPathAggregationmodel. Portfolio rollups still includetotalEquityUsd,breakdown, and in-transit USD fields. For per-object valuations, usewatchObject(path)or the newwatchObjects(paths)in TypeScript andwatchObjects(paths:exchange:)in Swift — these emit merged per-pathObjectValuationupdates. For one-shot reads, usegetObjectValuation(path). Client-siderevalueAggregationnow derives live totals frombreakdown(spot entries revalued; exchange/perp pass-through;departingUsd/arrivingUsdunchanged as USD pass-through). - Real-time P&L on exchange state.
watchExchangeState()now subscribes to mid prices and revalues position P&L, equity, and margin summary client-side on every price tick. Previously, exchange state updates arrived only every ~5 seconds via a server round-trip. Position P&L now updates at the same frequency aswatchObject()andwatchAggregation(). Each update includes asourcefield ('exchange'for server-pushed structural changes,'mids'for client-side revaluation). Available in both TypeScript and Swift SDKs. UserevalueExchangeState(state, mids)for manual revaluation outside a stream. - Mid price responsiveness: all assets have prices immediately.
watchPrices()now guarantees that.pricesis fully populated when theawaitresolves — including illiquid and HIP-3 assets that previously could take seconds to minutes to appear. The server now seeds mid prices from the full asset universe at startup, and the SDK no longer resolvesready()before data arrives.
2026-03-29
- ⚠️ SDK fix: max order size now uses correct margin metric.
watchMaxOrderSize()andderiveActiveAssetDataFromState()previously usedavailableToWithdraw(withdrawal cushion: equity minus maintenance margin) to compute max order sizes. This inflated buying power because maintenance margin is much smaller than initial margin. The SDK now correctly usesequity - initialMarginUsedto determine available trading margin, matching the backend's order validation logic. If you were computing max order sizes with your own code usingavailableToWithdraw, switch toequity - initialMarginUsed. - Docs: clarified availableToWithdraw semantics. The
availableToWithdrawfield documentation previously described it as "equity minus initial margin," which was incorrect. It is equity minus maintenance margin — a withdrawal safety metric, not trading capacity. Docs now clearly distinguish between withdrawable amount and available trading margin.
2026-03-26
- Swift SDK: watchCandleChart(coin:interval:count:) New
CandleChartStreamthat blends historical candles from the REST API with live WebSocket events into a single, always-up-to-date candle array. Handles deduplication, sorting, in-place updates for in-progress candles, and automatic gap recovery on WebSocket reconnection. This replaces the need to manually mergegetCandles()andwatchCandles()in your app — the stream does it for you.
2026-03-21
- Active asset data now streams in real time.
watchMaxOrderSize()now receives live exchange state updates (orders, fills, leverage, deposits, funding) in addition to price changes. Previously, max order sizes only updated on price ticks. - Swift SDK: watchMaxOrderSize(options:) Added
watchMaxOrderSize()to the Swift SDK, matching the TypeScript SDK. Returns aMaxOrderSizeWatchStreamthat recomputesActiveAssetDataon price and exchange state changes.
2026-03-09
- ⚠️ ActiveAssetData sell sizing fields are now unsigned.
maxSellSize,maxSellUsd, and the sell entry inavailableToTradeare now returned as positive magnitudes. Direction continues to be selected via orderside.
2026-03-08
- ⚠️ ActiveAssetData: named fields replace arrays.
maxTradeSzsandavailableToTradearrays have been replaced with four named fields:maxBuySize,maxSellSize,maxBuyUsd,maxSellUsd. Affects the REST API, TypeScript SDK, and Swift SDK. - placeOrder leverage parameter now works. The
leverageparameter onplaceOrdernow automatically sets the account's per-coin leverage before placing the order. Previously, it was accepted but ignored — callers had to callupdateLeverageseparately. - Swift SDK v0.1.0 tag. First semver tag for the Swift SDK. Pin your SPM dependency to
from: "0.1.0"instead ofbranch: "main". - Weekly reset status endpoint.
GET /api/v1/status/resetreturns the next and last weekly reset timestamps. No authentication required. - REST docs: transfer examples and balance cross-reference. Added curl example for the transfer endpoint, clarified transfer vs withdrawal semantics, and added a balance endpoint cross-reference in Getting Started.