@pear-protocol/market-sdk 0.0.13 → 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/README.md +27 -0
- package/dist/chart/cache/index.d.ts +1 -1
- package/dist/chart/cache/index.js +15 -3
- package/dist/chart/chart.d.ts +1 -1
- package/dist/chart/chart.js +14 -23
- package/dist/chart/collector/binance.d.ts +1 -1
- package/dist/chart/collector/binance.js +4 -0
- package/dist/chart/collector/bybit.d.ts +1 -1
- package/dist/chart/collector/bybit.js +12 -1
- package/dist/chart/collector/helpers.d.ts +2 -2
- package/dist/chart/collector/helpers.js +5 -2
- package/dist/chart/collector/hyperliquid.d.ts +1 -1
- package/dist/chart/collector/hyperliquid.js +12 -2
- package/dist/chart/collector/index.d.ts +1 -1
- package/dist/chart/collector/index.js +28 -12
- package/dist/chart/collector/lighter.d.ts +2 -2
- package/dist/chart/collector/lighter.js +10 -4
- package/dist/chart/collector/okx.d.ts +1 -1
- package/dist/chart/collector/okx.js +12 -1
- package/dist/chart/compute/asset.d.ts +1 -1
- package/dist/chart/compute/asset.js +4 -0
- package/dist/chart/compute/index.d.ts +1 -1
- package/dist/chart/compute/performance.d.ts +1 -1
- package/dist/chart/compute/performance.js +20 -4
- package/dist/chart/compute/price-ratio.d.ts +1 -1
- package/dist/chart/compute/price-ratio.js +8 -1
- package/dist/chart/compute/weighted-ratio.d.ts +1 -1
- package/dist/chart/compute/weighted-ratio.js +9 -1
- package/dist/chart/types.d.ts +1 -1
- package/dist/chart/utils.d.ts +1 -1
- package/dist/chart/utils.js +19 -11
- package/dist/chart/ws/base-candle.d.ts +11 -5
- package/dist/chart/ws/base-candle.js +6 -2
- package/dist/chart/ws/binance.d.ts +4 -6
- package/dist/chart/ws/binance.js +33 -19
- package/dist/chart/ws/bybit.d.ts +4 -6
- package/dist/chart/ws/bybit.js +40 -24
- package/dist/chart/ws/hyperliquid.d.ts +4 -6
- package/dist/chart/ws/hyperliquid.js +37 -19
- package/dist/chart/ws/index.js +3 -0
- package/dist/chart/ws/lighter.d.ts +20 -20
- package/dist/chart/ws/lighter.js +83 -196
- package/dist/chart/ws/okx.d.ts +4 -6
- package/dist/chart/ws/okx.js +47 -23
- package/dist/funding-rate/fetcher/binance.d.ts +1 -1
- package/dist/funding-rate/fetcher/binance.js +7 -1
- package/dist/funding-rate/fetcher/bybit.d.ts +1 -1
- package/dist/funding-rate/fetcher/bybit.js +15 -13
- package/dist/funding-rate/fetcher/http-client.d.ts +1 -1
- package/dist/funding-rate/fetcher/http-client.js +15 -10
- package/dist/funding-rate/fetcher/hyperliquid.d.ts +1 -1
- package/dist/funding-rate/fetcher/hyperliquid.js +7 -1
- package/dist/funding-rate/fetcher/index.d.ts +2 -2
- package/dist/funding-rate/fetcher/index.js +5 -2
- package/dist/funding-rate/fetcher/lighter.d.ts +2 -2
- package/dist/funding-rate/fetcher/lighter.js +11 -3
- package/dist/funding-rate/fetcher/okx.d.ts +1 -1
- package/dist/funding-rate/fetcher/okx.js +14 -12
- package/dist/funding-rate/funding-rate.d.ts +1 -1
- package/dist/funding-rate/funding-rate.js +30 -21
- package/dist/funding-rate/types.d.ts +1 -1
- package/dist/funding-rate/utils.d.ts +1 -1
- package/dist/funding-rate/utils.js +26 -5
- package/dist/index.d.ts +2 -2
- package/dist/orderbook/book/aggregate.d.ts +1 -1
- package/dist/orderbook/book/aggregate.js +16 -3
- package/dist/orderbook/book/local-book.d.ts +1 -1
- package/dist/orderbook/book/local-book.js +16 -5
- package/dist/orderbook/orderbook.d.ts +1 -1
- package/dist/orderbook/orderbook.js +29 -13
- package/dist/orderbook/types.d.ts +1 -1
- package/dist/orderbook/types.js +7 -1
- package/dist/orderbook/utils.d.ts +1 -1
- package/dist/orderbook/utils.js +5 -0
- package/dist/orderbook/ws/base-depth.js +10 -1
- package/dist/orderbook/ws/binance.js +28 -7
- package/dist/orderbook/ws/bybit.js +20 -5
- package/dist/orderbook/ws/hyperliquid.js +31 -11
- package/dist/orderbook/ws/index.js +3 -0
- package/dist/orderbook/ws/lighter.js +30 -7
- package/dist/orderbook/ws/okx.js +23 -2
- package/dist/shared/types.d.ts +6 -1
- package/dist/transport/base-transport.d.ts +4 -0
- package/dist/transport/base-transport.js +13 -0
- package/dist/transport/binance.js +5 -0
- package/dist/transport/bybit.js +8 -1
- package/dist/transport/hyperliquid.js +8 -1
- package/dist/transport/index.d.ts +11 -3
- package/dist/transport/index.js +5 -2
- package/dist/transport/lighter.d.ts +31 -1
- package/dist/transport/lighter.js +86 -1
- package/dist/transport/okx.js +5 -0
- package/package.json +5 -3
package/dist/chart/ws/lighter.js
CHANGED
|
@@ -1,214 +1,101 @@
|
|
|
1
1
|
import { getIntervalSeconds } from '../utils';
|
|
2
2
|
import { BaseCandleWs } from './base-candle';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
function toIntervalOpenTime(ts, intervalMs) {
|
|
17
|
-
return Math.floor(ts / intervalMs) * intervalMs;
|
|
18
|
-
}
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
6
|
+
const SUPPORTED_RESOLUTIONS = /* @__PURE__ */ new Set([
|
|
7
|
+
"1m",
|
|
8
|
+
"5m",
|
|
9
|
+
"15m",
|
|
10
|
+
"30m",
|
|
11
|
+
"1h",
|
|
12
|
+
"4h",
|
|
13
|
+
"12h",
|
|
14
|
+
"1d"
|
|
15
|
+
]);
|
|
19
16
|
class LighterCandleWs extends BaseCandleWs {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
ownMessageListenerId = null;
|
|
23
|
-
ownOpenListenerId = null;
|
|
24
|
-
buildSubscribeMessage(symbol, _interval) {
|
|
25
|
-
return { type: "subscribe", channel: `trade/${symbol}` };
|
|
26
|
-
}
|
|
27
|
-
buildUnsubscribeMessage(symbol, _interval) {
|
|
28
|
-
return { type: "unsubscribe", channel: `trade/${symbol}` };
|
|
29
|
-
}
|
|
30
|
-
parseMessage(_data) {
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
start() {
|
|
34
|
-
if (this.ownMessageListenerId) return;
|
|
35
|
-
this.ownMessageListenerId = this.transport.addMessageListener((data) => {
|
|
36
|
-
this.handleTradeMessage(data);
|
|
37
|
-
});
|
|
38
|
-
this.ownOpenListenerId = this.transport.addOpenListener(() => {
|
|
39
|
-
this.candleState.clear();
|
|
40
|
-
for (const [symbol, intervals] of this.symbolIntervals) {
|
|
41
|
-
this.transport.send(this.buildSubscribeMessage(symbol, "1m"));
|
|
42
|
-
for (const interval of intervals) {
|
|
43
|
-
void this.seedFromHistory(symbol, interval);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
if (!this.transport.connected) {
|
|
48
|
-
this.transport.connect();
|
|
49
|
-
} else {
|
|
50
|
-
for (const symbol of this.symbolIntervals.keys()) {
|
|
51
|
-
this.transport.send(this.buildSubscribeMessage(symbol, "1m"));
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
stop() {
|
|
56
|
-
if (this.ownMessageListenerId) {
|
|
57
|
-
this.transport.removeMessageListener(this.ownMessageListenerId);
|
|
58
|
-
this.ownMessageListenerId = null;
|
|
59
|
-
}
|
|
60
|
-
if (this.ownOpenListenerId) {
|
|
61
|
-
this.transport.removeOpenListener(this.ownOpenListenerId);
|
|
62
|
-
this.ownOpenListenerId = null;
|
|
63
|
-
}
|
|
64
|
-
if (this.transport.connected) {
|
|
65
|
-
for (const symbol of this.symbolIntervals.keys()) {
|
|
66
|
-
this.transport.send(this.buildUnsubscribeMessage(symbol, "1m"));
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
this.symbolIntervals.clear();
|
|
70
|
-
this.candleState.clear();
|
|
71
|
-
super.stop();
|
|
72
|
-
}
|
|
73
|
-
subscribe(symbol, interval) {
|
|
74
|
-
let intervals = this.symbolIntervals.get(symbol);
|
|
75
|
-
if (!intervals) {
|
|
76
|
-
intervals = /* @__PURE__ */ new Set();
|
|
77
|
-
this.symbolIntervals.set(symbol, intervals);
|
|
78
|
-
}
|
|
79
|
-
const isFirstForSymbol = intervals.size === 0;
|
|
80
|
-
intervals.add(interval);
|
|
81
|
-
if (isFirstForSymbol && this.transport.connected) {
|
|
82
|
-
this.transport.send(this.buildSubscribeMessage(symbol, interval));
|
|
83
|
-
}
|
|
84
|
-
void this.seedFromHistory(symbol, interval);
|
|
85
|
-
}
|
|
86
|
-
unsubscribe(symbol, interval) {
|
|
87
|
-
const intervals = this.symbolIntervals.get(symbol);
|
|
88
|
-
if (!intervals) return;
|
|
89
|
-
intervals.delete(interval);
|
|
90
|
-
if (intervals.size === 0) {
|
|
91
|
-
this.symbolIntervals.delete(symbol);
|
|
92
|
-
this.candleState.delete(symbol);
|
|
93
|
-
if (this.transport.connected) {
|
|
94
|
-
this.transport.send(this.buildUnsubscribeMessage(symbol, interval));
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
// Called before subscribe() in attachCandleWs so seedFromHistory can skip its fetch when
|
|
99
|
-
// the current period is already covered by historical data.
|
|
100
|
-
onHistoricalDataFetched(symbol, interval, candles) {
|
|
101
|
-
if (candles.length === 0) return;
|
|
102
|
-
const lastCandle = candles[candles.length - 1];
|
|
103
|
-
if (!lastCandle) return;
|
|
104
|
-
const intervalMs = getIntervalSeconds(interval) * 1e3;
|
|
105
|
-
if (lastCandle.t !== toIntervalOpenTime(Date.now(), intervalMs)) return;
|
|
106
|
-
this.applyCandleState(symbol, interval, {
|
|
107
|
-
openTime: lastCandle.t,
|
|
108
|
-
closeTime: lastCandle.T,
|
|
109
|
-
open: lastCandle.o,
|
|
110
|
-
high: lastCandle.h,
|
|
111
|
-
low: lastCandle.l,
|
|
112
|
-
close: lastCandle.c
|
|
113
|
-
});
|
|
17
|
+
static {
|
|
18
|
+
__name(this, "LighterCandleWs");
|
|
114
19
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
symbolState.set(interval, state);
|
|
20
|
+
/** Subscribes to a market's candle stream; `symbol` is Lighter's numeric market id. */
|
|
21
|
+
buildSubscribeMessage(symbol, interval) {
|
|
22
|
+
const authToken = this.transport.authToken;
|
|
23
|
+
if (!authToken) {
|
|
24
|
+
return {
|
|
25
|
+
type: "subscribe",
|
|
26
|
+
channel: `candle/${symbol}/${interval}`
|
|
27
|
+
};
|
|
124
28
|
}
|
|
29
|
+
return {
|
|
30
|
+
type: "subscribe",
|
|
31
|
+
channel: `candle/${symbol}/${interval}`,
|
|
32
|
+
auth: authToken
|
|
33
|
+
};
|
|
125
34
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
if (this.candleState.get(symbol)?.get(interval)?.openTime === openTime) return;
|
|
133
|
-
try {
|
|
134
|
-
const params = new URLSearchParams({
|
|
135
|
-
market_id: symbol,
|
|
136
|
-
resolution,
|
|
137
|
-
start_timestamp: String(openTime),
|
|
138
|
-
end_timestamp: String(now),
|
|
139
|
-
count_back: "1"
|
|
140
|
-
});
|
|
141
|
-
const response = await fetch(`${LIGHTER_BASE_URL}/api/v1/candles?${params}`);
|
|
142
|
-
if (!response.ok) return;
|
|
143
|
-
const data = await response.json();
|
|
144
|
-
if (data.code !== 200 || !data.c?.length) return;
|
|
145
|
-
const candle = data.c[data.c.length - 1];
|
|
146
|
-
if (!this.symbolIntervals.get(symbol)?.has(interval)) return;
|
|
147
|
-
this.applyCandleState(symbol, interval, {
|
|
148
|
-
openTime: candle.t,
|
|
149
|
-
closeTime: candle.t + intervalMs - 1,
|
|
150
|
-
open: candle.o ?? 0,
|
|
151
|
-
high: candle.h ?? 0,
|
|
152
|
-
low: candle.l ?? 0,
|
|
153
|
-
close: candle.c ?? 0
|
|
154
|
-
});
|
|
155
|
-
} catch {
|
|
156
|
-
}
|
|
35
|
+
/** Mirrors the subscribe channel — Lighter keys unsubscribes by the same slash-delimited name. */
|
|
36
|
+
buildUnsubscribeMessage(symbol, interval) {
|
|
37
|
+
return {
|
|
38
|
+
type: "unsubscribe",
|
|
39
|
+
channel: `candle/${symbol}/${interval}`
|
|
40
|
+
};
|
|
157
41
|
}
|
|
158
|
-
|
|
159
|
-
|
|
42
|
+
/**
|
|
43
|
+
* Translates one candle message into CandleData, oldest first.
|
|
44
|
+
*
|
|
45
|
+
* Lighter batches updates every 500ms and, when a period rolls over, sends the just-closed candle
|
|
46
|
+
* followed by the newly opened one — both are emitted so the closed bar keeps its final trades.
|
|
47
|
+
*/
|
|
48
|
+
parseMessages(data) {
|
|
49
|
+
let message;
|
|
160
50
|
try {
|
|
161
|
-
|
|
51
|
+
message = JSON.parse(data);
|
|
162
52
|
} catch {
|
|
163
|
-
|
|
164
|
-
return;
|
|
53
|
+
return [];
|
|
165
54
|
}
|
|
166
|
-
if (
|
|
167
|
-
|
|
168
|
-
const colonIdx = msg.channel.indexOf(":");
|
|
169
|
-
if (colonIdx === -1 || !msg.channel.startsWith("trade")) return;
|
|
170
|
-
const symbol = msg.channel.slice(colonIdx + 1);
|
|
171
|
-
const intervals = this.symbolIntervals.get(symbol);
|
|
172
|
-
if (!intervals || intervals.size === 0) return;
|
|
173
|
-
let symbolState = this.candleState.get(symbol);
|
|
174
|
-
if (!symbolState) {
|
|
175
|
-
symbolState = /* @__PURE__ */ new Map();
|
|
176
|
-
this.candleState.set(symbol, symbolState);
|
|
55
|
+
if (message.type !== "subscribed/candle" && message.type !== "update/candle") {
|
|
56
|
+
return [];
|
|
177
57
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
intervalMsMap.set(interval, getIntervalSeconds(interval) * 1e3);
|
|
58
|
+
if (!Array.isArray(message.candles) || message.candles.length === 0) {
|
|
59
|
+
return [];
|
|
181
60
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
for (const interval of intervals) {
|
|
186
|
-
const intervalMs = intervalMsMap.get(interval);
|
|
187
|
-
if (intervalMs === void 0) continue;
|
|
188
|
-
const openTime = toIntervalOpenTime(ts, intervalMs);
|
|
189
|
-
const closeTime = openTime + intervalMs - 1;
|
|
190
|
-
const existing = symbolState.get(interval);
|
|
191
|
-
let state;
|
|
192
|
-
if (!existing || existing.openTime !== openTime) {
|
|
193
|
-
state = { openTime, closeTime, open: price, high: price, low: price, close: price };
|
|
194
|
-
symbolState.set(interval, state);
|
|
195
|
-
} else {
|
|
196
|
-
if (price > existing.high) existing.high = price;
|
|
197
|
-
if (price < existing.low) existing.low = price;
|
|
198
|
-
existing.close = price;
|
|
199
|
-
state = existing;
|
|
200
|
-
}
|
|
201
|
-
this.onCandle(symbol, {
|
|
202
|
-
t: state.openTime,
|
|
203
|
-
T: state.closeTime,
|
|
204
|
-
o: state.open,
|
|
205
|
-
h: state.high,
|
|
206
|
-
l: state.low,
|
|
207
|
-
c: state.close
|
|
208
|
-
});
|
|
209
|
-
}
|
|
61
|
+
const route = parseChannel(message.channel);
|
|
62
|
+
if (!route) {
|
|
63
|
+
return [];
|
|
210
64
|
}
|
|
65
|
+
const intervalMs = getIntervalSeconds(route.interval) * 1e3;
|
|
66
|
+
return message.candles.map((candle) => ({
|
|
67
|
+
symbol: route.symbol,
|
|
68
|
+
candle: toCandleData(candle, intervalMs)
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function parseChannel(channel) {
|
|
73
|
+
if (!channel) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
const [prefix, symbol, resolution] = channel.split(":");
|
|
77
|
+
if (prefix !== "candle" || !symbol || !resolution) {
|
|
78
|
+
return null;
|
|
211
79
|
}
|
|
80
|
+
if (!SUPPORTED_RESOLUTIONS.has(resolution)) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
symbol,
|
|
85
|
+
interval: resolution
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
__name(parseChannel, "parseChannel");
|
|
89
|
+
function toCandleData(candle, intervalMs) {
|
|
90
|
+
return {
|
|
91
|
+
t: candle.t,
|
|
92
|
+
T: candle.t + intervalMs - 1,
|
|
93
|
+
o: candle.o ?? 0,
|
|
94
|
+
h: candle.h ?? 0,
|
|
95
|
+
l: candle.l ?? 0,
|
|
96
|
+
c: candle.c ?? 0
|
|
97
|
+
};
|
|
212
98
|
}
|
|
99
|
+
__name(toCandleData, "toCandleData");
|
|
213
100
|
|
|
214
101
|
export { LighterCandleWs };
|
package/dist/chart/ws/okx.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { WsMessage } from '../../shared/types.js';
|
|
2
|
-
import { CandleInterval
|
|
3
|
-
import { BaseCandleWs } from './base-candle.js';
|
|
2
|
+
import { CandleInterval } from '../types.js';
|
|
3
|
+
import { BaseCandleWs, ParsedCandle } from './base-candle.js';
|
|
4
4
|
import '../../transport/index.js';
|
|
5
5
|
import '@pear-protocol/types';
|
|
6
6
|
import '../../transport/base-transport.js';
|
|
@@ -9,10 +9,8 @@ import 'partysocket';
|
|
|
9
9
|
declare class OkxCandleWs extends BaseCandleWs {
|
|
10
10
|
protected buildSubscribeMessage(symbol: string, interval: CandleInterval): WsMessage;
|
|
11
11
|
protected buildUnsubscribeMessage(symbol: string, interval: CandleInterval): WsMessage;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
candle: CandleData;
|
|
15
|
-
} | null;
|
|
12
|
+
/** Translates one OKX candle frame into a single-candle batch. */
|
|
13
|
+
protected parseMessages(data: string): ParsedCandle[];
|
|
16
14
|
}
|
|
17
15
|
|
|
18
16
|
export { OkxCandleWs };
|
package/dist/chart/ws/okx.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { BaseCandleWs } from './base-candle';
|
|
2
2
|
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
5
|
const intervalMap = {
|
|
4
6
|
"1m": "1m",
|
|
5
7
|
"3m": "3m",
|
|
@@ -16,44 +18,66 @@ const intervalMap = {
|
|
|
16
18
|
"1w": "1W",
|
|
17
19
|
"1M": "1M"
|
|
18
20
|
};
|
|
19
|
-
const toChannel = (interval) => `candle${intervalMap[interval]}
|
|
21
|
+
const toChannel = /* @__PURE__ */ __name((interval) => `candle${intervalMap[interval]}`, "toChannel");
|
|
20
22
|
class OkxCandleWs extends BaseCandleWs {
|
|
23
|
+
static {
|
|
24
|
+
__name(this, "OkxCandleWs");
|
|
25
|
+
}
|
|
21
26
|
buildSubscribeMessage(symbol, interval) {
|
|
22
27
|
return {
|
|
23
28
|
op: "subscribe",
|
|
24
|
-
args: [
|
|
29
|
+
args: [
|
|
30
|
+
{
|
|
31
|
+
channel: toChannel(interval),
|
|
32
|
+
instId: symbol
|
|
33
|
+
}
|
|
34
|
+
]
|
|
25
35
|
};
|
|
26
36
|
}
|
|
27
37
|
buildUnsubscribeMessage(symbol, interval) {
|
|
28
38
|
return {
|
|
29
39
|
op: "unsubscribe",
|
|
30
|
-
args: [
|
|
40
|
+
args: [
|
|
41
|
+
{
|
|
42
|
+
channel: toChannel(interval),
|
|
43
|
+
instId: symbol
|
|
44
|
+
}
|
|
45
|
+
]
|
|
31
46
|
};
|
|
32
47
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
48
|
+
/** Translates one OKX candle frame into a single-candle batch. */
|
|
49
|
+
parseMessages(data) {
|
|
50
|
+
if (data === "pong") {
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
let message;
|
|
36
54
|
try {
|
|
37
|
-
|
|
55
|
+
message = JSON.parse(data);
|
|
38
56
|
} catch {
|
|
39
|
-
return
|
|
57
|
+
return [];
|
|
40
58
|
}
|
|
41
|
-
const arg =
|
|
42
|
-
const candleData =
|
|
43
|
-
if (!arg || !candleData || !Array.isArray(candleData) || candleData.length === 0)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
59
|
+
const arg = message.arg;
|
|
60
|
+
const candleData = message.data;
|
|
61
|
+
if (!arg || !candleData || !Array.isArray(candleData) || candleData.length === 0) {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
if (!arg.channel.startsWith("candle")) {
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
const tuple = candleData[0];
|
|
68
|
+
return [
|
|
69
|
+
{
|
|
70
|
+
symbol: arg.instId,
|
|
71
|
+
candle: {
|
|
72
|
+
t: Number(tuple[0]),
|
|
73
|
+
T: Number(tuple[0]),
|
|
74
|
+
o: Number(tuple[1]),
|
|
75
|
+
h: Number(tuple[2]),
|
|
76
|
+
l: Number(tuple[3]),
|
|
77
|
+
c: Number(tuple[4])
|
|
78
|
+
}
|
|
55
79
|
}
|
|
56
|
-
|
|
80
|
+
];
|
|
57
81
|
}
|
|
58
82
|
}
|
|
59
83
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { FundingRateEntry } from '../types.js';
|
|
2
2
|
import '../../transport/index.js';
|
|
3
3
|
import '@pear-protocol/types';
|
|
4
|
+
import '../../shared/types.js';
|
|
4
5
|
import '../../transport/base-transport.js';
|
|
5
6
|
import 'partysocket';
|
|
6
|
-
import '../../shared/types.js';
|
|
7
7
|
|
|
8
8
|
declare function fetchHistoricalFundingRates(symbol: string, startTime: number, endTime: number): Promise<FundingRateEntry[]>;
|
|
9
9
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { httpGet } from './http-client';
|
|
2
2
|
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
5
|
const BINANCE_FUTURES_URL = "https://fapi.binance.com/fapi/v1/fundingRate";
|
|
4
6
|
const MAX_LIMIT = 1e3;
|
|
5
7
|
async function fetchHistoricalFundingRates(symbol, startTime, endTime) {
|
|
@@ -14,7 +16,10 @@ async function fetchHistoricalFundingRates(symbol, startTime, endTime) {
|
|
|
14
16
|
});
|
|
15
17
|
if (data.length === 0) break;
|
|
16
18
|
for (const entry of data) {
|
|
17
|
-
allRates.push({
|
|
19
|
+
allRates.push({
|
|
20
|
+
time: entry.fundingTime,
|
|
21
|
+
rate: Number(entry.fundingRate)
|
|
22
|
+
});
|
|
18
23
|
}
|
|
19
24
|
const lastTime = data[data.length - 1]?.fundingTime;
|
|
20
25
|
if (!lastTime || lastTime <= cursor) break;
|
|
@@ -22,5 +27,6 @@ async function fetchHistoricalFundingRates(symbol, startTime, endTime) {
|
|
|
22
27
|
}
|
|
23
28
|
return allRates.sort((a, b) => a.time - b.time);
|
|
24
29
|
}
|
|
30
|
+
__name(fetchHistoricalFundingRates, "fetchHistoricalFundingRates");
|
|
25
31
|
|
|
26
32
|
export { fetchHistoricalFundingRates };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { FundingRateEntry } from '../types.js';
|
|
2
2
|
import '../../transport/index.js';
|
|
3
3
|
import '@pear-protocol/types';
|
|
4
|
+
import '../../shared/types.js';
|
|
4
5
|
import '../../transport/base-transport.js';
|
|
5
6
|
import 'partysocket';
|
|
6
|
-
import '../../shared/types.js';
|
|
7
7
|
|
|
8
8
|
declare function fetchHistoricalFundingRates(symbol: string, startTime: number, endTime: number): Promise<FundingRateEntry[]>;
|
|
9
9
|
|
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
import { httpGet } from './http-client';
|
|
2
2
|
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
5
|
const BYBIT_URL = "https://api.bybit.com/v5/market/funding/history";
|
|
4
6
|
const MAX_LIMIT = 200;
|
|
5
7
|
async function fetchHistoricalFundingRates(symbol, startTime, endTime) {
|
|
6
8
|
const allRates = [];
|
|
7
9
|
let cursor = endTime;
|
|
8
|
-
const validate = (d) => d.retCode !== 0 ? `Bybit API error: ${d.retMsg}` : void 0;
|
|
10
|
+
const validate = /* @__PURE__ */ __name((d) => d.retCode !== 0 ? `Bybit API error: ${d.retMsg}` : void 0, "validate");
|
|
9
11
|
while (cursor > startTime) {
|
|
10
|
-
const data = await httpGet(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
limit: String(MAX_LIMIT)
|
|
18
|
-
},
|
|
19
|
-
validate
|
|
20
|
-
);
|
|
12
|
+
const data = await httpGet(BYBIT_URL, {
|
|
13
|
+
category: "linear",
|
|
14
|
+
symbol,
|
|
15
|
+
startTime: String(startTime),
|
|
16
|
+
endTime: String(cursor),
|
|
17
|
+
limit: String(MAX_LIMIT)
|
|
18
|
+
}, validate);
|
|
21
19
|
if (data.result.list.length === 0) break;
|
|
22
20
|
for (const entry of data.result.list) {
|
|
23
|
-
allRates.push({
|
|
21
|
+
allRates.push({
|
|
22
|
+
time: Number(entry.fundingRateTimestamp),
|
|
23
|
+
rate: Number(entry.fundingRate)
|
|
24
|
+
});
|
|
24
25
|
}
|
|
25
26
|
const oldestTime = Number(data.result.list[data.result.list.length - 1]?.fundingRateTimestamp);
|
|
26
27
|
if (!oldestTime || oldestTime >= cursor) break;
|
|
@@ -28,5 +29,6 @@ async function fetchHistoricalFundingRates(symbol, startTime, endTime) {
|
|
|
28
29
|
}
|
|
29
30
|
return allRates.sort((a, b) => a.time - b.time);
|
|
30
31
|
}
|
|
32
|
+
__name(fetchHistoricalFundingRates, "fetchHistoricalFundingRates");
|
|
31
33
|
|
|
32
34
|
export { fetchHistoricalFundingRates };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
type ResponseValidator<T> = (data: T) => string | undefined;
|
|
2
|
-
declare function httpGet<T>(url: string, params: Record<string, string>, validate?: ResponseValidator<T>): Promise<T>;
|
|
2
|
+
declare function httpGet<T>(url: string, params: Record<string, string>, validate?: ResponseValidator<T>, headers?: Record<string, string>): Promise<T>;
|
|
3
3
|
declare function httpPost<T>(url: string, body: unknown, validate?: ResponseValidator<T>): Promise<T>;
|
|
4
4
|
|
|
5
5
|
export { type ResponseValidator, httpGet, httpPost };
|
|
@@ -1,20 +1,24 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
1
3
|
const BASE_DELAY_MS = 1e3;
|
|
2
4
|
const MAX_DELAY_MS = 6e4;
|
|
3
|
-
async function httpGet(url, params, validate) {
|
|
5
|
+
async function httpGet(url, params, validate, headers) {
|
|
4
6
|
const qs = new URLSearchParams(params).toString();
|
|
5
|
-
return httpFetch(`${url}?${qs}`,
|
|
7
|
+
return httpFetch(`${url}?${qs}`, headers ? {
|
|
8
|
+
headers
|
|
9
|
+
} : void 0, validate);
|
|
6
10
|
}
|
|
11
|
+
__name(httpGet, "httpGet");
|
|
7
12
|
async function httpPost(url, body, validate) {
|
|
8
|
-
return httpFetch(
|
|
9
|
-
|
|
10
|
-
{
|
|
11
|
-
|
|
12
|
-
headers: { "Content-Type": "application/json" },
|
|
13
|
-
body: JSON.stringify(body)
|
|
13
|
+
return httpFetch(url, {
|
|
14
|
+
method: "POST",
|
|
15
|
+
headers: {
|
|
16
|
+
"Content-Type": "application/json"
|
|
14
17
|
},
|
|
15
|
-
|
|
16
|
-
);
|
|
18
|
+
body: JSON.stringify(body)
|
|
19
|
+
}, validate);
|
|
17
20
|
}
|
|
21
|
+
__name(httpPost, "httpPost");
|
|
18
22
|
async function httpFetch(url, init, validate) {
|
|
19
23
|
let attempt = 0;
|
|
20
24
|
while (true) {
|
|
@@ -36,5 +40,6 @@ async function httpFetch(url, init, validate) {
|
|
|
36
40
|
return data;
|
|
37
41
|
}
|
|
38
42
|
}
|
|
43
|
+
__name(httpFetch, "httpFetch");
|
|
39
44
|
|
|
40
45
|
export { httpGet, httpPost };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { FundingRateEntry } from '../types.js';
|
|
2
2
|
import '../../transport/index.js';
|
|
3
3
|
import '@pear-protocol/types';
|
|
4
|
+
import '../../shared/types.js';
|
|
4
5
|
import '../../transport/base-transport.js';
|
|
5
6
|
import 'partysocket';
|
|
6
|
-
import '../../shared/types.js';
|
|
7
7
|
|
|
8
8
|
declare function fetchHistoricalFundingRates(symbol: string, startTime: number, endTime: number): Promise<FundingRateEntry[]>;
|
|
9
9
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { httpPost } from './http-client';
|
|
2
2
|
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
5
|
async function fetchHistoricalFundingRates(symbol, startTime, endTime) {
|
|
4
6
|
const allRates = [];
|
|
5
7
|
let cursor = startTime;
|
|
@@ -13,7 +15,10 @@ async function fetchHistoricalFundingRates(symbol, startTime, endTime) {
|
|
|
13
15
|
if (data.length === 0) break;
|
|
14
16
|
for (const entry of data) {
|
|
15
17
|
if (entry.time >= endTime) continue;
|
|
16
|
-
allRates.push({
|
|
18
|
+
allRates.push({
|
|
19
|
+
time: entry.time,
|
|
20
|
+
rate: Number(entry.fundingRate)
|
|
21
|
+
});
|
|
17
22
|
}
|
|
18
23
|
const lastTime = data[data.length - 1]?.time;
|
|
19
24
|
if (!lastTime || lastTime <= cursor) break;
|
|
@@ -21,5 +26,6 @@ async function fetchHistoricalFundingRates(symbol, startTime, endTime) {
|
|
|
21
26
|
}
|
|
22
27
|
return allRates.sort((a, b) => a.time - b.time);
|
|
23
28
|
}
|
|
29
|
+
__name(fetchHistoricalFundingRates, "fetchHistoricalFundingRates");
|
|
24
30
|
|
|
25
31
|
export { fetchHistoricalFundingRates };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Connector } from '@pear-protocol/types';
|
|
2
2
|
import { FundingRateDuration, FundingRateEntry } from '../types.js';
|
|
3
3
|
import '../../transport/index.js';
|
|
4
|
+
import '../../shared/types.js';
|
|
4
5
|
import '../../transport/base-transport.js';
|
|
5
6
|
import 'partysocket';
|
|
6
|
-
import '../../shared/types.js';
|
|
7
7
|
|
|
8
|
-
declare function fetchHistoricalFundingRates(connector: Connector, symbol: string, startTime: number, endTime: number, duration: FundingRateDuration): Promise<FundingRateEntry[]>;
|
|
8
|
+
declare function fetchHistoricalFundingRates(connector: Connector, symbol: string, startTime: number, endTime: number, duration: FundingRateDuration, authToken?: string): Promise<FundingRateEntry[]>;
|
|
9
9
|
|
|
10
10
|
export { fetchHistoricalFundingRates };
|
|
@@ -4,7 +4,9 @@ import { fetchHistoricalFundingRates as fetchHistoricalFundingRates$5 } from './
|
|
|
4
4
|
import { fetchHistoricalFundingRates as fetchHistoricalFundingRates$1 } from './lighter';
|
|
5
5
|
import { fetchHistoricalFundingRates as fetchHistoricalFundingRates$2 } from './okx';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
var __defProp = Object.defineProperty;
|
|
8
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
9
|
+
async function fetchHistoricalFundingRates(connector, symbol, startTime, endTime, duration, authToken) {
|
|
8
10
|
switch (connector) {
|
|
9
11
|
case "hyperliquid":
|
|
10
12
|
return fetchHistoricalFundingRates$5(symbol, startTime, endTime);
|
|
@@ -15,10 +17,11 @@ async function fetchHistoricalFundingRates(connector, symbol, startTime, endTime
|
|
|
15
17
|
case "okx":
|
|
16
18
|
return fetchHistoricalFundingRates$2(symbol, startTime, endTime);
|
|
17
19
|
case "lighter":
|
|
18
|
-
return fetchHistoricalFundingRates$1(symbol, startTime, endTime, duration);
|
|
20
|
+
return fetchHistoricalFundingRates$1(symbol, startTime, endTime, duration, authToken);
|
|
19
21
|
default:
|
|
20
22
|
throw new Error(`Unsupported connector: ${connector}`);
|
|
21
23
|
}
|
|
22
24
|
}
|
|
25
|
+
__name(fetchHistoricalFundingRates, "fetchHistoricalFundingRates");
|
|
23
26
|
|
|
24
27
|
export { fetchHistoricalFundingRates };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { FundingRateDuration, FundingRateEntry } from '../types.js';
|
|
2
2
|
import '../../transport/index.js';
|
|
3
3
|
import '@pear-protocol/types';
|
|
4
|
+
import '../../shared/types.js';
|
|
4
5
|
import '../../transport/base-transport.js';
|
|
5
6
|
import 'partysocket';
|
|
6
|
-
import '../../shared/types.js';
|
|
7
7
|
|
|
8
|
-
declare function fetchHistoricalFundingRates(symbol: string, startTime: number, endTime: number, _duration: FundingRateDuration): Promise<FundingRateEntry[]>;
|
|
8
|
+
declare function fetchHistoricalFundingRates(symbol: string, startTime: number, endTime: number, _duration: FundingRateDuration, authToken?: string): Promise<FundingRateEntry[]>;
|
|
9
9
|
|
|
10
10
|
export { fetchHistoricalFundingRates };
|