@acta-markets/ts-sdk 0.0.17-beta → 0.0.19-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/dist/cjs/ws/client.handshake.integration.test.js +2 -1
- package/dist/cjs/ws/client.js +43 -14
- package/dist/cjs/ws/client.test.js +5 -1
- package/dist/ws/client.d.ts +18 -4
- package/dist/ws/client.handshake.integration.test.js +2 -1
- package/dist/ws/client.js +43 -14
- package/dist/ws/client.test.js +5 -1
- package/dist/ws/types.d.ts +55 -0
- package/package.json +1 -1
|
@@ -55,7 +55,8 @@ describeIfWsUrl("ws handshake integration (real backend)", () => {
|
|
|
55
55
|
});
|
|
56
56
|
client.on("error", (err) => {
|
|
57
57
|
if (!welcomeReceived) {
|
|
58
|
-
|
|
58
|
+
const msg = err.type === "generic" ? err.data.message : err.type;
|
|
59
|
+
finish(new Error(msg));
|
|
59
60
|
}
|
|
60
61
|
});
|
|
61
62
|
client.on("disconnected", (code, reason) => {
|
package/dist/cjs/ws/client.js
CHANGED
|
@@ -4,6 +4,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
exports.ActaWsClient = void 0;
|
|
5
5
|
const flows_1 = require("./flows");
|
|
6
6
|
const wirePolicy_1 = require("./wirePolicy");
|
|
7
|
+
function toGenericServerError(err) {
|
|
8
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
9
|
+
return { type: "generic", data: { code: "client_error", message } };
|
|
10
|
+
}
|
|
7
11
|
function formatServerError(error) {
|
|
8
12
|
if (error.type === "generic") {
|
|
9
13
|
return `${error.data.code}: ${error.data.message}`;
|
|
@@ -160,7 +164,7 @@ class ActaWsClient extends TypedEventEmitter {
|
|
|
160
164
|
if (this.ws?.readyState === WS_OPEN) {
|
|
161
165
|
if (this.welcomeReceived && !this.startAuthSent) {
|
|
162
166
|
void this.beginAuthHandshake().catch((err) => {
|
|
163
|
-
this.emit("error", err);
|
|
167
|
+
this.emit("error", toGenericServerError(err));
|
|
164
168
|
this.setConnectionState("error");
|
|
165
169
|
});
|
|
166
170
|
}
|
|
@@ -327,6 +331,14 @@ class ActaWsClient extends TypedEventEmitter {
|
|
|
327
331
|
});
|
|
328
332
|
return requestId;
|
|
329
333
|
}
|
|
334
|
+
getTokenMarketsInfo(underlyingMint) {
|
|
335
|
+
const requestId = this.nextRequestId();
|
|
336
|
+
this.send({
|
|
337
|
+
type: "GetTokenMarketsInfo",
|
|
338
|
+
data: { request_id: requestId, underlying_mint: underlyingMint },
|
|
339
|
+
});
|
|
340
|
+
return requestId;
|
|
341
|
+
}
|
|
330
342
|
logout() {
|
|
331
343
|
this.send({ type: "Logout" });
|
|
332
344
|
}
|
|
@@ -385,6 +397,7 @@ class ActaWsClient extends TypedEventEmitter {
|
|
|
385
397
|
}
|
|
386
398
|
subscribe(channels, markets) {
|
|
387
399
|
this.ensureAuthenticated();
|
|
400
|
+
const request_id = this.nextRequestId();
|
|
388
401
|
for (const c of channels)
|
|
389
402
|
this.subscribedChannels.add(c);
|
|
390
403
|
if (markets) {
|
|
@@ -394,18 +407,21 @@ class ActaWsClient extends TypedEventEmitter {
|
|
|
394
407
|
this.send({
|
|
395
408
|
type: "Subscribe",
|
|
396
409
|
data: this.hasMarketScope
|
|
397
|
-
? { channels, markets: Array.from(this.subscribedMarkets) }
|
|
398
|
-
: { channels },
|
|
410
|
+
? { request_id, channels, markets: Array.from(this.subscribedMarkets) }
|
|
411
|
+
: { request_id, channels },
|
|
399
412
|
});
|
|
413
|
+
return request_id;
|
|
400
414
|
}
|
|
401
415
|
unsubscribe(channels) {
|
|
402
416
|
this.ensureAuthenticated();
|
|
417
|
+
const request_id = this.nextRequestId();
|
|
403
418
|
for (const c of channels)
|
|
404
419
|
this.subscribedChannels.delete(c);
|
|
405
420
|
this.send({
|
|
406
421
|
type: "Unsubscribe",
|
|
407
|
-
data: { channels },
|
|
422
|
+
data: { request_id, channels },
|
|
408
423
|
});
|
|
424
|
+
return request_id;
|
|
409
425
|
}
|
|
410
426
|
ping() {
|
|
411
427
|
if (this.ws?.readyState === WS_OPEN) {
|
|
@@ -460,7 +476,7 @@ class ActaWsClient extends TypedEventEmitter {
|
|
|
460
476
|
};
|
|
461
477
|
ws.onerror = (ev) => {
|
|
462
478
|
this.log("WebSocket error:", ev);
|
|
463
|
-
this.emit("error",
|
|
479
|
+
this.emit("error", toGenericServerError("WebSocket error"));
|
|
464
480
|
if (this.shouldReconnect) {
|
|
465
481
|
this.cleanup();
|
|
466
482
|
this.scheduleReconnect();
|
|
@@ -477,7 +493,7 @@ class ActaWsClient extends TypedEventEmitter {
|
|
|
477
493
|
this.flushPendingMessages();
|
|
478
494
|
if (this.authRequested && this.authProvider && !this.startAuthSent) {
|
|
479
495
|
void this.beginAuthHandshake().catch((err) => {
|
|
480
|
-
this.emit("error", err);
|
|
496
|
+
this.emit("error", toGenericServerError(err));
|
|
481
497
|
this.setConnectionState("error");
|
|
482
498
|
});
|
|
483
499
|
}
|
|
@@ -569,6 +585,9 @@ class ActaWsClient extends TypedEventEmitter {
|
|
|
569
585
|
case "EarnSummary":
|
|
570
586
|
this.emit("earnSummary", message.data);
|
|
571
587
|
break;
|
|
588
|
+
case "TokenMarketsInfo":
|
|
589
|
+
this.emit("tokenMarketsInfo", message.data);
|
|
590
|
+
break;
|
|
572
591
|
case "RfqBroadcast":
|
|
573
592
|
// Keep local RFQ state reasonably fresh even without a new snapshot.
|
|
574
593
|
if (!this.state.activeRfqs.has(message.data.rfq_id)) {
|
|
@@ -700,7 +719,16 @@ class ActaWsClient extends TypedEventEmitter {
|
|
|
700
719
|
case "Pong":
|
|
701
720
|
break;
|
|
702
721
|
case "Error":
|
|
703
|
-
this.emit("error",
|
|
722
|
+
this.emit("error", message.data);
|
|
723
|
+
break;
|
|
724
|
+
case "RequestError":
|
|
725
|
+
this.emit("requestError", message.data);
|
|
726
|
+
break;
|
|
727
|
+
case "SubscribeAck":
|
|
728
|
+
this.emit("subscribeAck", message.data);
|
|
729
|
+
break;
|
|
730
|
+
case "UnsubscribeAck":
|
|
731
|
+
this.emit("unsubscribeAck", message.data);
|
|
704
732
|
break;
|
|
705
733
|
}
|
|
706
734
|
}
|
|
@@ -721,7 +749,7 @@ class ActaWsClient extends TypedEventEmitter {
|
|
|
721
749
|
async handleAuthRequest(challenge) {
|
|
722
750
|
this.setConnectionState("authenticating");
|
|
723
751
|
if (!this.authProvider) {
|
|
724
|
-
this.emit("error",
|
|
752
|
+
this.emit("error", toGenericServerError("No auth provider configured"));
|
|
725
753
|
return;
|
|
726
754
|
}
|
|
727
755
|
try {
|
|
@@ -735,7 +763,7 @@ class ActaWsClient extends TypedEventEmitter {
|
|
|
735
763
|
});
|
|
736
764
|
}
|
|
737
765
|
catch (err) {
|
|
738
|
-
this.emit("error", err);
|
|
766
|
+
this.emit("error", toGenericServerError(err));
|
|
739
767
|
this.setConnectionState("error");
|
|
740
768
|
}
|
|
741
769
|
}
|
|
@@ -786,9 +814,10 @@ class ActaWsClient extends TypedEventEmitter {
|
|
|
786
814
|
this.emit("authenticated", sessionId, expiresAt);
|
|
787
815
|
if (this.subscribedChannels.size > 0) {
|
|
788
816
|
const channels = Array.from(this.subscribedChannels);
|
|
817
|
+
const request_id = this.nextRequestId();
|
|
789
818
|
const data = this.hasMarketScope
|
|
790
|
-
? { channels, markets: Array.from(this.subscribedMarkets) }
|
|
791
|
-
: { channels };
|
|
819
|
+
? { request_id, channels, markets: Array.from(this.subscribedMarkets) }
|
|
820
|
+
: { request_id, channels };
|
|
792
821
|
this.send({ type: "Subscribe", data });
|
|
793
822
|
}
|
|
794
823
|
}
|
|
@@ -802,14 +831,14 @@ class ActaWsClient extends TypedEventEmitter {
|
|
|
802
831
|
this.lastAuthSessionId = null;
|
|
803
832
|
this.startAuthSent = false;
|
|
804
833
|
void this.sendStartAuth().catch((err) => {
|
|
805
|
-
this.emit("error", err);
|
|
834
|
+
this.emit("error", toGenericServerError(err));
|
|
806
835
|
this.setConnectionState("error");
|
|
807
836
|
});
|
|
808
837
|
return;
|
|
809
838
|
}
|
|
810
839
|
this.setConnectionState("error");
|
|
811
840
|
const details = message ? `${reason}: ${message}` : reason;
|
|
812
|
-
this.emit("error",
|
|
841
|
+
this.emit("error", toGenericServerError(`Authentication failed: ${details}`));
|
|
813
842
|
}
|
|
814
843
|
handleSnapshot(snapshot) {
|
|
815
844
|
this.state.markets.clear();
|
|
@@ -948,7 +977,7 @@ class ActaWsClient extends TypedEventEmitter {
|
|
|
948
977
|
this.log("Pending queue full, dropping newest message:", message.type);
|
|
949
978
|
return false;
|
|
950
979
|
case "throw":
|
|
951
|
-
this.emit("error",
|
|
980
|
+
this.emit("error", toGenericServerError(`Pending queue overflow (maxPendingMessages=${maxPending}) for message type=${message.type}`));
|
|
952
981
|
return false;
|
|
953
982
|
}
|
|
954
983
|
}
|
|
@@ -420,7 +420,11 @@ describe("ActaWsClient", () => {
|
|
|
420
420
|
client.getMarkets();
|
|
421
421
|
client.getTokens();
|
|
422
422
|
expect(errors).toHaveLength(1);
|
|
423
|
-
|
|
423
|
+
const err0 = errors[0];
|
|
424
|
+
expect(err0.type).toBe("generic");
|
|
425
|
+
if (err0.type === "generic") {
|
|
426
|
+
expect(err0.data.message).toContain("Pending queue overflow");
|
|
427
|
+
}
|
|
424
428
|
ws.triggerMessage(WELCOME_MESSAGE);
|
|
425
429
|
const flushedTypes = ws.sent
|
|
426
430
|
.slice(1)
|
package/dist/ws/client.d.ts
CHANGED
|
@@ -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, 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";
|
|
5
|
+
import type { ActiveRfqInfo, ChainEventMessage, EarnSummaryData, TokenMarketsInfoData, 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, ServerError, 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";
|
|
@@ -60,7 +60,19 @@ export type ActaWsClientEvents = {
|
|
|
60
60
|
authError: (reason: string, message?: string) => void;
|
|
61
61
|
logoutSuccess: () => void;
|
|
62
62
|
disconnected: (code: number, reason: string) => void;
|
|
63
|
-
error: (error:
|
|
63
|
+
error: (error: ServerError) => void;
|
|
64
|
+
requestError: (data: {
|
|
65
|
+
request_id: RequestId;
|
|
66
|
+
error: ServerError;
|
|
67
|
+
}) => void;
|
|
68
|
+
subscribeAck: (data: {
|
|
69
|
+
request_id: RequestId;
|
|
70
|
+
subscribed: WsChannel[];
|
|
71
|
+
}) => void;
|
|
72
|
+
unsubscribeAck: (data: {
|
|
73
|
+
request_id: RequestId;
|
|
74
|
+
unsubscribed: WsChannel[];
|
|
75
|
+
}) => void;
|
|
64
76
|
stateChange: (state: ConnectionState) => void;
|
|
65
77
|
message: (message: ServerMessage) => void;
|
|
66
78
|
snapshot: (snapshot: SnapshotMessage) => void;
|
|
@@ -74,6 +86,7 @@ export type ActaWsClientEvents = {
|
|
|
74
86
|
}) => void;
|
|
75
87
|
statsUpdate: (stats: GlobalStats) => void;
|
|
76
88
|
earnSummary: (data: EarnSummaryData) => void;
|
|
89
|
+
tokenMarketsInfo: (data: TokenMarketsInfoData) => void;
|
|
77
90
|
subscriptions: (msg: SubscriptionsMessage) => void;
|
|
78
91
|
activeRfqs: (rfqs: ActiveRfqInfo[]) => void;
|
|
79
92
|
rfqBroadcast: (rfq: RfqBroadcastMessage) => void;
|
|
@@ -219,6 +232,7 @@ export declare class ActaWsClient extends TypedEventEmitter<ActaWsClientEvents>
|
|
|
219
232
|
include_markets?: boolean;
|
|
220
233
|
}): RequestId;
|
|
221
234
|
getEarnSummary(): RequestId;
|
|
235
|
+
getTokenMarketsInfo(underlyingMint: string): RequestId;
|
|
222
236
|
logout(): void;
|
|
223
237
|
getOrderStatus(orderIdHex: string): RequestId;
|
|
224
238
|
cancelRfq(rfqId: string): RequestId;
|
|
@@ -239,8 +253,8 @@ export declare class ActaWsClient extends TypedEventEmitter<ActaWsClientEvents>
|
|
|
239
253
|
makerSigner: SignerLike;
|
|
240
254
|
}): Promise<void>;
|
|
241
255
|
cancelQuote(rfqId: string): RequestId;
|
|
242
|
-
subscribe(channels: WsChannel[], markets?: string[]):
|
|
243
|
-
unsubscribe(channels: WsChannel[]):
|
|
256
|
+
subscribe(channels: WsChannel[], markets?: string[]): RequestId;
|
|
257
|
+
unsubscribe(channels: WsChannel[]): RequestId;
|
|
244
258
|
ping(): void;
|
|
245
259
|
resumeAuth(sessionId: string): void;
|
|
246
260
|
private doConnect;
|
|
@@ -50,7 +50,8 @@ describeIfWsUrl("ws handshake integration (real backend)", () => {
|
|
|
50
50
|
});
|
|
51
51
|
client.on("error", (err) => {
|
|
52
52
|
if (!welcomeReceived) {
|
|
53
|
-
|
|
53
|
+
const msg = err.type === "generic" ? err.data.message : err.type;
|
|
54
|
+
finish(new Error(msg));
|
|
54
55
|
}
|
|
55
56
|
});
|
|
56
57
|
client.on("disconnected", (code, reason) => {
|
package/dist/ws/client.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/** Acta WebSocket client (rfq-server). */
|
|
2
2
|
import { buildSignedQuoteMessage, buildAcceptQuoteMessage } from "./flows";
|
|
3
3
|
import { assertWsU64Safe, validateQuantityBySizeRule } from "./wirePolicy";
|
|
4
|
+
function toGenericServerError(err) {
|
|
5
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
6
|
+
return { type: "generic", data: { code: "client_error", message } };
|
|
7
|
+
}
|
|
4
8
|
function formatServerError(error) {
|
|
5
9
|
if (error.type === "generic") {
|
|
6
10
|
return `${error.data.code}: ${error.data.message}`;
|
|
@@ -157,7 +161,7 @@ export class ActaWsClient extends TypedEventEmitter {
|
|
|
157
161
|
if (this.ws?.readyState === WS_OPEN) {
|
|
158
162
|
if (this.welcomeReceived && !this.startAuthSent) {
|
|
159
163
|
void this.beginAuthHandshake().catch((err) => {
|
|
160
|
-
this.emit("error", err);
|
|
164
|
+
this.emit("error", toGenericServerError(err));
|
|
161
165
|
this.setConnectionState("error");
|
|
162
166
|
});
|
|
163
167
|
}
|
|
@@ -324,6 +328,14 @@ export class ActaWsClient extends TypedEventEmitter {
|
|
|
324
328
|
});
|
|
325
329
|
return requestId;
|
|
326
330
|
}
|
|
331
|
+
getTokenMarketsInfo(underlyingMint) {
|
|
332
|
+
const requestId = this.nextRequestId();
|
|
333
|
+
this.send({
|
|
334
|
+
type: "GetTokenMarketsInfo",
|
|
335
|
+
data: { request_id: requestId, underlying_mint: underlyingMint },
|
|
336
|
+
});
|
|
337
|
+
return requestId;
|
|
338
|
+
}
|
|
327
339
|
logout() {
|
|
328
340
|
this.send({ type: "Logout" });
|
|
329
341
|
}
|
|
@@ -382,6 +394,7 @@ export class ActaWsClient extends TypedEventEmitter {
|
|
|
382
394
|
}
|
|
383
395
|
subscribe(channels, markets) {
|
|
384
396
|
this.ensureAuthenticated();
|
|
397
|
+
const request_id = this.nextRequestId();
|
|
385
398
|
for (const c of channels)
|
|
386
399
|
this.subscribedChannels.add(c);
|
|
387
400
|
if (markets) {
|
|
@@ -391,18 +404,21 @@ export class ActaWsClient extends TypedEventEmitter {
|
|
|
391
404
|
this.send({
|
|
392
405
|
type: "Subscribe",
|
|
393
406
|
data: this.hasMarketScope
|
|
394
|
-
? { channels, markets: Array.from(this.subscribedMarkets) }
|
|
395
|
-
: { channels },
|
|
407
|
+
? { request_id, channels, markets: Array.from(this.subscribedMarkets) }
|
|
408
|
+
: { request_id, channels },
|
|
396
409
|
});
|
|
410
|
+
return request_id;
|
|
397
411
|
}
|
|
398
412
|
unsubscribe(channels) {
|
|
399
413
|
this.ensureAuthenticated();
|
|
414
|
+
const request_id = this.nextRequestId();
|
|
400
415
|
for (const c of channels)
|
|
401
416
|
this.subscribedChannels.delete(c);
|
|
402
417
|
this.send({
|
|
403
418
|
type: "Unsubscribe",
|
|
404
|
-
data: { channels },
|
|
419
|
+
data: { request_id, channels },
|
|
405
420
|
});
|
|
421
|
+
return request_id;
|
|
406
422
|
}
|
|
407
423
|
ping() {
|
|
408
424
|
if (this.ws?.readyState === WS_OPEN) {
|
|
@@ -457,7 +473,7 @@ export class ActaWsClient extends TypedEventEmitter {
|
|
|
457
473
|
};
|
|
458
474
|
ws.onerror = (ev) => {
|
|
459
475
|
this.log("WebSocket error:", ev);
|
|
460
|
-
this.emit("error",
|
|
476
|
+
this.emit("error", toGenericServerError("WebSocket error"));
|
|
461
477
|
if (this.shouldReconnect) {
|
|
462
478
|
this.cleanup();
|
|
463
479
|
this.scheduleReconnect();
|
|
@@ -474,7 +490,7 @@ export class ActaWsClient extends TypedEventEmitter {
|
|
|
474
490
|
this.flushPendingMessages();
|
|
475
491
|
if (this.authRequested && this.authProvider && !this.startAuthSent) {
|
|
476
492
|
void this.beginAuthHandshake().catch((err) => {
|
|
477
|
-
this.emit("error", err);
|
|
493
|
+
this.emit("error", toGenericServerError(err));
|
|
478
494
|
this.setConnectionState("error");
|
|
479
495
|
});
|
|
480
496
|
}
|
|
@@ -566,6 +582,9 @@ export class ActaWsClient extends TypedEventEmitter {
|
|
|
566
582
|
case "EarnSummary":
|
|
567
583
|
this.emit("earnSummary", message.data);
|
|
568
584
|
break;
|
|
585
|
+
case "TokenMarketsInfo":
|
|
586
|
+
this.emit("tokenMarketsInfo", message.data);
|
|
587
|
+
break;
|
|
569
588
|
case "RfqBroadcast":
|
|
570
589
|
// Keep local RFQ state reasonably fresh even without a new snapshot.
|
|
571
590
|
if (!this.state.activeRfqs.has(message.data.rfq_id)) {
|
|
@@ -697,7 +716,16 @@ export class ActaWsClient extends TypedEventEmitter {
|
|
|
697
716
|
case "Pong":
|
|
698
717
|
break;
|
|
699
718
|
case "Error":
|
|
700
|
-
this.emit("error",
|
|
719
|
+
this.emit("error", message.data);
|
|
720
|
+
break;
|
|
721
|
+
case "RequestError":
|
|
722
|
+
this.emit("requestError", message.data);
|
|
723
|
+
break;
|
|
724
|
+
case "SubscribeAck":
|
|
725
|
+
this.emit("subscribeAck", message.data);
|
|
726
|
+
break;
|
|
727
|
+
case "UnsubscribeAck":
|
|
728
|
+
this.emit("unsubscribeAck", message.data);
|
|
701
729
|
break;
|
|
702
730
|
}
|
|
703
731
|
}
|
|
@@ -718,7 +746,7 @@ export class ActaWsClient extends TypedEventEmitter {
|
|
|
718
746
|
async handleAuthRequest(challenge) {
|
|
719
747
|
this.setConnectionState("authenticating");
|
|
720
748
|
if (!this.authProvider) {
|
|
721
|
-
this.emit("error",
|
|
749
|
+
this.emit("error", toGenericServerError("No auth provider configured"));
|
|
722
750
|
return;
|
|
723
751
|
}
|
|
724
752
|
try {
|
|
@@ -732,7 +760,7 @@ export class ActaWsClient extends TypedEventEmitter {
|
|
|
732
760
|
});
|
|
733
761
|
}
|
|
734
762
|
catch (err) {
|
|
735
|
-
this.emit("error", err);
|
|
763
|
+
this.emit("error", toGenericServerError(err));
|
|
736
764
|
this.setConnectionState("error");
|
|
737
765
|
}
|
|
738
766
|
}
|
|
@@ -783,9 +811,10 @@ export class ActaWsClient extends TypedEventEmitter {
|
|
|
783
811
|
this.emit("authenticated", sessionId, expiresAt);
|
|
784
812
|
if (this.subscribedChannels.size > 0) {
|
|
785
813
|
const channels = Array.from(this.subscribedChannels);
|
|
814
|
+
const request_id = this.nextRequestId();
|
|
786
815
|
const data = this.hasMarketScope
|
|
787
|
-
? { channels, markets: Array.from(this.subscribedMarkets) }
|
|
788
|
-
: { channels };
|
|
816
|
+
? { request_id, channels, markets: Array.from(this.subscribedMarkets) }
|
|
817
|
+
: { request_id, channels };
|
|
789
818
|
this.send({ type: "Subscribe", data });
|
|
790
819
|
}
|
|
791
820
|
}
|
|
@@ -799,14 +828,14 @@ export class ActaWsClient extends TypedEventEmitter {
|
|
|
799
828
|
this.lastAuthSessionId = null;
|
|
800
829
|
this.startAuthSent = false;
|
|
801
830
|
void this.sendStartAuth().catch((err) => {
|
|
802
|
-
this.emit("error", err);
|
|
831
|
+
this.emit("error", toGenericServerError(err));
|
|
803
832
|
this.setConnectionState("error");
|
|
804
833
|
});
|
|
805
834
|
return;
|
|
806
835
|
}
|
|
807
836
|
this.setConnectionState("error");
|
|
808
837
|
const details = message ? `${reason}: ${message}` : reason;
|
|
809
|
-
this.emit("error",
|
|
838
|
+
this.emit("error", toGenericServerError(`Authentication failed: ${details}`));
|
|
810
839
|
}
|
|
811
840
|
handleSnapshot(snapshot) {
|
|
812
841
|
this.state.markets.clear();
|
|
@@ -945,7 +974,7 @@ export class ActaWsClient extends TypedEventEmitter {
|
|
|
945
974
|
this.log("Pending queue full, dropping newest message:", message.type);
|
|
946
975
|
return false;
|
|
947
976
|
case "throw":
|
|
948
|
-
this.emit("error",
|
|
977
|
+
this.emit("error", toGenericServerError(`Pending queue overflow (maxPendingMessages=${maxPending}) for message type=${message.type}`));
|
|
949
978
|
return false;
|
|
950
979
|
}
|
|
951
980
|
}
|
package/dist/ws/client.test.js
CHANGED
|
@@ -418,7 +418,11 @@ describe("ActaWsClient", () => {
|
|
|
418
418
|
client.getMarkets();
|
|
419
419
|
client.getTokens();
|
|
420
420
|
expect(errors).toHaveLength(1);
|
|
421
|
-
|
|
421
|
+
const err0 = errors[0];
|
|
422
|
+
expect(err0.type).toBe("generic");
|
|
423
|
+
if (err0.type === "generic") {
|
|
424
|
+
expect(err0.data.message).toContain("Pending queue overflow");
|
|
425
|
+
}
|
|
422
426
|
ws.triggerMessage(WELCOME_MESSAGE);
|
|
423
427
|
const flushedTypes = ws.sent
|
|
424
428
|
.slice(1)
|
package/dist/ws/types.d.ts
CHANGED
|
@@ -154,6 +154,9 @@ export type ClientMessage = {
|
|
|
154
154
|
} | {
|
|
155
155
|
type: "GetEarnSummary";
|
|
156
156
|
data: GetEarnSummaryMessage;
|
|
157
|
+
} | {
|
|
158
|
+
type: "GetTokenMarketsInfo";
|
|
159
|
+
data: GetTokenMarketsInfoMessage;
|
|
157
160
|
} | {
|
|
158
161
|
type: "GetMyTrades";
|
|
159
162
|
data: GetMyTradesMessage;
|
|
@@ -168,12 +171,14 @@ export type ClientMessage = {
|
|
|
168
171
|
} | {
|
|
169
172
|
type: "Subscribe";
|
|
170
173
|
data: {
|
|
174
|
+
request_id: RequestId;
|
|
171
175
|
channels: WsChannel[];
|
|
172
176
|
markets?: string[];
|
|
173
177
|
};
|
|
174
178
|
} | {
|
|
175
179
|
type: "Unsubscribe";
|
|
176
180
|
data: {
|
|
181
|
+
request_id: RequestId;
|
|
177
182
|
channels: WsChannel[];
|
|
178
183
|
};
|
|
179
184
|
};
|
|
@@ -463,6 +468,9 @@ export type ServerMessage = {
|
|
|
463
468
|
} | {
|
|
464
469
|
type: "EarnSummary";
|
|
465
470
|
data: EarnSummaryData;
|
|
471
|
+
} | {
|
|
472
|
+
type: "TokenMarketsInfo";
|
|
473
|
+
data: TokenMarketsInfoData;
|
|
466
474
|
} | {
|
|
467
475
|
type: "MyTrades";
|
|
468
476
|
data: MyTradesMessage;
|
|
@@ -477,6 +485,24 @@ export type ServerMessage = {
|
|
|
477
485
|
} | {
|
|
478
486
|
type: "Error";
|
|
479
487
|
data: ServerError;
|
|
488
|
+
} | {
|
|
489
|
+
type: "RequestError";
|
|
490
|
+
data: {
|
|
491
|
+
request_id: RequestId;
|
|
492
|
+
error: ServerError;
|
|
493
|
+
};
|
|
494
|
+
} | {
|
|
495
|
+
type: "SubscribeAck";
|
|
496
|
+
data: {
|
|
497
|
+
request_id: RequestId;
|
|
498
|
+
subscribed: WsChannel[];
|
|
499
|
+
};
|
|
500
|
+
} | {
|
|
501
|
+
type: "UnsubscribeAck";
|
|
502
|
+
data: {
|
|
503
|
+
request_id: RequestId;
|
|
504
|
+
unsubscribed: WsChannel[];
|
|
505
|
+
};
|
|
480
506
|
};
|
|
481
507
|
export type MarketDescriptorInfo = {
|
|
482
508
|
market: MarketDescriptor;
|
|
@@ -1072,6 +1098,35 @@ export type EarnSummaryData = {
|
|
|
1072
1098
|
assets: EarnAssetSummary[];
|
|
1073
1099
|
computed_at: number;
|
|
1074
1100
|
};
|
|
1101
|
+
export type GetTokenMarketsInfoMessage = {
|
|
1102
|
+
request_id: RequestId;
|
|
1103
|
+
underlying_mint: string;
|
|
1104
|
+
};
|
|
1105
|
+
export type TokenMarketIndicatives = {
|
|
1106
|
+
position_type: PositionType;
|
|
1107
|
+
updated_at: WsU64;
|
|
1108
|
+
is_stale: boolean;
|
|
1109
|
+
strikes: Array<{
|
|
1110
|
+
strike: WsU64;
|
|
1111
|
+
best_price?: WsU64 | null;
|
|
1112
|
+
}>;
|
|
1113
|
+
};
|
|
1114
|
+
export type TokenMarketEntry = {
|
|
1115
|
+
market_pda: string;
|
|
1116
|
+
expiry_ts: WsU64;
|
|
1117
|
+
is_put: boolean;
|
|
1118
|
+
indicatives: TokenMarketIndicatives[];
|
|
1119
|
+
};
|
|
1120
|
+
export type TokenMarketsInfoData = {
|
|
1121
|
+
request_id: RequestId;
|
|
1122
|
+
underlying_symbol: string;
|
|
1123
|
+
underlying_decimals: WsU64;
|
|
1124
|
+
quote_symbol: string;
|
|
1125
|
+
quote_decimals: WsU64;
|
|
1126
|
+
size_rule: PositionSizeRule;
|
|
1127
|
+
reference_price: WsU64;
|
|
1128
|
+
markets: TokenMarketEntry[];
|
|
1129
|
+
};
|
|
1075
1130
|
export type GetMyTradesMessage = {
|
|
1076
1131
|
request_id: RequestId;
|
|
1077
1132
|
limit?: WsU32;
|