acta-maker-sdk
Rust SDK for Acta options market makers. Handles WebSocket connectivity, authentication, order signing, and message serialization.
Two API levels:
ManagedWs— reconnects and authenticates automatically, and exposessend_await()for correlated responses.WsClient— raw WebSocket client. You manage the connection yourself. Good for scripts and testing.
No features enabled by default — lightweight core with opt-in WS and Solana support.
WebSocket snippets are compiled with
cargo test --doc --features ws-client; chain snippets are also compiled withcargo test --doc --features ws-client,chain-rpc. They are markedno_run: they type-check but do not open a live connection.
Install
[]
= { = "0.2.0", = ["ws-client"] }
| Feature | What it enables |
|---|---|
ws-client |
WebSocket client (WsClient, ManagedWs), requires tokio |
chain |
Solana instruction builders (DepositPremium, WithdrawPremium, FundPosition) |
chain-rpc |
Solana RPC queries (extends chain) |
test-helpers |
Test utilities (ManagedWsHandle::test_handle, message injection) |
Quick start (ManagedWs)
use *;
use ;
use Arc;
#
ManagedWsConfig defaults to the maker quote endpoint (/maker). Keep
latency-sensitive commands there: Quote, BatchQuotes, ReplaceQuote,
CancelQuote, CancelAllQuotes, and subscriptions. For private maker reads
and recovery queries, open a separate data-plane connection:
use *;
use ;
use Arc;
#
The data endpoint normalizes to /maker/data and is the preferred place for
GetActiveRfqs, GetMyQuotes, GetMakerPositions, GetMarketsForMaker,
GetMyTrades, and GetMmSummary. Automatic reconcile reads are enabled on
the data endpoint and disabled on the quote endpoint by default.
send() confirms that the frame was written to the current WebSocket. It is
not a server ACK. Use send_await() when the command has a correlated server
response. Commands submitted while reconnecting fail with Disconnected; the
SDK never replays a quote behind the strategy's back. try_send() returns a
SendTicket, whose wait() method reports the eventual socket-write result.
Each inbound message carries a connection epoch and a connection-local
sequence number. ManagedMessageReceiver::recv() returns Gap if its bounded
broadcast buffer overflows. Treat that as a reason to refresh state through the
data connection.
Quick start (WsClient)
use *;
use *;
# async
WsClient enables TCP_NODELAY and applies bounded frame, message, and write
buffers. For a message that will be sent more than once, build a
PreparedClientMessage and call send_prepared() to reuse its serialized
bytes.
Order signing
use *;
#
BytesSigner wraps an Ed25519 keypair with Zeroize on drop. SignerLike is the synchronous
hot-path interface for local keys. Use AsyncSignerLike when signing may wait for an external
process or device. The SDK verifies every returned signature against the requested message and
pubkey_bytes. ManagedWsConfig::auth_timeout bounds the complete authentication flow, including
signing; timed-out signer futures are dropped and must therefore be cancellation-safe.
Funding positions with native SOL
With the chain-rpc feature, FundPositionArgs can wrap native SOL when the
position settles in wSOL. Wrapping is opt-in:
#
#
The SDK validates the position, market, and existing wSOL account. When the maker
is also the fee payer, the final pre-sign check includes the wrap amount, rent for
missing token accounts created by funding, the RPC fee for the assembled transaction, and the configured
reserve. With an external fee payer, the maker budget includes only the wrap and
reserve. This is a snapshot guarantee, not an on-chain lock: another concurrent
wallet transaction can still spend SOL after the check. RPC and account-validation
errors fail closed; they are not treated as a zero token balance. Use
NativeSolFunding::Disabled when wrapping is handled by the caller.
Value sets (string enums)
These are String on the wire; the SDK provides enums for known value sets:
PositionType:"covered_call"|"cash_secured_put"QuoteStatus:"pending"|"best"|"outbid"|"filled"|"expired"QuoteCancelReason:"requested"|"risk_check"|"rfq_accepted"RfqAvailableAgainReason:"signature_timeout"|"tx_failed"|"tx_build_failed"RfqCloseReason:"expired"|"taker_cancelled"|"filled"|"market_expired"|"ladder_timeout"QuoteFinalStatus:"expired"|"outbid"|"cancelled"|"filled"PositionUpdateType:"created"|"funded"|"liquidated"|"settled"
Known order and position statuses are represented by SDK enums. Truly open-ended backend fields, such as diagnostic reason text, remain strings.
Examples
Examples require the ws-client feature:
Subscribe to RFQs + chain events
use *;
use *;
# async
Send a quote
use *;
use *;
use Uuid;
# async
Discovery APIs
use *;
use ;
# async
Cancel quote(s)
use *;
use Uuid;
# async
Documentation
Full documentation is available at docs.acta.markets:
- Rust SDK integration guide
- Wire examples (JSON and Rust)
- Maker API reference (all WS messages)
- Sandbox / devnet setup
- FAQ and troubleshooting
License
MIT