@arbiterapi/sdk 0.1.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/index.cjs +151 -0
- package/dist/index.d.cts +299 -0
- package/dist/index.d.ts +299 -0
- package/dist/index.js +120 -0
- package/package.json +27 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
ArbiterClient: () => ArbiterClient,
|
|
24
|
+
ArbiterError: () => ArbiterError,
|
|
25
|
+
AuthenticationError: () => AuthenticationError,
|
|
26
|
+
BadRequestError: () => BadRequestError,
|
|
27
|
+
NotFoundError: () => NotFoundError
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(index_exports);
|
|
30
|
+
|
|
31
|
+
// src/errors.ts
|
|
32
|
+
var ArbiterError = class extends Error {
|
|
33
|
+
constructor(message, status, body) {
|
|
34
|
+
super(message);
|
|
35
|
+
this.status = status;
|
|
36
|
+
this.body = body;
|
|
37
|
+
this.name = "ArbiterError";
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
var NotFoundError = class extends ArbiterError {
|
|
41
|
+
constructor(message, body) {
|
|
42
|
+
super(message, 404, body);
|
|
43
|
+
this.name = "NotFoundError";
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
var BadRequestError = class extends ArbiterError {
|
|
47
|
+
constructor(message, body) {
|
|
48
|
+
super(message, 400, body);
|
|
49
|
+
this.name = "BadRequestError";
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
var AuthenticationError = class extends ArbiterError {
|
|
53
|
+
constructor(message, body) {
|
|
54
|
+
super(message, 401, body);
|
|
55
|
+
this.name = "AuthenticationError";
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// src/client.ts
|
|
60
|
+
var DEFAULT_BASE_URL = "https://api.arbiterapi.com";
|
|
61
|
+
var ArbiterClient = class {
|
|
62
|
+
apiKey;
|
|
63
|
+
baseUrl;
|
|
64
|
+
constructor(config) {
|
|
65
|
+
this.apiKey = config.apiKey;
|
|
66
|
+
this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
67
|
+
}
|
|
68
|
+
// ── Internal fetch helper ──
|
|
69
|
+
async request(path, params) {
|
|
70
|
+
const url = new URL(`${this.baseUrl}${path}`);
|
|
71
|
+
if (params) {
|
|
72
|
+
for (const [k, v] of Object.entries(params)) {
|
|
73
|
+
if (v !== void 0) url.searchParams.set(k, String(v));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const res = await fetch(url.toString(), {
|
|
77
|
+
headers: { "X-API-Key": this.apiKey }
|
|
78
|
+
});
|
|
79
|
+
if (!res.ok) {
|
|
80
|
+
const body = await res.json().catch(() => null);
|
|
81
|
+
const msg = body?.detail ?? res.statusText;
|
|
82
|
+
if (res.status === 401 || res.status === 403)
|
|
83
|
+
throw new AuthenticationError(msg, body);
|
|
84
|
+
if (res.status === 400) throw new BadRequestError(msg, body);
|
|
85
|
+
if (res.status === 404) throw new NotFoundError(msg, body);
|
|
86
|
+
throw new ArbiterError(msg, res.status, body);
|
|
87
|
+
}
|
|
88
|
+
return res.json();
|
|
89
|
+
}
|
|
90
|
+
// ── Public API ──
|
|
91
|
+
/** Health check (no auth required) */
|
|
92
|
+
async health() {
|
|
93
|
+
const res = await fetch(`${this.baseUrl}/health`);
|
|
94
|
+
return res.json();
|
|
95
|
+
}
|
|
96
|
+
/** Markets namespace */
|
|
97
|
+
markets = {
|
|
98
|
+
list: (params) => this.request("/v1/markets", params),
|
|
99
|
+
get: (marketId) => this.request(`/v1/markets/${encodeURIComponent(marketId)}`),
|
|
100
|
+
search: (params) => this.request("/v1/markets/search", params),
|
|
101
|
+
price: (marketId, params) => this.request(`/v1/markets/${encodeURIComponent(marketId)}/price`, params),
|
|
102
|
+
orderbook: (marketId) => this.request(`/v1/markets/${encodeURIComponent(marketId)}/orderbook`),
|
|
103
|
+
orderbookHistory: (marketId, params) => this.request(
|
|
104
|
+
`/v1/markets/${encodeURIComponent(marketId)}/orderbook/history`,
|
|
105
|
+
params
|
|
106
|
+
),
|
|
107
|
+
trades: (marketId, params) => this.request(
|
|
108
|
+
`/v1/markets/${encodeURIComponent(marketId)}/trades`,
|
|
109
|
+
params
|
|
110
|
+
),
|
|
111
|
+
candles: (marketId, params) => {
|
|
112
|
+
const query = {};
|
|
113
|
+
if (params?.interval) query.interval = params.interval;
|
|
114
|
+
if (params?.start) {
|
|
115
|
+
query.start_ts = params.start instanceof Date ? Math.floor(params.start.getTime() / 1e3) : params.start;
|
|
116
|
+
}
|
|
117
|
+
if (params?.end) {
|
|
118
|
+
query.end_ts = params.end instanceof Date ? Math.floor(params.end.getTime() / 1e3) : params.end;
|
|
119
|
+
}
|
|
120
|
+
return this.request(
|
|
121
|
+
`/v1/markets/${encodeURIComponent(marketId)}/candles`,
|
|
122
|
+
query
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
/** Events namespace */
|
|
127
|
+
events = {
|
|
128
|
+
list: (params) => this.request("/v1/events", params),
|
|
129
|
+
get: (slug) => this.request(`/v1/events/${encodeURIComponent(slug)}`)
|
|
130
|
+
};
|
|
131
|
+
/** Cross-platform matching namespace */
|
|
132
|
+
matching = {
|
|
133
|
+
list: (params) => this.request("/v1/matching-markets", params)
|
|
134
|
+
};
|
|
135
|
+
/** Wallets namespace (Polymarket) */
|
|
136
|
+
wallets = {
|
|
137
|
+
get: (address, params) => this.request(`/v1/wallets/${address}`, params),
|
|
138
|
+
trades: (address, params) => this.request(`/v1/wallets/${address}/trades`, params),
|
|
139
|
+
positions: (address, params) => this.request(`/v1/wallets/${address}/positions`, params),
|
|
140
|
+
pnl: (address) => this.request(`/v1/wallets/${address}/pnl`),
|
|
141
|
+
activity: (address, params) => this.request(`/v1/wallets/${address}/activity`, params)
|
|
142
|
+
};
|
|
143
|
+
};
|
|
144
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
145
|
+
0 && (module.exports = {
|
|
146
|
+
ArbiterClient,
|
|
147
|
+
ArbiterError,
|
|
148
|
+
AuthenticationError,
|
|
149
|
+
BadRequestError,
|
|
150
|
+
NotFoundError
|
|
151
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/** Platform identifiers */
|
|
2
|
+
type Platform = "polymarket" | "kalshi";
|
|
3
|
+
/** Market lifecycle status */
|
|
4
|
+
type MarketStatus = "open" | "closed" | "resolved";
|
|
5
|
+
/** Candle interval for OHLCV data */
|
|
6
|
+
type CandleInterval = "1m" | "5m" | "15m" | "1h" | "4h" | "1d";
|
|
7
|
+
/** Market outcome with current price */
|
|
8
|
+
interface Outcome {
|
|
9
|
+
label: string;
|
|
10
|
+
price: number;
|
|
11
|
+
price_cents: number;
|
|
12
|
+
}
|
|
13
|
+
/** Where a market is listed */
|
|
14
|
+
interface PlatformListing {
|
|
15
|
+
platform: Platform;
|
|
16
|
+
native_id: string;
|
|
17
|
+
url?: string;
|
|
18
|
+
best_bid?: number;
|
|
19
|
+
best_ask?: number;
|
|
20
|
+
volume_24h?: number;
|
|
21
|
+
}
|
|
22
|
+
/** Unified market object — the core data type */
|
|
23
|
+
interface Market {
|
|
24
|
+
id: string;
|
|
25
|
+
slug: string;
|
|
26
|
+
question: string;
|
|
27
|
+
description?: string;
|
|
28
|
+
status: MarketStatus;
|
|
29
|
+
outcomes: Outcome[];
|
|
30
|
+
platforms: PlatformListing[];
|
|
31
|
+
volume_24h: number;
|
|
32
|
+
volume_total?: number;
|
|
33
|
+
open_interest?: number;
|
|
34
|
+
created_at?: number;
|
|
35
|
+
close_time?: number;
|
|
36
|
+
tags: string[];
|
|
37
|
+
category?: string;
|
|
38
|
+
}
|
|
39
|
+
/** A single price level in the orderbook */
|
|
40
|
+
interface PriceLevel {
|
|
41
|
+
price: number;
|
|
42
|
+
size: number;
|
|
43
|
+
platform: Platform;
|
|
44
|
+
}
|
|
45
|
+
/** Orderbook snapshot */
|
|
46
|
+
interface OrderBook {
|
|
47
|
+
market_id: string;
|
|
48
|
+
bids: PriceLevel[];
|
|
49
|
+
asks: PriceLevel[];
|
|
50
|
+
spread: number;
|
|
51
|
+
mid_price: number;
|
|
52
|
+
timestamp_ms: number;
|
|
53
|
+
}
|
|
54
|
+
/** A single trade */
|
|
55
|
+
interface Trade {
|
|
56
|
+
id: string;
|
|
57
|
+
market_id: string;
|
|
58
|
+
platform: Platform;
|
|
59
|
+
price: number;
|
|
60
|
+
size: number;
|
|
61
|
+
side: string;
|
|
62
|
+
timestamp_ms: number;
|
|
63
|
+
native_trade_id?: string;
|
|
64
|
+
}
|
|
65
|
+
/** Paginated trades response */
|
|
66
|
+
interface TradesResponse {
|
|
67
|
+
market_id: string;
|
|
68
|
+
trades: Trade[];
|
|
69
|
+
cursor?: string;
|
|
70
|
+
has_more: boolean;
|
|
71
|
+
}
|
|
72
|
+
/** OHLCV candle */
|
|
73
|
+
interface Candle {
|
|
74
|
+
timestamp_ms: number;
|
|
75
|
+
open: number;
|
|
76
|
+
high: number;
|
|
77
|
+
low: number;
|
|
78
|
+
close: number;
|
|
79
|
+
volume?: number;
|
|
80
|
+
}
|
|
81
|
+
/** Candle response with metadata */
|
|
82
|
+
interface CandleResponse {
|
|
83
|
+
market_id: string;
|
|
84
|
+
interval: CandleInterval;
|
|
85
|
+
candles: Candle[];
|
|
86
|
+
}
|
|
87
|
+
/** Health check response */
|
|
88
|
+
interface HealthResponse {
|
|
89
|
+
status: string;
|
|
90
|
+
redis: boolean;
|
|
91
|
+
exchanges: {
|
|
92
|
+
polymarket: boolean;
|
|
93
|
+
kalshi: boolean;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
interface ListMarketsParams {
|
|
97
|
+
platform?: Platform;
|
|
98
|
+
status?: MarketStatus;
|
|
99
|
+
tag?: string;
|
|
100
|
+
min_volume?: number;
|
|
101
|
+
q?: string;
|
|
102
|
+
limit?: number;
|
|
103
|
+
offset?: number;
|
|
104
|
+
}
|
|
105
|
+
interface SearchMarketsParams {
|
|
106
|
+
q: string;
|
|
107
|
+
platform?: Platform;
|
|
108
|
+
status?: MarketStatus;
|
|
109
|
+
category?: string;
|
|
110
|
+
tag?: string;
|
|
111
|
+
min_volume?: number;
|
|
112
|
+
start_ts?: number;
|
|
113
|
+
end_ts?: number;
|
|
114
|
+
sort_by?: "volume" | "created_at";
|
|
115
|
+
limit?: number;
|
|
116
|
+
offset?: number;
|
|
117
|
+
}
|
|
118
|
+
interface GetTradesParams {
|
|
119
|
+
limit?: number;
|
|
120
|
+
cursor?: string;
|
|
121
|
+
}
|
|
122
|
+
interface GetCandlesParams {
|
|
123
|
+
interval?: CandleInterval;
|
|
124
|
+
start?: Date | number;
|
|
125
|
+
end?: Date | number;
|
|
126
|
+
}
|
|
127
|
+
interface PriceResponse {
|
|
128
|
+
market_id: string;
|
|
129
|
+
price: number;
|
|
130
|
+
at_time: number;
|
|
131
|
+
timestamp_ms: number;
|
|
132
|
+
platform: string;
|
|
133
|
+
source: string;
|
|
134
|
+
}
|
|
135
|
+
interface GetPriceParams {
|
|
136
|
+
at_time?: number;
|
|
137
|
+
}
|
|
138
|
+
interface OrderBookSnapshot {
|
|
139
|
+
market_id: string;
|
|
140
|
+
bids: PriceLevel[];
|
|
141
|
+
asks: PriceLevel[];
|
|
142
|
+
spread: number;
|
|
143
|
+
mid_price: number;
|
|
144
|
+
bid_depth?: number;
|
|
145
|
+
ask_depth?: number;
|
|
146
|
+
timestamp_ms: number;
|
|
147
|
+
}
|
|
148
|
+
interface OrderBookHistoryResponse {
|
|
149
|
+
market_id: string;
|
|
150
|
+
snapshots: OrderBookSnapshot[];
|
|
151
|
+
cursor?: string;
|
|
152
|
+
has_more: boolean;
|
|
153
|
+
}
|
|
154
|
+
interface GetOrderBookHistoryParams {
|
|
155
|
+
start_ts?: number;
|
|
156
|
+
end_ts?: number;
|
|
157
|
+
limit?: number;
|
|
158
|
+
cursor?: string;
|
|
159
|
+
}
|
|
160
|
+
interface Event {
|
|
161
|
+
slug: string;
|
|
162
|
+
title: string;
|
|
163
|
+
status: string;
|
|
164
|
+
markets: Market[];
|
|
165
|
+
market_count: number;
|
|
166
|
+
total_volume_24h: number;
|
|
167
|
+
total_volume?: number;
|
|
168
|
+
platforms: string[];
|
|
169
|
+
category?: string;
|
|
170
|
+
tags: string[];
|
|
171
|
+
}
|
|
172
|
+
interface EventsResponse {
|
|
173
|
+
events: Event[];
|
|
174
|
+
total: number;
|
|
175
|
+
limit: number;
|
|
176
|
+
offset: number;
|
|
177
|
+
}
|
|
178
|
+
interface ListEventsParams {
|
|
179
|
+
platform?: Platform;
|
|
180
|
+
status?: MarketStatus;
|
|
181
|
+
q?: string;
|
|
182
|
+
min_volume?: number;
|
|
183
|
+
limit?: number;
|
|
184
|
+
offset?: number;
|
|
185
|
+
}
|
|
186
|
+
interface MatchedMarket {
|
|
187
|
+
polymarket: Market;
|
|
188
|
+
kalshi: Market;
|
|
189
|
+
score: number;
|
|
190
|
+
confidence: "high" | "medium";
|
|
191
|
+
}
|
|
192
|
+
interface MatchingResponse {
|
|
193
|
+
matches: MatchedMarket[];
|
|
194
|
+
total: number;
|
|
195
|
+
}
|
|
196
|
+
interface GetMatchingParams {
|
|
197
|
+
min_score?: number;
|
|
198
|
+
confidence?: "high" | "medium";
|
|
199
|
+
q?: string;
|
|
200
|
+
limit?: number;
|
|
201
|
+
offset?: number;
|
|
202
|
+
}
|
|
203
|
+
interface WalletProfile {
|
|
204
|
+
address: string;
|
|
205
|
+
proxy_wallet: string;
|
|
206
|
+
pseudonym?: string;
|
|
207
|
+
bio?: string;
|
|
208
|
+
profile_image?: string;
|
|
209
|
+
platform: string;
|
|
210
|
+
portfolio_value?: any;
|
|
211
|
+
}
|
|
212
|
+
interface GetWalletTradesParams {
|
|
213
|
+
limit?: number;
|
|
214
|
+
offset?: number;
|
|
215
|
+
side?: "BUY" | "SELL";
|
|
216
|
+
}
|
|
217
|
+
interface GetWalletPositionsParams {
|
|
218
|
+
limit?: number;
|
|
219
|
+
sort_by?: "CURRENT" | "CASHPNL" | "PERCENTPNL" | "INITIAL" | "SIZE";
|
|
220
|
+
redeemable?: boolean;
|
|
221
|
+
}
|
|
222
|
+
interface WalletPnL {
|
|
223
|
+
address: string;
|
|
224
|
+
proxy_wallet: string;
|
|
225
|
+
total_pnl: number;
|
|
226
|
+
total_realized_pnl: number;
|
|
227
|
+
total_initial_value: number;
|
|
228
|
+
total_current_value: number;
|
|
229
|
+
positions_count: number;
|
|
230
|
+
winning_positions: number;
|
|
231
|
+
losing_positions: number;
|
|
232
|
+
platform: string;
|
|
233
|
+
}
|
|
234
|
+
interface GetWalletActivityParams {
|
|
235
|
+
limit?: number;
|
|
236
|
+
offset?: number;
|
|
237
|
+
activity_type?: "TRADE" | "SPLIT" | "MERGE" | "REDEEM" | "REWARD" | "CONVERSION";
|
|
238
|
+
}
|
|
239
|
+
/** SDK configuration */
|
|
240
|
+
interface ArbiterConfig {
|
|
241
|
+
apiKey: string;
|
|
242
|
+
baseUrl?: string;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
declare class ArbiterClient {
|
|
246
|
+
private apiKey;
|
|
247
|
+
private baseUrl;
|
|
248
|
+
constructor(config: ArbiterConfig);
|
|
249
|
+
private request;
|
|
250
|
+
/** Health check (no auth required) */
|
|
251
|
+
health(): Promise<HealthResponse>;
|
|
252
|
+
/** Markets namespace */
|
|
253
|
+
markets: {
|
|
254
|
+
list: (params?: ListMarketsParams) => Promise<Market[]>;
|
|
255
|
+
get: (marketId: string) => Promise<Market>;
|
|
256
|
+
search: (params: SearchMarketsParams) => Promise<Market[]>;
|
|
257
|
+
price: (marketId: string, params?: GetPriceParams) => Promise<PriceResponse>;
|
|
258
|
+
orderbook: (marketId: string) => Promise<OrderBook>;
|
|
259
|
+
orderbookHistory: (marketId: string, params?: GetOrderBookHistoryParams) => Promise<OrderBookHistoryResponse>;
|
|
260
|
+
trades: (marketId: string, params?: GetTradesParams) => Promise<TradesResponse>;
|
|
261
|
+
candles: (marketId: string, params?: GetCandlesParams) => Promise<CandleResponse>;
|
|
262
|
+
};
|
|
263
|
+
/** Events namespace */
|
|
264
|
+
events: {
|
|
265
|
+
list: (params?: ListEventsParams) => Promise<EventsResponse>;
|
|
266
|
+
get: (slug: string) => Promise<Event>;
|
|
267
|
+
};
|
|
268
|
+
/** Cross-platform matching namespace */
|
|
269
|
+
matching: {
|
|
270
|
+
list: (params?: GetMatchingParams) => Promise<MatchingResponse>;
|
|
271
|
+
};
|
|
272
|
+
/** Wallets namespace (Polymarket) */
|
|
273
|
+
wallets: {
|
|
274
|
+
get: (address: string, params?: {
|
|
275
|
+
with_metrics?: boolean;
|
|
276
|
+
}) => Promise<WalletProfile>;
|
|
277
|
+
trades: (address: string, params?: GetWalletTradesParams) => Promise<any[]>;
|
|
278
|
+
positions: (address: string, params?: GetWalletPositionsParams) => Promise<any[]>;
|
|
279
|
+
pnl: (address: string) => Promise<WalletPnL>;
|
|
280
|
+
activity: (address: string, params?: GetWalletActivityParams) => Promise<any[]>;
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
declare class ArbiterError extends Error {
|
|
285
|
+
status: number;
|
|
286
|
+
body?: unknown | undefined;
|
|
287
|
+
constructor(message: string, status: number, body?: unknown | undefined);
|
|
288
|
+
}
|
|
289
|
+
declare class NotFoundError extends ArbiterError {
|
|
290
|
+
constructor(message: string, body?: unknown);
|
|
291
|
+
}
|
|
292
|
+
declare class BadRequestError extends ArbiterError {
|
|
293
|
+
constructor(message: string, body?: unknown);
|
|
294
|
+
}
|
|
295
|
+
declare class AuthenticationError extends ArbiterError {
|
|
296
|
+
constructor(message: string, body?: unknown);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export { ArbiterClient, type ArbiterConfig, ArbiterError, AuthenticationError, BadRequestError, type Candle, type CandleInterval, type CandleResponse, type GetCandlesParams, type GetTradesParams, type HealthResponse, type ListMarketsParams, type Market, type MarketStatus, NotFoundError, type OrderBook, type Outcome, type Platform, type PlatformListing, type PriceLevel, type SearchMarketsParams, type Trade, type TradesResponse };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/** Platform identifiers */
|
|
2
|
+
type Platform = "polymarket" | "kalshi";
|
|
3
|
+
/** Market lifecycle status */
|
|
4
|
+
type MarketStatus = "open" | "closed" | "resolved";
|
|
5
|
+
/** Candle interval for OHLCV data */
|
|
6
|
+
type CandleInterval = "1m" | "5m" | "15m" | "1h" | "4h" | "1d";
|
|
7
|
+
/** Market outcome with current price */
|
|
8
|
+
interface Outcome {
|
|
9
|
+
label: string;
|
|
10
|
+
price: number;
|
|
11
|
+
price_cents: number;
|
|
12
|
+
}
|
|
13
|
+
/** Where a market is listed */
|
|
14
|
+
interface PlatformListing {
|
|
15
|
+
platform: Platform;
|
|
16
|
+
native_id: string;
|
|
17
|
+
url?: string;
|
|
18
|
+
best_bid?: number;
|
|
19
|
+
best_ask?: number;
|
|
20
|
+
volume_24h?: number;
|
|
21
|
+
}
|
|
22
|
+
/** Unified market object — the core data type */
|
|
23
|
+
interface Market {
|
|
24
|
+
id: string;
|
|
25
|
+
slug: string;
|
|
26
|
+
question: string;
|
|
27
|
+
description?: string;
|
|
28
|
+
status: MarketStatus;
|
|
29
|
+
outcomes: Outcome[];
|
|
30
|
+
platforms: PlatformListing[];
|
|
31
|
+
volume_24h: number;
|
|
32
|
+
volume_total?: number;
|
|
33
|
+
open_interest?: number;
|
|
34
|
+
created_at?: number;
|
|
35
|
+
close_time?: number;
|
|
36
|
+
tags: string[];
|
|
37
|
+
category?: string;
|
|
38
|
+
}
|
|
39
|
+
/** A single price level in the orderbook */
|
|
40
|
+
interface PriceLevel {
|
|
41
|
+
price: number;
|
|
42
|
+
size: number;
|
|
43
|
+
platform: Platform;
|
|
44
|
+
}
|
|
45
|
+
/** Orderbook snapshot */
|
|
46
|
+
interface OrderBook {
|
|
47
|
+
market_id: string;
|
|
48
|
+
bids: PriceLevel[];
|
|
49
|
+
asks: PriceLevel[];
|
|
50
|
+
spread: number;
|
|
51
|
+
mid_price: number;
|
|
52
|
+
timestamp_ms: number;
|
|
53
|
+
}
|
|
54
|
+
/** A single trade */
|
|
55
|
+
interface Trade {
|
|
56
|
+
id: string;
|
|
57
|
+
market_id: string;
|
|
58
|
+
platform: Platform;
|
|
59
|
+
price: number;
|
|
60
|
+
size: number;
|
|
61
|
+
side: string;
|
|
62
|
+
timestamp_ms: number;
|
|
63
|
+
native_trade_id?: string;
|
|
64
|
+
}
|
|
65
|
+
/** Paginated trades response */
|
|
66
|
+
interface TradesResponse {
|
|
67
|
+
market_id: string;
|
|
68
|
+
trades: Trade[];
|
|
69
|
+
cursor?: string;
|
|
70
|
+
has_more: boolean;
|
|
71
|
+
}
|
|
72
|
+
/** OHLCV candle */
|
|
73
|
+
interface Candle {
|
|
74
|
+
timestamp_ms: number;
|
|
75
|
+
open: number;
|
|
76
|
+
high: number;
|
|
77
|
+
low: number;
|
|
78
|
+
close: number;
|
|
79
|
+
volume?: number;
|
|
80
|
+
}
|
|
81
|
+
/** Candle response with metadata */
|
|
82
|
+
interface CandleResponse {
|
|
83
|
+
market_id: string;
|
|
84
|
+
interval: CandleInterval;
|
|
85
|
+
candles: Candle[];
|
|
86
|
+
}
|
|
87
|
+
/** Health check response */
|
|
88
|
+
interface HealthResponse {
|
|
89
|
+
status: string;
|
|
90
|
+
redis: boolean;
|
|
91
|
+
exchanges: {
|
|
92
|
+
polymarket: boolean;
|
|
93
|
+
kalshi: boolean;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
interface ListMarketsParams {
|
|
97
|
+
platform?: Platform;
|
|
98
|
+
status?: MarketStatus;
|
|
99
|
+
tag?: string;
|
|
100
|
+
min_volume?: number;
|
|
101
|
+
q?: string;
|
|
102
|
+
limit?: number;
|
|
103
|
+
offset?: number;
|
|
104
|
+
}
|
|
105
|
+
interface SearchMarketsParams {
|
|
106
|
+
q: string;
|
|
107
|
+
platform?: Platform;
|
|
108
|
+
status?: MarketStatus;
|
|
109
|
+
category?: string;
|
|
110
|
+
tag?: string;
|
|
111
|
+
min_volume?: number;
|
|
112
|
+
start_ts?: number;
|
|
113
|
+
end_ts?: number;
|
|
114
|
+
sort_by?: "volume" | "created_at";
|
|
115
|
+
limit?: number;
|
|
116
|
+
offset?: number;
|
|
117
|
+
}
|
|
118
|
+
interface GetTradesParams {
|
|
119
|
+
limit?: number;
|
|
120
|
+
cursor?: string;
|
|
121
|
+
}
|
|
122
|
+
interface GetCandlesParams {
|
|
123
|
+
interval?: CandleInterval;
|
|
124
|
+
start?: Date | number;
|
|
125
|
+
end?: Date | number;
|
|
126
|
+
}
|
|
127
|
+
interface PriceResponse {
|
|
128
|
+
market_id: string;
|
|
129
|
+
price: number;
|
|
130
|
+
at_time: number;
|
|
131
|
+
timestamp_ms: number;
|
|
132
|
+
platform: string;
|
|
133
|
+
source: string;
|
|
134
|
+
}
|
|
135
|
+
interface GetPriceParams {
|
|
136
|
+
at_time?: number;
|
|
137
|
+
}
|
|
138
|
+
interface OrderBookSnapshot {
|
|
139
|
+
market_id: string;
|
|
140
|
+
bids: PriceLevel[];
|
|
141
|
+
asks: PriceLevel[];
|
|
142
|
+
spread: number;
|
|
143
|
+
mid_price: number;
|
|
144
|
+
bid_depth?: number;
|
|
145
|
+
ask_depth?: number;
|
|
146
|
+
timestamp_ms: number;
|
|
147
|
+
}
|
|
148
|
+
interface OrderBookHistoryResponse {
|
|
149
|
+
market_id: string;
|
|
150
|
+
snapshots: OrderBookSnapshot[];
|
|
151
|
+
cursor?: string;
|
|
152
|
+
has_more: boolean;
|
|
153
|
+
}
|
|
154
|
+
interface GetOrderBookHistoryParams {
|
|
155
|
+
start_ts?: number;
|
|
156
|
+
end_ts?: number;
|
|
157
|
+
limit?: number;
|
|
158
|
+
cursor?: string;
|
|
159
|
+
}
|
|
160
|
+
interface Event {
|
|
161
|
+
slug: string;
|
|
162
|
+
title: string;
|
|
163
|
+
status: string;
|
|
164
|
+
markets: Market[];
|
|
165
|
+
market_count: number;
|
|
166
|
+
total_volume_24h: number;
|
|
167
|
+
total_volume?: number;
|
|
168
|
+
platforms: string[];
|
|
169
|
+
category?: string;
|
|
170
|
+
tags: string[];
|
|
171
|
+
}
|
|
172
|
+
interface EventsResponse {
|
|
173
|
+
events: Event[];
|
|
174
|
+
total: number;
|
|
175
|
+
limit: number;
|
|
176
|
+
offset: number;
|
|
177
|
+
}
|
|
178
|
+
interface ListEventsParams {
|
|
179
|
+
platform?: Platform;
|
|
180
|
+
status?: MarketStatus;
|
|
181
|
+
q?: string;
|
|
182
|
+
min_volume?: number;
|
|
183
|
+
limit?: number;
|
|
184
|
+
offset?: number;
|
|
185
|
+
}
|
|
186
|
+
interface MatchedMarket {
|
|
187
|
+
polymarket: Market;
|
|
188
|
+
kalshi: Market;
|
|
189
|
+
score: number;
|
|
190
|
+
confidence: "high" | "medium";
|
|
191
|
+
}
|
|
192
|
+
interface MatchingResponse {
|
|
193
|
+
matches: MatchedMarket[];
|
|
194
|
+
total: number;
|
|
195
|
+
}
|
|
196
|
+
interface GetMatchingParams {
|
|
197
|
+
min_score?: number;
|
|
198
|
+
confidence?: "high" | "medium";
|
|
199
|
+
q?: string;
|
|
200
|
+
limit?: number;
|
|
201
|
+
offset?: number;
|
|
202
|
+
}
|
|
203
|
+
interface WalletProfile {
|
|
204
|
+
address: string;
|
|
205
|
+
proxy_wallet: string;
|
|
206
|
+
pseudonym?: string;
|
|
207
|
+
bio?: string;
|
|
208
|
+
profile_image?: string;
|
|
209
|
+
platform: string;
|
|
210
|
+
portfolio_value?: any;
|
|
211
|
+
}
|
|
212
|
+
interface GetWalletTradesParams {
|
|
213
|
+
limit?: number;
|
|
214
|
+
offset?: number;
|
|
215
|
+
side?: "BUY" | "SELL";
|
|
216
|
+
}
|
|
217
|
+
interface GetWalletPositionsParams {
|
|
218
|
+
limit?: number;
|
|
219
|
+
sort_by?: "CURRENT" | "CASHPNL" | "PERCENTPNL" | "INITIAL" | "SIZE";
|
|
220
|
+
redeemable?: boolean;
|
|
221
|
+
}
|
|
222
|
+
interface WalletPnL {
|
|
223
|
+
address: string;
|
|
224
|
+
proxy_wallet: string;
|
|
225
|
+
total_pnl: number;
|
|
226
|
+
total_realized_pnl: number;
|
|
227
|
+
total_initial_value: number;
|
|
228
|
+
total_current_value: number;
|
|
229
|
+
positions_count: number;
|
|
230
|
+
winning_positions: number;
|
|
231
|
+
losing_positions: number;
|
|
232
|
+
platform: string;
|
|
233
|
+
}
|
|
234
|
+
interface GetWalletActivityParams {
|
|
235
|
+
limit?: number;
|
|
236
|
+
offset?: number;
|
|
237
|
+
activity_type?: "TRADE" | "SPLIT" | "MERGE" | "REDEEM" | "REWARD" | "CONVERSION";
|
|
238
|
+
}
|
|
239
|
+
/** SDK configuration */
|
|
240
|
+
interface ArbiterConfig {
|
|
241
|
+
apiKey: string;
|
|
242
|
+
baseUrl?: string;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
declare class ArbiterClient {
|
|
246
|
+
private apiKey;
|
|
247
|
+
private baseUrl;
|
|
248
|
+
constructor(config: ArbiterConfig);
|
|
249
|
+
private request;
|
|
250
|
+
/** Health check (no auth required) */
|
|
251
|
+
health(): Promise<HealthResponse>;
|
|
252
|
+
/** Markets namespace */
|
|
253
|
+
markets: {
|
|
254
|
+
list: (params?: ListMarketsParams) => Promise<Market[]>;
|
|
255
|
+
get: (marketId: string) => Promise<Market>;
|
|
256
|
+
search: (params: SearchMarketsParams) => Promise<Market[]>;
|
|
257
|
+
price: (marketId: string, params?: GetPriceParams) => Promise<PriceResponse>;
|
|
258
|
+
orderbook: (marketId: string) => Promise<OrderBook>;
|
|
259
|
+
orderbookHistory: (marketId: string, params?: GetOrderBookHistoryParams) => Promise<OrderBookHistoryResponse>;
|
|
260
|
+
trades: (marketId: string, params?: GetTradesParams) => Promise<TradesResponse>;
|
|
261
|
+
candles: (marketId: string, params?: GetCandlesParams) => Promise<CandleResponse>;
|
|
262
|
+
};
|
|
263
|
+
/** Events namespace */
|
|
264
|
+
events: {
|
|
265
|
+
list: (params?: ListEventsParams) => Promise<EventsResponse>;
|
|
266
|
+
get: (slug: string) => Promise<Event>;
|
|
267
|
+
};
|
|
268
|
+
/** Cross-platform matching namespace */
|
|
269
|
+
matching: {
|
|
270
|
+
list: (params?: GetMatchingParams) => Promise<MatchingResponse>;
|
|
271
|
+
};
|
|
272
|
+
/** Wallets namespace (Polymarket) */
|
|
273
|
+
wallets: {
|
|
274
|
+
get: (address: string, params?: {
|
|
275
|
+
with_metrics?: boolean;
|
|
276
|
+
}) => Promise<WalletProfile>;
|
|
277
|
+
trades: (address: string, params?: GetWalletTradesParams) => Promise<any[]>;
|
|
278
|
+
positions: (address: string, params?: GetWalletPositionsParams) => Promise<any[]>;
|
|
279
|
+
pnl: (address: string) => Promise<WalletPnL>;
|
|
280
|
+
activity: (address: string, params?: GetWalletActivityParams) => Promise<any[]>;
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
declare class ArbiterError extends Error {
|
|
285
|
+
status: number;
|
|
286
|
+
body?: unknown | undefined;
|
|
287
|
+
constructor(message: string, status: number, body?: unknown | undefined);
|
|
288
|
+
}
|
|
289
|
+
declare class NotFoundError extends ArbiterError {
|
|
290
|
+
constructor(message: string, body?: unknown);
|
|
291
|
+
}
|
|
292
|
+
declare class BadRequestError extends ArbiterError {
|
|
293
|
+
constructor(message: string, body?: unknown);
|
|
294
|
+
}
|
|
295
|
+
declare class AuthenticationError extends ArbiterError {
|
|
296
|
+
constructor(message: string, body?: unknown);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export { ArbiterClient, type ArbiterConfig, ArbiterError, AuthenticationError, BadRequestError, type Candle, type CandleInterval, type CandleResponse, type GetCandlesParams, type GetTradesParams, type HealthResponse, type ListMarketsParams, type Market, type MarketStatus, NotFoundError, type OrderBook, type Outcome, type Platform, type PlatformListing, type PriceLevel, type SearchMarketsParams, type Trade, type TradesResponse };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
var ArbiterError = class extends Error {
|
|
3
|
+
constructor(message, status, body) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.status = status;
|
|
6
|
+
this.body = body;
|
|
7
|
+
this.name = "ArbiterError";
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
var NotFoundError = class extends ArbiterError {
|
|
11
|
+
constructor(message, body) {
|
|
12
|
+
super(message, 404, body);
|
|
13
|
+
this.name = "NotFoundError";
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
var BadRequestError = class extends ArbiterError {
|
|
17
|
+
constructor(message, body) {
|
|
18
|
+
super(message, 400, body);
|
|
19
|
+
this.name = "BadRequestError";
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
var AuthenticationError = class extends ArbiterError {
|
|
23
|
+
constructor(message, body) {
|
|
24
|
+
super(message, 401, body);
|
|
25
|
+
this.name = "AuthenticationError";
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// src/client.ts
|
|
30
|
+
var DEFAULT_BASE_URL = "https://api.arbiterapi.com";
|
|
31
|
+
var ArbiterClient = class {
|
|
32
|
+
apiKey;
|
|
33
|
+
baseUrl;
|
|
34
|
+
constructor(config) {
|
|
35
|
+
this.apiKey = config.apiKey;
|
|
36
|
+
this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
37
|
+
}
|
|
38
|
+
// ── Internal fetch helper ──
|
|
39
|
+
async request(path, params) {
|
|
40
|
+
const url = new URL(`${this.baseUrl}${path}`);
|
|
41
|
+
if (params) {
|
|
42
|
+
for (const [k, v] of Object.entries(params)) {
|
|
43
|
+
if (v !== void 0) url.searchParams.set(k, String(v));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const res = await fetch(url.toString(), {
|
|
47
|
+
headers: { "X-API-Key": this.apiKey }
|
|
48
|
+
});
|
|
49
|
+
if (!res.ok) {
|
|
50
|
+
const body = await res.json().catch(() => null);
|
|
51
|
+
const msg = body?.detail ?? res.statusText;
|
|
52
|
+
if (res.status === 401 || res.status === 403)
|
|
53
|
+
throw new AuthenticationError(msg, body);
|
|
54
|
+
if (res.status === 400) throw new BadRequestError(msg, body);
|
|
55
|
+
if (res.status === 404) throw new NotFoundError(msg, body);
|
|
56
|
+
throw new ArbiterError(msg, res.status, body);
|
|
57
|
+
}
|
|
58
|
+
return res.json();
|
|
59
|
+
}
|
|
60
|
+
// ── Public API ──
|
|
61
|
+
/** Health check (no auth required) */
|
|
62
|
+
async health() {
|
|
63
|
+
const res = await fetch(`${this.baseUrl}/health`);
|
|
64
|
+
return res.json();
|
|
65
|
+
}
|
|
66
|
+
/** Markets namespace */
|
|
67
|
+
markets = {
|
|
68
|
+
list: (params) => this.request("/v1/markets", params),
|
|
69
|
+
get: (marketId) => this.request(`/v1/markets/${encodeURIComponent(marketId)}`),
|
|
70
|
+
search: (params) => this.request("/v1/markets/search", params),
|
|
71
|
+
price: (marketId, params) => this.request(`/v1/markets/${encodeURIComponent(marketId)}/price`, params),
|
|
72
|
+
orderbook: (marketId) => this.request(`/v1/markets/${encodeURIComponent(marketId)}/orderbook`),
|
|
73
|
+
orderbookHistory: (marketId, params) => this.request(
|
|
74
|
+
`/v1/markets/${encodeURIComponent(marketId)}/orderbook/history`,
|
|
75
|
+
params
|
|
76
|
+
),
|
|
77
|
+
trades: (marketId, params) => this.request(
|
|
78
|
+
`/v1/markets/${encodeURIComponent(marketId)}/trades`,
|
|
79
|
+
params
|
|
80
|
+
),
|
|
81
|
+
candles: (marketId, params) => {
|
|
82
|
+
const query = {};
|
|
83
|
+
if (params?.interval) query.interval = params.interval;
|
|
84
|
+
if (params?.start) {
|
|
85
|
+
query.start_ts = params.start instanceof Date ? Math.floor(params.start.getTime() / 1e3) : params.start;
|
|
86
|
+
}
|
|
87
|
+
if (params?.end) {
|
|
88
|
+
query.end_ts = params.end instanceof Date ? Math.floor(params.end.getTime() / 1e3) : params.end;
|
|
89
|
+
}
|
|
90
|
+
return this.request(
|
|
91
|
+
`/v1/markets/${encodeURIComponent(marketId)}/candles`,
|
|
92
|
+
query
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
/** Events namespace */
|
|
97
|
+
events = {
|
|
98
|
+
list: (params) => this.request("/v1/events", params),
|
|
99
|
+
get: (slug) => this.request(`/v1/events/${encodeURIComponent(slug)}`)
|
|
100
|
+
};
|
|
101
|
+
/** Cross-platform matching namespace */
|
|
102
|
+
matching = {
|
|
103
|
+
list: (params) => this.request("/v1/matching-markets", params)
|
|
104
|
+
};
|
|
105
|
+
/** Wallets namespace (Polymarket) */
|
|
106
|
+
wallets = {
|
|
107
|
+
get: (address, params) => this.request(`/v1/wallets/${address}`, params),
|
|
108
|
+
trades: (address, params) => this.request(`/v1/wallets/${address}/trades`, params),
|
|
109
|
+
positions: (address, params) => this.request(`/v1/wallets/${address}/positions`, params),
|
|
110
|
+
pnl: (address) => this.request(`/v1/wallets/${address}/pnl`),
|
|
111
|
+
activity: (address, params) => this.request(`/v1/wallets/${address}/activity`, params)
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
export {
|
|
115
|
+
ArbiterClient,
|
|
116
|
+
ArbiterError,
|
|
117
|
+
AuthenticationError,
|
|
118
|
+
BadRequestError,
|
|
119
|
+
NotFoundError
|
|
120
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@arbiterapi/sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "TypeScript SDK for the Arbiter prediction market API",
|
|
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
|
+
"require": "./dist/index.cjs"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": ["dist"],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsup src/index.ts --format esm,cjs --dts",
|
|
18
|
+
"dev": "tsup src/index.ts --format esm,cjs --dts --watch",
|
|
19
|
+
"typecheck": "tsc --noEmit"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"tsup": "^8.0.0",
|
|
23
|
+
"typescript": "^5.5.0"
|
|
24
|
+
},
|
|
25
|
+
"keywords": ["prediction-markets", "polymarket", "kalshi", "api"],
|
|
26
|
+
"license": "MIT"
|
|
27
|
+
}
|