pmxt-core 2.24.0 → 2.25.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 (42) hide show
  1. package/dist/exchanges/kalshi/api.d.ts +1 -1
  2. package/dist/exchanges/kalshi/api.js +1 -1
  3. package/dist/exchanges/limitless/api.d.ts +1 -1
  4. package/dist/exchanges/limitless/api.js +1 -1
  5. package/dist/exchanges/myriad/api.d.ts +1 -1
  6. package/dist/exchanges/myriad/api.js +1 -1
  7. package/dist/exchanges/opinion/api.d.ts +1 -1
  8. package/dist/exchanges/opinion/api.js +1 -1
  9. package/dist/exchanges/polymarket/api-clob.d.ts +1 -1
  10. package/dist/exchanges/polymarket/api-clob.js +1 -1
  11. package/dist/exchanges/polymarket/api-data.d.ts +1 -1
  12. package/dist/exchanges/polymarket/api-data.js +1 -1
  13. package/dist/exchanges/polymarket/api-gamma.d.ts +1 -1
  14. package/dist/exchanges/polymarket/api-gamma.js +1 -1
  15. package/dist/exchanges/polymarket_us/config.d.ts +18 -0
  16. package/dist/exchanges/polymarket_us/config.js +22 -0
  17. package/dist/exchanges/polymarket_us/errors.d.ts +19 -0
  18. package/dist/exchanges/polymarket_us/errors.js +123 -0
  19. package/dist/exchanges/polymarket_us/errors.test.d.ts +1 -0
  20. package/dist/exchanges/polymarket_us/errors.test.js +54 -0
  21. package/dist/exchanges/polymarket_us/index.d.ts +90 -0
  22. package/dist/exchanges/polymarket_us/index.js +366 -0
  23. package/dist/exchanges/polymarket_us/index.test.d.ts +8 -0
  24. package/dist/exchanges/polymarket_us/index.test.js +237 -0
  25. package/dist/exchanges/polymarket_us/normalizer.d.ts +55 -0
  26. package/dist/exchanges/polymarket_us/normalizer.js +385 -0
  27. package/dist/exchanges/polymarket_us/normalizer.test.d.ts +1 -0
  28. package/dist/exchanges/polymarket_us/normalizer.test.js +224 -0
  29. package/dist/exchanges/polymarket_us/price.d.ts +94 -0
  30. package/dist/exchanges/polymarket_us/price.js +149 -0
  31. package/dist/exchanges/polymarket_us/price.test.d.ts +1 -0
  32. package/dist/exchanges/polymarket_us/price.test.js +131 -0
  33. package/dist/exchanges/polymarket_us/websocket.d.ts +39 -0
  34. package/dist/exchanges/polymarket_us/websocket.js +181 -0
  35. package/dist/exchanges/polymarket_us/websocket.test.d.ts +8 -0
  36. package/dist/exchanges/polymarket_us/websocket.test.js +162 -0
  37. package/dist/exchanges/probable/api.d.ts +1 -1
  38. package/dist/exchanges/probable/api.js +1 -1
  39. package/dist/index.d.ts +4 -0
  40. package/dist/index.js +5 -1
  41. package/dist/server/app.js +6 -0
  42. package/package.json +4 -3
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ /**
3
+ * Unit tests for PolymarketUSWebSocket.
4
+ *
5
+ * The polymarket-us SDK is fully stubbed here so the tests run without
6
+ * touching the network. A fake MarketsWebSocket captures subscriptions
7
+ * and lets each test fire synthetic messages through a listener map.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ const websocket_1 = require("./websocket");
11
+ const normalizer_1 = require("./normalizer");
12
+ class FakeMarketsWebSocket {
13
+ listeners = new Map();
14
+ connectCalls = 0;
15
+ closeCalls = 0;
16
+ subscribeMarketDataCalls = [];
17
+ subscribeTradesCalls = [];
18
+ on(event, listener) {
19
+ const arr = this.listeners.get(event) ?? [];
20
+ arr.push(listener);
21
+ this.listeners.set(event, arr);
22
+ return this;
23
+ }
24
+ async connect() {
25
+ this.connectCalls += 1;
26
+ }
27
+ close() {
28
+ this.closeCalls += 1;
29
+ }
30
+ subscribeMarketData(requestId, slugs) {
31
+ this.subscribeMarketDataCalls.push({ requestId, slugs });
32
+ }
33
+ subscribeTrades(requestId, slugs) {
34
+ this.subscribeTradesCalls.push({ requestId, slugs });
35
+ }
36
+ emit(event, arg) {
37
+ const arr = this.listeners.get(event) ?? [];
38
+ for (const listener of arr)
39
+ listener(arg);
40
+ }
41
+ }
42
+ function makeClient(fakeSocket) {
43
+ return {
44
+ ws: {
45
+ markets: () => fakeSocket,
46
+ },
47
+ };
48
+ }
49
+ describe('PolymarketUSWebSocket', () => {
50
+ let fake;
51
+ let ws;
52
+ beforeEach(() => {
53
+ fake = new FakeMarketsWebSocket();
54
+ ws = new websocket_1.PolymarketUSWebSocket(makeClient(fake), new normalizer_1.PolymarketUSNormalizer());
55
+ });
56
+ describe('watchOrderBook', () => {
57
+ it('connects lazily, subscribes once per slug, and resolves on marketData', async () => {
58
+ const pending = ws.watchOrderBook('btc-100k');
59
+ // Let the ensureInitialized microtask run so connect resolves
60
+ await new Promise(r => setImmediate(r));
61
+ expect(fake.connectCalls).toBe(1);
62
+ expect(fake.subscribeMarketDataCalls).toEqual([
63
+ { requestId: 'book:btc-100k', slugs: ['btc-100k'] },
64
+ ]);
65
+ fake.emit('marketData', {
66
+ requestId: 'book:btc-100k',
67
+ subscriptionType: 'SUBSCRIPTION_TYPE_MARKET_DATA',
68
+ marketData: {
69
+ marketSlug: 'btc-100k',
70
+ bids: [{ px: { value: '0.55', currency: 'USD' }, qty: '10' }],
71
+ offers: [{ px: { value: '0.57', currency: 'USD' }, qty: '5' }],
72
+ state: 'MARKET_STATE_OPEN',
73
+ transactTime: '2026-04-06T00:00:00Z',
74
+ },
75
+ });
76
+ const book = await pending;
77
+ expect(book.bids).toEqual([{ price: 0.55, size: 10 }]);
78
+ expect(book.asks).toEqual([{ price: 0.57, size: 5 }]);
79
+ });
80
+ it('strips :long suffix before subscribing', async () => {
81
+ const pending = ws.watchOrderBook('btc-100k:long');
82
+ await new Promise(r => setImmediate(r));
83
+ expect(fake.subscribeMarketDataCalls).toEqual([
84
+ { requestId: 'book:btc-100k', slugs: ['btc-100k'] },
85
+ ]);
86
+ fake.emit('marketData', {
87
+ marketData: {
88
+ marketSlug: 'btc-100k',
89
+ bids: [],
90
+ offers: [],
91
+ state: 'MARKET_STATE_OPEN',
92
+ },
93
+ });
94
+ await pending;
95
+ });
96
+ it('does not re-subscribe when called twice for the same slug', async () => {
97
+ const p1 = ws.watchOrderBook('btc-100k');
98
+ await new Promise(r => setImmediate(r));
99
+ const p2 = ws.watchOrderBook('btc-100k');
100
+ await new Promise(r => setImmediate(r));
101
+ expect(fake.subscribeMarketDataCalls).toHaveLength(1);
102
+ fake.emit('marketData', {
103
+ marketData: {
104
+ marketSlug: 'btc-100k',
105
+ bids: [],
106
+ offers: [],
107
+ state: 'MARKET_STATE_OPEN',
108
+ },
109
+ });
110
+ const [b1, b2] = await Promise.all([p1, p2]);
111
+ expect(b1.bids).toEqual([]);
112
+ expect(b2.bids).toEqual([]);
113
+ });
114
+ });
115
+ describe('watchTrades', () => {
116
+ it('resolves with a PMXT Trade on the next trade message', async () => {
117
+ const pending = ws.watchTrades('btc-100k');
118
+ await new Promise(r => setImmediate(r));
119
+ expect(fake.subscribeTradesCalls).toEqual([
120
+ { requestId: 'trade:btc-100k', slugs: ['btc-100k'] },
121
+ ]);
122
+ fake.emit('trade', {
123
+ requestId: 'trade:btc-100k',
124
+ subscriptionType: 'SUBSCRIPTION_TYPE_TRADE',
125
+ trade: {
126
+ marketSlug: 'btc-100k',
127
+ price: { value: '0.55', currency: 'USD' },
128
+ quantity: { value: '10', currency: 'USD' },
129
+ tradeTime: '2026-04-06T00:00:00Z',
130
+ maker: { side: 'ORDER_SIDE_SELL', intent: 'ORDER_INTENT_SELL_LONG' },
131
+ taker: { side: 'ORDER_SIDE_BUY', intent: 'ORDER_INTENT_BUY_LONG' },
132
+ },
133
+ });
134
+ const trades = await pending;
135
+ expect(trades).toHaveLength(1);
136
+ expect(trades[0].price).toBeCloseTo(0.55);
137
+ expect(trades[0].amount).toBeCloseTo(10);
138
+ expect(trades[0].side).toBe('buy');
139
+ expect(trades[0].timestamp).toBe(new Date('2026-04-06T00:00:00Z').getTime());
140
+ });
141
+ });
142
+ describe('close', () => {
143
+ it('rejects pending watchers and closes the socket', async () => {
144
+ const pending = ws.watchOrderBook('btc-100k');
145
+ await new Promise(r => setImmediate(r));
146
+ const pendingTrade = ws.watchTrades('btc-100k');
147
+ await new Promise(r => setImmediate(r));
148
+ await ws.close();
149
+ await expect(pending).rejects.toThrow('PolymarketUS WebSocket closed');
150
+ await expect(pendingTrade).rejects.toThrow('PolymarketUS WebSocket closed');
151
+ expect(fake.closeCalls).toBe(1);
152
+ });
153
+ });
154
+ describe('error handling', () => {
155
+ it('rejects pending watchers when the socket emits an error', async () => {
156
+ const pending = ws.watchOrderBook('btc-100k');
157
+ await new Promise(r => setImmediate(r));
158
+ fake.emit('error', new Error('boom'));
159
+ await expect(pending).rejects.toThrow('boom');
160
+ });
161
+ });
162
+ });
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/probable/probable.yaml
3
- * Generated at: 2026-04-06T14:01:00.988Z
3
+ * Generated at: 2026-04-06T19:59:33.366Z
4
4
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
5
5
  */
6
6
  export declare const probableApiSpec: {
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.probableApiSpec = void 0;
4
4
  /**
5
5
  * Auto-generated from /home/runner/work/pmxt/pmxt/core/specs/probable/probable.yaml
6
- * Generated at: 2026-04-06T14:01:00.988Z
6
+ * Generated at: 2026-04-06T19:59:33.366Z
7
7
  * Do not edit manually -- run "npm run fetch:openapi" to regenerate.
8
8
  */
9
9
  exports.probableApiSpec = {
package/dist/index.d.ts CHANGED
@@ -13,6 +13,7 @@ export * from './exchanges/myriad';
13
13
  export * from './exchanges/opinion';
14
14
  export * from './exchanges/metaculus';
15
15
  export * from './exchanges/smarkets';
16
+ export * from './exchanges/polymarket_us';
16
17
  export * from './server/app';
17
18
  export * from './server/utils/port-manager';
18
19
  export * from './server/utils/lock-file';
@@ -26,6 +27,7 @@ import { MyriadExchange } from './exchanges/myriad';
26
27
  import { OpinionExchange } from './exchanges/opinion';
27
28
  import { MetaculusExchange } from './exchanges/metaculus';
28
29
  import { SmarketsExchange } from './exchanges/smarkets';
30
+ import { PolymarketUSExchange } from './exchanges/polymarket_us';
29
31
  declare const pmxt: {
30
32
  Polymarket: typeof PolymarketExchange;
31
33
  Limitless: typeof LimitlessExchange;
@@ -37,6 +39,7 @@ declare const pmxt: {
37
39
  Opinion: typeof OpinionExchange;
38
40
  Metaculus: typeof MetaculusExchange;
39
41
  Smarkets: typeof SmarketsExchange;
42
+ PolymarketUS: typeof PolymarketUSExchange;
40
43
  };
41
44
  export declare const Polymarket: typeof PolymarketExchange;
42
45
  export declare const Limitless: typeof LimitlessExchange;
@@ -48,4 +51,5 @@ export declare const Myriad: typeof MyriadExchange;
48
51
  export declare const Opinion: typeof OpinionExchange;
49
52
  export declare const Metaculus: typeof MetaculusExchange;
50
53
  export declare const Smarkets: typeof SmarketsExchange;
54
+ export declare const PolymarketUS: typeof PolymarketUSExchange;
51
55
  export default pmxt;
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.Smarkets = exports.Metaculus = exports.Opinion = exports.Myriad = exports.Baozi = exports.Probable = exports.KalshiDemo = exports.Kalshi = exports.Limitless = exports.Polymarket = exports.parseOpenApiSpec = void 0;
17
+ exports.PolymarketUS = exports.Smarkets = exports.Metaculus = exports.Opinion = exports.Myriad = exports.Baozi = exports.Probable = exports.KalshiDemo = exports.Kalshi = exports.Limitless = exports.Polymarket = exports.parseOpenApiSpec = void 0;
18
18
  __exportStar(require("./BaseExchange"), exports);
19
19
  __exportStar(require("./types"), exports);
20
20
  __exportStar(require("./utils/math"), exports);
@@ -31,6 +31,7 @@ __exportStar(require("./exchanges/myriad"), exports);
31
31
  __exportStar(require("./exchanges/opinion"), exports);
32
32
  __exportStar(require("./exchanges/metaculus"), exports);
33
33
  __exportStar(require("./exchanges/smarkets"), exports);
34
+ __exportStar(require("./exchanges/polymarket_us"), exports);
34
35
  __exportStar(require("./server/app"), exports);
35
36
  __exportStar(require("./server/utils/port-manager"), exports);
36
37
  __exportStar(require("./server/utils/lock-file"), exports);
@@ -44,6 +45,7 @@ const myriad_1 = require("./exchanges/myriad");
44
45
  const opinion_1 = require("./exchanges/opinion");
45
46
  const metaculus_1 = require("./exchanges/metaculus");
46
47
  const smarkets_1 = require("./exchanges/smarkets");
48
+ const polymarket_us_1 = require("./exchanges/polymarket_us");
47
49
  const pmxt = {
48
50
  Polymarket: polymarket_1.PolymarketExchange,
49
51
  Limitless: limitless_1.LimitlessExchange,
@@ -55,6 +57,7 @@ const pmxt = {
55
57
  Opinion: opinion_1.OpinionExchange,
56
58
  Metaculus: metaculus_1.MetaculusExchange,
57
59
  Smarkets: smarkets_1.SmarketsExchange,
60
+ PolymarketUS: polymarket_us_1.PolymarketUSExchange,
58
61
  };
59
62
  exports.Polymarket = polymarket_1.PolymarketExchange;
60
63
  exports.Limitless = limitless_1.LimitlessExchange;
@@ -66,4 +69,5 @@ exports.Myriad = myriad_1.MyriadExchange;
66
69
  exports.Opinion = opinion_1.OpinionExchange;
67
70
  exports.Metaculus = metaculus_1.MetaculusExchange;
68
71
  exports.Smarkets = smarkets_1.SmarketsExchange;
72
+ exports.PolymarketUS = polymarket_us_1.PolymarketUSExchange;
69
73
  exports.default = pmxt;
@@ -16,6 +16,7 @@ const myriad_1 = require("../exchanges/myriad");
16
16
  const opinion_1 = require("../exchanges/opinion");
17
17
  const metaculus_1 = require("../exchanges/metaculus");
18
18
  const smarkets_1 = require("../exchanges/smarkets");
19
+ const polymarket_us_1 = require("../exchanges/polymarket_us");
19
20
  const errors_1 = require("../errors");
20
21
  // Singleton instances for local usage (when no credentials provided)
21
22
  const defaultExchanges = {
@@ -212,6 +213,11 @@ function createExchange(name, credentials) {
212
213
  apiKey: credentials?.apiKey || process.env.SMARKETS_EMAIL,
213
214
  privateKey: credentials?.privateKey || process.env.SMARKETS_PASSWORD,
214
215
  });
216
+ case "polymarket_us":
217
+ return new polymarket_us_1.PolymarketUSExchange({
218
+ apiKey: credentials?.apiKey || process.env.POLYMARKET_US_KEY_ID,
219
+ privateKey: credentials?.privateKey || process.env.POLYMARKET_US_SECRET_KEY,
220
+ });
215
221
  default:
216
222
  throw new Error(`Unknown exchange: ${name}`);
217
223
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmxt-core",
3
- "version": "2.24.0",
3
+ "version": "2.25.0",
4
4
  "description": "pmxt is a unified prediction market data API. The ccxt for prediction markets.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -29,8 +29,8 @@
29
29
  "test": "jest -c jest.config.js",
30
30
  "server": "tsx watch src/server/index.ts",
31
31
  "server:prod": "node dist/server/index.js",
32
- "generate:sdk:python": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g python -o ../sdks/python/generated --package-name pmxt_internal --additional-properties=projectName=pmxt-internal,packageVersion=2.24.0,library=urllib3",
33
- "generate:sdk:typescript": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g typescript-fetch -o ../sdks/typescript/generated --additional-properties=npmName=pmxtjs,npmVersion=2.24.0,supportsES6=true,typescriptThreePlus=true && node ../sdks/typescript/scripts/fix-generated.js",
32
+ "generate:sdk:python": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g python -o ../sdks/python/generated --package-name pmxt_internal --additional-properties=projectName=pmxt-internal,packageVersion=2.25.0,library=urllib3",
33
+ "generate:sdk:typescript": "npx @openapitools/openapi-generator-cli generate -i src/server/openapi.yaml -g typescript-fetch -o ../sdks/typescript/generated --additional-properties=npmName=pmxtjs,npmVersion=2.25.0,supportsES6=true,typescriptThreePlus=true && node ../sdks/typescript/scripts/fix-generated.js",
34
34
  "fetch:openapi": "node scripts/fetch-openapi-specs.js",
35
35
  "extract:jsdoc": "node ../scripts/extract-jsdoc.js",
36
36
  "generate:docs": "npm run extract:jsdoc && node ../scripts/generate-api-docs.js",
@@ -58,6 +58,7 @@
58
58
  "express": "^5.2.1",
59
59
  "isows": "^1.0.6",
60
60
  "jest": "^30.2.0",
61
+ "polymarket-us": "0.1.1",
61
62
  "tsx": "^4.21.0",
62
63
  "ws": "^8.18.0"
63
64
  },