@imbingox/acex 0.4.0-beta.15 → 0.4.0-beta.17

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.
@@ -19,10 +19,15 @@ import {
19
19
  buildAcexErrorDetails,
20
20
  formatAcexErrorMessage,
21
21
  } from "../errors.ts";
22
+ import type {
23
+ AsyncEventBusOverflowInfo,
24
+ AsyncEventBusStreamOptions,
25
+ } from "../internal/async-event-bus.ts";
22
26
  import { AsyncEventBus } from "../internal/async-event-bus.ts";
23
27
  import { toCanonical } from "../internal/decimal.ts";
24
28
  import { matchesMarketFilter } from "../internal/filters.ts";
25
29
  import type {
30
+ EventStreamOptions,
26
31
  FundingRateSnapshot,
27
32
  FundingRateUpdatedEvent,
28
33
  L1Book,
@@ -67,6 +72,14 @@ interface MarketRecord {
67
72
  status: MarketDataStatus;
68
73
  l1BookStream?: StreamHandle;
69
74
  fundingRateStream?: StreamHandle;
75
+ lastPublishedStatusKey?: MarketStatusPublicationKey;
76
+ }
77
+
78
+ interface MarketStatusPublicationKey {
79
+ activity: MarketDataStatus["activity"];
80
+ ready: MarketDataStatus["ready"];
81
+ freshness: MarketDataStatus["freshness"];
82
+ reason: MarketDataStatus["reason"];
70
83
  }
71
84
 
72
85
  interface CatalogFetchResult {
@@ -85,10 +98,38 @@ function marketKey(input: MarketKeyInput): string {
85
98
  return `${input.venue}:${input.symbol}`;
86
99
  }
87
100
 
101
+ function marketEventConflateKey(event: MarketEvent): string {
102
+ return `${event.type}:${marketKey(event)}`;
103
+ }
104
+
88
105
  function cloneMarketStatus(status: MarketDataStatus): MarketDataStatus {
89
106
  return { ...status };
90
107
  }
91
108
 
109
+ function statusPublicationKey(
110
+ status: MarketDataStatus,
111
+ ): MarketStatusPublicationKey {
112
+ return {
113
+ activity: status.activity,
114
+ ready: status.ready,
115
+ freshness: status.freshness,
116
+ reason: status.reason,
117
+ };
118
+ }
119
+
120
+ function sameStatusPublicationKey(
121
+ current: MarketStatusPublicationKey,
122
+ previous: MarketStatusPublicationKey | undefined,
123
+ ): boolean {
124
+ return (
125
+ previous !== undefined &&
126
+ current.activity === previous.activity &&
127
+ current.ready === previous.ready &&
128
+ current.freshness === previous.freshness &&
129
+ current.reason === previous.reason
130
+ );
131
+ }
132
+
92
133
  function cloneStreamStatus(
93
134
  status: MarketDataStreamStatus,
94
135
  ): MarketDataStreamStatus {
@@ -153,23 +194,49 @@ export class MarketManagerImpl
153
194
  options.l1ReconnectMaxDelayMs ?? DEFAULT_L1_RECONNECT_MAX_DELAY_MS;
154
195
 
155
196
  this.events = {
156
- all: (filter) =>
157
- this.marketBus.stream((event) => matchesMarketFilter(event, filter)),
158
- fundingRateUpdates: (filter) =>
197
+ all: (filter, options) =>
198
+ this.marketBus.stream(
199
+ (event) => matchesMarketFilter(event, filter),
200
+ this.createStreamOptions(
201
+ "market.all",
202
+ options,
203
+ "buffer",
204
+ marketEventConflateKey,
205
+ ),
206
+ ),
207
+ fundingRateUpdates: (filter, options) =>
159
208
  this.marketBus.stream(
160
209
  (event): event is FundingRateUpdatedEvent =>
161
210
  event.type === "funding_rate.updated" &&
162
211
  matchesMarketFilter(event, filter),
212
+ this.createStreamOptions(
213
+ "market.fundingRateUpdates",
214
+ options,
215
+ "conflate",
216
+ marketKey,
217
+ ),
163
218
  ),
164
- l1BookUpdates: (filter) =>
219
+ l1BookUpdates: (filter, options) =>
165
220
  this.marketBus.stream(
166
221
  (event): event is L1BookUpdatedEvent =>
167
222
  event.type === "l1_book.updated" &&
168
223
  matchesMarketFilter(event, filter),
224
+ this.createStreamOptions(
225
+ "market.l1BookUpdates",
226
+ options,
227
+ "conflate",
228
+ marketKey,
229
+ ),
169
230
  ),
170
- status: (filter) =>
171
- this.marketStatusBus.stream((event) =>
172
- matchesMarketFilter(event, filter),
231
+ status: (filter, options) =>
232
+ this.marketStatusBus.stream(
233
+ (event) => matchesMarketFilter(event, filter),
234
+ this.createStreamOptions(
235
+ "market.status",
236
+ options,
237
+ "buffer",
238
+ marketKey,
239
+ ),
173
240
  ),
174
241
  };
175
242
  }
@@ -1064,6 +1131,14 @@ export class MarketManagerImpl
1064
1131
  record.status.lastReadyAt = this.resolveLastReadyAt(record);
1065
1132
  }
1066
1133
 
1134
+ const publicationKey = statusPublicationKey(record.status);
1135
+ if (
1136
+ sameStatusPublicationKey(publicationKey, record.lastPublishedStatusKey)
1137
+ ) {
1138
+ return;
1139
+ }
1140
+
1141
+ record.lastPublishedStatusKey = publicationKey;
1067
1142
  this.publishStatus(record);
1068
1143
  }
1069
1144
 
@@ -1184,6 +1259,35 @@ export class MarketManagerImpl
1184
1259
  this.context.publishHealthEvent(event);
1185
1260
  }
1186
1261
 
1262
+ private createStreamOptions<U extends { venue: Venue; symbol: string }>(
1263
+ stream: string,
1264
+ options: EventStreamOptions | undefined,
1265
+ defaultMode: "buffer" | "conflate",
1266
+ conflateKey: (event: U) => string,
1267
+ ): AsyncEventBusStreamOptions<U> {
1268
+ return {
1269
+ mode: options?.mode ?? defaultMode,
1270
+ maxBuffer: options?.maxBuffer,
1271
+ conflateKey,
1272
+ onOverflow: this.createOverflowHandler(stream),
1273
+ };
1274
+ }
1275
+
1276
+ private createOverflowHandler(
1277
+ stream: string,
1278
+ ): (info: AsyncEventBusOverflowInfo) => void {
1279
+ return ({ maxBuffer }) => {
1280
+ const error = new AcexError(
1281
+ "EVENT_BUFFER_OVERFLOW",
1282
+ `Event stream buffer overflow: ${stream}`,
1283
+ );
1284
+ this.context.publishRuntimeError("market", error, {
1285
+ stream,
1286
+ maxBuffer,
1287
+ });
1288
+ };
1289
+ }
1290
+
1187
1291
  private async resumeStreams(): Promise<void> {
1188
1292
  for (const record of this.records.values()) {
1189
1293
  const market = record.market;
@@ -1,6 +1,7 @@
1
1
  import type { OrderDataStatus, Venue } from "../../types/index.ts";
2
2
 
3
3
  export const DEFAULT_MAX_CLOSED_ORDERS_PER_SYMBOL = 500;
4
+ export const DEFAULT_MISSING_ORDER_EVICTION_THRESHOLD = 3;
4
5
 
5
6
  export function cloneOrderStatus(status: OrderDataStatus): OrderDataStatus {
6
7
  return { ...status };
@@ -28,6 +29,14 @@ export function normalizeMaxClosedOrdersPerSymbol(
28
29
  : DEFAULT_MAX_CLOSED_ORDERS_PER_SYMBOL;
29
30
  }
30
31
 
32
+ export function normalizeMissingOrderEvictionThreshold(
33
+ value: number | undefined,
34
+ ): number {
35
+ return value !== undefined && Number.isInteger(value) && value > 0
36
+ ? value
37
+ : DEFAULT_MISSING_ORDER_EVICTION_THRESHOLD;
38
+ }
39
+
31
40
  export function successfulStatus(
32
41
  status: OrderDataStatus,
33
42
  options: {
@@ -15,6 +15,7 @@ export interface OrderRecord {
15
15
  orderIdOnlyIndex: Map<string, Set<string>>;
16
16
  clientOrderIdIndex: Map<string, Set<string>>;
17
17
  pendingClientOrderIdIndex: Map<string, PendingOrderClaim>;
18
+ missingOrderConfirmations: Map<string, number>;
18
19
  status: OrderDataStatus;
19
20
  }
20
21
 
@@ -29,8 +30,10 @@ export interface OrderLocation {
29
30
  export interface PendingOrderClaim {
30
31
  localOrderId: string;
31
32
  symbol: string;
33
+ claimedAt: number;
32
34
  }
33
35
 
34
36
  export interface OrderManagerOptions {
35
37
  maxClosedOrdersPerSymbol?: number;
38
+ missingOrderEvictionThreshold?: number;
36
39
  }
@@ -78,6 +78,7 @@ export function orderPriority(status: OrderSnapshot["status"]): number {
78
78
  case "expired":
79
79
  return 4;
80
80
  case "rejected":
81
+ case "unknown":
81
82
  return 3;
82
83
  case "partially_filled":
83
84
  return 2;
@@ -5,6 +5,7 @@ import type {
5
5
  import type {
6
6
  AccountAwareManager,
7
7
  ClientContext,
8
+ ExpiredPendingOrderClaim,
8
9
  HealthReporter,
9
10
  ManagerLifecycle,
10
11
  PrivateOrderDataConsumer,
@@ -16,6 +17,7 @@ import {
16
17
  buildAcexErrorDetails,
17
18
  formatAcexErrorMessage,
18
19
  } from "../errors.ts";
20
+ import type { AsyncEventBusOverflowInfo } from "../internal/async-event-bus.ts";
19
21
  import { AsyncEventBus } from "../internal/async-event-bus.ts";
20
22
  import { matchesOrderFilter } from "../internal/filters.ts";
21
23
  import { isTransportError } from "../internal/http-client.ts";
@@ -43,6 +45,7 @@ import {
43
45
  cloneOrderStatus,
44
46
  createOrderDataStatus,
45
47
  normalizeMaxClosedOrdersPerSymbol,
48
+ normalizeMissingOrderEvictionThreshold,
46
49
  successfulStatus,
47
50
  } from "./order/data-status.ts";
48
51
  import {
@@ -61,6 +64,7 @@ import { createSnapshot, isOpenOrder } from "./order/snapshot.ts";
61
64
  import {
62
65
  getAllSnapshots,
63
66
  getExistingSnapshot,
67
+ getExistingSnapshotLocation,
64
68
  getLocalOrderIdForVenueOrderId,
65
69
  getLocationByLocalOrderId,
66
70
  getOpenOrderSnapshots,
@@ -96,6 +100,7 @@ export class OrderManagerImpl
96
100
 
97
101
  private readonly context: ClientContext;
98
102
  private readonly maxClosedOrdersPerSymbol: number;
103
+ private readonly missingOrderEvictionThreshold: number;
99
104
  private readonly orderBus = new AsyncEventBus<OrderEvent>();
100
105
  private readonly orderStatusBus =
101
106
  new AsyncEventBus<OrderStatusChangedEvent>();
@@ -107,25 +112,38 @@ export class OrderManagerImpl
107
112
  this.maxClosedOrdersPerSymbol = normalizeMaxClosedOrdersPerSymbol(
108
113
  options.maxClosedOrdersPerSymbol,
109
114
  );
115
+ this.missingOrderEvictionThreshold = normalizeMissingOrderEvictionThreshold(
116
+ options.missingOrderEvictionThreshold,
117
+ );
110
118
 
111
119
  this.events = {
112
- status: (filter) =>
113
- this.orderStatusBus.stream((event) =>
114
- matchesOrderFilter(
115
- { accountId: event.accountId, venue: event.venue },
116
- filter,
117
- ),
120
+ status: (filter, options) =>
121
+ this.orderStatusBus.stream(
122
+ (event) =>
123
+ matchesOrderFilter(
124
+ { accountId: event.accountId, venue: event.venue },
125
+ filter,
126
+ ),
127
+ {
128
+ maxBuffer: options?.maxBuffer,
129
+ onOverflow: this.createOverflowHandler("order.status"),
130
+ },
118
131
  ),
119
- updates: (filter) =>
120
- this.orderBus.stream((event) =>
121
- matchesOrderFilter(
122
- {
123
- accountId: event.accountId,
124
- venue: event.venue,
125
- symbol: "symbol" in event ? event.symbol : undefined,
126
- },
127
- filter,
128
- ),
132
+ updates: (filter, options) =>
133
+ this.orderBus.stream(
134
+ (event) =>
135
+ matchesOrderFilter(
136
+ {
137
+ accountId: event.accountId,
138
+ venue: event.venue,
139
+ symbol: "symbol" in event ? event.symbol : undefined,
140
+ },
141
+ filter,
142
+ ),
143
+ {
144
+ maxBuffer: options?.maxBuffer,
145
+ onOverflow: this.createOverflowHandler("order.updates"),
146
+ },
129
147
  ),
130
148
  };
131
149
  }
@@ -494,6 +512,9 @@ export class OrderManagerImpl
494
512
  openSetKeys.add(lookupKey);
495
513
  }
496
514
  const current = getExistingSnapshot(record, update);
515
+ if (current) {
516
+ this.clearMissingOrderConfirmationsForUpdate(record, current);
517
+ }
497
518
  const nextSnapshot = this.applyUpdateToRecord(
498
519
  record,
499
520
  accountId,
@@ -565,6 +586,36 @@ export class OrderManagerImpl
565
586
  return this.getOpenOrders(accountId);
566
587
  }
567
588
 
589
+ getExpiredPrivateOrderClaims(
590
+ accountId: string,
591
+ now: number,
592
+ ttlMs: number,
593
+ ): ExpiredPendingOrderClaim[] {
594
+ const record = this.records.get(accountId);
595
+ if (!record || ttlMs <= 0) {
596
+ return [];
597
+ }
598
+
599
+ const expired: ExpiredPendingOrderClaim[] = [];
600
+ for (const [
601
+ venueClientOrderId,
602
+ claim,
603
+ ] of record.pendingClientOrderIdIndex) {
604
+ if (now - claim.claimedAt < ttlMs) {
605
+ continue;
606
+ }
607
+
608
+ expired.push({
609
+ venueClientOrderId,
610
+ localOrderId: claim.localOrderId,
611
+ symbol: claim.symbol,
612
+ claimedAt: claim.claimedAt,
613
+ });
614
+ }
615
+
616
+ return expired;
617
+ }
618
+
568
619
  onPrivateOrderUpdate(
569
620
  accountId: string,
570
621
  venue: Venue,
@@ -590,32 +641,129 @@ export class OrderManagerImpl
590
641
  return;
591
642
  }
592
643
 
593
- const eventType =
594
- snapshot.status === "filled"
595
- ? "order.filled"
596
- : snapshot.status === "rejected"
597
- ? "order.rejected"
598
- : snapshot.status === "canceled" || snapshot.status === "expired"
599
- ? "order.canceled"
600
- : "order.updated";
644
+ this.publishOrderEvent(accountId, venue, snapshot);
601
645
 
602
- this.orderBus.publish({
603
- type: eventType,
646
+ record.status = successfulStatus(record.status, {
647
+ preserveStatus: options.preserveStatus,
648
+ lastReceivedAt: snapshot.receivedAt,
649
+ lastReadyAt: snapshot.updatedAt,
650
+ });
651
+ this.publishStatus(record);
652
+ }
653
+
654
+ onPrivateOrderConfirmedMissing(
655
+ accountId: string,
656
+ venue: Venue,
657
+ order: OrderSnapshot,
658
+ ): void {
659
+ const record = this.getOrCreateRecord(accountId, venue);
660
+ if (!record.subscribed) {
661
+ return;
662
+ }
663
+
664
+ const location = getExistingSnapshotLocation(record, order);
665
+ if (!location || location.table !== "open") {
666
+ return;
667
+ }
668
+
669
+ const current = getSnapshotAtLocation(record, location);
670
+ if (!current || !isOpenOrder(current)) {
671
+ return;
672
+ }
673
+
674
+ const confirmations =
675
+ (record.missingOrderConfirmations.get(location.localOrderId) ?? 0) + 1;
676
+ if (confirmations < this.missingOrderEvictionThreshold) {
677
+ record.missingOrderConfirmations.set(
678
+ location.localOrderId,
679
+ confirmations,
680
+ );
681
+ return;
682
+ }
683
+
684
+ const receivedAt = this.context.now();
685
+ const snapshot = createSnapshot(
604
686
  accountId,
605
687
  venue,
606
- symbol: snapshot.symbol,
607
- snapshot,
608
- ts: this.context.now(),
609
- });
688
+ {
689
+ orderId: current.orderId,
690
+ clientOrderId: current.clientOrderId,
691
+ symbol: current.symbol,
692
+ side: current.side,
693
+ type: current.type,
694
+ status: "unknown",
695
+ price: current.price,
696
+ triggerPrice: current.triggerPrice,
697
+ amount: current.amount,
698
+ filled: current.filled,
699
+ remaining: current.remaining,
700
+ reduceOnly: current.reduceOnly,
701
+ positionSide: current.positionSide,
702
+ avgFillPrice: current.avgFillPrice,
703
+ receivedAt,
704
+ },
705
+ current,
706
+ );
610
707
 
708
+ if (
709
+ !this.writeSnapshot(record, location.localOrderId, snapshot, location)
710
+ ) {
711
+ return;
712
+ }
713
+
714
+ this.context.publishRuntimeError(
715
+ "order",
716
+ new Error(
717
+ `Evicted ${venue} open order after ${confirmations} confirmed missing checks`,
718
+ ),
719
+ {
720
+ accountId,
721
+ venue,
722
+ symbol: current.symbol,
723
+ },
724
+ );
725
+ this.publishOrderEvent(accountId, venue, snapshot);
611
726
  record.status = successfulStatus(record.status, {
612
- preserveStatus: options.preserveStatus,
613
727
  lastReceivedAt: snapshot.receivedAt,
614
728
  lastReadyAt: snapshot.updatedAt,
615
729
  });
616
730
  this.publishStatus(record);
617
731
  }
618
732
 
733
+ onPrivateOrderClaimNotFound(
734
+ accountId: string,
735
+ venue: Venue,
736
+ claim: ExpiredPendingOrderClaim,
737
+ ): void {
738
+ const record = this.records.get(accountId);
739
+ if (!record) {
740
+ return;
741
+ }
742
+
743
+ const pending = record.pendingClientOrderIdIndex.get(
744
+ claim.venueClientOrderId,
745
+ );
746
+ if (
747
+ pending?.localOrderId !== claim.localOrderId ||
748
+ pending.symbol !== claim.symbol
749
+ ) {
750
+ return;
751
+ }
752
+
753
+ record.pendingClientOrderIdIndex.delete(claim.venueClientOrderId);
754
+ this.context.publishRuntimeError(
755
+ "order",
756
+ new Error(
757
+ `createOrder timed out and the order was not found on the venue: ${claim.venueClientOrderId}`,
758
+ ),
759
+ {
760
+ accountId,
761
+ venue,
762
+ symbol: claim.symbol,
763
+ },
764
+ );
765
+ }
766
+
619
767
  onPrivateOrderStreamState(
620
768
  accountId: string,
621
769
  venue: Venue,
@@ -670,6 +818,7 @@ export class OrderManagerImpl
670
818
  orderIdOnlyIndex: new Map(),
671
819
  clientOrderIdIndex: new Map(),
672
820
  pendingClientOrderIdIndex: new Map(),
821
+ missingOrderConfirmations: new Map(),
673
822
  status: createOrderDataStatus(accountId, venue, "inactive"),
674
823
  };
675
824
 
@@ -718,9 +867,51 @@ export class OrderManagerImpl
718
867
 
719
868
  this.warnSystemClientOrderIdOnlyClaim(record, snapshot);
720
869
  this.warnProvisionalTerminalOrder(record, snapshot);
870
+ this.clearMissingOrderConfirmations(record, localOrderId);
721
871
  return true;
722
872
  }
723
873
 
874
+ private clearMissingOrderConfirmations(
875
+ record: OrderRecord,
876
+ localOrderId: string,
877
+ ): void {
878
+ record.missingOrderConfirmations.delete(localOrderId);
879
+ }
880
+
881
+ private clearMissingOrderConfirmationsForUpdate(
882
+ record: OrderRecord,
883
+ update: { symbol: string; orderId?: string; clientOrderId?: string },
884
+ ): void {
885
+ const location = getExistingSnapshotLocation(record, update);
886
+ if (location) {
887
+ this.clearMissingOrderConfirmations(record, location.localOrderId);
888
+ }
889
+ }
890
+
891
+ private publishOrderEvent(
892
+ accountId: string,
893
+ venue: Venue,
894
+ snapshot: OrderSnapshot,
895
+ ): void {
896
+ const eventType =
897
+ snapshot.status === "filled"
898
+ ? "order.filled"
899
+ : snapshot.status === "rejected"
900
+ ? "order.rejected"
901
+ : isOpenOrder(snapshot)
902
+ ? "order.updated"
903
+ : "order.canceled";
904
+
905
+ this.orderBus.publish({
906
+ type: eventType,
907
+ accountId,
908
+ venue,
909
+ symbol: snapshot.symbol,
910
+ snapshot,
911
+ ts: this.context.now(),
912
+ });
913
+ }
914
+
724
915
  private warnDroppedUnkeyedTerminalOrder(
725
916
  record: OrderRecord,
726
917
  snapshot: OrderSnapshot,
@@ -800,6 +991,9 @@ export class OrderManagerImpl
800
991
  options: { requestStartedAt?: number; preserveStatus?: boolean } = {},
801
992
  ): OrderSnapshot | undefined {
802
993
  const resolution = this.resolveLocalOrderIdForUpdate(record, update);
994
+ if (resolution.localOrderId) {
995
+ this.clearMissingOrderConfirmations(record, resolution.localOrderId);
996
+ }
803
997
  const localOrderId = resolution.localOrderId ?? this.generateLocalOrderId();
804
998
  const previousLocation = getLocationByLocalOrderId(record, localOrderId);
805
999
  const previous = previousLocation
@@ -874,6 +1068,7 @@ export class OrderManagerImpl
874
1068
  record.pendingClientOrderIdIndex.set(venueClientOrderId, {
875
1069
  localOrderId,
876
1070
  symbol,
1071
+ claimedAt: this.context.now(),
877
1072
  });
878
1073
  }
879
1074
 
@@ -955,6 +1150,9 @@ export class OrderManagerImpl
955
1150
  update,
956
1151
  options.localOrderId,
957
1152
  );
1153
+ if (resolution.localOrderId) {
1154
+ this.clearMissingOrderConfirmations(record, resolution.localOrderId);
1155
+ }
958
1156
  const localOrderId = resolution.localOrderId ?? this.generateLocalOrderId();
959
1157
  const previousLocation = getLocationByLocalOrderId(record, localOrderId);
960
1158
  const previous = previousLocation
@@ -1083,6 +1281,21 @@ export class OrderManagerImpl
1083
1281
  },
1084
1282
  };
1085
1283
  }
1284
+
1285
+ private createOverflowHandler(
1286
+ stream: string,
1287
+ ): (info: AsyncEventBusOverflowInfo) => void {
1288
+ return ({ maxBuffer }) => {
1289
+ const error = new AcexError(
1290
+ "EVENT_BUFFER_OVERFLOW",
1291
+ `Event stream buffer overflow: ${stream}`,
1292
+ );
1293
+ this.context.publishRuntimeError("order", error, {
1294
+ stream,
1295
+ maxBuffer,
1296
+ });
1297
+ };
1298
+ }
1086
1299
  }
1087
1300
 
1088
1301
  function isOrderErrorCode(
@@ -1,4 +1,5 @@
1
1
  import type {
2
+ BufferedEventStreamOptions,
2
3
  PrivateRuntimeReason,
3
4
  PrivateRuntimeStatus,
4
5
  SubscriptionActivity,
@@ -158,8 +159,14 @@ export type AccountEvent =
158
159
  | AccountSnapshotReplacedEvent;
159
160
 
160
161
  export interface AccountEventStreams {
161
- updates(filter?: AccountEventFilter): AsyncIterable<AccountEvent>;
162
- status(filter?: AccountEventFilter): AsyncIterable<AccountStatusChangedEvent>;
162
+ updates(
163
+ filter?: AccountEventFilter,
164
+ options?: BufferedEventStreamOptions,
165
+ ): AsyncIterable<AccountEvent>;
166
+ status(
167
+ filter?: AccountEventFilter,
168
+ options?: BufferedEventStreamOptions,
169
+ ): AsyncIterable<AccountStatusChangedEvent>;
163
170
  }
164
171
 
165
172
  export interface AccountManager {
@@ -18,6 +18,7 @@ import type {
18
18
  import type {
19
19
  AccountCredentials,
20
20
  AcexInternalError,
21
+ BufferedEventStreamOptions,
21
22
  ClientStatus,
22
23
  CreateClientOptions,
23
24
  RegisterAccountInput,
@@ -54,8 +55,13 @@ export interface HealthEventFilter {
54
55
  }
55
56
 
56
57
  export interface ClientEventStreams {
57
- health(filter?: HealthEventFilter): AsyncIterable<HealthEvent>;
58
- errors(): AsyncIterable<AcexInternalError>;
58
+ health(
59
+ filter?: HealthEventFilter,
60
+ options?: BufferedEventStreamOptions,
61
+ ): AsyncIterable<HealthEvent>;
62
+ errors(
63
+ options?: BufferedEventStreamOptions,
64
+ ): AsyncIterable<AcexInternalError>;
59
65
  }
60
66
 
61
67
  export type VenueRuntimeStatus = "available" | "type_only" | "reserved";
@@ -1,6 +1,11 @@
1
1
  import type BigNumber from "bignumber.js";
2
2
  import type { AcexError } from "../errors.ts";
3
- import type { MarketFreshness, SubscriptionActivity, Venue } from "./shared.ts";
3
+ import type {
4
+ EventStreamOptions,
5
+ MarketFreshness,
6
+ SubscriptionActivity,
7
+ Venue,
8
+ } from "./shared.ts";
4
9
 
5
10
  export type MarketType = "spot" | "swap" | "future";
6
11
 
@@ -170,12 +175,22 @@ export type MarketEvent =
170
175
  | MarketStatusChangedEvent;
171
176
 
172
177
  export interface MarketEventStreams {
173
- l1BookUpdates(filter?: MarketEventFilter): AsyncIterable<L1BookUpdatedEvent>;
178
+ l1BookUpdates(
179
+ filter?: MarketEventFilter,
180
+ options?: EventStreamOptions,
181
+ ): AsyncIterable<L1BookUpdatedEvent>;
174
182
  fundingRateUpdates(
175
183
  filter?: MarketEventFilter,
184
+ options?: EventStreamOptions,
176
185
  ): AsyncIterable<FundingRateUpdatedEvent>;
177
- status(filter?: MarketEventFilter): AsyncIterable<MarketStatusChangedEvent>;
178
- all(filter?: MarketEventFilter): AsyncIterable<MarketEvent>;
186
+ status(
187
+ filter?: MarketEventFilter,
188
+ options?: EventStreamOptions,
189
+ ): AsyncIterable<MarketStatusChangedEvent>;
190
+ all(
191
+ filter?: MarketEventFilter,
192
+ options?: EventStreamOptions,
193
+ ): AsyncIterable<MarketEvent>;
179
194
  }
180
195
 
181
196
  export interface MarketManager {