@alpha-arcade/sdk 0.4.0 → 0.4.2

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
@@ -2,7 +2,7 @@
2
2
 
3
3
  TypeScript SDK for trading on **Alpha Market** — Algorand prediction markets.
4
4
 
5
- Place orders, manage positions, read orderbooks, and build automated trading bots — all directly on-chain.
5
+ Place orders, manage positions, read orderbooks from the API or chain, and build automated trading bots.
6
6
 
7
7
  ## Installation
8
8
 
@@ -246,7 +246,7 @@ for (const pos of positions) {
246
246
 
247
247
  #### `getOrderbook(marketAppId)`
248
248
 
249
- Fetches the full on-chain orderbook.
249
+ Fetches the full on-chain orderbook for a single market app.
250
250
 
251
251
  ```typescript
252
252
  const book = await client.getOrderbook(123456789);
@@ -263,6 +263,24 @@ if (book.yes.bids.length > 0) {
263
263
  }
264
264
  ```
265
265
 
266
+ #### `getFullOrderbookFromApi(marketId)`
267
+
268
+ Fetches the full processed orderbook snapshot for a market from the Alpha REST API. Requires `apiKey`.
269
+
270
+ This returns the same shape as websocket `orderbook_changed.orderbook`: a record keyed by `marketAppId`, where each value includes:
271
+ - top-level aggregated `bids`, `asks`, and `spread`
272
+ - detailed `yes` and `no` bid/ask orders with `escrowAppId` and `owner`
273
+
274
+ ```typescript
275
+ const snapshot = await client.getFullOrderbookFromApi('market-uuid-here');
276
+
277
+ for (const [appId, book] of Object.entries(snapshot)) {
278
+ console.log(`App ${appId}: spread=${book.spread}`);
279
+ console.log('Top-level bids:', book.bids);
280
+ console.log('Detailed YES bids:', book.yes.bids);
281
+ }
282
+ ```
283
+
266
284
  #### `getOpenOrders(marketAppId, walletAddress?)`
267
285
 
268
286
  Gets open orders for a wallet on a specific market (from on-chain data).
@@ -341,6 +359,27 @@ for (const m of rewardMarkets) {
341
359
 
342
360
  Real-time data streams via WebSocket. No API key or auth required. Replaces polling with push-based updates.
343
361
 
362
+ The SDK connects to the public platform websocket at `wss://wss.platform.alphaarcade.com`. The first
363
+ subscription is sent in the connection query string, and any later subscribe or unsubscribe calls use the
364
+ server's control-message envelope:
365
+
366
+ ```json
367
+ {
368
+ "id": "request-id",
369
+ "method": "SUBSCRIBE",
370
+ "params": [
371
+ { "stream": "get-orderbook", "slug": "will-btc-hit-100k" }
372
+ ]
373
+ }
374
+ ```
375
+
376
+ Supported public streams:
377
+
378
+ - `get-live-markets`
379
+ - `get-market` with `slug`
380
+ - `get-orderbook` with `slug`
381
+ - `get-wallet-orders` with `wallet`
382
+
344
383
  ```typescript
345
384
  import { AlphaWebSocket } from '@alpha-arcade/sdk';
346
385
 
@@ -386,7 +425,7 @@ ws.subscribeMarket('will-btc-hit-100k', (event) => {
386
425
 
387
426
  #### `subscribeOrderbook(slug, callback)`
388
427
 
389
- Receive full orderbook snapshots on every change (~5s interval). Replaces on-chain polling.
428
+ Receive full orderbook snapshots on every change (~5s interval). The payload matches `getFullOrderbookFromApi(marketId)`.
390
429
 
391
430
  **Note:** The WebSocket API uses market **slugs** (URL-friendly names like `"will-btc-hit-100k"`), not `marketAppId` numbers. You can get a market's slug from the `slug` field on `Market` objects returned by `getLiveMarkets()` or `getMarket()`.
392
431
 
@@ -429,7 +468,7 @@ unsub();
429
468
  // List active subscriptions on this connection
430
469
  const subs = await ws.listSubscriptions();
431
470
 
432
- // Query server properties
471
+ // Query server properties (`heartbeat` or `limits`)
433
472
  const props = await ws.getProperty('heartbeat');
434
473
  ```
435
474
 
package/dist/index.cjs CHANGED
@@ -2266,6 +2266,18 @@ var getWalletOrdersFromApi = async (config, walletAddress) => {
2266
2266
  }
2267
2267
  return allOrders;
2268
2268
  };
2269
+ var getFullOrderbookFromApi = async (config, marketId) => {
2270
+ if (!config.apiKey) {
2271
+ throw new Error("apiKey is required for API-based orderbook fetching. Retrieve an API key from the Alpha Arcade platform via the Account page and pass it to the client.");
2272
+ }
2273
+ const baseUrl = config.apiBaseUrl ?? DEFAULT_API_BASE_URL;
2274
+ const url = `${baseUrl}/get-full-orderbook?marketId=${encodeURIComponent(marketId)}`;
2275
+ const response = await fetch(url, { headers: { "x-api-key": config.apiKey } });
2276
+ if (!response.ok) {
2277
+ throw new Error(`Alpha API error: ${response.status} ${response.statusText}`);
2278
+ }
2279
+ return response.json();
2280
+ };
2269
2281
 
2270
2282
  // src/modules/trading.ts
2271
2283
  var extractEscrowAppId = async (algodClient, indexerClient, targetTxId) => {
@@ -3272,6 +3284,19 @@ var AlphaClient = class {
3272
3284
  async getOrderbook(marketAppId) {
3273
3285
  return getOrderbook(this.config, marketAppId);
3274
3286
  }
3287
+ /**
3288
+ * Fetches the full processed orderbook snapshot for a market from the Alpha REST API.
3289
+ *
3290
+ * Returns the same shape as websocket `orderbook_changed.orderbook`: a record keyed by
3291
+ * `marketAppId`, where each value includes aggregated bids/asks plus detailed yes/no orders.
3292
+ * Requires `apiKey`.
3293
+ *
3294
+ * @param marketId - The Alpha market UUID
3295
+ * @returns Full processed market orderbook keyed by marketAppId
3296
+ */
3297
+ async getFullOrderbookFromApi(marketId) {
3298
+ return getFullOrderbookFromApi(this.config, marketId);
3299
+ }
3275
3300
  /**
3276
3301
  * Gets open orders for a specific wallet on a market.
3277
3302
  *
@@ -3446,7 +3471,7 @@ var AlphaWebSocket = class {
3446
3471
  }
3447
3472
  /** Query a server property (e.g. "heartbeat", "limits") */
3448
3473
  getProperty(property) {
3449
- return this.sendRequest({ method: "GET_PROPERTY", property });
3474
+ return this.sendRequest({ method: "GET_PROPERTY", params: [property] });
3450
3475
  }
3451
3476
  // ============================================
3452
3477
  // Lifecycle
@@ -3546,9 +3571,10 @@ var AlphaWebSocket = class {
3546
3571
  this.send({ method: "PONG" });
3547
3572
  return;
3548
3573
  }
3549
- if (msg.requestId && this.pendingRequests.has(msg.requestId)) {
3550
- const req = this.pendingRequests.get(msg.requestId);
3551
- this.pendingRequests.delete(msg.requestId);
3574
+ const responseId = typeof msg.id === "string" ? msg.id : typeof msg.requestId === "string" ? msg.requestId : null;
3575
+ if (responseId && this.pendingRequests.has(responseId)) {
3576
+ const req = this.pendingRequests.get(responseId);
3577
+ this.pendingRequests.delete(responseId);
3552
3578
  clearTimeout(req.timer);
3553
3579
  req.resolve(msg);
3554
3580
  return;
@@ -3565,10 +3591,10 @@ var AlphaWebSocket = class {
3565
3591
  }
3566
3592
  }
3567
3593
  sendSubscribe(stream, params) {
3568
- this.send({ method: "SUBSCRIBE", stream, ...params });
3594
+ this.send({ method: "SUBSCRIBE", params: [{ stream, ...params }] });
3569
3595
  }
3570
3596
  sendUnsubscribe(stream, params) {
3571
- this.send({ method: "UNSUBSCRIBE", stream, ...params });
3597
+ this.send({ method: "UNSUBSCRIBE", params: [{ stream, ...params }] });
3572
3598
  }
3573
3599
  sendRequest(payload, timeoutMs = 1e4) {
3574
3600
  const requestId = crypto.randomUUID();
@@ -3580,10 +3606,10 @@ var AlphaWebSocket = class {
3580
3606
  this.pendingRequests.set(requestId, { resolve, reject, timer });
3581
3607
  if (!this.connected) {
3582
3608
  this.connect().then(() => {
3583
- this.send({ ...payload, requestId });
3609
+ this.send({ ...payload, id: requestId });
3584
3610
  }).catch(reject);
3585
3611
  } else {
3586
- this.send({ ...payload, requestId });
3612
+ this.send({ ...payload, id: requestId });
3587
3613
  }
3588
3614
  });
3589
3615
  }
@@ -3598,7 +3624,7 @@ var AlphaWebSocket = class {
3598
3624
  startHeartbeat() {
3599
3625
  this.stopHeartbeat();
3600
3626
  this.heartbeatTimer = setInterval(() => {
3601
- this.send({ type: "ping" });
3627
+ this.send({ method: "PING" });
3602
3628
  }, this.heartbeatIntervalMs);
3603
3629
  }
3604
3630
  stopHeartbeat() {