pmxtjs 0.3.0 → 0.4.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 (50) hide show
  1. package/API_REFERENCE.md +448 -51
  2. package/dist/BaseExchange.d.ts +38 -3
  3. package/dist/BaseExchange.js +43 -1
  4. package/dist/exchanges/Kalshi.js +10 -2
  5. package/dist/exchanges/Polymarket.js +12 -4
  6. package/dist/exchanges/kalshi/auth.d.ts +23 -0
  7. package/dist/exchanges/kalshi/auth.js +99 -0
  8. package/dist/exchanges/kalshi/fetchMarkets.d.ts +3 -0
  9. package/dist/exchanges/kalshi/fetchMarkets.js +84 -0
  10. package/dist/exchanges/kalshi/fetchOHLCV.d.ts +3 -0
  11. package/dist/exchanges/kalshi/fetchOHLCV.js +78 -0
  12. package/dist/exchanges/kalshi/fetchOrderBook.d.ts +2 -0
  13. package/dist/exchanges/kalshi/fetchOrderBook.js +32 -0
  14. package/dist/exchanges/kalshi/fetchTrades.d.ts +3 -0
  15. package/dist/exchanges/kalshi/fetchTrades.js +31 -0
  16. package/dist/exchanges/kalshi/getMarketsBySlug.d.ts +7 -0
  17. package/dist/exchanges/kalshi/getMarketsBySlug.js +46 -0
  18. package/dist/exchanges/kalshi/index.d.ts +21 -0
  19. package/dist/exchanges/kalshi/index.js +273 -0
  20. package/dist/exchanges/kalshi/kalshi.test.d.ts +1 -0
  21. package/dist/exchanges/kalshi/kalshi.test.js +309 -0
  22. package/dist/exchanges/kalshi/searchMarkets.d.ts +3 -0
  23. package/dist/exchanges/kalshi/searchMarkets.js +28 -0
  24. package/dist/exchanges/kalshi/utils.d.ts +4 -0
  25. package/dist/exchanges/kalshi/utils.js +70 -0
  26. package/dist/exchanges/polymarket/auth.d.ts +32 -0
  27. package/dist/exchanges/polymarket/auth.js +98 -0
  28. package/dist/exchanges/polymarket/fetchMarkets.d.ts +3 -0
  29. package/dist/exchanges/polymarket/fetchMarkets.js +75 -0
  30. package/dist/exchanges/polymarket/fetchOHLCV.d.ts +7 -0
  31. package/dist/exchanges/polymarket/fetchOHLCV.js +73 -0
  32. package/dist/exchanges/polymarket/fetchOrderBook.d.ts +6 -0
  33. package/dist/exchanges/polymarket/fetchOrderBook.js +38 -0
  34. package/dist/exchanges/polymarket/fetchPositions.d.ts +2 -0
  35. package/dist/exchanges/polymarket/fetchPositions.js +27 -0
  36. package/dist/exchanges/polymarket/fetchTrades.d.ts +11 -0
  37. package/dist/exchanges/polymarket/fetchTrades.js +59 -0
  38. package/dist/exchanges/polymarket/getMarketsBySlug.d.ts +7 -0
  39. package/dist/exchanges/polymarket/getMarketsBySlug.js +39 -0
  40. package/dist/exchanges/polymarket/index.d.ts +23 -0
  41. package/dist/exchanges/polymarket/index.js +216 -0
  42. package/dist/exchanges/polymarket/searchMarkets.d.ts +3 -0
  43. package/dist/exchanges/polymarket/searchMarkets.js +35 -0
  44. package/dist/exchanges/polymarket/utils.d.ts +7 -0
  45. package/dist/exchanges/polymarket/utils.js +95 -0
  46. package/dist/index.d.ts +4 -4
  47. package/dist/index.js +8 -8
  48. package/dist/types.d.ts +38 -0
  49. package/package.json +5 -1
  50. package/readme.md +44 -24
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KALSHI_API_URL = void 0;
4
+ exports.mapMarketToUnified = mapMarketToUnified;
5
+ exports.mapIntervalToKalshi = mapIntervalToKalshi;
6
+ exports.KALSHI_API_URL = "https://api.elections.kalshi.com/trade-api/v2/events";
7
+ function mapMarketToUnified(event, market) {
8
+ if (!market)
9
+ return null;
10
+ // Calculate price
11
+ let price = 0.5;
12
+ if (market.last_price) {
13
+ price = market.last_price / 100;
14
+ }
15
+ else if (market.yes_ask && market.yes_bid) {
16
+ price = (market.yes_ask + market.yes_bid) / 200;
17
+ }
18
+ else if (market.yes_ask) {
19
+ price = market.yes_ask / 100;
20
+ }
21
+ // Extract candidate name
22
+ let candidateName = null;
23
+ if (market.subtitle || market.yes_sub_title) {
24
+ candidateName = market.subtitle || market.yes_sub_title;
25
+ }
26
+ // Calculate 24h change
27
+ let priceChange = 0;
28
+ if (market.previous_price_dollars !== undefined && market.last_price_dollars !== undefined) {
29
+ priceChange = market.last_price_dollars - market.previous_price_dollars;
30
+ }
31
+ const outcomes = [
32
+ {
33
+ id: market.ticker, // The actual market ticker (primary tradeable)
34
+ label: candidateName || 'Yes',
35
+ price: price,
36
+ priceChange24h: priceChange
37
+ },
38
+ {
39
+ id: `${market.ticker}-NO`, // Virtual ID for the No outcome
40
+ label: candidateName ? `Not ${candidateName}` : 'No',
41
+ price: 1 - price,
42
+ priceChange24h: -priceChange // Inverse change for No? simplified assumption
43
+ }
44
+ ];
45
+ return {
46
+ id: market.ticker,
47
+ title: event.title,
48
+ description: event.sub_title || market.subtitle || "",
49
+ outcomes: outcomes,
50
+ resolutionDate: new Date(market.expiration_time),
51
+ volume24h: Number(market.volume_24h || market.volume || 0),
52
+ volume: Number(market.volume || 0),
53
+ liquidity: Number(market.liquidity || 0), // Kalshi 'liquidity' might need specific mapping if available, otherwise 0 to avoid conflation
54
+ openInterest: Number(market.open_interest || 0),
55
+ url: `https://kalshi.com/events/${event.event_ticker}`,
56
+ category: event.category,
57
+ tags: event.tags || []
58
+ };
59
+ }
60
+ function mapIntervalToKalshi(interval) {
61
+ const mapping = {
62
+ '1m': 1,
63
+ '5m': 1,
64
+ '15m': 1,
65
+ '1h': 60,
66
+ '6h': 60,
67
+ '1d': 1440
68
+ };
69
+ return mapping[interval];
70
+ }
@@ -0,0 +1,32 @@
1
+ import { ClobClient } from '@polymarket/clob-client';
2
+ import type { ApiKeyCreds } from '@polymarket/clob-client';
3
+ import { ExchangeCredentials } from '../../BaseExchange';
4
+ /**
5
+ * Manages Polymarket authentication and CLOB client initialization.
6
+ * Handles both L1 (wallet-based) and L2 (API credentials) authentication.
7
+ */
8
+ export declare class PolymarketAuth {
9
+ private credentials;
10
+ private signer?;
11
+ private clobClient?;
12
+ private apiCreds?;
13
+ constructor(credentials: ExchangeCredentials);
14
+ /**
15
+ * Get or create API credentials using L1 authentication.
16
+ * This uses the private key to derive/create API credentials.
17
+ */
18
+ getApiCredentials(): Promise<ApiKeyCreds>;
19
+ /**
20
+ * Get an authenticated CLOB client for L2 operations (trading).
21
+ * This client can place orders, cancel orders, query positions, etc.
22
+ */
23
+ getClobClient(): Promise<ClobClient>;
24
+ /**
25
+ * Get the signer's address.
26
+ */
27
+ getAddress(): string;
28
+ /**
29
+ * Reset cached credentials and client (useful for testing or credential rotation).
30
+ */
31
+ reset(): void;
32
+ }
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PolymarketAuth = void 0;
4
+ const clob_client_1 = require("@polymarket/clob-client");
5
+ const ethers_1 = require("ethers");
6
+ const POLYMARKET_HOST = 'https://clob.polymarket.com';
7
+ const POLYGON_CHAIN_ID = 137;
8
+ /**
9
+ * Manages Polymarket authentication and CLOB client initialization.
10
+ * Handles both L1 (wallet-based) and L2 (API credentials) authentication.
11
+ */
12
+ class PolymarketAuth {
13
+ constructor(credentials) {
14
+ this.credentials = credentials;
15
+ if (!credentials.privateKey) {
16
+ throw new Error('Polymarket requires a privateKey for authentication');
17
+ }
18
+ // Initialize the signer
19
+ this.signer = new ethers_1.Wallet(credentials.privateKey);
20
+ }
21
+ /**
22
+ * Get or create API credentials using L1 authentication.
23
+ * This uses the private key to derive/create API credentials.
24
+ */
25
+ async getApiCredentials() {
26
+ // Return cached credentials if available
27
+ if (this.apiCreds) {
28
+ return this.apiCreds;
29
+ }
30
+ // If credentials were provided, use them
31
+ if (this.credentials.apiKey && this.credentials.apiSecret && this.credentials.passphrase) {
32
+ this.apiCreds = {
33
+ key: this.credentials.apiKey,
34
+ secret: this.credentials.apiSecret,
35
+ passphrase: this.credentials.passphrase,
36
+ };
37
+ return this.apiCreds;
38
+ }
39
+ // Otherwise, derive/create them using L1 auth
40
+ const l1Client = new clob_client_1.ClobClient(POLYMARKET_HOST, POLYGON_CHAIN_ID, this.signer);
41
+ // Robust derivation strategy:
42
+ // 1. Try to DERIVE existing credentials first (most common case).
43
+ // 2. If that fails (e.g. 404 or 400), try to CREATE new ones.
44
+ let creds;
45
+ try {
46
+ // console.log('Trying to derive existing API key...');
47
+ creds = await l1Client.deriveApiKey();
48
+ }
49
+ catch (deriveError) {
50
+ // console.log('Derivation failed, trying to create new API key...');
51
+ try {
52
+ creds = await l1Client.createApiKey();
53
+ }
54
+ catch (createError) {
55
+ console.error('Failed to both derive and create API key:', createError?.message || createError);
56
+ throw new Error('Authentication failed: Could not create or derive API key.');
57
+ }
58
+ }
59
+ if (!creds) {
60
+ throw new Error('Authentication failed: Credentials are empty.');
61
+ }
62
+ this.apiCreds = creds;
63
+ return creds;
64
+ }
65
+ /**
66
+ * Get an authenticated CLOB client for L2 operations (trading).
67
+ * This client can place orders, cancel orders, query positions, etc.
68
+ */
69
+ async getClobClient() {
70
+ // Return cached client if available
71
+ if (this.clobClient) {
72
+ return this.clobClient;
73
+ }
74
+ // Get API credentials (L1 auth)
75
+ const apiCreds = await this.getApiCredentials();
76
+ // Determine signature type (default to EOA = 0)
77
+ const signatureType = this.credentials.signatureType ?? 0;
78
+ // Determine funder address (defaults to signer's address)
79
+ const funderAddress = this.credentials.funderAddress ?? this.signer.address;
80
+ // Create L2-authenticated client
81
+ this.clobClient = new clob_client_1.ClobClient(POLYMARKET_HOST, POLYGON_CHAIN_ID, this.signer, apiCreds, signatureType, funderAddress);
82
+ return this.clobClient;
83
+ }
84
+ /**
85
+ * Get the signer's address.
86
+ */
87
+ getAddress() {
88
+ return this.signer.address;
89
+ }
90
+ /**
91
+ * Reset cached credentials and client (useful for testing or credential rotation).
92
+ */
93
+ reset() {
94
+ this.apiCreds = undefined;
95
+ this.clobClient = undefined;
96
+ }
97
+ }
98
+ exports.PolymarketAuth = PolymarketAuth;
@@ -0,0 +1,3 @@
1
+ import { MarketFilterParams } from '../../BaseExchange';
2
+ import { UnifiedMarket } from '../../types';
3
+ export declare function fetchMarkets(params?: MarketFilterParams): Promise<UnifiedMarket[]>;
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.fetchMarkets = fetchMarkets;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const utils_1 = require("./utils");
9
+ async function fetchMarkets(params) {
10
+ const limit = params?.limit || 200; // Higher default for better coverage
11
+ const offset = params?.offset || 0;
12
+ // Map generic sort params to Polymarket Gamma API params
13
+ let queryParams = {
14
+ active: 'true',
15
+ closed: 'false',
16
+ limit: limit,
17
+ offset: offset,
18
+ };
19
+ // Gamma API uses 'order' and 'ascending' for sorting
20
+ if (params?.sort === 'volume') {
21
+ queryParams.order = 'volume';
22
+ queryParams.ascending = 'false';
23
+ }
24
+ else if (params?.sort === 'newest') {
25
+ queryParams.order = 'startDate';
26
+ queryParams.ascending = 'false';
27
+ }
28
+ else if (params?.sort === 'liquidity') {
29
+ // queryParams.order = 'liquidity';
30
+ }
31
+ else {
32
+ // Default: do not send order param to avoid 422
33
+ }
34
+ try {
35
+ // Fetch active events from Gamma
36
+ const response = await axios_1.default.get(utils_1.GAMMA_API_URL, {
37
+ params: queryParams
38
+ });
39
+ const events = response.data;
40
+ const unifiedMarkets = [];
41
+ for (const event of events) {
42
+ // Each event is a container (e.g. "US Election").
43
+ // It contains specific "markets" (e.g. "Winner", "Pop Vote").
44
+ if (!event.markets)
45
+ continue;
46
+ for (const market of event.markets) {
47
+ const unifiedMarket = (0, utils_1.mapMarketToUnified)(event, market);
48
+ if (unifiedMarket) {
49
+ unifiedMarkets.push(unifiedMarket);
50
+ }
51
+ }
52
+ }
53
+ // Client-side Sort capability to ensure contract fulfillment
54
+ // Often API filters are "good effort" or apply to the 'event' but not the 'market'
55
+ if (params?.sort === 'volume') {
56
+ unifiedMarkets.sort((a, b) => b.volume24h - a.volume24h);
57
+ }
58
+ else if (params?.sort === 'newest') {
59
+ // unifiedMarkets.sort((a, b) => b.resolutionDate.getTime() - a.resolutionDate.getTime()); // Not quite 'newest'
60
+ }
61
+ else if (params?.sort === 'liquidity') {
62
+ unifiedMarkets.sort((a, b) => b.liquidity - a.liquidity);
63
+ }
64
+ else {
65
+ // Default volume sort
66
+ unifiedMarkets.sort((a, b) => b.volume24h - a.volume24h);
67
+ }
68
+ // Respect limit strictly after flattening
69
+ return unifiedMarkets.slice(0, limit);
70
+ }
71
+ catch (error) {
72
+ console.error("Error fetching Polymarket data:", error);
73
+ return [];
74
+ }
75
+ }
@@ -0,0 +1,7 @@
1
+ import { HistoryFilterParams } from '../../BaseExchange';
2
+ import { PriceCandle } from '../../types';
3
+ /**
4
+ * Fetch historical price data (OHLCV candles) for a specific token.
5
+ * @param id - The CLOB token ID (e.g., outcome token ID)
6
+ */
7
+ export declare function fetchOHLCV(id: string, params: HistoryFilterParams): Promise<PriceCandle[]>;
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.fetchOHLCV = fetchOHLCV;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const utils_1 = require("./utils");
9
+ /**
10
+ * Fetch historical price data (OHLCV candles) for a specific token.
11
+ * @param id - The CLOB token ID (e.g., outcome token ID)
12
+ */
13
+ async function fetchOHLCV(id, params) {
14
+ // ID Validation: Polymarket CLOB requires a Token ID (long numeric string) not a Market ID
15
+ if (id.length < 10 && /^\d+$/.test(id)) {
16
+ throw new Error(`Invalid ID for Polymarket history: "${id}". You provided a Market ID, but Polymarket's CLOB API requires a Token ID. Ensure you are using 'outcome.id'.`);
17
+ }
18
+ try {
19
+ const fidelity = (0, utils_1.mapIntervalToFidelity)(params.resolution);
20
+ const nowTs = Math.floor(Date.now() / 1000);
21
+ // 1. Smart Lookback Calculation
22
+ // If start/end not provided, calculate window based on limit * resolution
23
+ let startTs = params.start ? Math.floor(params.start.getTime() / 1000) : 0;
24
+ let endTs = params.end ? Math.floor(params.end.getTime() / 1000) : nowTs;
25
+ if (!params.start) {
26
+ // Default limit is usually 20 in the example, but safety margin is good.
27
+ // If limit is not set, we default to 100 candles.
28
+ const count = params.limit || 100;
29
+ // fidelity is in minutes.
30
+ const durationSeconds = count * fidelity * 60;
31
+ startTs = endTs - durationSeconds;
32
+ }
33
+ const queryParams = {
34
+ market: id,
35
+ fidelity: fidelity,
36
+ startTs: startTs,
37
+ endTs: endTs
38
+ };
39
+ const response = await axios_1.default.get(`${utils_1.CLOB_API_URL}/prices-history`, {
40
+ params: queryParams
41
+ });
42
+ const history = response.data.history || [];
43
+ // 2. Align Timestamps (Snap to Grid)
44
+ // Polymarket returns random tick timestamps (e.g. 1:00:21).
45
+ // We want to normalize this to the start of the bucket (1:00:00).
46
+ const resolutionMs = fidelity * 60 * 1000;
47
+ const candles = history.map((item) => {
48
+ const rawMs = item.t * 1000;
49
+ const snappedMs = Math.floor(rawMs / resolutionMs) * resolutionMs;
50
+ return {
51
+ timestamp: snappedMs, // Aligned timestamp
52
+ open: item.p,
53
+ high: item.p,
54
+ low: item.p,
55
+ close: item.p,
56
+ volume: undefined
57
+ };
58
+ });
59
+ // Apply limit if specified
60
+ if (params.limit && candles.length > params.limit) {
61
+ return candles.slice(-params.limit);
62
+ }
63
+ return candles;
64
+ }
65
+ catch (error) {
66
+ if (axios_1.default.isAxiosError(error) && error.response) {
67
+ const apiError = error.response.data?.error || error.response.data?.message || "Unknown API Error";
68
+ throw new Error(`Polymarket History API Error (${error.response.status}): ${apiError}. Used ID: ${id}`);
69
+ }
70
+ console.error(`Unexpected error fetching Polymarket history for ${id}:`, error);
71
+ throw error;
72
+ }
73
+ }
@@ -0,0 +1,6 @@
1
+ import { OrderBook } from '../../types';
2
+ /**
3
+ * Fetch the current order book for a specific token.
4
+ * @param id - The CLOB token ID
5
+ */
6
+ export declare function fetchOrderBook(id: string): Promise<OrderBook>;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.fetchOrderBook = fetchOrderBook;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const utils_1 = require("./utils");
9
+ /**
10
+ * Fetch the current order book for a specific token.
11
+ * @param id - The CLOB token ID
12
+ */
13
+ async function fetchOrderBook(id) {
14
+ try {
15
+ const response = await axios_1.default.get(`${utils_1.CLOB_API_URL}/book`, {
16
+ params: { token_id: id }
17
+ });
18
+ const data = response.data;
19
+ // Response format: { bids: [{price: "0.52", size: "100"}], asks: [...] }
20
+ const bids = (data.bids || []).map((level) => ({
21
+ price: parseFloat(level.price),
22
+ size: parseFloat(level.size)
23
+ })).sort((a, b) => b.price - a.price); // Sort Bids Descending (Best/Highest first)
24
+ const asks = (data.asks || []).map((level) => ({
25
+ price: parseFloat(level.price),
26
+ size: parseFloat(level.size)
27
+ })).sort((a, b) => a.price - b.price); // Sort Asks Ascending (Best/Lowest first)
28
+ return {
29
+ bids,
30
+ asks,
31
+ timestamp: data.timestamp ? new Date(data.timestamp).getTime() : Date.now()
32
+ };
33
+ }
34
+ catch (error) {
35
+ console.error(`Error fetching Polymarket orderbook for ${id}:`, error);
36
+ return { bids: [], asks: [] };
37
+ }
38
+ }
@@ -0,0 +1,2 @@
1
+ import { Position } from '../../types';
2
+ export declare function fetchPositions(userAddress: string): Promise<Position[]>;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.fetchPositions = fetchPositions;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const DATA_API_URL = 'https://data-api.polymarket.com';
9
+ async function fetchPositions(userAddress) {
10
+ const response = await axios_1.default.get(`${DATA_API_URL}/positions`, {
11
+ params: {
12
+ user: userAddress,
13
+ limit: 100
14
+ }
15
+ });
16
+ const data = Array.isArray(response.data) ? response.data : [];
17
+ return data.map((p) => ({
18
+ marketId: p.conditionId,
19
+ outcomeId: p.asset,
20
+ outcomeLabel: p.outcome || 'Unknown',
21
+ size: parseFloat(p.size),
22
+ entryPrice: parseFloat(p.avgPrice),
23
+ currentPrice: parseFloat(p.curPrice || '0'),
24
+ unrealizedPnL: parseFloat(p.cashPnl || '0'),
25
+ realizedPnL: parseFloat(p.realizedPnl || '0')
26
+ }));
27
+ }
@@ -0,0 +1,11 @@
1
+ import { HistoryFilterParams } from '../../BaseExchange';
2
+ import { Trade } from '../../types';
3
+ /**
4
+ * Fetch raw trade history for a specific token.
5
+ * @param id - The CLOB token ID
6
+ *
7
+ * NOTE: Polymarket's /trades endpoint currently requires L2 Authentication (API Key).
8
+ * This method will return an empty array if an API key is not provided in headers.
9
+ * Use fetchOHLCV for public historical price data instead.
10
+ */
11
+ export declare function fetchTrades(id: string, params: HistoryFilterParams): Promise<Trade[]>;
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.fetchTrades = fetchTrades;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const utils_1 = require("./utils");
9
+ /**
10
+ * Fetch raw trade history for a specific token.
11
+ * @param id - The CLOB token ID
12
+ *
13
+ * NOTE: Polymarket's /trades endpoint currently requires L2 Authentication (API Key).
14
+ * This method will return an empty array if an API key is not provided in headers.
15
+ * Use fetchOHLCV for public historical price data instead.
16
+ */
17
+ async function fetchTrades(id, params) {
18
+ // ID Validation
19
+ if (id.length < 10 && /^\d+$/.test(id)) {
20
+ throw new Error(`Invalid ID for Polymarket trades: "${id}". You provided a Market ID, but Polymarket's CLOB API requires a Token ID.`);
21
+ }
22
+ try {
23
+ const queryParams = {
24
+ market: id
25
+ };
26
+ // Add time filters if provided
27
+ if (params.start) {
28
+ queryParams.after = Math.floor(params.start.getTime() / 1000);
29
+ }
30
+ if (params.end) {
31
+ queryParams.before = Math.floor(params.end.getTime() / 1000);
32
+ }
33
+ const response = await axios_1.default.get(`${utils_1.CLOB_API_URL}/trades`, {
34
+ params: queryParams
35
+ });
36
+ // Response is an array of trade objects
37
+ const trades = response.data || [];
38
+ const mappedTrades = trades.map((trade) => ({
39
+ id: trade.id || `${trade.timestamp}-${trade.price}`,
40
+ timestamp: trade.timestamp * 1000, // Convert to milliseconds
41
+ price: parseFloat(trade.price),
42
+ amount: parseFloat(trade.size || trade.amount || 0),
43
+ side: trade.side === 'BUY' ? 'buy' : trade.side === 'SELL' ? 'sell' : 'unknown'
44
+ }));
45
+ // Apply limit if specified
46
+ if (params.limit && mappedTrades.length > params.limit) {
47
+ return mappedTrades.slice(-params.limit); // Return most recent N trades
48
+ }
49
+ return mappedTrades;
50
+ }
51
+ catch (error) {
52
+ if (axios_1.default.isAxiosError(error) && error.response) {
53
+ const apiError = error.response.data?.error || error.response.data?.message || "Unknown API Error";
54
+ throw new Error(`Polymarket Trades API Error (${error.response.status}): ${apiError}. Used ID: ${id}`);
55
+ }
56
+ console.error(`Unexpected error fetching Polymarket trades for ${id}:`, error);
57
+ throw error;
58
+ }
59
+ }
@@ -0,0 +1,7 @@
1
+ import { UnifiedMarket } from '../../types';
2
+ /**
3
+ * Fetch specific markets by their URL slug.
4
+ * Useful for looking up a specific event from a URL.
5
+ * @param slug - The event slug (e.g. "will-fed-cut-rates-in-march")
6
+ */
7
+ export declare function getMarketsBySlug(slug: string): Promise<UnifiedMarket[]>;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getMarketsBySlug = getMarketsBySlug;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const utils_1 = require("./utils");
9
+ /**
10
+ * Fetch specific markets by their URL slug.
11
+ * Useful for looking up a specific event from a URL.
12
+ * @param slug - The event slug (e.g. "will-fed-cut-rates-in-march")
13
+ */
14
+ async function getMarketsBySlug(slug) {
15
+ try {
16
+ const response = await axios_1.default.get(utils_1.GAMMA_API_URL, {
17
+ params: { slug: slug }
18
+ });
19
+ const events = response.data;
20
+ if (!events || events.length === 0)
21
+ return [];
22
+ const unifiedMarkets = [];
23
+ for (const event of events) {
24
+ if (!event.markets)
25
+ continue;
26
+ for (const market of event.markets) {
27
+ const unifiedMarket = (0, utils_1.mapMarketToUnified)(event, market, { useQuestionAsCandidateFallback: true });
28
+ if (unifiedMarket) {
29
+ unifiedMarkets.push(unifiedMarket);
30
+ }
31
+ }
32
+ }
33
+ return unifiedMarkets;
34
+ }
35
+ catch (error) {
36
+ console.error(`Error fetching Polymarket slug ${slug}:`, error);
37
+ return [];
38
+ }
39
+ }
@@ -0,0 +1,23 @@
1
+ import { PredictionMarketExchange, MarketFilterParams, HistoryFilterParams, ExchangeCredentials } from '../../BaseExchange';
2
+ import { UnifiedMarket, PriceCandle, OrderBook, Trade, Order, Position, Balance, CreateOrderParams } from '../../types';
3
+ export declare class PolymarketExchange extends PredictionMarketExchange {
4
+ private auth?;
5
+ constructor(credentials?: ExchangeCredentials);
6
+ get name(): string;
7
+ fetchMarkets(params?: MarketFilterParams): Promise<UnifiedMarket[]>;
8
+ searchMarkets(query: string, params?: MarketFilterParams): Promise<UnifiedMarket[]>;
9
+ getMarketsBySlug(slug: string): Promise<UnifiedMarket[]>;
10
+ fetchOHLCV(id: string, params: HistoryFilterParams): Promise<PriceCandle[]>;
11
+ fetchOrderBook(id: string): Promise<OrderBook>;
12
+ fetchTrades(id: string, params: HistoryFilterParams): Promise<Trade[]>;
13
+ /**
14
+ * Ensure authentication is initialized before trading operations.
15
+ */
16
+ private ensureAuth;
17
+ createOrder(params: CreateOrderParams): Promise<Order>;
18
+ cancelOrder(orderId: string): Promise<Order>;
19
+ fetchOrder(orderId: string): Promise<Order>;
20
+ fetchOpenOrders(marketId?: string): Promise<Order[]>;
21
+ fetchPositions(): Promise<Position[]>;
22
+ fetchBalance(): Promise<Balance[]>;
23
+ }