@ebowwa/polymarket-client 1.0.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.
- package/dist/client.d.ts +135 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +170 -0
- package/package.json +56 -0
- package/src/client.ts +304 -0
- package/src/index.ts +8 -0
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @codespaces/polymarket/client
|
|
3
|
+
*
|
|
4
|
+
* Polymarket API client wrapper for prediction markets integration.
|
|
5
|
+
* Provides access to Gamma API, CLOB API, and Data API.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Polymarket market data structure
|
|
9
|
+
*/
|
|
10
|
+
export interface PolymarketMarket {
|
|
11
|
+
condition_id: string;
|
|
12
|
+
markets: Array<{
|
|
13
|
+
market_id: string;
|
|
14
|
+
question: string;
|
|
15
|
+
description: string;
|
|
16
|
+
end_date: string;
|
|
17
|
+
active: boolean;
|
|
18
|
+
closed: boolean;
|
|
19
|
+
volume: number;
|
|
20
|
+
liquidity: number;
|
|
21
|
+
token_id: string;
|
|
22
|
+
outcome_prices: number[];
|
|
23
|
+
}>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Polymarket event data structure
|
|
27
|
+
*/
|
|
28
|
+
export interface PolymarketEvent {
|
|
29
|
+
id: string;
|
|
30
|
+
slug: string;
|
|
31
|
+
title: string;
|
|
32
|
+
description: string;
|
|
33
|
+
start_date: string;
|
|
34
|
+
end_date?: string;
|
|
35
|
+
image: string;
|
|
36
|
+
markets: string[];
|
|
37
|
+
tags: string[];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Polymarket profile data structure
|
|
41
|
+
*/
|
|
42
|
+
export interface PolymarketProfile {
|
|
43
|
+
wallet_address: string;
|
|
44
|
+
username?: string;
|
|
45
|
+
profit_loss?: number;
|
|
46
|
+
volume?: number;
|
|
47
|
+
trades?: number;
|
|
48
|
+
markets_traded?: number;
|
|
49
|
+
biggest_win?: number;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Polymarket order book data structure
|
|
53
|
+
*/
|
|
54
|
+
export interface PolymarketOrderBook {
|
|
55
|
+
market_id: string;
|
|
56
|
+
bids: Array<{
|
|
57
|
+
price: number;
|
|
58
|
+
size: number;
|
|
59
|
+
}>;
|
|
60
|
+
asks: Array<{
|
|
61
|
+
price: number;
|
|
62
|
+
size: number;
|
|
63
|
+
}>;
|
|
64
|
+
last_updated: number;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Polymarket client configuration
|
|
68
|
+
*/
|
|
69
|
+
export interface PolymarketClientConfig {
|
|
70
|
+
gammaApiBase?: string;
|
|
71
|
+
clobApiBase?: string;
|
|
72
|
+
dataApiBase?: string;
|
|
73
|
+
debug?: boolean;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Polymarket API client
|
|
77
|
+
*/
|
|
78
|
+
export declare class PolymarketClient {
|
|
79
|
+
private gammaApiBase;
|
|
80
|
+
private clobApiBase;
|
|
81
|
+
private dataApiBase;
|
|
82
|
+
private debug;
|
|
83
|
+
constructor(config?: PolymarketClientConfig);
|
|
84
|
+
private debugLog;
|
|
85
|
+
listMarkets(params?: {
|
|
86
|
+
limit?: number;
|
|
87
|
+
offset?: number;
|
|
88
|
+
archived?: boolean;
|
|
89
|
+
closed?: boolean;
|
|
90
|
+
active?: boolean;
|
|
91
|
+
order?: 'volume' | 'liquidity' | 'createdAt';
|
|
92
|
+
order_dir?: 'asc' | 'desc';
|
|
93
|
+
}): Promise<{
|
|
94
|
+
markets: PolymarketMarket[];
|
|
95
|
+
}>;
|
|
96
|
+
getMarket(conditionId: string): Promise<{
|
|
97
|
+
market: PolymarketMarket;
|
|
98
|
+
}>;
|
|
99
|
+
listEvents(params?: {
|
|
100
|
+
limit?: number;
|
|
101
|
+
offset?: number;
|
|
102
|
+
archived?: boolean;
|
|
103
|
+
closed?: boolean;
|
|
104
|
+
tag_id?: string;
|
|
105
|
+
}): Promise<{
|
|
106
|
+
events: PolymarketEvent[];
|
|
107
|
+
}>;
|
|
108
|
+
getEvent(eventSlug: string): Promise<{
|
|
109
|
+
event: PolymarketEvent;
|
|
110
|
+
}>;
|
|
111
|
+
getProfile(walletAddress: string): Promise<{
|
|
112
|
+
profile: PolymarketProfile;
|
|
113
|
+
}>;
|
|
114
|
+
search(query: string, params?: {
|
|
115
|
+
limit?: number;
|
|
116
|
+
offset?: number;
|
|
117
|
+
}): Promise<any>;
|
|
118
|
+
getOrderbook(tokenId: string): Promise<{
|
|
119
|
+
orderbook: PolymarketOrderBook;
|
|
120
|
+
}>;
|
|
121
|
+
getTrades(tokenId: string, limit?: number): Promise<any>;
|
|
122
|
+
getPrice(tokenId: string): Promise<{
|
|
123
|
+
price: number;
|
|
124
|
+
}>;
|
|
125
|
+
getPositions(walletAddress: string): Promise<any>;
|
|
126
|
+
getWalletTrades(walletAddress: string, params?: {
|
|
127
|
+
limit?: number;
|
|
128
|
+
offset?: number;
|
|
129
|
+
}): Promise<any>;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Create a new Polymarket client
|
|
133
|
+
*/
|
|
134
|
+
export declare function createPolymarketClient(config?: PolymarketClientConfig): PolymarketClient;
|
|
135
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,cAAc,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// src/client.ts
|
|
2
|
+
class PolymarketClient {
|
|
3
|
+
gammaApiBase;
|
|
4
|
+
clobApiBase;
|
|
5
|
+
dataApiBase;
|
|
6
|
+
debug;
|
|
7
|
+
constructor(config = {}) {
|
|
8
|
+
this.gammaApiBase = config.gammaApiBase || "https://gamma-api.polymarket.com";
|
|
9
|
+
this.clobApiBase = config.clobApiBase || "https://clob.polymarket.com";
|
|
10
|
+
this.dataApiBase = config.dataApiBase || "https://data-api.polymarket.com";
|
|
11
|
+
this.debug = config.debug || false;
|
|
12
|
+
}
|
|
13
|
+
debugLog(...args) {
|
|
14
|
+
if (this.debug) {
|
|
15
|
+
console.log("[Polymarket Client]", ...args);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
async listMarkets(params = {}) {
|
|
19
|
+
const searchParams = new URLSearchParams;
|
|
20
|
+
if (params.limit)
|
|
21
|
+
searchParams.set("limit", params.limit.toString());
|
|
22
|
+
if (params.offset)
|
|
23
|
+
searchParams.set("offset", params.offset.toString());
|
|
24
|
+
if (params.archived !== undefined)
|
|
25
|
+
searchParams.set("archived", params.archived.toString());
|
|
26
|
+
if (params.closed !== undefined)
|
|
27
|
+
searchParams.set("closed", params.closed.toString());
|
|
28
|
+
if (params.active !== undefined)
|
|
29
|
+
searchParams.set("active", params.active.toString());
|
|
30
|
+
if (params.order)
|
|
31
|
+
searchParams.set("order", params.order);
|
|
32
|
+
if (params.order_dir)
|
|
33
|
+
searchParams.set("order_dir", params.order_dir);
|
|
34
|
+
const response = await fetch(`${this.gammaApiBase}/markets?${searchParams.toString()}`);
|
|
35
|
+
if (!response.ok) {
|
|
36
|
+
throw new Error(`Gamma API error: ${response.status} ${response.statusText}`);
|
|
37
|
+
}
|
|
38
|
+
const data = await response.json();
|
|
39
|
+
return { markets: Array.isArray(data) ? data : [] };
|
|
40
|
+
}
|
|
41
|
+
async getMarket(conditionId) {
|
|
42
|
+
const response = await fetch(`${this.gammaApiBase}/markets/${conditionId}`);
|
|
43
|
+
if (!response.ok) {
|
|
44
|
+
throw new Error(`Gamma API error: ${response.status} ${response.statusText}`);
|
|
45
|
+
}
|
|
46
|
+
const data = await response.json();
|
|
47
|
+
return { market: data };
|
|
48
|
+
}
|
|
49
|
+
async listEvents(params = {}) {
|
|
50
|
+
const searchParams = new URLSearchParams;
|
|
51
|
+
if (params.limit)
|
|
52
|
+
searchParams.set("limit", params.limit.toString());
|
|
53
|
+
if (params.offset)
|
|
54
|
+
searchParams.set("offset", params.offset.toString());
|
|
55
|
+
if (params.archived !== undefined)
|
|
56
|
+
searchParams.set("archived", params.archived.toString());
|
|
57
|
+
if (params.closed !== undefined)
|
|
58
|
+
searchParams.set("closed", params.closed.toString());
|
|
59
|
+
if (params.tag_id)
|
|
60
|
+
searchParams.set("tag_id", params.tag_id);
|
|
61
|
+
const response = await fetch(`${this.gammaApiBase}/events?${searchParams.toString()}`);
|
|
62
|
+
if (!response.ok) {
|
|
63
|
+
throw new Error(`Gamma API error: ${response.status} ${response.statusText}`);
|
|
64
|
+
}
|
|
65
|
+
const data = await response.json();
|
|
66
|
+
return { events: Array.isArray(data) ? data : [] };
|
|
67
|
+
}
|
|
68
|
+
async getEvent(eventSlug) {
|
|
69
|
+
const response = await fetch(`${this.gammaApiBase}/events/${eventSlug}`);
|
|
70
|
+
if (!response.ok) {
|
|
71
|
+
throw new Error(`Gamma API error: ${response.status} ${response.statusText}`);
|
|
72
|
+
}
|
|
73
|
+
const data = await response.json();
|
|
74
|
+
return { event: data };
|
|
75
|
+
}
|
|
76
|
+
async getProfile(walletAddress) {
|
|
77
|
+
const response = await fetch(`${this.gammaApiBase}/profiles/${walletAddress}`);
|
|
78
|
+
if (!response.ok) {
|
|
79
|
+
throw new Error(`Gamma API error: ${response.status} ${response.statusText}`);
|
|
80
|
+
}
|
|
81
|
+
const data = await response.json();
|
|
82
|
+
return { profile: data };
|
|
83
|
+
}
|
|
84
|
+
async search(query, params = {}) {
|
|
85
|
+
const searchLower = query.toLowerCase();
|
|
86
|
+
const limit = params.limit || 20;
|
|
87
|
+
const offset = params.offset || 0;
|
|
88
|
+
try {
|
|
89
|
+
const searchParams = new URLSearchParams;
|
|
90
|
+
searchParams.set("query", query);
|
|
91
|
+
if (params.limit)
|
|
92
|
+
searchParams.set("limit", params.limit.toString());
|
|
93
|
+
if (params.offset)
|
|
94
|
+
searchParams.set("offset", params.offset.toString());
|
|
95
|
+
const response = await fetch(`${this.gammaApiBase}/search?${searchParams.toString()}`);
|
|
96
|
+
if (response.ok) {
|
|
97
|
+
return response.json();
|
|
98
|
+
}
|
|
99
|
+
this.debugLog(`Search endpoint returned ${response.status}, falling back to client-side`);
|
|
100
|
+
} catch (error) {
|
|
101
|
+
this.debugLog("Search endpoint error:", error);
|
|
102
|
+
}
|
|
103
|
+
const fetchResult = await this.listMarkets({ limit: 500 });
|
|
104
|
+
const allMarkets = fetchResult.markets || [];
|
|
105
|
+
const filtered = allMarkets.filter((m) => {
|
|
106
|
+
const question = (m.question || "").toLowerCase();
|
|
107
|
+
const description = (m.description || "").toLowerCase();
|
|
108
|
+
const slug = (m.slug || "").toLowerCase();
|
|
109
|
+
const tags = (m.tags || []).join(" ").toLowerCase();
|
|
110
|
+
return question.includes(searchLower) || description.includes(searchLower) || slug.includes(searchLower) || tags.includes(searchLower);
|
|
111
|
+
});
|
|
112
|
+
const paginated = filtered.slice(offset, offset + limit);
|
|
113
|
+
return {
|
|
114
|
+
markets: paginated,
|
|
115
|
+
total: filtered.length,
|
|
116
|
+
query,
|
|
117
|
+
note: "Results filtered client-side"
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
async getOrderbook(tokenId) {
|
|
121
|
+
const response = await fetch(`${this.clobApiBase}/orderbook?token_id=${tokenId}`);
|
|
122
|
+
if (!response.ok) {
|
|
123
|
+
throw new Error(`CLOB API error: ${response.status} ${response.statusText}`);
|
|
124
|
+
}
|
|
125
|
+
const data = await response.json();
|
|
126
|
+
return { orderbook: data };
|
|
127
|
+
}
|
|
128
|
+
async getTrades(tokenId, limit = 100) {
|
|
129
|
+
const response = await fetch(`${this.clobApiBase}/history?token_id=${tokenId}&limit=${limit}`);
|
|
130
|
+
if (!response.ok) {
|
|
131
|
+
throw new Error(`CLOB API error: ${response.status} ${response.statusText}`);
|
|
132
|
+
}
|
|
133
|
+
return response.json();
|
|
134
|
+
}
|
|
135
|
+
async getPrice(tokenId) {
|
|
136
|
+
const response = await fetch(`${this.clobApiBase}/price?token_id=${tokenId}`);
|
|
137
|
+
if (!response.ok) {
|
|
138
|
+
throw new Error(`CLOB API error: ${response.status} ${response.statusText}`);
|
|
139
|
+
}
|
|
140
|
+
const data = await response.json();
|
|
141
|
+
return { price: data.price };
|
|
142
|
+
}
|
|
143
|
+
async getPositions(walletAddress) {
|
|
144
|
+
const response = await fetch(`${this.dataApiBase}/positions?wallet=${walletAddress}`);
|
|
145
|
+
if (!response.ok) {
|
|
146
|
+
throw new Error(`Data API error: ${response.status} ${response.statusText}`);
|
|
147
|
+
}
|
|
148
|
+
return response.json();
|
|
149
|
+
}
|
|
150
|
+
async getWalletTrades(walletAddress, params = {}) {
|
|
151
|
+
const searchParams = new URLSearchParams;
|
|
152
|
+
searchParams.set("wallet", walletAddress);
|
|
153
|
+
if (params.limit)
|
|
154
|
+
searchParams.set("limit", params.limit.toString());
|
|
155
|
+
if (params.offset)
|
|
156
|
+
searchParams.set("offset", params.offset.toString());
|
|
157
|
+
const response = await fetch(`${this.dataApiBase}/trades?${searchParams.toString()}`);
|
|
158
|
+
if (!response.ok) {
|
|
159
|
+
throw new Error(`Data API error: ${response.status} ${response.statusText}`);
|
|
160
|
+
}
|
|
161
|
+
return response.json();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
function createPolymarketClient(config) {
|
|
165
|
+
return new PolymarketClient(config);
|
|
166
|
+
}
|
|
167
|
+
export {
|
|
168
|
+
createPolymarketClient,
|
|
169
|
+
PolymarketClient
|
|
170
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ebowwa/polymarket-client",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Polymarket prediction markets SDK wrapper and utilities",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./client": {
|
|
14
|
+
"types": "./dist/client.d.ts",
|
|
15
|
+
"import": "./dist/client.js"
|
|
16
|
+
},
|
|
17
|
+
"./types": {
|
|
18
|
+
"types": "./dist/types.d.ts",
|
|
19
|
+
"import": "./dist/types.js"
|
|
20
|
+
},
|
|
21
|
+
"./gamma": {
|
|
22
|
+
"types": "./dist/gamma.d.ts",
|
|
23
|
+
"import": "./dist/gamma.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"src"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "bun build src/index.ts --outdir dist --target node && tsc --emitDeclarationOnly",
|
|
32
|
+
"dev": "bun --watch src/index.ts",
|
|
33
|
+
"typecheck": "tsc --noEmit",
|
|
34
|
+
"test": "bun test",
|
|
35
|
+
"prepublishOnly": "bun run build"
|
|
36
|
+
},
|
|
37
|
+
"keywords": [
|
|
38
|
+
"polymarket",
|
|
39
|
+
"prediction-markets",
|
|
40
|
+
"trading",
|
|
41
|
+
"clob",
|
|
42
|
+
"gamma-api"
|
|
43
|
+
],
|
|
44
|
+
"author": "ebowwa",
|
|
45
|
+
"license": "MIT",
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@polymarket/clob-client": "^2.0.0"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/bun": "^1.3.8",
|
|
51
|
+
"typescript": "^5.7.2"
|
|
52
|
+
},
|
|
53
|
+
"engines": {
|
|
54
|
+
"node": ">=20.0.0"
|
|
55
|
+
}
|
|
56
|
+
}
|
package/src/client.ts
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @codespaces/polymarket/client
|
|
3
|
+
*
|
|
4
|
+
* Polymarket API client wrapper for prediction markets integration.
|
|
5
|
+
* Provides access to Gamma API, CLOB API, and Data API.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Polymarket market data structure
|
|
10
|
+
*/
|
|
11
|
+
export interface PolymarketMarket {
|
|
12
|
+
condition_id: string;
|
|
13
|
+
markets: Array<{
|
|
14
|
+
market_id: string;
|
|
15
|
+
question: string;
|
|
16
|
+
description: string;
|
|
17
|
+
end_date: string;
|
|
18
|
+
active: boolean;
|
|
19
|
+
closed: boolean;
|
|
20
|
+
volume: number;
|
|
21
|
+
liquidity: number;
|
|
22
|
+
token_id: string;
|
|
23
|
+
outcome_prices: number[];
|
|
24
|
+
}>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Polymarket event data structure
|
|
29
|
+
*/
|
|
30
|
+
export interface PolymarketEvent {
|
|
31
|
+
id: string;
|
|
32
|
+
slug: string;
|
|
33
|
+
title: string;
|
|
34
|
+
description: string;
|
|
35
|
+
start_date: string;
|
|
36
|
+
end_date?: string;
|
|
37
|
+
image: string;
|
|
38
|
+
markets: string[];
|
|
39
|
+
tags: string[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Polymarket profile data structure
|
|
44
|
+
*/
|
|
45
|
+
export interface PolymarketProfile {
|
|
46
|
+
wallet_address: string;
|
|
47
|
+
username?: string;
|
|
48
|
+
profit_loss?: number;
|
|
49
|
+
volume?: number;
|
|
50
|
+
trades?: number;
|
|
51
|
+
markets_traded?: number;
|
|
52
|
+
biggest_win?: number;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Polymarket order book data structure
|
|
57
|
+
*/
|
|
58
|
+
export interface PolymarketOrderBook {
|
|
59
|
+
market_id: string;
|
|
60
|
+
bids: Array<{ price: number; size: number }>;
|
|
61
|
+
asks: Array<{ price: number; size: number }>;
|
|
62
|
+
last_updated: number;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Polymarket client configuration
|
|
67
|
+
*/
|
|
68
|
+
export interface PolymarketClientConfig {
|
|
69
|
+
gammaApiBase?: string;
|
|
70
|
+
clobApiBase?: string;
|
|
71
|
+
dataApiBase?: string;
|
|
72
|
+
debug?: boolean;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Polymarket API client
|
|
77
|
+
*/
|
|
78
|
+
export class PolymarketClient {
|
|
79
|
+
private gammaApiBase: string;
|
|
80
|
+
private clobApiBase: string;
|
|
81
|
+
private dataApiBase: string;
|
|
82
|
+
private debug: boolean;
|
|
83
|
+
|
|
84
|
+
constructor(config: PolymarketClientConfig = {}) {
|
|
85
|
+
this.gammaApiBase = config.gammaApiBase || 'https://gamma-api.polymarket.com';
|
|
86
|
+
this.clobApiBase = config.clobApiBase || 'https://clob.polymarket.com';
|
|
87
|
+
this.dataApiBase = config.dataApiBase || 'https://data-api.polymarket.com';
|
|
88
|
+
this.debug = config.debug || false;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private debugLog(...args: unknown[]) {
|
|
92
|
+
if (this.debug) {
|
|
93
|
+
console.log('[Polymarket Client]', ...args);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ============================================================================
|
|
98
|
+
// GAMMA API (Market Discovery)
|
|
99
|
+
// ============================================================================
|
|
100
|
+
|
|
101
|
+
async listMarkets(params: {
|
|
102
|
+
limit?: number;
|
|
103
|
+
offset?: number;
|
|
104
|
+
archived?: boolean;
|
|
105
|
+
closed?: boolean;
|
|
106
|
+
active?: boolean;
|
|
107
|
+
order?: 'volume' | 'liquidity' | 'createdAt';
|
|
108
|
+
order_dir?: 'asc' | 'desc';
|
|
109
|
+
} = {}): Promise<{ markets: PolymarketMarket[] }> {
|
|
110
|
+
const searchParams = new URLSearchParams();
|
|
111
|
+
if (params.limit) searchParams.set('limit', params.limit.toString());
|
|
112
|
+
if (params.offset) searchParams.set('offset', params.offset.toString());
|
|
113
|
+
if (params.archived !== undefined) searchParams.set('archived', params.archived.toString());
|
|
114
|
+
if (params.closed !== undefined) searchParams.set('closed', params.closed.toString());
|
|
115
|
+
if (params.active !== undefined) searchParams.set('active', params.active.toString());
|
|
116
|
+
if (params.order) searchParams.set('order', params.order);
|
|
117
|
+
if (params.order_dir) searchParams.set('order_dir', params.order_dir);
|
|
118
|
+
|
|
119
|
+
const response = await fetch(`${this.gammaApiBase}/markets?${searchParams.toString()}`);
|
|
120
|
+
if (!response.ok) {
|
|
121
|
+
throw new Error(`Gamma API error: ${response.status} ${response.statusText}`);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const data = await response.json();
|
|
125
|
+
return { markets: Array.isArray(data) ? data : [] };
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async getMarket(conditionId: string): Promise<{ market: PolymarketMarket }> {
|
|
129
|
+
const response = await fetch(`${this.gammaApiBase}/markets/${conditionId}`);
|
|
130
|
+
if (!response.ok) {
|
|
131
|
+
throw new Error(`Gamma API error: ${response.status} ${response.statusText}`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const data = await response.json() as PolymarketMarket;
|
|
135
|
+
return { market: data };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async listEvents(params: {
|
|
139
|
+
limit?: number;
|
|
140
|
+
offset?: number;
|
|
141
|
+
archived?: boolean;
|
|
142
|
+
closed?: boolean;
|
|
143
|
+
tag_id?: string;
|
|
144
|
+
} = {}): Promise<{ events: PolymarketEvent[] }> {
|
|
145
|
+
const searchParams = new URLSearchParams();
|
|
146
|
+
if (params.limit) searchParams.set('limit', params.limit.toString());
|
|
147
|
+
if (params.offset) searchParams.set('offset', params.offset.toString());
|
|
148
|
+
if (params.archived !== undefined) searchParams.set('archived', params.archived.toString());
|
|
149
|
+
if (params.closed !== undefined) searchParams.set('closed', params.closed.toString());
|
|
150
|
+
if (params.tag_id) searchParams.set('tag_id', params.tag_id);
|
|
151
|
+
|
|
152
|
+
const response = await fetch(`${this.gammaApiBase}/events?${searchParams.toString()}`);
|
|
153
|
+
if (!response.ok) {
|
|
154
|
+
throw new Error(`Gamma API error: ${response.status} ${response.statusText}`);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const data = await response.json();
|
|
158
|
+
return { events: Array.isArray(data) ? data : [] };
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async getEvent(eventSlug: string): Promise<{ event: PolymarketEvent }> {
|
|
162
|
+
const response = await fetch(`${this.gammaApiBase}/events/${eventSlug}`);
|
|
163
|
+
if (!response.ok) {
|
|
164
|
+
throw new Error(`Gamma API error: ${response.status} ${response.statusText}`);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const data = await response.json() as PolymarketEvent;
|
|
168
|
+
return { event: data };
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async getProfile(walletAddress: string): Promise<{ profile: PolymarketProfile }> {
|
|
172
|
+
const response = await fetch(`${this.gammaApiBase}/profiles/${walletAddress}`);
|
|
173
|
+
if (!response.ok) {
|
|
174
|
+
throw new Error(`Gamma API error: ${response.status} ${response.statusText}`);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const data = await response.json() as PolymarketProfile;
|
|
178
|
+
return { profile: data };
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async search(query: string, params: {
|
|
182
|
+
limit?: number;
|
|
183
|
+
offset?: number;
|
|
184
|
+
} = {}): Promise<any> {
|
|
185
|
+
const searchLower = query.toLowerCase();
|
|
186
|
+
const limit = params.limit || 20;
|
|
187
|
+
const offset = params.offset || 0;
|
|
188
|
+
|
|
189
|
+
// Try API search first (may require auth)
|
|
190
|
+
try {
|
|
191
|
+
const searchParams = new URLSearchParams();
|
|
192
|
+
searchParams.set('query', query);
|
|
193
|
+
if (params.limit) searchParams.set('limit', params.limit.toString());
|
|
194
|
+
if (params.offset) searchParams.set('offset', params.offset.toString());
|
|
195
|
+
|
|
196
|
+
const response = await fetch(`${this.gammaApiBase}/search?${searchParams.toString()}`);
|
|
197
|
+
|
|
198
|
+
if (response.ok) {
|
|
199
|
+
return response.json();
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
this.debugLog(`Search endpoint returned ${response.status}, falling back to client-side`);
|
|
203
|
+
} catch (error) {
|
|
204
|
+
this.debugLog('Search endpoint error:', error);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Client-side fallback
|
|
208
|
+
const fetchResult = await this.listMarkets({ limit: 500 });
|
|
209
|
+
const allMarkets = fetchResult.markets || [];
|
|
210
|
+
|
|
211
|
+
const filtered = allMarkets.filter((m: any) => {
|
|
212
|
+
const question = (m.question || '').toLowerCase();
|
|
213
|
+
const description = (m.description || '').toLowerCase();
|
|
214
|
+
const slug = (m.slug || '').toLowerCase();
|
|
215
|
+
const tags = ((m.tags || []) as string[]).join(' ').toLowerCase();
|
|
216
|
+
|
|
217
|
+
return (
|
|
218
|
+
question.includes(searchLower) ||
|
|
219
|
+
description.includes(searchLower) ||
|
|
220
|
+
slug.includes(searchLower) ||
|
|
221
|
+
tags.includes(searchLower)
|
|
222
|
+
);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
const paginated = filtered.slice(offset, offset + limit);
|
|
226
|
+
|
|
227
|
+
return {
|
|
228
|
+
markets: paginated,
|
|
229
|
+
total: filtered.length,
|
|
230
|
+
query,
|
|
231
|
+
note: 'Results filtered client-side',
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// ============================================================================
|
|
236
|
+
// CLOB API (Order Book & Trading)
|
|
237
|
+
// ============================================================================
|
|
238
|
+
|
|
239
|
+
async getOrderbook(tokenId: string): Promise<{ orderbook: PolymarketOrderBook }> {
|
|
240
|
+
const response = await fetch(`${this.clobApiBase}/orderbook?token_id=${tokenId}`);
|
|
241
|
+
if (!response.ok) {
|
|
242
|
+
throw new Error(`CLOB API error: ${response.status} ${response.statusText}`);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const data = await response.json() as PolymarketOrderBook;
|
|
246
|
+
return { orderbook: data };
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
async getTrades(tokenId: string, limit: number = 100): Promise<any> {
|
|
250
|
+
const response = await fetch(`${this.clobApiBase}/history?token_id=${tokenId}&limit=${limit}`);
|
|
251
|
+
if (!response.ok) {
|
|
252
|
+
throw new Error(`CLOB API error: ${response.status} ${response.statusText}`);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return response.json();
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
async getPrice(tokenId: string): Promise<{ price: number }> {
|
|
259
|
+
const response = await fetch(`${this.clobApiBase}/price?token_id=${tokenId}`);
|
|
260
|
+
if (!response.ok) {
|
|
261
|
+
throw new Error(`CLOB API error: ${response.status} ${response.statusText}`);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const data = await response.json() as { price: number };
|
|
265
|
+
return { price: data.price };
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// ============================================================================
|
|
269
|
+
// DATA API (User Data)
|
|
270
|
+
// ============================================================================
|
|
271
|
+
|
|
272
|
+
async getPositions(walletAddress: string): Promise<any> {
|
|
273
|
+
const response = await fetch(`${this.dataApiBase}/positions?wallet=${walletAddress}`);
|
|
274
|
+
if (!response.ok) {
|
|
275
|
+
throw new Error(`Data API error: ${response.status} ${response.statusText}`);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return response.json();
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
async getWalletTrades(walletAddress: string, params: {
|
|
282
|
+
limit?: number;
|
|
283
|
+
offset?: number;
|
|
284
|
+
} = {}): Promise<any> {
|
|
285
|
+
const searchParams = new URLSearchParams();
|
|
286
|
+
searchParams.set('wallet', walletAddress);
|
|
287
|
+
if (params.limit) searchParams.set('limit', params.limit.toString());
|
|
288
|
+
if (params.offset) searchParams.set('offset', params.offset.toString());
|
|
289
|
+
|
|
290
|
+
const response = await fetch(`${this.dataApiBase}/trades?${searchParams.toString()}`);
|
|
291
|
+
if (!response.ok) {
|
|
292
|
+
throw new Error(`Data API error: ${response.status} ${response.statusText}`);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return response.json();
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Create a new Polymarket client
|
|
301
|
+
*/
|
|
302
|
+
export function createPolymarketClient(config?: PolymarketClientConfig): PolymarketClient {
|
|
303
|
+
return new PolymarketClient(config);
|
|
304
|
+
}
|