pmxt-core 2.3.0 → 2.5.0

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.
Files changed (89) hide show
  1. package/dist/BaseExchange.d.ts +38 -0
  2. package/dist/BaseExchange.js +51 -2
  3. package/dist/errors.d.ts +6 -0
  4. package/dist/errors.js +21 -1
  5. package/dist/exchanges/baozi/auth.d.ts +14 -0
  6. package/dist/exchanges/baozi/auth.js +33 -0
  7. package/dist/exchanges/baozi/errors.d.ts +11 -0
  8. package/dist/exchanges/baozi/errors.js +70 -0
  9. package/dist/exchanges/baozi/fetchEvents.d.ts +8 -0
  10. package/dist/exchanges/baozi/fetchEvents.js +34 -0
  11. package/dist/exchanges/baozi/fetchMarkets.d.ts +5 -0
  12. package/dist/exchanges/baozi/fetchMarkets.js +160 -0
  13. package/dist/exchanges/baozi/fetchOHLCV.d.ts +6 -0
  14. package/dist/exchanges/baozi/fetchOHLCV.js +10 -0
  15. package/dist/exchanges/baozi/fetchOrderBook.d.ts +12 -0
  16. package/dist/exchanges/baozi/fetchOrderBook.js +36 -0
  17. package/dist/exchanges/baozi/fetchTrades.d.ts +6 -0
  18. package/dist/exchanges/baozi/fetchTrades.js +10 -0
  19. package/dist/exchanges/baozi/index.d.ts +28 -0
  20. package/dist/exchanges/baozi/index.js +404 -0
  21. package/dist/exchanges/baozi/utils.d.ts +112 -0
  22. package/dist/exchanges/baozi/utils.js +446 -0
  23. package/dist/exchanges/baozi/websocket.d.ts +14 -0
  24. package/dist/exchanges/baozi/websocket.js +78 -0
  25. package/dist/exchanges/kalshi/auth.js +1 -0
  26. package/dist/exchanges/kalshi/fetchEvents.js +39 -0
  27. package/dist/exchanges/kalshi/fetchMarkets.js +13 -0
  28. package/dist/exchanges/kalshi/index.js +6 -0
  29. package/dist/exchanges/kalshi/websocket.js +14 -9
  30. package/dist/exchanges/limitless/auth.js +4 -0
  31. package/dist/exchanges/limitless/client.js +5 -1
  32. package/dist/exchanges/limitless/fetchEvents.js +69 -0
  33. package/dist/exchanges/limitless/fetchMarkets.js +13 -0
  34. package/dist/exchanges/limitless/index.js +8 -1
  35. package/dist/exchanges/limitless/websocket.js +7 -5
  36. package/dist/exchanges/myriad/auth.d.ts +8 -0
  37. package/dist/exchanges/myriad/auth.js +25 -0
  38. package/dist/exchanges/myriad/errors.d.ts +8 -0
  39. package/dist/exchanges/myriad/errors.js +33 -0
  40. package/dist/exchanges/myriad/fetchEvents.d.ts +3 -0
  41. package/dist/exchanges/myriad/fetchEvents.js +48 -0
  42. package/dist/exchanges/myriad/fetchMarkets.d.ts +3 -0
  43. package/dist/exchanges/myriad/fetchMarkets.js +102 -0
  44. package/dist/exchanges/myriad/fetchOHLCV.d.ts +3 -0
  45. package/dist/exchanges/myriad/fetchOHLCV.js +91 -0
  46. package/dist/exchanges/myriad/fetchOrderBook.d.ts +2 -0
  47. package/dist/exchanges/myriad/fetchOrderBook.js +47 -0
  48. package/dist/exchanges/myriad/fetchTrades.d.ts +3 -0
  49. package/dist/exchanges/myriad/fetchTrades.js +62 -0
  50. package/dist/exchanges/myriad/index.d.ts +24 -0
  51. package/dist/exchanges/myriad/index.js +209 -0
  52. package/dist/exchanges/myriad/utils.d.ts +15 -0
  53. package/dist/exchanges/myriad/utils.js +99 -0
  54. package/dist/exchanges/myriad/websocket.d.ts +17 -0
  55. package/dist/exchanges/myriad/websocket.js +105 -0
  56. package/dist/exchanges/polymarket/auth.js +6 -0
  57. package/dist/exchanges/polymarket/fetchEvents.js +72 -3
  58. package/dist/exchanges/polymarket/fetchMarkets.js +52 -0
  59. package/dist/exchanges/polymarket/index.js +6 -0
  60. package/dist/exchanges/polymarket/websocket.js +6 -3
  61. package/dist/exchanges/probable/auth.d.ts +14 -0
  62. package/dist/exchanges/probable/auth.js +67 -0
  63. package/dist/exchanges/probable/errors.d.ts +8 -0
  64. package/dist/exchanges/probable/errors.js +61 -0
  65. package/dist/exchanges/probable/fetchEvents.d.ts +5 -0
  66. package/dist/exchanges/probable/fetchEvents.js +148 -0
  67. package/dist/exchanges/probable/fetchMarkets.d.ts +3 -0
  68. package/dist/exchanges/probable/fetchMarkets.js +235 -0
  69. package/dist/exchanges/probable/fetchOHLCV.d.ts +3 -0
  70. package/dist/exchanges/probable/fetchOHLCV.js +83 -0
  71. package/dist/exchanges/probable/fetchOrderBook.d.ts +2 -0
  72. package/dist/exchanges/probable/fetchOrderBook.js +37 -0
  73. package/dist/exchanges/probable/fetchPositions.d.ts +2 -0
  74. package/dist/exchanges/probable/fetchPositions.js +33 -0
  75. package/dist/exchanges/probable/fetchTrades.d.ts +10 -0
  76. package/dist/exchanges/probable/fetchTrades.js +36 -0
  77. package/dist/exchanges/probable/index.d.ts +35 -0
  78. package/dist/exchanges/probable/index.js +317 -0
  79. package/dist/exchanges/probable/utils.d.ts +9 -0
  80. package/dist/exchanges/probable/utils.js +106 -0
  81. package/dist/exchanges/probable/websocket.d.ts +27 -0
  82. package/dist/exchanges/probable/websocket.js +102 -0
  83. package/dist/index.d.ts +12 -0
  84. package/dist/index.js +14 -2
  85. package/dist/server/app.js +23 -1
  86. package/dist/server/utils/lock-file.d.ts +1 -0
  87. package/dist/server/utils/lock-file.js +29 -8
  88. package/dist/utils/error-mapper.js +1 -0
  89. package/package.json +6 -3
@@ -9,8 +9,12 @@ const LIMITLESS_API_URL = 'https://api.limitless.exchange';
9
9
  * Provides a simplified interface for market data and order operations.
10
10
  */
11
11
  class LimitlessClient {
12
+ httpClient;
13
+ orderClient;
14
+ marketFetcher;
15
+ signer;
16
+ marketCache = {};
12
17
  constructor(privateKey, apiKey) {
13
- this.marketCache = {};
14
18
  // Fix for common .env issue where newlines are escaped
15
19
  if (privateKey.includes('\\n')) {
16
20
  privateKey = privateKey.replace(/\\n/g, '\n');
@@ -1,4 +1,37 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
37
  };
@@ -7,8 +40,44 @@ exports.fetchEvents = fetchEvents;
7
40
  const axios_1 = __importDefault(require("axios"));
8
41
  const utils_1 = require("./utils");
9
42
  const errors_1 = require("./errors");
43
+ async function fetchEventBySlug(slug) {
44
+ const { HttpClient, MarketFetcher } = await Promise.resolve().then(() => __importStar(require('@limitless-exchange/sdk')));
45
+ const httpClient = new HttpClient({ baseURL: utils_1.LIMITLESS_API_URL });
46
+ const marketFetcher = new MarketFetcher(httpClient);
47
+ const market = await marketFetcher.getMarket(slug);
48
+ if (!market)
49
+ return null;
50
+ let marketsList = [];
51
+ if (market.markets && Array.isArray(market.markets)) {
52
+ marketsList = market.markets
53
+ .map((child) => (0, utils_1.mapMarketToUnified)(child))
54
+ .filter((m) => m !== null);
55
+ }
56
+ else {
57
+ const unifiedMarket = (0, utils_1.mapMarketToUnified)(market);
58
+ if (unifiedMarket)
59
+ marketsList = [unifiedMarket];
60
+ }
61
+ return {
62
+ id: market.slug,
63
+ title: market.title || market.question,
64
+ description: market.description || '',
65
+ slug: market.slug,
66
+ markets: marketsList,
67
+ url: `https://limitless.exchange/markets/${market.slug}`,
68
+ image: market.logo || `https://limitless.exchange/api/og?slug=${market.slug}`,
69
+ category: market.categories?.[0],
70
+ tags: market.tags || []
71
+ };
72
+ }
10
73
  async function fetchEvents(params) {
11
74
  try {
75
+ // Handle eventId/slug lookup (same thing for Limitless)
76
+ if (params.eventId || params.slug) {
77
+ const slug = params.eventId || params.slug;
78
+ const event = await fetchEventBySlug(slug);
79
+ return event ? [event] : [];
80
+ }
12
81
  // NOTE: The Limitless /markets/search endpoint currently only returns active/funded markets.
13
82
  // It does not include expired or resolved markets in search results.
14
83
  // Consequently, status 'inactive' will likely return 0 results and 'all' will only show active markets.
@@ -55,10 +55,23 @@ async function fetchMarkets(params, apiKey) {
55
55
  apiKey: apiKey, // Optional - not required for public market data
56
56
  });
57
57
  const marketFetcher = new MarketFetcher(httpClient);
58
+ // Handle marketId lookup (Limitless marketId is the slug)
59
+ if (params?.marketId) {
60
+ return await fetchMarketsBySlug(marketFetcher, params.marketId);
61
+ }
58
62
  // Handle slug-based lookup
59
63
  if (params?.slug) {
60
64
  return await fetchMarketsBySlug(marketFetcher, params.slug);
61
65
  }
66
+ // Handle outcomeId lookup (no direct API, fetch and filter client-side)
67
+ if (params?.outcomeId) {
68
+ const markets = await fetchMarketsDefault(marketFetcher, params);
69
+ return markets.filter(m => m.outcomes.some(o => o.outcomeId === params.outcomeId));
70
+ }
71
+ // Handle eventId lookup (same as slug for Limitless)
72
+ if (params?.eventId) {
73
+ return await fetchMarketsBySlug(marketFetcher, params.eventId);
74
+ }
62
75
  // Handle query-based search
63
76
  if (params?.query) {
64
77
  return await searchMarkets(marketFetcher, params.query, params);
@@ -16,6 +16,9 @@ const errors_2 = require("../../errors");
16
16
  const sdk_1 = require("@limitless-exchange/sdk");
17
17
  const ethers_1 = require("ethers");
18
18
  class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
19
+ auth;
20
+ client;
21
+ wsConfig;
19
22
  constructor(options) {
20
23
  // Support both old signature (credentials only) and new signature (options object)
21
24
  let credentials;
@@ -112,7 +115,7 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
112
115
  throw new Error('Limit orders require a price');
113
116
  }
114
117
  // Limitless (USDC on Base) supports 6 decimals max.
115
- const price = Math.round(params.price * 1000000) / 1000000;
118
+ const price = Math.round(params.price * 1_000_000) / 1_000_000;
116
119
  const response = await client.createOrder({
117
120
  marketSlug: marketSlug,
118
121
  outcomeId: params.outcomeId,
@@ -231,6 +234,10 @@ class LimitlessExchange extends BaseExchange_1.PredictionMarketExchange {
231
234
  throw errors_1.limitlessErrorMapper.mapError(error);
232
235
  }
233
236
  }
237
+ // ----------------------------------------------------------------------------
238
+ // WebSocket Methods
239
+ // ----------------------------------------------------------------------------
240
+ ws;
234
241
  /**
235
242
  * Initialize WebSocket with API key if available.
236
243
  */
@@ -21,12 +21,14 @@ function convertSize(rawSize) {
21
21
  * - User transactions (requires API key)
22
22
  */
23
23
  class LimitlessWebSocket {
24
+ client;
25
+ config;
26
+ orderbookCallbacks = new Map();
27
+ priceCallbacks = new Map();
28
+ orderbookResolvers = new Map();
29
+ orderbookBuffers = new Map();
30
+ lastOrderbookTimestamps = new Map();
24
31
  constructor(config = {}) {
25
- this.orderbookCallbacks = new Map();
26
- this.priceCallbacks = new Map();
27
- this.orderbookResolvers = new Map();
28
- this.orderbookBuffers = new Map();
29
- this.lastOrderbookTimestamps = new Map();
30
32
  this.config = config;
31
33
  // Initialize SDK WebSocket client
32
34
  const wsConfig = {
@@ -0,0 +1,8 @@
1
+ import { ExchangeCredentials } from '../../BaseExchange';
2
+ export declare class MyriadAuth {
3
+ private credentials;
4
+ constructor(credentials: ExchangeCredentials);
5
+ private validateCredentials;
6
+ getHeaders(): Record<string, string>;
7
+ get walletAddress(): string | undefined;
8
+ }
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MyriadAuth = void 0;
4
+ class MyriadAuth {
5
+ credentials;
6
+ constructor(credentials) {
7
+ this.credentials = credentials;
8
+ this.validateCredentials();
9
+ }
10
+ validateCredentials() {
11
+ if (!this.credentials.apiKey) {
12
+ throw new Error('Myriad requires an apiKey for authentication');
13
+ }
14
+ }
15
+ getHeaders() {
16
+ return {
17
+ 'x-api-key': this.credentials.apiKey,
18
+ 'Content-Type': 'application/json',
19
+ };
20
+ }
21
+ get walletAddress() {
22
+ return this.credentials.privateKey;
23
+ }
24
+ }
25
+ exports.MyriadAuth = MyriadAuth;
@@ -0,0 +1,8 @@
1
+ import { ErrorMapper } from '../../utils/error-mapper';
2
+ import { BadRequest } from '../../errors';
3
+ export declare class MyriadErrorMapper extends ErrorMapper {
4
+ constructor();
5
+ protected extractErrorMessage(error: any): string;
6
+ protected mapBadRequestError(message: string, data: any): BadRequest;
7
+ }
8
+ export declare const myriadErrorMapper: MyriadErrorMapper;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.myriadErrorMapper = exports.MyriadErrorMapper = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const error_mapper_1 = require("../../utils/error-mapper");
9
+ const errors_1 = require("../../errors");
10
+ class MyriadErrorMapper extends error_mapper_1.ErrorMapper {
11
+ constructor() {
12
+ super('Myriad');
13
+ }
14
+ extractErrorMessage(error) {
15
+ if (axios_1.default.isAxiosError(error) && error.response?.data) {
16
+ const data = error.response.data;
17
+ if (data.message)
18
+ return data.message;
19
+ if (data.error && typeof data.error === 'string')
20
+ return data.error;
21
+ }
22
+ return super.extractErrorMessage(error);
23
+ }
24
+ mapBadRequestError(message, data) {
25
+ const lowerMessage = message.toLowerCase();
26
+ if (lowerMessage.includes('insufficient') || lowerMessage.includes('liquidity')) {
27
+ return new errors_1.BadRequest(message, this.exchangeName);
28
+ }
29
+ return super.mapBadRequestError(message, data);
30
+ }
31
+ }
32
+ exports.MyriadErrorMapper = MyriadErrorMapper;
33
+ exports.myriadErrorMapper = new MyriadErrorMapper();
@@ -0,0 +1,3 @@
1
+ import { EventFetchParams } from '../../BaseExchange';
2
+ import { UnifiedEvent } from '../../types';
3
+ export declare function fetchEvents(params: EventFetchParams, headers?: Record<string, string>): Promise<UnifiedEvent[]>;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.fetchEvents = fetchEvents;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const utils_1 = require("./utils");
9
+ const errors_1 = require("./errors");
10
+ async function fetchEvents(params, headers) {
11
+ try {
12
+ if (params.eventId) {
13
+ return await fetchQuestionById(params.eventId, headers);
14
+ }
15
+ if (params.slug) {
16
+ return await fetchQuestionById(params.slug, headers);
17
+ }
18
+ const limit = params.limit || 100;
19
+ const queryParams = {
20
+ page: 1,
21
+ limit: Math.min(limit, 100),
22
+ };
23
+ if (params.query) {
24
+ queryParams.keyword = params.query;
25
+ }
26
+ const response = await axios_1.default.get(`${utils_1.BASE_URL}/questions`, {
27
+ params: queryParams,
28
+ headers,
29
+ });
30
+ const questions = response.data.data || response.data.questions || [];
31
+ const events = [];
32
+ for (const q of questions) {
33
+ const event = (0, utils_1.mapQuestionToEvent)(q);
34
+ if (event)
35
+ events.push(event);
36
+ }
37
+ return events.slice(0, limit);
38
+ }
39
+ catch (error) {
40
+ throw errors_1.myriadErrorMapper.mapError(error);
41
+ }
42
+ }
43
+ async function fetchQuestionById(id, headers) {
44
+ const response = await axios_1.default.get(`${utils_1.BASE_URL}/questions/${id}`, { headers });
45
+ const question = response.data.data || response.data;
46
+ const event = (0, utils_1.mapQuestionToEvent)(question);
47
+ return event ? [event] : [];
48
+ }
@@ -0,0 +1,3 @@
1
+ import { MarketFetchParams } from '../../BaseExchange';
2
+ import { UnifiedMarket } from '../../types';
3
+ export declare function fetchMarkets(params?: MarketFetchParams, headers?: Record<string, string>): Promise<UnifiedMarket[]>;
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.fetchMarkets = fetchMarkets;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const utils_1 = require("./utils");
9
+ const errors_1 = require("./errors");
10
+ const MAX_PAGE_SIZE = 100;
11
+ async function fetchMarkets(params, headers) {
12
+ try {
13
+ if (params?.marketId) {
14
+ return await fetchMarketById(params.marketId, headers);
15
+ }
16
+ if (params?.slug) {
17
+ return await fetchMarketBySlug(params.slug, headers);
18
+ }
19
+ const limit = params?.limit || 100;
20
+ const queryParams = {
21
+ page: params?.page || 1,
22
+ limit: Math.min(limit, MAX_PAGE_SIZE),
23
+ };
24
+ if (params?.query) {
25
+ queryParams.keyword = params.query;
26
+ }
27
+ const myriadState = (0, utils_1.mapStatusToMyriad)(params?.status);
28
+ if (myriadState) {
29
+ queryParams.state = myriadState;
30
+ }
31
+ if (params?.sort === 'volume') {
32
+ queryParams.sort = 'volume';
33
+ queryParams.order = 'desc';
34
+ }
35
+ else if (params?.sort === 'liquidity') {
36
+ queryParams.sort = 'liquidity';
37
+ queryParams.order = 'desc';
38
+ }
39
+ else if (params?.sort === 'newest') {
40
+ queryParams.sort = 'published_at';
41
+ queryParams.order = 'desc';
42
+ }
43
+ // If we need more than one page, paginate
44
+ if (limit <= MAX_PAGE_SIZE) {
45
+ const response = await axios_1.default.get(`${utils_1.BASE_URL}/markets`, {
46
+ params: queryParams,
47
+ headers,
48
+ });
49
+ const markets = response.data.data || response.data.markets || [];
50
+ return markets.map(utils_1.mapMarketToUnified).filter(Boolean);
51
+ }
52
+ // Paginate through multiple pages
53
+ const allMarkets = [];
54
+ let page = 1;
55
+ const maxPages = Math.ceil(limit / MAX_PAGE_SIZE);
56
+ while (page <= maxPages) {
57
+ queryParams.page = page;
58
+ queryParams.limit = MAX_PAGE_SIZE;
59
+ const response = await axios_1.default.get(`${utils_1.BASE_URL}/markets`, {
60
+ params: queryParams,
61
+ headers,
62
+ });
63
+ const data = response.data;
64
+ const markets = data.data || data.markets || [];
65
+ for (const m of markets) {
66
+ const um = (0, utils_1.mapMarketToUnified)(m);
67
+ if (um)
68
+ allMarkets.push(um);
69
+ }
70
+ const pagination = data.pagination;
71
+ if (!pagination?.hasNext || markets.length === 0)
72
+ break;
73
+ page++;
74
+ }
75
+ return allMarkets.slice(0, limit);
76
+ }
77
+ catch (error) {
78
+ throw errors_1.myriadErrorMapper.mapError(error);
79
+ }
80
+ }
81
+ async function fetchMarketById(marketId, headers) {
82
+ // marketId format: {networkId}:{id}
83
+ const parts = marketId.split(':');
84
+ if (parts.length !== 2) {
85
+ // Try as slug
86
+ return fetchMarketBySlug(marketId, headers);
87
+ }
88
+ const [networkId, id] = parts;
89
+ const response = await axios_1.default.get(`${utils_1.BASE_URL}/markets/${id}`, {
90
+ params: { network_id: Number(networkId) },
91
+ headers,
92
+ });
93
+ const market = response.data.data || response.data;
94
+ const um = (0, utils_1.mapMarketToUnified)(market);
95
+ return um ? [um] : [];
96
+ }
97
+ async function fetchMarketBySlug(slug, headers) {
98
+ const response = await axios_1.default.get(`${utils_1.BASE_URL}/markets/${slug}`, { headers });
99
+ const market = response.data.data || response.data;
100
+ const um = (0, utils_1.mapMarketToUnified)(market);
101
+ return um ? [um] : [];
102
+ }
@@ -0,0 +1,3 @@
1
+ import { OHLCVParams, HistoryFilterParams } from '../../BaseExchange';
2
+ import { PriceCandle } from '../../types';
3
+ export declare function fetchOHLCV(id: string, params: OHLCVParams | HistoryFilterParams, headers?: Record<string, string>): Promise<PriceCandle[]>;
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.fetchOHLCV = fetchOHLCV;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const utils_1 = require("./utils");
9
+ const errors_1 = require("./errors");
10
+ // Myriad provides price charts via GET /markets/:id with these timeframes:
11
+ // - 24h: 5-minute buckets (max 288)
12
+ // - 7d: 30-minute buckets (max 336)
13
+ // - 30d: 4-hour buckets (max 180)
14
+ // - all: 4-hour buckets
15
+ function selectTimeframe(interval) {
16
+ switch (interval) {
17
+ case '1m':
18
+ case '5m':
19
+ return '24h';
20
+ case '15m':
21
+ case '1h':
22
+ return '7d';
23
+ case '6h':
24
+ case '1d':
25
+ return '30d';
26
+ default:
27
+ return '7d';
28
+ }
29
+ }
30
+ async function fetchOHLCV(id, params, headers) {
31
+ if (!params.resolution) {
32
+ throw new Error('fetchOHLCV requires a resolution parameter.');
33
+ }
34
+ try {
35
+ // id format: {networkId}:{marketId}:{outcomeId}
36
+ // We need the marketId and networkId to fetch the market, then extract the outcome's price_charts
37
+ const parts = id.split(':');
38
+ if (parts.length < 2) {
39
+ throw new Error(`Invalid Myriad outcome ID format: "${id}". Expected "{networkId}:{marketId}:{outcomeId}".`);
40
+ }
41
+ const networkId = parts[0];
42
+ const marketId = parts[1];
43
+ const outcomeId = parts.length >= 3 ? parts[2] : undefined;
44
+ const response = await axios_1.default.get(`${utils_1.BASE_URL}/markets/${marketId}`, {
45
+ params: { network_id: Number(networkId) },
46
+ headers,
47
+ });
48
+ const market = response.data.data || response.data;
49
+ const outcomes = market.outcomes || [];
50
+ // Find the target outcome
51
+ let targetOutcome = outcomes[0];
52
+ if (outcomeId !== undefined) {
53
+ const found = outcomes.find((o) => String(o.id) === outcomeId);
54
+ if (found)
55
+ targetOutcome = found;
56
+ }
57
+ if (!targetOutcome || !targetOutcome.price_charts) {
58
+ return [];
59
+ }
60
+ // price_charts is an object with numeric keys (0-3), each containing:
61
+ // { timeframe: '24h'|'7d'|'30d'|'all', prices: [{value, timestamp, date}] }
62
+ const desiredTimeframe = selectTimeframe(params.resolution);
63
+ const charts = targetOutcome.price_charts;
64
+ let prices = null;
65
+ for (const key of Object.keys(charts)) {
66
+ const chart = charts[key];
67
+ if (chart && chart.timeframe === desiredTimeframe && Array.isArray(chart.prices)) {
68
+ prices = chart.prices;
69
+ break;
70
+ }
71
+ }
72
+ if (!prices || prices.length === 0) {
73
+ return [];
74
+ }
75
+ const candles = prices.map((point) => ({
76
+ timestamp: point.timestamp ? point.timestamp * 1000 : Date.now(),
77
+ open: Number(point.value || 0),
78
+ high: Number(point.value || 0),
79
+ low: Number(point.value || 0),
80
+ close: Number(point.value || 0),
81
+ volume: undefined,
82
+ }));
83
+ if (params.limit && candles.length > params.limit) {
84
+ return candles.slice(-params.limit);
85
+ }
86
+ return candles;
87
+ }
88
+ catch (error) {
89
+ throw errors_1.myriadErrorMapper.mapError(error);
90
+ }
91
+ }
@@ -0,0 +1,2 @@
1
+ import { OrderBook } from '../../types';
2
+ export declare function fetchOrderBook(id: string, headers?: Record<string, string>): Promise<OrderBook>;
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.fetchOrderBook = fetchOrderBook;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const utils_1 = require("./utils");
9
+ const errors_1 = require("./errors");
10
+ // Myriad is AMM-based -- there is no native order book.
11
+ // We synthesize a minimal order book from the current outcome price
12
+ // and quote data to give callers a consistent interface.
13
+ async function fetchOrderBook(id, headers) {
14
+ try {
15
+ // id format: {networkId}:{marketId}:{outcomeId}
16
+ const parts = id.split(':');
17
+ if (parts.length < 3) {
18
+ throw new Error(`Invalid Myriad outcome ID format: "${id}". Expected "{networkId}:{marketId}:{outcomeId}".`);
19
+ }
20
+ const [networkId, marketId, outcomeId] = parts;
21
+ // Fetch the market to get current prices
22
+ const response = await axios_1.default.get(`${utils_1.BASE_URL}/markets/${marketId}`, {
23
+ params: { network_id: Number(networkId) },
24
+ headers,
25
+ });
26
+ const market = response.data.data || response.data;
27
+ const outcomes = market.outcomes || [];
28
+ const outcome = outcomes.find((o) => String(o.id) === outcomeId) || outcomes[0];
29
+ if (!outcome) {
30
+ return { bids: [], asks: [], timestamp: Date.now() };
31
+ }
32
+ const price = Number(outcome.price) || 0.5;
33
+ const liquidity = Number(market.liquidity || 0);
34
+ // For AMM markets, we represent the current price as a single-level book.
35
+ // The spread is zero (AMM provides continuous liquidity at the current price).
36
+ // Size is derived from the market's liquidity.
37
+ const size = liquidity > 0 ? liquidity : 1;
38
+ return {
39
+ bids: [{ price, size }],
40
+ asks: [{ price, size }],
41
+ timestamp: Date.now(),
42
+ };
43
+ }
44
+ catch (error) {
45
+ throw errors_1.myriadErrorMapper.mapError(error);
46
+ }
47
+ }
@@ -0,0 +1,3 @@
1
+ import { TradesParams, HistoryFilterParams } from '../../BaseExchange';
2
+ import { Trade } from '../../types';
3
+ export declare function fetchTrades(id: string, params: TradesParams | HistoryFilterParams, headers?: Record<string, string>): Promise<Trade[]>;
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.fetchTrades = fetchTrades;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const utils_1 = require("./utils");
9
+ const errors_1 = require("./errors");
10
+ async function fetchTrades(id, params, headers) {
11
+ try {
12
+ // id format: {networkId}:{marketId}:{outcomeId} or {networkId}:{marketId}
13
+ const parts = id.split(':');
14
+ if (parts.length < 2) {
15
+ throw new Error(`Invalid Myriad ID format: "${id}". Expected "{networkId}:{marketId}" or "{networkId}:{marketId}:{outcomeId}".`);
16
+ }
17
+ const [networkId, marketId] = parts;
18
+ const outcomeId = parts.length >= 3 ? parts[2] : undefined;
19
+ const queryParams = {
20
+ network_id: Number(networkId),
21
+ page: 1,
22
+ limit: params.limit || 100,
23
+ };
24
+ // Handle date range filters
25
+ const ensureDate = (d) => {
26
+ if (typeof d === 'string') {
27
+ if (!d.endsWith('Z') && !d.match(/[+-]\d{2}:\d{2}$/)) {
28
+ return new Date(d + 'Z');
29
+ }
30
+ return new Date(d);
31
+ }
32
+ return d;
33
+ };
34
+ if (params.start) {
35
+ queryParams.since = Math.floor(ensureDate(params.start).getTime() / 1000);
36
+ }
37
+ if (params.end) {
38
+ queryParams.until = Math.floor(ensureDate(params.end).getTime() / 1000);
39
+ }
40
+ const response = await axios_1.default.get(`${utils_1.BASE_URL}/markets/${marketId}/events`, {
41
+ params: queryParams,
42
+ headers,
43
+ });
44
+ const events = response.data.data || response.data.events || [];
45
+ // Filter to buy/sell actions only (skip liquidity events)
46
+ const tradeEvents = events.filter((e) => e.action === 'buy' || e.action === 'sell');
47
+ // Filter by outcomeId if specified
48
+ const filtered = outcomeId
49
+ ? tradeEvents.filter((e) => String(e.outcomeId) === outcomeId)
50
+ : tradeEvents;
51
+ return filtered.map((t, index) => ({
52
+ id: `${t.blockNumber || t.timestamp}-${index}`,
53
+ timestamp: (t.timestamp || 0) * 1000,
54
+ price: t.shares > 0 ? Number(t.value) / Number(t.shares) : 0,
55
+ amount: Number(t.shares || 0),
56
+ side: t.action === 'buy' ? 'buy' : 'sell',
57
+ }));
58
+ }
59
+ catch (error) {
60
+ throw errors_1.myriadErrorMapper.mapError(error);
61
+ }
62
+ }
@@ -0,0 +1,24 @@
1
+ import { PredictionMarketExchange, MarketFilterParams, HistoryFilterParams, OHLCVParams, TradesParams, ExchangeCredentials, EventFetchParams } from '../../BaseExchange';
2
+ import { UnifiedMarket, UnifiedEvent, PriceCandle, OrderBook, Trade, Balance, Order, Position, CreateOrderParams } from '../../types';
3
+ export declare class MyriadExchange extends PredictionMarketExchange {
4
+ private auth?;
5
+ private ws?;
6
+ constructor(credentials?: ExchangeCredentials);
7
+ get name(): string;
8
+ private getHeaders;
9
+ private ensureAuth;
10
+ protected fetchMarketsImpl(params?: MarketFilterParams): Promise<UnifiedMarket[]>;
11
+ protected fetchEventsImpl(params: EventFetchParams): Promise<UnifiedEvent[]>;
12
+ fetchOHLCV(id: string, params: OHLCVParams | HistoryFilterParams): Promise<PriceCandle[]>;
13
+ fetchOrderBook(id: string): Promise<OrderBook>;
14
+ fetchTrades(id: string, params: TradesParams | HistoryFilterParams): Promise<Trade[]>;
15
+ createOrder(params: CreateOrderParams): Promise<Order>;
16
+ cancelOrder(_orderId: string): Promise<Order>;
17
+ fetchOrder(_orderId: string): Promise<Order>;
18
+ fetchOpenOrders(_marketId?: string): Promise<Order[]>;
19
+ fetchPositions(): Promise<Position[]>;
20
+ fetchBalance(): Promise<Balance[]>;
21
+ watchOrderBook(id: string, _limit?: number): Promise<OrderBook>;
22
+ watchTrades(id: string, _since?: number, _limit?: number): Promise<Trade[]>;
23
+ close(): Promise<void>;
24
+ }