polybrainz_polymarket 1.6.1
polybrainz_polymarket: ^1.6.1 copied to clipboard
A comprehensive Dart wrapper for the Polymarket API including Gamma, CLOB, Data APIs and WebSocket streams.
PolyBrainZ Polymarket #
A Comprehensive Dart SDK for Polymarket Prediction Markets #
Full-featured | Type-safe | Real-time WebSocket | Idiot-proof
Features #
| Feature | Description |
|---|---|
| Gamma API | Market discovery, events, tags, comments, profiles, search, leaderboard |
| CLOB API | Order book, pricing, order management, trade history |
| Data API | Positions, trades, activity, holders, portfolio analytics |
| WebSocket | Real-time order book, prices, user notifications |
| Authentication | L1 (EIP-712) and L2 (HMAC-SHA256) support |
| 30+ Type-safe Enums | Every string parameter with known values is a compile-time enum |
| Category Detection | Auto-detect categories from events, markets, and tags |
| Error Handling | Typed exception hierarchy with Result<T, E> support |
Installation #
Add to your pubspec.yaml:
dependencies:
polybrainz_polymarket: ^1.6.1
dart pub get
Quick Start #
Public Client (No Auth Required)
import 'package:polybrainz_polymarket/polybrainz_polymarket.dart';
void main() async {
final client = PolymarketClient.public();
// Get active events
final events = await client.gamma.events.listEvents(
limit: 10,
closed: false,
);
for (final event in events) {
print('${event.title} - ${event.markets.length} markets');
}
// Get order book
final book = await client.clob.orderbook.getOrderBook('token-id');
print('Best bid: ${book.bestBid}, Best ask: ${book.bestAsk}');
client.close();
}
Authenticated Client (For Trading)
import 'package:polybrainz_polymarket/polybrainz_polymarket.dart';
void main() async {
final client = PolymarketClient.authenticated(
credentials: ApiCredentials(
apiKey: 'your-api-key',
secret: 'your-secret',
passphrase: 'your-passphrase',
),
funder: '0xYourWalletAddress',
);
// Get your open orders
final orders = await client.clob.orders.getOpenOrders();
print('You have ${orders.length} open orders');
// Get your positions
final positions = await client.data.positions.getPositions(
userAddress: '0xYourWalletAddress',
);
for (final pos in positions) {
print('${pos.title}: ${pos.size} shares @ ${pos.avgPrice}');
}
client.close();
}
Real-Time WebSocket Streams
import 'package:polybrainz_polymarket/polybrainz_polymarket.dart';
void main() async {
final client = PolymarketClient.public();
await client.clobWebSocket.connect();
// Subscribe to price changes
client.clobWebSocket.subscribeToPriceChanges(['token-id-1', 'token-id-2'])
.listen((msg) {
for (final change in msg.priceChanges) {
print('${change.assetId}: ${change.price}');
}
});
// Subscribe to order book updates
client.clobWebSocket.subscribeToOrderBook('token-id')
.listen((book) {
print('Best bid: ${book.bestBid}, Best ask: ${book.bestAsk}');
});
// Crypto prices via RTDS
await client.rtdsWebSocket.connect(topics: [RtdsTopic.cryptoPrices]);
client.rtdsWebSocket.cryptoPrices.listen((msg) {
print('BTC: ${msg.getPrice('BTC')}, ETH: ${msg.getPrice('ETH')}');
});
}
API Reference #
Client Factories #
| Factory | Description |
|---|---|
PolymarketClient.public() |
Public client, no authentication |
PolymarketClient.authenticated() |
Authenticated client with API credentials |
PolymarketClient.withPrivateKey() |
Client with private key for deriving credentials |
Gamma API (Market Discovery) #
Events & Markets
// Events
final events = await client.gamma.events.listEvents(limit: 100, closed: false);
final event = await client.gamma.events.getById(123);
final event = await client.gamma.events.getBySlug('event-slug');
// Convenience methods
final hotEvents = await client.gamma.events.getHotEvents();
final featuredEvents = await client.gamma.events.getFeaturedEvents();
final endingSoon = await client.gamma.events.getEndingSoon(within: Duration(days: 3));
final politicsEvents = await client.gamma.events.getByTagSlug('politics');
// Markets
final markets = await client.gamma.markets.listMarkets(active: true);
final market = await client.gamma.markets.getByConditionId('condition-id');
final topVolume = await client.gamma.markets.getTopByVolume(limit: 20);
final topLiquidity = await client.gamma.markets.getTopByLiquidity();
Search (Type-Safe Queries)
// Preset queries (60+ available)
final results = await client.gamma.search.search(query: SearchQuery.bitcoin);
final election = await client.gamma.search.search(query: SearchQuery.election);
final nfl = await client.gamma.search.search(query: SearchQuery.nfl);
// Custom queries
final custom = await client.gamma.search.search(
query: SearchQuery.custom('my search'),
);
// Convenience methods
final btcResults = await client.gamma.search.searchBitcoin();
final electionResults = await client.gamma.search.searchElection();
final aiResults = await client.gamma.search.searchAI();
// Browse all presets by category
SearchQuery.cryptoPresets; // [bitcoin, ethereum, solana, ...]
SearchQuery.politicsPresets; // [election, trump, biden, ...]
SearchQuery.sportsPresets; // [nfl, nba, mlb, ...]
Tags, Comments, Profiles
// Tags
final tags = await client.gamma.tags.listTags(order: TagOrderBy.volume);
final related = await client.gamma.tags.getRelatedTags(tagId);
// Comments
final comments = await client.gamma.comments.listComments(
parentEntityType: ParentEntityType.market,
parentEntityId: 123,
order: CommentOrderBy.createdAt,
);
// Profiles
final profile = await client.gamma.profiles.getByAddress('0x...');
// Leaderboard
final leaders = await client.gamma.leaderboard.getTopByProfit(limit: 10);
CLOB API (Order Book & Trading) #
Order Book & Pricing
// Order Book
final book = await client.clob.orderbook.getOrderBook('token-id');
final books = await client.clob.orderbook.getOrderBooks(['token-1', 'token-2']);
// Pricing
final price = await client.clob.pricing.getPrice('token-id', OrderSide.buy);
final midpoint = await client.clob.pricing.getMidpoint('token-id');
final spread = await client.clob.pricing.getSpread('token-id');
final history = await client.clob.pricing.getPriceHistory(
'token-id',
interval: PriceHistoryInterval.hour1,
);
Orders & Trades (Requires Auth)
// Orders
final response = await client.clob.orders.postOrder(signedOrder);
final orders = await client.clob.orders.getOpenOrders();
await client.clob.orders.cancelOrder('order-id');
await client.clob.orders.cancelAllOrders();
// Trades
final trades = await client.clob.trades.getTrades(market: 'condition-id');
Data API (Analytics) #
Positions & Trades
// Positions
final positions = await client.data.positions.getPositions(
userAddress: '0x...',
sortBy: SortBy.value,
sortDirection: SortDirection.desc,
);
final closed = await client.data.positions.getClosedPositions(userAddress: '0x...');
// Trades
final trades = await client.data.trades.getUserTrades(userAddress: '0x...');
final marketTrades = await client.data.trades.getMarketTrades(conditionId: 'cond-id');
Activity, Holders, Portfolio
// Activity
final activity = await client.data.activity.getUserActivity(
userAddress: '0x...',
types: [ActivityType.trade, ActivityType.redeem],
);
// Holders
final holders = await client.data.holders.getTokenHolders(tokenId: 'token-id');
// Portfolio Value
final value = await client.data.value.getValue('0x...');
print('Total: ${value.totalValue}, PnL: ${value.totalPnl}');
// Leaderboard
final leaders = await client.data.leaderboard.getLeaderboard(
window: LeaderboardWindow.day7,
type: LeaderboardType.profit,
);
WebSocket Streams #
Real-Time Data
// CLOB WebSocket
await client.clobWebSocket.connect();
// Market data (public)
client.clobWebSocket.subscribeToMarket(['token-id']);
client.clobWebSocket.bookUpdates.listen((book) => print(book));
client.clobWebSocket.priceChanges.listen((price) => print(price));
client.clobWebSocket.lastTradePrices.listen((trade) => print(trade));
// User data (requires auth)
client.clobWebSocket.subscribeToUser(['token-id']);
client.clobWebSocket.userOrders.listen((order) => print(order));
client.clobWebSocket.userTrades.listen((trade) => print(trade));
// RTDS WebSocket (crypto prices, comments)
await client.rtdsWebSocket.connect(topics: [RtdsTopic.cryptoPrices, RtdsTopic.comments]);
client.rtdsWebSocket.cryptoPrices.listen((msg) => print(msg));
client.rtdsWebSocket.comments.listen((comment) => print(comment));
Type-Safe Enums #
Every parameter with known values is a compile-time enum. No more typos or invalid strings!
Order By Enums
| Enum | Values |
|---|---|
MarketOrderBy |
volume, volume24hr, liquidity, endDate, startDate, createdAt |
EventOrderBy |
volume, startDate, endDate, createdAt, liquidity |
TagOrderBy |
volume, eventsCount, createdAt, label |
CommentOrderBy |
createdAt, likes, replies, updatedAt |
SeriesOrderBy |
volume, startDate, endDate, createdAt, liquidity |
SportsOrderBy |
name, league, abbreviation, createdAt |
SearchSort |
relevance, volume, liquidity, startDate, endDate, createdAt |
GammaLeaderboardOrderBy |
profit, volume, marketsTraded |
Status & Type Enums
| Enum | Values | Helper Methods |
|---|---|---|
OutcomeType |
yes, no |
opposite, isYes, isNo |
OrderSide |
buy, sell |
opposite |
OrderType |
gtc, gtd, fok, fak |
- |
OrderStatus |
live, matched, filled, cancelled, pending, delayed |
isActive, isTerminal, isCancellable |
TradeStatus |
mined, confirmed, retrying, failed |
isTerminal, isPending |
GameStatus |
scheduled, inProgress, halftime, ended, postponed, cancelled, suspended |
isLive, isFinished, isUpcoming, isInterrupted |
EventsStatus |
active, closed, all |
- |
RecurrenceType |
daily, weekly, monthly, yearly, none |
isRecurring |
UmaResolutionStatus |
pending, proposed, disputed, resolved |
isTerminal, isInProgress, hasStarted |
SortDirection |
asc, desc |
opposite |
PriceHistoryInterval |
minute1, minute5, ... hour1, hour4, ... day1, week1, max |
- |
Category Enums
| Category | Subcategory Enum |
|---|---|
MarketCategory.politics |
PoliticsSubcategory |
MarketCategory.sports |
SportsSubcategory |
MarketCategory.crypto |
CryptoSubcategory |
MarketCategory.popCulture |
PopCultureSubcategory |
MarketCategory.business |
BusinessSubcategory |
MarketCategory.science |
ScienceSubcategory |
SearchQuery Sealed Class (60+ Presets)
| Category | Presets |
|---|---|
| Crypto | bitcoin, ethereum, solana, crypto, defi, nft, memecoin, altcoin |
| Politics | election, trump, biden, president, congress, senate, supremeCourt, policy |
| Sports | nfl, nba, mlb, nhl, soccer, ufc, boxing, tennis, golf, olympics, superBowl, worldCup |
| Entertainment | oscars, grammys, emmys, movies, tv, music, celebrity, taylorSwift, streaming |
| Business | stocks, fed, interestRates, inflation, recession, ipo, tesla, apple, google, amazon, microsoft, elonMusk |
| Science/Tech | ai, openai, chatgpt, spacex, nasa, climate, space, mars |
| World | war, ukraine, russia, china, israel, middleEast |
Category Detection #
Automatic Category Detection
import 'package:polybrainz_polymarket/polybrainz_polymarket.dart';
// Detect from a single event
final result = CategoryDetector.detectFromEvent(event);
print(result.category); // MarketCategory.politics
print(result.subcategories); // [PoliticsSubcategory.usPresidential]
print(result.tagSlugs); // ['politics', 'us-presidential', 'trump']
// Extension methods on lists
final markets = await client.gamma.markets.listMarkets(limit: 100);
final categories = markets.detectCategories();
final unique = markets.uniqueCategories; // Set<MarketCategory>
// Group by category
final grouped = markets.groupByCategory();
for (final entry in grouped.entries) {
print('${entry.key.label}: ${entry.value.length} markets');
}
// Filter by category using slugs
final cryptoMarkets = await client.gamma.markets.getByTagSlug('crypto');
final nflEvents = await client.gamma.events.listEvents(
tagSlug: SportsSubcategory.nfl.slug,
);
Authentication #
Using Existing API Credentials
final client = PolymarketClient.authenticated(
credentials: ApiCredentials(
apiKey: 'your-api-key',
secret: 'your-secret',
passphrase: 'your-passphrase',
),
funder: '0xYourWalletAddress',
);
Deriving API Credentials (Requires web3dart)
final client = PolymarketClient.withPrivateKey(
privateKey: '0xYourPrivateKey',
walletAddress: '0xYourWalletAddress',
);
// Requires proper EIP-712 implementation
// await client.clob.auth.createOrDeriveApiKey();
Note: L1 authentication (EIP-712 signing) is implemented as a placeholder. For production, integrate with
web3dartor similar.
Error Handling #
try {
final orders = await client.clob.orders.getOpenOrders();
} on AuthenticationException catch (e) {
print('Auth error: ${e.message}');
} on RateLimitException catch (e) {
print('Rate limited, retry after: ${e.retryAfter}');
} on ApiException catch (e) {
print('API error ${e.statusCode}: ${e.message}');
} on NetworkException catch (e) {
print('Network error: ${e.message}');
} on PolymarketException catch (e) {
print('Error: ${e.message}');
}
Key Concepts #
Token IDs vs Condition IDs
| Concept | Description |
|---|---|
| Condition ID | Identifies a market (e.g., "Will X happen?") |
| Token ID | Identifies a specific outcome token (Yes or No) |
A market has ONE condition ID but TWO token IDs.
Order Types
| Type | Description |
|---|---|
GTC |
Good Till Cancelled - rests on book until filled or cancelled |
GTD |
Good Till Date - expires at specified timestamp |
FOK |
Fill or Kill - must fill completely immediately or cancel |
FAK |
Fill and Kill (IOC) - fill what you can, cancel rest |
Negative Risk
Some markets support "negative risk" where Yes + No tokens can be merged/split for capital efficiency. Check the negRisk field on markets.
Examples #
See the example/ directory:
| Example | Description |
|---|---|
| Basic Usage | Simple API calls |
| WebSocket Streaming | Real-time data |
| Trading | Order management |
| Market Discovery | Search & category detection |
Resources #
| Resource | Link |
|---|---|
| Polymarket Gamma API | docs.polymarket.com/.../gamma-markets-api |
| Polymarket CLOB API | docs.polymarket.com/.../clob-api |
| Polymarket Data API | docs.polymarket.com/.../data-api |
MIT License - see LICENSE for details
Made with Dart