pmxtjs 0.1.0 → 0.1.1

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 (58) hide show
  1. package/dist/BaseExchange.js +30 -0
  2. package/{src/exchanges/Kalshi.ts → dist/exchanges/Kalshi.js} +75 -106
  3. package/{src/exchanges/Polymarket.ts → dist/exchanges/Polymarket.js} +107 -144
  4. package/dist/index.js +20 -0
  5. package/dist/types.js +5 -0
  6. package/package.json +4 -1
  7. package/API_REFERENCE.md +0 -88
  8. package/coverage/clover.xml +0 -334
  9. package/coverage/coverage-final.json +0 -4
  10. package/coverage/lcov-report/base.css +0 -224
  11. package/coverage/lcov-report/block-navigation.js +0 -87
  12. package/coverage/lcov-report/favicon.png +0 -0
  13. package/coverage/lcov-report/index.html +0 -131
  14. package/coverage/lcov-report/pmxt/BaseExchange.ts.html +0 -256
  15. package/coverage/lcov-report/pmxt/exchanges/Kalshi.ts.html +0 -1132
  16. package/coverage/lcov-report/pmxt/exchanges/Polymarket.ts.html +0 -1456
  17. package/coverage/lcov-report/pmxt/exchanges/index.html +0 -131
  18. package/coverage/lcov-report/pmxt/index.html +0 -116
  19. package/coverage/lcov-report/prettify.css +0 -1
  20. package/coverage/lcov-report/prettify.js +0 -2
  21. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  22. package/coverage/lcov-report/sorter.js +0 -210
  23. package/coverage/lcov-report/src/BaseExchange.ts.html +0 -256
  24. package/coverage/lcov-report/src/exchanges/Kalshi.ts.html +0 -1132
  25. package/coverage/lcov-report/src/exchanges/Polymarket.ts.html +0 -1456
  26. package/coverage/lcov-report/src/exchanges/index.html +0 -131
  27. package/coverage/lcov-report/src/index.html +0 -116
  28. package/coverage/lcov.info +0 -766
  29. package/examples/get_event_prices.ts +0 -37
  30. package/examples/historical_prices.ts +0 -117
  31. package/examples/orderbook.ts +0 -102
  32. package/examples/recent_trades.ts +0 -29
  33. package/examples/search_events.ts +0 -68
  34. package/examples/search_market.ts +0 -29
  35. package/jest.config.js +0 -11
  36. package/pmxt-0.1.0.tgz +0 -0
  37. package/src/BaseExchange.ts +0 -57
  38. package/src/index.ts +0 -5
  39. package/src/types.ts +0 -61
  40. package/test/exchanges/kalshi/ApiErrors.test.ts +0 -132
  41. package/test/exchanges/kalshi/EmptyResponse.test.ts +0 -44
  42. package/test/exchanges/kalshi/FetchAndNormalizeMarkets.test.ts +0 -56
  43. package/test/exchanges/kalshi/LiveApi.integration.test.ts +0 -40
  44. package/test/exchanges/kalshi/MarketHistory.test.ts +0 -185
  45. package/test/exchanges/kalshi/OrderBook.test.ts +0 -149
  46. package/test/exchanges/kalshi/SearchMarkets.test.ts +0 -174
  47. package/test/exchanges/kalshi/VolumeFallback.test.ts +0 -44
  48. package/test/exchanges/polymarket/DataValidation.test.ts +0 -271
  49. package/test/exchanges/polymarket/ErrorHandling.test.ts +0 -34
  50. package/test/exchanges/polymarket/FetchAndNormalizeMarkets.test.ts +0 -68
  51. package/test/exchanges/polymarket/GetMarketsBySlug.test.ts +0 -268
  52. package/test/exchanges/polymarket/LiveApi.integration.test.ts +0 -44
  53. package/test/exchanges/polymarket/MarketHistory.test.ts +0 -207
  54. package/test/exchanges/polymarket/OrderBook.test.ts +0 -167
  55. package/test/exchanges/polymarket/RequestParameters.test.ts +0 -39
  56. package/test/exchanges/polymarket/SearchMarkets.test.ts +0 -176
  57. package/test/exchanges/polymarket/TradeHistory.test.ts +0 -248
  58. package/tsconfig.json +0 -12
@@ -1,207 +0,0 @@
1
- import axios from 'axios';
2
- import { PolymarketExchange } from '../../../src/exchanges/Polymarket';
3
-
4
- /**
5
- * Polymarket getMarketHistory() Test
6
- *
7
- * What: Tests fetching historical price data from CLOB API.
8
- * Why: Historical data is essential for charting and analysis.
9
- * How: Mocks Polymarket prices-history API responses and verifies data transformation.
10
- */
11
-
12
- jest.mock('axios');
13
- const mockedAxios = axios as jest.Mocked<typeof axios>;
14
-
15
- describe('PolymarketExchange - getMarketHistory', () => {
16
- let exchange: PolymarketExchange;
17
-
18
- beforeEach(() => {
19
- exchange = new PolymarketExchange();
20
- jest.clearAllMocks();
21
- });
22
-
23
- it('should fetch and parse price history', async () => {
24
- mockedAxios.get.mockResolvedValue({
25
- data: {
26
- history: [
27
- { t: 1704067200, p: 0.52 },
28
- { t: 1704070800, p: 0.53 },
29
- { t: 1704074400, p: 0.54 }
30
- ]
31
- }
32
- });
33
-
34
- const history = await exchange.getMarketHistory('token123456789', { resolution: '1h' });
35
-
36
- expect(history.length).toBe(3);
37
- expect(history[0].close).toBe(0.52);
38
- expect(history[1].close).toBe(0.53);
39
- expect(history[2].close).toBe(0.54);
40
- });
41
-
42
- it('should convert timestamps to milliseconds', async () => {
43
- mockedAxios.get.mockResolvedValue({
44
- data: {
45
- history: [{ t: 1704067200, p: 0.50 }]
46
- }
47
- });
48
-
49
- const history = await exchange.getMarketHistory('token123456789', { resolution: '1h' });
50
-
51
- expect(history[0].timestamp).toBeGreaterThan(1704067200);
52
- expect(history[0].timestamp).toBeLessThanOrEqual(1704067200 * 1000 + 3600000);
53
- });
54
-
55
- it('should align timestamps to interval grid', async () => {
56
- mockedAxios.get.mockResolvedValue({
57
- data: {
58
- history: [
59
- { t: 1704067221, p: 0.50 } // 00:00:21
60
- ]
61
- }
62
- });
63
-
64
- const history = await exchange.getMarketHistory('token123456789', { resolution: '1h' });
65
-
66
- // Should snap to 00:00:00
67
- const expectedSnap = Math.floor(1704067221 / 3600) * 3600 * 1000;
68
- expect(history[0].timestamp).toBe(expectedSnap);
69
- });
70
-
71
- it('should respect limit parameter', async () => {
72
- const mockHistory = Array.from({ length: 100 }, (_, i) => ({
73
- t: 1704067200 + (i * 3600),
74
- p: 0.50 + (i * 0.001)
75
- }));
76
-
77
- mockedAxios.get.mockResolvedValue({
78
- data: { history: mockHistory }
79
- });
80
-
81
- const history = await exchange.getMarketHistory('token123456789', {
82
- resolution: '1h',
83
- limit: 20
84
- });
85
-
86
- expect(history.length).toBe(20);
87
- });
88
-
89
- it('should map intervals to fidelity correctly', async () => {
90
- mockedAxios.get.mockResolvedValue({
91
- data: { history: [] }
92
- });
93
-
94
- await exchange.getMarketHistory('token123456789', { resolution: '1m' });
95
- expect(mockedAxios.get).toHaveBeenCalledWith(
96
- expect.any(String),
97
- expect.objectContaining({
98
- params: expect.objectContaining({ fidelity: 1 })
99
- })
100
- );
101
-
102
- jest.clearAllMocks();
103
- mockedAxios.get.mockResolvedValue({ data: { history: [] } });
104
-
105
- await exchange.getMarketHistory('token123456789', { resolution: '1d' });
106
- expect(mockedAxios.get).toHaveBeenCalledWith(
107
- expect.any(String),
108
- expect.objectContaining({
109
- params: expect.objectContaining({ fidelity: 1440 })
110
- })
111
- );
112
- });
113
-
114
- it('should handle start and end timestamps', async () => {
115
- mockedAxios.get.mockResolvedValue({
116
- data: { history: [] }
117
- });
118
-
119
- const start = new Date('2025-01-01T00:00:00Z');
120
- const end = new Date('2025-01-02T00:00:00Z');
121
-
122
- await exchange.getMarketHistory('token123456789', {
123
- resolution: '1h',
124
- start,
125
- end
126
- });
127
-
128
- expect(mockedAxios.get).toHaveBeenCalledWith(
129
- expect.any(String),
130
- expect.objectContaining({
131
- params: expect.objectContaining({
132
- startTs: Math.floor(start.getTime() / 1000),
133
- endTs: Math.floor(end.getTime() / 1000)
134
- })
135
- })
136
- );
137
- });
138
-
139
- it('should calculate smart lookback when start not provided', async () => {
140
- mockedAxios.get.mockResolvedValue({
141
- data: { history: [] }
142
- });
143
-
144
- await exchange.getMarketHistory('token123456789', {
145
- resolution: '1h',
146
- limit: 24
147
- });
148
-
149
- const call = mockedAxios.get.mock.calls[0][1];
150
- const params = call?.params;
151
-
152
- expect(params.startTs).toBeDefined();
153
- expect(params.endTs).toBeDefined();
154
- // Should be approximately 24 hours worth of data
155
- const duration = params.endTs - params.startTs;
156
- expect(duration).toBeGreaterThan(24 * 60 * 60 * 0.9); // Allow 10% margin
157
- expect(duration).toBeLessThan(24 * 60 * 60 * 1.1);
158
- });
159
-
160
- it('should handle empty history array', async () => {
161
- mockedAxios.get.mockResolvedValue({
162
- data: { history: [] }
163
- });
164
-
165
- const history = await exchange.getMarketHistory('token123456789', { resolution: '1h' });
166
-
167
- expect(history).toEqual([]);
168
- });
169
-
170
- it('should set OHLC to same value (synthetic candles)', async () => {
171
- mockedAxios.get.mockResolvedValue({
172
- data: {
173
- history: [{ t: 1704067200, p: 0.52 }]
174
- }
175
- });
176
-
177
- const history = await exchange.getMarketHistory('token123456789', { resolution: '1h' });
178
-
179
- expect(history[0].open).toBe(0.52);
180
- expect(history[0].high).toBe(0.52);
181
- expect(history[0].low).toBe(0.52);
182
- expect(history[0].close).toBe(0.52);
183
- });
184
-
185
- it('should throw error for invalid token ID format', async () => {
186
- await expect(exchange.getMarketHistory('123', { resolution: '1h' }))
187
- .rejects
188
- .toThrow(/Invalid ID/i);
189
- });
190
-
191
- it('should handle API errors with detailed messages', async () => {
192
- const error = {
193
- response: {
194
- status: 400,
195
- data: { error: 'Invalid token ID' }
196
- },
197
- isAxiosError: true
198
- };
199
- mockedAxios.get.mockRejectedValue(error);
200
- // @ts-expect-error - Mock type mismatch is expected in tests
201
- mockedAxios.isAxiosError = jest.fn().mockReturnValue(true);
202
-
203
- await expect(exchange.getMarketHistory('token123456789', { resolution: '1h' }))
204
- .rejects
205
- .toThrow(/History API Error/i);
206
- });
207
- });
@@ -1,167 +0,0 @@
1
- import axios from 'axios';
2
- import { PolymarketExchange } from '../../../src/exchanges/Polymarket';
3
-
4
- /**
5
- * Polymarket getOrderBook() Test
6
- *
7
- * What: Tests fetching and parsing of CLOB order book data.
8
- * Why: Order book data is critical for trading and price discovery.
9
- * How: Mocks Polymarket CLOB API responses and verifies correct parsing and sorting.
10
- */
11
-
12
- jest.mock('axios');
13
- const mockedAxios = axios as jest.Mocked<typeof axios>;
14
-
15
- describe('PolymarketExchange - getOrderBook', () => {
16
- let exchange: PolymarketExchange;
17
-
18
- beforeEach(() => {
19
- exchange = new PolymarketExchange();
20
- jest.clearAllMocks();
21
- });
22
-
23
- it('should parse orderbook data correctly', async () => {
24
- mockedAxios.get.mockResolvedValue({
25
- data: {
26
- bids: [
27
- { price: '0.52', size: '100' },
28
- { price: '0.51', size: '250' },
29
- { price: '0.50', size: '500' }
30
- ],
31
- asks: [
32
- { price: '0.53', size: '150' },
33
- { price: '0.54', size: '200' },
34
- { price: '0.55', size: '300' }
35
- ],
36
- timestamp: '2025-01-08T12:00:00Z'
37
- }
38
- });
39
-
40
- const orderbook = await exchange.getOrderBook('token123456789');
41
-
42
- expect(orderbook.bids).toBeDefined();
43
- expect(orderbook.asks).toBeDefined();
44
- expect(orderbook.bids.length).toBe(3);
45
- expect(orderbook.asks.length).toBe(3);
46
- });
47
-
48
- it('should convert string prices to numbers', async () => {
49
- mockedAxios.get.mockResolvedValue({
50
- data: {
51
- bids: [{ price: '0.52', size: '100' }],
52
- asks: [{ price: '0.53', size: '150' }]
53
- }
54
- });
55
-
56
- const orderbook = await exchange.getOrderBook('token123456789');
57
-
58
- expect(typeof orderbook.bids[0].price).toBe('number');
59
- expect(typeof orderbook.bids[0].size).toBe('number');
60
- expect(orderbook.bids[0].price).toBe(0.52);
61
- expect(orderbook.bids[0].size).toBe(100);
62
- });
63
-
64
- it('should sort bids in descending order', async () => {
65
- mockedAxios.get.mockResolvedValue({
66
- data: {
67
- bids: [
68
- { price: '0.50', size: '100' },
69
- { price: '0.52', size: '200' },
70
- { price: '0.51', size: '150' }
71
- ],
72
- asks: []
73
- }
74
- });
75
-
76
- const orderbook = await exchange.getOrderBook('token123456789');
77
-
78
- expect(orderbook.bids[0].price).toBeGreaterThanOrEqual(orderbook.bids[1].price);
79
- expect(orderbook.bids[1].price).toBeGreaterThanOrEqual(orderbook.bids[2].price);
80
- });
81
-
82
- it('should sort asks in ascending order', async () => {
83
- mockedAxios.get.mockResolvedValue({
84
- data: {
85
- bids: [],
86
- asks: [
87
- { price: '0.55', size: '100' },
88
- { price: '0.53', size: '200' },
89
- { price: '0.54', size: '150' }
90
- ]
91
- }
92
- });
93
-
94
- const orderbook = await exchange.getOrderBook('token123456789');
95
-
96
- expect(orderbook.asks[0].price).toBeLessThanOrEqual(orderbook.asks[1].price);
97
- expect(orderbook.asks[1].price).toBeLessThanOrEqual(orderbook.asks[2].price);
98
- });
99
-
100
- it('should handle empty orderbook', async () => {
101
- mockedAxios.get.mockResolvedValue({
102
- data: {
103
- bids: [],
104
- asks: []
105
- }
106
- });
107
-
108
- const orderbook = await exchange.getOrderBook('token123456789');
109
-
110
- expect(orderbook.bids).toEqual([]);
111
- expect(orderbook.asks).toEqual([]);
112
- });
113
-
114
- it('should include timestamp', async () => {
115
- const mockTimestamp = '2025-01-08T12:00:00Z';
116
- mockedAxios.get.mockResolvedValue({
117
- data: {
118
- bids: [{ price: '0.52', size: '100' }],
119
- asks: [{ price: '0.53', size: '150' }],
120
- timestamp: mockTimestamp
121
- }
122
- });
123
-
124
- const orderbook = await exchange.getOrderBook('token123456789');
125
-
126
- expect(orderbook.timestamp).toBeDefined();
127
- expect(typeof orderbook.timestamp).toBe('number');
128
- });
129
-
130
- it('should handle missing timestamp with current time', async () => {
131
- mockedAxios.get.mockResolvedValue({
132
- data: {
133
- bids: [{ price: '0.52', size: '100' }],
134
- asks: [{ price: '0.53', size: '150' }]
135
- }
136
- });
137
-
138
- const before = Date.now();
139
- const orderbook = await exchange.getOrderBook('token123456789');
140
- const after = Date.now();
141
-
142
- expect(orderbook.timestamp).toBeGreaterThanOrEqual(before);
143
- expect(orderbook.timestamp).toBeLessThanOrEqual(after);
144
- });
145
-
146
- it('should handle missing bids/asks fields', async () => {
147
- mockedAxios.get.mockResolvedValue({
148
- data: {}
149
- });
150
-
151
- const orderbook = await exchange.getOrderBook('token123456789');
152
-
153
- expect(orderbook.bids).toEqual([]);
154
- expect(orderbook.asks).toEqual([]);
155
- });
156
-
157
- it('should return empty orderbook on error', async () => {
158
- mockedAxios.get.mockRejectedValue(new Error('API Error'));
159
- const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => { });
160
-
161
- const orderbook = await exchange.getOrderBook('token123456789');
162
-
163
- expect(orderbook).toEqual({ bids: [], asks: [] });
164
- expect(consoleSpy).toHaveBeenCalled();
165
- consoleSpy.mockRestore();
166
- });
167
- });
@@ -1,39 +0,0 @@
1
- import axios from 'axios';
2
- import { PolymarketExchange } from '../../../src/exchanges/Polymarket';
3
-
4
- /**
5
- * Polymarket Request Parameters Test
6
- *
7
- * What: Tests if internal filter parameters are correctly mapped to Polymarket API query params.
8
- * Why: Different exchanges use different parameter names (e.g., 'sort' vs 'order', 'limit' vs 'qty').
9
- * We must ensure our unified interface maps correctly to each exchange's native API.
10
- * How: Mocks axios and inspects the 'params' object passed to the get call.
11
- */
12
-
13
- jest.mock('axios');
14
- const mockedAxios = axios as jest.Mocked<typeof axios>;
15
-
16
- describe('PolymarketExchange - Request Parameters Mapping', () => {
17
- let exchange: PolymarketExchange;
18
-
19
- beforeEach(() => {
20
- exchange = new PolymarketExchange();
21
- jest.clearAllMocks();
22
- });
23
-
24
- it('should map limit and sort parameters correctly', async () => {
25
- mockedAxios.get.mockResolvedValue({ data: [] });
26
-
27
- await exchange.fetchMarkets({ limit: 50, sort: 'volume' });
28
-
29
- expect(mockedAxios.get).toHaveBeenCalledWith(
30
- expect.stringContaining('events'),
31
- expect.objectContaining({
32
- params: expect.objectContaining({
33
- limit: 50,
34
- order: 'volume'
35
- })
36
- })
37
- );
38
- });
39
- });
@@ -1,176 +0,0 @@
1
- import axios from 'axios';
2
- import { PolymarketExchange } from '../../../src/exchanges/Polymarket';
3
-
4
- /**
5
- * Polymarket searchMarkets() Test
6
- *
7
- * What: Tests the search functionality for finding markets by query string.
8
- * Why: Search is a critical user-facing feature that must work reliably.
9
- * How: Mocks API responses with various market data and verifies client-side filtering.
10
- */
11
-
12
- jest.mock('axios');
13
- const mockedAxios = axios as jest.Mocked<typeof axios>;
14
-
15
- describe('PolymarketExchange - searchMarkets', () => {
16
- let exchange: PolymarketExchange;
17
-
18
- beforeEach(() => {
19
- exchange = new PolymarketExchange();
20
- jest.clearAllMocks();
21
- });
22
-
23
- it('should filter markets by title', async () => {
24
- mockedAxios.get.mockResolvedValue({
25
- data: [
26
- {
27
- id: 'event-1',
28
- slug: 'fed-rate-decision',
29
- title: 'Federal Reserve Rate Decision',
30
- description: 'Federal Reserve interest rate decision',
31
- markets: [{
32
- id: 'market-1',
33
- question: 'Will rates be cut?',
34
- description: 'Federal Reserve rate cut prediction',
35
- outcomes: '["Yes", "No"]',
36
- outcomePrices: '["0.52", "0.48"]',
37
- clobTokenIds: '["token1", "token2"]',
38
- endDate: '2025-12-31T00:00:00Z',
39
- volume24hr: '100000'
40
- }]
41
- },
42
- {
43
- id: 'event-2',
44
- slug: 'election-2024',
45
- title: 'Presidential Election 2024',
46
- description: 'US Presidential Election',
47
- markets: [{
48
- id: 'market-2',
49
- question: 'Winner?',
50
- description: 'Election winner prediction',
51
- outcomes: '["Trump", "Biden"]',
52
- outcomePrices: '["0.48", "0.52"]',
53
- clobTokenIds: '["token3", "token4"]',
54
- endDate: '2024-11-05T00:00:00Z',
55
- volume24hr: '500000'
56
- }]
57
- }
58
- ]
59
- });
60
-
61
- const results = await exchange.searchMarkets('federal');
62
-
63
- expect(results.length).toBeGreaterThan(0);
64
- expect(results[0].title.toLowerCase()).toContain('federal');
65
- });
66
-
67
- it('should filter markets by description', async () => {
68
- mockedAxios.get.mockResolvedValue({
69
- data: [{
70
- id: 'event-1',
71
- slug: 'climate-policy',
72
- title: 'Climate Policy',
73
- description: 'Will Congress pass climate legislation?',
74
- markets: [{
75
- id: 'market-1',
76
- question: 'Pass by 2025?',
77
- description: 'Detailed climate change policy information',
78
- outcomes: '["Yes", "No"]',
79
- outcomePrices: '["0.30", "0.70"]',
80
- clobTokenIds: '["token1", "token2"]',
81
- endDate: '2025-12-31T00:00:00Z',
82
- volume24hr: '50000'
83
- }]
84
- }]
85
- });
86
-
87
- const results = await exchange.searchMarkets('climate');
88
-
89
- expect(results.length).toBeGreaterThan(0);
90
- });
91
-
92
- it('should respect limit parameter', async () => {
93
- const mockEvents = Array.from({ length: 30 }, (_, i) => ({
94
- id: `event-${i}`,
95
- slug: `test-event-${i}`,
96
- title: `Test Market ${i}`,
97
- markets: [{
98
- id: `market-${i}`,
99
- question: 'Test question',
100
- outcomes: '["Yes", "No"]',
101
- outcomePrices: '["0.50", "0.50"]',
102
- clobTokenIds: '["token1", "token2"]',
103
- endDate: '2025-12-31T00:00:00Z',
104
- volume24hr: '10000'
105
- }]
106
- }));
107
-
108
- mockedAxios.get.mockResolvedValue({ data: mockEvents });
109
-
110
- const results = await exchange.searchMarkets('test', { limit: 5 });
111
-
112
- expect(results.length).toBeLessThanOrEqual(5);
113
- });
114
-
115
- it('should return empty array when no matches found', async () => {
116
- mockedAxios.get.mockResolvedValue({
117
- data: [{
118
- id: 'event-1',
119
- slug: 'unrelated',
120
- title: 'Completely Different Topic',
121
- markets: [{
122
- id: 'market-1',
123
- question: 'Something else',
124
- outcomes: '["Yes", "No"]',
125
- outcomePrices: '["0.50", "0.50"]',
126
- clobTokenIds: '["token1", "token2"]',
127
- endDate: '2025-12-31T00:00:00Z',
128
- volume24hr: '10000'
129
- }]
130
- }]
131
- });
132
-
133
- const results = await exchange.searchMarkets('nonexistent query string');
134
-
135
- expect(results).toEqual([]);
136
- });
137
-
138
- it('should handle search errors gracefully', async () => {
139
- mockedAxios.get.mockRejectedValue(new Error('Search failed'));
140
- const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => { });
141
-
142
- const results = await exchange.searchMarkets('test');
143
-
144
- expect(results).toEqual([]);
145
- expect(consoleSpy).toHaveBeenCalled();
146
- consoleSpy.mockRestore();
147
- });
148
-
149
- it('should be case-insensitive', async () => {
150
- const mockData = {
151
- data: [{
152
- id: 'event-1',
153
- slug: 'test',
154
- title: 'FEDERAL RESERVE',
155
- markets: [{
156
- id: 'market-1',
157
- question: 'Test',
158
- outcomes: '["Yes", "No"]',
159
- outcomePrices: '["0.50", "0.50"]',
160
- clobTokenIds: '["token1", "token2"]',
161
- endDate: '2025-12-31T00:00:00Z',
162
- volume24hr: '10000'
163
- }]
164
- }]
165
- };
166
-
167
- mockedAxios.get.mockResolvedValue(mockData);
168
- const resultsLower = await exchange.searchMarkets('federal');
169
-
170
- jest.clearAllMocks();
171
- mockedAxios.get.mockResolvedValue(mockData);
172
- const resultsUpper = await exchange.searchMarkets('FEDERAL');
173
-
174
- expect(resultsLower.length).toBe(resultsUpper.length);
175
- });
176
- });