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,44 +0,0 @@
1
- import axios from 'axios';
2
- import { KalshiExchange } from '../../../src/exchanges/Kalshi';
3
-
4
- /**
5
- * Kalshi Empty Response Handling Test
6
- *
7
- * What: Tests how the exchange handles empty responses from the API.
8
- * Why: APIs can return empty lists during maintenance or based on filters.
9
- * The library must handle this gracefully without throwing errors.
10
- * How: Mocks an empty events array and verifies an empty market array is returned.
11
- */
12
-
13
- jest.mock('axios');
14
- const mockedAxios = axios as jest.Mocked<typeof axios>;
15
-
16
- describe('KalshiExchange - Empty Response Handling', () => {
17
- let exchange: KalshiExchange;
18
-
19
- beforeEach(() => {
20
- exchange = new KalshiExchange();
21
- jest.clearAllMocks();
22
- });
23
-
24
- it('should handle empty events array gracefully', async () => {
25
- mockedAxios.get.mockResolvedValue({
26
- data: {
27
- events: [],
28
- cursor: ''
29
- }
30
- });
31
-
32
- const markets = await exchange.fetchMarkets();
33
- expect(markets).toEqual([]);
34
- });
35
-
36
- it('should handle missing events field gracefully', async () => {
37
- mockedAxios.get.mockResolvedValue({
38
- data: {}
39
- });
40
-
41
- const markets = await exchange.fetchMarkets();
42
- expect(markets).toEqual([]);
43
- });
44
- });
@@ -1,56 +0,0 @@
1
- import axios from 'axios';
2
- import { KalshiExchange } from '../../../src/exchanges/Kalshi';
3
-
4
- /**
5
- * Kalshi Markets Normalization Test
6
- *
7
- * What: Tests if Kalshi markets are correctly normalized from the event-based structure.
8
- * Why: Kalshi uses a hierarchical Event > Market structure. We need to ensured nested markets
9
- * are correctly flattened and combined with their parent event metadata (title, category).
10
- * How: Mocks the Kalshi /events API response with nested markets and verifies the UnifiedMarket output.
11
- */
12
-
13
- jest.mock('axios');
14
- const mockedAxios = axios as jest.Mocked<typeof axios>;
15
-
16
- describe('KalshiExchange - Fetch and Normalize Markets', () => {
17
- let exchange: KalshiExchange;
18
-
19
- beforeEach(() => {
20
- exchange = new KalshiExchange();
21
- jest.clearAllMocks();
22
- });
23
-
24
- it('should correctly flatten nested markets from events', async () => {
25
- mockedAxios.get.mockResolvedValue({
26
- data: {
27
- events: [{
28
- event_ticker: 'KXINFLATION',
29
- title: 'Inflation > 3%',
30
- sub_title: 'CPI exceeds 3%',
31
- category: 'Economics',
32
- markets: [{
33
- ticker: 'KXINFLATION24',
34
- yes_ask: 45,
35
- yes_bid: 43,
36
- volume_24h: 1000,
37
- expiration_time: "2024-12-31T00:00:00Z",
38
- open_interest: 500,
39
- last_price: 44
40
- }]
41
- }],
42
- cursor: ''
43
- }
44
- });
45
-
46
- const markets = await exchange.fetchMarkets();
47
-
48
- expect(markets.length).toBe(1);
49
- const m = markets[0];
50
- expect(m.id).toBe('KXINFLATION24');
51
- expect(m.title).toBe('Inflation > 3%');
52
- expect(m.outcomes[0].price).toBe(0.44); // last_price / 100
53
- expect(m.volume24h).toBe(1000);
54
- expect(m.category).toBe('Economics');
55
- });
56
- });
@@ -1,40 +0,0 @@
1
- import { KalshiExchange } from '../../../src/exchanges/Kalshi';
2
-
3
- /**
4
- * Kalshi Integration Test (Live API)
5
- *
6
- * What: Verifies real-world connectivity and data structure from the live Kalshi API.
7
- * Why: To ensure our mapping logic matches the actual live data and to detect
8
- * breaking API changes early.
9
- * How: Makes actual HTTP requests to Kalshi's public endpoints and validates
10
- * the properties of the returned markets.
11
- */
12
-
13
- describe('KalshiExchange - Live API Integration', () => {
14
- const exchange = new KalshiExchange();
15
- jest.setTimeout(30000); // Kalshi fetches all events before applying limit (needs optimization)
16
-
17
- it('should fetch real markets with expected properties', async () => {
18
- const markets = await exchange.fetchMarkets({ limit: 5 });
19
-
20
- if (markets.length > 0) {
21
- const m = markets[0];
22
- expect(m.id).toBeDefined();
23
- expect(typeof m.title).toBe('string');
24
- expect(m.outcomes.length).toBeGreaterThan(0);
25
- expect(m.volume24h).toBeGreaterThanOrEqual(0);
26
-
27
- // Prices should be normalized to 0-1
28
- m.outcomes.forEach(outcome => {
29
- expect(outcome.price).toBeGreaterThanOrEqual(0);
30
- expect(outcome.price).toBeLessThanOrEqual(1);
31
- });
32
- }
33
- });
34
-
35
- it('should respect the limit parameter on live data', async () => {
36
- const limit = 3;
37
- const markets = await exchange.fetchMarkets({ limit });
38
- expect(markets.length).toBeLessThanOrEqual(limit);
39
- });
40
- });
@@ -1,185 +0,0 @@
1
- import axios from 'axios';
2
- import { KalshiExchange } from '../../../src/exchanges/Kalshi';
3
-
4
- /**
5
- * Kalshi getMarketHistory() Test
6
- *
7
- * What: Tests fetching historical OHLCV candlestick data.
8
- * Why: Historical data is essential for charting and analysis.
9
- * How: Mocks Kalshi candlestick API responses and verifies data transformation.
10
- */
11
-
12
- jest.mock('axios');
13
- const mockedAxios = axios as jest.Mocked<typeof axios>;
14
-
15
- describe('KalshiExchange - getMarketHistory', () => {
16
- let exchange: KalshiExchange;
17
-
18
- beforeEach(() => {
19
- exchange = new KalshiExchange();
20
- jest.clearAllMocks();
21
- });
22
-
23
- it('should fetch and parse candlestick data', async () => {
24
- mockedAxios.get.mockResolvedValue({
25
- data: {
26
- candlesticks: [
27
- {
28
- end_period_ts: 1704067200,
29
- price: { open: 5200, high: 5300, low: 5100, close: 5250 },
30
- volume: 1000
31
- },
32
- {
33
- end_period_ts: 1704070800,
34
- price: { open: 5250, high: 5400, low: 5200, close: 5350 },
35
- volume: 1500
36
- }
37
- ]
38
- }
39
- });
40
-
41
- const history = await exchange.getMarketHistory('FED-25JAN-B4.75', { resolution: '1h' });
42
-
43
- expect(history.length).toBe(2);
44
- expect(history[0].open).toBe(52); // 5200 / 100 = 52
45
- expect(history[0].high).toBe(53);
46
- expect(history[0].low).toBe(51);
47
- expect(history[0].close).toBe(52.5);
48
- expect(history[0].volume).toBe(1000);
49
- });
50
-
51
- it('should convert timestamps to milliseconds', async () => {
52
- mockedAxios.get.mockResolvedValue({
53
- data: {
54
- candlesticks: [{
55
- end_period_ts: 1704067200,
56
- price: { open: 5000, high: 5000, low: 5000, close: 5000 },
57
- volume: 100
58
- }]
59
- }
60
- });
61
-
62
- const history = await exchange.getMarketHistory('TEST-MARKET-B5', { resolution: '1h' });
63
-
64
- expect(history[0].timestamp).toBe(1704067200 * 1000);
65
- });
66
-
67
- it('should respect limit parameter', async () => {
68
- const mockCandles = Array.from({ length: 100 }, (_, i) => ({
69
- end_period_ts: 1704067200 + (i * 3600),
70
- price: { open: 5000, high: 5000, low: 5000, close: 5000 },
71
- volume: 100
72
- }));
73
-
74
- mockedAxios.get.mockResolvedValue({
75
- data: { candlesticks: mockCandles }
76
- });
77
-
78
- const history = await exchange.getMarketHistory('TEST-MARKET-B5', {
79
- resolution: '1h',
80
- limit: 20
81
- });
82
-
83
- expect(history.length).toBe(20);
84
- });
85
-
86
- it('should handle different intervals', async () => {
87
- mockedAxios.get.mockResolvedValue({
88
- data: {
89
- candlesticks: [{
90
- end_period_ts: 1704067200,
91
- price: { open: 5000, high: 5000, low: 5000, close: 5000 },
92
- volume: 100
93
- }]
94
- }
95
- });
96
-
97
- await exchange.getMarketHistory('TEST-MARKET-B5', { resolution: '1m' });
98
- expect(mockedAxios.get).toHaveBeenCalledWith(
99
- expect.any(String),
100
- expect.objectContaining({
101
- params: expect.objectContaining({ period_interval: 1 })
102
- })
103
- );
104
-
105
- jest.clearAllMocks();
106
- mockedAxios.get.mockResolvedValue({
107
- data: { candlesticks: [] }
108
- });
109
-
110
- await exchange.getMarketHistory('TEST-MARKET-B5', { resolution: '1d' });
111
- expect(mockedAxios.get).toHaveBeenCalledWith(
112
- expect.any(String),
113
- expect.objectContaining({
114
- params: expect.objectContaining({ period_interval: 1440 })
115
- })
116
- );
117
- });
118
-
119
- it('should handle start and end timestamps', async () => {
120
- mockedAxios.get.mockResolvedValue({
121
- data: { candlesticks: [] }
122
- });
123
-
124
- const start = new Date('2025-01-01T00:00:00Z');
125
- const end = new Date('2025-01-02T00:00:00Z');
126
-
127
- await exchange.getMarketHistory('TEST-MARKET-B5', {
128
- resolution: '1h',
129
- start,
130
- end
131
- });
132
-
133
- expect(mockedAxios.get).toHaveBeenCalledWith(
134
- expect.any(String),
135
- expect.objectContaining({
136
- params: expect.objectContaining({
137
- start_ts: Math.floor(start.getTime() / 1000),
138
- end_ts: Math.floor(end.getTime() / 1000)
139
- })
140
- })
141
- );
142
- });
143
-
144
- it('should handle empty candlesticks array', async () => {
145
- mockedAxios.get.mockResolvedValue({
146
- data: { candlesticks: [] }
147
- });
148
-
149
- const history = await exchange.getMarketHistory('TEST-MARKET-B5', { resolution: '1h' });
150
-
151
- expect(history).toEqual([]);
152
- });
153
-
154
- it('should handle missing price fields gracefully', async () => {
155
- mockedAxios.get.mockResolvedValue({
156
- data: {
157
- candlesticks: [{
158
- end_period_ts: 1704067200,
159
- price: {}, // Missing OHLC data
160
- volume: 100
161
- }]
162
- }
163
- });
164
-
165
- const history = await exchange.getMarketHistory('TEST-MARKET-B5', { resolution: '1h' });
166
-
167
- expect(history[0].open).toBe(0);
168
- expect(history[0].high).toBe(0);
169
- expect(history[0].low).toBe(0);
170
- expect(history[0].close).toBe(0);
171
- });
172
-
173
- it('should extract series ticker correctly', async () => {
174
- mockedAxios.get.mockResolvedValue({
175
- data: { candlesticks: [] }
176
- });
177
-
178
- await exchange.getMarketHistory('FED-25JAN-B4.75', { resolution: '1h' });
179
-
180
- expect(mockedAxios.get).toHaveBeenCalledWith(
181
- expect.stringContaining('/series/FED-25JAN/markets/FED-25JAN-B4.75/'),
182
- expect.any(Object)
183
- );
184
- });
185
- });
@@ -1,149 +0,0 @@
1
- import axios from 'axios';
2
- import { KalshiExchange } from '../../../src/exchanges/Kalshi';
3
-
4
- /**
5
- * Kalshi getOrderBook() Test
6
- *
7
- * What: Tests fetching and parsing of order book data (bids/asks).
8
- * Why: Order book data is critical for trading and price discovery.
9
- * How: Mocks Kalshi orderbook 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('KalshiExchange - getOrderBook', () => {
16
- let exchange: KalshiExchange;
17
-
18
- beforeEach(() => {
19
- exchange = new KalshiExchange();
20
- jest.clearAllMocks();
21
- });
22
-
23
- it('should parse orderbook data correctly', async () => {
24
- mockedAxios.get.mockResolvedValue({
25
- data: {
26
- orderbook: {
27
- yes: [
28
- [5200, 100], // price in cents, quantity
29
- [5100, 250],
30
- [5000, 500]
31
- ],
32
- no: [
33
- [4800, 150],
34
- [4900, 200],
35
- [5000, 300]
36
- ]
37
- }
38
- }
39
- });
40
-
41
- const orderbook = await exchange.getOrderBook('FED-25JAN-B4.75');
42
-
43
- expect(orderbook.bids).toBeDefined();
44
- expect(orderbook.asks).toBeDefined();
45
- expect(orderbook.bids.length).toBe(3);
46
- expect(orderbook.asks.length).toBe(3);
47
- });
48
-
49
- it('should convert prices from cents to decimals', async () => {
50
- mockedAxios.get.mockResolvedValue({
51
- data: {
52
- orderbook: {
53
- yes: [[5200, 100]],
54
- no: [[4800, 100]]
55
- }
56
- }
57
- });
58
-
59
- const orderbook = await exchange.getOrderBook('TEST-MARKET');
60
-
61
- expect(orderbook.bids[0].price).toBe(52); // 5200 / 100 = 52
62
- expect(orderbook.asks[0].price).toBe(-47); // (100 - 4800) / 100 = -47
63
- });
64
-
65
- it('should sort bids in descending order', async () => {
66
- mockedAxios.get.mockResolvedValue({
67
- data: {
68
- orderbook: {
69
- yes: [
70
- [5000, 100],
71
- [5200, 200],
72
- [5100, 150]
73
- ],
74
- no: []
75
- }
76
- }
77
- });
78
-
79
- const orderbook = await exchange.getOrderBook('TEST-MARKET');
80
-
81
- expect(orderbook.bids[0].price).toBeGreaterThanOrEqual(orderbook.bids[1].price);
82
- expect(orderbook.bids[1].price).toBeGreaterThanOrEqual(orderbook.bids[2].price);
83
- });
84
-
85
- it('should sort asks in ascending order', async () => {
86
- mockedAxios.get.mockResolvedValue({
87
- data: {
88
- orderbook: {
89
- yes: [],
90
- no: [
91
- [5000, 100],
92
- [4800, 200],
93
- [4900, 150]
94
- ]
95
- }
96
- }
97
- });
98
-
99
- const orderbook = await exchange.getOrderBook('TEST-MARKET');
100
-
101
- expect(orderbook.asks[0].price).toBeLessThanOrEqual(orderbook.asks[1].price);
102
- expect(orderbook.asks[1].price).toBeLessThanOrEqual(orderbook.asks[2].price);
103
- });
104
-
105
- it('should handle empty orderbook', async () => {
106
- mockedAxios.get.mockResolvedValue({
107
- data: {
108
- orderbook: {
109
- yes: [],
110
- no: []
111
- }
112
- }
113
- });
114
-
115
- const orderbook = await exchange.getOrderBook('TEST-MARKET');
116
-
117
- expect(orderbook.bids).toEqual([]);
118
- expect(orderbook.asks).toEqual([]);
119
- });
120
-
121
- it('should include timestamp', async () => {
122
- mockedAxios.get.mockResolvedValue({
123
- data: {
124
- orderbook: {
125
- yes: [[5200, 100]],
126
- no: [[4800, 100]]
127
- }
128
- }
129
- });
130
-
131
- const orderbook = await exchange.getOrderBook('TEST-MARKET');
132
-
133
- expect(orderbook.timestamp).toBeDefined();
134
- expect(typeof orderbook.timestamp).toBe('number');
135
- });
136
-
137
- it('should handle missing yes/no fields', async () => {
138
- mockedAxios.get.mockResolvedValue({
139
- data: {
140
- orderbook: {}
141
- }
142
- });
143
-
144
- const orderbook = await exchange.getOrderBook('TEST-MARKET');
145
-
146
- expect(orderbook.bids).toEqual([]);
147
- expect(orderbook.asks).toEqual([]);
148
- });
149
- });
@@ -1,174 +0,0 @@
1
- import axios from 'axios';
2
- import { KalshiExchange } from '../../../src/exchanges/Kalshi';
3
-
4
- /**
5
- * Kalshi 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 filtering logic.
10
- */
11
-
12
- jest.mock('axios');
13
- const mockedAxios = axios as jest.Mocked<typeof axios>;
14
-
15
- describe('KalshiExchange - searchMarkets', () => {
16
- let exchange: KalshiExchange;
17
-
18
- beforeEach(() => {
19
- exchange = new KalshiExchange();
20
- jest.clearAllMocks();
21
- });
22
-
23
- it('should filter markets by title', async () => {
24
- mockedAxios.get.mockResolvedValue({
25
- data: {
26
- events: [
27
- {
28
- event_ticker: 'FED-2025',
29
- title: 'Federal Reserve Interest Rate Decision',
30
- markets: [{
31
- ticker: 'FED-25JAN-B4.75',
32
- expiration_time: '2025-01-29T00:00:00Z',
33
- last_price: 5200
34
- }]
35
- },
36
- {
37
- event_ticker: 'PRES-2024',
38
- title: 'Presidential Election 2024',
39
- markets: [{
40
- ticker: 'PRES-2024-TRUMP',
41
- expiration_time: '2024-11-05T00:00:00Z',
42
- last_price: 4800
43
- }]
44
- }
45
- ],
46
- cursor: null
47
- }
48
- });
49
-
50
- const results = await exchange.searchMarkets('federal');
51
-
52
- expect(results.length).toBeGreaterThan(0);
53
- expect(results[0].title.toLowerCase()).toContain('federal');
54
- });
55
-
56
- it('should filter markets by description', async () => {
57
- mockedAxios.get.mockResolvedValue({
58
- data: {
59
- events: [
60
- {
61
- event_ticker: 'TEST-EVENT',
62
- title: 'Test Event',
63
- sub_title: 'This is about climate change policy',
64
- markets: [{
65
- ticker: 'TEST-MARKET',
66
- subtitle: 'Climate policy details',
67
- expiration_time: '2025-12-31T00:00:00Z',
68
- last_price: 5000
69
- }]
70
- }
71
- ],
72
- cursor: null
73
- }
74
- });
75
-
76
- const results = await exchange.searchMarkets('climate');
77
-
78
- expect(results.length).toBeGreaterThan(0);
79
- });
80
-
81
- it('should respect limit parameter', async () => {
82
- const mockEvents = Array.from({ length: 50 }, (_, i) => ({
83
- event_ticker: `EVENT-${i}`,
84
- title: `Test Market ${i}`,
85
- markets: [{
86
- ticker: `MARKET-${i}`,
87
- expiration_time: '2025-12-31T00:00:00Z',
88
- last_price: 5000
89
- }]
90
- }));
91
-
92
- mockedAxios.get.mockResolvedValue({
93
- data: {
94
- events: mockEvents,
95
- cursor: null
96
- }
97
- });
98
-
99
- const results = await exchange.searchMarkets('test', { limit: 5 });
100
-
101
- expect(results.length).toBeLessThanOrEqual(5);
102
- });
103
-
104
- it('should return empty array when no matches found', async () => {
105
- mockedAxios.get.mockResolvedValue({
106
- data: {
107
- events: [{
108
- event_ticker: 'UNRELATED',
109
- title: 'Completely Different Topic',
110
- markets: [{
111
- ticker: 'UNRELATED-MARKET',
112
- expiration_time: '2025-12-31T00:00:00Z',
113
- last_price: 5000
114
- }]
115
- }],
116
- cursor: null
117
- }
118
- });
119
-
120
- const results = await exchange.searchMarkets('nonexistent query string');
121
-
122
- expect(results).toEqual([]);
123
- });
124
-
125
- it('should handle search errors gracefully', async () => {
126
- mockedAxios.get.mockRejectedValue(new Error('Search failed'));
127
- const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => { });
128
-
129
- const results = await exchange.searchMarkets('test');
130
-
131
- expect(results).toEqual([]);
132
- expect(consoleSpy).toHaveBeenCalled();
133
- consoleSpy.mockRestore();
134
- });
135
-
136
- it('should be case-insensitive', async () => {
137
- mockedAxios.get.mockResolvedValue({
138
- data: {
139
- events: [{
140
- event_ticker: 'TEST',
141
- title: 'FEDERAL RESERVE',
142
- markets: [{
143
- ticker: 'TEST-MARKET',
144
- expiration_time: '2025-12-31T00:00:00Z',
145
- last_price: 5000
146
- }]
147
- }],
148
- cursor: null
149
- }
150
- });
151
-
152
- const resultsLower = await exchange.searchMarkets('federal');
153
-
154
- jest.clearAllMocks();
155
- mockedAxios.get.mockResolvedValue({
156
- data: {
157
- events: [{
158
- event_ticker: 'TEST',
159
- title: 'FEDERAL RESERVE',
160
- markets: [{
161
- ticker: 'TEST-MARKET',
162
- expiration_time: '2025-12-31T00:00:00Z',
163
- last_price: 5000
164
- }]
165
- }],
166
- cursor: null
167
- }
168
- });
169
-
170
- const resultsUpper = await exchange.searchMarkets('FEDERAL');
171
-
172
- expect(resultsLower.length).toBe(resultsUpper.length);
173
- });
174
- });
@@ -1,44 +0,0 @@
1
- import axios from 'axios';
2
- import { KalshiExchange } from '../../../src/exchanges/Kalshi';
3
-
4
- /**
5
- * Kalshi Volume Fallback Test
6
- *
7
- * What: Tests the fallback logic for volume reporting.
8
- * Why: Kalshi sometimes omits volume_24h for certain markets. In these cases,
9
- * we fall back to total volume to ensure we don't display 0 volume for active markets.
10
- * How: Mocks a market with 0 volume_24h but non-zero total volume.
11
- */
12
-
13
- jest.mock('axios');
14
- const mockedAxios = axios as jest.Mocked<typeof axios>;
15
-
16
- describe('KalshiExchange - Volume Fallback Mechanism', () => {
17
- let exchange: KalshiExchange;
18
-
19
- beforeEach(() => {
20
- exchange = new KalshiExchange();
21
- jest.clearAllMocks();
22
- });
23
-
24
- it('should fallback to total volume if 24h volume is missing or zero', async () => {
25
- mockedAxios.get.mockResolvedValue({
26
- data: {
27
- events: [{
28
- event_ticker: 'KXTEST',
29
- title: 'Test Event',
30
- markets: [{
31
- ticker: 'KXTEST-001',
32
- volume: 5000,
33
- volume_24h: 0,
34
- expiration_time: "2024-12-31T00:00:00Z"
35
- }]
36
- }],
37
- cursor: ''
38
- }
39
- });
40
-
41
- const markets = await exchange.fetchMarkets();
42
- expect(markets[0].volume24h).toBe(5000);
43
- });
44
- });