A TypeScript SDK for interacting with the Prob prediction market platform. This SDK provides a comprehensive interface for trading, managing positions, querying market data, and more.
npm install @prob/coreA TypeScript SDK for interacting with the Prob prediction market platform. This SDK provides a comprehensive interface for trading, managing positions, querying market data, and more.
- Order Management: Create, sign, submit, and cancel limit and market orders
- Market Data: Query orderbooks, prices, price history, and market information
- Position Management: Query, split, merge, and redeem positions
- Trade History: Access trading activity, PnL, and trade records
- Event & Market Queries: Search and retrieve events and markets
- Authentication: Support for L1 (wallet signature), L2 (API key)
- Safe Proxy Wallet: Built-in support for Safe proxy wallet operations
To use this SDK in your project, install the main package:
``bashUsing pnpm
pnpm add @prob/clob
Package Structure
This is a monorepo containing three main packages:
-
@prob/clob: Main SDK package for CLOB (Central Limit Order Book) operations
- @prob/core: Core utilities including exchange configs, ABIs, and token operations
- @prob/types: TypeScript type definitions shared across packagesQuick Start
$3
First, create a wallet client and then create the CLOB client:
`typescript
import { createWalletClient, http } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { bscTestnet } from 'viem/chains'
import { createClobClient } from '@prob/clob'// Create a wallet client
const account = privateKeyToAccount('0x...' as
0x${string})
const wallet = createWalletClient({
chain: bscTestnet,
transport: http(),
account: account,
})// Create the CLOB client
const client = createClobClient({
baseUrl: '...',
chainId: bscTestnet.id,
wallet: wallet,
})
// For methods that require authentication (order operations, trades, etc.),
// generate an API key first. The API key will be automatically stored in the client.
await client.generateApiKey()
`Note:
- L1 authentication (wallet signature) is automatically handled when you provide a
wallet to the client.
- Methods that use l1AuthHttpClient or l2AuthHttpClient require calling generateApiKey() first. These include:
- Order operations: postOrder, postOrders, getOrder, getOpenOrders, cancelOrder, cancelOrders, cancelAllOrders
- Trade operations: getTrades
- API key management: getApiKey, deleteApiKey
- Info: getTokenIdsForEvent
- Public methods (like getMarkets, getOrderBook, getEvents) don't require authentication.$3
`typescript
// Get markets (public, no authentication required)
const markets = await client.getMarkets({ eventId: '162' })// Get orderbook (public, no authentication required)
const orderbook = await client.getOrderBook({
tokenId: '74342822607920627529671190134784974807193804148539661920621719393105547397621',
})
// Get current positions (requires authentication, ensure generateApiKey() was called)
const positions = await client.getCurrentPositions({ eventId: '162' })
`Main API Usage Examples
$3
#### Fee
actually we have fees on order, can see the details here and api docs
can calculate fee through this function
`typescriptconst limitOrder = await client.createLimitOrder({...})
const marketOrder = await client.createMarketOrder({...})
const feeAmount = client.calculateFee(limitOrder)
const feeAmount = client.calculateFee(marketOrder, pricePerShare)
`#### Create and Submit a Limit Order
`typescript
import { OrderSide, LimitTimeInForce } from '@prob/clob'const order = await client.createLimitOrder({
tokenId: '74342822607920627529671190134784974807193804148539661920621719393105547397621',
price: 0.6,
size: 100,
side: OrderSide.Buy,
timeInForce: LimitTimeInForce.GTC,
})
const { orderId } = await client.postOrder(order)
console.log('Order created:', orderId)
`#### Create and Submit a Market Order
`typescript
const marketOrder = await client.createMarketOrder({
tokenId: '74342822607920627529671190134784974807193804148539661920621719393105547397621',
size: 100,
side: OrderSide.Buy,
})await client.postOrder(marketOrder)
`#### Get Open Orders
`typescript
// Get all open orders for an event
const openOrders = await client.getOpenOrders({ eventId: '162' })// Get open orders for specific tokens
const tokenOrders = await client.getOpenOrders({
tokenIds: [
'74342822607920627529671190134784974807193804148539661920621719393105547397621',
],
})
// Get a specific order
const order = await client.getOrder({
orderId: '123',
tokenId: '74342822607920627529671190134784974807193804148539661920621719393105547397621',
})
`#### Cancel Orders
`typescript
// Cancel a single order
await client.cancelOrder({ orderId: '123', tokenId: '...' })// Cancel multiple orders
await client.cancelOrders({
tokenId: '...',
orderIds: ['123', '456'],
})
// Cancel all orders
await client.cancelAllOrders({ eventId: '162' })
`$3
#### Get Prices
`typescript
// Get current price for a token
const price = await client.getPrice({
tokenId: '74342822607920627529671190134784974807193804148539661920621719393105547397621',
})// Get prices for multiple tokens
const prices = await client.getPrices({
tokenIds: [
'74342822607920627529671190134784974807193804148539661920621719393105547397621',
'109502175175535116549611025410934749011537522542042437183890832452933730647182',
],
})
// Get price history
const priceHistory = await client.getPricesHistory({
tokenId: '74342822607920627529671190134784974807193804148539661920621719393105547397621',
startTime: Date.now() - 86400000, // 24 hours ago
endTime: Date.now(),
})
`#### Get Orderbook
`typescript
const orderbook = await client.getOrderBook({
tokenId: '74342822607920627529671190134784974807193804148539661920621719393105547397621',
})
`#### Get Midpoint Price
`typescript
const midpoint = await client.getMidpoint({
tokenId: '74342822607920627529671190134784974807193804148539661920621719393105547397621',
})
`$3
#### Get Positions
`typescript
// Get current positions
const currentPositions = await client.getCurrentPositions({ eventId: '162' })// Get closed positions
const closedPositions = await client.getClosedPositions({ eventId: '162' })
// Get pending positions
const pendingPositions = await client.getPendingPositions({ eventId: '162' })
// Get position value
const positionValue = await client.getPositionValue({ eventId: '162' })
`#### Split Position
`typescript
const conditionId = '0x3614ed5aa3d8ab73edd3364541f8c1c48104aa7d0bb081ed51f0f634edd8dad9'
const txHash = await client.splitPosition({
conditionId,
formattedAmount: '1',
})
`#### Merge Position
`typescript
const conditionId = '0x3614ed5aa3d8ab73edd3364541f8c1c48104aa7d0bb081ed51f0f634edd8dad9'
const mergeTxHash = await client.mergePosition({
conditionId,
formattedAmount: '1',
})
`#### Redeem Position
`typescript
const conditionId = '0x3614ed5aa3d8ab73edd3364541f8c1c48104aa7d0bb081ed51f0f634edd8dad9'
const redeemTxHash = await client.redeemPosition({
conditionId,
})
`$3
#### Get Trading Activity
`typescript
const activity = await client.getActivity({ eventId: '162' })
`#### Get PnL (Profit and Loss)
`typescript
const pnl = await client.getPnL({ eventId: '162' })
`#### Get Trades
`typescript
const trades = await client.getTrades({ eventId: '162' })
`$3
#### Get Events
`typescript
const events = await client.getEvents({ limit: 10 })
`#### Get Event by ID or Slug
`typescript
const event = await client.getEventById({ eventId: '162' })
const eventBySlug = await client.getEventBySlug({ slug: 'event-slug' })
`#### Get Markets
`typescript
const markets = await client.getMarkets({ eventId: '162' })
const market = await client.getMarketById({ marketId: '123' })
`#### Search
`typescript
const results = await client.search({ query: 'bitcoin' })
`$3
#### Subscribe to Stream Data
`typescript
// Create client with wsUrl for WebSocket stream data
const client = createClobClient({
baseUrl: 'https://api.probable.markets/public/api/v1',
wsUrl: 'wss://ws.probable.markets/public/api/v1',
chainId: 56,
wallet: wallet,
})await client.generateApiKey()
const subscription = client.subscribeStreamData('executionReport', (data) => {
console.log('Order ID:', data.i)
console.log('Status:', data.X)
console.log('Side:', data.S)
console.log('Token ID:', data.ct)
})
subscription.on('ready', (data) => {
console.log('WebSocket ready, listenKey:', data?.listenKey)
})
subscription.on('error', (error) => {
console.error('WebSocket error:', error)
})
subscription.on('authError', (error) => {
// if api key is wrong, will auto retry 3 times then emit this event
// if call reconnect it will continue retry 3 times, and pls ensure wallet & api key get is right.
console.error('Auth error:', error)
subscription.reconnect()
})
subscription.on('close', () => {
console.log('WebSocket closed')
})
subscription.unsubscribe()
`Parameters:
-
eventType: 'executionReport' - The type of event to subscribe to
- handler: (data: ExecutionReportEvent) => void - Callback function to handle eventsEvents:
-
ready: Emitted when WebSocket is connected and authenticated. Returns { listenKey: string }
- error: Emitted when a WebSocket error occurs. Returns Error
- authError: Emitted when authentication fails after maximum retries. Returns Error
- close: Emitted when WebSocket connection is closedMethods:
-
unsubscribe(): Unsubscribe from the stream
- reconnect(): Manually reconnect the WebSocket, should ensure api key is rightEvent Types:
##### ExecutionReportEvent
`typescript
interface ExecutionReportEvent {
e: 'executionReport' // Event type
E: number // Event time
T: number // Transaction time
u: number // Trade ID
c: string // Client order ID
S: 'BUY' | 'SELL' // Side
o: 'LIMIT' | 'MARKET' // Order type
f: 'GTC' | 'IOC' | 'FOK' // Time in force
x: 'NEW' | 'CANCELED' | 'REPLACED' | 'REJECTED' | 'TRADE' | 'EXPIRED' // Execution type
X: 'NEW' | 'PARTIALLY_FILLED' | 'FILLED' | 'CANCELED' | 'PENDING_CANCEL' | 'REJECTED' | 'EXPIRED' // Order status
i: number // Order ID
t?: number // Trade ID
m: boolean // Is maker
ot: string // Original order type
O: number // Price
ct: string // Token ID
}
`
$3
#### Check if Safe Proxy Wallet Exists
`typescript
const exists = await client.checkSafeProxyWalletExists()
`#### Approve Collateral
`typescript
// Approve collateral if needed (checks current allowance first)
await client.proxyApproveCollateralIfNeeded()// Approve specific amount
await client.proxyApproveCollateral(BigInt(1000e6))
`#### Execute Transaction via Proxy
`typescript
const txHash = await client.proxyExecuteTx({
to: '0x...',
data: '0x...',
value: BigInt(0),
})
`Project Structure
`
prob-sdk/
├── packages/
│ ├── clob/ # Main SDK package
│ │ ├── src/
│ │ │ ├── auth/ # Authentication (L1, L2)
│ │ │ ├── clob/ # CLOB client and API methods
│ │ │ ├── order/ # Order creation and management
│ │ │ ├── positions/ # Position management
│ │ │ ├── price/ # Price and orderbook queries
│ │ │ ├── trades/ # Trade history
│ │ │ └── ...
│ │ └── e2e/ # End-to-end tests
│ ├── core/ # Core utilities
│ │ ├── src/
│ │ │ ├── abis/ # Contract ABIs
│ │ │ ├── constants/ # Exchange configs and addresses
│ │ │ ├── exchange/ # Exchange utilities
│ │ │ ├── token/ # Token operations
│ │ │ └── ...
│ └── types/ # Shared TypeScript types
│ └── src/
├── package.json
└── pnpm-workspace.yaml
`Development
$3
1. Clone the repository
2. Install dependencies:
pnpm install
3. Build all packages: pnpm build$3
-
pnpm lint: Run Biome linter
- pnpm lint:fix: Fix linting issues automatically
- pnpm test: Run tests with Vitest
- pnpm test:watch: Run tests in watch mode
- pnpm build: Build all packages$3
This project uses Biome for code formatting and linting. The configuration is in
biome.jsonc.$3
`bash
Build clob package
pnpm --filter ./packages/clob buildBuild core package
pnpm --filter ./packages/core build
`$3
`bash
Run all tests
pnpm testRun tests for a specific package
pnpm --filter ./packages/clob testRun tests in watch mode
pnpm test:watch
``