
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
@codifydoo/gamma-client
Advanced tools
TypeScript client library for Polymarket Gamma API (read-only market data)
A production-ready TypeScript client library for the Polymarket Gamma API (read-only market data).
anynpm install @codifydoo/gamma-client
import { GammaClient } from '@codifydoo/gamma-client';
const client = new GammaClient({
baseURL: 'https://gamma-api.polymarket.com',
timeoutMs: 10_000,
retries: 2,
rateLimit: { burst: 5, ratePerSec: 5 },
cache: { ttlMs: 5_000 },
userAgent: 'my-app/1.0.0',
});
// Health check
const health = await client.health.check();
console.log('API Status:', health.status);
// List active markets
const markets = await client.markets.list({
active: true,
limit: 10,
});
// Get market details with normalized data
const market = await client.markets.getBySlug('bitcoin-up-or-down-oct-2');
console.log('Outcomes:', market.outcomes); // ['Yes', 'No'] - automatically parsed
console.log('Prices:', market.outcomePrices); // [0.6, 0.4] - automatically parsed
// Search across markets, events, and profiles
const results = await client.search.query({
q: 'bitcoin',
types: ['market', 'event'],
limit: 20,
});
interface GammaClientConfig {
baseURL?: string; // Default: 'https://gamma-api.polymarket.com'
timeoutMs?: number; // Default: 10_000
retries?: number; // Default: 2
rateLimit?: {
// Default: { burst: 5, ratePerSec: 5 }
burst: number;
ratePerSec: number;
};
cache?: {
// Default: { ttlMs: 5_000 }
ttlMs?: number; // Set to 0 to disable caching
};
userAgent?: string; // Default: 'gamma-client/1.0.0'
}
const client = new GammaClient();
const client = new GammaClient({
baseURL: 'https://gamma-api.polymarket.com',
timeoutMs: 15_000,
retries: 3,
rateLimit: { burst: 10, ratePerSec: 8 },
cache: { ttlMs: 10_000 },
userAgent: 'my-trading-bot/1.0.0',
});
const client = new GammaClient({
cache: { ttlMs: 0 },
});
client.health.check()Check the health status of the Gamma API.
Returns: Promise<HealthCheckResponse>
const health = await client.health.check();
// { status: 'healthy', timestamp: '2024-01-01T00:00:00Z', ... }
client.sports.listTeams(params?)List all sports teams with optional filtering.
Parameters:
params.limit? - Number of teams to returnparams.offset? - Number of teams to skipparams.sport? - Filter by sportparams.league? - Filter by leagueReturns: Promise<ListTeamsResponse>
const teams = await client.sports.listTeams({
sport: 'basketball',
limit: 10,
});
client.sports.getMetadata()Get sports metadata information.
Returns: Promise<SportsMetadataResponse>
const metadata = await client.sports.getMetadata();
// { sports: [{ id: '1', name: 'Basketball', leagues: [...] }] }
client.tags.list(params?)List all tags with optional filtering.
Parameters:
params.limit? - Number of tags to returnparams.offset? - Number of tags to skipparams.category? - Filter by categoryparams.search? - Search termReturns: Promise<ListTagsResponse>
const tags = await client.tags.list({
category: 'politics',
limit: 20,
});
client.tags.getById(id)Get a tag by its ID.
Parameters:
id - Tag IDReturns: Promise<Tag>
const tag = await client.tags.getById('123');
client.tags.getBySlug(slug)Get a tag by its slug.
Parameters:
slug - Tag slugReturns: Promise<Tag>
const tag = await client.tags.getBySlug('us-elections');
client.tags.getRelationshipsById(id, params?)Get related tags relationships by tag ID.
Parameters:
id - Tag IDparams.limit? - Number of relationships to returnparams.offset? - Number of relationships to skipReturns: Promise<TagRelationships>
const relationships = await client.tags.getRelationshipsById('123');
client.tags.getRelationshipsBySlug(slug, params?)Get related tags relationships by tag slug.
Parameters:
slug - Tag slugparams.limit? - Number of relationships to returnparams.offset? - Number of relationships to skipReturns: Promise<TagRelationships>
const relationships = await client.tags.getRelationshipsBySlug('us-elections');
client.tags.getRelatedToId(id, params?)Get tags related to a tag ID.
Parameters:
id - Tag IDparams.limit? - Number of related tags to returnparams.offset? - Number of related tags to skipReturns: Promise<Tag[]>
const relatedTags = await client.tags.getRelatedToId('123');
client.tags.getRelatedToSlug(slug, params?)Get tags related to a tag slug.
Parameters:
slug - Tag slugparams.limit? - Number of related tags to returnparams.offset? - Number of related tags to skipReturns: Promise<Tag[]>
const relatedTags = await client.tags.getRelatedToSlug('us-elections');
client.events.list(params?)List all events with optional filtering.
Parameters:
params.limit? - Number of events to returnparams.offset? - Number of events to skipparams.active? - Filter by active statusparams.category? - Filter by categoryparams.tags? - Filter by tagsparams.startDate? - Filter by start dateparams.endDate? - Filter by end dateReturns: Promise<ListEventsResponse>
const events = await client.events.list({
active: true,
category: 'politics',
limit: 50,
});
client.events.getById(id)Get an event by its ID.
Parameters:
id - Event IDReturns: Promise<Event>
const event = await client.events.getById('123');
client.events.getTags(eventId)Get tags for an event.
Parameters:
eventId - Event IDReturns: Promise<Tag[]>
const tags = await client.events.getTags('123');
client.events.getBySlug(slug)Get an event by its slug.
Parameters:
slug - Event slugReturns: Promise<Event>
const event = await client.events.getBySlug('2024-presidential-election');
client.markets.list(params?)List all markets with optional filtering.
Parameters:
params.limit? - Number of markets to returnparams.offset? - Number of markets to skipparams.active? - Filter by active statusparams.eventId? - Filter by event IDparams.category? - Filter by categoryparams.tags? - Filter by tagsReturns: Promise<ListMarketsResponse>
const markets = await client.markets.list({
active: true,
limit: 100,
});
client.markets.getById(id)Get a market by its ID.
Parameters:
id - Market IDReturns: Promise<Market>
const market = await client.markets.getById('123');
client.markets.getTags(marketId)Get tags for a market.
Parameters:
marketId - Market IDReturns: Promise<Tag[]>
const tags = await client.markets.getTags('123');
client.markets.getBySlug(slug)Get a market by its slug.
Parameters:
slug - Market slugReturns: Promise<Market>
const market = await client.markets.getBySlug('bitcoin-up-or-down-oct-2');
client.series.list(params?)List all series with optional filtering.
Parameters:
params.limit? - Number of series to returnparams.offset? - Number of series to skipparams.active? - Filter by active statusparams.category? - Filter by categoryReturns: Promise<ListSeriesResponse>
const series = await client.series.list({
active: true,
limit: 20,
});
client.series.getById(id)Get a series by its ID.
Parameters:
id - Series IDReturns: Promise<Series>
const series = await client.series.getById('123');
client.comments.list(params?)List all comments with optional filtering.
Parameters:
params.limit? - Number of comments to returnparams.offset? - Number of comments to skipparams.marketId? - Filter by market IDparams.eventId? - Filter by event IDparams.parentId? - Filter by parent comment IDReturns: Promise<ListCommentsResponse>
const comments = await client.comments.list({
marketId: '123',
limit: 50,
});
client.comments.getById(id)Get a comment by its ID.
Parameters:
id - Comment IDReturns: Promise<Comment>
const comment = await client.comments.getById('123');
client.comments.getByUserAddress(address, params?)Get comments by user address.
Parameters:
address - User addressparams.limit? - Number of comments to returnparams.offset? - Number of comments to skipReturns: Promise<ListCommentsResponse>
const comments = await client.comments.getByUserAddress('0x123...', {
limit: 20,
});
client.search.query(params)Search markets, events, and profiles.
Parameters:
params.q - Search query (required)params.limit? - Number of results to returnparams.offset? - Number of results to skipparams.types? - Filter by result typesparams.category? - Filter by categoryparams.tags? - Filter by tagsReturns: Promise<SearchResponse>
const results = await client.search.query({
q: 'bitcoin',
types: ['market', 'event'],
limit: 20,
});
The Gamma API returns some fields as JSON-encoded strings. The client automatically normalizes these fields:
const market = await client.markets.getById('123');
// These fields are automatically parsed from JSON strings:
console.log(market.outcomes); // ['Yes', 'No'] instead of '["Yes", "No"]'
console.log(market.outcomePrices); // [0.6, 0.4] instead of '[0.6, 0.4]'
console.log(market.clobTokenIds); // ['token1', 'token2'] instead of '["token1", "token2"]'
You can also use the normalization utilities directly:
import { parseJsonArray, toNumber, toNumberArray, toStringArray } from '@codifydoo/gamma-client';
const jsonString = '["a", "b", "c"]';
const parsed = parseJsonArray(jsonString); // ['a', 'b', 'c']
const numberString = '123.45';
const number = toNumber(numberString); // 123.45
const numberArrayString = '[1, 2, 3]';
const numbers = toNumberArray(numberArrayString); // [1, 2, 3]
The client supports both offset-based and cursor-based pagination:
// Get first page
const page1 = await client.markets.list({ limit: 10, offset: 0 });
// Get second page
const page2 = await client.markets.list({ limit: 10, offset: 10 });
// Check if there are more results
if (page1.hasMore) {
console.log('More results available');
}
// Get first page
const page1 = await client.events.list({ limit: 10 });
// Get next page using cursor
if (page1.nextCursor) {
const page2 = await client.events.list({
limit: 10,
cursor: page1.nextCursor,
});
}
The client provides comprehensive error handling:
import { GammaClientError } from '@codifydoo/gamma-client';
try {
const market = await client.markets.getById('invalid-id');
} catch (error) {
if (error instanceof GammaClientError) {
console.error('API Error:', error.message);
console.error('Status Code:', error.statusCode);
console.error('Endpoint:', error.endpoint);
} else {
console.error('Unexpected error:', error);
}
}
try {
const result = await client.markets.list();
} catch (error) {
// Network errors are automatically retried with exponential backoff
console.error('Request failed after retries:', error.message);
}
try {
const result = await client.markets.list({ limit: -1 }); // Invalid limit
} catch (error) {
// Zod validation error
console.error('Validation error:', error.message);
}
// The client automatically handles rate limiting
// Requests are queued and executed at the configured rate
const promises = Array(100)
.fill(null)
.map(() => client.markets.list());
await Promise.all(promises); // Will be rate-limited automatically
The client includes an optional in-memory cache:
const client = new GammaClient({
cache: { ttlMs: 10_000 }, // Cache for 10 seconds
});
// First call - hits API
const market1 = await client.markets.getById('123');
// Second call within 10 seconds - hits cache
const market2 = await client.markets.getById('123');
// Clear cache
client.clearCache();
// Get cache statistics
const stats = client.getCacheStats();
console.log('Cache size:', stats?.size);
The client implements a token bucket rate limiter:
const client = new GammaClient({
rateLimit: {
burst: 10, // Allow up to 10 requests immediately
ratePerSec: 5, // Then limit to 5 requests per second
},
});
// These requests will be rate-limited automatically
const promises = Array(20)
.fill(null)
.map(() => client.markets.list());
await Promise.all(promises);
Always wrap API calls in try-catch blocks:
try {
const result = await client.markets.list();
// Process result
} catch (error) {
// Handle error appropriately
console.error('Failed to fetch markets:', error.message);
}
Use pagination to avoid loading too much data at once:
async function getAllMarkets() {
const allMarkets = [];
let offset = 0;
const limit = 100;
while (true) {
const response = await client.markets.list({ limit, offset });
allMarkets.push(...response.data);
if (!response.hasMore) break;
offset += limit;
}
return allMarkets;
}
Enable caching for frequently accessed data:
const client = new GammaClient({
cache: { ttlMs: 30_000 }, // Cache for 30 seconds
});
Configure appropriate rate limits for your use case:
const client = new GammaClient({
rateLimit: {
burst: 5, // Conservative burst
ratePerSec: 2, // Conservative rate
},
});
Use TypeScript strict mode and leverage the provided types:
import { Market, ListMarketsRequest } from '@codifydoo/gamma-client';
async function processMarkets(params: ListMarketsRequest): Promise<Market[]> {
const response = await client.markets.list(params);
return response.data;
}
const client = new GammaClient({
timeoutMs: 30_000, // Increase timeout for slow connections
});
const client = new GammaClient({
rateLimit: {
burst: 1, // Reduce burst
ratePerSec: 1, // Reduce rate
},
});
const client = new GammaClient({
cache: { ttlMs: 0 }, // Disable caching to reduce memory usage
});
Check the error message for specific validation issues:
try {
await client.markets.list({ limit: -1 });
} catch (error) {
console.error('Validation error:', error.message);
// Look for specific field validation errors
}
Enable debug logging to see request details:
// The client logs requests at debug level
// Enable debug logging in your application
MIT License - see LICENSE file for details.
FAQs
TypeScript client library for Polymarket Gamma API (read-only market data)
The npm package @codifydoo/gamma-client receives a total of 4 weekly downloads. As such, @codifydoo/gamma-client popularity was classified as not popular.
We found that @codifydoo/gamma-client demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.