@acta-markets/ts-sdk 0.0.14-beta → 0.0.16-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,7 +8,7 @@ Generated by Codama.
8
8
 
9
9
  ## Package
10
10
 
11
- Published package: **`@acta-markets/ts-sdk@0.0.6-beta`** (ESM-first, CJS fallback)
11
+ Published package: `@acta-markets/ts-sdk@0.0.6-beta` (ESM-first, CJS fallback)
12
12
 
13
13
  ```bash
14
14
  yarn add @acta-markets/ts-sdk@0.0.6-beta
@@ -49,7 +49,7 @@ const c2 = new ActaClient({ chain: { rpc, rpcSubscriptions, payer } });
49
49
 
50
50
  ## Web app quickstart (taker-only)
51
51
 
52
- ### 1) Connect to WS anonymously, then authenticate on Connect wallet
52
+ ### 1) Connect to WS anonymously, then authenticate on "Connect wallet"
53
53
 
54
54
  ```ts
55
55
  import { ActaClient } from "@acta-markets/ts-sdk";
@@ -64,7 +64,7 @@ const auth = new WalletAuthProvider({
64
64
  // No wallet prompt:
65
65
  client.ws!.connectAnonymous();
66
66
 
67
- // Later, on Connect wallet button:
67
+ // Later, on "Connect wallet" button:
68
68
  await client.ws!.authenticate(auth);
69
69
  client.ws!.on("snapshot", (s) => console.log("snapshot", s));
70
70
  client.ws!.on("chainEvent", (e) => console.log("chain event", e));
@@ -72,11 +72,11 @@ client.ws!.on("chainEvent", (e) => console.log("chain event", e));
72
72
 
73
73
  #### Auth providers (why there are multiple)
74
74
 
75
- - **`WalletAuthProvider`**: browser wallets (Phantom/Privy/etc.) that support `signMessage` (typical web integration).
76
- - **`KeypairAuthProvider`**: Node scripts/CI/bots where you load a local keypair (e.g. from `KEYPAIR_PATH`).
77
- - **`CustomAuthProvider`**: advanced integrations (remote signers, hardware wallets, nonstandard wallet APIs).
78
- - **`AuthProvider` (type)**: shared interface the WS client accepts.
79
- - **`WalletLike` (type)**: minimal wallet adapter shape (no dependency on wallet-adapter / web3.js types).
75
+ - `WalletAuthProvider`: browser wallets (Phantom/Privy/etc.) that support `signMessage`.
76
+ - `KeypairAuthProvider`: Node scripts/CI/bots where you load a local keypair (e.g. from `KEYPAIR_PATH`).
77
+ - `CustomAuthProvider`: advanced integrations (remote signers, hardware wallets, nonstandard wallet APIs).
78
+ - `AuthProvider` (type): shared interface the WS client accepts.
79
+ - `WalletLike` (type): minimal wallet adapter shape (no dependency on wallet-adapter / web3.js types).
80
80
 
81
81
  ### Markets + positions without on-chain RPC (WS convenience)
82
82
 
@@ -152,7 +152,7 @@ client.ws!.on("message", (m) => {
152
152
  if (m.type !== "Error") return;
153
153
  switch (m.data.code) {
154
154
  case "rfq_expired":
155
- // show quotes expired and offer a Retry RFQ button
155
+ // show "quotes expired" and offer a "Retry RFQ" button
156
156
  break;
157
157
  case "quote_expired":
158
158
  case "quote_refresh_required":
@@ -164,7 +164,7 @@ client.ws!.on("message", (m) => {
164
164
 
165
165
  ### APR/APY (annualized premium yield) from quotes
166
166
 
167
- Frontends often want to display a simple premium yield as an annualized percentage.
167
+ Frontends often want to display a simple "premium yield" as an annualized percentage.
168
168
  Given:
169
169
 
170
170
  - `price` = gross premium per 1 underlying (1e9 scale)
@@ -188,7 +188,7 @@ import { ws } from "@acta-markets/ts-sdk";
188
188
 
189
189
  const secondsToExpiry = rfq.market.expiry_ts - Math.floor(Date.now() / 1000);
190
190
 
191
- // Example: if you already render quantity as 10 SOL”, pass underlyingAmount=10.
191
+ // Example: if you already render quantity as "10 SOL", pass underlyingAmount=10.
192
192
  const { apr, apy, premiumNotional } = ws.computeApyFromScaledPrices({
193
193
  positionType: "cash_secured_put",
194
194
  underlyingAmount: 10,
@@ -199,7 +199,7 @@ const { apr, apy, premiumNotional } = ws.computeApyFromScaledPrices({
199
199
  ```
200
200
 
201
201
  Note:
202
- - This is a **display metric** (premium / collateral annualized), not a promise of guaranteed yield”.
202
+ - This is a display metric (premium / collateral annualized), not a promise of "guaranteed yield".
203
203
  - For covered calls you also need `spotPrice1e9` (from your own spot feed) to value collateral in quote units.
204
204
 
205
205
  ### Chain flow helpers
@@ -305,9 +305,9 @@ const openIx = await buildOpenPositionIx({
305
305
 
306
306
  ## OrderId rules (SDK-wide)
307
307
 
308
- - **Canonical**: `orderId` is always **32 bytes** (`sha256(preimage182)`), same as the on-chain program expects.
309
- - **In code**: use `Uint8Array(32)` everywhere.
310
- - **JSON / WS wire**: when `order_id` must be a string, it is **64-char hex** (32 bytes). SDK flow helpers handle encoding/decoding for you.
308
+ - Canonical: `orderId` is always 32 bytes (`sha256(preimage182)`), same as the on-chain program expects.
309
+ - In code: use `Uint8Array(32)` everywhere.
310
+ - JSON / WS wire: when `order_id` must be a string, it is 64-char hex (32 bytes). SDK flow helpers handle encoding/decoding for you.
311
311
 
312
312
  ## WS order status events
313
313
 
@@ -7,7 +7,7 @@
7
7
  * @see https://github.com/codama-idl/codama
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.ACTA_CONTRACT_ERROR__DUPLICATE_ACCOUNT = exports.ACTA_CONTRACT_ERROR__ORACLE_HAS_ACTIVE_MARKETS = exports.ACTA_CONTRACT_ERROR__ORACLE_SOURCE_LOCKED = exports.ACTA_CONTRACT_ERROR__ORACLE_ALREADY_UPDATED = exports.ACTA_CONTRACT_ERROR__ORACLE_CLOSE_TOO_EARLY = exports.ACTA_CONTRACT_ERROR__UNAUTHORIZED = exports.ACTA_CONTRACT_ERROR__INVALID_TIMESTAMP = exports.ACTA_CONTRACT_ERROR__INVALID_PROGRAM_ID = exports.ACTA_CONTRACT_ERROR__INSUFFICIENT_FUNDS = exports.ACTA_CONTRACT_ERROR__MINT_MISMATCH = exports.ACTA_CONTRACT_ERROR__MATH_OVERFLOW = exports.ACTA_CONTRACT_ERROR__INVALID_INSTRUCTION_DATA = exports.ACTA_CONTRACT_ERROR__SIGNED_MESSAGE_MISMATCH = exports.ACTA_CONTRACT_ERROR__SIGNER_MISMATCH = exports.ACTA_CONTRACT_ERROR__INVALID_SIGNATURE_COUNT = exports.ACTA_CONTRACT_ERROR__INVALID_ORDER_ID = exports.ACTA_CONTRACT_ERROR__CANNOT_LIQUIDATE_FUNDED = exports.ACTA_CONTRACT_ERROR__POSITION_TYPE_MISMATCH = exports.ACTA_CONTRACT_ERROR__POSITION_NOT_ITM = exports.ACTA_CONTRACT_ERROR__POSITION_ALREADY_SETTLED = exports.ACTA_CONTRACT_ERROR__POSITION_NOT_FUNDED = exports.ACTA_CONTRACT_ERROR__POSITION_ALREADY_FUNDED = exports.ACTA_CONTRACT_ERROR__POSITION_NOT_OPEN = exports.ACTA_CONTRACT_ERROR__POSITION_ALREADY_OPEN = exports.ACTA_CONTRACT_ERROR__ORACLE_INVALID_PRICE = exports.ACTA_CONTRACT_ERROR__ORACLE_INACTIVE = exports.ACTA_CONTRACT_ERROR__ORACLE_STALE = exports.ACTA_CONTRACT_ERROR__ORACLE_EXPIRY_MISMATCH = exports.ACTA_CONTRACT_ERROR__INVALID_ORACLE_ACCOUNT = exports.ACTA_CONTRACT_ERROR__INVALID_ORACLE_TYPE = exports.ACTA_CONTRACT_ERROR__MARKET_NOT_EMPTY = exports.ACTA_CONTRACT_ERROR__MARKET_EXPIRED = exports.ACTA_CONTRACT_ERROR__MARKET_NOT_FINALIZED = exports.ACTA_CONTRACT_ERROR__MARKET_FINALIZED = exports.ACTA_CONTRACT_ERROR__MAKER_NOT_OWNER = exports.ACTA_CONTRACT_ERROR__MAKER_NOT_REGISTERED = exports.ACTA_CONTRACT_ERROR__MAKER_ALREADY_REGISTERED = exports.ACTA_CONTRACT_ERROR__ACCOUNT_ALREADY_INITIALIZED = exports.ACTA_CONTRACT_ERROR__INVALID_ACCOUNT_DATA = exports.ACTA_CONTRACT_ERROR__INVALID_ACCOUNT_COUNT = exports.ACTA_CONTRACT_ERROR__ACCOUNT_NOT_INITIALIZED = exports.ACTA_CONTRACT_ERROR__INVALID_PDA = exports.ACTA_CONTRACT_ERROR__INVALID_OWNER = exports.ACTA_CONTRACT_ERROR__NOT_SIGNED = void 0;
10
+ exports.ACTA_CONTRACT_ERROR__MARKET_NOT_EXPIRED = exports.ACTA_CONTRACT_ERROR__DUPLICATE_ACCOUNT = exports.ACTA_CONTRACT_ERROR__ORACLE_HAS_ACTIVE_MARKETS = exports.ACTA_CONTRACT_ERROR__ORACLE_SOURCE_LOCKED = exports.ACTA_CONTRACT_ERROR__ORACLE_ALREADY_UPDATED = exports.ACTA_CONTRACT_ERROR__ORACLE_CLOSE_TOO_EARLY = exports.ACTA_CONTRACT_ERROR__UNAUTHORIZED = exports.ACTA_CONTRACT_ERROR__INVALID_TIMESTAMP = exports.ACTA_CONTRACT_ERROR__INVALID_PROGRAM_ID = exports.ACTA_CONTRACT_ERROR__INSUFFICIENT_FUNDS = exports.ACTA_CONTRACT_ERROR__MINT_MISMATCH = exports.ACTA_CONTRACT_ERROR__MATH_OVERFLOW = exports.ACTA_CONTRACT_ERROR__INVALID_INSTRUCTION_DATA = exports.ACTA_CONTRACT_ERROR__SIGNED_MESSAGE_MISMATCH = exports.ACTA_CONTRACT_ERROR__SIGNER_MISMATCH = exports.ACTA_CONTRACT_ERROR__INVALID_SIGNATURE_COUNT = exports.ACTA_CONTRACT_ERROR__INVALID_ORDER_ID = exports.ACTA_CONTRACT_ERROR__CANNOT_LIQUIDATE_FUNDED = exports.ACTA_CONTRACT_ERROR__POSITION_TYPE_MISMATCH = exports.ACTA_CONTRACT_ERROR__POSITION_NOT_ITM = exports.ACTA_CONTRACT_ERROR__POSITION_ALREADY_SETTLED = exports.ACTA_CONTRACT_ERROR__POSITION_NOT_FUNDED = exports.ACTA_CONTRACT_ERROR__POSITION_ALREADY_FUNDED = exports.ACTA_CONTRACT_ERROR__POSITION_NOT_OPEN = exports.ACTA_CONTRACT_ERROR__POSITION_ALREADY_OPEN = exports.ACTA_CONTRACT_ERROR__ORACLE_INVALID_PRICE = exports.ACTA_CONTRACT_ERROR__ORACLE_INACTIVE = exports.ACTA_CONTRACT_ERROR__ORACLE_STALE = exports.ACTA_CONTRACT_ERROR__ORACLE_EXPIRY_MISMATCH = exports.ACTA_CONTRACT_ERROR__INVALID_ORACLE_ACCOUNT = exports.ACTA_CONTRACT_ERROR__INVALID_ORACLE_TYPE = exports.ACTA_CONTRACT_ERROR__MARKET_NOT_EMPTY = exports.ACTA_CONTRACT_ERROR__MARKET_EXPIRED = exports.ACTA_CONTRACT_ERROR__MARKET_NOT_FINALIZED = exports.ACTA_CONTRACT_ERROR__MARKET_FINALIZED = exports.ACTA_CONTRACT_ERROR__MAKER_NOT_OWNER = exports.ACTA_CONTRACT_ERROR__MAKER_NOT_REGISTERED = exports.ACTA_CONTRACT_ERROR__MAKER_ALREADY_REGISTERED = exports.ACTA_CONTRACT_ERROR__ACCOUNT_ALREADY_INITIALIZED = exports.ACTA_CONTRACT_ERROR__INVALID_ACCOUNT_DATA = exports.ACTA_CONTRACT_ERROR__INVALID_ACCOUNT_COUNT = exports.ACTA_CONTRACT_ERROR__ACCOUNT_NOT_INITIALIZED = exports.ACTA_CONTRACT_ERROR__INVALID_PDA = exports.ACTA_CONTRACT_ERROR__INVALID_OWNER = exports.ACTA_CONTRACT_ERROR__NOT_SIGNED = void 0;
11
11
  exports.getActaContractErrorMessage = getActaContractErrorMessage;
12
12
  exports.isActaContractError = isActaContractError;
13
13
  const kit_1 = require("@solana/kit");
@@ -100,6 +100,8 @@ exports.ACTA_CONTRACT_ERROR__ORACLE_SOURCE_LOCKED = 0x431; // 1073
100
100
  exports.ACTA_CONTRACT_ERROR__ORACLE_HAS_ACTIVE_MARKETS = 0x432; // 1074
101
101
  /** DuplicateAccount: Duplicate account passed to instruction */
102
102
  exports.ACTA_CONTRACT_ERROR__DUPLICATE_ACCOUNT = 0x433; // 1075
103
+ /** MarketNotExpired: Market has not expired yet */
104
+ exports.ACTA_CONTRACT_ERROR__MARKET_NOT_EXPIRED = 0x434; // 1076
103
105
  let actaContractErrorMessages;
104
106
  if (process.env.NODE_ENV !== "production") {
105
107
  actaContractErrorMessages = {
@@ -125,6 +127,7 @@ if (process.env.NODE_ENV !== "production") {
125
127
  [exports.ACTA_CONTRACT_ERROR__MARKET_EXPIRED]: `Market expired`,
126
128
  [exports.ACTA_CONTRACT_ERROR__MARKET_FINALIZED]: `Market already finalized`,
127
129
  [exports.ACTA_CONTRACT_ERROR__MARKET_NOT_EMPTY]: `Market has open positions (cannot close)`,
130
+ [exports.ACTA_CONTRACT_ERROR__MARKET_NOT_EXPIRED]: `Market has not expired yet`,
128
131
  [exports.ACTA_CONTRACT_ERROR__MARKET_NOT_FINALIZED]: `Market not yet finalized`,
129
132
  [exports.ACTA_CONTRACT_ERROR__MATH_OVERFLOW]: `Arithmetic overflow`,
130
133
  [exports.ACTA_CONTRACT_ERROR__MINT_MISMATCH]: `Mint mismatch between token accounts`,
@@ -2363,6 +2363,11 @@
2363
2363
  "code": 1075,
2364
2364
  "name": "DuplicateAccount",
2365
2365
  "msg": "Duplicate account passed to instruction"
2366
+ },
2367
+ {
2368
+ "code": 1076,
2369
+ "name": "MarketNotExpired",
2370
+ "msg": "Market has not expired yet"
2366
2371
  }
2367
2372
  ]
2368
2373
  }
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ACTA_IDL_SHA256 = void 0;
4
- exports.ACTA_IDL_SHA256 = "85637746c4aabc7c4638de439ca8cf3cf6dfda58b2e26e5347077abdb78958dc";
4
+ exports.ACTA_IDL_SHA256 = "8072bc43541635b8c359d8c0209c3ab63f6a264d6843997d20c9d6c9473130c9";
@@ -319,6 +319,14 @@ class ActaWsClient extends TypedEventEmitter {
319
319
  });
320
320
  return requestId;
321
321
  }
322
+ getEarnSummary() {
323
+ const requestId = this.nextRequestId();
324
+ this.send({
325
+ type: "GetEarnSummary",
326
+ data: { request_id: requestId },
327
+ });
328
+ return requestId;
329
+ }
322
330
  logout() {
323
331
  this.send({ type: "Logout" });
324
332
  }
@@ -558,6 +566,9 @@ class ActaWsClient extends TypedEventEmitter {
558
566
  case "StatsUpdate":
559
567
  this.handleStatsUpdate(message.data.stats);
560
568
  break;
569
+ case "EarnSummary":
570
+ this.emit("earnSummary", message.data);
571
+ break;
561
572
  case "RfqBroadcast":
562
573
  // Keep local RFQ state reasonably fresh even without a new snapshot.
563
574
  if (!this.state.activeRfqs.has(message.data.rfq_id)) {
@@ -801,17 +812,6 @@ class ActaWsClient extends TypedEventEmitter {
801
812
  this.emit("error", new Error(`Authentication failed: ${details}`));
802
813
  }
803
814
  handleSnapshot(snapshot) {
804
- this.state.stats = snapshot.stats;
805
- this.state.activeRfqs.clear();
806
- for (const rfq of snapshot.active_rfqs) {
807
- this.state.activeRfqs.set(rfq.rfq_id, rfq);
808
- }
809
- this.state.myActiveRfqs.clear();
810
- this.state.positions.clear();
811
- for (const position of snapshot.positions ?? []) {
812
- this.state.positions.set(position.pda, position);
813
- }
814
- this.state.recentTrades = snapshot.recent_trades ?? [];
815
815
  this.state.markets.clear();
816
816
  for (const market of snapshot.markets) {
817
817
  this.state.markets.set(market.pda, market);
@@ -1,14 +1,2 @@
1
1
  "use strict";
2
- /**
3
- * WebSocket protocol types for Acta RFQ server.
4
- *
5
- * Source of truth:
6
- * - docs/state-machines-eng.md (protocol spec)
7
- * - rust-backend/shared/src/types/ws.rs (as-built reference)
8
- *
9
- * Notes:
10
- * - UUIDs are represented as strings in JSON.
11
- * - Rust uses u64 in many places; we model them as `number` for now.
12
- * If/when we need precision beyond JS safe integer, we can migrate to `bigint | string`.
13
- */
14
2
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -94,7 +94,9 @@ export declare const ACTA_CONTRACT_ERROR__ORACLE_SOURCE_LOCKED = 1073;
94
94
  export declare const ACTA_CONTRACT_ERROR__ORACLE_HAS_ACTIVE_MARKETS = 1074;
95
95
  /** DuplicateAccount: Duplicate account passed to instruction */
96
96
  export declare const ACTA_CONTRACT_ERROR__DUPLICATE_ACCOUNT = 1075;
97
- export type ActaContractError = typeof ACTA_CONTRACT_ERROR__ACCOUNT_ALREADY_INITIALIZED | typeof ACTA_CONTRACT_ERROR__ACCOUNT_NOT_INITIALIZED | typeof ACTA_CONTRACT_ERROR__CANNOT_LIQUIDATE_FUNDED | typeof ACTA_CONTRACT_ERROR__DUPLICATE_ACCOUNT | typeof ACTA_CONTRACT_ERROR__INSUFFICIENT_FUNDS | typeof ACTA_CONTRACT_ERROR__INVALID_ACCOUNT_COUNT | typeof ACTA_CONTRACT_ERROR__INVALID_ACCOUNT_DATA | typeof ACTA_CONTRACT_ERROR__INVALID_INSTRUCTION_DATA | typeof ACTA_CONTRACT_ERROR__INVALID_ORACLE_ACCOUNT | typeof ACTA_CONTRACT_ERROR__INVALID_ORACLE_TYPE | typeof ACTA_CONTRACT_ERROR__INVALID_ORDER_ID | typeof ACTA_CONTRACT_ERROR__INVALID_OWNER | typeof ACTA_CONTRACT_ERROR__INVALID_PDA | typeof ACTA_CONTRACT_ERROR__INVALID_PROGRAM_ID | typeof ACTA_CONTRACT_ERROR__INVALID_SIGNATURE_COUNT | typeof ACTA_CONTRACT_ERROR__INVALID_TIMESTAMP | typeof ACTA_CONTRACT_ERROR__MAKER_ALREADY_REGISTERED | typeof ACTA_CONTRACT_ERROR__MAKER_NOT_OWNER | typeof ACTA_CONTRACT_ERROR__MAKER_NOT_REGISTERED | typeof ACTA_CONTRACT_ERROR__MARKET_EXPIRED | typeof ACTA_CONTRACT_ERROR__MARKET_FINALIZED | typeof ACTA_CONTRACT_ERROR__MARKET_NOT_EMPTY | typeof ACTA_CONTRACT_ERROR__MARKET_NOT_FINALIZED | typeof ACTA_CONTRACT_ERROR__MATH_OVERFLOW | typeof ACTA_CONTRACT_ERROR__MINT_MISMATCH | typeof ACTA_CONTRACT_ERROR__NOT_SIGNED | typeof ACTA_CONTRACT_ERROR__ORACLE_ALREADY_UPDATED | typeof ACTA_CONTRACT_ERROR__ORACLE_CLOSE_TOO_EARLY | typeof ACTA_CONTRACT_ERROR__ORACLE_EXPIRY_MISMATCH | typeof ACTA_CONTRACT_ERROR__ORACLE_HAS_ACTIVE_MARKETS | typeof ACTA_CONTRACT_ERROR__ORACLE_INACTIVE | typeof ACTA_CONTRACT_ERROR__ORACLE_INVALID_PRICE | typeof ACTA_CONTRACT_ERROR__ORACLE_SOURCE_LOCKED | typeof ACTA_CONTRACT_ERROR__ORACLE_STALE | typeof ACTA_CONTRACT_ERROR__POSITION_ALREADY_FUNDED | typeof ACTA_CONTRACT_ERROR__POSITION_ALREADY_OPEN | typeof ACTA_CONTRACT_ERROR__POSITION_ALREADY_SETTLED | typeof ACTA_CONTRACT_ERROR__POSITION_NOT_FUNDED | typeof ACTA_CONTRACT_ERROR__POSITION_NOT_ITM | typeof ACTA_CONTRACT_ERROR__POSITION_NOT_OPEN | typeof ACTA_CONTRACT_ERROR__POSITION_TYPE_MISMATCH | typeof ACTA_CONTRACT_ERROR__SIGNED_MESSAGE_MISMATCH | typeof ACTA_CONTRACT_ERROR__SIGNER_MISMATCH | typeof ACTA_CONTRACT_ERROR__UNAUTHORIZED;
97
+ /** MarketNotExpired: Market has not expired yet */
98
+ export declare const ACTA_CONTRACT_ERROR__MARKET_NOT_EXPIRED = 1076;
99
+ export type ActaContractError = typeof ACTA_CONTRACT_ERROR__ACCOUNT_ALREADY_INITIALIZED | typeof ACTA_CONTRACT_ERROR__ACCOUNT_NOT_INITIALIZED | typeof ACTA_CONTRACT_ERROR__CANNOT_LIQUIDATE_FUNDED | typeof ACTA_CONTRACT_ERROR__DUPLICATE_ACCOUNT | typeof ACTA_CONTRACT_ERROR__INSUFFICIENT_FUNDS | typeof ACTA_CONTRACT_ERROR__INVALID_ACCOUNT_COUNT | typeof ACTA_CONTRACT_ERROR__INVALID_ACCOUNT_DATA | typeof ACTA_CONTRACT_ERROR__INVALID_INSTRUCTION_DATA | typeof ACTA_CONTRACT_ERROR__INVALID_ORACLE_ACCOUNT | typeof ACTA_CONTRACT_ERROR__INVALID_ORACLE_TYPE | typeof ACTA_CONTRACT_ERROR__INVALID_ORDER_ID | typeof ACTA_CONTRACT_ERROR__INVALID_OWNER | typeof ACTA_CONTRACT_ERROR__INVALID_PDA | typeof ACTA_CONTRACT_ERROR__INVALID_PROGRAM_ID | typeof ACTA_CONTRACT_ERROR__INVALID_SIGNATURE_COUNT | typeof ACTA_CONTRACT_ERROR__INVALID_TIMESTAMP | typeof ACTA_CONTRACT_ERROR__MAKER_ALREADY_REGISTERED | typeof ACTA_CONTRACT_ERROR__MAKER_NOT_OWNER | typeof ACTA_CONTRACT_ERROR__MAKER_NOT_REGISTERED | typeof ACTA_CONTRACT_ERROR__MARKET_EXPIRED | typeof ACTA_CONTRACT_ERROR__MARKET_FINALIZED | typeof ACTA_CONTRACT_ERROR__MARKET_NOT_EMPTY | typeof ACTA_CONTRACT_ERROR__MARKET_NOT_EXPIRED | typeof ACTA_CONTRACT_ERROR__MARKET_NOT_FINALIZED | typeof ACTA_CONTRACT_ERROR__MATH_OVERFLOW | typeof ACTA_CONTRACT_ERROR__MINT_MISMATCH | typeof ACTA_CONTRACT_ERROR__NOT_SIGNED | typeof ACTA_CONTRACT_ERROR__ORACLE_ALREADY_UPDATED | typeof ACTA_CONTRACT_ERROR__ORACLE_CLOSE_TOO_EARLY | typeof ACTA_CONTRACT_ERROR__ORACLE_EXPIRY_MISMATCH | typeof ACTA_CONTRACT_ERROR__ORACLE_HAS_ACTIVE_MARKETS | typeof ACTA_CONTRACT_ERROR__ORACLE_INACTIVE | typeof ACTA_CONTRACT_ERROR__ORACLE_INVALID_PRICE | typeof ACTA_CONTRACT_ERROR__ORACLE_SOURCE_LOCKED | typeof ACTA_CONTRACT_ERROR__ORACLE_STALE | typeof ACTA_CONTRACT_ERROR__POSITION_ALREADY_FUNDED | typeof ACTA_CONTRACT_ERROR__POSITION_ALREADY_OPEN | typeof ACTA_CONTRACT_ERROR__POSITION_ALREADY_SETTLED | typeof ACTA_CONTRACT_ERROR__POSITION_NOT_FUNDED | typeof ACTA_CONTRACT_ERROR__POSITION_NOT_ITM | typeof ACTA_CONTRACT_ERROR__POSITION_NOT_OPEN | typeof ACTA_CONTRACT_ERROR__POSITION_TYPE_MISMATCH | typeof ACTA_CONTRACT_ERROR__SIGNED_MESSAGE_MISMATCH | typeof ACTA_CONTRACT_ERROR__SIGNER_MISMATCH | typeof ACTA_CONTRACT_ERROR__UNAUTHORIZED;
98
100
  export declare function getActaContractErrorMessage(code: ActaContractError): string;
99
101
  export declare function isActaContractError<TProgramErrorCode extends ActaContractError>(error: unknown, transactionMessage: {
100
102
  instructions: Record<number, {
@@ -95,6 +95,8 @@ export const ACTA_CONTRACT_ERROR__ORACLE_SOURCE_LOCKED = 0x431; // 1073
95
95
  export const ACTA_CONTRACT_ERROR__ORACLE_HAS_ACTIVE_MARKETS = 0x432; // 1074
96
96
  /** DuplicateAccount: Duplicate account passed to instruction */
97
97
  export const ACTA_CONTRACT_ERROR__DUPLICATE_ACCOUNT = 0x433; // 1075
98
+ /** MarketNotExpired: Market has not expired yet */
99
+ export const ACTA_CONTRACT_ERROR__MARKET_NOT_EXPIRED = 0x434; // 1076
98
100
  let actaContractErrorMessages;
99
101
  if (process.env.NODE_ENV !== "production") {
100
102
  actaContractErrorMessages = {
@@ -120,6 +122,7 @@ if (process.env.NODE_ENV !== "production") {
120
122
  [ACTA_CONTRACT_ERROR__MARKET_EXPIRED]: `Market expired`,
121
123
  [ACTA_CONTRACT_ERROR__MARKET_FINALIZED]: `Market already finalized`,
122
124
  [ACTA_CONTRACT_ERROR__MARKET_NOT_EMPTY]: `Market has open positions (cannot close)`,
125
+ [ACTA_CONTRACT_ERROR__MARKET_NOT_EXPIRED]: `Market has not expired yet`,
123
126
  [ACTA_CONTRACT_ERROR__MARKET_NOT_FINALIZED]: `Market not yet finalized`,
124
127
  [ACTA_CONTRACT_ERROR__MATH_OVERFLOW]: `Arithmetic overflow`,
125
128
  [ACTA_CONTRACT_ERROR__MINT_MISMATCH]: `Mint mismatch between token accounts`,
@@ -2363,6 +2363,11 @@
2363
2363
  "code": 1075,
2364
2364
  "name": "DuplicateAccount",
2365
2365
  "msg": "Duplicate account passed to instruction"
2366
+ },
2367
+ {
2368
+ "code": 1076,
2369
+ "name": "MarketNotExpired",
2370
+ "msg": "Market has not expired yet"
2366
2371
  }
2367
2372
  ]
2368
2373
  }
@@ -1 +1 @@
1
- export declare const ACTA_IDL_SHA256 = "85637746c4aabc7c4638de439ca8cf3cf6dfda58b2e26e5347077abdb78958dc";
1
+ export declare const ACTA_IDL_SHA256 = "8072bc43541635b8c359d8c0209c3ab63f6a264d6843997d20c9d6c9473130c9";
package/dist/idl/hash.js CHANGED
@@ -1 +1 @@
1
- export const ACTA_IDL_SHA256 = "85637746c4aabc7c4638de439ca8cf3cf6dfda58b2e26e5347077abdb78958dc";
1
+ export const ACTA_IDL_SHA256 = "8072bc43541635b8c359d8c0209c3ab63f6a264d6843997d20c9d6c9473130c9";
@@ -2,7 +2,7 @@
2
2
  import type { AuthProvider } from "./auth";
3
3
  import type { SignerLike } from "../chain/orders";
4
4
  import type { Address } from "@solana/addresses";
5
- import type { ActiveRfqInfo, ChainEventMessage, GlobalStats, MarketDescriptorInfo, MarketInfo, MyActiveRfqInfo, MyActiveRfqsMessage, OrderStatusMessage, PositionInfo, QuoteAcknowledgedMessage, QuoteBestStatusMessage, QuoteCancelledMessage, QuoteMessage, QuoteRefreshRequestedMessage, QuoteOutbidMessage, QuoteReceivedMessage, QuoteSelectedMessage, QuotesUpdateMessage, RfqBroadcastMessage, RfqClosedMessage, RfqCreatedMessage, RfqSkippedMessage, RfqRequestMessage, RfqAvailableAgainMessage, QuoteExpiredMessage, QuoteFilledMessage, IndicativePricesMessage, IndicativePricesRequestMessage, IndicativePricesResponseMessage, GetIndicativePricesMessage, RequestId, ServerMessage, SnapshotMessage, StatsDelta, SubscriptionsMessage, TokenInfo, TradeInfo, UuidString, VersionMismatchMessage, WelcomeMessage, WsChannel } from "./types";
5
+ import type { ActiveRfqInfo, ChainEventMessage, EarnSummaryData, GlobalStats, MarketDescriptorInfo, MarketInfo, MyActiveRfqInfo, MyActiveRfqsMessage, OrderStatusMessage, PositionInfo, QuoteAcknowledgedMessage, QuoteBestStatusMessage, QuoteCancelledMessage, QuoteMessage, QuoteRefreshRequestedMessage, QuoteOutbidMessage, QuoteReceivedMessage, QuoteSelectedMessage, QuotesUpdateMessage, RfqBroadcastMessage, RfqClosedMessage, RfqCreatedMessage, RfqSkippedMessage, RfqRequestMessage, RfqAvailableAgainMessage, QuoteExpiredMessage, QuoteFilledMessage, IndicativePricesMessage, IndicativePricesRequestMessage, IndicativePricesResponseMessage, GetIndicativePricesMessage, RequestId, ServerMessage, SnapshotMessage, StatsDelta, SubscriptionsMessage, TokenInfo, TradeInfo, UuidString, VersionMismatchMessage, WelcomeMessage, WsChannel } from "./types";
6
6
  export type ConnectionState = "disconnected" | "connecting" | "authenticating" | "authenticated" | "error";
7
7
  export type ClientRole = "taker" | "maker";
8
8
  export type PendingMessagesOverflowPolicy = "drop_oldest" | "drop_newest" | "throw";
@@ -73,6 +73,7 @@ export type ActaWsClientEvents = {
73
73
  quotesByUnderlying: Record<string, TokenInfo[]>;
74
74
  }) => void;
75
75
  statsUpdate: (stats: GlobalStats) => void;
76
+ earnSummary: (data: EarnSummaryData) => void;
76
77
  subscriptions: (msg: SubscriptionsMessage) => void;
77
78
  activeRfqs: (rfqs: ActiveRfqInfo[]) => void;
78
79
  rfqBroadcast: (rfq: RfqBroadcastMessage) => void;
@@ -217,6 +218,7 @@ export declare class ActaWsClient extends TypedEventEmitter<ActaWsClientEvents>
217
218
  getTokenCaps(args?: {
218
219
  include_markets?: boolean;
219
220
  }): RequestId;
221
+ getEarnSummary(): RequestId;
220
222
  logout(): void;
221
223
  getOrderStatus(orderIdHex: string): RequestId;
222
224
  cancelRfq(rfqId: string): RequestId;
package/dist/ws/client.js CHANGED
@@ -316,6 +316,14 @@ export class ActaWsClient extends TypedEventEmitter {
316
316
  });
317
317
  return requestId;
318
318
  }
319
+ getEarnSummary() {
320
+ const requestId = this.nextRequestId();
321
+ this.send({
322
+ type: "GetEarnSummary",
323
+ data: { request_id: requestId },
324
+ });
325
+ return requestId;
326
+ }
319
327
  logout() {
320
328
  this.send({ type: "Logout" });
321
329
  }
@@ -555,6 +563,9 @@ export class ActaWsClient extends TypedEventEmitter {
555
563
  case "StatsUpdate":
556
564
  this.handleStatsUpdate(message.data.stats);
557
565
  break;
566
+ case "EarnSummary":
567
+ this.emit("earnSummary", message.data);
568
+ break;
558
569
  case "RfqBroadcast":
559
570
  // Keep local RFQ state reasonably fresh even without a new snapshot.
560
571
  if (!this.state.activeRfqs.has(message.data.rfq_id)) {
@@ -798,17 +809,6 @@ export class ActaWsClient extends TypedEventEmitter {
798
809
  this.emit("error", new Error(`Authentication failed: ${details}`));
799
810
  }
800
811
  handleSnapshot(snapshot) {
801
- this.state.stats = snapshot.stats;
802
- this.state.activeRfqs.clear();
803
- for (const rfq of snapshot.active_rfqs) {
804
- this.state.activeRfqs.set(rfq.rfq_id, rfq);
805
- }
806
- this.state.myActiveRfqs.clear();
807
- this.state.positions.clear();
808
- for (const position of snapshot.positions ?? []) {
809
- this.state.positions.set(position.pda, position);
810
- }
811
- this.state.recentTrades = snapshot.recent_trades ?? [];
812
812
  this.state.markets.clear();
813
813
  for (const market of snapshot.markets) {
814
814
  this.state.markets.set(market.pda, market);
@@ -1,15 +1,3 @@
1
- /**
2
- * WebSocket protocol types for Acta RFQ server.
3
- *
4
- * Source of truth:
5
- * - docs/state-machines-eng.md (protocol spec)
6
- * - rust-backend/shared/src/types/ws.rs (as-built reference)
7
- *
8
- * Notes:
9
- * - UUIDs are represented as strings in JSON.
10
- * - Rust uses u64 in many places; we model them as `number` for now.
11
- * If/when we need precision beyond JS safe integer, we can migrate to `bigint | string`.
12
- */
13
1
  import type { Address } from "@solana/addresses";
14
2
  export type UuidString = string;
15
3
  export type RequestId = string;
@@ -163,6 +151,9 @@ export type ClientMessage = {
163
151
  } | {
164
152
  type: "GetMyCaps";
165
153
  data: GetMyCapsMessage;
154
+ } | {
155
+ type: "GetEarnSummary";
156
+ data: GetEarnSummaryMessage;
166
157
  } | {
167
158
  type: "GetSubscriptions";
168
159
  data: GetSubscriptionsMessage;
@@ -466,6 +457,9 @@ export type ServerMessage = {
466
457
  } | {
467
458
  type: "StatsUpdate";
468
459
  data: StatsUpdateMessage;
460
+ } | {
461
+ type: "EarnSummary";
462
+ data: EarnSummaryData;
469
463
  } | {
470
464
  type: "RfqSkipped";
471
465
  data: RfqSkippedMessage;
@@ -741,7 +735,7 @@ export type MakerPositionInfo = {
741
735
  quantity: WsU64;
742
736
  price: WsU64;
743
737
  /** Net premium amount from on-chain position state (quote token base units). */
744
- total_premium?: WsU64;
738
+ total_premium: WsU64;
745
739
  collateral_locked: WsU64;
746
740
  created_at: WsU64;
747
741
  expiry_ts: WsU64;
@@ -949,10 +943,6 @@ export type TokensMessage = {
949
943
  quotes_by_underlying: Record<Address<string>, TokenInfo[]>;
950
944
  };
951
945
  export type SnapshotMessage = {
952
- stats: GlobalStats;
953
- active_rfqs: ActiveRfqInfo[];
954
- positions?: PositionInfo[];
955
- recent_trades?: TradeInfo[];
956
946
  markets: MarketInfo[];
957
947
  };
958
948
  export type MyActiveRfqsMessage = {
@@ -1014,7 +1004,7 @@ export type PositionInfo = {
1014
1004
  quantity: WsU64;
1015
1005
  price: WsU64;
1016
1006
  /** Net premium amount from on-chain position state (quote token base units). */
1017
- total_premium?: WsU64;
1007
+ total_premium: WsU64;
1018
1008
  created_at: WsU64;
1019
1009
  /** Market expiry timestamp (unix seconds), sourced from markets table join. */
1020
1010
  expiry_ts: WsU64;
@@ -1052,6 +1042,28 @@ export type PositionUpdateType = string;
1052
1042
  export type StatsUpdateMessage = {
1053
1043
  stats: GlobalStats;
1054
1044
  };
1045
+ export type GetEarnSummaryMessage = {
1046
+ request_id: RequestId;
1047
+ };
1048
+ export type EarnAssetSummary = {
1049
+ underlying_mint: string;
1050
+ underlying_symbol: string;
1051
+ quote_mint: string;
1052
+ quote_symbol: string;
1053
+ position_type: PositionType;
1054
+ min_apr: number | null;
1055
+ max_apr: number | null;
1056
+ cap_filled_pct: number;
1057
+ cap_total: WsU64;
1058
+ cap_used: WsU64;
1059
+ strikes_count: number;
1060
+ nearest_expiry_ts: number;
1061
+ };
1062
+ export type EarnSummaryData = {
1063
+ request_id: RequestId;
1064
+ assets: EarnAssetSummary[];
1065
+ computed_at: number;
1066
+ };
1055
1067
  export type StatsDelta = {
1056
1068
  volume_added?: WsU64 | null;
1057
1069
  trades_added?: WsU32 | null;
package/dist/ws/types.js CHANGED
@@ -1,13 +1 @@
1
- /**
2
- * WebSocket protocol types for Acta RFQ server.
3
- *
4
- * Source of truth:
5
- * - docs/state-machines-eng.md (protocol spec)
6
- * - rust-backend/shared/src/types/ws.rs (as-built reference)
7
- *
8
- * Notes:
9
- * - UUIDs are represented as strings in JSON.
10
- * - Rust uses u64 in many places; we model them as `number` for now.
11
- * If/when we need precision beyond JS safe integer, we can migrate to `bigint | string`.
12
- */
13
1
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acta-markets/ts-sdk",
3
- "version": "0.0.14-beta",
3
+ "version": "0.0.16-beta",
4
4
  "description": "TypeScript SDK for Acta Protocol",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",