pmxt-core 2.20.1 → 2.20.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.
Files changed (111) hide show
  1. package/dist/exchanges/baozi/fetcher.d.ts +40 -0
  2. package/dist/exchanges/baozi/fetcher.js +155 -0
  3. package/dist/exchanges/baozi/index.d.ts +2 -0
  4. package/dist/exchanges/baozi/index.js +60 -131
  5. package/dist/exchanges/baozi/normalizer.d.ts +14 -0
  6. package/dist/exchanges/baozi/normalizer.js +208 -0
  7. package/dist/exchanges/interfaces.d.ts +28 -0
  8. package/dist/exchanges/interfaces.js +2 -0
  9. package/dist/exchanges/kalshi/api.d.ts +1 -1
  10. package/dist/exchanges/kalshi/api.js +1 -1
  11. package/dist/exchanges/kalshi/fetcher.d.ts +136 -0
  12. package/dist/exchanges/kalshi/fetcher.js +313 -0
  13. package/dist/exchanges/kalshi/index.d.ts +6 -6
  14. package/dist/exchanges/kalshi/index.js +119 -202
  15. package/dist/exchanges/kalshi/normalizer.d.ts +25 -0
  16. package/dist/exchanges/kalshi/normalizer.js +313 -0
  17. package/dist/exchanges/limitless/api.d.ts +1 -1
  18. package/dist/exchanges/limitless/api.js +1 -1
  19. package/dist/exchanges/limitless/fetcher.d.ts +81 -0
  20. package/dist/exchanges/limitless/fetcher.js +238 -0
  21. package/dist/exchanges/limitless/index.d.ts +6 -9
  22. package/dist/exchanges/limitless/index.js +81 -79
  23. package/dist/exchanges/limitless/normalizer.d.ts +14 -0
  24. package/dist/exchanges/limitless/normalizer.js +117 -0
  25. package/dist/exchanges/limitless/websocket.d.ts +3 -0
  26. package/dist/exchanges/limitless/websocket.js +5 -4
  27. package/dist/exchanges/myriad/api.d.ts +1 -1
  28. package/dist/exchanges/myriad/api.js +1 -1
  29. package/dist/exchanges/myriad/fetcher.d.ts +73 -0
  30. package/dist/exchanges/myriad/fetcher.js +217 -0
  31. package/dist/exchanges/myriad/index.d.ts +2 -0
  32. package/dist/exchanges/myriad/index.js +40 -97
  33. package/dist/exchanges/myriad/normalizer.d.ts +14 -0
  34. package/dist/exchanges/myriad/normalizer.js +167 -0
  35. package/dist/exchanges/myriad/websocket.d.ts +3 -1
  36. package/dist/exchanges/myriad/websocket.js +4 -3
  37. package/dist/exchanges/polymarket/api-clob.d.ts +1 -1
  38. package/dist/exchanges/polymarket/api-clob.js +1 -1
  39. package/dist/exchanges/polymarket/api-data.d.ts +1 -1
  40. package/dist/exchanges/polymarket/api-data.js +1 -1
  41. package/dist/exchanges/polymarket/api-gamma.d.ts +1 -1
  42. package/dist/exchanges/polymarket/api-gamma.js +1 -1
  43. package/dist/exchanges/polymarket/fetcher.d.ts +99 -0
  44. package/dist/exchanges/polymarket/fetcher.js +335 -0
  45. package/dist/exchanges/polymarket/index.d.ts +2 -0
  46. package/dist/exchanges/polymarket/index.js +80 -66
  47. package/dist/exchanges/polymarket/normalizer.d.ts +18 -0
  48. package/dist/exchanges/polymarket/normalizer.js +126 -0
  49. package/dist/exchanges/probable/api.d.ts +1 -1
  50. package/dist/exchanges/probable/api.js +1 -1
  51. package/dist/exchanges/probable/fetcher.d.ts +106 -0
  52. package/dist/exchanges/probable/fetcher.js +357 -0
  53. package/dist/exchanges/probable/index.d.ts +3 -1
  54. package/dist/exchanges/probable/index.js +73 -105
  55. package/dist/exchanges/probable/normalizer.d.ts +14 -0
  56. package/dist/exchanges/probable/normalizer.js +109 -0
  57. package/package.json +3 -3
  58. package/dist/exchanges/baozi/fetchEvents.d.ts +0 -8
  59. package/dist/exchanges/baozi/fetchEvents.js +0 -39
  60. package/dist/exchanges/baozi/fetchMarkets.d.ts +0 -5
  61. package/dist/exchanges/baozi/fetchMarkets.js +0 -160
  62. package/dist/exchanges/baozi/fetchOHLCV.d.ts +0 -6
  63. package/dist/exchanges/baozi/fetchOHLCV.js +0 -10
  64. package/dist/exchanges/baozi/fetchOrderBook.d.ts +0 -12
  65. package/dist/exchanges/baozi/fetchOrderBook.js +0 -36
  66. package/dist/exchanges/baozi/fetchTrades.d.ts +0 -6
  67. package/dist/exchanges/baozi/fetchTrades.js +0 -10
  68. package/dist/exchanges/kalshi/fetchEvents.d.ts +0 -5
  69. package/dist/exchanges/kalshi/fetchEvents.js +0 -196
  70. package/dist/exchanges/kalshi/fetchMarkets.d.ts +0 -6
  71. package/dist/exchanges/kalshi/fetchMarkets.js +0 -247
  72. package/dist/exchanges/kalshi/fetchOHLCV.d.ts +0 -3
  73. package/dist/exchanges/kalshi/fetchOHLCV.js +0 -97
  74. package/dist/exchanges/kalshi/fetchOrderBook.d.ts +0 -2
  75. package/dist/exchanges/kalshi/fetchOrderBook.js +0 -60
  76. package/dist/exchanges/kalshi/fetchTrades.d.ts +0 -3
  77. package/dist/exchanges/kalshi/fetchTrades.js +0 -33
  78. package/dist/exchanges/limitless/fetchEvents.d.ts +0 -4
  79. package/dist/exchanges/limitless/fetchEvents.js +0 -173
  80. package/dist/exchanges/limitless/fetchMarkets.d.ts +0 -3
  81. package/dist/exchanges/limitless/fetchMarkets.js +0 -152
  82. package/dist/exchanges/limitless/fetchOHLCV.d.ts +0 -7
  83. package/dist/exchanges/limitless/fetchOHLCV.js +0 -49
  84. package/dist/exchanges/limitless/fetchOrderBook.d.ts +0 -6
  85. package/dist/exchanges/limitless/fetchOrderBook.js +0 -41
  86. package/dist/exchanges/limitless/fetchTrades.d.ts +0 -8
  87. package/dist/exchanges/limitless/fetchTrades.js +0 -27
  88. package/dist/exchanges/myriad/fetchEvents.d.ts +0 -4
  89. package/dist/exchanges/myriad/fetchEvents.js +0 -48
  90. package/dist/exchanges/myriad/fetchMarkets.d.ts +0 -4
  91. package/dist/exchanges/myriad/fetchMarkets.js +0 -102
  92. package/dist/exchanges/myriad/fetchOHLCV.d.ts +0 -3
  93. package/dist/exchanges/myriad/fetchOHLCV.js +0 -83
  94. package/dist/exchanges/myriad/fetchOrderBook.d.ts +0 -2
  95. package/dist/exchanges/myriad/fetchOrderBook.js +0 -39
  96. package/dist/exchanges/polymarket/fetchEvents.d.ts +0 -4
  97. package/dist/exchanges/polymarket/fetchEvents.js +0 -135
  98. package/dist/exchanges/polymarket/fetchMarkets.d.ts +0 -4
  99. package/dist/exchanges/polymarket/fetchMarkets.js +0 -214
  100. package/dist/exchanges/polymarket/fetchOHLCV.d.ts +0 -7
  101. package/dist/exchanges/polymarket/fetchOHLCV.js +0 -98
  102. package/dist/exchanges/polymarket/fetchOrderBook.d.ts +0 -6
  103. package/dist/exchanges/polymarket/fetchOrderBook.js +0 -33
  104. package/dist/exchanges/polymarket/fetchTrades.d.ts +0 -9
  105. package/dist/exchanges/polymarket/fetchTrades.js +0 -43
  106. package/dist/exchanges/probable/fetchEvents.d.ts +0 -6
  107. package/dist/exchanges/probable/fetchEvents.js +0 -151
  108. package/dist/exchanges/probable/fetchMarkets.d.ts +0 -4
  109. package/dist/exchanges/probable/fetchMarkets.js +0 -239
  110. package/dist/exchanges/probable/fetchTrades.d.ts +0 -10
  111. package/dist/exchanges/probable/fetchTrades.js +0 -40
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MyriadFetcher = void 0;
4
+ const utils_1 = require("./utils");
5
+ const errors_1 = require("./errors");
6
+ const MAX_PAGE_SIZE = 100;
7
+ class MyriadFetcher {
8
+ ctx;
9
+ constructor(ctx) {
10
+ this.ctx = ctx;
11
+ }
12
+ async fetchRawMarkets(params) {
13
+ try {
14
+ if (params?.marketId) {
15
+ return this.fetchRawMarketById(params.marketId);
16
+ }
17
+ if (params?.slug) {
18
+ return this.fetchRawMarketBySlug(params.slug);
19
+ }
20
+ const limit = params?.limit || 100;
21
+ const queryParams = {
22
+ page: params?.page || 1,
23
+ limit: Math.min(limit, MAX_PAGE_SIZE),
24
+ };
25
+ if (params?.query) {
26
+ queryParams.keyword = params.query;
27
+ }
28
+ const myriadState = (0, utils_1.mapStatusToMyriad)(params?.status);
29
+ if (myriadState) {
30
+ queryParams.state = myriadState;
31
+ }
32
+ if (params?.sort === 'volume') {
33
+ queryParams.sort = 'volume';
34
+ queryParams.order = 'desc';
35
+ }
36
+ else if (params?.sort === 'liquidity') {
37
+ queryParams.sort = 'liquidity';
38
+ queryParams.order = 'desc';
39
+ }
40
+ else if (params?.sort === 'newest') {
41
+ queryParams.sort = 'published_at';
42
+ queryParams.order = 'desc';
43
+ }
44
+ if (limit <= MAX_PAGE_SIZE) {
45
+ const response = await this.ctx.http.get(`${utils_1.BASE_URL}/markets`, {
46
+ params: queryParams,
47
+ headers: this.ctx.getHeaders(),
48
+ });
49
+ return response.data.data || response.data.markets || [];
50
+ }
51
+ // Paginate through multiple pages
52
+ const allMarkets = [];
53
+ let page = 1;
54
+ const maxPages = Math.ceil(limit / MAX_PAGE_SIZE);
55
+ while (page <= maxPages) {
56
+ queryParams.page = page;
57
+ queryParams.limit = MAX_PAGE_SIZE;
58
+ const response = await this.ctx.http.get(`${utils_1.BASE_URL}/markets`, {
59
+ params: queryParams,
60
+ headers: this.ctx.getHeaders(),
61
+ });
62
+ const data = response.data;
63
+ const markets = data.data || data.markets || [];
64
+ allMarkets.push(...markets);
65
+ const pagination = data.pagination;
66
+ if (!pagination?.hasNext || markets.length === 0)
67
+ break;
68
+ page++;
69
+ }
70
+ return allMarkets.slice(0, limit);
71
+ }
72
+ catch (error) {
73
+ throw errors_1.myriadErrorMapper.mapError(error);
74
+ }
75
+ }
76
+ async fetchRawEvents(params) {
77
+ try {
78
+ if (params.eventId) {
79
+ return this.fetchRawQuestionById(params.eventId);
80
+ }
81
+ if (params.slug) {
82
+ return this.fetchRawQuestionById(params.slug);
83
+ }
84
+ const limit = params.limit || 100;
85
+ const queryParams = {
86
+ page: 1,
87
+ limit: Math.min(limit, 100),
88
+ };
89
+ if (params.query) {
90
+ queryParams.keyword = params.query;
91
+ }
92
+ const response = await this.ctx.http.get(`${utils_1.BASE_URL}/questions`, {
93
+ params: queryParams,
94
+ headers: this.ctx.getHeaders(),
95
+ });
96
+ const questions = response.data.data || response.data.questions || [];
97
+ return questions.slice(0, limit);
98
+ }
99
+ catch (error) {
100
+ throw errors_1.myriadErrorMapper.mapError(error);
101
+ }
102
+ }
103
+ async fetchRawOHLCV(id, _params) {
104
+ try {
105
+ const parts = id.split(':');
106
+ if (parts.length < 2) {
107
+ throw new Error(`Invalid Myriad outcome ID format: "${id}". Expected "{networkId}:{marketId}:{outcomeId}".`);
108
+ }
109
+ const [networkId, marketId] = parts;
110
+ const response = await this.ctx.callApi('getMarkets', { id: marketId, network_id: Number(networkId) });
111
+ return response.data || response;
112
+ }
113
+ catch (error) {
114
+ throw errors_1.myriadErrorMapper.mapError(error);
115
+ }
116
+ }
117
+ async fetchRawOrderBook(id) {
118
+ try {
119
+ const parts = id.split(':');
120
+ if (parts.length < 3) {
121
+ throw new Error(`Invalid Myriad outcome ID format: "${id}". Expected "{networkId}:{marketId}:{outcomeId}".`);
122
+ }
123
+ const [networkId, marketId] = parts;
124
+ const response = await this.ctx.callApi('getMarkets', { id: marketId, network_id: Number(networkId) });
125
+ return response.data || response;
126
+ }
127
+ catch (error) {
128
+ throw errors_1.myriadErrorMapper.mapError(error);
129
+ }
130
+ }
131
+ async fetchRawTrades(id, params) {
132
+ const parts = id.split(':');
133
+ if (parts.length < 2) {
134
+ throw new Error(`Invalid Myriad ID format: "${id}". Expected "{networkId}:{marketId}" or "{networkId}:{marketId}:{outcomeId}".`);
135
+ }
136
+ const [networkId, marketId] = parts;
137
+ const outcomeId = parts.length >= 3 ? parts[2] : undefined;
138
+ const ensureDate = (d) => {
139
+ if (typeof d === 'string') {
140
+ if (!d.endsWith('Z') && !d.match(/[+-]\d{2}:\d{2}$/))
141
+ return new Date(d + 'Z');
142
+ return new Date(d);
143
+ }
144
+ return d;
145
+ };
146
+ const queryParams = {
147
+ id: marketId,
148
+ network_id: Number(networkId),
149
+ page: 1,
150
+ limit: params.limit || 100,
151
+ };
152
+ if (params.start)
153
+ queryParams.since = Math.floor(ensureDate(params.start).getTime() / 1000);
154
+ if (params.end)
155
+ queryParams.until = Math.floor(ensureDate(params.end).getTime() / 1000);
156
+ const data = await this.ctx.callApi('getMarketsEvents', queryParams);
157
+ const events = data.data || data.events || [];
158
+ const tradeEvents = events.filter((e) => e.action === 'buy' || e.action === 'sell');
159
+ return outcomeId
160
+ ? tradeEvents.filter((e) => String(e.outcomeId) === outcomeId)
161
+ : tradeEvents;
162
+ }
163
+ async fetchRawMyTrades(params, walletAddress) {
164
+ const queryParams = { address: walletAddress };
165
+ if (params?.marketId) {
166
+ const parts = params.marketId.split(':');
167
+ if (parts.length >= 2)
168
+ queryParams.market_id = parts[1];
169
+ }
170
+ if (params?.since)
171
+ queryParams.since = Math.floor(params.since.getTime() / 1000);
172
+ if (params?.until)
173
+ queryParams.until = Math.floor(params.until.getTime() / 1000);
174
+ if (params?.limit)
175
+ queryParams.limit = params.limit;
176
+ const data = await this.ctx.callApi('getUsersEvents', queryParams);
177
+ const events = data.data || data.events || [];
178
+ return events.filter((e) => e.action === 'buy' || e.action === 'sell');
179
+ }
180
+ async fetchRawPositions(walletAddress) {
181
+ const data = await this.ctx.callApi('getUsersPortfolio', { address: walletAddress, limit: 100 });
182
+ return data.data || data.items || [];
183
+ }
184
+ async fetchRawBalance(walletAddress) {
185
+ const data = await this.ctx.callApi('getUsersPortfolio', { address: walletAddress, limit: 100 });
186
+ return data.data || data.items || [];
187
+ }
188
+ // -- Private helpers -------------------------------------------------------
189
+ async fetchRawMarketById(marketId) {
190
+ const parts = marketId.split(':');
191
+ if (parts.length !== 2) {
192
+ return this.fetchRawMarketBySlug(marketId);
193
+ }
194
+ const [networkId, id] = parts;
195
+ const response = await this.ctx.http.get(`${utils_1.BASE_URL}/markets/${id}`, {
196
+ params: { network_id: Number(networkId) },
197
+ headers: this.ctx.getHeaders(),
198
+ });
199
+ const market = response.data.data || response.data;
200
+ return market ? [market] : [];
201
+ }
202
+ async fetchRawMarketBySlug(slug) {
203
+ const response = await this.ctx.http.get(`${utils_1.BASE_URL}/markets/${slug}`, {
204
+ headers: this.ctx.getHeaders(),
205
+ });
206
+ const market = response.data.data || response.data;
207
+ return market ? [market] : [];
208
+ }
209
+ async fetchRawQuestionById(id) {
210
+ const response = await this.ctx.http.get(`${utils_1.BASE_URL}/questions/${id}`, {
211
+ headers: this.ctx.getHeaders(),
212
+ });
213
+ const question = response.data.data || response.data;
214
+ return question ? [question] : [];
215
+ }
216
+ }
217
+ exports.MyriadFetcher = MyriadFetcher;
@@ -25,6 +25,8 @@ export declare class MyriadExchange extends PredictionMarketExchange {
25
25
  };
26
26
  private auth?;
27
27
  private ws?;
28
+ private readonly fetcher;
29
+ private readonly normalizer;
28
30
  constructor(credentials?: ExchangeCredentials);
29
31
  get name(): string;
30
32
  private getHeaders;
@@ -2,10 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MyriadExchange = void 0;
4
4
  const BaseExchange_1 = require("../../BaseExchange");
5
- const fetchMarkets_1 = require("./fetchMarkets");
6
- const fetchEvents_1 = require("./fetchEvents");
7
- const fetchOHLCV_1 = require("./fetchOHLCV");
8
- const fetchOrderBook_1 = require("./fetchOrderBook");
9
5
  const auth_1 = require("./auth");
10
6
  const websocket_1 = require("./websocket");
11
7
  const errors_1 = require("./errors");
@@ -13,7 +9,8 @@ const errors_2 = require("../../errors");
13
9
  const utils_1 = require("./utils");
14
10
  const openapi_1 = require("../../utils/openapi");
15
11
  const api_1 = require("./api");
16
- const price_1 = require("./price");
12
+ const fetcher_1 = require("./fetcher");
13
+ const normalizer_1 = require("./normalizer");
17
14
  class MyriadExchange extends BaseExchange_1.PredictionMarketExchange {
18
15
  has = {
19
16
  fetchMarkets: true,
@@ -39,6 +36,8 @@ class MyriadExchange extends BaseExchange_1.PredictionMarketExchange {
39
36
  };
40
37
  auth;
41
38
  ws;
39
+ fetcher;
40
+ normalizer;
42
41
  constructor(credentials) {
43
42
  super(credentials);
44
43
  this.rateLimit = 500;
@@ -47,6 +46,13 @@ class MyriadExchange extends BaseExchange_1.PredictionMarketExchange {
47
46
  }
48
47
  const descriptor = (0, openapi_1.parseOpenApiSpec)(api_1.myriadApiSpec, utils_1.BASE_URL);
49
48
  this.defineImplicitApi(descriptor);
49
+ const ctx = {
50
+ http: this.http,
51
+ callApi: this.callApi.bind(this),
52
+ getHeaders: () => this.getHeaders(),
53
+ };
54
+ this.fetcher = new fetcher_1.MyriadFetcher(ctx);
55
+ this.normalizer = new normalizer_1.MyriadNormalizer();
50
56
  }
51
57
  get name() {
52
58
  return 'Myriad';
@@ -70,102 +76,58 @@ class MyriadExchange extends BaseExchange_1.PredictionMarketExchange {
70
76
  return this.auth;
71
77
  }
72
78
  // ------------------------------------------------------------------------
73
- // Market Data
79
+ // Market Data (fetcher -> normalizer)
74
80
  // ------------------------------------------------------------------------
75
81
  async fetchMarketsImpl(params) {
76
- return (0, fetchMarkets_1.fetchMarkets)(params, this.getHeaders(), this.http);
82
+ const rawMarkets = await this.fetcher.fetchRawMarkets(params);
83
+ return rawMarkets
84
+ .map((raw) => this.normalizer.normalizeMarket(raw))
85
+ .filter((m) => m !== null);
77
86
  }
78
87
  async fetchEventsImpl(params) {
79
- return (0, fetchEvents_1.fetchEvents)(params, this.getHeaders(), this.http);
88
+ const rawQuestions = await this.fetcher.fetchRawEvents(params);
89
+ return rawQuestions
90
+ .map((raw) => this.normalizer.normalizeEvent(raw))
91
+ .filter((e) => e !== null);
80
92
  }
81
93
  async fetchOHLCV(id, params) {
82
- return (0, fetchOHLCV_1.fetchOHLCV)(id, params, this.callApi.bind(this));
94
+ if (!params.resolution) {
95
+ throw new Error('fetchOHLCV requires a resolution parameter.');
96
+ }
97
+ const parts = id.split(':');
98
+ const outcomeId = parts.length >= 3 ? parts[2] : undefined;
99
+ const rawMarket = await this.fetcher.fetchRawOHLCV(id, params);
100
+ return this.normalizer.normalizeOHLCV(rawMarket, params, outcomeId);
83
101
  }
84
102
  async fetchOrderBook(id) {
85
- return (0, fetchOrderBook_1.fetchOrderBook)(id, this.callApi.bind(this));
103
+ const rawMarket = await this.fetcher.fetchRawOrderBook(id);
104
+ return this.normalizer.normalizeOrderBook(rawMarket, id);
86
105
  }
87
106
  async fetchTrades(id, params) {
88
107
  if ('resolution' in params && params.resolution !== undefined) {
89
108
  console.warn('[pmxt] Warning: The "resolution" parameter is deprecated for fetchTrades() and will be ignored. ' +
90
109
  'It will be removed in v3.0.0. Please remove it from your code.');
91
110
  }
92
- const parts = id.split(':');
93
- if (parts.length < 2) {
94
- throw new Error(`Invalid Myriad ID format: "${id}". Expected "{networkId}:{marketId}" or "{networkId}:{marketId}:{outcomeId}".`);
95
- }
96
- const [networkId, marketId] = parts;
97
- const outcomeId = parts.length >= 3 ? parts[2] : undefined;
98
- const ensureDate = (d) => {
99
- if (typeof d === 'string') {
100
- if (!d.endsWith('Z') && !d.match(/[+-]\d{2}:\d{2}$/))
101
- return new Date(d + 'Z');
102
- return new Date(d);
103
- }
104
- return d;
105
- };
106
- const queryParams = {
107
- id: marketId,
108
- network_id: Number(networkId),
109
- page: 1,
110
- limit: params.limit || 100,
111
- };
112
- if (params.start)
113
- queryParams.since = Math.floor(ensureDate(params.start).getTime() / 1000);
114
- if (params.end)
115
- queryParams.until = Math.floor(ensureDate(params.end).getTime() / 1000);
116
- const data = await this.callApi('getMarketsEvents', queryParams);
117
- const events = data.data || data.events || [];
118
- const tradeEvents = events.filter((e) => e.action === 'buy' || e.action === 'sell');
119
- const filtered = outcomeId
120
- ? tradeEvents.filter((e) => String(e.outcomeId) === outcomeId)
121
- : tradeEvents;
122
- return filtered.map((t, index) => ({
123
- id: `${t.blockNumber || t.timestamp}-${index}`,
124
- timestamp: (t.timestamp || 0) * 1000,
125
- price: (0, price_1.resolveMyriadPrice)(t),
126
- amount: Number(t.shares || 0),
127
- side: t.action === 'buy' ? 'buy' : 'sell',
128
- }));
111
+ const rawTrades = await this.fetcher.fetchRawTrades(id, params);
112
+ return rawTrades.map((raw, i) => this.normalizer.normalizeTrade(raw, i));
129
113
  }
130
114
  async fetchMyTrades(params) {
131
115
  const walletAddress = this.ensureAuth().walletAddress;
132
116
  if (!walletAddress) {
133
117
  throw new errors_2.AuthenticationError('fetchMyTrades requires a wallet address. Pass privateKey as the wallet address in credentials.', 'Myriad');
134
118
  }
135
- const queryParams = { address: walletAddress };
136
- if (params?.marketId) {
137
- const parts = params.marketId.split(':');
138
- if (parts.length >= 2)
139
- queryParams.market_id = parts[1];
140
- }
141
- if (params?.since)
142
- queryParams.since = Math.floor(params.since.getTime() / 1000);
143
- if (params?.until)
144
- queryParams.until = Math.floor(params.until.getTime() / 1000);
145
- if (params?.limit)
146
- queryParams.limit = params.limit;
147
- const data = await this.callApi('getUsersEvents', queryParams);
148
- const events = data.data || data.events || [];
149
- const tradeEvents = events.filter((e) => e.action === 'buy' || e.action === 'sell');
150
- return tradeEvents.map((t, i) => ({
151
- id: `${t.blockNumber || t.timestamp}-${i}`,
152
- timestamp: (t.timestamp || 0) * 1000,
153
- price: (0, price_1.resolveMyriadPrice)(t),
154
- amount: Number(t.shares || 0),
155
- side: t.action === 'buy' ? 'buy' : 'sell',
156
- }));
119
+ const rawTrades = await this.fetcher.fetchRawMyTrades(params || {}, walletAddress);
120
+ return rawTrades.map((raw, i) => this.normalizer.normalizeUserTrade(raw, i));
157
121
  }
158
122
  // ------------------------------------------------------------------------
159
- // Trading
123
+ // Trading (fetcher -> normalizer)
160
124
  // ------------------------------------------------------------------------
161
125
  async createOrder(params) {
162
- // Parse composite marketId: {networkId}:{marketId}
163
126
  const parts = params.marketId.split(':');
164
127
  if (parts.length < 2) {
165
128
  throw new Error(`Invalid marketId format: "${params.marketId}". Expected "{networkId}:{marketId}".`);
166
129
  }
167
130
  const [networkId, marketId] = parts;
168
- // Parse outcomeId: {networkId}:{marketId}:{outcomeId}
169
131
  const outcomeParts = params.outcomeId.split(':');
170
132
  const outcomeId = outcomeParts.length >= 3 ? Number(outcomeParts[2]) : Number(outcomeParts[0]);
171
133
  const quoteBody = {
@@ -213,35 +175,16 @@ class MyriadExchange extends BaseExchange_1.PredictionMarketExchange {
213
175
  if (!walletAddress) {
214
176
  throw new errors_2.AuthenticationError('fetchPositions requires a wallet address. Pass privateKey as the wallet address in credentials.', 'Myriad');
215
177
  }
216
- const data = await this.callApi('getUsersPortfolio', { address: walletAddress, limit: 100 });
217
- const items = data.data || data.items || [];
218
- return items.map((pos) => ({
219
- marketId: `${pos.networkId}:${pos.marketId}`,
220
- outcomeId: `${pos.networkId}:${pos.marketId}:${pos.outcomeId}`,
221
- outcomeLabel: pos.outcomeTitle || `Outcome ${pos.outcomeId}`,
222
- size: Number(pos.shares || 0),
223
- entryPrice: Number(pos.price || 0),
224
- currentPrice: (0, price_1.resolveMyriadPrice)(pos),
225
- unrealizedPnL: Number(pos.profit || 0),
226
- }));
178
+ const rawItems = await this.fetcher.fetchRawPositions(walletAddress);
179
+ return rawItems.map((raw) => this.normalizer.normalizePosition(raw));
227
180
  }
228
181
  async fetchBalance() {
229
182
  const walletAddress = this.ensureAuth().walletAddress;
230
183
  if (!walletAddress) {
231
184
  throw new errors_2.AuthenticationError('fetchBalance requires a wallet address. Pass privateKey as the wallet address in credentials.', 'Myriad');
232
185
  }
233
- const data = await this.callApi('getUsersPortfolio', { address: walletAddress, limit: 100 });
234
- const items = data.data || data.items || [];
235
- let totalValue = 0;
236
- for (const pos of items) {
237
- totalValue += Number(pos.value || 0);
238
- }
239
- return [{
240
- currency: 'USDC',
241
- total: totalValue,
242
- available: 0,
243
- locked: totalValue,
244
- }];
186
+ const rawItems = await this.fetcher.fetchRawBalance(walletAddress);
187
+ return this.normalizer.normalizeBalance(rawItems);
245
188
  }
246
189
  // ------------------------------------------------------------------------
247
190
  // WebSocket (poll-based)
@@ -249,14 +192,14 @@ class MyriadExchange extends BaseExchange_1.PredictionMarketExchange {
249
192
  async watchOrderBook(id, _limit) {
250
193
  this.ensureAuth();
251
194
  if (!this.ws) {
252
- this.ws = new websocket_1.MyriadWebSocket(this.callApi.bind(this));
195
+ this.ws = new websocket_1.MyriadWebSocket(this.callApi.bind(this), (id) => this.fetchOrderBook(id));
253
196
  }
254
197
  return this.ws.watchOrderBook(id);
255
198
  }
256
199
  async watchTrades(id, address, _since, _limit) {
257
200
  this.ensureAuth();
258
201
  if (!this.ws) {
259
- this.ws = new websocket_1.MyriadWebSocket(this.callApi.bind(this));
202
+ this.ws = new websocket_1.MyriadWebSocket(this.callApi.bind(this), (id) => this.fetchOrderBook(id));
260
203
  }
261
204
  return this.ws.watchTrades(id);
262
205
  }
@@ -0,0 +1,14 @@
1
+ import { OHLCVParams } from '../../BaseExchange';
2
+ import { UnifiedMarket, UnifiedEvent, PriceCandle, OrderBook, Trade, UserTrade, Position, Balance } from '../../types';
3
+ import { IExchangeNormalizer } from '../interfaces';
4
+ import { MyriadRawMarket, MyriadRawQuestion, MyriadRawTradeEvent, MyriadRawPortfolioItem } from './fetcher';
5
+ export declare class MyriadNormalizer implements IExchangeNormalizer<MyriadRawMarket, MyriadRawQuestion> {
6
+ normalizeMarket(raw: MyriadRawMarket): UnifiedMarket | null;
7
+ normalizeEvent(raw: MyriadRawQuestion): UnifiedEvent | null;
8
+ normalizeOHLCV(raw: MyriadRawMarket, params: OHLCVParams, outcomeId?: string): PriceCandle[];
9
+ normalizeOrderBook(raw: MyriadRawMarket, id: string): OrderBook;
10
+ normalizeTrade(raw: MyriadRawTradeEvent, index: number): Trade;
11
+ normalizeUserTrade(raw: MyriadRawTradeEvent, index: number): UserTrade;
12
+ normalizePosition(raw: MyriadRawPortfolioItem): Position;
13
+ normalizeBalance(rawItems: MyriadRawPortfolioItem[]): Balance[];
14
+ }
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MyriadNormalizer = void 0;
4
+ const market_utils_1 = require("../../utils/market-utils");
5
+ const price_1 = require("./price");
6
+ function selectTimeframe(interval) {
7
+ switch (interval) {
8
+ case '1m':
9
+ case '5m':
10
+ return '24h';
11
+ case '15m':
12
+ case '1h':
13
+ return '7d';
14
+ case '6h':
15
+ case '1d':
16
+ return '30d';
17
+ default:
18
+ return '7d';
19
+ }
20
+ }
21
+ class MyriadNormalizer {
22
+ normalizeMarket(raw) {
23
+ if (!raw)
24
+ return null;
25
+ const outcomes = (raw.outcomes || []).map((o) => ({
26
+ outcomeId: `${raw.networkId}:${raw.id}:${o.id}`,
27
+ marketId: `${raw.networkId}:${raw.id}`,
28
+ label: o.title || `Outcome ${o.id}`,
29
+ price: Number(o.price) || 0,
30
+ priceChange24h: o.priceChange24h != null ? Number(o.priceChange24h) : undefined,
31
+ }));
32
+ const um = {
33
+ marketId: `${raw.networkId}:${raw.id}`,
34
+ eventId: raw.questionId ? String(raw.questionId) : undefined,
35
+ title: raw.title || '',
36
+ description: raw.description || '',
37
+ outcomes,
38
+ resolutionDate: raw.expiresAt ? new Date(raw.expiresAt) : new Date(0),
39
+ volume24h: Number(raw.volume24h || 0),
40
+ volume: Number(raw.volume || 0),
41
+ liquidity: Number(raw.liquidity || 0),
42
+ url: `https://myriad.markets/markets/${raw.slug || raw.id}`,
43
+ image: raw.imageUrl,
44
+ tags: raw.topics || [],
45
+ };
46
+ (0, market_utils_1.addBinaryOutcomes)(um);
47
+ return um;
48
+ }
49
+ normalizeEvent(raw) {
50
+ if (!raw)
51
+ return null;
52
+ const markets = [];
53
+ for (const m of raw.markets || []) {
54
+ const um = this.normalizeMarket(m);
55
+ if (um)
56
+ markets.push(um);
57
+ }
58
+ return {
59
+ id: String(raw.id),
60
+ title: raw.title || '',
61
+ description: '',
62
+ slug: String(raw.id),
63
+ markets,
64
+ volume24h: markets.reduce((sum, m) => sum + m.volume24h, 0),
65
+ volume: markets.some(m => m.volume !== undefined)
66
+ ? markets.reduce((sum, m) => sum + (m.volume ?? 0), 0)
67
+ : undefined,
68
+ url: `https://myriad.markets`,
69
+ };
70
+ }
71
+ normalizeOHLCV(raw, params, outcomeId) {
72
+ const outcomes = raw.outcomes || [];
73
+ let targetOutcome = outcomes[0];
74
+ if (outcomeId !== undefined) {
75
+ const found = outcomes.find((o) => String(o.id) === outcomeId);
76
+ if (found)
77
+ targetOutcome = found;
78
+ }
79
+ if (!targetOutcome || !targetOutcome.price_charts) {
80
+ return [];
81
+ }
82
+ const desiredTimeframe = selectTimeframe(params.resolution);
83
+ const charts = targetOutcome.price_charts;
84
+ let prices = null;
85
+ for (const key of Object.keys(charts)) {
86
+ const chart = charts[key];
87
+ if (chart && chart.timeframe === desiredTimeframe && Array.isArray(chart.prices)) {
88
+ prices = chart.prices;
89
+ break;
90
+ }
91
+ }
92
+ if (!prices || prices.length === 0) {
93
+ return [];
94
+ }
95
+ const candles = prices.map((point) => ({
96
+ timestamp: point.timestamp ? point.timestamp * 1000 : Date.now(),
97
+ open: Number(point.value || 0),
98
+ high: Number(point.value || 0),
99
+ low: Number(point.value || 0),
100
+ close: Number(point.value || 0),
101
+ volume: undefined,
102
+ }));
103
+ if (params.limit && candles.length > params.limit) {
104
+ return candles.slice(-params.limit);
105
+ }
106
+ return candles;
107
+ }
108
+ normalizeOrderBook(raw, id) {
109
+ const parts = id.split(':');
110
+ const outcomeId = parts.length >= 3 ? parts[2] : undefined;
111
+ const outcomes = raw.outcomes || [];
112
+ const outcome = outcomes.find((o) => String(o.id) === outcomeId) || outcomes[0];
113
+ if (!outcome) {
114
+ return { bids: [], asks: [], timestamp: Date.now() };
115
+ }
116
+ const price = Number(outcome.price) || 0.5;
117
+ const liquidity = Number(raw.liquidity || 0);
118
+ const size = liquidity > 0 ? liquidity : 1;
119
+ return {
120
+ bids: [{ price, size }],
121
+ asks: [{ price, size }],
122
+ timestamp: Date.now(),
123
+ };
124
+ }
125
+ normalizeTrade(raw, index) {
126
+ return {
127
+ id: `${raw.blockNumber || raw.timestamp}-${index}`,
128
+ timestamp: (raw.timestamp || 0) * 1000,
129
+ price: (0, price_1.resolveMyriadPrice)(raw),
130
+ amount: Number(raw.shares || 0),
131
+ side: raw.action === 'buy' ? 'buy' : 'sell',
132
+ };
133
+ }
134
+ normalizeUserTrade(raw, index) {
135
+ return {
136
+ id: `${raw.blockNumber || raw.timestamp}-${index}`,
137
+ timestamp: (raw.timestamp || 0) * 1000,
138
+ price: (0, price_1.resolveMyriadPrice)(raw),
139
+ amount: Number(raw.shares || 0),
140
+ side: raw.action === 'buy' ? 'buy' : 'sell',
141
+ };
142
+ }
143
+ normalizePosition(raw) {
144
+ return {
145
+ marketId: `${raw.networkId}:${raw.marketId}`,
146
+ outcomeId: `${raw.networkId}:${raw.marketId}:${raw.outcomeId}`,
147
+ outcomeLabel: raw.outcomeTitle || `Outcome ${raw.outcomeId}`,
148
+ size: Number(raw.shares || 0),
149
+ entryPrice: Number(raw.price || 0),
150
+ currentPrice: (0, price_1.resolveMyriadPrice)(raw),
151
+ unrealizedPnL: Number(raw.profit || 0),
152
+ };
153
+ }
154
+ normalizeBalance(rawItems) {
155
+ let totalValue = 0;
156
+ for (const pos of rawItems) {
157
+ totalValue += Number(pos.value || 0);
158
+ }
159
+ return [{
160
+ currency: 'USDC',
161
+ total: totalValue,
162
+ available: 0,
163
+ locked: totalValue,
164
+ }];
165
+ }
166
+ }
167
+ exports.MyriadNormalizer = MyriadNormalizer;
@@ -1,6 +1,8 @@
1
1
  import { OrderBook, Trade } from '../../types';
2
+ export type FetchOrderBookFn = (id: string) => Promise<OrderBook>;
2
3
  export declare class MyriadWebSocket {
3
4
  private callApi;
5
+ private fetchOrderBook;
4
6
  private pollInterval;
5
7
  private orderBookTimers;
6
8
  private tradeTimers;
@@ -8,7 +10,7 @@ export declare class MyriadWebSocket {
8
10
  private tradeResolvers;
9
11
  private lastTradeTimestamp;
10
12
  private closed;
11
- constructor(callApi: (operationId: string, params?: Record<string, any>) => Promise<any>, pollInterval?: number);
13
+ constructor(callApi: (operationId: string, params?: Record<string, any>) => Promise<any>, fetchOrderBook: FetchOrderBookFn, pollInterval?: number);
12
14
  watchOrderBook(id: string): Promise<OrderBook>;
13
15
  watchTrades(id: string): Promise<Trade[]>;
14
16
  close(): Promise<void>;