@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
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import BigNumber from 'bignumber.js';
|
|
2
2
|
import { httpGet } from './http-client';
|
|
3
3
|
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
4
6
|
const BASE_URL = "https://mainnet.zklighter.elliot.ai";
|
|
5
7
|
const MAX_LIMIT = 500;
|
|
6
|
-
async function fetchHistoricalFundingRates(symbol, startTime, endTime, _duration) {
|
|
8
|
+
async function fetchHistoricalFundingRates(symbol, startTime, endTime, _duration, authToken) {
|
|
7
9
|
const intervalMs = 60 * 60 * 1e3;
|
|
8
10
|
const allRates = [];
|
|
9
11
|
let cursor = startTime;
|
|
@@ -15,13 +17,18 @@ async function fetchHistoricalFundingRates(symbol, startTime, endTime, _duration
|
|
|
15
17
|
start_timestamp: String(cursor),
|
|
16
18
|
end_timestamp: String(endTime),
|
|
17
19
|
count_back: String(countBack)
|
|
18
|
-
}
|
|
20
|
+
}, void 0, authToken ? {
|
|
21
|
+
authorization: authToken
|
|
22
|
+
} : void 0);
|
|
19
23
|
const entries = data.fundings ?? [];
|
|
20
24
|
if (entries.length === 0) break;
|
|
21
25
|
for (const entry of entries) {
|
|
22
26
|
const timeMs = entry.timestamp * 1e3;
|
|
23
27
|
const rate = entry.rate ? new BigNumber(entry.rate).dividedBy(100).times(entry.direction === "long" ? -1 : 1).toNumber() : 0;
|
|
24
|
-
allRates.push({
|
|
28
|
+
allRates.push({
|
|
29
|
+
time: timeMs,
|
|
30
|
+
rate
|
|
31
|
+
});
|
|
25
32
|
}
|
|
26
33
|
const lastTimestamp = entries[entries.length - 1]?.timestamp;
|
|
27
34
|
if (!lastTimestamp) break;
|
|
@@ -31,5 +38,6 @@ async function fetchHistoricalFundingRates(symbol, startTime, endTime, _duration
|
|
|
31
38
|
}
|
|
32
39
|
return allRates.sort((a, b) => a.time - b.time);
|
|
33
40
|
}
|
|
41
|
+
__name(fetchHistoricalFundingRates, "fetchHistoricalFundingRates");
|
|
34
42
|
|
|
35
43
|
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(instId: string, startTime: number, endTime: number): Promise<FundingRateEntry[]>;
|
|
9
9
|
|
|
@@ -1,27 +1,28 @@
|
|
|
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 OKX_URL = "https://www.okx.com/api/v5/public/funding-rate-history";
|
|
4
6
|
const MAX_LIMIT = 400;
|
|
5
7
|
async function fetchHistoricalFundingRates(instId, startTime, endTime) {
|
|
6
8
|
const allRates = [];
|
|
7
9
|
let cursor = endTime;
|
|
8
|
-
const validate = (d) => d.code !== "0" ? `OKX API error: ${d.msg}` : void 0;
|
|
10
|
+
const validate = /* @__PURE__ */ __name((d) => d.code !== "0" ? `OKX API error: ${d.msg}` : void 0, "validate");
|
|
9
11
|
while (cursor > startTime) {
|
|
10
|
-
const data = await httpGet(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
limit: String(MAX_LIMIT)
|
|
17
|
-
},
|
|
18
|
-
validate
|
|
19
|
-
);
|
|
12
|
+
const data = await httpGet(OKX_URL, {
|
|
13
|
+
instId,
|
|
14
|
+
before: String(startTime),
|
|
15
|
+
after: String(cursor),
|
|
16
|
+
limit: String(MAX_LIMIT)
|
|
17
|
+
}, validate);
|
|
20
18
|
if (data.data.length === 0) break;
|
|
21
19
|
let oldestTime = Infinity;
|
|
22
20
|
for (const entry of data.data) {
|
|
23
21
|
const time = Number(entry.fundingTime);
|
|
24
|
-
allRates.push({
|
|
22
|
+
allRates.push({
|
|
23
|
+
time,
|
|
24
|
+
rate: Number(entry.realizedRate)
|
|
25
|
+
});
|
|
25
26
|
if (time < oldestTime) oldestTime = time;
|
|
26
27
|
}
|
|
27
28
|
if (oldestTime >= cursor) break;
|
|
@@ -29,5 +30,6 @@ async function fetchHistoricalFundingRates(instId, startTime, endTime) {
|
|
|
29
30
|
}
|
|
30
31
|
return allRates.filter((r) => r.time >= startTime && r.time < endTime).sort((a, b) => a.time - b.time);
|
|
31
32
|
}
|
|
33
|
+
__name(fetchHistoricalFundingRates, "fetchHistoricalFundingRates");
|
|
32
34
|
|
|
33
35
|
export { fetchHistoricalFundingRates };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { FundingRateConfig, TokenSelection, FundingRateAggregation, 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
8
|
declare class FundingRate {
|
|
9
9
|
private transport;
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { fetchHistoricalFundingRates } from './fetcher';
|
|
2
2
|
import { aggregateRates, annualizeRates, computeBasketRates, computeStartTime } from './utils';
|
|
3
3
|
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
4
6
|
const DEFAULT_AGGREGATION = "1d";
|
|
5
7
|
const DEFAULT_DURATION = "1m";
|
|
6
8
|
class FundingRate {
|
|
9
|
+
static {
|
|
10
|
+
__name(this, "FundingRate");
|
|
11
|
+
}
|
|
7
12
|
transport;
|
|
8
13
|
longTokens;
|
|
9
14
|
shortTokens;
|
|
@@ -83,29 +88,33 @@ class FundingRate {
|
|
|
83
88
|
}
|
|
84
89
|
async refetch(tokens, start, end, duration) {
|
|
85
90
|
if (tokens.length === 0) return;
|
|
86
|
-
await
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
91
|
+
const authToken = await this.transport.retrieveAuthToken();
|
|
92
|
+
await Promise.all(tokens.map(async (token) => {
|
|
93
|
+
const existing = this.cache[token.symbol];
|
|
94
|
+
const fetchStart = existing ? Math.min(start, existing.start) : start;
|
|
95
|
+
const fetchEnd = existing ? Math.max(end, existing.end) : end;
|
|
96
|
+
try {
|
|
97
|
+
const rates = await fetchHistoricalFundingRates(this.transport.connector, token.symbol, fetchStart, fetchEnd, duration, authToken);
|
|
98
|
+
this.cache[token.symbol] = {
|
|
99
|
+
entries: rates,
|
|
100
|
+
start: fetchStart,
|
|
101
|
+
end: fetchEnd
|
|
102
|
+
};
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.warn(`Failed to fetch funding rate data for ${token.symbol}:`, error);
|
|
105
|
+
this.cache[token.symbol] = {
|
|
106
|
+
entries: [],
|
|
107
|
+
start: fetchStart,
|
|
108
|
+
end: fetchEnd
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}));
|
|
106
112
|
}
|
|
107
113
|
getAllTokens() {
|
|
108
|
-
return [
|
|
114
|
+
return [
|
|
115
|
+
...this.longTokens,
|
|
116
|
+
...this.shortTokens
|
|
117
|
+
];
|
|
109
118
|
}
|
|
110
119
|
assertTokenExists(symbol) {
|
|
111
120
|
if (!this.getAllTokens().some((t) => t.symbol === symbol)) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { FundingRateEntry, FundingRateAggregation, TokenSelection, FundingRateDuration } 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 computeStartTime(endTime: number, duration: FundingRateDuration): number;
|
|
9
9
|
declare function aggregateRates(rawRates: FundingRateEntry[], aggregation: FundingRateAggregation): FundingRateEntry[];
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import BigNumber from 'bignumber.js';
|
|
2
2
|
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
5
|
function computeStartTime(endTime, duration) {
|
|
4
6
|
const date = new Date(endTime);
|
|
5
7
|
switch (duration) {
|
|
@@ -13,6 +15,7 @@ function computeStartTime(endTime, duration) {
|
|
|
13
15
|
return date.getTime();
|
|
14
16
|
}
|
|
15
17
|
}
|
|
18
|
+
__name(computeStartTime, "computeStartTime");
|
|
16
19
|
function getBucketStart(timestamp, aggregation) {
|
|
17
20
|
const date = new Date(timestamp);
|
|
18
21
|
switch (aggregation) {
|
|
@@ -28,20 +31,29 @@ function getBucketStart(timestamp, aggregation) {
|
|
|
28
31
|
return Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), 1);
|
|
29
32
|
}
|
|
30
33
|
}
|
|
34
|
+
__name(getBucketStart, "getBucketStart");
|
|
31
35
|
function aggregateRates(rawRates, aggregation) {
|
|
32
36
|
if (aggregation === "none") {
|
|
33
|
-
return [
|
|
37
|
+
return [
|
|
38
|
+
...rawRates
|
|
39
|
+
].sort((a, b) => a.time - b.time);
|
|
34
40
|
}
|
|
35
41
|
const buckets = /* @__PURE__ */ new Map();
|
|
36
42
|
for (const rate of rawRates) {
|
|
37
43
|
const key = getBucketStart(rate.time, aggregation);
|
|
38
44
|
buckets.set(key, (buckets.get(key) ?? new BigNumber(0)).plus(rate.rate));
|
|
39
45
|
}
|
|
40
|
-
return Array.from(buckets.entries()).map(([time, rate]) => ({
|
|
46
|
+
return Array.from(buckets.entries()).map(([time, rate]) => ({
|
|
47
|
+
time,
|
|
48
|
+
rate: rate.toNumber()
|
|
49
|
+
})).sort((a, b) => a.time - b.time);
|
|
41
50
|
}
|
|
51
|
+
__name(aggregateRates, "aggregateRates");
|
|
42
52
|
function inferAvgIntervalMs(entries) {
|
|
43
53
|
if (entries.length < 2) return null;
|
|
44
|
-
const sorted = [
|
|
54
|
+
const sorted = [
|
|
55
|
+
...entries
|
|
56
|
+
].sort((a, b) => a.time - b.time);
|
|
45
57
|
let totalGap = new BigNumber(0);
|
|
46
58
|
let count = 0;
|
|
47
59
|
for (let i = 1; i < sorted.length; i++) {
|
|
@@ -56,6 +68,7 @@ function inferAvgIntervalMs(entries) {
|
|
|
56
68
|
}
|
|
57
69
|
return count > 0 ? totalGap.div(count) : null;
|
|
58
70
|
}
|
|
71
|
+
__name(inferAvgIntervalMs, "inferAvgIntervalMs");
|
|
59
72
|
const MS_PER_YEAR = 365 * 864e5;
|
|
60
73
|
function annualizeRates(entries, aggregation, rawEntriesForInference) {
|
|
61
74
|
let multiplier;
|
|
@@ -77,8 +90,12 @@ function annualizeRates(entries, aggregation, rawEntriesForInference) {
|
|
|
77
90
|
annualizedRate: new BigNumber(e.rate).times(multiplier).toNumber()
|
|
78
91
|
}));
|
|
79
92
|
}
|
|
93
|
+
__name(annualizeRates, "annualizeRates");
|
|
80
94
|
function computeBasketRates(longTokens, shortTokens, tokenRates) {
|
|
81
|
-
const allSymbols = [
|
|
95
|
+
const allSymbols = [
|
|
96
|
+
...longTokens,
|
|
97
|
+
...shortTokens
|
|
98
|
+
].map((t) => t.symbol);
|
|
82
99
|
if (allSymbols.length === 0) return [];
|
|
83
100
|
const lookups = {};
|
|
84
101
|
const allTimestamps = /* @__PURE__ */ new Set();
|
|
@@ -111,10 +128,14 @@ function computeBasketRates(longTokens, shortTokens, tokenRates) {
|
|
|
111
128
|
}
|
|
112
129
|
}
|
|
113
130
|
if (count > 0) {
|
|
114
|
-
result.push({
|
|
131
|
+
result.push({
|
|
132
|
+
time,
|
|
133
|
+
rate: total.toNumber()
|
|
134
|
+
});
|
|
115
135
|
}
|
|
116
136
|
}
|
|
117
137
|
return result;
|
|
118
138
|
}
|
|
139
|
+
__name(computeBasketRates, "computeBasketRates");
|
|
119
140
|
|
|
120
141
|
export { aggregateRates, annualizeRates, computeBasketRates, computeStartTime };
|
package/dist/index.d.ts
CHANGED
|
@@ -5,8 +5,8 @@ export { FundingRateAggregation, FundingRateConfig, FundingRateDuration, Funding
|
|
|
5
5
|
export { Orderbook } from './orderbook/orderbook.js';
|
|
6
6
|
export { AggregationConfig, BBO, CexAggregationConfig, HyperliquidAggregationConfig, OrderbookCallback, OrderbookConfig, OrderbookLevel, OrderbookSnapshot } from './orderbook/types.js';
|
|
7
7
|
export { getAvailableAggregations } from './orderbook/utils.js';
|
|
8
|
-
export {
|
|
8
|
+
export { AuthTokenProvider } from './shared/types.js';
|
|
9
|
+
export { CreateTransport, Transport, TransportOptions } from './transport/index.js';
|
|
9
10
|
export { BaseTransport } from './transport/base-transport.js';
|
|
10
11
|
import '@pear-protocol/types';
|
|
11
12
|
import 'partysocket';
|
|
12
|
-
import './shared/types.js';
|
|
@@ -2,9 +2,9 @@ import { OrderbookLevel } from '../types.js';
|
|
|
2
2
|
import { LocalBook } from './local-book.js';
|
|
3
3
|
import '../../transport/index.js';
|
|
4
4
|
import '@pear-protocol/types';
|
|
5
|
+
import '../../shared/types.js';
|
|
5
6
|
import '../../transport/base-transport.js';
|
|
6
7
|
import 'partysocket';
|
|
7
|
-
import '../../shared/types.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Pure aggregation of a LocalBook into top-N bid/ask buckets at the given
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import BigNumber from 'bignumber.js';
|
|
2
2
|
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
5
|
function aggregateBook(localBook, bucketSize, depth) {
|
|
4
6
|
const bucket = new BigNumber(bucketSize);
|
|
5
|
-
if (!bucket.isFinite() || bucket.lte(0)) return {
|
|
7
|
+
if (!bucket.isFinite() || bucket.lte(0)) return {
|
|
8
|
+
bids: [],
|
|
9
|
+
asks: []
|
|
10
|
+
};
|
|
6
11
|
return {
|
|
7
12
|
bids: walk(localBook.sortedBids(), bucket, "bid", depth),
|
|
8
13
|
asks: walk(localBook.sortedAsks(), bucket, "ask", depth)
|
|
9
14
|
};
|
|
10
15
|
}
|
|
16
|
+
__name(aggregateBook, "aggregateBook");
|
|
11
17
|
function walk(sorted, bucket, side, depth) {
|
|
12
18
|
const result = [];
|
|
13
19
|
let currentBoundary = null;
|
|
@@ -21,7 +27,10 @@ function walk(sorted, bucket, side, depth) {
|
|
|
21
27
|
const boundary = side === "bid" ? p.div(bucket).integerValue(BigNumber.ROUND_FLOOR).times(bucket) : p.div(bucket).integerValue(BigNumber.ROUND_CEIL).times(bucket);
|
|
22
28
|
if (currentBoundary === null || !boundary.eq(currentBoundary)) {
|
|
23
29
|
if (currentBoundary !== null) {
|
|
24
|
-
result.push({
|
|
30
|
+
result.push({
|
|
31
|
+
price: currentBoundary.toNumber(),
|
|
32
|
+
size: currentSize.toNumber()
|
|
33
|
+
});
|
|
25
34
|
if (result.length >= depth) return result;
|
|
26
35
|
}
|
|
27
36
|
currentBoundary = boundary;
|
|
@@ -30,9 +39,13 @@ function walk(sorted, bucket, side, depth) {
|
|
|
30
39
|
currentSize = currentSize.plus(size);
|
|
31
40
|
}
|
|
32
41
|
if (currentBoundary !== null && result.length < depth) {
|
|
33
|
-
result.push({
|
|
42
|
+
result.push({
|
|
43
|
+
price: currentBoundary.toNumber(),
|
|
44
|
+
size: currentSize.toNumber()
|
|
45
|
+
});
|
|
34
46
|
}
|
|
35
47
|
return result;
|
|
36
48
|
}
|
|
49
|
+
__name(walk, "walk");
|
|
37
50
|
|
|
38
51
|
export { aggregateBook };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { BBO } 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
|
type Level = readonly [price: string, size: number];
|
|
9
9
|
declare class LocalBook {
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import BigNumber from 'bignumber.js';
|
|
2
2
|
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
5
|
class LocalBook {
|
|
6
|
+
static {
|
|
7
|
+
__name(this, "LocalBook");
|
|
8
|
+
}
|
|
4
9
|
_bids = [];
|
|
5
10
|
_asks = [];
|
|
6
11
|
lastUpdateTs = 0;
|
|
@@ -60,9 +65,9 @@ class LocalBook {
|
|
|
60
65
|
this.isLoaded = false;
|
|
61
66
|
}
|
|
62
67
|
/**
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
68
|
+
* Insert, update, or remove a level in a sorted array.
|
|
69
|
+
* @param dir -1 for descending (bids), 1 for ascending (asks)
|
|
70
|
+
*/
|
|
66
71
|
upsert(levels, price, size, dir) {
|
|
67
72
|
const numPrice = Number(price);
|
|
68
73
|
let lo = 0;
|
|
@@ -77,12 +82,18 @@ class LocalBook {
|
|
|
77
82
|
if (size === 0) {
|
|
78
83
|
levels.splice(lo, 1);
|
|
79
84
|
} else {
|
|
80
|
-
levels[lo] = [
|
|
85
|
+
levels[lo] = [
|
|
86
|
+
price,
|
|
87
|
+
size
|
|
88
|
+
];
|
|
81
89
|
}
|
|
82
90
|
return;
|
|
83
91
|
}
|
|
84
92
|
if (size > 0) {
|
|
85
|
-
levels.splice(lo, 0, [
|
|
93
|
+
levels.splice(lo, 0, [
|
|
94
|
+
price,
|
|
95
|
+
size
|
|
96
|
+
]);
|
|
86
97
|
}
|
|
87
98
|
}
|
|
88
99
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { OrderbookConfig, OrderbookCallback, OrderbookSnapshot, BBO } 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
|
/**
|
|
9
9
|
* Orderbook exposes an aggregated top-of-book view for a single symbol.
|
|
@@ -3,7 +3,12 @@ import { LocalBook } from './book/local-book';
|
|
|
3
3
|
import { DEFAULT_DEPTH } from './types';
|
|
4
4
|
import { createDepthWs } from './ws';
|
|
5
5
|
|
|
6
|
+
var __defProp = Object.defineProperty;
|
|
7
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
6
8
|
class Orderbook {
|
|
9
|
+
static {
|
|
10
|
+
__name(this, "Orderbook");
|
|
11
|
+
}
|
|
7
12
|
depthWs;
|
|
8
13
|
symbol;
|
|
9
14
|
book = new LocalBook();
|
|
@@ -22,23 +27,23 @@ class Orderbook {
|
|
|
22
27
|
this.depthWs.subscribe(this.symbol);
|
|
23
28
|
}
|
|
24
29
|
/**
|
|
25
|
-
|
|
26
|
-
|
|
30
|
+
* Subscribe to orderbook updates. Returns the symbol as the subscription ID.
|
|
31
|
+
*/
|
|
27
32
|
subscribe(cb) {
|
|
28
33
|
this.listener = cb;
|
|
29
34
|
return this.symbol;
|
|
30
35
|
}
|
|
31
36
|
/**
|
|
32
|
-
|
|
33
|
-
|
|
37
|
+
* Unsubscribe from orderbook updates.
|
|
38
|
+
*/
|
|
34
39
|
unsubscribe(id) {
|
|
35
40
|
if (id !== this.symbol) throw new Error(`Subscription "${id}" not found`);
|
|
36
41
|
this.listener = null;
|
|
37
42
|
}
|
|
38
43
|
/**
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
44
|
+
* Set the aggregation bucket size (e.g. 0.1, 1, 10, 100).
|
|
45
|
+
* Set to 0 to disable aggregation.
|
|
46
|
+
*/
|
|
42
47
|
setAggregation(aggregation) {
|
|
43
48
|
if (this.aggregation === aggregation) return;
|
|
44
49
|
this.aggregation = aggregation;
|
|
@@ -51,9 +56,9 @@ class Orderbook {
|
|
|
51
56
|
return this.aggregation;
|
|
52
57
|
}
|
|
53
58
|
/**
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
59
|
+
* Update the snapshotted mid-price used for server-side aggregation params
|
|
60
|
+
* (e.g. Hyperliquid's nSigFigs/mantissa).
|
|
61
|
+
*/
|
|
57
62
|
setSnapshottedPrice(price) {
|
|
58
63
|
this.depthWs.setSnapshottedPrice(price);
|
|
59
64
|
}
|
|
@@ -62,7 +67,12 @@ class Orderbook {
|
|
|
62
67
|
return this.buildSnapshot();
|
|
63
68
|
}
|
|
64
69
|
get bbo() {
|
|
65
|
-
if (!this.book.isLoaded) return {
|
|
70
|
+
if (!this.book.isLoaded) return {
|
|
71
|
+
bestBid: null,
|
|
72
|
+
bestAsk: null,
|
|
73
|
+
spread: null,
|
|
74
|
+
spreadPct: null
|
|
75
|
+
};
|
|
66
76
|
return this.book.bbo();
|
|
67
77
|
}
|
|
68
78
|
destroy() {
|
|
@@ -87,8 +97,14 @@ class Orderbook {
|
|
|
87
97
|
bids = aggregated.bids;
|
|
88
98
|
asks = aggregated.asks;
|
|
89
99
|
} else {
|
|
90
|
-
bids = this.book.topBids(this.depth).map(([price, size]) => ({
|
|
91
|
-
|
|
100
|
+
bids = this.book.topBids(this.depth).map(([price, size]) => ({
|
|
101
|
+
price: Number(price),
|
|
102
|
+
size
|
|
103
|
+
}));
|
|
104
|
+
asks = this.book.topAsks(this.depth).map(([price, size]) => ({
|
|
105
|
+
price: Number(price),
|
|
106
|
+
size
|
|
107
|
+
}));
|
|
92
108
|
}
|
|
93
109
|
return {
|
|
94
110
|
symbol: this.symbol,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Transport } from '../transport/index.js';
|
|
2
2
|
import '@pear-protocol/types';
|
|
3
|
+
import '../shared/types.js';
|
|
3
4
|
import '../transport/base-transport.js';
|
|
4
5
|
import 'partysocket';
|
|
5
|
-
import '../shared/types.js';
|
|
6
6
|
|
|
7
7
|
declare const DEFAULT_DEPTH = 10;
|
|
8
8
|
declare const DEFAULT_MULTIPLIERS: number[];
|
package/dist/orderbook/types.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Connector } from '@pear-protocol/types';
|
|
2
2
|
import { AggregationConfig } 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
8
|
declare function getCexAvailableAggregations(tickSize: number, midPrice: number, multipliers?: number[]): number[];
|
|
9
9
|
declare function getHyperliquidAvailableAggregations(maxDecimals: number, midPrice: number, multipliers?: number[]): number[];
|
package/dist/orderbook/utils.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import BigNumber from 'bignumber.js';
|
|
2
2
|
import { DEFAULT_MULTIPLIERS } from './types';
|
|
3
3
|
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
4
6
|
function getCexAvailableAggregations(tickSize, midPrice, multipliers = DEFAULT_MULTIPLIERS) {
|
|
5
7
|
if (tickSize <= 0 || midPrice <= 0) return [];
|
|
6
8
|
const tick = new BigNumber(tickSize);
|
|
@@ -11,6 +13,7 @@ function getCexAvailableAggregations(tickSize, midPrice, multipliers = DEFAULT_M
|
|
|
11
13
|
return bucket < midPrice && bucketMag <= maxBucketMag;
|
|
12
14
|
});
|
|
13
15
|
}
|
|
16
|
+
__name(getCexAvailableAggregations, "getCexAvailableAggregations");
|
|
14
17
|
function getHyperliquidAvailableAggregations(maxDecimals, midPrice, multipliers = DEFAULT_MULTIPLIERS) {
|
|
15
18
|
if (midPrice <= 0) return [];
|
|
16
19
|
const decimals = Math.max(0, maxDecimals);
|
|
@@ -23,6 +26,7 @@ function getHyperliquidAvailableAggregations(maxDecimals, midPrice, multipliers
|
|
|
23
26
|
return bucket < midPrice && bucketMag >= minBucketMag && bucketMag <= maxBucketMag;
|
|
24
27
|
});
|
|
25
28
|
}
|
|
29
|
+
__name(getHyperliquidAvailableAggregations, "getHyperliquidAvailableAggregations");
|
|
26
30
|
function getAvailableAggregations(connector, config, multipliers = DEFAULT_MULTIPLIERS) {
|
|
27
31
|
if (connector === "hyperliquid") {
|
|
28
32
|
const { maxDecimals, midPrice: midPrice2 } = config;
|
|
@@ -31,5 +35,6 @@ function getAvailableAggregations(connector, config, multipliers = DEFAULT_MULTI
|
|
|
31
35
|
const { tickSize, midPrice } = config;
|
|
32
36
|
return getCexAvailableAggregations(tickSize, midPrice, multipliers);
|
|
33
37
|
}
|
|
38
|
+
__name(getAvailableAggregations, "getAvailableAggregations");
|
|
34
39
|
|
|
35
40
|
export { getAvailableAggregations, getCexAvailableAggregations, getHyperliquidAvailableAggregations };
|
|
@@ -1,14 +1,23 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
1
3
|
function parseStringLevels(levels) {
|
|
2
4
|
if (!levels) return [];
|
|
3
5
|
const out = new Array(levels.length);
|
|
4
6
|
for (let i = 0; i < levels.length; i++) {
|
|
5
7
|
const entry = levels[i];
|
|
6
8
|
if (!entry) continue;
|
|
7
|
-
out[i] = [
|
|
9
|
+
out[i] = [
|
|
10
|
+
entry[0],
|
|
11
|
+
Number(entry[1])
|
|
12
|
+
];
|
|
8
13
|
}
|
|
9
14
|
return out;
|
|
10
15
|
}
|
|
16
|
+
__name(parseStringLevels, "parseStringLevels");
|
|
11
17
|
class BaseDepthWs {
|
|
18
|
+
static {
|
|
19
|
+
__name(this, "BaseDepthWs");
|
|
20
|
+
}
|
|
12
21
|
transport;
|
|
13
22
|
onUpdate;
|
|
14
23
|
snapshottedPrice = 0;
|