@vesper85/strategy-sdk 0.1.2 → 0.1.3

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/index.js CHANGED
@@ -9,6 +9,7 @@ import { createClient } from 'redis';
9
9
  import superjson from 'superjson';
10
10
  import { TechnicalAnalysisService } from '@osiris-ai/technical-indicators';
11
11
  import WebSocket from 'ws';
12
+ import { RealTimeDataClient, ConnectionStatus } from '@polymarket/real-time-data-client';
12
13
  import { privateKeyToAccount } from 'viem/accounts';
13
14
  import { sepolia, base, optimism, arbitrum, polygon, mainnet } from 'viem/chains';
14
15
 
@@ -27,6 +28,30 @@ function isOpportunitySubscription(sub) {
27
28
  function isCustomSubscription(sub) {
28
29
  return sub.type === "custom";
29
30
  }
31
+ function isClobMarketSubscription(sub) {
32
+ return sub.type === "clob_market";
33
+ }
34
+ function isClobUserSubscription(sub) {
35
+ return sub.type === "clob_user";
36
+ }
37
+ function isActivitySubscription(sub) {
38
+ return sub.type === "activity";
39
+ }
40
+ function isCommentsSubscription(sub) {
41
+ return sub.type === "comments";
42
+ }
43
+ function isCryptoPricesSubscription(sub) {
44
+ return sub.type === "crypto_prices";
45
+ }
46
+ function isRfqSubscription(sub) {
47
+ return sub.type === "rfq";
48
+ }
49
+ function isPolymarketSubscription(sub) {
50
+ return isClobMarketSubscription(sub) || isClobUserSubscription(sub) || isActivitySubscription(sub) || isCommentsSubscription(sub) || isCryptoPricesSubscription(sub) || isRfqSubscription(sub);
51
+ }
52
+ function isOsirisSubscription(sub) {
53
+ return isWalletSubscription(sub) || isOpportunitySubscription(sub);
54
+ }
30
55
  var OsirisSigner = class {
31
56
  hubBaseUrl;
32
57
  accessToken;
@@ -161,6 +186,80 @@ var OsirisSigner = class {
161
186
  return void 0;
162
187
  }
163
188
  };
189
+
190
+ // src/utils/index.ts
191
+ function mapToGammaMarket(raw) {
192
+ const safeParse = (value) => {
193
+ try {
194
+ return typeof value === "string" ? JSON.parse(value) : value;
195
+ } catch {
196
+ return [];
197
+ }
198
+ };
199
+ return {
200
+ // Identity & Basic Info
201
+ id: raw.id,
202
+ question: raw.question,
203
+ slug: raw.slug,
204
+ condition_id: raw.conditionId,
205
+ question_id: raw.questionId,
206
+ // If present
207
+ description: raw.description,
208
+ // Dates
209
+ end_date: raw.endDate,
210
+ start_date: raw.startDate,
211
+ created_at: raw.createdAt,
212
+ updated_at: raw.updatedAt,
213
+ closed_time: raw.closedTime,
214
+ // Images
215
+ image: raw.image,
216
+ icon: raw.icon,
217
+ twitter_card_image: raw.twitterCardImage,
218
+ // Categorization
219
+ category: raw.category,
220
+ tags: raw.tags,
221
+ market_type: raw.marketType,
222
+ active: raw.active,
223
+ closed: raw.closed,
224
+ archived: raw.archived,
225
+ restricted: raw.restricted,
226
+ // Financials & Numbers (Type Conversions)
227
+ liquidity: raw.liquidity ? parseFloat(raw.liquidity) : 0,
228
+ volume: raw.volume,
229
+ // Interface keeps this as string
230
+ volume_24hr: raw.volume24hr?.toString(),
231
+ // Prices (Number -> String conversion based on your Interface)
232
+ best_bid: raw.bestBid?.toString(),
233
+ best_ask: raw.bestAsk?.toString(),
234
+ last_trade_price: raw.lastTradePrice?.toString(),
235
+ // Arrays (Parsing stringified JSON)
236
+ outcomes: safeParse(raw.outcomes),
237
+ outcome_prices: safeParse(raw.outcomePrices),
238
+ outcomePrices: safeParse(raw.outcomePrices),
239
+ // Populating alias
240
+ clob_token_ids: safeParse(raw.clobTokenIds),
241
+ clobTokenIds: safeParse(raw.clobTokenIds),
242
+ // Populating alias
243
+ uma_resolution_statuses: safeParse(raw.umaResolutionStatuses),
244
+ // Market Maker & Fees
245
+ market_maker_address: raw.marketMakerAddress,
246
+ maker_fee_bps: raw.makerFeeBps,
247
+ taker_fee_bps: raw.takerFeeBps,
248
+ // IDs
249
+ created_by: raw.updatedBy,
250
+ // Note: response has updatedBy, mapping to potentially relevant field
251
+ updated_by: raw.updatedBy,
252
+ // Misc
253
+ events: raw.events,
254
+ // Pass through if structure matches, otherwise map Event type similarly
255
+ new: raw.new,
256
+ featured: raw.featured,
257
+ cyom: raw.cyom,
258
+ competitive: raw.competitive
259
+ };
260
+ }
261
+
262
+ // src/clients/polymarket-client.ts
164
263
  var MaxUint256BigInt = typeof ethers.constants !== "undefined" && ethers.constants.MaxUint256 ? BigInt(ethers.MaxUint256.toString()) : BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
165
264
  var POLYGON_CHAIN_ID = 137;
166
265
  var USDC_ADDRESS = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174";
@@ -178,6 +277,13 @@ var ERC1155_ABI = [
178
277
  "function setApprovalForAll(address operator, bool approved) external",
179
278
  "function isApprovedForAll(address account, address operator) external view returns (bool)"
180
279
  ];
280
+ function wrapWalletForV5Compatibility(wallet) {
281
+ const wrappedWallet = wallet;
282
+ wrappedWallet._signTypedData = async function(domain, types, value) {
283
+ return wallet.signTypedData(domain, types, value);
284
+ };
285
+ return wrappedWallet;
286
+ }
181
287
  var PolymarketClient = class {
182
288
  constructor(logger, signer, userAddress, options) {
183
289
  this.logger = logger;
@@ -185,7 +291,7 @@ var PolymarketClient = class {
185
291
  this.userAddress = userAddress;
186
292
  this.gammaClient = new PolymarketGammaClient();
187
293
  this.provider = new ethers.JsonRpcProvider(POLYGON_RPC_URL);
188
- this.isOsirisSigner = signer instanceof OsirisSigner || signer.impl instanceof OsirisSigner || signer.getPrivateKey() === void 0;
294
+ this.isOsirisSigner = signer instanceof OsirisSigner || signer.getPrivateKey() === void 0;
189
295
  this.options = {
190
296
  chainId: options?.chainId ?? POLYGON_CHAIN_ID,
191
297
  autoApprove: options?.autoApprove ?? false,
@@ -244,10 +350,11 @@ var PolymarketClient = class {
244
350
  throw new Error("Could not obtain private key for CLOB client initialization. Private key signer is required for trading.");
245
351
  }
246
352
  this.wallet = new ethers.Wallet(privateKey, this.provider);
353
+ const v5CompatibleWallet = wrapWalletForV5Compatibility(this.wallet);
247
354
  const tempClient = new ClobClient(
248
355
  this.options.clobHost,
249
356
  this.options.chainId,
250
- this.wallet
357
+ v5CompatibleWallet
251
358
  );
252
359
  this.logger.info("Deriving API credentials...");
253
360
  const apiCreds = await tempClient.createOrDeriveApiKey();
@@ -255,7 +362,7 @@ var PolymarketClient = class {
255
362
  this.clobClient = new ClobClient(
256
363
  this.options.clobHost,
257
364
  this.options.chainId,
258
- this.wallet,
365
+ v5CompatibleWallet,
259
366
  apiCreds,
260
367
  signatureType
261
368
  );
@@ -269,15 +376,6 @@ var PolymarketClient = class {
269
376
  isTradingClientInitialized() {
270
377
  return this.tradingInitialized;
271
378
  }
272
- async getPrivateKeyFromSigner() {
273
- if (this.signer && "getPrivateKey" in this.signer) {
274
- return this.signer.getPrivateKey();
275
- }
276
- if (this.signer && this.signer.account?.privateKey) {
277
- return this.signer.account.privateKey;
278
- }
279
- return null;
280
- }
281
379
  ensureTradingClient() {
282
380
  if (!this.clobClient || !this.tradingInitialized) {
283
381
  throw new Error("Trading client not initialized. Call initializeTradingClient() first.");
@@ -1099,7 +1197,8 @@ var PolymarketClient = class {
1099
1197
  throw new Error(`Gamma API error: ${response.status} ${response.statusText}`);
1100
1198
  }
1101
1199
  const data = await response.json();
1102
- return data;
1200
+ const mappedData = data.map(mapToGammaMarket);
1201
+ return mappedData;
1103
1202
  } catch (error) {
1104
1203
  this.logger.error("Error fetching markets from Gamma API", error);
1105
1204
  throw error;
@@ -1596,11 +1695,11 @@ async function runStrategy(strategy, config, context) {
1596
1695
  }
1597
1696
  return false;
1598
1697
  } catch (error) {
1599
- config.logger.error(`Error executing strategy: ${error.message}`, error);
1698
+ config.logger?.error(`Error executing strategy: ${error.message}`, error);
1600
1699
  throw error;
1601
1700
  }
1602
1701
  }
1603
- function createStrategyEngine(strategy, config, context) {
1702
+ function createStrategyEngine(strategy, context, config) {
1604
1703
  return new StrategyEngine(strategy, config, context);
1605
1704
  }
1606
1705
  var StrategyEngine = class {
@@ -1608,6 +1707,7 @@ var StrategyEngine = class {
1608
1707
  this.strategy = strategy;
1609
1708
  this.config = config;
1610
1709
  this.context = context;
1710
+ this.config.logger = this.config.logger || createConsoleLogger();
1611
1711
  }
1612
1712
  intervalId = null;
1613
1713
  isRunning = false;
@@ -1615,6 +1715,9 @@ var StrategyEngine = class {
1615
1715
  * Start the engine with the configured tick interval
1616
1716
  */
1617
1717
  start() {
1718
+ if (!this.config.logger) {
1719
+ this.config.logger = createConsoleLogger();
1720
+ }
1618
1721
  if (this.isRunning) {
1619
1722
  this.config.logger.warning("Strategy engine is already running");
1620
1723
  return;
@@ -1631,6 +1734,9 @@ var StrategyEngine = class {
1631
1734
  * Stop the engine
1632
1735
  */
1633
1736
  stop() {
1737
+ if (!this.config.logger) {
1738
+ this.config.logger = createConsoleLogger();
1739
+ }
1634
1740
  if (!this.isRunning) {
1635
1741
  return;
1636
1742
  }
@@ -1649,6 +1755,9 @@ var StrategyEngine = class {
1649
1755
  }
1650
1756
  async tick() {
1651
1757
  const tickStart = Date.now();
1758
+ if (!this.config.logger) {
1759
+ this.config.logger = createConsoleLogger();
1760
+ }
1652
1761
  this.config.logger.debug(`Tick start: ${(/* @__PURE__ */ new Date()).toISOString()}`);
1653
1762
  try {
1654
1763
  await runStrategy(this.strategy, this.config, this.context);
@@ -1862,7 +1971,59 @@ var PolymarketEventRunner = class {
1862
1971
  const rtdsSubscriptions = [];
1863
1972
  for (const sub of this.strategy.subscriptions) {
1864
1973
  let rtdsSub = null;
1865
- if (isMarketSubscription(sub)) {
1974
+ if (isCryptoPricesSubscription(sub)) {
1975
+ rtdsSub = {
1976
+ topic: "crypto_prices",
1977
+ type: "update"
1978
+ };
1979
+ if (sub.symbol) {
1980
+ rtdsSub.filters = JSON.stringify({ symbol: sub.symbol.toLowerCase() });
1981
+ }
1982
+ } else if (isActivitySubscription(sub)) {
1983
+ rtdsSub = {
1984
+ topic: "activity",
1985
+ type: sub.messageType || "*"
1986
+ };
1987
+ if (sub.eventSlug) {
1988
+ rtdsSub.filters = JSON.stringify({ event_slug: sub.eventSlug });
1989
+ } else if (sub.marketSlug) {
1990
+ rtdsSub.filters = JSON.stringify({ market_slug: sub.marketSlug });
1991
+ }
1992
+ } else if (isClobMarketSubscription(sub)) {
1993
+ rtdsSub = {
1994
+ topic: "clob_market",
1995
+ type: sub.messageType || "*",
1996
+ filters: JSON.stringify([sub.marketId])
1997
+ };
1998
+ } else if (isClobUserSubscription(sub)) {
1999
+ rtdsSub = {
2000
+ topic: "clob_user",
2001
+ type: sub.messageType || "*"
2002
+ };
2003
+ if (this.config.clobAuth) {
2004
+ rtdsSub.clob_auth = this.config.clobAuth;
2005
+ } else {
2006
+ this.config.logger.warning(
2007
+ `clob_user subscription requires clobAuth credentials`
2008
+ );
2009
+ }
2010
+ } else if (isCommentsSubscription(sub)) {
2011
+ rtdsSub = {
2012
+ topic: "comments",
2013
+ type: sub.messageType || "*"
2014
+ };
2015
+ if (sub.parentEntityId && sub.parentEntityType) {
2016
+ rtdsSub.filters = JSON.stringify({
2017
+ parentEntityID: sub.parentEntityId,
2018
+ parentEntityType: sub.parentEntityType
2019
+ });
2020
+ }
2021
+ } else if (isRfqSubscription(sub)) {
2022
+ rtdsSub = {
2023
+ topic: "rfq",
2024
+ type: sub.messageType || "*"
2025
+ };
2026
+ } else if (isMarketSubscription(sub)) {
1866
2027
  const topic = this.mapEventTypeToTopic(sub.type);
1867
2028
  rtdsSub = {
1868
2029
  topic,
@@ -1891,7 +2052,7 @@ var PolymarketEventRunner = class {
1891
2052
  }
1892
2053
  } else {
1893
2054
  this.config.logger.warning(
1894
- `Subscription type '${sub.type}' is not supported by Polymarket RTDS. Only market subscriptions (price, orderbook, trade, fill) and custom subscriptions with valid RTDS topics are supported.`
2055
+ `Subscription type '${sub.type}' is not supported by Polymarket RTDS. Osiris-only subscription types (wallet, opportunity) should use eventSource: 'osiris'.`
1895
2056
  );
1896
2057
  continue;
1897
2058
  }
@@ -1911,6 +2072,9 @@ var PolymarketEventRunner = class {
1911
2072
  /**
1912
2073
  * Get the message type for a given RTDS topic
1913
2074
  * Each topic has specific message types as per the Polymarket RTDS documentation
2075
+ *
2076
+ * Note: Only 'crypto_prices' and 'comments' are documented RTDS topics.
2077
+ * 'trades' and 'orders' subscriptions require the CLOB WebSocket API, not RTDS.
1914
2078
  */
1915
2079
  getMessageTypeForTopic(topic) {
1916
2080
  switch (topic) {
@@ -1918,15 +2082,18 @@ var PolymarketEventRunner = class {
1918
2082
  return "update";
1919
2083
  case "comments":
1920
2084
  return "comment_created";
1921
- // Subscribes to all comment events
1922
2085
  case "trades":
1923
- return "orders_matched";
2086
+ this.config.logger.warning(
2087
+ `Topic 'trades' may not be supported by Polymarket RTDS. Consider using the CLOB WebSocket API for order/trade events.`
2088
+ );
2089
+ return "trade";
1924
2090
  case "orders":
2091
+ this.config.logger.warning(
2092
+ `Topic 'orders' may not be supported by Polymarket RTDS. Consider using the CLOB WebSocket API for order/trade events.`
2093
+ );
1925
2094
  return "order_placed";
1926
- // Can also be 'order_cancelled', 'order_filled'
1927
2095
  case "activity":
1928
2096
  return "trade";
1929
- // Can also be 'offer', etc.
1930
2097
  case "profile":
1931
2098
  return "update";
1932
2099
  default:
@@ -2525,6 +2692,888 @@ function createEventRunner(strategy, config, context) {
2525
2692
  if (!config.eventSourceUrl) ;
2526
2693
  return new OsirisEventRunner(strategy, config, context);
2527
2694
  }
2695
+ var PolymarketRTDSService = class {
2696
+ client = null;
2697
+ config;
2698
+ isConnected = false;
2699
+ activeSubscriptions = [];
2700
+ constructor(config) {
2701
+ this.config = config;
2702
+ }
2703
+ /**
2704
+ * Connect to the Polymarket RTDS WebSocket
2705
+ */
2706
+ connect() {
2707
+ if (this.isConnected) {
2708
+ this.config.logger.warning("PolymarketRTDS: Already connected");
2709
+ return;
2710
+ }
2711
+ this.config.logger.info("PolymarketRTDS: Connecting...");
2712
+ this.client = new RealTimeDataClient({
2713
+ onConnect: (_client) => {
2714
+ this.isConnected = true;
2715
+ this.config.logger.info("PolymarketRTDS: Connected");
2716
+ this.config.onConnect?.();
2717
+ },
2718
+ onMessage: (_client, message) => {
2719
+ this.handleMessage(message);
2720
+ },
2721
+ onStatusChange: (status) => {
2722
+ if (status === ConnectionStatus.DISCONNECTED) {
2723
+ this.isConnected = false;
2724
+ this.config.logger.info("PolymarketRTDS: Disconnected");
2725
+ this.config.onDisconnect?.();
2726
+ } else if (status === ConnectionStatus.CONNECTING) {
2727
+ this.config.logger.info("PolymarketRTDS: Reconnecting...");
2728
+ }
2729
+ },
2730
+ pingInterval: this.config.pingIntervalMs ?? 5e3,
2731
+ autoReconnect: this.config.autoReconnect ?? true
2732
+ });
2733
+ this.client.connect();
2734
+ }
2735
+ /**
2736
+ * Disconnect from the Polymarket RTDS WebSocket
2737
+ */
2738
+ disconnect() {
2739
+ if (!this.client) {
2740
+ return;
2741
+ }
2742
+ this.config.logger.info("PolymarketRTDS: Disconnecting...");
2743
+ this.client.disconnect();
2744
+ this.client = null;
2745
+ this.isConnected = false;
2746
+ this.activeSubscriptions = [];
2747
+ }
2748
+ /**
2749
+ * Check if connected
2750
+ */
2751
+ isActive() {
2752
+ return this.isConnected;
2753
+ }
2754
+ /**
2755
+ * Subscribe to events
2756
+ * Converts SDK EventSubscription types to RTDS Subscription format
2757
+ */
2758
+ subscribe(subscriptions) {
2759
+ if (!this.client) {
2760
+ this.config.logger.warning("PolymarketRTDS: Cannot subscribe - not connected");
2761
+ return;
2762
+ }
2763
+ const rtdsSubscriptions = this.mapToRTDSSubscriptions(subscriptions);
2764
+ if (rtdsSubscriptions.length === 0) {
2765
+ this.config.logger.warning("PolymarketRTDS: No valid subscriptions to add");
2766
+ return;
2767
+ }
2768
+ const msg = { subscriptions: rtdsSubscriptions };
2769
+ this.client.subscribe(msg);
2770
+ this.activeSubscriptions.push(...rtdsSubscriptions);
2771
+ this.config.logger.info(
2772
+ `PolymarketRTDS: Subscribed to ${rtdsSubscriptions.length} topic(s): ` + rtdsSubscriptions.map((s) => `${s.topic}:${s.type}`).join(", ")
2773
+ );
2774
+ }
2775
+ /**
2776
+ * Unsubscribe from events
2777
+ */
2778
+ unsubscribe(subscriptions) {
2779
+ if (!this.client) {
2780
+ return;
2781
+ }
2782
+ const rtdsSubscriptions = this.mapToRTDSSubscriptions(subscriptions);
2783
+ if (rtdsSubscriptions.length === 0) {
2784
+ return;
2785
+ }
2786
+ const msg = { subscriptions: rtdsSubscriptions };
2787
+ this.client.unsubscribe(msg);
2788
+ for (const unsub of rtdsSubscriptions) {
2789
+ const idx = this.activeSubscriptions.findIndex(
2790
+ (s) => s.topic === unsub.topic && s.type === unsub.type
2791
+ );
2792
+ if (idx >= 0) {
2793
+ this.activeSubscriptions.splice(idx, 1);
2794
+ }
2795
+ }
2796
+ this.config.logger.info(
2797
+ `PolymarketRTDS: Unsubscribed from ${rtdsSubscriptions.length} topic(s)`
2798
+ );
2799
+ }
2800
+ /**
2801
+ * Map SDK EventSubscription to RTDS Subscription format
2802
+ */
2803
+ mapToRTDSSubscriptions(subscriptions) {
2804
+ const result = [];
2805
+ for (const sub of subscriptions) {
2806
+ const rtdsSub = this.mapSubscription(sub);
2807
+ if (rtdsSub) {
2808
+ result.push(rtdsSub);
2809
+ }
2810
+ }
2811
+ return result;
2812
+ }
2813
+ /**
2814
+ * Map a single SDK EventSubscription to RTDS Subscription
2815
+ */
2816
+ mapSubscription(sub) {
2817
+ if (isClobMarketSubscription(sub)) {
2818
+ return this.mapClobMarketSubscription(sub);
2819
+ }
2820
+ if (isClobUserSubscription(sub)) {
2821
+ return this.mapClobUserSubscription(sub);
2822
+ }
2823
+ if (isActivitySubscription(sub)) {
2824
+ return this.mapActivitySubscription(sub);
2825
+ }
2826
+ if (isCommentsSubscription(sub)) {
2827
+ return this.mapCommentsSubscription(sub);
2828
+ }
2829
+ if (isCryptoPricesSubscription(sub)) {
2830
+ return this.mapCryptoPricesSubscription(sub);
2831
+ }
2832
+ if (isRfqSubscription(sub)) {
2833
+ return this.mapRfqSubscription(sub);
2834
+ }
2835
+ if (isMarketSubscription(sub)) {
2836
+ return this.mapMarketSubscription(sub);
2837
+ }
2838
+ this.config.logger.warning(
2839
+ `PolymarketRTDS: Unsupported subscription type '${sub.type}'`
2840
+ );
2841
+ return null;
2842
+ }
2843
+ mapClobMarketSubscription(sub) {
2844
+ return {
2845
+ topic: "clob_market",
2846
+ type: sub.messageType || "*",
2847
+ filters: JSON.stringify([sub.marketId])
2848
+ };
2849
+ }
2850
+ mapClobUserSubscription(sub) {
2851
+ if (!this.config.clobAuth) {
2852
+ this.config.logger.warning(
2853
+ "PolymarketRTDS: clob_user subscription requires clobAuth credentials"
2854
+ );
2855
+ }
2856
+ return {
2857
+ topic: "clob_user",
2858
+ type: sub.messageType || "*",
2859
+ clob_auth: this.config.clobAuth
2860
+ };
2861
+ }
2862
+ mapActivitySubscription(sub) {
2863
+ let filters;
2864
+ if (sub.eventSlug) {
2865
+ filters = JSON.stringify({ event_slug: sub.eventSlug });
2866
+ } else if (sub.marketSlug) {
2867
+ filters = JSON.stringify({ market_slug: sub.marketSlug });
2868
+ }
2869
+ return {
2870
+ topic: "activity",
2871
+ type: sub.messageType || "*",
2872
+ filters
2873
+ };
2874
+ }
2875
+ mapCommentsSubscription(sub) {
2876
+ let filters;
2877
+ if (sub.parentEntityId && sub.parentEntityType) {
2878
+ filters = JSON.stringify({
2879
+ parentEntityID: sub.parentEntityId,
2880
+ parentEntityType: sub.parentEntityType
2881
+ });
2882
+ }
2883
+ return {
2884
+ topic: "comments",
2885
+ type: sub.messageType || "*",
2886
+ filters
2887
+ };
2888
+ }
2889
+ mapCryptoPricesSubscription(sub) {
2890
+ let filters;
2891
+ if (sub.symbol) {
2892
+ filters = JSON.stringify({ symbol: sub.symbol.toLowerCase() });
2893
+ }
2894
+ return {
2895
+ topic: "crypto_prices",
2896
+ type: "update",
2897
+ filters
2898
+ };
2899
+ }
2900
+ mapRfqSubscription(sub) {
2901
+ return {
2902
+ topic: "rfq",
2903
+ type: sub.messageType || "*"
2904
+ };
2905
+ }
2906
+ mapMarketSubscription(sub) {
2907
+ switch (sub.type) {
2908
+ case "price":
2909
+ return {
2910
+ topic: "clob_market",
2911
+ type: "price_change",
2912
+ filters: JSON.stringify([sub.market])
2913
+ };
2914
+ case "orderbook":
2915
+ return {
2916
+ topic: "clob_market",
2917
+ type: "agg_orderbook",
2918
+ filters: JSON.stringify([sub.market])
2919
+ };
2920
+ case "trade":
2921
+ return {
2922
+ topic: "activity",
2923
+ type: "trades",
2924
+ filters: JSON.stringify({ market_slug: sub.market })
2925
+ };
2926
+ case "fill":
2927
+ if (!this.config.clobAuth) {
2928
+ this.config.logger.warning(
2929
+ "PolymarketRTDS: fill subscription requires clobAuth credentials"
2930
+ );
2931
+ }
2932
+ return {
2933
+ topic: "clob_user",
2934
+ type: "order",
2935
+ clob_auth: this.config.clobAuth
2936
+ };
2937
+ default:
2938
+ return {
2939
+ topic: "activity",
2940
+ type: "trades",
2941
+ filters: JSON.stringify({ market_slug: sub.market })
2942
+ };
2943
+ }
2944
+ }
2945
+ /**
2946
+ * Handle incoming RTDS messages
2947
+ */
2948
+ handleMessage(message) {
2949
+ try {
2950
+ const event = this.convertToStrategyEvent(message);
2951
+ this.config.onEvent(event);
2952
+ } catch (error) {
2953
+ this.config.logger.error(
2954
+ `PolymarketRTDS: Error processing message - ${error.message}`
2955
+ );
2956
+ }
2957
+ }
2958
+ /**
2959
+ * Convert RTDS Message to StrategyEvent
2960
+ */
2961
+ convertToStrategyEvent(message) {
2962
+ const eventType = this.mapTopicToEventType(message.topic, message.type);
2963
+ const eventData = this.extractEventData(message);
2964
+ return {
2965
+ type: eventType,
2966
+ timestamp: message.timestamp || Date.now(),
2967
+ market: eventData.market,
2968
+ data: eventData
2969
+ };
2970
+ }
2971
+ /**
2972
+ * Map RTDS topic/type to SDK EventType
2973
+ */
2974
+ mapTopicToEventType(topic, type) {
2975
+ switch (topic) {
2976
+ case "crypto_prices":
2977
+ return "price";
2978
+ case "clob_market":
2979
+ switch (type) {
2980
+ case "price_change":
2981
+ case "last_trade_price":
2982
+ return "price";
2983
+ case "agg_orderbook":
2984
+ return "orderbook";
2985
+ default:
2986
+ return "custom";
2987
+ }
2988
+ case "activity":
2989
+ return "trade";
2990
+ case "clob_user":
2991
+ return type === "trade" ? "trade" : "fill";
2992
+ default:
2993
+ return "custom";
2994
+ }
2995
+ }
2996
+ /**
2997
+ * Extract event data from RTDS message payload
2998
+ */
2999
+ extractEventData(message) {
3000
+ const payload = message.payload;
3001
+ const data = {
3002
+ raw: {
3003
+ topic: message.topic,
3004
+ type: message.type,
3005
+ ...payload
3006
+ }
3007
+ };
3008
+ switch (message.topic) {
3009
+ case "crypto_prices":
3010
+ data.price = payload.value;
3011
+ data.market = payload.symbol;
3012
+ break;
3013
+ case "clob_market":
3014
+ if (message.type === "price_change") {
3015
+ data.market = payload.market;
3016
+ if (payload.price_changes?.length > 0) {
3017
+ const change = payload.price_changes[0];
3018
+ data.bestBid = parseFloat(change.best_bid);
3019
+ data.bestAsk = parseFloat(change.best_ask);
3020
+ data.price = parseFloat(change.price);
3021
+ }
3022
+ } else if (message.type === "agg_orderbook") {
3023
+ data.market = payload.market;
3024
+ data.bids = payload.bids;
3025
+ data.asks = payload.asks;
3026
+ if (payload.bids?.length > 0) {
3027
+ data.bestBid = parseFloat(payload.bids[0].price);
3028
+ }
3029
+ if (payload.asks?.length > 0) {
3030
+ data.bestAsk = parseFloat(payload.asks[0].price);
3031
+ }
3032
+ } else if (message.type === "last_trade_price") {
3033
+ data.market = payload.market;
3034
+ data.price = parseFloat(payload.price);
3035
+ data.side = payload.side;
3036
+ data.size = parseFloat(payload.size);
3037
+ }
3038
+ break;
3039
+ case "activity":
3040
+ data.market = payload.slug || payload.conditionId;
3041
+ data.price = payload.price;
3042
+ data.size = payload.size;
3043
+ data.side = payload.side?.toLowerCase();
3044
+ data.tradeId = payload.transactionHash;
3045
+ break;
3046
+ case "clob_user":
3047
+ data.market = payload.market;
3048
+ data.orderId = payload.id;
3049
+ data.price = parseFloat(payload.price);
3050
+ data.size = parseFloat(payload.size || payload.original_size);
3051
+ data.side = payload.side?.toLowerCase();
3052
+ break;
3053
+ case "rfq":
3054
+ data.market = payload.market;
3055
+ data.price = payload.price;
3056
+ data.size = payload.sizeIn || payload.sizeOut;
3057
+ data.side = payload.side?.toLowerCase();
3058
+ break;
3059
+ }
3060
+ return data;
3061
+ }
3062
+ };
3063
+ function createPolymarketRTDSService(config) {
3064
+ return new PolymarketRTDSService(config);
3065
+ }
3066
+ var DEFAULT_OSIRIS_RTDS_URL = "wss://rtds.osirislabs.xyz";
3067
+ var OsirisRTDSService = class {
3068
+ ws = null;
3069
+ config;
3070
+ isConnected = false;
3071
+ reconnectAttempts = 0;
3072
+ reconnectTimeout = null;
3073
+ pingInterval = null;
3074
+ isIntentionallyClosed = false;
3075
+ activeTopics = /* @__PURE__ */ new Set();
3076
+ // Reconnection settings
3077
+ maxReconnectAttempts;
3078
+ baseReconnectDelay;
3079
+ maxReconnectDelay;
3080
+ pingIntervalMs;
3081
+ url;
3082
+ constructor(config) {
3083
+ this.config = config;
3084
+ this.maxReconnectAttempts = config.reconnect?.maxAttempts ?? 10;
3085
+ this.baseReconnectDelay = config.reconnect?.delayMs ?? 1e3;
3086
+ this.maxReconnectDelay = config.reconnect?.maxDelayMs ?? 3e4;
3087
+ this.pingIntervalMs = config.pingIntervalMs ?? 3e4;
3088
+ this.url = config.url || DEFAULT_OSIRIS_RTDS_URL;
3089
+ }
3090
+ /**
3091
+ * Connect to the Osiris Pub/Sub WebSocket
3092
+ */
3093
+ connect() {
3094
+ if (this.isConnected) {
3095
+ this.config.logger.warning("OsirisRTDS: Already connected");
3096
+ return;
3097
+ }
3098
+ this.isIntentionallyClosed = false;
3099
+ this.config.logger.info(`OsirisRTDS: Connecting to ${this.url}...`);
3100
+ try {
3101
+ this.ws = new WebSocket(this.url);
3102
+ this.ws.on("open", () => {
3103
+ this.isConnected = true;
3104
+ this.reconnectAttempts = 0;
3105
+ this.config.logger.info("OsirisRTDS: Connected");
3106
+ this.startPingInterval();
3107
+ this.config.onConnect?.();
3108
+ });
3109
+ this.ws.on("message", (data) => {
3110
+ this.handleMessage(data);
3111
+ });
3112
+ this.ws.on("error", (error) => {
3113
+ this.config.logger.error(`OsirisRTDS: Error - ${error.message}`);
3114
+ this.config.onError?.(error);
3115
+ });
3116
+ this.ws.on("close", (code, reason) => {
3117
+ this.isConnected = false;
3118
+ this.stopPingInterval();
3119
+ const reasonStr = reason.toString() || "none";
3120
+ this.config.logger.info(`OsirisRTDS: Disconnected (code: ${code}, reason: ${reasonStr})`);
3121
+ this.config.onDisconnect?.();
3122
+ if (!this.isIntentionallyClosed) {
3123
+ this.attemptReconnect();
3124
+ }
3125
+ });
3126
+ } catch (error) {
3127
+ this.config.logger.error(`OsirisRTDS: Connection failed - ${error.message}`);
3128
+ if (!this.isIntentionallyClosed) {
3129
+ this.attemptReconnect();
3130
+ }
3131
+ }
3132
+ }
3133
+ /**
3134
+ * Disconnect from the Osiris Pub/Sub WebSocket
3135
+ */
3136
+ disconnect() {
3137
+ this.isIntentionallyClosed = true;
3138
+ this.stopPingInterval();
3139
+ if (this.reconnectTimeout) {
3140
+ clearTimeout(this.reconnectTimeout);
3141
+ this.reconnectTimeout = null;
3142
+ }
3143
+ if (this.ws) {
3144
+ this.config.logger.info("OsirisRTDS: Disconnecting...");
3145
+ try {
3146
+ if (this.activeTopics.size > 0) {
3147
+ this.unsubscribeFromTopics(Array.from(this.activeTopics));
3148
+ }
3149
+ this.ws.close(1e3, "Intentional close");
3150
+ } catch {
3151
+ }
3152
+ this.ws = null;
3153
+ }
3154
+ this.isConnected = false;
3155
+ this.activeTopics.clear();
3156
+ }
3157
+ /**
3158
+ * Check if connected
3159
+ */
3160
+ isActive() {
3161
+ return this.isConnected;
3162
+ }
3163
+ /**
3164
+ * Subscribe to events
3165
+ */
3166
+ subscribe(subscriptions) {
3167
+ if (!this.ws || !this.isConnected) {
3168
+ this.config.logger.warning("OsirisRTDS: Cannot subscribe - not connected");
3169
+ return;
3170
+ }
3171
+ const { topics, filters } = this.mapToOsirisSubscriptions(subscriptions);
3172
+ if (topics.length === 0) {
3173
+ this.config.logger.warning("OsirisRTDS: No valid topics to subscribe");
3174
+ return;
3175
+ }
3176
+ const message = {
3177
+ action: "subscribe",
3178
+ topics,
3179
+ ...Object.keys(filters).length > 0 ? { filters } : {}
3180
+ };
3181
+ try {
3182
+ this.ws.send(JSON.stringify(message));
3183
+ topics.forEach((t) => this.activeTopics.add(t));
3184
+ this.config.logger.info(`OsirisRTDS: Subscribing to ${topics.join(", ")}`);
3185
+ } catch (error) {
3186
+ this.config.logger.error(`OsirisRTDS: Failed to subscribe - ${error.message}`);
3187
+ }
3188
+ }
3189
+ /**
3190
+ * Unsubscribe from topics
3191
+ */
3192
+ unsubscribe(subscriptions) {
3193
+ if (!this.ws || !this.isConnected) {
3194
+ return;
3195
+ }
3196
+ const { topics } = this.mapToOsirisSubscriptions(subscriptions);
3197
+ this.unsubscribeFromTopics(topics);
3198
+ }
3199
+ /**
3200
+ * Unsubscribe from topics by name
3201
+ */
3202
+ unsubscribeFromTopics(topics) {
3203
+ if (topics.length === 0) return;
3204
+ const message = {
3205
+ action: "unsubscribe",
3206
+ topics
3207
+ };
3208
+ try {
3209
+ this.ws?.send(JSON.stringify(message));
3210
+ topics.forEach((t) => this.activeTopics.delete(t));
3211
+ this.config.logger.info(`OsirisRTDS: Unsubscribed from ${topics.join(", ")}`);
3212
+ } catch {
3213
+ }
3214
+ }
3215
+ /**
3216
+ * Send ping to keep connection alive
3217
+ */
3218
+ ping() {
3219
+ if (this.ws && this.isConnected) {
3220
+ try {
3221
+ this.ws.send(JSON.stringify({ action: "ping" }));
3222
+ } catch {
3223
+ }
3224
+ }
3225
+ }
3226
+ /**
3227
+ * Map SDK subscriptions to Osiris Pub/Sub format
3228
+ */
3229
+ mapToOsirisSubscriptions(subscriptions) {
3230
+ const topics = [];
3231
+ const filters = {};
3232
+ for (const sub of subscriptions) {
3233
+ const topic = this.mapSubscriptionToTopic(sub);
3234
+ if (topic) {
3235
+ topics.push(topic);
3236
+ if (sub.conditions) {
3237
+ filters[topic] = sub.conditions;
3238
+ }
3239
+ }
3240
+ }
3241
+ return { topics, filters };
3242
+ }
3243
+ /**
3244
+ * Map SDK subscription to Osiris topic string
3245
+ */
3246
+ mapSubscriptionToTopic(sub) {
3247
+ if (isMarketSubscription(sub)) {
3248
+ return sub.market ? `market:${sub.market}` : null;
3249
+ }
3250
+ if (isWalletSubscription(sub)) {
3251
+ return sub.wallet ? `wallet:${sub.wallet.toLowerCase()}` : null;
3252
+ }
3253
+ if (isOpportunitySubscription(sub)) {
3254
+ return `opps:${sub.filter || "all"}`;
3255
+ }
3256
+ if (isCustomSubscription(sub)) {
3257
+ return sub.topic || null;
3258
+ }
3259
+ return null;
3260
+ }
3261
+ /**
3262
+ * Start ping interval
3263
+ */
3264
+ startPingInterval() {
3265
+ this.stopPingInterval();
3266
+ this.pingInterval = setInterval(() => this.ping(), this.pingIntervalMs);
3267
+ }
3268
+ /**
3269
+ * Stop ping interval
3270
+ */
3271
+ stopPingInterval() {
3272
+ if (this.pingInterval) {
3273
+ clearInterval(this.pingInterval);
3274
+ this.pingInterval = null;
3275
+ }
3276
+ }
3277
+ /**
3278
+ * Attempt reconnection with exponential backoff
3279
+ */
3280
+ attemptReconnect() {
3281
+ if (this.reconnectAttempts >= this.maxReconnectAttempts) {
3282
+ this.config.logger.error(
3283
+ `OsirisRTDS: Max reconnection attempts (${this.maxReconnectAttempts}) reached`
3284
+ );
3285
+ return;
3286
+ }
3287
+ this.reconnectAttempts++;
3288
+ const delay = Math.min(
3289
+ this.baseReconnectDelay * Math.pow(2, this.reconnectAttempts - 1) + Math.random() * 1e3,
3290
+ this.maxReconnectDelay
3291
+ );
3292
+ this.config.logger.info(
3293
+ `OsirisRTDS: Reconnecting in ${Math.round(delay)}ms (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})`
3294
+ );
3295
+ this.reconnectTimeout = setTimeout(() => {
3296
+ this.reconnectTimeout = null;
3297
+ this.connect();
3298
+ }, delay);
3299
+ }
3300
+ /**
3301
+ * Handle incoming WebSocket messages
3302
+ */
3303
+ handleMessage(data) {
3304
+ try {
3305
+ const rawData = typeof data === "string" ? data : data.toString();
3306
+ if (!rawData.trim()) return;
3307
+ let message;
3308
+ try {
3309
+ message = JSON.parse(rawData);
3310
+ } catch {
3311
+ this.config.logger.warning(`OsirisRTDS: Non-JSON message received`);
3312
+ return;
3313
+ }
3314
+ switch (message.type) {
3315
+ case "connected":
3316
+ this.config.logger.info(`OsirisRTDS: ${message.message}`);
3317
+ return;
3318
+ case "subscribe.result":
3319
+ if (message.success) {
3320
+ this.config.logger.info(
3321
+ `OsirisRTDS: Subscribed to ${message.subscribed?.join(", ")}`
3322
+ );
3323
+ } else {
3324
+ this.config.logger.error(
3325
+ `OsirisRTDS: Subscription failed - ${message.errors?.join(", ")}`
3326
+ );
3327
+ }
3328
+ return;
3329
+ case "error":
3330
+ this.config.logger.error(`OsirisRTDS: Server error - ${message.error}`);
3331
+ return;
3332
+ case "pong":
3333
+ return;
3334
+ }
3335
+ const event = this.convertToStrategyEvent(message);
3336
+ if (event) {
3337
+ this.config.onEvent(event);
3338
+ }
3339
+ } catch (error) {
3340
+ this.config.logger.error(`OsirisRTDS: Error processing message - ${error.message}`);
3341
+ }
3342
+ }
3343
+ /**
3344
+ * Convert Osiris message to StrategyEvent
3345
+ */
3346
+ convertToStrategyEvent(message) {
3347
+ const timestamp = message.ts || Date.now();
3348
+ switch (message.type) {
3349
+ case "market.analysis":
3350
+ return {
3351
+ type: "price",
3352
+ // Market analysis treated as price/market update
3353
+ market: message.slug,
3354
+ timestamp,
3355
+ data: {
3356
+ ...message.data,
3357
+ raw: message
3358
+ }
3359
+ };
3360
+ case "wallet.analysis":
3361
+ return {
3362
+ type: "wallet",
3363
+ wallet: message.address,
3364
+ timestamp,
3365
+ data: {
3366
+ ...message.data,
3367
+ raw: message
3368
+ }
3369
+ };
3370
+ case "opportunity":
3371
+ return {
3372
+ type: "opportunity",
3373
+ market: message.slug,
3374
+ timestamp,
3375
+ data: {
3376
+ ...message.data,
3377
+ raw: message
3378
+ }
3379
+ };
3380
+ default:
3381
+ return null;
3382
+ }
3383
+ }
3384
+ };
3385
+ function createOsirisRTDSService(config) {
3386
+ return new OsirisRTDSService(config);
3387
+ }
3388
+
3389
+ // src/rtds/unified-rtds.service.ts
3390
+ var UnifiedRTDSService = class {
3391
+ config;
3392
+ polymarketService = null;
3393
+ osirisService = null;
3394
+ polymarketConnected = false;
3395
+ osirisConnected = false;
3396
+ constructor(config) {
3397
+ this.config = config;
3398
+ this.initializeServices();
3399
+ }
3400
+ /**
3401
+ * Initialize the underlying services based on configuration
3402
+ */
3403
+ initializeServices() {
3404
+ if (this.config.polymarket?.enabled !== false) {
3405
+ this.polymarketService = new PolymarketRTDSService({
3406
+ logger: this.config.logger,
3407
+ onEvent: this.config.onEvent,
3408
+ onError: this.config.onError,
3409
+ onConnect: () => {
3410
+ this.polymarketConnected = true;
3411
+ this.checkAllConnected();
3412
+ },
3413
+ onDisconnect: () => {
3414
+ this.polymarketConnected = false;
3415
+ this.checkAnyDisconnected();
3416
+ },
3417
+ clobAuth: this.config.polymarket?.clobAuth
3418
+ });
3419
+ }
3420
+ if (this.config.osiris?.enabled !== false) {
3421
+ this.osirisService = new OsirisRTDSService({
3422
+ logger: this.config.logger,
3423
+ onEvent: this.config.onEvent,
3424
+ onError: this.config.onError,
3425
+ onConnect: () => {
3426
+ this.osirisConnected = true;
3427
+ this.checkAllConnected();
3428
+ },
3429
+ onDisconnect: () => {
3430
+ this.osirisConnected = false;
3431
+ this.checkAnyDisconnected();
3432
+ },
3433
+ url: this.config.osiris?.url || DEFAULT_OSIRIS_RTDS_URL,
3434
+ pingIntervalMs: this.config.osiris?.pingIntervalMs,
3435
+ reconnect: this.config.reconnect
3436
+ });
3437
+ }
3438
+ }
3439
+ /**
3440
+ * Connect to all enabled services
3441
+ */
3442
+ connect() {
3443
+ this.config.logger.info("UnifiedRTDS: Connecting to enabled services...");
3444
+ if (this.polymarketService) {
3445
+ this.polymarketService.connect();
3446
+ }
3447
+ if (this.osirisService) {
3448
+ this.osirisService.connect();
3449
+ }
3450
+ }
3451
+ /**
3452
+ * Disconnect from all services
3453
+ */
3454
+ disconnect() {
3455
+ this.config.logger.info("UnifiedRTDS: Disconnecting from all services...");
3456
+ if (this.polymarketService) {
3457
+ this.polymarketService.disconnect();
3458
+ }
3459
+ if (this.osirisService) {
3460
+ this.osirisService.disconnect();
3461
+ }
3462
+ }
3463
+ /**
3464
+ * Check if connected to at least one service
3465
+ */
3466
+ isActive() {
3467
+ return (this.polymarketService?.isActive() ?? false) || (this.osirisService?.isActive() ?? false);
3468
+ }
3469
+ /**
3470
+ * Get connection status for each service
3471
+ */
3472
+ getStatus() {
3473
+ return {
3474
+ polymarket: {
3475
+ enabled: this.polymarketService !== null,
3476
+ connected: this.polymarketConnected
3477
+ },
3478
+ osiris: {
3479
+ enabled: this.osirisService !== null,
3480
+ connected: this.osirisConnected
3481
+ }
3482
+ };
3483
+ }
3484
+ /**
3485
+ * Subscribe to events
3486
+ * Automatically routes subscriptions to the appropriate backend
3487
+ */
3488
+ subscribe(subscriptions) {
3489
+ const { polymarketSubs, osirisSubs } = this.routeSubscriptions(subscriptions);
3490
+ if (polymarketSubs.length > 0) {
3491
+ if (this.polymarketService) {
3492
+ this.polymarketService.subscribe(polymarketSubs);
3493
+ } else {
3494
+ this.config.logger.warning(
3495
+ "UnifiedRTDS: Polymarket subscriptions requested but service not enabled"
3496
+ );
3497
+ }
3498
+ }
3499
+ if (osirisSubs.length > 0) {
3500
+ if (this.osirisService) {
3501
+ this.osirisService.subscribe(osirisSubs);
3502
+ } else {
3503
+ this.config.logger.warning(
3504
+ "UnifiedRTDS: Osiris subscriptions requested but service not enabled"
3505
+ );
3506
+ }
3507
+ }
3508
+ }
3509
+ /**
3510
+ * Unsubscribe from events
3511
+ */
3512
+ unsubscribe(subscriptions) {
3513
+ const { polymarketSubs, osirisSubs } = this.routeSubscriptions(subscriptions);
3514
+ if (polymarketSubs.length > 0 && this.polymarketService) {
3515
+ this.polymarketService.unsubscribe(polymarketSubs);
3516
+ }
3517
+ if (osirisSubs.length > 0 && this.osirisService) {
3518
+ this.osirisService.unsubscribe(osirisSubs);
3519
+ }
3520
+ }
3521
+ /**
3522
+ * Route subscriptions to appropriate backends based on type and eventSource
3523
+ */
3524
+ routeSubscriptions(subscriptions) {
3525
+ const polymarketSubs = [];
3526
+ const osirisSubs = [];
3527
+ for (const sub of subscriptions) {
3528
+ if (sub.eventSource === "polymarket") {
3529
+ polymarketSubs.push(sub);
3530
+ continue;
3531
+ }
3532
+ if (sub.eventSource === "osiris") {
3533
+ osirisSubs.push(sub);
3534
+ continue;
3535
+ }
3536
+ if (isPolymarketSubscription(sub)) {
3537
+ polymarketSubs.push(sub);
3538
+ } else if (isOsirisSubscription(sub)) {
3539
+ osirisSubs.push(sub);
3540
+ } else if (isMarketSubscription(sub)) {
3541
+ polymarketSubs.push(sub);
3542
+ } else if (isCustomSubscription(sub)) {
3543
+ const topic = sub.topic;
3544
+ if (topic.startsWith("market:") || topic.startsWith("wallet:") || topic.startsWith("opps:")) {
3545
+ osirisSubs.push(sub);
3546
+ } else {
3547
+ polymarketSubs.push(sub);
3548
+ }
3549
+ } else {
3550
+ polymarketSubs.push(sub);
3551
+ }
3552
+ }
3553
+ return { polymarketSubs, osirisSubs };
3554
+ }
3555
+ /**
3556
+ * Check if all enabled services are connected
3557
+ */
3558
+ checkAllConnected() {
3559
+ const polymarketOk = !this.polymarketService || this.polymarketConnected;
3560
+ const osirisOk = !this.osirisService || this.osirisConnected;
3561
+ if (polymarketOk && osirisOk) {
3562
+ this.config.onConnect?.();
3563
+ }
3564
+ }
3565
+ /**
3566
+ * Check if any service disconnected
3567
+ */
3568
+ checkAnyDisconnected() {
3569
+ if (!this.polymarketConnected && !this.osirisConnected) {
3570
+ this.config.onDisconnect?.();
3571
+ }
3572
+ }
3573
+ };
3574
+ function createUnifiedRTDSService(config) {
3575
+ return new UnifiedRTDSService(config);
3576
+ }
2528
3577
  var CHAIN_MAP = {
2529
3578
  "evm:eip155:1": mainnet,
2530
3579
  "evm:eip155:137": polygon,
@@ -2675,6 +3724,6 @@ var Signer = class {
2675
3724
  }
2676
3725
  };
2677
3726
 
2678
- export { HyperliquidClient, MemoryStateManager, OsirisEventRunner, OsirisSigner, PolymarketClient, PolymarketEventRunner, PrivateKeySigner, RedisStateManager, Signer, StrategyEngine, createConsoleLogger, createEventRunner, createOsirisContext, createPolymarketEventRunner, createStrategyEngine, isCustomSubscription, isEventBasedStrategy, isMarketSubscription, isOpportunitySubscription, isTickBasedStrategy, isWalletSubscription, runStrategy, validateStrategy };
3727
+ export { DEFAULT_OSIRIS_RTDS_URL, HyperliquidClient, MemoryStateManager, OsirisEventRunner, OsirisRTDSService, OsirisSigner, PolymarketClient, PolymarketEventRunner, PolymarketRTDSService, PrivateKeySigner, RedisStateManager, Signer, StrategyEngine, UnifiedRTDSService, createConsoleLogger, createEventRunner, createOsirisContext, createOsirisRTDSService, createPolymarketEventRunner, createPolymarketRTDSService, createStrategyEngine, createUnifiedRTDSService, isActivitySubscription, isClobMarketSubscription, isClobUserSubscription, isCommentsSubscription, isCryptoPricesSubscription, isCustomSubscription, isEventBasedStrategy, isMarketSubscription, isOpportunitySubscription, isOsirisSubscription, isPolymarketSubscription, isRfqSubscription, isTickBasedStrategy, isWalletSubscription, runStrategy, validateStrategy };
2679
3728
  //# sourceMappingURL=index.js.map
2680
3729
  //# sourceMappingURL=index.js.map