A unified interface for interacting with multiple prediction market exchanges (Kalshi, Polymarket) identically.
npm install pmxtjsimport pmxt from 'pmxtjs';
const poly = new pmxt.Polymarket();
const kalshi = new pmxt.Kalshi();pmxt is currently CommonJS-only. If you're using "type": "module" in your package.json, you have two options:
Option 1: Default import (recommended)
import pmxt from 'pmxtjs';
const poly = new pmxt.Polymarket();Option 2: Dynamic import
const pmxt = await import('pmxtjs');
const poly = new pmxt.default.Polymarket();Note: Named exports like import { Polymarket } from 'pmxtjs' will not work in ESM projects.
Get active markets from an exchange. This is the unified method for all market fetching operations.
Parameters:
limit: Number of results (default: 20)offset: Pagination offsetsort: 'volume' | 'liquidity' | 'newest'query: Search text (replacessearchMarkets)slug: Market slug or ticker (replacesgetMarketsBySlug)
// 1. Fetch recent markets
const markets = await polymarket.fetchMarkets({
limit: 20,
sort: 'volume'
});
// 2. Search by text (replaces searchMarkets)
const results = await kalshi.fetchMarkets({
query: 'Fed rates',
limit: 10
});
// 3. Fetch by slug/ticker (replaces getMarketsBySlug)
const market = await polymarket.fetchMarkets({
slug: 'who-will-trump-nominate-as-fed-chair'
});Get events (groups of related markets). Unified method for event fetching.
Parameters:
query: Search textlimit: Number of resultsoffset: Pagination offset
// Search for events
const events = await polymarket.fetchEvents({
query: 'Fed Chair',
limit: 5
});Get historical price candles.
CRITICAL: Use outcome.outcomeId, not market.marketId.
- Polymarket:
outcome.outcomeIdis the CLOB Token ID - Kalshi:
outcome.outcomeIdis the Market Ticker
const markets = await polymarket.fetchMarkets({ query: 'Trump' });
const outcomeId = markets[0].outcomes[0].outcomeId; // Get the outcome ID
const candles = await polymarket.fetchOHLCV(outcomeId, {
resolution: '1h', // '1m' | '5m' | '15m' | '1h' | '6h' | '1d'
start: new Date('2024-01-01'),
end: new Date('2024-01-31'),
limit: 100
});Get current bids/asks.
const orderBook = await kalshi.fetchOrderBook('FED-25JAN');
console.log('Best bid:', orderBook.bids[0].price);
console.log('Best ask:', orderBook.asks[0].price);Get trade history.
Note: Polymarket requires API key. Use fetchOHLCV for public historical data.
const trades = await kalshi.fetchTrades('FED-25JAN', {
limit: 100
});Calculate the volume-weighted average price for a given amount. Returns 0 if there is insufficient liquidity to fully fill the amount.
const orderBook = await polymarket.fetchOrderBook(outcomeId);
const price = await polymarket.getExecutionPrice(orderBook, 'buy', 100);
console.log(`Average price for 100 shares: ${price}`);Calculate detailed execution price information, including partial fills.
const detailed = await polymarket.getExecutionPriceDetailed(orderBook, 'buy', 100);
console.log(`Average Price: ${detailed.price}`);
console.log(`Filled Amount: ${detailed.filledAmount}`);
console.log(`Fully Filled: ${detailed.fullyFilled}`);{
marketId: string; // Market ID (use this for createOrder)
title: string;
description: string;
outcomes: MarketOutcome[]; // All tradeable outcomes
resolutionDate: Date;
volume24h: number; // USD
volume?: number; // Total volume (USD)
liquidity: number; // USD
openInterest?: number; // USD
url: string;
image?: string;
category?: string;
tags?: string[];
}{
outcomeId: string; // Use this for fetchOHLCV/fetchOrderBook/fetchTrades
// Polymarket: CLOB Token ID
// Kalshi: Market Ticker
label: string; // "Trump", "Yes", etc.
price: number; // 0.0 to 1.0 (probability)
priceChange24h?: number;
metadata?: {
clobTokenId?: string; // Polymarket only
}
}interface PriceCandle {
timestamp: number; // Unix ms
open: number; // 0.0 to 1.0
high: number;
low: number;
close: number;
volume?: number;
}
interface OrderBook {
bids: OrderLevel[]; // Sorted high to low
asks: OrderLevel[]; // Sorted low to high
timestamp?: number;
}
interface OrderLevel {
price: number; // 0.0 to 1.0
size: number; // Contracts
}
interface Trade {
id: string;
timestamp: number; // Unix ms
price: number; // 0.0 to 1.0
amount: number;
side: 'buy' | 'sell' | 'unknown';
}
interface ExecutionPriceResult {
price: number; // Average execution price
filledAmount: number; // Amount filled (shares)
fullyFilled: boolean; // If the requested amount was met
}// 1. Search for markets
const markets = await polymarket.fetchMarkets({ query: 'Fed Chair' });
const market = markets[0];
// 2. Get outcome details
const outcome = market.outcomes[0];
console.log(`${outcome.label}: ${(outcome.price * 100).toFixed(1)}%`);
// 3. Fetch historical data (use outcome.outcomeId!)
const candles = await polymarket.fetchOHLCV(outcome.outcomeId, {
resolution: '1d',
limit: 30
});
// 4. Get current order book
const orderBook = await polymarket.fetchOrderBook(outcome.outcomeId);
const spread = orderBook.asks[0].price - orderBook.bids[0].price;
console.log(`Spread: ${(spread * 100).toFixed(2)}%`);| Feature | Polymarket | Kalshi |
|---|---|---|
| Sorting | Server-side | Client-side (slower for large sets) |
| Market ID | UUID | Event Ticker (e.g., "PRES-2024") |
| Outcome ID | CLOB Token ID | Market Ticker (e.g., "FED-25JAN") |
| OHLCV Quality | Synthetic (O=H=L=C) | Native (distinct values) |
| Auth Required | Only for fetchTrades() |
No (all public) |
| Slug Format | lowercase-with-hyphens | UPPERCASE (auto-normalized) |
try {
const markets = await kalshi.getMarketsBySlug('INVALID-TICKER');
} catch (error) {
// Kalshi: "Event not found: INVALID-TICKER"
// Polymarket: Returns empty array []
console.error(error.message);
}Common Errors:
404: Market/event doesn't exist401: Missing API key (PolymarketfetchTrades)429: Rate limited500: Exchange API issue
import pmxt, {
UnifiedMarket,
MarketOutcome,
PriceCandle,
OrderBook,
Trade,
CandleInterval,
MarketFilterParams,
HistoryFilterParams
} from 'pmxtjs';Both Polymarket and Kalshi support authenticated trading operations. You must provide credentials when initializing the exchange.
Requires your Polygon Private Key. See Setup Guide for details.
import pmxt from 'pmxtjs';
const polymarket = new pmxt.Polymarket({
privateKey: process.env.POLYMARKET_PRIVATE_KEY,
funderAddress: process.env.POLYMARKET_PROXY_ADDRESS, // Optional: Proxy address
signatureType: 'gnosis-safe' // 'eoa' | 'poly-proxy' | 'gnosis-safe'
});Requires API Key and Private Key.
import pmxt from 'pmxtjs';
const kalshi = new pmxt.Kalshi({
apiKey: process.env.KALSHI_API_KEY,
privateKey: process.env.KALSHI_PRIVATE_KEY
});Get your account balance.
const balances = await polymarket.fetchBalance();
console.log(balances);
// [{ currency: 'USDC', total: 1000, available: 950, locked: 50 }]Returns: Balance[]
interface Balance {
currency: string; // e.g., 'USDC'
total: number; // Total balance
available: number; // Available for trading
locked: number; // Locked in open orders
}Get your current positions across all markets.
const positions = await kalshi.fetchPositions();
positions.forEach(pos => {
console.log(`${pos.outcomeLabel}: ${pos.size} @ $${pos.entryPrice}`);
console.log(`Unrealized P&L: $${pos.unrealizedPnL}`);
});Returns: Position[]
interface Position {
marketId: string;
outcomeId: string;
outcomeLabel: string;
size: number; // Positive for long, negative for short
entryPrice: number;
currentPrice: number;
unrealizedPnL: number;
realizedPnL?: number;
}Place a new order (market or limit).
Limit Order Example:
const order = await polymarket.createOrder({
marketId: '663583',
outcomeId: '10991849228756847439673778874175365458450913336396982752046655649803657501964',
side: 'buy',
type: 'limit',
amount: 10, // Number of contracts
price: 0.55 // Required for limit orders (0.0-1.0)
});
console.log(`Order ${order.id}: ${order.status}`);Market Order Example:
const order = await kalshi.createOrder({
marketId: 'FED-25JAN',
outcomeId: 'FED-25JAN-YES',
side: 'sell',
type: 'market',
amount: 5 // Price not needed for market orders
});Parameters: CreateOrderParams
interface CreateOrderParams {
marketId: string; // Use market.marketId from market data
outcomeId: string; // Use outcome.outcomeId from market data
side: 'buy' | 'sell';
type: 'market' | 'limit';
amount: number; // Number of contracts/shares
price?: number; // Required for limit orders (0.0-1.0)
}Returns: Order
interface Order {
id: string;
marketId: string;
outcomeId: string;
side: 'buy' | 'sell';
type: 'market' | 'limit';
price?: number;
amount: number;
status: 'pending' | 'open' | 'filled' | 'cancelled' | 'rejected';
filled: number; // Amount filled so far
remaining: number; // Amount remaining
timestamp: number;
fee?: number;
}Cancel an open order.
const cancelledOrder = await polymarket.cancelOrder('order-123');
console.log(cancelledOrder.status); // 'cancelled'Returns: Order (with updated status)
Get details of a specific order.
const order = await kalshi.fetchOrder('order-456');
console.log(`Filled: ${order.filled}/${order.amount}`);Returns: Order
Get all open orders, optionally filtered by market.
// All open orders
const allOrders = await polymarket.fetchOpenOrders();
// Open orders for specific market
const marketOrders = await kalshi.fetchOpenOrders('FED-25JAN');
allOrders.forEach(order => {
console.log(`${order.side} ${order.amount} @ ${order.price}`);
});Returns: Order[]
import pmxt from 'pmxtjs';
const exchange = new pmxt.Polymarket({
privateKey: process.env.POLYMARKET_PRIVATE_KEY
});
// 1. Check balance
const [balance] = await exchange.fetchBalance();
console.log(`Available: $${balance.available}`);
// 2. Search for a market
const markets = await exchange.fetchMarkets({ query: 'Trump' });
const market = markets[0];
const outcome = market.outcomes[0];
// 3. Place a limit order
const order = await exchange.createOrder({
marketId: market.marketId,
outcomeId: outcome.outcomeId,
side: 'buy',
type: 'limit',
amount: 10,
price: 0.50
});
console.log(`Order placed: ${order.id}`);
// 4. Check order status
const updatedOrder = await exchange.fetchOrder(order.id);
console.log(`Status: ${updatedOrder.status}`);
console.log(`Filled: ${updatedOrder.filled}/${updatedOrder.amount}`);
// 5. Cancel if needed
if (updatedOrder.status === 'open') {
await exchange.cancelOrder(order.id);
console.log('Order cancelled');
}
// 6. Check positions
const positions = await exchange.fetchPositions();
positions.forEach(pos => {
console.log(`${pos.outcomeLabel}: ${pos.unrealizedPnL > 0 ? '+' : ''}$${pos.unrealizedPnL.toFixed(2)}`);
});- Prices: Always 0.0-1.0 (multiply by 100 for %)
- Timestamps: Unix milliseconds
- Volumes: USD
- IDs: Use
outcome.outcomeIdfor deep-dive methods (fetchOHLCV, fetchOrderBook, fetchTrades), andmarket.marketIdfor trading operations - Authentication: Required for all trading and account methods
For more examples, see examples/.