@limitless-exchange/sdk 1.0.1 → 1.0.3

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.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { AxiosRequestConfig } from 'axios';
1
+ import { AxiosRequestConfig, RawAxiosResponseHeaders, AxiosResponseHeaders } from 'axios';
2
2
  import { ethers } from 'ethers';
3
3
 
4
4
  /**
@@ -1096,11 +1096,15 @@ interface MarketSettings {
1096
1096
  /**
1097
1097
  * Rewards epoch duration
1098
1098
  */
1099
- rewardsEpoch: string;
1099
+ rewardsEpoch: string | number;
1100
1100
  /**
1101
1101
  * Constant parameter
1102
1102
  */
1103
- c: string;
1103
+ c: string | number;
1104
+ /**
1105
+ * Market maker rebate rate.
1106
+ */
1107
+ rebateRate?: number;
1104
1108
  }
1105
1109
  /**
1106
1110
  * Trade prices for different order types.
@@ -1257,7 +1261,7 @@ interface Venue {
1257
1261
  * Required for NegRisk/Grouped markets only.
1258
1262
  * SELL orders on NegRisk markets require CT approval to both exchange AND adapter.
1259
1263
  */
1260
- adapter: string;
1264
+ adapter: string | null;
1261
1265
  }
1262
1266
  /**
1263
1267
  * Market token IDs for CLOB markets.
@@ -1358,6 +1362,38 @@ interface Market$1 {
1358
1362
  * Formatted trading volume
1359
1363
  */
1360
1364
  volumeFormatted?: string;
1365
+ /**
1366
+ * Market automation type.
1367
+ */
1368
+ automationType?: 'manual' | 'lumy' | 'sports';
1369
+ /**
1370
+ * Primary market image URL.
1371
+ */
1372
+ imageUrl?: string | null;
1373
+ /**
1374
+ * Price trend data.
1375
+ */
1376
+ trends?: Record<string, unknown>;
1377
+ /**
1378
+ * Open interest (AMM markets).
1379
+ */
1380
+ openInterest?: string;
1381
+ /**
1382
+ * Formatted open interest (AMM markets).
1383
+ */
1384
+ openInterestFormatted?: string;
1385
+ /**
1386
+ * Liquidity (AMM markets).
1387
+ */
1388
+ liquidity?: string;
1389
+ /**
1390
+ * Formatted liquidity (AMM markets).
1391
+ */
1392
+ liquidityFormatted?: string;
1393
+ /**
1394
+ * Position IDs (AMM markets).
1395
+ */
1396
+ positionIds?: string[];
1361
1397
  /**
1362
1398
  * Condition ID (CLOB only)
1363
1399
  */
@@ -1897,6 +1933,28 @@ interface HttpClientConfig {
1897
1933
  */
1898
1934
  additionalHeaders?: Record<string, string>;
1899
1935
  }
1936
+ /**
1937
+ * Raw HTTP response with status and headers.
1938
+ *
1939
+ * @remarks
1940
+ * Useful for endpoints where response metadata matters (for example redirect handling).
1941
+ *
1942
+ * @public
1943
+ */
1944
+ interface HttpRawResponse<T = any> {
1945
+ /**
1946
+ * HTTP status code.
1947
+ */
1948
+ status: number;
1949
+ /**
1950
+ * Response headers.
1951
+ */
1952
+ headers: RawAxiosResponseHeaders | AxiosResponseHeaders;
1953
+ /**
1954
+ * Response body.
1955
+ */
1956
+ data: T;
1957
+ }
1900
1958
  /**
1901
1959
  * HTTP client wrapper for Limitless Exchange API.
1902
1960
  *
@@ -1921,6 +1979,16 @@ declare class HttpClient {
1921
1979
  * @internal
1922
1980
  */
1923
1981
  private setupInterceptors;
1982
+ /**
1983
+ * Extracts a human-readable error message from API response payload.
1984
+ * @internal
1985
+ */
1986
+ private extractErrorMessage;
1987
+ /**
1988
+ * Creates a typed API error class from status code.
1989
+ * @internal
1990
+ */
1991
+ private createTypedApiError;
1924
1992
  /**
1925
1993
  * Sets the API key for authenticated requests.
1926
1994
  *
@@ -1939,6 +2007,17 @@ declare class HttpClient {
1939
2007
  * @returns Promise resolving to the response data
1940
2008
  */
1941
2009
  get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>;
2010
+ /**
2011
+ * Performs a GET request and returns raw response metadata.
2012
+ *
2013
+ * @remarks
2014
+ * Use this when callers need access to status code or headers (e.g. redirect `Location`).
2015
+ *
2016
+ * @param url - Request URL
2017
+ * @param config - Additional request configuration
2018
+ * @returns Promise resolving to status, headers, and response data
2019
+ */
2020
+ getRaw<T = any>(url: string, config?: AxiosRequestConfig): Promise<HttpRawResponse<T>>;
1942
2021
  /**
1943
2022
  * Performs a POST request.
1944
2023
  *
@@ -1998,6 +2077,14 @@ declare class Market {
1998
2077
  metadata: MarketMetadata;
1999
2078
  volume?: string;
2000
2079
  volumeFormatted?: string;
2080
+ automationType?: 'manual' | 'lumy' | 'sports';
2081
+ imageUrl?: string | null;
2082
+ trends?: Record<string, unknown>;
2083
+ openInterest?: string;
2084
+ openInterestFormatted?: string;
2085
+ liquidity?: string;
2086
+ liquidityFormatted?: string;
2087
+ positionIds?: string[];
2001
2088
  conditionId?: string;
2002
2089
  negRiskRequestId?: string | null;
2003
2090
  tokens?: MarketTokens;
@@ -2048,6 +2135,159 @@ declare class Market {
2048
2135
  getUserOrders(): Promise<any[]>;
2049
2136
  }
2050
2137
 
2138
+ /**
2139
+ * Navigation node returned by /navigation endpoint.
2140
+ * @public
2141
+ */
2142
+ interface NavigationNode {
2143
+ id: string;
2144
+ name: string;
2145
+ slug: string;
2146
+ path: string;
2147
+ icon?: string;
2148
+ children: NavigationNode[];
2149
+ }
2150
+ /**
2151
+ * Filter group option for market pages.
2152
+ * @public
2153
+ */
2154
+ interface FilterGroupOption {
2155
+ label: string;
2156
+ value: string;
2157
+ metadata?: Record<string, unknown>;
2158
+ }
2159
+ /**
2160
+ * Filter group for market pages.
2161
+ * @public
2162
+ */
2163
+ interface FilterGroup {
2164
+ name?: string;
2165
+ slug?: string;
2166
+ allowMultiple?: boolean;
2167
+ presentation?: string;
2168
+ options?: FilterGroupOption[];
2169
+ source?: Record<string, unknown>;
2170
+ }
2171
+ /**
2172
+ * Breadcrumb item returned by /market-pages/by-path endpoint.
2173
+ * @public
2174
+ */
2175
+ interface BreadcrumbItem {
2176
+ name: string;
2177
+ slug: string;
2178
+ path: string;
2179
+ }
2180
+ /**
2181
+ * Market page data resolved by path.
2182
+ * @public
2183
+ */
2184
+ interface MarketPage {
2185
+ id: string;
2186
+ name: string;
2187
+ slug: string;
2188
+ fullPath: string;
2189
+ description: string | null;
2190
+ baseFilter: Record<string, unknown>;
2191
+ filterGroups: FilterGroup[];
2192
+ metadata: Record<string, unknown>;
2193
+ breadcrumb: BreadcrumbItem[];
2194
+ }
2195
+ /**
2196
+ * Property option returned by property-keys endpoints.
2197
+ * @public
2198
+ */
2199
+ interface PropertyOption {
2200
+ id: string;
2201
+ propertyKeyId: string;
2202
+ value: string;
2203
+ label: string;
2204
+ sortOrder: number;
2205
+ parentOptionId: string | null;
2206
+ metadata: Record<string, unknown>;
2207
+ createdAt: string;
2208
+ updatedAt: string;
2209
+ }
2210
+ /**
2211
+ * Property key returned by property-keys endpoints.
2212
+ * @public
2213
+ */
2214
+ interface PropertyKey {
2215
+ id: string;
2216
+ name: string;
2217
+ slug: string;
2218
+ type: 'select' | 'multi-select';
2219
+ metadata: Record<string, unknown>;
2220
+ isSystem: boolean;
2221
+ options?: PropertyOption[];
2222
+ createdAt: string;
2223
+ updatedAt: string;
2224
+ }
2225
+ /**
2226
+ * Offset pagination metadata.
2227
+ * @public
2228
+ */
2229
+ interface OffsetPagination {
2230
+ page: number;
2231
+ limit: number;
2232
+ total: number;
2233
+ totalPages: number;
2234
+ }
2235
+ /**
2236
+ * Cursor pagination metadata.
2237
+ * @public
2238
+ */
2239
+ interface CursorPagination {
2240
+ nextCursor: string | null;
2241
+ }
2242
+ /**
2243
+ * Sort field for market-pages market listing.
2244
+ * @public
2245
+ */
2246
+ type MarketPageSortField = 'createdAt' | 'updatedAt' | 'deadline' | 'id';
2247
+ /**
2248
+ * Sort value for market-pages market listing.
2249
+ * @public
2250
+ */
2251
+ type MarketPageSort = MarketPageSortField | `-${MarketPageSortField}`;
2252
+ /**
2253
+ * Query params for /market-pages/:id/markets endpoint.
2254
+ * @public
2255
+ */
2256
+ type MarketPageFilterPrimitive = string | number | boolean;
2257
+ type MarketPageFilterValue = MarketPageFilterPrimitive | MarketPageFilterPrimitive[];
2258
+ /**
2259
+ * Query params for /market-pages/:id/markets endpoint.
2260
+ * @public
2261
+ */
2262
+ interface MarketPageMarketsParams {
2263
+ page?: number;
2264
+ limit?: number;
2265
+ sort?: MarketPageSort;
2266
+ cursor?: string;
2267
+ filters?: Record<string, MarketPageFilterValue>;
2268
+ }
2269
+ /**
2270
+ * Offset response for /market-pages/:id/markets endpoint.
2271
+ * @public
2272
+ */
2273
+ interface MarketPageMarketsOffsetResponse {
2274
+ data: Market[];
2275
+ pagination: OffsetPagination;
2276
+ }
2277
+ /**
2278
+ * Cursor response for /market-pages/:id/markets endpoint.
2279
+ * @public
2280
+ */
2281
+ interface MarketPageMarketsCursorResponse {
2282
+ data: Market[];
2283
+ cursor: CursorPagination;
2284
+ }
2285
+ /**
2286
+ * Union response for /market-pages/:id/markets endpoint.
2287
+ * @public
2288
+ */
2289
+ type MarketPageMarketsResponse = MarketPageMarketsOffsetResponse | MarketPageMarketsCursorResponse;
2290
+
2051
2291
  /**
2052
2292
  * API error types for Limitless Exchange SDK.
2053
2293
  * @module api/errors
@@ -3187,6 +3427,57 @@ declare class OrderClient {
3187
3427
  get ownerId(): number | undefined;
3188
3428
  }
3189
3429
 
3430
+ /**
3431
+ * Fetcher for market-pages and property-keys APIs.
3432
+ *
3433
+ * @remarks
3434
+ * This class provides access to the new navigation-driven market discovery API.
3435
+ *
3436
+ * @public
3437
+ */
3438
+ declare class MarketPageFetcher {
3439
+ private httpClient;
3440
+ private logger;
3441
+ /**
3442
+ * Creates a new market-pages fetcher.
3443
+ *
3444
+ * @param httpClient - HTTP client for API calls
3445
+ * @param logger - Optional logger
3446
+ */
3447
+ constructor(httpClient: HttpClient, logger?: ILogger);
3448
+ /**
3449
+ * Gets the navigation tree.
3450
+ */
3451
+ getNavigation(): Promise<NavigationNode[]>;
3452
+ /**
3453
+ * Resolves a market page by path.
3454
+ *
3455
+ * @remarks
3456
+ * Handles 301 redirects manually by re-requesting `/market-pages/by-path` with the
3457
+ * redirected path value from `Location` header.
3458
+ */
3459
+ getMarketPageByPath(path: string): Promise<MarketPage>;
3460
+ private getMarketPageByPathInternal;
3461
+ private extractRedirectPath;
3462
+ /**
3463
+ * Gets markets for a market page with optional filtering and pagination.
3464
+ */
3465
+ getMarkets(pageId: string, params?: MarketPageMarketsParams): Promise<MarketPageMarketsResponse>;
3466
+ /**
3467
+ * Lists all property keys with options.
3468
+ */
3469
+ getPropertyKeys(): Promise<PropertyKey[]>;
3470
+ /**
3471
+ * Gets a single property key by ID.
3472
+ */
3473
+ getPropertyKey(id: string): Promise<PropertyKey>;
3474
+ /**
3475
+ * Lists options for a property key, optionally filtered by parent option ID.
3476
+ */
3477
+ getPropertyOptions(keyId: string, parentId?: string): Promise<PropertyOption[]>;
3478
+ private stringifyFilterValue;
3479
+ }
3480
+
3190
3481
  /**
3191
3482
  * Portfolio data fetcher for Limitless Exchange.
3192
3483
  * @module portfolio/fetcher
@@ -3530,4 +3821,4 @@ declare class WebSocketClient {
3530
3821
  private getChannelFromKey;
3531
3822
  }
3532
3823
 
3533
- export { type AMMPosition, APIError, type ActiveMarketsParams, type ActiveMarketsResponse, type ActiveMarketsSortBy, type AmmPriceEntry, AuthenticationError, BASE_SEPOLIA_CHAIN_ID, type BaseOrderArgs, type CLOBPosition, CONTRACT_ADDRESSES, type CollateralToken, ConsoleLogger, type CreatedOrder, DEFAULT_API_URL, DEFAULT_CHAIN_ID, DEFAULT_WS_URL, type FOKOrderArgs, type FillEvent, type GTCOrderArgs, type HistoryEntry, type HistoryResponse, HttpClient, type HttpClientConfig, type ILogger, type LatestTrade, Market, type MarketCreator, MarketFetcher, type Market$1 as MarketInterface, type MarketMetadata, type MarketOutcome, type MarketSettings, type MarketTokens, type MarketUpdate, type MarketsResponse, type ModeInfo, type NewOrderPayload, type NewPriceData, NoOpLogger, type OrderArgs, type OrderBook, OrderBuilder, OrderClient, type OrderClientConfig, type OrderMatch, type OrderResponse, OrderSigner, type OrderSigningConfig, OrderType, type OrderUpdate, OrderValidationError, type OrderbookData, type OrderbookEntry, type OrderbookUpdate, PortfolioFetcher, type PortfolioPositionsResponse, type PortfolioSummary, type Position, type PositionMarket, type PositionSide, type PriceOracleMetadata, type PriceUpdate, RateLimitError, type ReferralData, RetryConfig, type RetryConfigOptions, RetryableClient, SIGNING_MESSAGE_TEMPLATE, Side, SignatureType, type SignedOrder, type SubscriptionChannel, type SubscriptionOptions, type TokenBalance, type TradeEvent, type TradePrices, type TradingMode, type TransactionEvent, type UnsignedOrder, type UserData, type UserProfile, type UserRank, ValidationError, type Venue, WebSocketClient, type WebSocketConfig, type WebSocketEvents, WebSocketState, ZERO_ADDRESS, getContractAddress, retryOnErrors, validateOrderArgs, validateSignedOrder, validateUnsignedOrder, withRetry };
3824
+ export { type AMMPosition, APIError, type ActiveMarketsParams, type ActiveMarketsResponse, type ActiveMarketsSortBy, type AmmPriceEntry, AuthenticationError, BASE_SEPOLIA_CHAIN_ID, type BaseOrderArgs, type BreadcrumbItem, type CLOBPosition, CONTRACT_ADDRESSES, type CollateralToken, ConsoleLogger, type CreatedOrder, type CursorPagination, DEFAULT_API_URL, DEFAULT_CHAIN_ID, DEFAULT_WS_URL, type FOKOrderArgs, type FillEvent, type FilterGroup, type FilterGroupOption, type GTCOrderArgs, type HistoryEntry, type HistoryResponse, HttpClient, type HttpClientConfig, type HttpRawResponse, type ILogger, type LatestTrade, Market, type MarketCreator, MarketFetcher, type Market$1 as MarketInterface, type MarketMetadata, type MarketOutcome, type MarketPage, MarketPageFetcher, type MarketPageFilterPrimitive, type MarketPageFilterValue, type MarketPageMarketsCursorResponse, type MarketPageMarketsOffsetResponse, type MarketPageMarketsParams, type MarketPageMarketsResponse, type MarketPageSort, type MarketPageSortField, type MarketSettings, type MarketTokens, type MarketUpdate, type MarketsResponse, type ModeInfo, type NavigationNode, type NewOrderPayload, type NewPriceData, NoOpLogger, type OffsetPagination, type OrderArgs, type OrderBook, OrderBuilder, OrderClient, type OrderClientConfig, type OrderMatch, type OrderResponse, OrderSigner, type OrderSigningConfig, OrderType, type OrderUpdate, OrderValidationError, type OrderbookData, type OrderbookEntry, type OrderbookUpdate, PortfolioFetcher, type PortfolioPositionsResponse, type PortfolioSummary, type Position, type PositionMarket, type PositionSide, type PriceOracleMetadata, type PriceUpdate, type PropertyKey, type PropertyOption, RateLimitError, type ReferralData, RetryConfig, type RetryConfigOptions, RetryableClient, SIGNING_MESSAGE_TEMPLATE, Side, SignatureType, type SignedOrder, type SubscriptionChannel, type SubscriptionOptions, type TokenBalance, type TradeEvent, type TradePrices, type TradingMode, type TransactionEvent, type UnsignedOrder, type UserData, type UserProfile, type UserRank, ValidationError, type Venue, WebSocketClient, type WebSocketConfig, type WebSocketEvents, WebSocketState, ZERO_ADDRESS, getContractAddress, retryOnErrors, validateOrderArgs, validateSignedOrder, validateUnsignedOrder, withRetry };
package/dist/index.js CHANGED
@@ -41,6 +41,7 @@ __export(index_exports, {
41
41
  HttpClient: () => HttpClient,
42
42
  Market: () => Market,
43
43
  MarketFetcher: () => MarketFetcher,
44
+ MarketPageFetcher: () => MarketPageFetcher,
44
45
  NoOpLogger: () => NoOpLogger,
45
46
  OrderBuilder: () => OrderBuilder,
46
47
  OrderClient: () => OrderClient,
@@ -421,6 +422,42 @@ var HttpClient = class {
421
422
  }
422
423
  );
423
424
  }
425
+ /**
426
+ * Extracts a human-readable error message from API response payload.
427
+ * @internal
428
+ */
429
+ extractErrorMessage(data, fallback) {
430
+ if (!data) {
431
+ return fallback;
432
+ }
433
+ if (typeof data === "object") {
434
+ if (Array.isArray(data.message)) {
435
+ const messages = data.message.map((err) => {
436
+ const details = Object.entries(err || {}).filter(([_key, val]) => val !== "" && val !== null && val !== void 0).map(([key, val]) => `${key}: ${val}`).join(", ");
437
+ return details || JSON.stringify(err);
438
+ }).filter((msg) => msg.trim() !== "").join(" | ");
439
+ return messages || data.error || JSON.stringify(data);
440
+ }
441
+ return data.message || data.error || data.msg || data.errors && JSON.stringify(data.errors) || JSON.stringify(data);
442
+ }
443
+ return String(data);
444
+ }
445
+ /**
446
+ * Creates a typed API error class from status code.
447
+ * @internal
448
+ */
449
+ createTypedApiError(status, message, data, url, method) {
450
+ if (status === 429) {
451
+ return new RateLimitError(message, status, data, url, method);
452
+ }
453
+ if (status === 401 || status === 403) {
454
+ return new AuthenticationError(message, status, data, url, method);
455
+ }
456
+ if (status === 400) {
457
+ return new ValidationError(message, status, data, url, method);
458
+ }
459
+ return new APIError(message, status, data, url, method);
460
+ }
424
461
  /**
425
462
  * Sets the API key for authenticated requests.
426
463
  *
@@ -446,6 +483,28 @@ var HttpClient = class {
446
483
  const response = await this.client.get(url, config);
447
484
  return response.data;
448
485
  }
486
+ /**
487
+ * Performs a GET request and returns raw response metadata.
488
+ *
489
+ * @remarks
490
+ * Use this when callers need access to status code or headers (e.g. redirect `Location`).
491
+ *
492
+ * @param url - Request URL
493
+ * @param config - Additional request configuration
494
+ * @returns Promise resolving to status, headers, and response data
495
+ */
496
+ async getRaw(url, config) {
497
+ const response = await this.client.get(url, config);
498
+ if (response.status >= 400) {
499
+ const message = this.extractErrorMessage(response.data, `Request failed with status ${response.status}`);
500
+ throw this.createTypedApiError(response.status, message, response.data, url, "GET");
501
+ }
502
+ return {
503
+ status: response.status,
504
+ headers: response.headers,
505
+ data: response.data
506
+ };
507
+ }
449
508
  /**
450
509
  * Performs a POST request.
451
510
  *
@@ -1092,7 +1151,7 @@ var OrderValidationError = class extends Error {
1092
1151
  }
1093
1152
  };
1094
1153
  function isFOKOrder(args) {
1095
- return "amount" in args;
1154
+ return "makerAmount" in args;
1096
1155
  }
1097
1156
  function validateOrderArgs(args) {
1098
1157
  if (!args.tokenId) {
@@ -1880,6 +1939,174 @@ var OrderClient = class {
1880
1939
  }
1881
1940
  };
1882
1941
 
1942
+ // src/market-pages/fetcher.ts
1943
+ var MAX_REDIRECT_DEPTH = 3;
1944
+ var MarketPageFetcher = class {
1945
+ /**
1946
+ * Creates a new market-pages fetcher.
1947
+ *
1948
+ * @param httpClient - HTTP client for API calls
1949
+ * @param logger - Optional logger
1950
+ */
1951
+ constructor(httpClient, logger) {
1952
+ this.httpClient = httpClient;
1953
+ this.logger = logger || new NoOpLogger();
1954
+ }
1955
+ /**
1956
+ * Gets the navigation tree.
1957
+ */
1958
+ async getNavigation() {
1959
+ this.logger.debug("Fetching navigation tree");
1960
+ return this.httpClient.get("/navigation");
1961
+ }
1962
+ /**
1963
+ * Resolves a market page by path.
1964
+ *
1965
+ * @remarks
1966
+ * Handles 301 redirects manually by re-requesting `/market-pages/by-path` with the
1967
+ * redirected path value from `Location` header.
1968
+ */
1969
+ async getMarketPageByPath(path) {
1970
+ return this.getMarketPageByPathInternal(path, 0);
1971
+ }
1972
+ async getMarketPageByPathInternal(path, depth) {
1973
+ const query = new URLSearchParams({ path }).toString();
1974
+ const endpoint = `/market-pages/by-path?${query}`;
1975
+ const requestConfig = {
1976
+ maxRedirects: 0,
1977
+ validateStatus: (status) => status === 200 || status === 301
1978
+ };
1979
+ this.logger.debug("Resolving market page by path", { path, depth });
1980
+ const response = await this.httpClient.getRaw(endpoint, requestConfig);
1981
+ if (response.status === 200) {
1982
+ return response.data;
1983
+ }
1984
+ if (response.status !== 301) {
1985
+ throw new Error(`Unexpected response status: ${response.status}`);
1986
+ }
1987
+ if (depth >= MAX_REDIRECT_DEPTH) {
1988
+ throw new Error(
1989
+ `Too many redirects while resolving market page path '${path}' (max ${MAX_REDIRECT_DEPTH})`
1990
+ );
1991
+ }
1992
+ const locationHeader = response.headers?.location;
1993
+ const location = Array.isArray(locationHeader) ? locationHeader[0] : locationHeader;
1994
+ if (!location || typeof location !== "string") {
1995
+ throw new Error("Redirect response missing valid Location header");
1996
+ }
1997
+ const redirectedPath = this.extractRedirectPath(location);
1998
+ this.logger.info("Following market page redirect", {
1999
+ from: path,
2000
+ to: redirectedPath,
2001
+ depth: depth + 1
2002
+ });
2003
+ return this.getMarketPageByPathInternal(redirectedPath, depth + 1);
2004
+ }
2005
+ extractRedirectPath(location) {
2006
+ const directByPathPrefix = "/market-pages/by-path";
2007
+ if (location.startsWith(directByPathPrefix)) {
2008
+ const url = new URL(location, "https://api.limitless.exchange");
2009
+ const path = url.searchParams.get("path");
2010
+ if (!path) {
2011
+ throw new Error("Redirect location '/market-pages/by-path' is missing required 'path' query parameter");
2012
+ }
2013
+ return path;
2014
+ }
2015
+ if (/^https?:\/\//i.test(location)) {
2016
+ const url = new URL(location);
2017
+ if (url.pathname === directByPathPrefix) {
2018
+ const path = url.searchParams.get("path");
2019
+ if (!path) {
2020
+ throw new Error("Redirect location '/market-pages/by-path' is missing required 'path' query parameter");
2021
+ }
2022
+ return path;
2023
+ }
2024
+ return url.pathname || "/";
2025
+ }
2026
+ return location;
2027
+ }
2028
+ /**
2029
+ * Gets markets for a market page with optional filtering and pagination.
2030
+ */
2031
+ async getMarkets(pageId, params = {}) {
2032
+ if (params.cursor !== void 0 && params.page !== void 0) {
2033
+ throw new Error("Parameters `cursor` and `page` are mutually exclusive");
2034
+ }
2035
+ const query = new URLSearchParams();
2036
+ if (params.page !== void 0) {
2037
+ query.append("page", String(params.page));
2038
+ }
2039
+ if (params.limit !== void 0) {
2040
+ query.append("limit", String(params.limit));
2041
+ }
2042
+ if (params.sort) {
2043
+ query.append("sort", params.sort);
2044
+ }
2045
+ if (params.cursor !== void 0) {
2046
+ query.append("cursor", params.cursor);
2047
+ }
2048
+ if (params.filters) {
2049
+ for (const [key, value] of Object.entries(params.filters)) {
2050
+ if (Array.isArray(value)) {
2051
+ for (const item of value) {
2052
+ query.append(key, this.stringifyFilterValue(item));
2053
+ }
2054
+ } else {
2055
+ query.append(key, this.stringifyFilterValue(value));
2056
+ }
2057
+ }
2058
+ }
2059
+ const queryString = query.toString();
2060
+ const endpoint = `/market-pages/${pageId}/markets${queryString ? `?${queryString}` : ""}`;
2061
+ this.logger.debug("Fetching market-page markets", { pageId, params });
2062
+ const response = await this.httpClient.get(endpoint);
2063
+ const markets = (response.data || []).map((marketData) => new Market(marketData, this.httpClient));
2064
+ if (response.pagination) {
2065
+ return {
2066
+ data: markets,
2067
+ pagination: response.pagination
2068
+ };
2069
+ }
2070
+ if (response.cursor) {
2071
+ return {
2072
+ data: markets,
2073
+ cursor: response.cursor
2074
+ };
2075
+ }
2076
+ throw new Error("Invalid market-page response: expected `pagination` or `cursor` metadata");
2077
+ }
2078
+ /**
2079
+ * Lists all property keys with options.
2080
+ */
2081
+ async getPropertyKeys() {
2082
+ return this.httpClient.get("/property-keys");
2083
+ }
2084
+ /**
2085
+ * Gets a single property key by ID.
2086
+ */
2087
+ async getPropertyKey(id) {
2088
+ return this.httpClient.get(`/property-keys/${id}`);
2089
+ }
2090
+ /**
2091
+ * Lists options for a property key, optionally filtered by parent option ID.
2092
+ */
2093
+ async getPropertyOptions(keyId, parentId) {
2094
+ const query = new URLSearchParams();
2095
+ if (parentId) {
2096
+ query.append("parentId", parentId);
2097
+ }
2098
+ const queryString = query.toString();
2099
+ const endpoint = `/property-keys/${keyId}/options${queryString ? `?${queryString}` : ""}`;
2100
+ return this.httpClient.get(endpoint);
2101
+ }
2102
+ stringifyFilterValue(value) {
2103
+ if (typeof value === "boolean") {
2104
+ return value ? "true" : "false";
2105
+ }
2106
+ return String(value);
2107
+ }
2108
+ };
2109
+
1883
2110
  // src/websocket/client.ts
1884
2111
  var import_socket = require("socket.io-client");
1885
2112
  var WebSocketClient = class {
@@ -2263,6 +2490,7 @@ var WebSocketClient = class {
2263
2490
  HttpClient,
2264
2491
  Market,
2265
2492
  MarketFetcher,
2493
+ MarketPageFetcher,
2266
2494
  NoOpLogger,
2267
2495
  OrderBuilder,
2268
2496
  OrderClient,