TypeScript SDK
In one paragraph. @trion/sdk is the official TypeScript SDK for Trion markets, orders, positions, realtime streams and agent grants. One TrionClient covers public reads, signed trading and agent delegation; the SDK owns order signing, epoch resolution and settlement tracking so your code writes strategy, not plumbing.
Publication status
@trion/sdk is not published yet: it is not on npm, and publication is pending during the beta. The code below shows the intended usage; you cannot install it today. Access is no longer invite-gated: since 2026-09-26 the Agent Kit is open to any wallet, and the perp matcher's agent routes (/v1/agents) have no invite list. The CMPT-USD perpetual the SDK trades is in open beta.
Client setup
import { TrionClient, privateKeySigner, Side, Tif } from "@trion/sdk";
const client = new TrionClient({
baseUrl: "https://api.trion.market",
market: "CMPT-USD",
signer: privateKeySigner("0x..."),
});
baseUrl defaults to https://api.trion.market; market defaults to CMPT-USD. The client derives the perp API (https://api.trion.market/perp) and WebSocket endpoints from baseUrl automatically.
Signers
Three signer implementations:
| Signer | Factory | Use case |
|---|---|---|
| Private key | privateKeySigner(hexKey) | Automated bots, backend scripts |
| EIP-1193 wallet | walletSigner(provider, address) | Browser wallets (MetaMask, Rabby, window.ethereum) |
| Agent | agentSigner({ agentKey, trader }) | Delegated trading: the agent key signs orders on behalf of trader |
When you use agentSigner, every order and cancel is signed with the agent's key but carries the owner's trader address; the SDK sets the agent field and the grant's strategyId/strategyEpoch so the matcher verifies the delegation. If you omit strategyId and strategyEpoch, the client resolves the active grant for that agent key on first use and throws AgentNotAuthorizedError if none is active.
const bot = new TrionClient({
baseUrl: "https://api.trion.market",
market: "CMPT-USD",
signer: agentSigner({ agentKey: "0x...", trader: "0x..." }),
});
await bot.placeLimitOrder({ side: Side.BUY, price: "49.500", quantity: "2" });
Quickstart
// 1. Read market summary, orderbook and recent trades
const markets = await client.getMarkets();
const book = await client.getBook("CMPT-USD", 10);
const trades = await client.getTrades("CMPT-USD", 10);
console.log("Best bid:", book.bids[0], "Best ask:", book.asks[0]);
// 2. Place a limit order
const order = await client.placeLimitOrder({
side: Side.BUY,
price: "50.000",
quantity: "1",
tif: Tif.GTC,
});
console.log("Order submitted:", order.orderHash);
// 3. Create and register an agent grant
const { agentKey, grant, typedData } = await client.agents.create({
maxOrderQty: "10", // max lots per order
maxPositionLots: "50", // max position in lots
reduceOnly: false, // allow opening trades
expiryDays: 30, // grant lifetime (max 180 days)
});
const signature = await client.signer!.signTypedData(typedData);
await client.agents.register(grant, signature);
// 4. Stream the orderbook with gap detection
const stream = client.stream();
const unsubscribe = stream.subscribeBook({ symbol: "CMPT-USD" }, (view, event) => {
console.log(`Seq: ${view.seq}, Bids: ${view.bids.length}, Asks: ${view.asks.length}`);
});
The example prices are illustrative: a real order must sit inside the matcher's ±3% index price band (the CMPT-USD perp index was ~$2.75 on 2026-09-26), so 50.000 would be rejected.
Order types and safety primitives
placeLimitOrder(options)— limit order withtif(GTC, IOC, FOK) andpostOnly/reduceOnlyflags.placeMarketOrder(options)— IOC order with slippage protection against the best book price (default 50 bps).closePosition(options)— sized from the live position; submits an IOC reduce-only order in the opposite direction.cancelOrder(orderHash)— soft-cancels a resting order viapersonal_sign.cancelAll(params)— cancels all the trader's resting orders on a market with a monotonic replay guard.
Streams
client.stream() opens a WebSocket with reconnect backoff and heartbeat handling:
book2— full snapshot then incremental deltas, with gap detection: ifprevSeqdoesn't match the local sequence, the SDK resubscribes for a fresh snapshot.trades2— batched public executions.ticker— 24-hour pricing, volume and funding rates.account2— private balance, fill and position events.
Epochs (fail closed)
The matcher checks accountEpoch and strategyEpoch on every order. To avoid RPC round-trips, the SDK resolves epochs in this order:
- Explicit
accountEpoch/strategyEpochpassed toplaceLimitOrder. - The matcher's canonical account response (
GET /v1/account/:symbol/:address). defaultAccountEpochonTrionClientOptions.
Fail closed: if the epoch is missing everywhere, the SDK throws a typed TrionApiError with code ACCOUNT_EPOCH_UNKNOWN. Silent fallback to 0 is forbidden because a wrong epoch makes every order fail with EPOCH.
Typed errors
TrionApiError— base error withservice, HTTPstatus,codeandmessage.RetryableError— transient faults (TRANSPORT, HTTP 429 withretryAfterMs, 5xx); bounded retries with backoff are applied to idempotent GETs.AgentLimitError— an agent tried to trade outside its grant (AGENT_LIMIT).
See Agent grants and limits for the bounds, and Signed orders for the order struct the SDK signs.
Source trail: overdrive/exchange/sdk/README.md, overdrive/exchange/sdk/src/client.ts (base URL derivation), streams.ts (gap detection), overdrive/exchange/core/src/v2.ts (order and grant types).
Repository-owned documentation · October 2026 · Educational material, not investment advice and not an audit.
Documentation
Options live · Perps in open beta