@pear-protocol/market-sdk 0.2.1 → 0.3.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.
@@ -17,7 +17,8 @@ async function fetchHistoricalCandles(connector, symbol, startTime, endTime, int
17
17
  case "okx":
18
18
  return fetchHistoricalCandles$2(symbol, startTime, endTime, interval);
19
19
  case "lighter":
20
- return fetchHistoricalCandles$1(symbol, startTime, endTime, interval, authToken);
20
+ case "lighter_rhc":
21
+ return fetchHistoricalCandles$1(connector, symbol, startTime, endTime, interval, authToken);
21
22
  default:
22
23
  throw new Error(`Unsupported connector: ${connector}`);
23
24
  }
@@ -1,10 +1,12 @@
1
+ import { LighterConnector } from '../../shared/lighter-hosts.js';
1
2
  import { CandleInterval, CandleData } from '../types.js';
2
- import '../../transport/index.js';
3
3
  import '@pear-protocol/types';
4
+ import '../../transport/index.js';
4
5
  import '../../shared/types.js';
5
6
  import '../../transport/base-transport.js';
6
7
  import 'partysocket';
7
8
 
8
- declare function fetchHistoricalCandles(symbol: string, startTime: number, endTime: number, interval: CandleInterval, authToken?: string): Promise<CandleData[]>;
9
+ /** Reads one deployment's candles for a range, synthesizing the resolutions it does not serve. */
10
+ declare function fetchHistoricalCandles(connector: LighterConnector, symbol: string, startTime: number, endTime: number, interval: CandleInterval, authToken?: string): Promise<CandleData[]>;
9
11
 
10
12
  export { fetchHistoricalCandles };
@@ -1,9 +1,9 @@
1
+ import { LIGHTER_BASE_URLS } from '../../shared/lighter-hosts';
1
2
  import { getIntervalSeconds } from '../utils';
2
3
  import { getWeekStart, aggregateDailyCandlesToWeekly } from '../weekly';
3
4
 
4
5
  var __defProp = Object.defineProperty;
5
6
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
6
- const BASE_URL = "https://mainnet.zklighter.elliot.ai";
7
7
  const MAX_LIMIT = 500;
8
8
  const DAY_MS = getIntervalSeconds("1d") * 1e3;
9
9
  const RESOLUTION_MAP = {
@@ -16,25 +16,25 @@ const RESOLUTION_MAP = {
16
16
  "12h": "12h",
17
17
  "1d": "1d"
18
18
  };
19
- async function fetchHistoricalCandles(symbol, startTime, endTime, interval, authToken) {
19
+ async function fetchHistoricalCandles(connector, symbol, startTime, endTime, interval, authToken) {
20
20
  if (interval === "1w") {
21
- const dailyCandles = await fetchDailyCandlesChunked(symbol, getWeekStart(startTime), endTime, authToken);
21
+ const dailyCandles = await fetchDailyCandlesChunked(connector, symbol, getWeekStart(startTime), endTime, authToken);
22
22
  return aggregateDailyCandlesToWeekly(dailyCandles);
23
23
  }
24
- return fetchResolutionCandles(symbol, startTime, endTime, interval, authToken);
24
+ return fetchResolutionCandles(connector, symbol, startTime, endTime, interval, authToken);
25
25
  }
26
26
  __name(fetchHistoricalCandles, "fetchHistoricalCandles");
27
- async function fetchDailyCandlesChunked(symbol, startTime, endTime, authToken) {
27
+ async function fetchDailyCandlesChunked(connector, symbol, startTime, endTime, authToken) {
28
28
  const chunkMs = MAX_LIMIT * DAY_MS;
29
29
  const chunkStarts = [];
30
30
  for (let chunkStart = startTime; chunkStart < endTime; chunkStart += chunkMs) {
31
31
  chunkStarts.push(chunkStart);
32
32
  }
33
- const chunks = await Promise.all(chunkStarts.map((chunkStart) => fetchResolutionCandles(symbol, chunkStart, Math.min(chunkStart + chunkMs, endTime), "1d", authToken)));
33
+ const chunks = await Promise.all(chunkStarts.map((chunkStart) => fetchResolutionCandles(connector, symbol, chunkStart, Math.min(chunkStart + chunkMs, endTime), "1d", authToken)));
34
34
  return chunks.flat();
35
35
  }
36
36
  __name(fetchDailyCandlesChunked, "fetchDailyCandlesChunked");
37
- async function fetchResolutionCandles(symbol, startTime, endTime, interval, authToken) {
37
+ async function fetchResolutionCandles(connector, symbol, startTime, endTime, interval, authToken) {
38
38
  const resolution = RESOLUTION_MAP[interval];
39
39
  if (!resolution) throw new Error(`Lighter does not support the '${interval}' interval`);
40
40
  const intervalMs = getIntervalSeconds(interval) * 1e3;
@@ -46,7 +46,7 @@ async function fetchResolutionCandles(symbol, startTime, endTime, interval, auth
46
46
  end_timestamp: String(endTime),
47
47
  count_back: String(countBack)
48
48
  });
49
- const response = await fetch(`${BASE_URL}/api/v1/candles?${params}`, authToken ? {
49
+ const response = await fetch(`${LIGHTER_BASE_URLS[connector]}/api/v1/candles?${params}`, authToken ? {
50
50
  headers: {
51
51
  authorization: authToken
52
52
  }
@@ -18,6 +18,7 @@ function createCandleWs(transport, connector, onCandle) {
18
18
  case "okx":
19
19
  return new OkxCandleWs(transport, onCandle);
20
20
  case "lighter":
21
+ case "lighter_rhc":
21
22
  return new LighterCandleWs(transport, onCandle);
22
23
  default: {
23
24
  const _exhaustive = connector;
@@ -17,7 +17,8 @@ async function fetchHistoricalFundingRates(connector, symbol, startTime, endTime
17
17
  case "okx":
18
18
  return fetchHistoricalFundingRates$2(symbol, startTime, endTime);
19
19
  case "lighter":
20
- return fetchHistoricalFundingRates$1(symbol, startTime, endTime, duration, authToken);
20
+ case "lighter_rhc":
21
+ return fetchHistoricalFundingRates$1(connector, symbol, startTime, endTime, duration, authToken);
21
22
  default:
22
23
  throw new Error(`Unsupported connector: ${connector}`);
23
24
  }
@@ -1,10 +1,11 @@
1
+ import { LighterConnector } from '../../shared/lighter-hosts.js';
1
2
  import { FundingRateDuration, FundingRateEntry } from '../types.js';
2
- import '../../transport/index.js';
3
3
  import '@pear-protocol/types';
4
+ import '../../transport/index.js';
4
5
  import '../../shared/types.js';
5
6
  import '../../transport/base-transport.js';
6
7
  import 'partysocket';
7
8
 
8
- declare function fetchHistoricalFundingRates(symbol: string, startTime: number, endTime: number, _duration: FundingRateDuration, authToken?: string): Promise<FundingRateEntry[]>;
9
+ declare function fetchHistoricalFundingRates(connector: LighterConnector, symbol: string, startTime: number, endTime: number, _duration: FundingRateDuration, authToken?: string): Promise<FundingRateEntry[]>;
9
10
 
10
11
  export { fetchHistoricalFundingRates };
@@ -1,17 +1,17 @@
1
1
  import BigNumber from 'bignumber.js';
2
+ import { LIGHTER_BASE_URLS } from '../../shared/lighter-hosts';
2
3
  import { httpGet } from './http-client';
3
4
 
4
5
  var __defProp = Object.defineProperty;
5
6
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
6
- const BASE_URL = "https://mainnet.zklighter.elliot.ai";
7
7
  const MAX_LIMIT = 500;
8
- async function fetchHistoricalFundingRates(symbol, startTime, endTime, _duration, authToken) {
8
+ async function fetchHistoricalFundingRates(connector, symbol, startTime, endTime, _duration, authToken) {
9
9
  const intervalMs = 60 * 60 * 1e3;
10
10
  const allRates = [];
11
11
  let cursor = startTime;
12
12
  while (cursor < endTime) {
13
13
  const countBack = Math.min(Math.ceil((endTime - cursor) / intervalMs) + 1, MAX_LIMIT);
14
- const data = await httpGet(`${BASE_URL}/api/v1/fundings`, {
14
+ const data = await httpGet(`${LIGHTER_BASE_URLS[connector]}/api/v1/fundings`, {
15
15
  market_id: symbol,
16
16
  resolution: "1h",
17
17
  start_timestamp: String(cursor),
@@ -18,6 +18,7 @@ function createDepthWs(transport, connector, onUpdate) {
18
18
  case "okx":
19
19
  return new OkxDepthWs(transport, onUpdate);
20
20
  case "lighter":
21
+ case "lighter_rhc":
21
22
  return new LighterDepthWs(transport, onUpdate);
22
23
  default: {
23
24
  const _exhaustive = connector;
@@ -0,0 +1,18 @@
1
+ import { Connector } from '@pear-protocol/types';
2
+
3
+ /**
4
+ * The connector values that are deployments of the Lighter stack. The deployments share the
5
+ * protocol but nothing else — hosts and market indices are per-deployment, so every Lighter code
6
+ * path in this SDK resolves its host from the connector value.
7
+ */
8
+ type LighterConnector = Extract<Connector, 'lighter' | 'lighter_rhc'>;
9
+ /**
10
+ * REST host per Lighter deployment.
11
+ */
12
+ declare const LIGHTER_BASE_URLS: Record<LighterConnector, string>;
13
+ /**
14
+ * WebSocket stream URL per Lighter deployment.
15
+ */
16
+ declare const LIGHTER_WS_URLS: Record<LighterConnector, string>;
17
+
18
+ export { LIGHTER_BASE_URLS, LIGHTER_WS_URLS, type LighterConnector };
@@ -0,0 +1,10 @@
1
+ const LIGHTER_BASE_URLS = {
2
+ lighter: "https://mainnet.zklighter.elliot.ai",
3
+ lighter_rhc: "https://api.rh.lighter.xyz"
4
+ };
5
+ const LIGHTER_WS_URLS = {
6
+ lighter: "wss://mainnet.zklighter.elliot.ai/stream",
7
+ lighter_rhc: "wss://api.rh.lighter.xyz/stream"
8
+ };
9
+
10
+ export { LIGHTER_BASE_URLS, LIGHTER_WS_URLS };
@@ -18,7 +18,8 @@ function CreateTransport(connector, options) {
18
18
  case "hyperliquid":
19
19
  return new HyperliquidTransport();
20
20
  case "lighter":
21
- return new LighterTransport(options?.authToken);
21
+ case "lighter_rhc":
22
+ return new LighterTransport(connector, options?.authToken);
22
23
  default: {
23
24
  const _exhaustive = connector;
24
25
  throw new Error(`Unsupported connector: ${String(_exhaustive)}`);
@@ -1,6 +1,7 @@
1
- import { Connector } from '@pear-protocol/types';
1
+ import { LighterConnector } from '../shared/lighter-hosts.js';
2
2
  import { AuthTokenProvider, WsMessage } from '../shared/types.js';
3
3
  import { BaseTransport } from './base-transport.js';
4
+ import '@pear-protocol/types';
4
5
  import 'partysocket';
5
6
 
6
7
  /**
@@ -10,14 +11,17 @@ import 'partysocket';
10
11
  */
11
12
 
12
13
  declare class LighterTransport extends BaseTransport {
13
- readonly connector: Connector;
14
+ readonly connector: LighterConnector;
14
15
  private readonly authTokenProvider;
15
16
  private cachedAuthToken;
16
17
  private authRefreshTimer;
17
18
  private mintInFlight;
18
19
  private wantsConnection;
19
- /** Takes the caller's minter; without one this transport stays anonymous for its whole life. */
20
- constructor(authTokenProvider?: AuthTokenProvider);
20
+ /**
21
+ * Takes the deployment this transport streams from, and the caller's minter; without a minter
22
+ * this transport stays anonymous for its whole life.
23
+ */
24
+ constructor(connector: LighterConnector, authTokenProvider?: AuthTokenProvider);
21
25
  /** Holds the socket until a first token lands, so the opening subscriptions carry it. */
22
26
  connect(): void;
23
27
  /** Tears the socket down and drops the identity that belonged to it. */
@@ -26,7 +30,7 @@ declare class LighterTransport extends BaseTransport {
26
30
  get authToken(): string | undefined;
27
31
  /** Refreshes the cached token; the caller's provider owns expiry and request coalescing. */
28
32
  retrieveAuthToken(): Promise<string | undefined>;
29
- /** The venue's public market-data stream, which serves both authenticated and anonymous traffic. */
33
+ /** The deployment's public market-data stream, which serves both authenticated and anonymous traffic. */
30
34
  protected getWsUrl(): string;
31
35
  /** How often the socket must speak to stay open. */
32
36
  protected getPingIntervalMs(): number;
@@ -1,3 +1,4 @@
1
+ import { LIGHTER_WS_URLS } from '../shared/lighter-hosts';
1
2
  import { BaseTransport } from './base-transport';
2
3
 
3
4
  var __defProp = Object.defineProperty;
@@ -7,15 +8,19 @@ class LighterTransport extends BaseTransport {
7
8
  static {
8
9
  __name(this, "LighterTransport");
9
10
  }
10
- connector = "lighter";
11
+ connector;
11
12
  authTokenProvider;
12
13
  cachedAuthToken;
13
14
  authRefreshTimer = null;
14
15
  mintInFlight = false;
15
16
  wantsConnection = false;
16
- /** Takes the caller's minter; without one this transport stays anonymous for its whole life. */
17
- constructor(authTokenProvider) {
17
+ /**
18
+ * Takes the deployment this transport streams from, and the caller's minter; without a minter
19
+ * this transport stays anonymous for its whole life.
20
+ */
21
+ constructor(connector, authTokenProvider) {
18
22
  super();
23
+ this.connector = connector;
19
24
  this.authTokenProvider = authTokenProvider;
20
25
  }
21
26
  /** Holds the socket until a first token lands, so the opening subscriptions carry it. */
@@ -61,9 +66,9 @@ class LighterTransport extends BaseTransport {
61
66
  }
62
67
  return this.cachedAuthToken;
63
68
  }
64
- /** The venue's public market-data stream, which serves both authenticated and anonymous traffic. */
69
+ /** The deployment's public market-data stream, which serves both authenticated and anonymous traffic. */
65
70
  getWsUrl() {
66
- return "wss://mainnet.zklighter.elliot.ai/stream";
71
+ return LIGHTER_WS_URLS[this.connector];
67
72
  }
68
73
  /** How often the socket must speak to stay open. */
69
74
  getPingIntervalMs() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pear-protocol/market-sdk",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Pear Protocol Market SDK",
5
5
  "private": false,
6
6
  "type": "module",
@@ -26,7 +26,7 @@
26
26
  "typecheck": "tsc --noEmit"
27
27
  },
28
28
  "dependencies": {
29
- "@pear-protocol/types": "^2.0.0",
29
+ "@pear-protocol/types": "^2.2.0",
30
30
  "bignumber.js": "^9.1.2",
31
31
  "partysocket": "^1.0.3"
32
32
  },