@orderly.network/hooks 2.8.0 → 2.8.1
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.mts +3 -10
- package/dist/index.d.ts +3 -10
- package/dist/index.js +2052 -2088
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2052 -2089
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -10
package/dist/index.js
CHANGED
|
@@ -61,9 +61,9 @@ var __export = (target, all) => {
|
|
|
61
61
|
// src/version.ts
|
|
62
62
|
if (typeof window !== "undefined") {
|
|
63
63
|
window.__ORDERLY_VERSION__ = window.__ORDERLY_VERSION__ || {};
|
|
64
|
-
window.__ORDERLY_VERSION__["@orderly.network/hooks"] = "2.8.
|
|
64
|
+
window.__ORDERLY_VERSION__["@orderly.network/hooks"] = "2.8.1";
|
|
65
65
|
}
|
|
66
|
-
var version_default = "2.8.
|
|
66
|
+
var version_default = "2.8.1";
|
|
67
67
|
var fetcher = (url, init2 = {}, queryOptions) => net.get(url, init2, queryOptions?.formatter);
|
|
68
68
|
var noCacheConfig = {
|
|
69
69
|
dedupingInterval: 0,
|
|
@@ -1249,7 +1249,7 @@ function checkTPSLOrderTypeIsMarket(key, values) {
|
|
|
1249
1249
|
}
|
|
1250
1250
|
function tpslCalculateHelper(key, inputs, options = {}) {
|
|
1251
1251
|
const { symbol } = options;
|
|
1252
|
-
if (key !== "quantity" && key !== "tp_trigger_price" && key !== "sl_trigger_price" && key !== "tp_pnl" && key !== "sl_pnl" && key !== "tp_offset" && key !== "sl_offset" && key !== "tp_offset_percentage" && key !== "sl_offset_percentage" && key !== "tp_order_price" && key !== "sl_order_price" && key !== "tp_order_type" && key !== "sl_order_type"
|
|
1252
|
+
if (key !== "quantity" && key !== "tp_trigger_price" && key !== "sl_trigger_price" && key !== "tp_pnl" && key !== "sl_pnl" && key !== "tp_offset" && key !== "sl_offset" && key !== "tp_offset_percentage" && key !== "sl_offset_percentage" && key !== "tp_order_price" && key !== "sl_order_price" && key !== "tp_order_type" && key !== "sl_order_type") {
|
|
1253
1253
|
return {
|
|
1254
1254
|
[key]: inputs.value
|
|
1255
1255
|
};
|
|
@@ -1288,19 +1288,6 @@ function tpslCalculateHelper(key, inputs, options = {}) {
|
|
|
1288
1288
|
}
|
|
1289
1289
|
break;
|
|
1290
1290
|
}
|
|
1291
|
-
case "tp_enable":
|
|
1292
|
-
case "sl_enable": {
|
|
1293
|
-
return {
|
|
1294
|
-
[`${keyPrefix}enable`]: inputs.value,
|
|
1295
|
-
[`${keyPrefix}order_type`]: types.OrderType.MARKET,
|
|
1296
|
-
[`${keyPrefix}trigger_price`]: "",
|
|
1297
|
-
[`${keyPrefix}order_price`]: "",
|
|
1298
|
-
[`${keyPrefix}offset`]: "",
|
|
1299
|
-
[`${keyPrefix}offset_percentage`]: "",
|
|
1300
|
-
[`${keyPrefix}pnl`]: "",
|
|
1301
|
-
[`${keyPrefix}ROI`]: ""
|
|
1302
|
-
};
|
|
1303
|
-
}
|
|
1304
1291
|
case "tp_pnl":
|
|
1305
1292
|
case "sl_pnl": {
|
|
1306
1293
|
pnl = inputs.value;
|
|
@@ -1649,7 +1636,6 @@ var getCalculateHandler = (fieldName) => {
|
|
|
1649
1636
|
case "total": {
|
|
1650
1637
|
return totalInputHandle;
|
|
1651
1638
|
}
|
|
1652
|
-
case "tp_enable":
|
|
1653
1639
|
case "tp_pnl":
|
|
1654
1640
|
case "sl_pnl":
|
|
1655
1641
|
case "tp_trigger_price":
|
|
@@ -1660,7 +1646,6 @@ var getCalculateHandler = (fieldName) => {
|
|
|
1660
1646
|
case "sl_offset_percentage":
|
|
1661
1647
|
case "tp_order_price":
|
|
1662
1648
|
case "tp_order_type":
|
|
1663
|
-
case "sl_enable":
|
|
1664
1649
|
case "sl_order_type":
|
|
1665
1650
|
case "sl_order_price":
|
|
1666
1651
|
return tpslInputHandle;
|
|
@@ -2760,6 +2745,7 @@ var useAppStore = zustand.create()(
|
|
|
2760
2745
|
);
|
|
2761
2746
|
var useAccountInfo2 = () => useAppStore((state) => state.accountInfo);
|
|
2762
2747
|
var usePortfolio = () => useAppStore((state) => state.portfolio);
|
|
2748
|
+
var useFundingRateBySymbol = (symbol) => useAppStore((state) => state.fundingRates?.[symbol]);
|
|
2763
2749
|
|
|
2764
2750
|
// src/orderly/useRwaSymbolsInfo.ts
|
|
2765
2751
|
var isCurrentlyTrading = (nextClose, status, currentTime = Date.now()) => {
|
|
@@ -2781,10 +2767,16 @@ var computeSymbolState = (rwaSymbol, currentTime) => {
|
|
|
2781
2767
|
let closeTimeInterval;
|
|
2782
2768
|
let openTimeInterval;
|
|
2783
2769
|
if (next_close && typeof next_close === "number" && next_close > currentTime) {
|
|
2784
|
-
closeTimeInterval = Math.max(
|
|
2770
|
+
closeTimeInterval = Math.max(
|
|
2771
|
+
0,
|
|
2772
|
+
Math.floor((next_close - currentTime) / 1e3)
|
|
2773
|
+
);
|
|
2785
2774
|
}
|
|
2786
2775
|
if (next_open && typeof next_open === "number" && next_open > currentTime) {
|
|
2787
|
-
openTimeInterval = Math.max(
|
|
2776
|
+
openTimeInterval = Math.max(
|
|
2777
|
+
0,
|
|
2778
|
+
Math.floor((next_open - currentTime) / 1e3)
|
|
2779
|
+
);
|
|
2788
2780
|
}
|
|
2789
2781
|
return {
|
|
2790
2782
|
isRwa: true,
|
|
@@ -2795,46 +2787,48 @@ var computeSymbolState = (rwaSymbol, currentTime) => {
|
|
|
2795
2787
|
openTimeInterval
|
|
2796
2788
|
};
|
|
2797
2789
|
};
|
|
2798
|
-
var useRwaSymbolsRuntimeStore = zustand.create(
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
const
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2790
|
+
var useRwaSymbolsRuntimeStore = zustand.create(
|
|
2791
|
+
(set, get3) => ({
|
|
2792
|
+
computedStates: {},
|
|
2793
|
+
currentTime: Date.now(),
|
|
2794
|
+
timerId: void 0,
|
|
2795
|
+
startTimer: () => {
|
|
2796
|
+
const state = get3();
|
|
2797
|
+
if (state.timerId) {
|
|
2798
|
+
clearInterval(state.timerId);
|
|
2799
|
+
}
|
|
2800
|
+
const timerId = setInterval(() => {
|
|
2801
|
+
const currentTime = Date.now();
|
|
2802
|
+
const rwaSymbolsInfo = useAppStore.getState().rwaSymbolsInfo;
|
|
2803
|
+
if (!rwaSymbolsInfo) {
|
|
2804
|
+
set({ currentTime });
|
|
2805
|
+
return;
|
|
2806
|
+
}
|
|
2807
|
+
const computedStates = {};
|
|
2808
|
+
Object.entries(rwaSymbolsInfo).forEach(([symbol, rwaSymbol]) => {
|
|
2809
|
+
computedStates[symbol] = computeSymbolState(rwaSymbol, currentTime);
|
|
2810
|
+
});
|
|
2811
|
+
set({ computedStates, currentTime });
|
|
2812
|
+
}, 1e3);
|
|
2813
|
+
set({ timerId });
|
|
2814
|
+
},
|
|
2815
|
+
stopTimer: () => {
|
|
2816
|
+
const state = get3();
|
|
2817
|
+
if (state.timerId) {
|
|
2818
|
+
clearInterval(state.timerId);
|
|
2819
|
+
set({ timerId: void 0 });
|
|
2813
2820
|
}
|
|
2821
|
+
},
|
|
2822
|
+
updateComputedStates: (rwaSymbolsInfo) => {
|
|
2823
|
+
const currentTime = get3().currentTime;
|
|
2814
2824
|
const computedStates = {};
|
|
2815
2825
|
Object.entries(rwaSymbolsInfo).forEach(([symbol, rwaSymbol]) => {
|
|
2816
2826
|
computedStates[symbol] = computeSymbolState(rwaSymbol, currentTime);
|
|
2817
2827
|
});
|
|
2818
|
-
set({ computedStates
|
|
2819
|
-
}, 1e3);
|
|
2820
|
-
set({ timerId });
|
|
2821
|
-
},
|
|
2822
|
-
stopTimer: () => {
|
|
2823
|
-
const state = get3();
|
|
2824
|
-
if (state.timerId) {
|
|
2825
|
-
clearInterval(state.timerId);
|
|
2826
|
-
set({ timerId: void 0 });
|
|
2828
|
+
set({ computedStates });
|
|
2827
2829
|
}
|
|
2828
|
-
}
|
|
2829
|
-
|
|
2830
|
-
const currentTime = get3().currentTime;
|
|
2831
|
-
const computedStates = {};
|
|
2832
|
-
Object.entries(rwaSymbolsInfo).forEach(([symbol, rwaSymbol]) => {
|
|
2833
|
-
computedStates[symbol] = computeSymbolState(rwaSymbol, currentTime);
|
|
2834
|
-
});
|
|
2835
|
-
set({ computedStates });
|
|
2836
|
-
}
|
|
2837
|
-
}));
|
|
2830
|
+
})
|
|
2831
|
+
);
|
|
2838
2832
|
var useInitRwaSymbolsRuntime = () => {
|
|
2839
2833
|
const rwaSymbolsInfo = useRwaSymbolsInfoStore();
|
|
2840
2834
|
const { startTimer, stopTimer, updateComputedStates } = useRwaSymbolsRuntimeStore();
|
|
@@ -3310,1914 +3304,1918 @@ var useWSObserver = (calculatorService) => {
|
|
|
3310
3304
|
};
|
|
3311
3305
|
}, []);
|
|
3312
3306
|
};
|
|
3313
|
-
var useApiStatusStore = zustand.create()(
|
|
3314
|
-
immer.immer((set) => ({
|
|
3315
|
-
apis: {
|
|
3316
|
-
positions: {
|
|
3317
|
-
loading: false
|
|
3318
|
-
}
|
|
3319
|
-
},
|
|
3320
|
-
actions: {
|
|
3321
|
-
updateStatus: (key, status) => {
|
|
3322
|
-
set((state) => {
|
|
3323
|
-
state.apis[key] = status;
|
|
3324
|
-
});
|
|
3325
|
-
},
|
|
3326
|
-
updateApiLoading: (key, loading) => {
|
|
3327
|
-
set((state) => {
|
|
3328
|
-
state.apis[key].loading = loading;
|
|
3329
|
-
});
|
|
3330
|
-
},
|
|
3331
|
-
updateApiError: (key, error) => {
|
|
3332
|
-
set((state) => {
|
|
3333
|
-
state.apis[key] = {
|
|
3334
|
-
loading: false,
|
|
3335
|
-
error
|
|
3336
|
-
};
|
|
3337
|
-
});
|
|
3338
|
-
}
|
|
3339
|
-
}
|
|
3340
|
-
}))
|
|
3341
|
-
);
|
|
3342
|
-
var useApiStatusActions = () => useApiStatusStore((state) => state.actions);
|
|
3343
|
-
var useTokensInfoStore = zustand.create(
|
|
3344
|
-
(set) => ({
|
|
3345
|
-
tokensInfo: [],
|
|
3346
|
-
setTokensInfo(data) {
|
|
3347
|
-
set({ tokensInfo: data });
|
|
3348
|
-
}
|
|
3349
|
-
})
|
|
3350
|
-
);
|
|
3351
|
-
var useTokensInfo = () => {
|
|
3352
|
-
const tokensInfo = useTokensInfoStore((state) => state.tokensInfo);
|
|
3353
|
-
return tokensInfo;
|
|
3354
|
-
};
|
|
3355
|
-
var useTokenInfo = (token) => {
|
|
3356
|
-
const tokensInfo = useTokensInfo();
|
|
3357
|
-
return React2.useMemo(() => {
|
|
3358
|
-
return tokensInfo?.find((item) => item.token === token);
|
|
3359
|
-
}, [tokensInfo, token]);
|
|
3360
|
-
};
|
|
3361
3307
|
|
|
3362
|
-
// src/orderly/
|
|
3363
|
-
var
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3308
|
+
// src/orderly/orderbook.service.ts
|
|
3309
|
+
var defaultRawOrderBook = {
|
|
3310
|
+
asks: [],
|
|
3311
|
+
bids: [],
|
|
3312
|
+
ts: 0
|
|
3367
3313
|
};
|
|
3368
|
-
var
|
|
3369
|
-
markPrices: {},
|
|
3370
|
-
// orderBook: {},
|
|
3371
|
-
// ask_bid: [],
|
|
3372
|
-
actions: {
|
|
3373
|
-
updateMarkPrice: (markPrice) => {
|
|
3374
|
-
set({
|
|
3375
|
-
markPrices: markPrice
|
|
3376
|
-
});
|
|
3377
|
-
},
|
|
3378
|
-
getMarkPriceBySymbol: (symbol) => {
|
|
3379
|
-
return get3().markPrices[symbol];
|
|
3380
|
-
}
|
|
3381
|
-
}
|
|
3382
|
-
}));
|
|
3383
|
-
var useMarkPriceBySymbol = (symbol) => useMarkPriceStore((state) => state.actions.getMarkPriceBySymbol(symbol));
|
|
3384
|
-
var useMarkPriceActions = () => useMarkPriceStore((state) => state.actions);
|
|
3385
|
-
|
|
3386
|
-
// src/orderly/calculator/markPrice.ts
|
|
3387
|
-
var MarketCalculatorName = "markPriceCalculator";
|
|
3388
|
-
var MarkPriceCalculator = class extends BaseCalculator {
|
|
3314
|
+
var OrderbookService = class _OrderbookService {
|
|
3389
3315
|
constructor() {
|
|
3390
|
-
|
|
3391
|
-
this.
|
|
3392
|
-
}
|
|
3393
|
-
calc(scope, data, ctx) {
|
|
3394
|
-
return data;
|
|
3316
|
+
this.bufferedOrderBookUpdates = {};
|
|
3317
|
+
this.rawOrderBook = {};
|
|
3395
3318
|
}
|
|
3396
|
-
|
|
3397
|
-
|
|
3319
|
+
static getInstance() {
|
|
3320
|
+
if (!this.instance) {
|
|
3321
|
+
this.instance = new _OrderbookService();
|
|
3322
|
+
}
|
|
3323
|
+
return this.instance;
|
|
3398
3324
|
}
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
// src/orderly/calculator/calculatorContext.ts
|
|
3402
|
-
var CalculatorContext = class _CalculatorContext {
|
|
3403
|
-
static get instance() {
|
|
3404
|
-
return this._instance;
|
|
3325
|
+
sortBufferedOrderBookUpdates(symbol) {
|
|
3326
|
+
this.bufferedOrderBookUpdates[symbol]?.sort((a, b) => a.ts - b.ts);
|
|
3405
3327
|
}
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3328
|
+
applyUpdateToRawOrderBook(symbol, update) {
|
|
3329
|
+
const rawOrderBook = this.rawOrderBook[symbol];
|
|
3330
|
+
if (!rawOrderBook || rawOrderBook.ts > update.prevTs) {
|
|
3331
|
+
return;
|
|
3409
3332
|
}
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3333
|
+
const askMap = /* @__PURE__ */ new Map();
|
|
3334
|
+
const bidMap = /* @__PURE__ */ new Map();
|
|
3335
|
+
rawOrderBook.asks.forEach((ask) => {
|
|
3336
|
+
askMap.set(ask[0], ask[1]);
|
|
3337
|
+
});
|
|
3338
|
+
rawOrderBook.bids.forEach((bid) => {
|
|
3339
|
+
bidMap.set(bid[0], bid[1]);
|
|
3340
|
+
});
|
|
3341
|
+
update.asks.forEach(
|
|
3342
|
+
(ask) => ask[1] === 0 ? askMap.delete(ask[0]) : askMap.set(ask[0], ask[1])
|
|
3343
|
+
);
|
|
3344
|
+
update.bids.forEach(
|
|
3345
|
+
(bid) => bid[1] === 0 ? bidMap.delete(bid[0]) : bidMap.set(bid[0], bid[1])
|
|
3346
|
+
);
|
|
3347
|
+
rawOrderBook.asks = Array.from(askMap.entries()).sort(
|
|
3348
|
+
(a, b) => a[0] - b[0]
|
|
3349
|
+
);
|
|
3350
|
+
rawOrderBook.bids = Array.from(bidMap.entries()).sort(
|
|
3351
|
+
(a, b) => b[0] - a[0]
|
|
3352
|
+
);
|
|
3353
|
+
rawOrderBook.ts = update.ts;
|
|
3417
3354
|
}
|
|
3418
|
-
|
|
3419
|
-
this.
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
return this;
|
|
3355
|
+
applyBufferedUpdatesToRawOrderBooks(symbol) {
|
|
3356
|
+
this.bufferedOrderBookUpdates[symbol]?.forEach((update) => {
|
|
3357
|
+
this.applyUpdateToRawOrderBook(symbol, update);
|
|
3358
|
+
});
|
|
3423
3359
|
}
|
|
3424
|
-
|
|
3425
|
-
this.
|
|
3426
|
-
this.symbolsInfo = useAppStore.getState().symbolsInfo;
|
|
3427
|
-
this.fundingRates = useAppStore.getState().fundingRates;
|
|
3428
|
-
this.tokensInfo = useTokensInfoStore.getState().tokensInfo;
|
|
3360
|
+
deleteBufferedOrderBookUpdates(symbol) {
|
|
3361
|
+
delete this.bufferedOrderBookUpdates[symbol];
|
|
3429
3362
|
}
|
|
3430
|
-
|
|
3431
|
-
|
|
3363
|
+
commitOrderBook(symbol) {
|
|
3364
|
+
const rawOrderBook = this.rawOrderBook[symbol];
|
|
3365
|
+
if (!rawOrderBook) {
|
|
3366
|
+
return;
|
|
3367
|
+
}
|
|
3432
3368
|
}
|
|
3433
|
-
|
|
3434
|
-
|
|
3369
|
+
pushUpdateToBuffer(symbol, update) {
|
|
3370
|
+
if (this.bufferedOrderBookUpdates[symbol] === void 0) {
|
|
3371
|
+
this.bufferedOrderBookUpdates[symbol] = [];
|
|
3372
|
+
}
|
|
3373
|
+
const buffer = this.bufferedOrderBookUpdates[symbol];
|
|
3374
|
+
if (buffer.length > 0) {
|
|
3375
|
+
const lastUpdate = buffer[buffer.length - 1];
|
|
3376
|
+
if (lastUpdate.ts !== update.prevTs) {
|
|
3377
|
+
this.bufferedOrderBookUpdates[symbol] = [];
|
|
3378
|
+
}
|
|
3379
|
+
}
|
|
3380
|
+
this.bufferedOrderBookUpdates[symbol].push(update);
|
|
3435
3381
|
}
|
|
3436
|
-
|
|
3437
|
-
this.
|
|
3438
|
-
|
|
3439
|
-
|
|
3382
|
+
isValidFullOrderBook(symbol, currentTs) {
|
|
3383
|
+
if ((this.bufferedOrderBookUpdates[symbol]?.length ?? 0) !== 0) {
|
|
3384
|
+
const earliestUpdates = this.bufferedOrderBookUpdates[symbol][0];
|
|
3385
|
+
return earliestUpdates.prevTs <= currentTs;
|
|
3386
|
+
}
|
|
3387
|
+
return true;
|
|
3440
3388
|
}
|
|
3441
|
-
|
|
3442
|
-
|
|
3389
|
+
setFullOrderbook(symbol, rawOrderbook) {
|
|
3390
|
+
const { ts } = rawOrderbook;
|
|
3391
|
+
this.rawOrderBook[symbol] = rawOrderbook;
|
|
3392
|
+
this.sortBufferedOrderBookUpdates(symbol);
|
|
3393
|
+
if (this.isValidFullOrderBook(symbol, ts)) {
|
|
3394
|
+
this.applyBufferedUpdatesToRawOrderBooks(symbol);
|
|
3395
|
+
}
|
|
3443
3396
|
}
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3397
|
+
updateOrderbook(symbol, update, callback) {
|
|
3398
|
+
const { asks, bids, prevTs, ts } = update;
|
|
3399
|
+
const rawOrderBook = this.rawOrderBook[symbol];
|
|
3400
|
+
if (!rawOrderBook) {
|
|
3401
|
+
return;
|
|
3402
|
+
}
|
|
3403
|
+
const currentTs = rawOrderBook.ts;
|
|
3404
|
+
if (currentTs === 0) {
|
|
3405
|
+
this.pushUpdateToBuffer(symbol, { asks, bids, prevTs, ts });
|
|
3406
|
+
return;
|
|
3407
|
+
}
|
|
3408
|
+
if (prevTs !== currentTs) {
|
|
3409
|
+
this.pushUpdateToBuffer(symbol, { asks, bids, prevTs, ts });
|
|
3410
|
+
if (callback) {
|
|
3411
|
+
callback();
|
|
3412
|
+
}
|
|
3413
|
+
return;
|
|
3414
|
+
}
|
|
3415
|
+
this.applyUpdateToRawOrderBook(symbol, update);
|
|
3416
|
+
this.deleteBufferedOrderBookUpdates(symbol);
|
|
3450
3417
|
}
|
|
3451
|
-
|
|
3452
|
-
this.
|
|
3418
|
+
getRawOrderbook(symbol) {
|
|
3419
|
+
return this.rawOrderBook[symbol];
|
|
3453
3420
|
}
|
|
3454
|
-
|
|
3455
|
-
|
|
3421
|
+
resetOrderBook(symbol) {
|
|
3422
|
+
this.rawOrderBook[symbol] = defaultRawOrderBook;
|
|
3456
3423
|
}
|
|
3457
3424
|
};
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
var
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3425
|
+
var orderBookService = OrderbookService.getInstance();
|
|
3426
|
+
var orderbook_service_default = orderBookService;
|
|
3427
|
+
var useMarkPrice = (symbol) => {
|
|
3428
|
+
const ws = useWS();
|
|
3429
|
+
const [price, setPrice] = React2.useState(0);
|
|
3430
|
+
React2.useEffect(() => {
|
|
3431
|
+
const unsubscribe = ws.subscribe(`${symbol}@markprice`, {
|
|
3432
|
+
onMessage: (message) => {
|
|
3433
|
+
setPrice(message.price);
|
|
3434
|
+
}
|
|
3435
|
+
});
|
|
3436
|
+
return () => {
|
|
3437
|
+
unsubscribe?.();
|
|
3438
|
+
};
|
|
3439
|
+
}, [symbol]);
|
|
3440
|
+
return { data: price };
|
|
3441
|
+
};
|
|
3442
|
+
var useIndexPrice = (symbol) => {
|
|
3443
|
+
symbol = symbol.replace("PERP", "SPOT");
|
|
3444
|
+
const ws = useWS();
|
|
3445
|
+
return useSWRSubscription__default.default(`${symbol}@indexprice`, (key, { next }) => {
|
|
3446
|
+
const unsubscribe = ws.subscribe(`${symbol}@indexprice`, {
|
|
3447
|
+
onMessage: (message) => {
|
|
3448
|
+
next(null, message.price);
|
|
3449
|
+
}
|
|
3450
|
+
});
|
|
3451
|
+
return () => {
|
|
3452
|
+
unsubscribe?.();
|
|
3453
|
+
};
|
|
3454
|
+
});
|
|
3455
|
+
};
|
|
3456
|
+
var useOpenInterest = (symbol) => {
|
|
3457
|
+
const ws = useWS();
|
|
3458
|
+
return useSWRSubscription__default.default(`${symbol}@openinterest`, (key, { next }) => {
|
|
3459
|
+
const unsubscribe = ws.subscribe(`${symbol}@openinterest`, {
|
|
3460
|
+
onMessage: (message) => {
|
|
3461
|
+
next(null, message.openInterest);
|
|
3462
|
+
}
|
|
3463
|
+
});
|
|
3464
|
+
return () => {
|
|
3465
|
+
unsubscribe?.();
|
|
3466
|
+
};
|
|
3467
|
+
});
|
|
3468
|
+
};
|
|
3469
|
+
var useFutures = () => {
|
|
3470
|
+
const { data, isLoading, error } = useQuery(
|
|
3471
|
+
`/v1/public/futures`,
|
|
3472
|
+
{
|
|
3473
|
+
revalidateOnFocus: false
|
|
3478
3474
|
}
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3475
|
+
);
|
|
3476
|
+
const [sortedData, setSortedData] = React2.useState(data);
|
|
3477
|
+
useWS();
|
|
3478
|
+
React2.useEffect(() => {
|
|
3479
|
+
}, []);
|
|
3480
|
+
React2.useEffect(() => {
|
|
3481
|
+
if (data) {
|
|
3482
|
+
const sortedData2 = data.sort((a, b) => {
|
|
3483
|
+
return 0;
|
|
3484
|
+
});
|
|
3485
|
+
setSortedData(sortedData2);
|
|
3484
3486
|
}
|
|
3485
|
-
|
|
3487
|
+
}, [data]);
|
|
3488
|
+
const sortBy = React2.useCallback((key) => {
|
|
3489
|
+
}, [data]);
|
|
3490
|
+
const filterBy = React2.useCallback((key) => {
|
|
3491
|
+
}, [data]);
|
|
3492
|
+
return {
|
|
3493
|
+
data: sortedData,
|
|
3494
|
+
sortBy,
|
|
3495
|
+
filterBy,
|
|
3496
|
+
isLoading,
|
|
3497
|
+
error
|
|
3498
|
+
};
|
|
3499
|
+
};
|
|
3500
|
+
|
|
3501
|
+
// src/orderly/useTickerStream.ts
|
|
3502
|
+
var useTickerStream = (symbol) => {
|
|
3503
|
+
if (!symbol) {
|
|
3504
|
+
throw new types.SDKError("Symbol is required");
|
|
3486
3505
|
}
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
this.referenceCount.set(ref_count_name, count - 1);
|
|
3492
|
-
return;
|
|
3506
|
+
const { data: info } = useQuery(
|
|
3507
|
+
`/v1/public/futures/${symbol}`,
|
|
3508
|
+
{
|
|
3509
|
+
revalidateOnFocus: false
|
|
3493
3510
|
}
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3511
|
+
);
|
|
3512
|
+
const [ticker, setTicker] = React2.useState();
|
|
3513
|
+
const ws = useWS();
|
|
3514
|
+
React2.useEffect(() => {
|
|
3515
|
+
const unsubscribe = ws.subscribe(
|
|
3516
|
+
// { event: "subscribe", topic: "markprices" },
|
|
3517
|
+
`${symbol}@ticker`,
|
|
3518
|
+
{
|
|
3519
|
+
onMessage: (message) => {
|
|
3520
|
+
if (message.symbol !== symbol)
|
|
3521
|
+
return;
|
|
3522
|
+
setTicker(message);
|
|
3523
|
+
}
|
|
3524
|
+
// onUnsubscribe: () => {
|
|
3525
|
+
// return "markprices";
|
|
3526
|
+
// },
|
|
3527
|
+
// onError: (error: any) => {
|
|
3528
|
+
//
|
|
3529
|
+
// },
|
|
3500
3530
|
}
|
|
3531
|
+
);
|
|
3532
|
+
return () => {
|
|
3533
|
+
setTicker(void 0);
|
|
3534
|
+
unsubscribe?.();
|
|
3535
|
+
};
|
|
3536
|
+
}, [symbol]);
|
|
3537
|
+
const { data: markPrice } = useMarkPrice(symbol);
|
|
3538
|
+
const { data: indexPrice } = useIndexPrice(symbol);
|
|
3539
|
+
const { data: openInterest } = useOpenInterest(symbol);
|
|
3540
|
+
const { data: futures } = useFutures();
|
|
3541
|
+
const value = React2.useMemo(() => {
|
|
3542
|
+
if (!info)
|
|
3543
|
+
return null;
|
|
3544
|
+
if (!ticker || ticker.symbol !== symbol)
|
|
3545
|
+
return info;
|
|
3546
|
+
const futureIndex = futures?.findIndex(
|
|
3547
|
+
(item) => item.symbol === symbol
|
|
3548
|
+
);
|
|
3549
|
+
let _oi = openInterest;
|
|
3550
|
+
if (!_oi && futureIndex !== -1 && futures) {
|
|
3551
|
+
_oi = futures[futureIndex].open_interest;
|
|
3501
3552
|
}
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3553
|
+
const config = {
|
|
3554
|
+
...info,
|
|
3555
|
+
mark_price: markPrice,
|
|
3556
|
+
index_price: indexPrice,
|
|
3557
|
+
open_interest: _oi
|
|
3558
|
+
};
|
|
3559
|
+
if (ticker.open !== void 0) {
|
|
3560
|
+
config["24h_open"] = ticker.open;
|
|
3507
3561
|
}
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
return;
|
|
3562
|
+
if (ticker.close !== void 0) {
|
|
3563
|
+
config["24h_close"] = ticker.close;
|
|
3511
3564
|
}
|
|
3512
|
-
if (
|
|
3513
|
-
|
|
3514
|
-
this.calcQueue.push({ scope, data, options });
|
|
3515
|
-
await this.handleCalcQueue(ctx);
|
|
3516
|
-
this.ctx = ctx;
|
|
3517
|
-
}
|
|
3518
|
-
// private async handlePendingCalc() {
|
|
3519
|
-
// // console.log("[handlePendingCalc]:", this.pendingCalc);
|
|
3520
|
-
// if (this.pendingCalc.length === 0) return;
|
|
3521
|
-
// this.calcQueue = [...this.pendingCalc, ...this.calcQueue];
|
|
3522
|
-
// this.pendingCalc = [];
|
|
3523
|
-
// }
|
|
3524
|
-
async handleCalcQueue(context) {
|
|
3525
|
-
const first = this.calcQueue.shift();
|
|
3526
|
-
if (first) {
|
|
3527
|
-
const { scope, data, options } = first;
|
|
3528
|
-
const ctx = context || CalculatorContext.create(scope, data);
|
|
3529
|
-
const calculators = this.calculators.get(scope);
|
|
3530
|
-
if (Array.isArray(calculators) && calculators.length) {
|
|
3531
|
-
try {
|
|
3532
|
-
await this.scheduler.calc(scope, calculators, data, ctx);
|
|
3533
|
-
} catch (e) {
|
|
3534
|
-
}
|
|
3535
|
-
if (!options?.skipUpdate) {
|
|
3536
|
-
this.scheduler.update(scope, calculators, ctx.outputToValue());
|
|
3537
|
-
}
|
|
3538
|
-
}
|
|
3539
|
-
if (this.calcQueue.length) {
|
|
3540
|
-
this.handleCalcQueue(ctx);
|
|
3541
|
-
}
|
|
3565
|
+
if (ticker.high !== void 0) {
|
|
3566
|
+
config["24h_high"] = ticker.high;
|
|
3542
3567
|
}
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
this.calcQueue = [];
|
|
3546
|
-
this.ctx?.clearCache();
|
|
3547
|
-
}
|
|
3548
|
-
get windowIsVisible() {
|
|
3549
|
-
if (typeof document === "undefined") {
|
|
3550
|
-
return true;
|
|
3568
|
+
if (ticker.low !== void 0) {
|
|
3569
|
+
config["24h_low"] = ticker.low;
|
|
3551
3570
|
}
|
|
3552
|
-
|
|
3553
|
-
|
|
3571
|
+
if (ticker.volume !== void 0) {
|
|
3572
|
+
config["24h_volumn"] = ticker.volume;
|
|
3573
|
+
config["24h_volume"] = ticker.volume;
|
|
3574
|
+
}
|
|
3575
|
+
if (ticker.close !== void 0 && ticker.open !== void 0) {
|
|
3576
|
+
config["change"] = new utils.Decimal(ticker.close).minus(ticker.open).div(ticker.open).toNumber();
|
|
3577
|
+
config["24h_change"] = new utils.Decimal(ticker.close).minus(ticker.open).toNumber();
|
|
3578
|
+
}
|
|
3579
|
+
return config;
|
|
3580
|
+
}, [info, symbol, ticker, futures, openInterest]);
|
|
3581
|
+
return value;
|
|
3554
3582
|
};
|
|
3555
|
-
var CalculatorServiceID = "CalculatorService";
|
|
3556
3583
|
|
|
3557
|
-
// src/orderly/
|
|
3558
|
-
var
|
|
3559
|
-
|
|
3560
|
-
return
|
|
3561
|
-
callback({
|
|
3562
|
-
didTimeout: false,
|
|
3563
|
-
timeRemaining: () => Math.max(0, 50 - (Date.now() - startTime))
|
|
3564
|
-
});
|
|
3565
|
-
}, 1);
|
|
3584
|
+
// src/orderly/useOrderbookStream.ts
|
|
3585
|
+
var paddingFn = (len) => Array(len).fill([Number.NaN, Number.NaN, Number.NaN, Number.NaN]);
|
|
3586
|
+
var isNumber = (val) => {
|
|
3587
|
+
return typeof val === "number" && !Number.isNaN(val);
|
|
3566
3588
|
};
|
|
3567
|
-
var
|
|
3568
|
-
|
|
3589
|
+
var getPriceKey = (rawPrice, depth, isAsks) => {
|
|
3590
|
+
return new utils.Decimal(rawPrice).div(depth).toDecimalPlaces(0, isAsks ? utils.Decimal.ROUND_CEIL : utils.Decimal.ROUND_FLOOR).mul(depth).toNumber();
|
|
3569
3591
|
};
|
|
3570
|
-
var
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
// run(calculators: Calculator[]) {}
|
|
3574
|
-
calc(scope, calculators, data, ctx) {
|
|
3575
|
-
return new Promise((resolve, reject) => {
|
|
3576
|
-
try {
|
|
3577
|
-
this.computation(
|
|
3578
|
-
calculators,
|
|
3579
|
-
(shard) => {
|
|
3580
|
-
const results = [];
|
|
3581
|
-
for (let index = 0; index < shard.length; index++) {
|
|
3582
|
-
const calculator = shard[index];
|
|
3583
|
-
const result = calculator.calc(scope, data, ctx);
|
|
3584
|
-
if (result) {
|
|
3585
|
-
ctx.saveOutput(calculator.name, result);
|
|
3586
|
-
results.push(result);
|
|
3587
|
-
}
|
|
3588
|
-
}
|
|
3589
|
-
return results;
|
|
3590
|
-
},
|
|
3591
|
-
(results) => {
|
|
3592
|
-
resolve(results);
|
|
3593
|
-
}
|
|
3594
|
-
);
|
|
3595
|
-
} catch (error) {
|
|
3596
|
-
reject(error);
|
|
3597
|
-
}
|
|
3598
|
-
});
|
|
3592
|
+
var reduceItems = (depth, data, isAsks) => {
|
|
3593
|
+
if (!Array.isArray(data) || data.length === 0) {
|
|
3594
|
+
return [];
|
|
3599
3595
|
}
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3596
|
+
let newData = [...data];
|
|
3597
|
+
const result = [];
|
|
3598
|
+
if (typeof depth !== "undefined") {
|
|
3599
|
+
const pricesMap = /* @__PURE__ */ new Map();
|
|
3600
|
+
const len = data.length;
|
|
3601
|
+
for (let i = 0; i < len; i++) {
|
|
3602
|
+
const [rawPrice, quantity] = data[i];
|
|
3603
|
+
if (!isNumber(rawPrice) || !isNumber(quantity)) {
|
|
3604
|
+
continue;
|
|
3605
|
+
}
|
|
3606
|
+
const priceKey = getPriceKey(rawPrice, depth, isAsks);
|
|
3607
|
+
const amtByRaw = new utils.Decimal(rawPrice).mul(quantity).toNumber();
|
|
3608
|
+
if (pricesMap.has(priceKey)) {
|
|
3609
|
+
const item = pricesMap.get(priceKey);
|
|
3610
|
+
const sumQty = new utils.Decimal(item[1]).add(quantity).toNumber();
|
|
3611
|
+
const sumAmtByRaw = new utils.Decimal(item[2] ?? 0).add(amtByRaw).toNumber();
|
|
3612
|
+
pricesMap.set(priceKey, [priceKey, sumQty, sumAmtByRaw]);
|
|
3613
|
+
} else {
|
|
3614
|
+
pricesMap.set(priceKey, [priceKey, quantity, amtByRaw]);
|
|
3606
3615
|
}
|
|
3607
3616
|
}
|
|
3608
|
-
|
|
3617
|
+
newData = Array.from(pricesMap.values());
|
|
3609
3618
|
}
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3619
|
+
for (let i = 0; i < newData.length; i++) {
|
|
3620
|
+
const [price, quantity, sumAmtByRaw] = newData[i];
|
|
3621
|
+
if (!isNumber(price) || !isNumber(quantity)) {
|
|
3622
|
+
continue;
|
|
3623
|
+
}
|
|
3624
|
+
const resLen = result.length;
|
|
3625
|
+
const newQuantity = new utils.Decimal(quantity).add(resLen ? result[resLen - 1][2] : 0).toNumber();
|
|
3626
|
+
const pieceAmount = isNumber(sumAmtByRaw) ? sumAmtByRaw : new utils.Decimal(quantity).mul(price).toNumber();
|
|
3627
|
+
const newAmount = new utils.Decimal(pieceAmount).add(resLen ? result[resLen - 1][3] : 0).toNumber();
|
|
3628
|
+
result.push([price, quantity, newQuantity, newAmount]);
|
|
3629
|
+
}
|
|
3630
|
+
return result;
|
|
3631
|
+
};
|
|
3632
|
+
var reduceOrderbook = (depth, level, padding, data) => {
|
|
3633
|
+
let asks = reduceItems(depth, data.asks, true);
|
|
3634
|
+
let bids = reduceItems(depth, data.bids, false);
|
|
3635
|
+
if (asks.length !== 0 && bids.length !== 0 && asks[0][0] <= bids[0][0]) {
|
|
3636
|
+
if (asks.length === 1) {
|
|
3637
|
+
const [price, qty, newQuantity, newAmount] = asks[0];
|
|
3638
|
+
asks.shift();
|
|
3639
|
+
asks.push([
|
|
3640
|
+
price + (depth === void 0 ? 0 : Number(depth)),
|
|
3641
|
+
qty,
|
|
3642
|
+
newQuantity,
|
|
3643
|
+
newAmount
|
|
3644
|
+
]);
|
|
3645
|
+
} else {
|
|
3646
|
+
const [bidPrice] = bids[0];
|
|
3647
|
+
while (asks.length > 0) {
|
|
3648
|
+
const [askPrice, askQty, newQuantity, newAmount] = asks[0];
|
|
3649
|
+
if (askPrice <= bidPrice) {
|
|
3650
|
+
asks.shift();
|
|
3651
|
+
for (let i = 0; i < asks.length; i++) {
|
|
3652
|
+
if (i === 0) {
|
|
3653
|
+
const quantity = new utils.Decimal(asks[i][1]).add(askQty);
|
|
3654
|
+
asks[i][1] = quantity.toNumber();
|
|
3655
|
+
asks[i][2] = quantity.toNumber();
|
|
3656
|
+
asks[i][3] = quantity.toDecimalPlaces(0, utils.Decimal.ROUND_CEIL).mul(asks[i][0]).toNumber();
|
|
3657
|
+
} else {
|
|
3658
|
+
asks[i][3] = new utils.Decimal(asks[i][0]).mul(asks[i][1]).add(asks[i - 1][3]).toNumber();
|
|
3659
|
+
}
|
|
3660
|
+
}
|
|
3623
3661
|
} else {
|
|
3624
|
-
|
|
3662
|
+
break;
|
|
3625
3663
|
}
|
|
3626
3664
|
}
|
|
3627
|
-
if (index < data.length) {
|
|
3628
|
-
safeRequestIdleCallback(processNextShard, {
|
|
3629
|
-
timeout: 1e3
|
|
3630
|
-
});
|
|
3631
|
-
} else {
|
|
3632
|
-
onComplete(results.flat());
|
|
3633
|
-
}
|
|
3634
3665
|
}
|
|
3635
|
-
safeRequestIdleCallback(processNextShard, {
|
|
3636
|
-
timeout: 1e3
|
|
3637
|
-
});
|
|
3638
3666
|
}
|
|
3667
|
+
asks = asks.reverse();
|
|
3668
|
+
if (padding) {
|
|
3669
|
+
asks = asks.length < level ? paddingFn(level - asks.length).concat(asks) : asks;
|
|
3670
|
+
bids = bids.length < level ? bids.concat(paddingFn(level - bids.length)) : bids;
|
|
3671
|
+
}
|
|
3672
|
+
return {
|
|
3673
|
+
asks,
|
|
3674
|
+
bids
|
|
3675
|
+
};
|
|
3639
3676
|
};
|
|
3640
|
-
var
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
maintenance_margin_ratio: 0,
|
|
3645
|
-
open_margin_ratio: 0,
|
|
3646
|
-
current_margin_ratio_with_orders: 0,
|
|
3647
|
-
initial_margin_ratio_with_orders: 0,
|
|
3648
|
-
maintenance_margin_ratio_with_orders: 0,
|
|
3649
|
-
total_collateral_value: 0,
|
|
3650
|
-
free_collateral: 0,
|
|
3651
|
-
total_pnl_24_h: 0,
|
|
3652
|
-
unrealPnL: 0,
|
|
3653
|
-
total_unreal_pnl: 0,
|
|
3654
|
-
unsettledPnL: 0,
|
|
3655
|
-
total_unsettled_pnl: 0,
|
|
3656
|
-
notional: 0,
|
|
3657
|
-
unrealPnlROI: 0
|
|
3677
|
+
var ORDERLY_ORDERBOOK_DEPTH_KEY = "orderly_orderbook_depth_key";
|
|
3678
|
+
var INIT_DATA = {
|
|
3679
|
+
asks: [],
|
|
3680
|
+
bids: []
|
|
3658
3681
|
};
|
|
3659
|
-
var
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
all: POSITION_EMPTY
|
|
3663
|
-
},
|
|
3664
|
-
actions: {
|
|
3665
|
-
setPositions: (key, positions3) => {
|
|
3666
|
-
set((state) => {
|
|
3667
|
-
state.positions[key] = positions3;
|
|
3668
|
-
});
|
|
3669
|
-
},
|
|
3670
|
-
closePosition: (symbol) => {
|
|
3671
|
-
set((state) => {
|
|
3672
|
-
delete state.positions[symbol];
|
|
3673
|
-
});
|
|
3674
|
-
},
|
|
3675
|
-
clearAll: () => {
|
|
3676
|
-
set((state) => {
|
|
3677
|
-
state.positions = {
|
|
3678
|
-
all: POSITION_EMPTY
|
|
3679
|
-
};
|
|
3680
|
-
});
|
|
3681
|
-
}
|
|
3682
|
-
}
|
|
3683
|
-
}))
|
|
3684
|
-
);
|
|
3685
|
-
var usePositions = (symbol = "all") => usePositionStore((state) => (state.positions[symbol] ?? POSITION_EMPTY).rows);
|
|
3686
|
-
var usePositionActions = () => usePositionStore((state) => state.actions);
|
|
3687
|
-
|
|
3688
|
-
// src/orderly/calculator/positions.ts
|
|
3689
|
-
var NAME_PREFIX = "positionCalculator";
|
|
3690
|
-
var AllPositions = "all";
|
|
3691
|
-
var PositionCalculator = class extends BaseCalculator {
|
|
3692
|
-
// private id: string;
|
|
3693
|
-
constructor(symbol = AllPositions) {
|
|
3694
|
-
super();
|
|
3695
|
-
this.name = `${NAME_PREFIX}_${symbol}`;
|
|
3696
|
-
this.symbol = symbol;
|
|
3682
|
+
var useOrderbookStream = (symbol, initial = INIT_DATA, options) => {
|
|
3683
|
+
if (!symbol) {
|
|
3684
|
+
throw new types.SDKError("Symbol is required");
|
|
3697
3685
|
}
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3686
|
+
const level = options?.level ?? 10;
|
|
3687
|
+
const padding = options?.padding ?? true;
|
|
3688
|
+
const symbolRef = React2.useRef(symbol);
|
|
3689
|
+
symbolRef.current = symbol;
|
|
3690
|
+
const {
|
|
3691
|
+
defaultOrderbookTickSizes: DEFAULT_TICK_SIZES2 = {},
|
|
3692
|
+
defaultOrderbookSymbolDepths: DEFAULT_SYMBOL_DEPTHS2 = {}
|
|
3693
|
+
} = React2.useContext(OrderlyContext);
|
|
3694
|
+
const [data, setData] = React2.useState(initial);
|
|
3695
|
+
const [isLoading, setIsLoading] = React2.useState(true);
|
|
3696
|
+
const config = useSymbolsInfo()[symbol];
|
|
3697
|
+
const [depthObject, setDepthObject] = useLocalStorage(
|
|
3698
|
+
ORDERLY_ORDERBOOK_DEPTH_KEY,
|
|
3699
|
+
{}
|
|
3700
|
+
);
|
|
3701
|
+
const prevMiddlePrice = React2.useRef(0);
|
|
3702
|
+
const tick = config("quote_tick");
|
|
3703
|
+
const depths = React2.useMemo(() => {
|
|
3704
|
+
if (DEFAULT_SYMBOL_DEPTHS2[symbol]) {
|
|
3705
|
+
return DEFAULT_SYMBOL_DEPTHS2[symbol];
|
|
3701
3706
|
}
|
|
3702
|
-
if (
|
|
3703
|
-
return
|
|
3707
|
+
if (typeof tick === "undefined") {
|
|
3708
|
+
return [];
|
|
3704
3709
|
}
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
+
try {
|
|
3711
|
+
const base = new utils.Decimal(tick);
|
|
3712
|
+
return [
|
|
3713
|
+
base.toNumber(),
|
|
3714
|
+
base.mul(10).toNumber(),
|
|
3715
|
+
base.mul(100).toNumber(),
|
|
3716
|
+
base.mul(1e3).toNumber()
|
|
3717
|
+
];
|
|
3718
|
+
} catch {
|
|
3710
3719
|
}
|
|
3711
|
-
return
|
|
3712
|
-
}
|
|
3713
|
-
|
|
3714
|
-
if (
|
|
3720
|
+
return [tick];
|
|
3721
|
+
}, [symbol, tick]);
|
|
3722
|
+
React2.useEffect(() => {
|
|
3723
|
+
if (depthObject[symbol]) {
|
|
3715
3724
|
return;
|
|
3716
|
-
usePositionStore.getState().actions.setPositions(this.symbol, data);
|
|
3717
|
-
if (Array.isArray(data.rows) && useApiStatusStore.getState().apis.positions.loading) {
|
|
3718
|
-
useApiStatusStore.getState().actions.updateApiLoading("positions", false);
|
|
3719
3725
|
}
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
return positions3;
|
|
3726
|
-
positions3 = {
|
|
3727
|
-
...positions3,
|
|
3728
|
-
rows: positions3.rows.map((item) => {
|
|
3729
|
-
return {
|
|
3730
|
-
...item,
|
|
3731
|
-
mark_price: markPrice[item.symbol] || item.mark_price
|
|
3732
|
-
};
|
|
3733
|
-
})
|
|
3734
|
-
};
|
|
3735
|
-
return this.format(positions3, ctx);
|
|
3736
|
-
}
|
|
3737
|
-
calcByIndexPrice(indexPrice, ctx) {
|
|
3738
|
-
let positions3 = this.getPosition(indexPrice, ctx);
|
|
3739
|
-
if (!positions3) {
|
|
3740
|
-
return positions3;
|
|
3741
|
-
}
|
|
3742
|
-
if (!Array.isArray(positions3.rows) || !positions3.rows.length)
|
|
3743
|
-
return positions3;
|
|
3744
|
-
positions3 = {
|
|
3745
|
-
...positions3,
|
|
3746
|
-
rows: positions3.rows.map((item) => ({
|
|
3747
|
-
...item,
|
|
3748
|
-
index_price: indexPrice[item.symbol] || item.index_price || item.mark_price
|
|
3749
|
-
}))
|
|
3750
|
-
};
|
|
3751
|
-
return this.format(positions3, ctx);
|
|
3752
|
-
}
|
|
3753
|
-
calcByPosition(positions3, ctx) {
|
|
3754
|
-
if (positions3.rows.length === 0)
|
|
3755
|
-
return positions3;
|
|
3756
|
-
return this.format(positions3, ctx);
|
|
3757
|
-
}
|
|
3758
|
-
format(data, ctx) {
|
|
3759
|
-
const { accountInfo, symbolsInfo, fundingRates, portfolio } = ctx;
|
|
3760
|
-
if (!accountInfo || !fundingRates || !symbolsInfo) {
|
|
3761
|
-
return data;
|
|
3762
|
-
}
|
|
3763
|
-
let unrealPnL_total = utils.zero, unrealPnL_total_index = utils.zero, notional_total = utils.zero, unsettlementPnL_total = utils.zero;
|
|
3764
|
-
let rows = data.rows.map((item) => {
|
|
3765
|
-
const info = symbolsInfo[item.symbol];
|
|
3766
|
-
const sum_unitary_funding = fundingRates?.[item.symbol]?.["sum_unitary_funding"] ?? 0;
|
|
3767
|
-
const notional = perp.positions.notional(item.position_qty, item.mark_price);
|
|
3768
|
-
const unrealPnl = perp.positions.unrealizedPnL({
|
|
3769
|
-
qty: item.position_qty,
|
|
3770
|
-
openPrice: item?.average_open_price,
|
|
3771
|
-
// markPrice: unRealizedPrice,
|
|
3772
|
-
markPrice: item.mark_price
|
|
3773
|
-
});
|
|
3774
|
-
let unrealPnl_index = 0, unrealPnlROI_index = 0;
|
|
3775
|
-
const maxLeverage = item.leverage || 1;
|
|
3776
|
-
const imr = perp.account.IMR({
|
|
3777
|
-
maxLeverage,
|
|
3778
|
-
baseIMR: info?.["base_imr"],
|
|
3779
|
-
IMR_Factor: accountInfo.imr_factor[item.symbol],
|
|
3780
|
-
positionNotional: notional,
|
|
3781
|
-
ordersNotional: 0,
|
|
3782
|
-
IMR_factor_power: 4 / 5
|
|
3783
|
-
});
|
|
3784
|
-
const unrealPnlROI = perp.positions.unrealizedPnLROI({
|
|
3785
|
-
positionQty: item.position_qty,
|
|
3786
|
-
openPrice: item.average_open_price,
|
|
3787
|
-
IMR: imr,
|
|
3788
|
-
unrealizedPnL: unrealPnl
|
|
3789
|
-
});
|
|
3790
|
-
if (item.index_price) {
|
|
3791
|
-
unrealPnl_index = perp.positions.unrealizedPnL({
|
|
3792
|
-
qty: item.position_qty,
|
|
3793
|
-
openPrice: item?.average_open_price,
|
|
3794
|
-
// markPrice: unRealizedPrice,
|
|
3795
|
-
markPrice: item.index_price
|
|
3796
|
-
});
|
|
3797
|
-
unrealPnlROI_index = perp.positions.unrealizedPnLROI({
|
|
3798
|
-
positionQty: item.position_qty,
|
|
3799
|
-
openPrice: item.average_open_price,
|
|
3800
|
-
IMR: imr,
|
|
3801
|
-
unrealizedPnL: unrealPnl_index
|
|
3802
|
-
});
|
|
3803
|
-
}
|
|
3804
|
-
const unsettlementPnL2 = perp.positions.unsettlementPnL({
|
|
3805
|
-
positionQty: item.position_qty,
|
|
3806
|
-
markPrice: item.mark_price,
|
|
3807
|
-
costPosition: item.cost_position,
|
|
3808
|
-
sumUnitaryFunding: ramda.propOr(
|
|
3809
|
-
0,
|
|
3810
|
-
"sum_unitary_funding",
|
|
3811
|
-
fundingRates[item.symbol]
|
|
3812
|
-
),
|
|
3813
|
-
lastSumUnitaryFunding: item.last_sum_unitary_funding
|
|
3814
|
-
});
|
|
3815
|
-
const MMR = perp.positions.MMR({
|
|
3816
|
-
baseMMR: info?.["base_mmr"],
|
|
3817
|
-
baseIMR: info?.["base_imr"],
|
|
3818
|
-
IMRFactor: accountInfo.imr_factor[item.symbol],
|
|
3819
|
-
positionNotional: notional,
|
|
3820
|
-
IMR_factor_power: 4 / 5
|
|
3821
|
-
});
|
|
3822
|
-
unrealPnL_total = unrealPnL_total.add(unrealPnl);
|
|
3823
|
-
unrealPnL_total_index = unrealPnL_total_index.add(unrealPnl_index);
|
|
3824
|
-
notional_total = notional_total.add(notional);
|
|
3825
|
-
unsettlementPnL_total = unsettlementPnL_total.add(unsettlementPnL2);
|
|
3826
|
-
const fundingFee = new utils.Decimal(sum_unitary_funding).sub(item.last_sum_unitary_funding).mul(item.position_qty).negated().toNumber();
|
|
3827
|
-
return {
|
|
3828
|
-
...item,
|
|
3829
|
-
fundingFee,
|
|
3830
|
-
mm: perp.positions.maintenanceMargin({
|
|
3831
|
-
positionQty: item.position_qty,
|
|
3832
|
-
markPrice: item.mark_price,
|
|
3833
|
-
MMR
|
|
3834
|
-
}),
|
|
3835
|
-
mmr: MMR,
|
|
3836
|
-
notional,
|
|
3837
|
-
unsettlement_pnl: unsettlementPnL2,
|
|
3838
|
-
unrealized_pnl: unrealPnl,
|
|
3839
|
-
unrealized_pnl_index: unrealPnl_index,
|
|
3840
|
-
unrealized_pnl_ROI: unrealPnlROI,
|
|
3841
|
-
unrealized_pnl_ROI_index: unrealPnlROI_index
|
|
3842
|
-
};
|
|
3843
|
-
});
|
|
3844
|
-
const totalUnrealPnl = unrealPnL_total.toNumber();
|
|
3845
|
-
const totalUnrealPnl_index = unrealPnL_total_index.toNumber();
|
|
3846
|
-
const unsettlementPnL = unsettlementPnL_total.toNumber();
|
|
3847
|
-
let totalUnrealizedROI = 0, totalUnrealizedROI_index = 0;
|
|
3848
|
-
if (portfolio) {
|
|
3849
|
-
const { totalValue, totalCollateral } = portfolio;
|
|
3850
|
-
rows = rows.map((item) => {
|
|
3851
|
-
const est_liq_price = perp.positions.liqPrice({
|
|
3852
|
-
markPrice: item.mark_price,
|
|
3853
|
-
totalCollateral: totalCollateral.toNumber(),
|
|
3854
|
-
positionQty: item.position_qty,
|
|
3855
|
-
positions: rows,
|
|
3856
|
-
MMR: item.mmr
|
|
3857
|
-
});
|
|
3858
|
-
return {
|
|
3859
|
-
...item,
|
|
3860
|
-
est_liq_price
|
|
3861
|
-
};
|
|
3862
|
-
});
|
|
3863
|
-
if (totalValue !== null && !totalValue.eq(utils.zero)) {
|
|
3864
|
-
totalUnrealizedROI = perp.account.totalUnrealizedROI({
|
|
3865
|
-
totalUnrealizedPnL: totalUnrealPnl,
|
|
3866
|
-
totalValue: totalValue.toNumber()
|
|
3867
|
-
});
|
|
3868
|
-
totalUnrealizedROI_index = perp.account.totalUnrealizedROI({
|
|
3869
|
-
totalUnrealizedPnL: totalUnrealPnl_index,
|
|
3870
|
-
totalValue: totalValue.toNumber()
|
|
3871
|
-
});
|
|
3872
|
-
}
|
|
3873
|
-
}
|
|
3874
|
-
return {
|
|
3875
|
-
...data,
|
|
3876
|
-
unrealPnL: totalUnrealPnl,
|
|
3877
|
-
total_unreal_pnl: totalUnrealPnl,
|
|
3878
|
-
total_unreal_pnl_index: totalUnrealPnl_index,
|
|
3879
|
-
notional: notional_total.toNumber(),
|
|
3880
|
-
unsettledPnL: unsettlementPnL,
|
|
3881
|
-
total_unsettled_pnl: unsettlementPnL,
|
|
3882
|
-
unrealPnlROI: totalUnrealizedROI,
|
|
3883
|
-
unrealPnlROI_index: totalUnrealizedROI_index,
|
|
3884
|
-
rows
|
|
3885
|
-
};
|
|
3886
|
-
}
|
|
3887
|
-
preprocess(data) {
|
|
3888
|
-
let rows = data.rows;
|
|
3889
|
-
if (this.symbol !== AllPositions && Array.isArray(rows)) {
|
|
3890
|
-
rows = rows.filter((item) => item.symbol === this.symbol);
|
|
3891
|
-
}
|
|
3892
|
-
return {
|
|
3893
|
-
...data,
|
|
3894
|
-
rows
|
|
3895
|
-
};
|
|
3896
|
-
}
|
|
3897
|
-
getPosition(_, ctx) {
|
|
3898
|
-
const positions3 = ctx.get((output) => output[this.name]) || usePositionStore.getState().positions[this.symbol];
|
|
3899
|
-
if (this.symbol === AllPositions) {
|
|
3900
|
-
return positions3;
|
|
3901
|
-
}
|
|
3902
|
-
if (positions3 && Array.isArray(positions3.rows)) {
|
|
3903
|
-
return positions3;
|
|
3904
|
-
}
|
|
3905
|
-
return this.preprocess(this.getAllPositions(ctx));
|
|
3906
|
-
}
|
|
3907
|
-
destroy() {
|
|
3908
|
-
usePositionStore.getState().actions.closePosition(this.symbol);
|
|
3909
|
-
CalculatorContext.instance?.deleteByName(this.name);
|
|
3910
|
-
}
|
|
3911
|
-
getAllPositions(ctx) {
|
|
3912
|
-
return ctx.get((output) => output[AllPositions]) || usePositionStore.getState().positions[AllPositions];
|
|
3913
|
-
}
|
|
3914
|
-
};
|
|
3915
|
-
PositionCalculator.logPosition = (symbol = "all") => {
|
|
3916
|
-
return usePositionStore.getState().positions[symbol];
|
|
3917
|
-
};
|
|
3918
|
-
var parseHolding = (holding, indexPrices, tokensInfo) => {
|
|
3919
|
-
const nonUSDC = [];
|
|
3920
|
-
let USDC_holding = 0;
|
|
3921
|
-
holding.forEach((item) => {
|
|
3922
|
-
if (item.token === "USDC") {
|
|
3923
|
-
USDC_holding = item.holding;
|
|
3924
|
-
} else {
|
|
3925
|
-
const tokenInfo = tokensInfo.find(({ token }) => token === item.token);
|
|
3926
|
-
const {
|
|
3927
|
-
base_weight = 0,
|
|
3928
|
-
discount_factor = 0,
|
|
3929
|
-
user_max_qty = 0
|
|
3930
|
-
} = tokenInfo || {};
|
|
3931
|
-
const holdingQty = item?.holding ?? 0;
|
|
3932
|
-
const indexPrice = indexPrices[`PERP_${item.token}_USDC`] ?? 0;
|
|
3933
|
-
const collateralRatio4 = perp.account.collateralRatio({
|
|
3934
|
-
baseWeight: base_weight,
|
|
3935
|
-
discountFactor: discount_factor,
|
|
3936
|
-
collateralQty: holdingQty,
|
|
3937
|
-
collateralCap: user_max_qty,
|
|
3938
|
-
indexPrice
|
|
3939
|
-
});
|
|
3940
|
-
nonUSDC.push({
|
|
3941
|
-
holding: holdingQty,
|
|
3942
|
-
indexPrice,
|
|
3943
|
-
collateralCap: user_max_qty,
|
|
3944
|
-
collateralRatio: collateralRatio4
|
|
3945
|
-
});
|
|
3946
|
-
}
|
|
3947
|
-
});
|
|
3948
|
-
return [USDC_holding, nonUSDC];
|
|
3949
|
-
};
|
|
3950
|
-
var useIndexPriceStore = zustand.create((set) => ({
|
|
3951
|
-
indexPrices: {},
|
|
3952
|
-
actions: {
|
|
3953
|
-
updateIndexPrice: (indexPrice) => {
|
|
3954
|
-
set({
|
|
3955
|
-
indexPrices: indexPrice
|
|
3956
|
-
});
|
|
3957
|
-
}
|
|
3958
|
-
}
|
|
3959
|
-
}));
|
|
3960
|
-
|
|
3961
|
-
// src/orderly/calculator/indexPrice.ts
|
|
3962
|
-
var IndexPriceCalculatorName = "indexPriceCalculator";
|
|
3963
|
-
var IndexPriceCalculator = class extends BaseCalculator {
|
|
3964
|
-
constructor() {
|
|
3965
|
-
super(...arguments);
|
|
3966
|
-
this.name = IndexPriceCalculatorName;
|
|
3967
|
-
}
|
|
3968
|
-
calc(scope, data, ctx) {
|
|
3969
|
-
return data;
|
|
3970
|
-
}
|
|
3971
|
-
update(data) {
|
|
3972
|
-
if (!data)
|
|
3973
|
-
return;
|
|
3974
|
-
useIndexPriceStore.getState().actions.updateIndexPrice(data);
|
|
3975
|
-
}
|
|
3976
|
-
static getValue() {
|
|
3977
|
-
return useIndexPriceStore.getState().indexPrices;
|
|
3978
|
-
}
|
|
3979
|
-
};
|
|
3980
|
-
|
|
3981
|
-
// src/orderly/calculator/portfolio.ts
|
|
3982
|
-
var PortfolioCalculatorName = "portfolio";
|
|
3983
|
-
var PortfolioCalculator = class extends BaseCalculator {
|
|
3984
|
-
constructor() {
|
|
3985
|
-
super(...arguments);
|
|
3986
|
-
this.name = PortfolioCalculatorName;
|
|
3987
|
-
}
|
|
3988
|
-
calc(scope, data, ctx) {
|
|
3989
|
-
let markPrices;
|
|
3990
|
-
let indexPrices;
|
|
3991
|
-
const portfolio = this.getPortfolio(ctx);
|
|
3992
|
-
if (scope === "markPrice" /* MARK_PRICE */) {
|
|
3993
|
-
markPrices = data;
|
|
3994
|
-
} else {
|
|
3995
|
-
markPrices = ctx.get(
|
|
3996
|
-
(cache) => cache[MarketCalculatorName]
|
|
3997
|
-
);
|
|
3998
|
-
}
|
|
3999
|
-
if (scope === "indexPrice" /* INDEX_PRICE */) {
|
|
4000
|
-
indexPrices = data;
|
|
3726
|
+
if (DEFAULT_TICK_SIZES2[symbol]) {
|
|
3727
|
+
setDepthObject((prev) => ({
|
|
3728
|
+
...prev,
|
|
3729
|
+
[symbol]: Number(DEFAULT_TICK_SIZES2[symbol])
|
|
3730
|
+
}));
|
|
4001
3731
|
} else {
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
3732
|
+
setDepthObject((prev) => ({
|
|
3733
|
+
...prev,
|
|
3734
|
+
[symbol]: tick
|
|
3735
|
+
}));
|
|
4005
3736
|
}
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
)
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
3737
|
+
}, [depthObject, tick, symbol, DEFAULT_TICK_SIZES2]);
|
|
3738
|
+
const onDepthChange = React2.useCallback(
|
|
3739
|
+
(val) => {
|
|
3740
|
+
setDepthObject((prev) => ({ ...prev, [symbol]: val }));
|
|
3741
|
+
},
|
|
3742
|
+
[symbol]
|
|
3743
|
+
);
|
|
3744
|
+
const ws = useWS();
|
|
3745
|
+
const ticker = useTickerStream(symbol);
|
|
3746
|
+
const eventEmitter = useEventEmitter();
|
|
3747
|
+
React2.useEffect(() => {
|
|
3748
|
+
let needRequestFullOrderbook = true;
|
|
3749
|
+
setIsLoading(true);
|
|
3750
|
+
let fullOrderBookUpdateSub;
|
|
3751
|
+
const orderBookUpdateSub = ws.subscribe(
|
|
3752
|
+
{
|
|
3753
|
+
event: "subscribe",
|
|
3754
|
+
topic: `${symbol}@orderbookupdate`
|
|
3755
|
+
},
|
|
3756
|
+
{
|
|
3757
|
+
formatter: (message) => message,
|
|
3758
|
+
onMessage: (message) => {
|
|
3759
|
+
const { data: wsData, ts } = message;
|
|
3760
|
+
const { symbol: symbol2, asks, bids, prevTs } = wsData;
|
|
3761
|
+
if (symbolRef.current !== symbol2) {
|
|
3762
|
+
orderBookUpdateSub?.();
|
|
3763
|
+
return;
|
|
4021
3764
|
}
|
|
4022
|
-
|
|
4023
|
-
|
|
3765
|
+
orderbook_service_default.updateOrderbook(
|
|
3766
|
+
symbol2,
|
|
3767
|
+
{ asks, bids, ts, prevTs },
|
|
3768
|
+
() => {
|
|
3769
|
+
needRequestFullOrderbook = true;
|
|
3770
|
+
}
|
|
3771
|
+
);
|
|
3772
|
+
const data2 = orderbook_service_default.getRawOrderbook(symbol2);
|
|
3773
|
+
setData({ bids: data2.bids, asks: data2.asks });
|
|
3774
|
+
}
|
|
4024
3775
|
}
|
|
4025
|
-
}
|
|
4026
|
-
const accountInfo = ctx.accountInfo;
|
|
4027
|
-
const symbolsInfo = ctx.symbolsInfo;
|
|
4028
|
-
const tokensInfo = ctx.tokensInfo;
|
|
4029
|
-
return this.format({
|
|
4030
|
-
holding,
|
|
4031
|
-
positions: positions3,
|
|
4032
|
-
markPrices,
|
|
4033
|
-
accountInfo,
|
|
4034
|
-
symbolsInfo,
|
|
4035
|
-
indexPrices,
|
|
4036
|
-
tokensInfo: tokensInfo ?? types.EMPTY_LIST
|
|
4037
|
-
});
|
|
4038
|
-
}
|
|
4039
|
-
getPortfolio(ctx) {
|
|
4040
|
-
return ctx.get((output) => output[this.name]) || useAppStore.getState().portfolio;
|
|
4041
|
-
}
|
|
4042
|
-
format(inputs) {
|
|
4043
|
-
const {
|
|
4044
|
-
holding,
|
|
4045
|
-
positions: positions3,
|
|
4046
|
-
markPrices,
|
|
4047
|
-
indexPrices,
|
|
4048
|
-
accountInfo,
|
|
4049
|
-
symbolsInfo,
|
|
4050
|
-
tokensInfo
|
|
4051
|
-
} = inputs;
|
|
4052
|
-
if (!holding || !positions3 || !Array.isArray(positions3.rows) || !markPrices || !indexPrices || !accountInfo) {
|
|
4053
|
-
return null;
|
|
4054
|
-
}
|
|
4055
|
-
const unsettledPnL = ramda.pathOr(0, ["total_unsettled_pnl"])(positions3);
|
|
4056
|
-
const unrealizedPnL = ramda.pathOr(0, ["total_unreal_pnl"])(positions3);
|
|
4057
|
-
const [USDC_holding, nonUSDC] = parseHolding(
|
|
4058
|
-
holding,
|
|
4059
|
-
indexPrices,
|
|
4060
|
-
tokensInfo
|
|
4061
3776
|
);
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
totalValue,
|
|
4095
|
-
totalUnrealizedROI,
|
|
4096
|
-
freeCollateral,
|
|
4097
|
-
availableBalance,
|
|
4098
|
-
unsettledPnL,
|
|
4099
|
-
holding
|
|
3777
|
+
if (needRequestFullOrderbook) {
|
|
3778
|
+
setIsLoading(true);
|
|
3779
|
+
fullOrderBookUpdateSub = ws.onceSubscribe(
|
|
3780
|
+
{
|
|
3781
|
+
event: "request",
|
|
3782
|
+
id: `${symbol}@orderbook`,
|
|
3783
|
+
params: {
|
|
3784
|
+
type: "orderbook",
|
|
3785
|
+
symbol
|
|
3786
|
+
}
|
|
3787
|
+
},
|
|
3788
|
+
{
|
|
3789
|
+
formatter: (message) => message,
|
|
3790
|
+
onMessage: (message) => {
|
|
3791
|
+
const { symbol: symbol2, asks, bids, ts } = message.data;
|
|
3792
|
+
if (symbolRef.current !== symbol2) {
|
|
3793
|
+
return;
|
|
3794
|
+
}
|
|
3795
|
+
orderbook_service_default.setFullOrderbook(symbol2, { asks, bids, ts });
|
|
3796
|
+
const data2 = orderbook_service_default.getRawOrderbook(symbol2);
|
|
3797
|
+
setData({ bids: data2.bids, asks: data2.asks });
|
|
3798
|
+
setIsLoading(false);
|
|
3799
|
+
}
|
|
3800
|
+
}
|
|
3801
|
+
);
|
|
3802
|
+
needRequestFullOrderbook = false;
|
|
3803
|
+
}
|
|
3804
|
+
return () => {
|
|
3805
|
+
orderBookUpdateSub?.();
|
|
3806
|
+
fullOrderBookUpdateSub?.();
|
|
3807
|
+
orderbook_service_default.resetOrderBook(symbol);
|
|
3808
|
+
setData(INIT_DATA);
|
|
4100
3809
|
};
|
|
4101
|
-
}
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
3810
|
+
}, [symbol]);
|
|
3811
|
+
const { data: markPrice } = useMarkPrice(symbol);
|
|
3812
|
+
const onItemClick = React2.useCallback((item) => {
|
|
3813
|
+
eventEmitter.emit("orderbook:item:click", item);
|
|
3814
|
+
}, []);
|
|
3815
|
+
const reducedData = reduceOrderbook(depthObject[symbol], level, padding, {
|
|
3816
|
+
asks: data.asks,
|
|
3817
|
+
bids: data.bids
|
|
3818
|
+
});
|
|
3819
|
+
React2.useEffect(() => {
|
|
3820
|
+
eventEmitter.emit("orderbook:update", reducedData);
|
|
3821
|
+
}, [reducedData]);
|
|
3822
|
+
const middlePrice = React2.useMemo(() => {
|
|
3823
|
+
let asksFrist = 0;
|
|
3824
|
+
let bidsFirst = 0;
|
|
3825
|
+
if (data.asks.length > 0) {
|
|
3826
|
+
asksFrist = reducedData.asks?.[reducedData.asks.length - 1]?.[0];
|
|
4113
3827
|
}
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
// src/useCalculatorService.ts
|
|
4118
|
-
var useCalculatorService = () => {
|
|
4119
|
-
const { get: get3 } = useSimpleDI();
|
|
4120
|
-
const calculatorService = useConstant__default.default(() => {
|
|
4121
|
-
let calculatorService2 = get3(CalculatorServiceID);
|
|
4122
|
-
if (!calculatorService2) {
|
|
4123
|
-
const positionCalculator = new PositionCalculator();
|
|
4124
|
-
const portfolioCalculator = new PortfolioCalculator();
|
|
4125
|
-
const markPriceCalculator = new MarkPriceCalculator();
|
|
4126
|
-
const indexPriceCalculator = new IndexPriceCalculator();
|
|
4127
|
-
calculatorService2 = new CalculatorService(new ShardingScheduler(), [
|
|
4128
|
-
[
|
|
4129
|
-
"markPrice" /* MARK_PRICE */,
|
|
4130
|
-
[
|
|
4131
|
-
markPriceCalculator,
|
|
4132
|
-
positionCalculator,
|
|
4133
|
-
portfolioCalculator,
|
|
4134
|
-
positionCalculator
|
|
4135
|
-
]
|
|
4136
|
-
],
|
|
4137
|
-
["position" /* POSITION */, [positionCalculator, portfolioCalculator]],
|
|
4138
|
-
["portfolio" /* PORTFOLIO */, [portfolioCalculator]],
|
|
4139
|
-
// indexPrice
|
|
4140
|
-
[
|
|
4141
|
-
"indexPrice" /* INDEX_PRICE */,
|
|
4142
|
-
[indexPriceCalculator, positionCalculator]
|
|
4143
|
-
]
|
|
4144
|
-
]);
|
|
4145
|
-
core.SimpleDI.registerByName(CalculatorServiceID, calculatorService2);
|
|
3828
|
+
if (data.bids.length > 0) {
|
|
3829
|
+
bidsFirst = data.bids[0][0];
|
|
4146
3830
|
}
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
return calculatorService;
|
|
4150
|
-
};
|
|
4151
|
-
|
|
4152
|
-
// src/orderly/orderbook.service.ts
|
|
4153
|
-
var defaultRawOrderBook = {
|
|
4154
|
-
asks: [],
|
|
4155
|
-
bids: [],
|
|
4156
|
-
ts: 0
|
|
4157
|
-
};
|
|
4158
|
-
var OrderbookService = class _OrderbookService {
|
|
4159
|
-
constructor() {
|
|
4160
|
-
this.bufferedOrderBookUpdates = {};
|
|
4161
|
-
this.rawOrderBook = {};
|
|
4162
|
-
}
|
|
4163
|
-
static getInstance() {
|
|
4164
|
-
if (!this.instance) {
|
|
4165
|
-
this.instance = new _OrderbookService();
|
|
3831
|
+
if (!isNumber(asksFrist) || !isNumber(bidsFirst) || !ticker) {
|
|
3832
|
+
return 0;
|
|
4166
3833
|
}
|
|
4167
|
-
return
|
|
4168
|
-
}
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
}
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
3834
|
+
return [asksFrist, bidsFirst, ticker["24h_close"]].sort()[1];
|
|
3835
|
+
}, [ticker?.["24h_close"], data]);
|
|
3836
|
+
React2.useEffect(() => {
|
|
3837
|
+
prevMiddlePrice.current = middlePrice;
|
|
3838
|
+
}, [middlePrice]);
|
|
3839
|
+
return [
|
|
3840
|
+
{
|
|
3841
|
+
asks: reducedData.asks.slice(-level),
|
|
3842
|
+
bids: reducedData.bids.slice(0, level),
|
|
3843
|
+
markPrice,
|
|
3844
|
+
middlePrice: [prevMiddlePrice.current, middlePrice]
|
|
3845
|
+
},
|
|
3846
|
+
{
|
|
3847
|
+
onDepthChange,
|
|
3848
|
+
depth: depthObject[symbol],
|
|
3849
|
+
allDepths: depths,
|
|
3850
|
+
isLoading,
|
|
3851
|
+
onItemClick
|
|
4176
3852
|
}
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
}
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
3853
|
+
];
|
|
3854
|
+
};
|
|
3855
|
+
var useSymbolInfo = (symbol) => {
|
|
3856
|
+
const infos = useSymbolsInfo();
|
|
3857
|
+
return React2.useMemo(() => {
|
|
3858
|
+
return !symbol || infos.isNil ? null : infos[symbol];
|
|
3859
|
+
}, [infos, symbol]);
|
|
3860
|
+
};
|
|
3861
|
+
var useFundingRates = () => {
|
|
3862
|
+
const data = useAppStore((state) => state.fundingRates);
|
|
3863
|
+
return createGetter({ ...data });
|
|
3864
|
+
};
|
|
3865
|
+
var useFundingRatesStore = () => {
|
|
3866
|
+
const data = useAppStore((state) => state.fundingRates);
|
|
3867
|
+
return data;
|
|
3868
|
+
};
|
|
3869
|
+
|
|
3870
|
+
// src/orderly/useMarket.ts
|
|
3871
|
+
var DefaultTab = { name: "Popular", id: 1 };
|
|
3872
|
+
var marketsKey = "markets";
|
|
3873
|
+
var useMarket = (type) => {
|
|
3874
|
+
const { configStore } = React2.useContext(OrderlyContext);
|
|
3875
|
+
const symbolsInfo = useSymbolsInfo();
|
|
3876
|
+
const fundingRates = useFundingRates();
|
|
3877
|
+
const { data: futures } = useMarketsStream();
|
|
3878
|
+
const updateStore = (key, data) => {
|
|
3879
|
+
configStore.set(marketsKey, {
|
|
3880
|
+
...configStore.getOr(marketsKey, {}),
|
|
3881
|
+
[key]: data
|
|
4202
3882
|
});
|
|
4203
|
-
}
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
}
|
|
4207
|
-
|
|
4208
|
-
const
|
|
4209
|
-
if (
|
|
4210
|
-
|
|
3883
|
+
};
|
|
3884
|
+
const getStore = (key, defaultValue) => {
|
|
3885
|
+
return configStore.get(marketsKey)[key] || defaultValue;
|
|
3886
|
+
};
|
|
3887
|
+
if (!configStore.get(marketsKey)) {
|
|
3888
|
+
const jsonStr = localStorage.getItem(marketsKey);
|
|
3889
|
+
if (jsonStr) {
|
|
3890
|
+
configStore.set(marketsKey, JSON.parse(jsonStr));
|
|
3891
|
+
} else {
|
|
3892
|
+
configStore.set(marketsKey, {
|
|
3893
|
+
recent: [],
|
|
3894
|
+
favorites: [
|
|
3895
|
+
{ name: "PERP_ETH_USDC", tabs: [{ ...DefaultTab }] },
|
|
3896
|
+
{ name: "PERP_BTC_USDC", tabs: [{ ...DefaultTab }] }
|
|
3897
|
+
],
|
|
3898
|
+
favoriteTabs: [{ ...DefaultTab }],
|
|
3899
|
+
lastSelectedFavoriteTab: { ...DefaultTab }
|
|
3900
|
+
});
|
|
4211
3901
|
}
|
|
4212
3902
|
}
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
const
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
3903
|
+
const getFavoriteTabs = React2.useMemo(() => {
|
|
3904
|
+
return getStore("favoriteTabs", [{ ...DefaultTab }]);
|
|
3905
|
+
}, []);
|
|
3906
|
+
const getFavorites = React2.useMemo(() => {
|
|
3907
|
+
const curData = getStore("favorites", []);
|
|
3908
|
+
const tabs = getFavoriteTabs;
|
|
3909
|
+
const result = [];
|
|
3910
|
+
const len = curData.length;
|
|
3911
|
+
for (let index = 0; index < len; index++) {
|
|
3912
|
+
const favData = curData[index];
|
|
3913
|
+
const favTabs = favData.tabs.filter(
|
|
3914
|
+
(tab) => tabs.findIndex((item) => tab.id === item.id) !== -1
|
|
3915
|
+
);
|
|
3916
|
+
if (favTabs.length) {
|
|
3917
|
+
result.push({ ...favData, tabs: favTabs });
|
|
4222
3918
|
}
|
|
4223
3919
|
}
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
}
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
const { asks, bids, prevTs, ts } = update;
|
|
4243
|
-
const rawOrderBook = this.rawOrderBook[symbol];
|
|
4244
|
-
if (!rawOrderBook) {
|
|
4245
|
-
return;
|
|
4246
|
-
}
|
|
4247
|
-
const currentTs = rawOrderBook.ts;
|
|
4248
|
-
if (currentTs === 0) {
|
|
4249
|
-
this.pushUpdateToBuffer(symbol, { asks, bids, prevTs, ts });
|
|
3920
|
+
updateStore("favorites", result);
|
|
3921
|
+
return result;
|
|
3922
|
+
}, [configStore]);
|
|
3923
|
+
const [favoriteTabs, setFavoriteTabs] = React2.useState(getFavoriteTabs);
|
|
3924
|
+
const [favorites, setFavorites] = React2.useState(getFavorites);
|
|
3925
|
+
const [recent, setRecent] = React2.useState(
|
|
3926
|
+
getStore("recent", []).filter((e) => e)
|
|
3927
|
+
);
|
|
3928
|
+
const [tabSort, setTabSort] = React2.useState(
|
|
3929
|
+
getStore("tabSort", {})
|
|
3930
|
+
);
|
|
3931
|
+
const updateFavoriteTabs = (tab, operator) => {
|
|
3932
|
+
const saveTabs = (tabs2) => {
|
|
3933
|
+
setFavoriteTabs(tabs2);
|
|
3934
|
+
updateStore("favoriteTabs", tabs2);
|
|
3935
|
+
};
|
|
3936
|
+
if (Array.isArray(tab)) {
|
|
3937
|
+
saveTabs(tab);
|
|
4250
3938
|
return;
|
|
4251
3939
|
}
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
3940
|
+
const tabs = [...favoriteTabs];
|
|
3941
|
+
const index = tabs.findIndex((item) => item.id === tab.id);
|
|
3942
|
+
if (operator?.add) {
|
|
3943
|
+
tabs.push(tab);
|
|
3944
|
+
} else if (operator?.update) {
|
|
3945
|
+
if (index !== -1) {
|
|
3946
|
+
tabs[index] = tab;
|
|
3947
|
+
}
|
|
3948
|
+
} else if (operator?.delete) {
|
|
3949
|
+
if (index !== -1) {
|
|
3950
|
+
tabs.splice(index, 1);
|
|
4256
3951
|
}
|
|
4257
|
-
return;
|
|
4258
3952
|
}
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
}
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
3953
|
+
saveTabs(tabs);
|
|
3954
|
+
};
|
|
3955
|
+
const updateFavorites = (favorites2) => {
|
|
3956
|
+
updateStore("favorites", favorites2);
|
|
3957
|
+
setFavorites(favorites2);
|
|
3958
|
+
};
|
|
3959
|
+
const addToHistory = (symbol) => {
|
|
3960
|
+
const curData = [...recent];
|
|
3961
|
+
const index = curData.findIndex((item) => item.name == symbol.symbol);
|
|
3962
|
+
if (index !== -1) {
|
|
3963
|
+
curData.splice(index, 1);
|
|
3964
|
+
}
|
|
3965
|
+
curData.unshift({ name: symbol.symbol });
|
|
3966
|
+
updateStore("recent", curData);
|
|
3967
|
+
setRecent(curData);
|
|
3968
|
+
};
|
|
3969
|
+
const updateSymbolFavoriteState = (symbol, tab, remove = false) => {
|
|
3970
|
+
const curData = [...favorites];
|
|
3971
|
+
const index = curData.findIndex((item) => item.name == symbol.symbol);
|
|
3972
|
+
if (index === -1) {
|
|
3973
|
+
if (Array.isArray(tab)) {
|
|
3974
|
+
if (tab.length > 0) {
|
|
3975
|
+
curData.unshift({ name: symbol.symbol, tabs: tab });
|
|
3976
|
+
}
|
|
3977
|
+
} else {
|
|
3978
|
+
if (!remove) {
|
|
3979
|
+
curData.unshift({ name: symbol.symbol, tabs: [tab] });
|
|
3980
|
+
}
|
|
4278
3981
|
}
|
|
4279
|
-
}
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
};
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
3982
|
+
} else {
|
|
3983
|
+
const favorite = curData[index];
|
|
3984
|
+
if (Array.isArray(tab)) {
|
|
3985
|
+
if (tab.length === 0) {
|
|
3986
|
+
curData.splice(index, 1);
|
|
3987
|
+
} else {
|
|
3988
|
+
curData[index] = { ...favorite, tabs: tab };
|
|
3989
|
+
}
|
|
3990
|
+
} else {
|
|
3991
|
+
if (remove) {
|
|
3992
|
+
const tabs = favorite.tabs.filter((item) => item.id != tab.id);
|
|
3993
|
+
if (tabs.length === 0) {
|
|
3994
|
+
curData.splice(index, 1);
|
|
3995
|
+
} else {
|
|
3996
|
+
curData[index] = { ...favorite, tabs };
|
|
3997
|
+
}
|
|
3998
|
+
} else {
|
|
3999
|
+
const tabs = favorite.tabs;
|
|
4000
|
+
tabs.push(tab);
|
|
4001
|
+
curData[index] = { ...favorite, tabs };
|
|
4002
|
+
}
|
|
4293
4003
|
}
|
|
4004
|
+
}
|
|
4005
|
+
updateStore("favorites", curData);
|
|
4006
|
+
setFavorites(() => curData);
|
|
4007
|
+
};
|
|
4008
|
+
const marketsList = React2.useMemo(() => {
|
|
4009
|
+
const list = futures?.map((item) => {
|
|
4010
|
+
const { open_interest = 0, index_price = 0 } = item;
|
|
4011
|
+
const info = symbolsInfo[item.symbol];
|
|
4012
|
+
const rate = fundingRates[item.symbol];
|
|
4013
|
+
const est_funding_rate = rate("est_funding_rate");
|
|
4014
|
+
const funding_period = info("funding_period");
|
|
4015
|
+
const change = item.change === void 0 ? get24hChange2(item["24h_close"], item["24h_open"]) : item.change;
|
|
4016
|
+
return {
|
|
4017
|
+
...item,
|
|
4018
|
+
change,
|
|
4019
|
+
"8h_funding": get8hFunding2(est_funding_rate, funding_period),
|
|
4020
|
+
quote_dp: info("quote_dp"),
|
|
4021
|
+
created_time: info("created_time"),
|
|
4022
|
+
openInterest: new utils.Decimal(open_interest || 0).mul(index_price || 0).toNumber()
|
|
4023
|
+
};
|
|
4294
4024
|
});
|
|
4295
|
-
return
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4025
|
+
return list || [];
|
|
4026
|
+
}, [symbolsInfo, futures, fundingRates]);
|
|
4027
|
+
const getData = (type2) => {
|
|
4028
|
+
const localData = type2 === 0 /* FAVORITES */ ? [...favorites] : [...recent];
|
|
4029
|
+
const keys = localData.map((item) => item.name);
|
|
4030
|
+
const filter = type2 == 2 /* ALL */ ? marketsList : marketsList?.filter((item) => keys.includes(item.symbol));
|
|
4031
|
+
const favoritesData = [...favorites];
|
|
4032
|
+
const favoriteKeys = favoritesData.map((item) => item.name);
|
|
4033
|
+
if (filter) {
|
|
4034
|
+
for (let index = 0; index < filter.length; index++) {
|
|
4035
|
+
const element = filter[index];
|
|
4036
|
+
const isFavorite = type2 == 0 /* FAVORITES */ ? true : favoriteKeys.includes(element.symbol);
|
|
4037
|
+
const fIndex = favoritesData.findIndex(
|
|
4038
|
+
(item) => item.name === element.symbol
|
|
4039
|
+
);
|
|
4040
|
+
const tabs = fIndex === -1 ? [] : favoritesData[fIndex].tabs;
|
|
4041
|
+
let imr = void 0;
|
|
4042
|
+
if (symbolsInfo) {
|
|
4043
|
+
imr = symbolsInfo?.[element.symbol]("base_imr");
|
|
4044
|
+
}
|
|
4045
|
+
filter[index] = {
|
|
4046
|
+
...filter[index],
|
|
4047
|
+
isFavorite,
|
|
4048
|
+
tabs,
|
|
4049
|
+
leverage: imr ? 1 / imr : void 0
|
|
4050
|
+
};
|
|
4306
4051
|
}
|
|
4307
|
-
}
|
|
4308
|
-
return
|
|
4309
|
-
|
|
4052
|
+
}
|
|
4053
|
+
return filter;
|
|
4054
|
+
};
|
|
4055
|
+
const pinToTop = (symbol) => {
|
|
4056
|
+
const index = favorites.findIndex((item) => item.name === symbol.symbol);
|
|
4057
|
+
if (index !== -1) {
|
|
4058
|
+
const element = favorites[index];
|
|
4059
|
+
const list = [...favorites];
|
|
4060
|
+
list.splice(index, 1);
|
|
4061
|
+
list.unshift(element);
|
|
4062
|
+
updateStore("favorites", list);
|
|
4063
|
+
setFavorites(list);
|
|
4064
|
+
}
|
|
4065
|
+
};
|
|
4066
|
+
const getLastSelFavTab = () => {
|
|
4067
|
+
return getStore("lastSelectedFavoriteTab", { ...DefaultTab });
|
|
4068
|
+
};
|
|
4069
|
+
const updateSelectedFavoriteTab = (tab) => {
|
|
4070
|
+
updateStore("lastSelectedFavoriteTab", tab);
|
|
4071
|
+
};
|
|
4072
|
+
const updateTabsSortState = (tabId, sortKey, sortOrder) => {
|
|
4073
|
+
const map = getStore("tabSort", {});
|
|
4074
|
+
map[tabId] = {
|
|
4075
|
+
sortKey,
|
|
4076
|
+
sortOrder
|
|
4310
4077
|
};
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
const
|
|
4315
|
-
|
|
4078
|
+
updateStore("tabSort", map);
|
|
4079
|
+
setTabSort(map);
|
|
4080
|
+
};
|
|
4081
|
+
const markets = getData(type);
|
|
4082
|
+
return [
|
|
4083
|
+
markets || types.EMPTY_LIST,
|
|
4316
4084
|
{
|
|
4317
|
-
|
|
4085
|
+
favoriteTabs,
|
|
4086
|
+
favorites,
|
|
4087
|
+
recent,
|
|
4088
|
+
tabSort,
|
|
4089
|
+
addToHistory,
|
|
4090
|
+
updateFavorites,
|
|
4091
|
+
updateFavoriteTabs,
|
|
4092
|
+
updateSymbolFavoriteState,
|
|
4093
|
+
pinToTop,
|
|
4094
|
+
getLastSelFavTab,
|
|
4095
|
+
updateSelectedFavoriteTab,
|
|
4096
|
+
updateTabsSortState
|
|
4318
4097
|
}
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4098
|
+
];
|
|
4099
|
+
};
|
|
4100
|
+
function get8hFunding2(est_funding_rate, funding_period) {
|
|
4101
|
+
let funding8h = 0;
|
|
4102
|
+
if (est_funding_rate === void 0 || est_funding_rate === null) {
|
|
4103
|
+
return null;
|
|
4104
|
+
}
|
|
4105
|
+
if (funding_period) {
|
|
4106
|
+
funding8h = new utils.Decimal(est_funding_rate || 0).mul(funding_period).div(8).toNumber();
|
|
4107
|
+
}
|
|
4108
|
+
return funding8h;
|
|
4109
|
+
}
|
|
4110
|
+
function get24hChange2(close, open) {
|
|
4111
|
+
if (close !== void 0 && open !== void 0) {
|
|
4112
|
+
if (open === 0) {
|
|
4113
|
+
return 0;
|
|
4114
|
+
}
|
|
4115
|
+
return new utils.Decimal(close).minus(open).div(open).toNumber();
|
|
4116
|
+
}
|
|
4117
|
+
}
|
|
4118
|
+
var useMarkPriceStore = zustand.create((set, get3) => ({
|
|
4119
|
+
markPrices: {},
|
|
4120
|
+
// orderBook: {},
|
|
4121
|
+
// ask_bid: [],
|
|
4122
|
+
actions: {
|
|
4123
|
+
updateMarkPrice: (markPrice) => {
|
|
4124
|
+
set({
|
|
4125
|
+
markPrices: markPrice
|
|
4126
|
+
});
|
|
4127
|
+
},
|
|
4128
|
+
getMarkPriceBySymbol: (symbol) => {
|
|
4129
|
+
return get3().markPrices[symbol];
|
|
4130
|
+
}
|
|
4131
|
+
}
|
|
4132
|
+
}));
|
|
4133
|
+
var useMarkPriceBySymbol = (symbol) => useMarkPriceStore((state) => state.actions.getMarkPriceBySymbol(symbol));
|
|
4134
|
+
var useMarkPriceActions = () => useMarkPriceStore((state) => state.actions);
|
|
4135
|
+
|
|
4136
|
+
// src/orderly/useMarkPricesStream.ts
|
|
4137
|
+
var useMarkPricesStream = () => {
|
|
4138
|
+
const data = useMarkPriceStore((state) => state.markPrices);
|
|
4139
|
+
return { data };
|
|
4140
|
+
};
|
|
4141
|
+
var useIndexPriceStore = zustand.create((set) => ({
|
|
4142
|
+
indexPrices: {},
|
|
4143
|
+
actions: {
|
|
4144
|
+
updateIndexPrice: (indexPrice) => {
|
|
4145
|
+
set({
|
|
4146
|
+
indexPrices: indexPrice
|
|
4328
4147
|
});
|
|
4329
|
-
setSortedData(sortedData2);
|
|
4330
4148
|
}
|
|
4331
|
-
}
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4149
|
+
}
|
|
4150
|
+
}));
|
|
4151
|
+
|
|
4152
|
+
// src/orderly/useIndexPricesStream.ts
|
|
4153
|
+
var useIndexPricesStream = () => {
|
|
4154
|
+
const indexPrices = useIndexPriceStore((state) => state.indexPrices);
|
|
4155
|
+
const getIndexPrice = (token) => {
|
|
4156
|
+
if (token === "USDC") {
|
|
4157
|
+
return 1;
|
|
4158
|
+
}
|
|
4159
|
+
return indexPrices[`PERP_${token}_USDC`] ?? 0;
|
|
4160
|
+
};
|
|
4336
4161
|
return {
|
|
4337
|
-
data:
|
|
4338
|
-
|
|
4339
|
-
filterBy,
|
|
4340
|
-
isLoading,
|
|
4341
|
-
error
|
|
4162
|
+
data: indexPrices,
|
|
4163
|
+
getIndexPrice: useMemoizedFn(getIndexPrice)
|
|
4342
4164
|
};
|
|
4343
4165
|
};
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4166
|
+
var generateLeverageLevers = (max2) => {
|
|
4167
|
+
const min2 = 1;
|
|
4168
|
+
const parts = 5;
|
|
4169
|
+
const step = (max2 - min2) / (parts - 1);
|
|
4170
|
+
const result = [];
|
|
4171
|
+
for (let i = 0; i < parts; i++) {
|
|
4172
|
+
result.push(Math.floor(min2 + step * i));
|
|
4349
4173
|
}
|
|
4350
|
-
|
|
4351
|
-
|
|
4174
|
+
return result;
|
|
4175
|
+
};
|
|
4176
|
+
var useLeverage = () => {
|
|
4177
|
+
const { data, mutate: mutate6 } = usePrivateQuery(
|
|
4178
|
+
"/v1/client/info",
|
|
4352
4179
|
{
|
|
4353
4180
|
revalidateOnFocus: false
|
|
4354
4181
|
}
|
|
4355
4182
|
);
|
|
4356
|
-
const [
|
|
4357
|
-
const
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
// return "markprices";
|
|
4370
|
-
// },
|
|
4371
|
-
// onError: (error: any) => {
|
|
4372
|
-
//
|
|
4373
|
-
// },
|
|
4183
|
+
const [update, { isMutating }] = useMutation("/v1/client/leverage");
|
|
4184
|
+
const { data: leverageConfig, isLoading } = useQuery("/v1/public/leverage", {
|
|
4185
|
+
revalidateOnFocus: false,
|
|
4186
|
+
errorRetryCount: 3
|
|
4187
|
+
// formatter: (data) => data,
|
|
4188
|
+
});
|
|
4189
|
+
const updateLeverage = React2.useCallback(
|
|
4190
|
+
async (data2) => {
|
|
4191
|
+
const res = await update(data2);
|
|
4192
|
+
if (res.success) {
|
|
4193
|
+
return mutate6();
|
|
4194
|
+
} else {
|
|
4195
|
+
throw new Error(res.message);
|
|
4374
4196
|
}
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
const { data: markPrice } = useMarkPrice(symbol);
|
|
4382
|
-
const { data: indexPrice } = useIndexPrice(symbol);
|
|
4383
|
-
const { data: openInterest } = useOpenInterest(symbol);
|
|
4384
|
-
const { data: futures } = useFutures();
|
|
4385
|
-
const value = React2.useMemo(() => {
|
|
4386
|
-
if (!info)
|
|
4387
|
-
return null;
|
|
4388
|
-
if (!ticker || ticker.symbol !== symbol)
|
|
4389
|
-
return info;
|
|
4390
|
-
const futureIndex = futures?.findIndex(
|
|
4391
|
-
(item) => item.symbol === symbol
|
|
4392
|
-
);
|
|
4393
|
-
let _oi = openInterest;
|
|
4394
|
-
if (!_oi && futureIndex !== -1 && futures) {
|
|
4395
|
-
_oi = futures[futureIndex].open_interest;
|
|
4396
|
-
}
|
|
4397
|
-
const config = {
|
|
4398
|
-
...info,
|
|
4399
|
-
mark_price: markPrice,
|
|
4400
|
-
index_price: indexPrice,
|
|
4401
|
-
open_interest: _oi
|
|
4402
|
-
};
|
|
4403
|
-
if (ticker.open !== void 0) {
|
|
4404
|
-
config["24h_open"] = ticker.open;
|
|
4405
|
-
}
|
|
4406
|
-
if (ticker.close !== void 0) {
|
|
4407
|
-
config["24h_close"] = ticker.close;
|
|
4408
|
-
}
|
|
4409
|
-
if (ticker.high !== void 0) {
|
|
4410
|
-
config["24h_high"] = ticker.high;
|
|
4411
|
-
}
|
|
4412
|
-
if (ticker.low !== void 0) {
|
|
4413
|
-
config["24h_low"] = ticker.low;
|
|
4414
|
-
}
|
|
4415
|
-
if (ticker.volume !== void 0) {
|
|
4416
|
-
config["24h_volumn"] = ticker.volume;
|
|
4417
|
-
config["24h_volume"] = ticker.volume;
|
|
4197
|
+
},
|
|
4198
|
+
[update, mutate6]
|
|
4199
|
+
);
|
|
4200
|
+
const memoizedCurLeverage = React2.useMemo(() => {
|
|
4201
|
+
if (data?.max_leverage !== void 0) {
|
|
4202
|
+
return Number(data.max_leverage);
|
|
4418
4203
|
}
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4204
|
+
return 1;
|
|
4205
|
+
}, [data?.max_leverage]);
|
|
4206
|
+
const memoizedMaxLeverage = React2.useMemo(() => {
|
|
4207
|
+
if (leverageConfig?.max_futures_leverage !== void 0) {
|
|
4208
|
+
return Number(leverageConfig.max_futures_leverage);
|
|
4422
4209
|
}
|
|
4423
|
-
return
|
|
4424
|
-
}, [
|
|
4425
|
-
|
|
4210
|
+
return 1;
|
|
4211
|
+
}, [leverageConfig?.max_futures_leverage]);
|
|
4212
|
+
const memoizedLeverageLevers = React2.useMemo(() => {
|
|
4213
|
+
return generateLeverageLevers(memoizedMaxLeverage);
|
|
4214
|
+
}, [memoizedMaxLeverage]);
|
|
4215
|
+
return {
|
|
4216
|
+
update: updateLeverage,
|
|
4217
|
+
isLoading: isLoading || isMutating,
|
|
4218
|
+
leverageLevers: memoizedLeverageLevers,
|
|
4219
|
+
curLeverage: memoizedCurLeverage,
|
|
4220
|
+
maxLeverage: memoizedMaxLeverage
|
|
4221
|
+
};
|
|
4426
4222
|
};
|
|
4427
4223
|
|
|
4428
|
-
// src/orderly/
|
|
4429
|
-
var
|
|
4430
|
-
|
|
4431
|
-
return typeof val === "number" && !Number.isNaN(val);
|
|
4432
|
-
};
|
|
4433
|
-
var getPriceKey = (rawPrice, depth, isAsks) => {
|
|
4434
|
-
return new utils.Decimal(rawPrice).div(depth).toDecimalPlaces(0, isAsks ? utils.Decimal.ROUND_CEIL : utils.Decimal.ROUND_FLOOR).mul(depth).toNumber();
|
|
4224
|
+
// src/orderly/useOdosQuote.ts
|
|
4225
|
+
var useOdosQuote = () => {
|
|
4226
|
+
return useMutation(`https://api.odos.xyz/sor/quote/v2`);
|
|
4435
4227
|
};
|
|
4436
|
-
var
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
const result = [];
|
|
4442
|
-
if (typeof depth !== "undefined") {
|
|
4443
|
-
const pricesMap = /* @__PURE__ */ new Map();
|
|
4444
|
-
const len = data.length;
|
|
4445
|
-
for (let i = 0; i < len; i++) {
|
|
4446
|
-
const [rawPrice, quantity] = data[i];
|
|
4447
|
-
if (!isNumber(rawPrice) || !isNumber(quantity)) {
|
|
4448
|
-
continue;
|
|
4449
|
-
}
|
|
4450
|
-
const priceKey = getPriceKey(rawPrice, depth, isAsks);
|
|
4451
|
-
const amtByRaw = new utils.Decimal(rawPrice).mul(quantity).toNumber();
|
|
4452
|
-
if (pricesMap.has(priceKey)) {
|
|
4453
|
-
const item = pricesMap.get(priceKey);
|
|
4454
|
-
const sumQty = new utils.Decimal(item[1]).add(quantity).toNumber();
|
|
4455
|
-
const sumAmtByRaw = new utils.Decimal(item[2] ?? 0).add(amtByRaw).toNumber();
|
|
4456
|
-
pricesMap.set(priceKey, [priceKey, sumQty, sumAmtByRaw]);
|
|
4457
|
-
} else {
|
|
4458
|
-
pricesMap.set(priceKey, [priceKey, quantity, amtByRaw]);
|
|
4459
|
-
}
|
|
4460
|
-
}
|
|
4461
|
-
newData = Array.from(pricesMap.values());
|
|
4462
|
-
}
|
|
4463
|
-
for (let i = 0; i < newData.length; i++) {
|
|
4464
|
-
const [price, quantity, sumAmtByRaw] = newData[i];
|
|
4465
|
-
if (!isNumber(price) || !isNumber(quantity)) {
|
|
4466
|
-
continue;
|
|
4228
|
+
var useTokensInfoStore = zustand.create(
|
|
4229
|
+
(set) => ({
|
|
4230
|
+
tokensInfo: [],
|
|
4231
|
+
setTokensInfo(data) {
|
|
4232
|
+
set({ tokensInfo: data });
|
|
4467
4233
|
}
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
}
|
|
4474
|
-
return result;
|
|
4234
|
+
})
|
|
4235
|
+
);
|
|
4236
|
+
var useTokensInfo = () => {
|
|
4237
|
+
const tokensInfo = useTokensInfoStore((state) => state.tokensInfo);
|
|
4238
|
+
return tokensInfo;
|
|
4475
4239
|
};
|
|
4476
|
-
var
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
for (let i = 0; i < asks.length; i++) {
|
|
4496
|
-
if (i === 0) {
|
|
4497
|
-
const quantity = new utils.Decimal(asks[i][1]).add(askQty);
|
|
4498
|
-
asks[i][1] = quantity.toNumber();
|
|
4499
|
-
asks[i][2] = quantity.toNumber();
|
|
4500
|
-
asks[i][3] = quantity.toDecimalPlaces(0, utils.Decimal.ROUND_CEIL).mul(asks[i][0]).toNumber();
|
|
4501
|
-
} else {
|
|
4502
|
-
asks[i][3] = new utils.Decimal(asks[i][0]).mul(asks[i][1]).add(asks[i - 1][3]).toNumber();
|
|
4503
|
-
}
|
|
4504
|
-
}
|
|
4505
|
-
} else {
|
|
4506
|
-
break;
|
|
4507
|
-
}
|
|
4508
|
-
}
|
|
4240
|
+
var useTokenInfo = (token) => {
|
|
4241
|
+
const tokensInfo = useTokensInfo();
|
|
4242
|
+
return React2.useMemo(() => {
|
|
4243
|
+
return tokensInfo?.find((item) => item.token === token);
|
|
4244
|
+
}, [tokensInfo, token]);
|
|
4245
|
+
};
|
|
4246
|
+
|
|
4247
|
+
// src/orderly/useComputedLTV.ts
|
|
4248
|
+
var { LTV, collateralRatio } = perp.account;
|
|
4249
|
+
var useComputedLTV = (options = {}) => {
|
|
4250
|
+
const { input, token } = options;
|
|
4251
|
+
const isUSDC = token?.toUpperCase() === "USDC";
|
|
4252
|
+
const tokensInfo = useTokensInfo();
|
|
4253
|
+
const { usdc, data: holdingList = [] } = useHoldingStream();
|
|
4254
|
+
const { getIndexPrice } = useIndexPricesStream();
|
|
4255
|
+
const { unsettledPnL } = useCollateral();
|
|
4256
|
+
const usdcBalance = React2.useMemo(() => {
|
|
4257
|
+
if (isUSDC && input) {
|
|
4258
|
+
return new utils.Decimal(usdc?.holding ?? 0).add(input).toNumber();
|
|
4509
4259
|
}
|
|
4260
|
+
return usdc?.holding ?? 0;
|
|
4261
|
+
}, [usdc?.holding, input, isUSDC]);
|
|
4262
|
+
const getAdjustedQty = React2.useCallback(
|
|
4263
|
+
(item) => {
|
|
4264
|
+
if (input && item.token === token) {
|
|
4265
|
+
return new utils.Decimal(item?.holding ?? 0).add(input).toNumber();
|
|
4266
|
+
}
|
|
4267
|
+
return item?.holding ?? 0;
|
|
4268
|
+
},
|
|
4269
|
+
[input, token]
|
|
4270
|
+
);
|
|
4271
|
+
const memoizedLTV = React2.useMemo(() => {
|
|
4272
|
+
return LTV({
|
|
4273
|
+
usdcBalance,
|
|
4274
|
+
upnl: unsettledPnL,
|
|
4275
|
+
assets: holdingList.filter((h) => h.token.toUpperCase() !== "USDC").map((item) => {
|
|
4276
|
+
const indexPrice = getIndexPrice(item.token);
|
|
4277
|
+
const findToken = tokensInfo?.find((i) => i.token === item.token);
|
|
4278
|
+
const qty = getAdjustedQty(item);
|
|
4279
|
+
const weight = collateralRatio({
|
|
4280
|
+
baseWeight: findToken?.base_weight ?? 0,
|
|
4281
|
+
discountFactor: findToken?.discount_factor ?? 0,
|
|
4282
|
+
collateralCap: findToken?.user_max_qty ?? qty,
|
|
4283
|
+
collateralQty: qty,
|
|
4284
|
+
indexPrice
|
|
4285
|
+
});
|
|
4286
|
+
return {
|
|
4287
|
+
qty,
|
|
4288
|
+
indexPrice,
|
|
4289
|
+
weight: weight.toNumber()
|
|
4290
|
+
};
|
|
4291
|
+
})
|
|
4292
|
+
});
|
|
4293
|
+
}, [
|
|
4294
|
+
usdcBalance,
|
|
4295
|
+
unsettledPnL,
|
|
4296
|
+
holdingList,
|
|
4297
|
+
tokensInfo,
|
|
4298
|
+
getIndexPrice,
|
|
4299
|
+
getAdjustedQty
|
|
4300
|
+
]);
|
|
4301
|
+
if (new utils.Decimal(usdcBalance).add(new utils.Decimal(unsettledPnL)).gte(utils.zero)) {
|
|
4302
|
+
return 0;
|
|
4510
4303
|
}
|
|
4511
|
-
|
|
4512
|
-
if (padding) {
|
|
4513
|
-
asks = asks.length < level ? paddingFn(level - asks.length).concat(asks) : asks;
|
|
4514
|
-
bids = bids.length < level ? bids.concat(paddingFn(level - bids.length)) : bids;
|
|
4515
|
-
}
|
|
4516
|
-
return {
|
|
4517
|
-
asks,
|
|
4518
|
-
bids
|
|
4519
|
-
};
|
|
4520
|
-
};
|
|
4521
|
-
var ORDERLY_ORDERBOOK_DEPTH_KEY = "orderly_orderbook_depth_key";
|
|
4522
|
-
var INIT_DATA = {
|
|
4523
|
-
asks: [],
|
|
4524
|
-
bids: []
|
|
4304
|
+
return new utils.Decimal(memoizedLTV).mul(100).toDecimalPlaces(2, utils.Decimal.ROUND_DOWN).toNumber();
|
|
4525
4305
|
};
|
|
4526
|
-
var
|
|
4306
|
+
var useFundingRate = (symbol) => {
|
|
4527
4307
|
if (!symbol) {
|
|
4528
4308
|
throw new types.SDKError("Symbol is required");
|
|
4529
4309
|
}
|
|
4530
|
-
const
|
|
4531
|
-
const
|
|
4532
|
-
const
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
const [isLoading, setIsLoading] = React2.useState(true);
|
|
4540
|
-
const config = useSymbolsInfo()[symbol];
|
|
4541
|
-
const [depthObject, setDepthObject] = useLocalStorage(
|
|
4542
|
-
ORDERLY_ORDERBOOK_DEPTH_KEY,
|
|
4543
|
-
{}
|
|
4544
|
-
);
|
|
4545
|
-
const prevMiddlePrice = React2.useRef(0);
|
|
4546
|
-
const tick = config("quote_tick");
|
|
4547
|
-
const depths = React2.useMemo(() => {
|
|
4548
|
-
if (DEFAULT_SYMBOL_DEPTHS2[symbol]) {
|
|
4549
|
-
return DEFAULT_SYMBOL_DEPTHS2[symbol];
|
|
4550
|
-
}
|
|
4551
|
-
if (typeof tick === "undefined") {
|
|
4552
|
-
return [];
|
|
4553
|
-
}
|
|
4554
|
-
try {
|
|
4555
|
-
const base = new utils.Decimal(tick);
|
|
4556
|
-
return [
|
|
4557
|
-
base.toNumber(),
|
|
4558
|
-
base.mul(10).toNumber(),
|
|
4559
|
-
base.mul(100).toNumber(),
|
|
4560
|
-
base.mul(1e3).toNumber()
|
|
4561
|
-
];
|
|
4562
|
-
} catch {
|
|
4310
|
+
const [countDown, setCountDown] = React2.useState("00:00:00");
|
|
4311
|
+
const timerRef = React2.useRef(null);
|
|
4312
|
+
const { data, isLoading } = useQuery(
|
|
4313
|
+
`/v1/public/funding_rate/${symbol}`,
|
|
4314
|
+
{
|
|
4315
|
+
fallbackData: {
|
|
4316
|
+
est_funding_rate: 0,
|
|
4317
|
+
next_funing_time: 0
|
|
4318
|
+
}
|
|
4563
4319
|
}
|
|
4564
|
-
|
|
4565
|
-
}, [symbol, tick]);
|
|
4320
|
+
);
|
|
4566
4321
|
React2.useEffect(() => {
|
|
4567
|
-
if (
|
|
4322
|
+
if (!data || isLoading) {
|
|
4568
4323
|
return;
|
|
4569
4324
|
}
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
[symbol]: Number(DEFAULT_TICK_SIZES2[symbol])
|
|
4574
|
-
}));
|
|
4575
|
-
} else {
|
|
4576
|
-
setDepthObject((prev) => ({
|
|
4577
|
-
...prev,
|
|
4578
|
-
[symbol]: tick
|
|
4579
|
-
}));
|
|
4325
|
+
const { next_funding_time } = data;
|
|
4326
|
+
if (!next_funding_time || next_funding_time <= 0) {
|
|
4327
|
+
return;
|
|
4580
4328
|
}
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
);
|
|
4588
|
-
const ws = useWS();
|
|
4589
|
-
const ticker = useTickerStream(symbol);
|
|
4590
|
-
const eventEmitter = useEventEmitter();
|
|
4591
|
-
React2.useEffect(() => {
|
|
4592
|
-
let needRequestFullOrderbook = true;
|
|
4593
|
-
setIsLoading(true);
|
|
4594
|
-
let fullOrderBookUpdateSub;
|
|
4595
|
-
const orderBookUpdateSub = ws.subscribe(
|
|
4596
|
-
{
|
|
4597
|
-
event: "subscribe",
|
|
4598
|
-
topic: `${symbol}@orderbookupdate`
|
|
4599
|
-
},
|
|
4600
|
-
{
|
|
4601
|
-
formatter: (message) => message,
|
|
4602
|
-
onMessage: (message) => {
|
|
4603
|
-
const { data: wsData, ts } = message;
|
|
4604
|
-
const { symbol: symbol2, asks, bids, prevTs } = wsData;
|
|
4605
|
-
if (symbolRef.current !== symbol2) {
|
|
4606
|
-
orderBookUpdateSub?.();
|
|
4607
|
-
return;
|
|
4608
|
-
}
|
|
4609
|
-
orderbook_service_default.updateOrderbook(
|
|
4610
|
-
symbol2,
|
|
4611
|
-
{ asks, bids, ts, prevTs },
|
|
4612
|
-
() => {
|
|
4613
|
-
needRequestFullOrderbook = true;
|
|
4614
|
-
}
|
|
4615
|
-
);
|
|
4616
|
-
const data2 = orderbook_service_default.getRawOrderbook(symbol2);
|
|
4617
|
-
setData({ bids: data2.bids, asks: data2.asks });
|
|
4329
|
+
timerRef.current = setInterval(() => {
|
|
4330
|
+
const diff = new Date(next_funding_time).getTime() - utils.getTimestamp();
|
|
4331
|
+
if (diff <= 0) {
|
|
4332
|
+
setCountDown("00:00:00");
|
|
4333
|
+
if (timerRef.current) {
|
|
4334
|
+
clearInterval(timerRef.current);
|
|
4618
4335
|
}
|
|
4336
|
+
return;
|
|
4337
|
+
}
|
|
4338
|
+
const result = utils.timeConvertString(diff);
|
|
4339
|
+
if (result.length === 3) {
|
|
4340
|
+
setCountDown(
|
|
4341
|
+
`${result[0].toString().padStart(2, "0")}:${result[1].toString().padStart(2, "0")}:${result[2].toString().padStart(2, "0")}`
|
|
4342
|
+
);
|
|
4343
|
+
}
|
|
4344
|
+
}, 1e3);
|
|
4345
|
+
return () => {
|
|
4346
|
+
if (timerRef.current) {
|
|
4347
|
+
clearInterval(timerRef.current);
|
|
4619
4348
|
}
|
|
4349
|
+
};
|
|
4350
|
+
}, [data, isLoading]);
|
|
4351
|
+
const est_funding_rate = React2.useMemo(() => {
|
|
4352
|
+
if (!data) {
|
|
4353
|
+
return;
|
|
4354
|
+
}
|
|
4355
|
+
const { next_funding_time, est_funding_rate: est_funding_rate2 = 0 } = data;
|
|
4356
|
+
if (utils.getTimestamp() > next_funding_time) {
|
|
4357
|
+
return null;
|
|
4358
|
+
}
|
|
4359
|
+
return new utils.Decimal(Number(est_funding_rate2) * 100).toFixed(
|
|
4360
|
+
4,
|
|
4361
|
+
utils.Decimal.ROUND_DOWN
|
|
4620
4362
|
);
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4363
|
+
}, [data]);
|
|
4364
|
+
return {
|
|
4365
|
+
...data,
|
|
4366
|
+
est_funding_rate,
|
|
4367
|
+
countDown
|
|
4368
|
+
};
|
|
4369
|
+
};
|
|
4370
|
+
var useFundingDetails = (symbol) => {
|
|
4371
|
+
if (!symbol) {
|
|
4372
|
+
throw new types.SDKError("symbol is required");
|
|
4373
|
+
}
|
|
4374
|
+
return useQuery(`/v1/public/info/${symbol}`, {
|
|
4375
|
+
errorRetryCount: 3,
|
|
4376
|
+
revalidateOnFocus: false
|
|
4377
|
+
});
|
|
4378
|
+
};
|
|
4379
|
+
var calculatePositiveRate = (periodData, period) => {
|
|
4380
|
+
if (!periodData || !period) {
|
|
4381
|
+
return 0;
|
|
4382
|
+
}
|
|
4383
|
+
const daysMap = {
|
|
4384
|
+
"1d": 1,
|
|
4385
|
+
"3d": 3,
|
|
4386
|
+
"7d": 7,
|
|
4387
|
+
"14d": 14,
|
|
4388
|
+
"30d": 30,
|
|
4389
|
+
"90d": 90
|
|
4390
|
+
};
|
|
4391
|
+
const totalTimes = daysMap[period] * 3;
|
|
4392
|
+
return periodData.positive / totalTimes;
|
|
4393
|
+
};
|
|
4394
|
+
var useFundingRateHistory = () => {
|
|
4395
|
+
const { data: historyData, isLoading } = useQuery(
|
|
4396
|
+
"/v1/public/market_info/funding_history"
|
|
4397
|
+
);
|
|
4398
|
+
const getPositiveRates = React2.useCallback(
|
|
4399
|
+
(data, period) => {
|
|
4400
|
+
if (!data?.length) {
|
|
4401
|
+
return {};
|
|
4402
|
+
}
|
|
4403
|
+
return data.reduce(
|
|
4404
|
+
(acc, item) => {
|
|
4405
|
+
acc[item.symbol] = calculatePositiveRate(
|
|
4406
|
+
item.funding[period],
|
|
4407
|
+
period
|
|
4408
|
+
);
|
|
4409
|
+
return acc;
|
|
4631
4410
|
},
|
|
4632
|
-
{
|
|
4633
|
-
formatter: (message) => message,
|
|
4634
|
-
onMessage: (message) => {
|
|
4635
|
-
const { symbol: symbol2, asks, bids, ts } = message.data;
|
|
4636
|
-
if (symbolRef.current !== symbol2) {
|
|
4637
|
-
return;
|
|
4638
|
-
}
|
|
4639
|
-
orderbook_service_default.setFullOrderbook(symbol2, { asks, bids, ts });
|
|
4640
|
-
const data2 = orderbook_service_default.getRawOrderbook(symbol2);
|
|
4641
|
-
setData({ bids: data2.bids, asks: data2.asks });
|
|
4642
|
-
setIsLoading(false);
|
|
4643
|
-
}
|
|
4644
|
-
}
|
|
4411
|
+
{}
|
|
4645
4412
|
);
|
|
4646
|
-
needRequestFullOrderbook = false;
|
|
4647
|
-
}
|
|
4648
|
-
return () => {
|
|
4649
|
-
orderBookUpdateSub?.();
|
|
4650
|
-
fullOrderBookUpdateSub?.();
|
|
4651
|
-
orderbook_service_default.resetOrderBook(symbol);
|
|
4652
|
-
setData(INIT_DATA);
|
|
4653
|
-
};
|
|
4654
|
-
}, [symbol]);
|
|
4655
|
-
const { data: markPrice } = useMarkPrice(symbol);
|
|
4656
|
-
const onItemClick = React2.useCallback((item) => {
|
|
4657
|
-
eventEmitter.emit("orderbook:item:click", item);
|
|
4658
|
-
}, []);
|
|
4659
|
-
const reducedData = reduceOrderbook(depthObject[symbol], level, padding, {
|
|
4660
|
-
asks: data.asks,
|
|
4661
|
-
bids: data.bids
|
|
4662
|
-
});
|
|
4663
|
-
React2.useEffect(() => {
|
|
4664
|
-
eventEmitter.emit("orderbook:update", reducedData);
|
|
4665
|
-
}, [reducedData]);
|
|
4666
|
-
const middlePrice = React2.useMemo(() => {
|
|
4667
|
-
let asksFrist = 0;
|
|
4668
|
-
let bidsFirst = 0;
|
|
4669
|
-
if (data.asks.length > 0) {
|
|
4670
|
-
asksFrist = reducedData.asks?.[reducedData.asks.length - 1]?.[0];
|
|
4671
|
-
}
|
|
4672
|
-
if (data.bids.length > 0) {
|
|
4673
|
-
bidsFirst = data.bids[0][0];
|
|
4674
|
-
}
|
|
4675
|
-
if (!isNumber(asksFrist) || !isNumber(bidsFirst) || !ticker) {
|
|
4676
|
-
return 0;
|
|
4677
|
-
}
|
|
4678
|
-
return [asksFrist, bidsFirst, ticker["24h_close"]].sort()[1];
|
|
4679
|
-
}, [ticker?.["24h_close"], data]);
|
|
4680
|
-
React2.useEffect(() => {
|
|
4681
|
-
prevMiddlePrice.current = middlePrice;
|
|
4682
|
-
}, [middlePrice]);
|
|
4683
|
-
return [
|
|
4684
|
-
{
|
|
4685
|
-
asks: reducedData.asks.slice(-level),
|
|
4686
|
-
bids: reducedData.bids.slice(0, level),
|
|
4687
|
-
markPrice,
|
|
4688
|
-
middlePrice: [prevMiddlePrice.current, middlePrice]
|
|
4689
4413
|
},
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
|
|
4414
|
+
[]
|
|
4415
|
+
);
|
|
4416
|
+
return React2.useMemo(() => {
|
|
4417
|
+
return {
|
|
4418
|
+
data: historyData ?? types.EMPTY_LIST,
|
|
4694
4419
|
isLoading,
|
|
4695
|
-
|
|
4696
|
-
}
|
|
4697
|
-
];
|
|
4420
|
+
getPositiveRates
|
|
4421
|
+
};
|
|
4422
|
+
}, [historyData, isLoading, getPositiveRates]);
|
|
4698
4423
|
};
|
|
4699
|
-
var
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4424
|
+
var useApiStatusStore = zustand.create()(
|
|
4425
|
+
immer.immer((set) => ({
|
|
4426
|
+
apis: {
|
|
4427
|
+
positions: {
|
|
4428
|
+
loading: false
|
|
4429
|
+
}
|
|
4430
|
+
},
|
|
4431
|
+
actions: {
|
|
4432
|
+
updateStatus: (key, status) => {
|
|
4433
|
+
set((state) => {
|
|
4434
|
+
state.apis[key] = status;
|
|
4435
|
+
});
|
|
4436
|
+
},
|
|
4437
|
+
updateApiLoading: (key, loading) => {
|
|
4438
|
+
set((state) => {
|
|
4439
|
+
state.apis[key].loading = loading;
|
|
4440
|
+
});
|
|
4441
|
+
},
|
|
4442
|
+
updateApiError: (key, error) => {
|
|
4443
|
+
set((state) => {
|
|
4444
|
+
state.apis[key] = {
|
|
4445
|
+
loading: false,
|
|
4446
|
+
error
|
|
4447
|
+
};
|
|
4448
|
+
});
|
|
4449
|
+
}
|
|
4450
|
+
}
|
|
4451
|
+
}))
|
|
4452
|
+
);
|
|
4453
|
+
var useApiStatusActions = () => useApiStatusStore((state) => state.actions);
|
|
4454
|
+
|
|
4455
|
+
// src/orderly/calculator/baseCalculator.ts
|
|
4456
|
+
var BaseCalculator = class {
|
|
4457
|
+
cache(data) {
|
|
4458
|
+
this._cache = data;
|
|
4459
|
+
}
|
|
4704
4460
|
};
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4461
|
+
|
|
4462
|
+
// src/orderly/calculator/markPrice.ts
|
|
4463
|
+
var MarketCalculatorName = "markPriceCalculator";
|
|
4464
|
+
var MarkPriceCalculator = class extends BaseCalculator {
|
|
4465
|
+
constructor() {
|
|
4466
|
+
super(...arguments);
|
|
4467
|
+
this.name = MarketCalculatorName;
|
|
4468
|
+
}
|
|
4469
|
+
calc(scope, data, ctx) {
|
|
4470
|
+
return data;
|
|
4471
|
+
}
|
|
4472
|
+
update(data, scope) {
|
|
4473
|
+
useMarkPriceStore.getState().actions.updateMarkPrice(data);
|
|
4474
|
+
}
|
|
4708
4475
|
};
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4476
|
+
|
|
4477
|
+
// src/orderly/calculator/calculatorContext.ts
|
|
4478
|
+
var CalculatorContext = class _CalculatorContext {
|
|
4479
|
+
static get instance() {
|
|
4480
|
+
return this._instance;
|
|
4481
|
+
}
|
|
4482
|
+
static create(scope, data) {
|
|
4483
|
+
if (!this._instance) {
|
|
4484
|
+
this._instance = new _CalculatorContext(scope, data);
|
|
4485
|
+
}
|
|
4486
|
+
return this._instance.update(scope, data);
|
|
4487
|
+
}
|
|
4488
|
+
constructor(scope, data) {
|
|
4489
|
+
this.setCtxData();
|
|
4490
|
+
this.output = {
|
|
4491
|
+
// rows: positions,
|
|
4492
|
+
};
|
|
4493
|
+
}
|
|
4494
|
+
update(scope, data) {
|
|
4495
|
+
this.setCtxData();
|
|
4496
|
+
this.markPrices = scope === "markPrice" /* MARK_PRICE */ ? data : this.output[MarketCalculatorName];
|
|
4497
|
+
this.portfolio = this.output["portfolio"] || useAppStore.getState().portfolio;
|
|
4498
|
+
return this;
|
|
4499
|
+
}
|
|
4500
|
+
setCtxData() {
|
|
4501
|
+
this.accountInfo = useAppStore.getState().accountInfo;
|
|
4502
|
+
this.symbolsInfo = useAppStore.getState().symbolsInfo;
|
|
4503
|
+
this.fundingRates = useAppStore.getState().fundingRates;
|
|
4504
|
+
this.tokensInfo = useTokensInfoStore.getState().tokensInfo;
|
|
4505
|
+
}
|
|
4506
|
+
get(fn) {
|
|
4507
|
+
return fn(this.output);
|
|
4508
|
+
}
|
|
4509
|
+
getCacheValue(name, fallback) {
|
|
4510
|
+
return this.output[name] || fallback();
|
|
4511
|
+
}
|
|
4512
|
+
clearCache() {
|
|
4513
|
+
this.output = {};
|
|
4514
|
+
this.accountInfo = void 0;
|
|
4515
|
+
this.portfolio = void 0;
|
|
4516
|
+
}
|
|
4517
|
+
deleteByName(name) {
|
|
4518
|
+
delete this.output[name];
|
|
4519
|
+
}
|
|
4520
|
+
// get positions(): API.PositionTPSLExt[] {
|
|
4521
|
+
// if (this.output.positionCalculator) return this.output.positionCalculator;
|
|
4522
|
+
// return usePositionStore.getState().positions;
|
|
4523
|
+
// }
|
|
4524
|
+
get isReady() {
|
|
4525
|
+
return !!this.accountInfo;
|
|
4526
|
+
}
|
|
4527
|
+
saveOutput(name, data) {
|
|
4528
|
+
this.output[name] = data;
|
|
4529
|
+
}
|
|
4530
|
+
outputToValue() {
|
|
4531
|
+
return this.output;
|
|
4532
|
+
}
|
|
4712
4533
|
};
|
|
4713
4534
|
|
|
4714
|
-
// src/orderly/
|
|
4715
|
-
var
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4535
|
+
// src/orderly/calculator/calculatorService.ts
|
|
4536
|
+
var CalculatorService = class {
|
|
4537
|
+
constructor(scheduler, calculators) {
|
|
4538
|
+
this.scheduler = scheduler;
|
|
4539
|
+
this.pendingCalc = [];
|
|
4540
|
+
this.calcQueue = [];
|
|
4541
|
+
/**
|
|
4542
|
+
* Reference count for each calculator, used to determine if a calculator is still in use.
|
|
4543
|
+
*/
|
|
4544
|
+
this.referenceCount = /* @__PURE__ */ new Map();
|
|
4545
|
+
this.isPaused = false;
|
|
4546
|
+
this.calculators = new Map(calculators);
|
|
4547
|
+
}
|
|
4548
|
+
register(scope, calculator) {
|
|
4549
|
+
const ref_count_name = `${scope}_${calculator.name}`;
|
|
4550
|
+
const count = this.referenceCount.get(ref_count_name);
|
|
4551
|
+
if (typeof count !== "undefined" && count > 0) {
|
|
4552
|
+
this.referenceCount.set(ref_count_name, count + 1);
|
|
4553
|
+
return;
|
|
4554
|
+
}
|
|
4555
|
+
const calculators = this.calculators.get(scope);
|
|
4556
|
+
if (Array.isArray(calculators)) {
|
|
4557
|
+
calculators.push(calculator);
|
|
4735
4558
|
} else {
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4559
|
+
this.calculators.set(scope, [calculator]);
|
|
4560
|
+
}
|
|
4561
|
+
this.referenceCount.set(ref_count_name, 1);
|
|
4562
|
+
}
|
|
4563
|
+
unregister(scope, calculator) {
|
|
4564
|
+
const ref_count_name = `${scope}_${calculator.name}`;
|
|
4565
|
+
const count = this.referenceCount.get(ref_count_name);
|
|
4566
|
+
if (typeof count !== "undefined" && count > 1) {
|
|
4567
|
+
this.referenceCount.set(ref_count_name, count - 1);
|
|
4568
|
+
return;
|
|
4569
|
+
}
|
|
4570
|
+
const calculators = this.calculators.get(scope);
|
|
4571
|
+
if (Array.isArray(calculators)) {
|
|
4572
|
+
const index = calculators.findIndex((c) => c.name === calculator.name);
|
|
4573
|
+
if (index > -1) {
|
|
4574
|
+
calculators[index].destroy?.();
|
|
4575
|
+
calculators.splice(index, 1);
|
|
4576
|
+
}
|
|
4745
4577
|
}
|
|
4578
|
+
this.referenceCount.delete(ref_count_name);
|
|
4746
4579
|
}
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
const getFavorites = React2.useMemo(() => {
|
|
4751
|
-
const curData = getStore("favorites", []);
|
|
4752
|
-
const tabs = getFavoriteTabs;
|
|
4753
|
-
const result = [];
|
|
4754
|
-
const len = curData.length;
|
|
4755
|
-
for (let index = 0; index < len; index++) {
|
|
4756
|
-
const favData = curData[index];
|
|
4757
|
-
const favTabs = favData.tabs.filter(
|
|
4758
|
-
(tab) => tabs.findIndex((item) => tab.id === item.id) !== -1
|
|
4759
|
-
);
|
|
4760
|
-
if (favTabs.length) {
|
|
4761
|
-
result.push({ ...favData, tabs: favTabs });
|
|
4762
|
-
}
|
|
4580
|
+
async calc(scope, data, options) {
|
|
4581
|
+
if (scope !== "position" /* POSITION */) {
|
|
4582
|
+
if (!options?.skipWhenOnPause) ;
|
|
4763
4583
|
}
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
}, [configStore]);
|
|
4767
|
-
const [favoriteTabs, setFavoriteTabs] = React2.useState(getFavoriteTabs);
|
|
4768
|
-
const [favorites, setFavorites] = React2.useState(getFavorites);
|
|
4769
|
-
const [recent, setRecent] = React2.useState(
|
|
4770
|
-
getStore("recent", []).filter((e) => e)
|
|
4771
|
-
);
|
|
4772
|
-
const [tabSort, setTabSort] = React2.useState(
|
|
4773
|
-
getStore("tabSort", {})
|
|
4774
|
-
);
|
|
4775
|
-
const updateFavoriteTabs = (tab, operator) => {
|
|
4776
|
-
const saveTabs = (tabs2) => {
|
|
4777
|
-
setFavoriteTabs(tabs2);
|
|
4778
|
-
updateStore("favoriteTabs", tabs2);
|
|
4779
|
-
};
|
|
4780
|
-
if (Array.isArray(tab)) {
|
|
4781
|
-
saveTabs(tab);
|
|
4584
|
+
const ctx = CalculatorContext.create(scope, data);
|
|
4585
|
+
if (!ctx.isReady && options?.skipPending) {
|
|
4782
4586
|
return;
|
|
4783
4587
|
}
|
|
4784
|
-
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4588
|
+
if (options?.skipWhenOnPause && !this.windowIsVisible)
|
|
4589
|
+
return;
|
|
4590
|
+
this.calcQueue.push({ scope, data, options });
|
|
4591
|
+
await this.handleCalcQueue(ctx);
|
|
4592
|
+
this.ctx = ctx;
|
|
4593
|
+
}
|
|
4594
|
+
// private async handlePendingCalc() {
|
|
4595
|
+
// // console.log("[handlePendingCalc]:", this.pendingCalc);
|
|
4596
|
+
// if (this.pendingCalc.length === 0) return;
|
|
4597
|
+
// this.calcQueue = [...this.pendingCalc, ...this.calcQueue];
|
|
4598
|
+
// this.pendingCalc = [];
|
|
4599
|
+
// }
|
|
4600
|
+
async handleCalcQueue(context) {
|
|
4601
|
+
const first = this.calcQueue.shift();
|
|
4602
|
+
if (first) {
|
|
4603
|
+
const { scope, data, options } = first;
|
|
4604
|
+
const ctx = context || CalculatorContext.create(scope, data);
|
|
4605
|
+
const calculators = this.calculators.get(scope);
|
|
4606
|
+
if (Array.isArray(calculators) && calculators.length) {
|
|
4607
|
+
try {
|
|
4608
|
+
await this.scheduler.calc(scope, calculators, data, ctx);
|
|
4609
|
+
} catch (e) {
|
|
4610
|
+
}
|
|
4611
|
+
if (!options?.skipUpdate) {
|
|
4612
|
+
this.scheduler.update(scope, calculators, ctx.outputToValue());
|
|
4613
|
+
}
|
|
4791
4614
|
}
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
tabs.splice(index, 1);
|
|
4615
|
+
if (this.calcQueue.length) {
|
|
4616
|
+
this.handleCalcQueue(ctx);
|
|
4795
4617
|
}
|
|
4796
4618
|
}
|
|
4797
|
-
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
const index = curData.findIndex((item) => item.name == symbol.symbol);
|
|
4806
|
-
if (index !== -1) {
|
|
4807
|
-
curData.splice(index, 1);
|
|
4619
|
+
}
|
|
4620
|
+
stop() {
|
|
4621
|
+
this.calcQueue = [];
|
|
4622
|
+
this.ctx?.clearCache();
|
|
4623
|
+
}
|
|
4624
|
+
get windowIsVisible() {
|
|
4625
|
+
if (typeof document === "undefined") {
|
|
4626
|
+
return true;
|
|
4808
4627
|
}
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4628
|
+
return document.visibilityState === "visible";
|
|
4629
|
+
}
|
|
4630
|
+
};
|
|
4631
|
+
var CalculatorServiceID = "CalculatorService";
|
|
4632
|
+
|
|
4633
|
+
// src/orderly/calculator/shardedScheduler.ts
|
|
4634
|
+
var requestIdleCallbackPolyfill = (callback, options) => {
|
|
4635
|
+
const startTime = Date.now();
|
|
4636
|
+
return setTimeout(() => {
|
|
4637
|
+
callback({
|
|
4638
|
+
didTimeout: false,
|
|
4639
|
+
timeRemaining: () => Math.max(0, 50 - (Date.now() - startTime))
|
|
4640
|
+
});
|
|
4641
|
+
}, 1);
|
|
4642
|
+
};
|
|
4643
|
+
var cancelIdleCallbackPolyfill = (id) => {
|
|
4644
|
+
clearTimeout(id);
|
|
4645
|
+
};
|
|
4646
|
+
var safeRequestIdleCallback = typeof window !== "undefined" && window.requestIdleCallback ? window.requestIdleCallback.bind(window) : requestIdleCallbackPolyfill;
|
|
4647
|
+
typeof window !== "undefined" && window.cancelIdleCallback ? window.cancelIdleCallback.bind(window) : cancelIdleCallbackPolyfill;
|
|
4648
|
+
var ShardingScheduler = class {
|
|
4649
|
+
// run(calculators: Calculator[]) {}
|
|
4650
|
+
calc(scope, calculators, data, ctx) {
|
|
4651
|
+
return new Promise((resolve, reject) => {
|
|
4652
|
+
try {
|
|
4653
|
+
this.computation(
|
|
4654
|
+
calculators,
|
|
4655
|
+
(shard) => {
|
|
4656
|
+
const results = [];
|
|
4657
|
+
for (let index = 0; index < shard.length; index++) {
|
|
4658
|
+
const calculator = shard[index];
|
|
4659
|
+
const result = calculator.calc(scope, data, ctx);
|
|
4660
|
+
if (result) {
|
|
4661
|
+
ctx.saveOutput(calculator.name, result);
|
|
4662
|
+
results.push(result);
|
|
4663
|
+
}
|
|
4664
|
+
}
|
|
4665
|
+
return results;
|
|
4666
|
+
},
|
|
4667
|
+
(results) => {
|
|
4668
|
+
resolve(results);
|
|
4669
|
+
}
|
|
4670
|
+
);
|
|
4671
|
+
} catch (error) {
|
|
4672
|
+
reject(error);
|
|
4825
4673
|
}
|
|
4826
|
-
}
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
4674
|
+
});
|
|
4675
|
+
}
|
|
4676
|
+
update(scope, calculators, data) {
|
|
4677
|
+
for (let index = 0; index < calculators.length; index++) {
|
|
4678
|
+
const calculator = calculators[index];
|
|
4679
|
+
const item = data[calculator.name];
|
|
4680
|
+
if (!!item) {
|
|
4681
|
+
calculator.update(item, scope);
|
|
4682
|
+
}
|
|
4683
|
+
}
|
|
4684
|
+
return Promise.resolve();
|
|
4685
|
+
}
|
|
4686
|
+
computation(data, processor, onComplete) {
|
|
4687
|
+
let index = 0;
|
|
4688
|
+
const results = [];
|
|
4689
|
+
const estimatedShardSize = Math.min(data.length, 2);
|
|
4690
|
+
function processNextShard(deadline) {
|
|
4691
|
+
let shardSize = estimatedShardSize;
|
|
4692
|
+
while (index + shardSize <= data.length && deadline.timeRemaining() > 0) {
|
|
4693
|
+
const shard = data.slice(index, index + shardSize);
|
|
4694
|
+
const result = processor(shard);
|
|
4695
|
+
results.push(result);
|
|
4696
|
+
index += shardSize;
|
|
4697
|
+
if (deadline.timeRemaining() < 1) {
|
|
4698
|
+
shardSize = Math.max(1, Math.floor(shardSize / 2));
|
|
4831
4699
|
} else {
|
|
4832
|
-
|
|
4700
|
+
shardSize = Math.min(data.length - index, shardSize * 2);
|
|
4833
4701
|
}
|
|
4702
|
+
}
|
|
4703
|
+
if (index < data.length) {
|
|
4704
|
+
safeRequestIdleCallback(processNextShard, {
|
|
4705
|
+
timeout: 1e3
|
|
4706
|
+
});
|
|
4834
4707
|
} else {
|
|
4835
|
-
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4708
|
+
onComplete(results.flat());
|
|
4709
|
+
}
|
|
4710
|
+
}
|
|
4711
|
+
safeRequestIdleCallback(processNextShard, {
|
|
4712
|
+
timeout: 1e3
|
|
4713
|
+
});
|
|
4714
|
+
}
|
|
4715
|
+
};
|
|
4716
|
+
var POSITION_EMPTY = {
|
|
4717
|
+
rows: null,
|
|
4718
|
+
margin_ratio: 0,
|
|
4719
|
+
initial_margin_ratio: 0,
|
|
4720
|
+
maintenance_margin_ratio: 0,
|
|
4721
|
+
open_margin_ratio: 0,
|
|
4722
|
+
current_margin_ratio_with_orders: 0,
|
|
4723
|
+
initial_margin_ratio_with_orders: 0,
|
|
4724
|
+
maintenance_margin_ratio_with_orders: 0,
|
|
4725
|
+
total_collateral_value: 0,
|
|
4726
|
+
free_collateral: 0,
|
|
4727
|
+
total_pnl_24_h: 0,
|
|
4728
|
+
unrealPnL: 0,
|
|
4729
|
+
total_unreal_pnl: 0,
|
|
4730
|
+
unsettledPnL: 0,
|
|
4731
|
+
total_unsettled_pnl: 0,
|
|
4732
|
+
notional: 0,
|
|
4733
|
+
unrealPnlROI: 0
|
|
4734
|
+
};
|
|
4735
|
+
var usePositionStore = zustand.create()(
|
|
4736
|
+
immer.immer((set) => ({
|
|
4737
|
+
positions: {
|
|
4738
|
+
all: POSITION_EMPTY
|
|
4739
|
+
},
|
|
4740
|
+
actions: {
|
|
4741
|
+
setPositions: (key, positions3) => {
|
|
4742
|
+
set((state) => {
|
|
4743
|
+
state.positions[key] = positions3;
|
|
4744
|
+
});
|
|
4745
|
+
},
|
|
4746
|
+
closePosition: (symbol) => {
|
|
4747
|
+
set((state) => {
|
|
4748
|
+
delete state.positions[symbol];
|
|
4749
|
+
});
|
|
4750
|
+
},
|
|
4751
|
+
clearAll: () => {
|
|
4752
|
+
set((state) => {
|
|
4753
|
+
state.positions = {
|
|
4754
|
+
all: POSITION_EMPTY
|
|
4755
|
+
};
|
|
4756
|
+
});
|
|
4847
4757
|
}
|
|
4848
4758
|
}
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4759
|
+
}))
|
|
4760
|
+
);
|
|
4761
|
+
var usePositions = (symbol = "all") => usePositionStore((state) => (state.positions[symbol] ?? POSITION_EMPTY).rows);
|
|
4762
|
+
var usePositionActions = () => usePositionStore((state) => state.actions);
|
|
4763
|
+
|
|
4764
|
+
// src/orderly/calculator/positions.ts
|
|
4765
|
+
var NAME_PREFIX = "positionCalculator";
|
|
4766
|
+
var AllPositions = "all";
|
|
4767
|
+
var PositionCalculator = class extends BaseCalculator {
|
|
4768
|
+
// private id: string;
|
|
4769
|
+
constructor(symbol = AllPositions) {
|
|
4770
|
+
super();
|
|
4771
|
+
this.name = `${NAME_PREFIX}_${symbol}`;
|
|
4772
|
+
this.symbol = symbol;
|
|
4773
|
+
}
|
|
4774
|
+
calc(scope, data, ctx) {
|
|
4775
|
+
if (scope === "markPrice" /* MARK_PRICE */) {
|
|
4776
|
+
return this.calcByMarkPrice(data, ctx);
|
|
4777
|
+
}
|
|
4778
|
+
if (scope === "indexPrice" /* INDEX_PRICE */) {
|
|
4779
|
+
return this.calcByIndexPrice(data, ctx);
|
|
4780
|
+
}
|
|
4781
|
+
if (scope === "position" /* POSITION */) {
|
|
4782
|
+
return this.calcByPosition(
|
|
4783
|
+
this.preprocess(data),
|
|
4784
|
+
ctx
|
|
4785
|
+
);
|
|
4786
|
+
}
|
|
4787
|
+
return data;
|
|
4788
|
+
}
|
|
4789
|
+
update(data, scope) {
|
|
4790
|
+
if (!data || !Array.isArray(data.rows))
|
|
4791
|
+
return;
|
|
4792
|
+
usePositionStore.getState().actions.setPositions(this.symbol, data);
|
|
4793
|
+
if (Array.isArray(data.rows) && useApiStatusStore.getState().apis.positions.loading) {
|
|
4794
|
+
useApiStatusStore.getState().actions.updateApiLoading("positions", false);
|
|
4795
|
+
}
|
|
4796
|
+
}
|
|
4797
|
+
calcByMarkPrice(markPrice, ctx) {
|
|
4798
|
+
let positions3 = this.getPosition(markPrice, ctx);
|
|
4799
|
+
useAppStore.getState().fundingRates;
|
|
4800
|
+
if (!positions3 || !Array.isArray(positions3.rows) || !positions3.rows.length)
|
|
4801
|
+
return positions3;
|
|
4802
|
+
positions3 = {
|
|
4803
|
+
...positions3,
|
|
4804
|
+
rows: positions3.rows.map((item) => {
|
|
4805
|
+
return {
|
|
4806
|
+
...item,
|
|
4807
|
+
mark_price: markPrice[item.symbol] || item.mark_price
|
|
4808
|
+
};
|
|
4809
|
+
})
|
|
4810
|
+
};
|
|
4811
|
+
return this.format(positions3, ctx);
|
|
4812
|
+
}
|
|
4813
|
+
calcByIndexPrice(indexPrice, ctx) {
|
|
4814
|
+
let positions3 = this.getPosition(indexPrice, ctx);
|
|
4815
|
+
if (!positions3) {
|
|
4816
|
+
return positions3;
|
|
4817
|
+
}
|
|
4818
|
+
if (!Array.isArray(positions3.rows) || !positions3.rows.length)
|
|
4819
|
+
return positions3;
|
|
4820
|
+
positions3 = {
|
|
4821
|
+
...positions3,
|
|
4822
|
+
rows: positions3.rows.map((item) => ({
|
|
4823
|
+
...item,
|
|
4824
|
+
index_price: indexPrice[item.symbol] || item.index_price || item.mark_price
|
|
4825
|
+
}))
|
|
4826
|
+
};
|
|
4827
|
+
return this.format(positions3, ctx);
|
|
4828
|
+
}
|
|
4829
|
+
calcByPosition(positions3, ctx) {
|
|
4830
|
+
if (positions3.rows.length === 0)
|
|
4831
|
+
return positions3;
|
|
4832
|
+
return this.format(positions3, ctx);
|
|
4833
|
+
}
|
|
4834
|
+
format(data, ctx) {
|
|
4835
|
+
const { accountInfo, symbolsInfo, fundingRates, portfolio } = ctx;
|
|
4836
|
+
if (!accountInfo || !fundingRates || !symbolsInfo) {
|
|
4837
|
+
return data;
|
|
4838
|
+
}
|
|
4839
|
+
let unrealPnL_total = utils.zero, unrealPnL_total_index = utils.zero, notional_total = utils.zero, unsettlementPnL_total = utils.zero;
|
|
4840
|
+
let rows = data.rows.map((item) => {
|
|
4855
4841
|
const info = symbolsInfo[item.symbol];
|
|
4856
|
-
const
|
|
4857
|
-
const
|
|
4858
|
-
const
|
|
4859
|
-
|
|
4842
|
+
const sum_unitary_funding = fundingRates?.[item.symbol]?.["sum_unitary_funding"] ?? 0;
|
|
4843
|
+
const notional = perp.positions.notional(item.position_qty, item.mark_price);
|
|
4844
|
+
const unrealPnl = perp.positions.unrealizedPnL({
|
|
4845
|
+
qty: item.position_qty,
|
|
4846
|
+
openPrice: item?.average_open_price,
|
|
4847
|
+
// markPrice: unRealizedPrice,
|
|
4848
|
+
markPrice: item.mark_price
|
|
4849
|
+
});
|
|
4850
|
+
let unrealPnl_index = 0, unrealPnlROI_index = 0;
|
|
4851
|
+
const maxLeverage = item.leverage || 1;
|
|
4852
|
+
const imr = perp.account.IMR({
|
|
4853
|
+
maxLeverage,
|
|
4854
|
+
baseIMR: info?.["base_imr"],
|
|
4855
|
+
IMR_Factor: accountInfo.imr_factor[item.symbol],
|
|
4856
|
+
positionNotional: notional,
|
|
4857
|
+
ordersNotional: 0,
|
|
4858
|
+
IMR_factor_power: 4 / 5
|
|
4859
|
+
});
|
|
4860
|
+
const unrealPnlROI = perp.positions.unrealizedPnLROI({
|
|
4861
|
+
positionQty: item.position_qty,
|
|
4862
|
+
openPrice: item.average_open_price,
|
|
4863
|
+
IMR: imr,
|
|
4864
|
+
unrealizedPnL: unrealPnl
|
|
4865
|
+
});
|
|
4866
|
+
if (item.index_price) {
|
|
4867
|
+
unrealPnl_index = perp.positions.unrealizedPnL({
|
|
4868
|
+
qty: item.position_qty,
|
|
4869
|
+
openPrice: item?.average_open_price,
|
|
4870
|
+
// markPrice: unRealizedPrice,
|
|
4871
|
+
markPrice: item.index_price
|
|
4872
|
+
});
|
|
4873
|
+
unrealPnlROI_index = perp.positions.unrealizedPnLROI({
|
|
4874
|
+
positionQty: item.position_qty,
|
|
4875
|
+
openPrice: item.average_open_price,
|
|
4876
|
+
IMR: imr,
|
|
4877
|
+
unrealizedPnL: unrealPnl_index
|
|
4878
|
+
});
|
|
4879
|
+
}
|
|
4880
|
+
const unsettlementPnL2 = perp.positions.unsettlementPnL({
|
|
4881
|
+
positionQty: item.position_qty,
|
|
4882
|
+
markPrice: item.mark_price,
|
|
4883
|
+
costPosition: item.cost_position,
|
|
4884
|
+
sumUnitaryFunding: ramda.propOr(
|
|
4885
|
+
0,
|
|
4886
|
+
"sum_unitary_funding",
|
|
4887
|
+
fundingRates[item.symbol]
|
|
4888
|
+
),
|
|
4889
|
+
lastSumUnitaryFunding: item.last_sum_unitary_funding
|
|
4890
|
+
});
|
|
4891
|
+
const MMR = perp.positions.MMR({
|
|
4892
|
+
baseMMR: info?.["base_mmr"],
|
|
4893
|
+
baseIMR: info?.["base_imr"],
|
|
4894
|
+
IMRFactor: accountInfo.imr_factor[item.symbol],
|
|
4895
|
+
positionNotional: notional,
|
|
4896
|
+
IMR_factor_power: 4 / 5
|
|
4897
|
+
});
|
|
4898
|
+
unrealPnL_total = unrealPnL_total.add(unrealPnl);
|
|
4899
|
+
unrealPnL_total_index = unrealPnL_total_index.add(unrealPnl_index);
|
|
4900
|
+
notional_total = notional_total.add(notional);
|
|
4901
|
+
unsettlementPnL_total = unsettlementPnL_total.add(unsettlementPnL2);
|
|
4902
|
+
const fundingFee = new utils.Decimal(sum_unitary_funding).sub(item.last_sum_unitary_funding).mul(item.position_qty).negated().toNumber();
|
|
4860
4903
|
return {
|
|
4861
4904
|
...item,
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4905
|
+
fundingFee,
|
|
4906
|
+
mm: perp.positions.maintenanceMargin({
|
|
4907
|
+
positionQty: item.position_qty,
|
|
4908
|
+
markPrice: item.mark_price,
|
|
4909
|
+
MMR
|
|
4910
|
+
}),
|
|
4911
|
+
mmr: MMR,
|
|
4912
|
+
notional,
|
|
4913
|
+
unsettlement_pnl: unsettlementPnL2,
|
|
4914
|
+
unrealized_pnl: unrealPnl,
|
|
4915
|
+
unrealized_pnl_index: unrealPnl_index,
|
|
4916
|
+
unrealized_pnl_ROI: unrealPnlROI,
|
|
4917
|
+
unrealized_pnl_ROI_index: unrealPnlROI_index
|
|
4867
4918
|
};
|
|
4868
4919
|
});
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
if (symbolsInfo) {
|
|
4887
|
-
imr = symbolsInfo?.[element.symbol]("base_imr");
|
|
4888
|
-
}
|
|
4889
|
-
filter[index] = {
|
|
4890
|
-
...filter[index],
|
|
4891
|
-
isFavorite,
|
|
4892
|
-
tabs,
|
|
4893
|
-
leverage: imr ? 1 / imr : void 0
|
|
4920
|
+
const totalUnrealPnl = unrealPnL_total.toNumber();
|
|
4921
|
+
const totalUnrealPnl_index = unrealPnL_total_index.toNumber();
|
|
4922
|
+
const unsettlementPnL = unsettlementPnL_total.toNumber();
|
|
4923
|
+
let totalUnrealizedROI = 0, totalUnrealizedROI_index = 0;
|
|
4924
|
+
if (portfolio) {
|
|
4925
|
+
const { totalValue, totalCollateral } = portfolio;
|
|
4926
|
+
rows = rows.map((item) => {
|
|
4927
|
+
const est_liq_price = perp.positions.liqPrice({
|
|
4928
|
+
markPrice: item.mark_price,
|
|
4929
|
+
totalCollateral: totalCollateral.toNumber(),
|
|
4930
|
+
positionQty: item.position_qty,
|
|
4931
|
+
positions: rows,
|
|
4932
|
+
MMR: item.mmr
|
|
4933
|
+
});
|
|
4934
|
+
return {
|
|
4935
|
+
...item,
|
|
4936
|
+
est_liq_price
|
|
4894
4937
|
};
|
|
4938
|
+
});
|
|
4939
|
+
if (totalValue !== null && !totalValue.eq(utils.zero)) {
|
|
4940
|
+
totalUnrealizedROI = perp.account.totalUnrealizedROI({
|
|
4941
|
+
totalUnrealizedPnL: totalUnrealPnl,
|
|
4942
|
+
totalValue: totalValue.toNumber()
|
|
4943
|
+
});
|
|
4944
|
+
totalUnrealizedROI_index = perp.account.totalUnrealizedROI({
|
|
4945
|
+
totalUnrealizedPnL: totalUnrealPnl_index,
|
|
4946
|
+
totalValue: totalValue.toNumber()
|
|
4947
|
+
});
|
|
4895
4948
|
}
|
|
4896
4949
|
}
|
|
4897
|
-
return
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
4950
|
+
return {
|
|
4951
|
+
...data,
|
|
4952
|
+
unrealPnL: totalUnrealPnl,
|
|
4953
|
+
total_unreal_pnl: totalUnrealPnl,
|
|
4954
|
+
total_unreal_pnl_index: totalUnrealPnl_index,
|
|
4955
|
+
notional: notional_total.toNumber(),
|
|
4956
|
+
unsettledPnL: unsettlementPnL,
|
|
4957
|
+
total_unsettled_pnl: unsettlementPnL,
|
|
4958
|
+
unrealPnlROI: totalUnrealizedROI,
|
|
4959
|
+
unrealPnlROI_index: totalUnrealizedROI_index,
|
|
4960
|
+
rows
|
|
4961
|
+
};
|
|
4962
|
+
}
|
|
4963
|
+
preprocess(data) {
|
|
4964
|
+
let rows = data.rows;
|
|
4965
|
+
if (this.symbol !== AllPositions && Array.isArray(rows)) {
|
|
4966
|
+
rows = rows.filter((item) => item.symbol === this.symbol);
|
|
4908
4967
|
}
|
|
4909
|
-
|
|
4910
|
-
|
|
4911
|
-
|
|
4912
|
-
};
|
|
4913
|
-
const updateSelectedFavoriteTab = (tab) => {
|
|
4914
|
-
updateStore("lastSelectedFavoriteTab", tab);
|
|
4915
|
-
};
|
|
4916
|
-
const updateTabsSortState = (tabId, sortKey, sortOrder) => {
|
|
4917
|
-
const map = getStore("tabSort", {});
|
|
4918
|
-
map[tabId] = {
|
|
4919
|
-
sortKey,
|
|
4920
|
-
sortOrder
|
|
4968
|
+
return {
|
|
4969
|
+
...data,
|
|
4970
|
+
rows
|
|
4921
4971
|
};
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
markets || types.EMPTY_LIST,
|
|
4928
|
-
{
|
|
4929
|
-
favoriteTabs,
|
|
4930
|
-
favorites,
|
|
4931
|
-
recent,
|
|
4932
|
-
tabSort,
|
|
4933
|
-
addToHistory,
|
|
4934
|
-
updateFavorites,
|
|
4935
|
-
updateFavoriteTabs,
|
|
4936
|
-
updateSymbolFavoriteState,
|
|
4937
|
-
pinToTop,
|
|
4938
|
-
getLastSelFavTab,
|
|
4939
|
-
updateSelectedFavoriteTab,
|
|
4940
|
-
updateTabsSortState
|
|
4972
|
+
}
|
|
4973
|
+
getPosition(_, ctx) {
|
|
4974
|
+
const positions3 = ctx.get((output) => output[this.name]) || usePositionStore.getState().positions[this.symbol];
|
|
4975
|
+
if (this.symbol === AllPositions) {
|
|
4976
|
+
return positions3;
|
|
4941
4977
|
}
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
if (est_funding_rate === void 0 || est_funding_rate === null) {
|
|
4947
|
-
return null;
|
|
4978
|
+
if (positions3 && Array.isArray(positions3.rows)) {
|
|
4979
|
+
return positions3;
|
|
4980
|
+
}
|
|
4981
|
+
return this.preprocess(this.getAllPositions(ctx));
|
|
4948
4982
|
}
|
|
4949
|
-
|
|
4950
|
-
|
|
4983
|
+
destroy() {
|
|
4984
|
+
usePositionStore.getState().actions.closePosition(this.symbol);
|
|
4985
|
+
CalculatorContext.instance?.deleteByName(this.name);
|
|
4951
4986
|
}
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
function get24hChange2(close, open) {
|
|
4955
|
-
if (close !== void 0 && open !== void 0) {
|
|
4956
|
-
if (open === 0) {
|
|
4957
|
-
return 0;
|
|
4958
|
-
}
|
|
4959
|
-
return new utils.Decimal(close).minus(open).div(open).toNumber();
|
|
4987
|
+
getAllPositions(ctx) {
|
|
4988
|
+
return ctx.get((output) => output[AllPositions]) || usePositionStore.getState().positions[AllPositions];
|
|
4960
4989
|
}
|
|
4961
|
-
}
|
|
4962
|
-
|
|
4963
|
-
// src/orderly/useMarkPricesStream.ts
|
|
4964
|
-
var useMarkPricesStream = () => {
|
|
4965
|
-
const data = useMarkPriceStore((state) => state.markPrices);
|
|
4966
|
-
return { data };
|
|
4967
|
-
};
|
|
4968
|
-
|
|
4969
|
-
// src/orderly/useIndexPricesStream.ts
|
|
4970
|
-
var useIndexPricesStream = () => {
|
|
4971
|
-
const indexPrices = useIndexPriceStore((state) => state.indexPrices);
|
|
4972
|
-
const getIndexPrice = (token) => {
|
|
4973
|
-
if (token === "USDC") {
|
|
4974
|
-
return 1;
|
|
4975
|
-
}
|
|
4976
|
-
return indexPrices[`PERP_${token}_USDC`] ?? 0;
|
|
4977
|
-
};
|
|
4978
|
-
return {
|
|
4979
|
-
data: indexPrices,
|
|
4980
|
-
getIndexPrice: useMemoizedFn(getIndexPrice)
|
|
4981
|
-
};
|
|
4982
4990
|
};
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
const parts = 5;
|
|
4986
|
-
const step = (max2 - min2) / (parts - 1);
|
|
4987
|
-
const result = [];
|
|
4988
|
-
for (let i = 0; i < parts; i++) {
|
|
4989
|
-
result.push(Math.floor(min2 + step * i));
|
|
4990
|
-
}
|
|
4991
|
-
return result;
|
|
4991
|
+
PositionCalculator.logPosition = (symbol = "all") => {
|
|
4992
|
+
return usePositionStore.getState().positions[symbol];
|
|
4992
4993
|
};
|
|
4993
|
-
var
|
|
4994
|
-
const
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4994
|
+
var parseHolding = (holding, indexPrices, tokensInfo) => {
|
|
4995
|
+
const nonUSDC = [];
|
|
4996
|
+
let USDC_holding = 0;
|
|
4997
|
+
holding.forEach((item) => {
|
|
4998
|
+
if (item.token === "USDC") {
|
|
4999
|
+
USDC_holding = item.holding;
|
|
5000
|
+
} else {
|
|
5001
|
+
const tokenInfo = tokensInfo.find(({ token }) => token === item.token);
|
|
5002
|
+
const {
|
|
5003
|
+
base_weight = 0,
|
|
5004
|
+
discount_factor = 0,
|
|
5005
|
+
user_max_qty = 0
|
|
5006
|
+
} = tokenInfo || {};
|
|
5007
|
+
const holdingQty = item?.holding ?? 0;
|
|
5008
|
+
const indexPrice = indexPrices[`PERP_${item.token}_USDC`] ?? 0;
|
|
5009
|
+
const collateralRatio4 = perp.account.collateralRatio({
|
|
5010
|
+
baseWeight: base_weight,
|
|
5011
|
+
discountFactor: discount_factor,
|
|
5012
|
+
collateralQty: holdingQty,
|
|
5013
|
+
collateralCap: user_max_qty,
|
|
5014
|
+
indexPrice
|
|
5015
|
+
});
|
|
5016
|
+
nonUSDC.push({
|
|
5017
|
+
holding: holdingQty,
|
|
5018
|
+
indexPrice,
|
|
5019
|
+
collateralCap: user_max_qty,
|
|
5020
|
+
collateralRatio: collateralRatio4
|
|
5021
|
+
});
|
|
4998
5022
|
}
|
|
4999
|
-
);
|
|
5000
|
-
const [update, { isMutating }] = useMutation("/v1/client/leverage");
|
|
5001
|
-
const { data: leverageConfig, isLoading } = useQuery("/v1/public/leverage", {
|
|
5002
|
-
revalidateOnFocus: false,
|
|
5003
|
-
errorRetryCount: 3
|
|
5004
|
-
// formatter: (data) => data,
|
|
5005
5023
|
});
|
|
5006
|
-
|
|
5007
|
-
async (data2) => {
|
|
5008
|
-
const res = await update(data2);
|
|
5009
|
-
if (res.success) {
|
|
5010
|
-
return mutate6();
|
|
5011
|
-
} else {
|
|
5012
|
-
throw new Error(res.message);
|
|
5013
|
-
}
|
|
5014
|
-
},
|
|
5015
|
-
[update, mutate6]
|
|
5016
|
-
);
|
|
5017
|
-
const memoizedCurLeverage = React2.useMemo(() => {
|
|
5018
|
-
if (data?.max_leverage !== void 0) {
|
|
5019
|
-
return Number(data.max_leverage);
|
|
5020
|
-
}
|
|
5021
|
-
return 1;
|
|
5022
|
-
}, [data?.max_leverage]);
|
|
5023
|
-
const memoizedMaxLeverage = React2.useMemo(() => {
|
|
5024
|
-
if (leverageConfig?.max_futures_leverage !== void 0) {
|
|
5025
|
-
return Number(leverageConfig.max_futures_leverage);
|
|
5026
|
-
}
|
|
5027
|
-
return 1;
|
|
5028
|
-
}, [leverageConfig?.max_futures_leverage]);
|
|
5029
|
-
const memoizedLeverageLevers = React2.useMemo(() => {
|
|
5030
|
-
return generateLeverageLevers(memoizedMaxLeverage);
|
|
5031
|
-
}, [memoizedMaxLeverage]);
|
|
5032
|
-
return {
|
|
5033
|
-
update: updateLeverage,
|
|
5034
|
-
isLoading: isLoading || isMutating,
|
|
5035
|
-
leverageLevers: memoizedLeverageLevers,
|
|
5036
|
-
curLeverage: memoizedCurLeverage,
|
|
5037
|
-
maxLeverage: memoizedMaxLeverage
|
|
5038
|
-
};
|
|
5024
|
+
return [USDC_holding, nonUSDC];
|
|
5039
5025
|
};
|
|
5040
5026
|
|
|
5041
|
-
// src/orderly/
|
|
5042
|
-
var
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
const { input, token } = options;
|
|
5048
|
-
const isUSDC = token?.toUpperCase() === "USDC";
|
|
5049
|
-
const tokensInfo = useTokensInfo();
|
|
5050
|
-
const { usdc, data: holdingList = [] } = useHoldingStream();
|
|
5051
|
-
const { getIndexPrice } = useIndexPricesStream();
|
|
5052
|
-
const { unsettledPnL } = useCollateral();
|
|
5053
|
-
const usdcBalance = React2.useMemo(() => {
|
|
5054
|
-
if (isUSDC && input) {
|
|
5055
|
-
return new utils.Decimal(usdc?.holding ?? 0).add(input).toNumber();
|
|
5056
|
-
}
|
|
5057
|
-
return usdc?.holding ?? 0;
|
|
5058
|
-
}, [usdc?.holding, input, isUSDC]);
|
|
5059
|
-
const getAdjustedQty = React2.useCallback(
|
|
5060
|
-
(item) => {
|
|
5061
|
-
if (input && item.token === token) {
|
|
5062
|
-
return new utils.Decimal(item?.holding ?? 0).add(input).toNumber();
|
|
5063
|
-
}
|
|
5064
|
-
return item?.holding ?? 0;
|
|
5065
|
-
},
|
|
5066
|
-
[input, token]
|
|
5067
|
-
);
|
|
5068
|
-
const memoizedLTV = React2.useMemo(() => {
|
|
5069
|
-
return LTV({
|
|
5070
|
-
usdcBalance,
|
|
5071
|
-
upnl: unsettledPnL,
|
|
5072
|
-
assets: holdingList.filter((h) => h.token.toUpperCase() !== "USDC").map((item) => {
|
|
5073
|
-
const indexPrice = getIndexPrice(item.token);
|
|
5074
|
-
const findToken = tokensInfo?.find((i) => i.token === item.token);
|
|
5075
|
-
const qty = getAdjustedQty(item);
|
|
5076
|
-
const weight = collateralRatio({
|
|
5077
|
-
baseWeight: findToken?.base_weight ?? 0,
|
|
5078
|
-
discountFactor: findToken?.discount_factor ?? 0,
|
|
5079
|
-
collateralCap: findToken?.user_max_qty ?? qty,
|
|
5080
|
-
collateralQty: qty,
|
|
5081
|
-
indexPrice
|
|
5082
|
-
});
|
|
5083
|
-
return {
|
|
5084
|
-
qty,
|
|
5085
|
-
indexPrice,
|
|
5086
|
-
weight: weight.toNumber()
|
|
5087
|
-
};
|
|
5088
|
-
})
|
|
5089
|
-
});
|
|
5090
|
-
}, [
|
|
5091
|
-
usdcBalance,
|
|
5092
|
-
unsettledPnL,
|
|
5093
|
-
holdingList,
|
|
5094
|
-
tokensInfo,
|
|
5095
|
-
getIndexPrice,
|
|
5096
|
-
getAdjustedQty
|
|
5097
|
-
]);
|
|
5098
|
-
if (new utils.Decimal(usdcBalance).add(new utils.Decimal(unsettledPnL)).gte(utils.zero)) {
|
|
5099
|
-
return 0;
|
|
5100
|
-
}
|
|
5101
|
-
return new utils.Decimal(memoizedLTV).mul(100).toDecimalPlaces(2, utils.Decimal.ROUND_DOWN).toNumber();
|
|
5102
|
-
};
|
|
5103
|
-
var useFundingRate = (symbol) => {
|
|
5104
|
-
if (!symbol) {
|
|
5105
|
-
throw new types.SDKError("Symbol is required");
|
|
5027
|
+
// src/orderly/calculator/indexPrice.ts
|
|
5028
|
+
var IndexPriceCalculatorName = "indexPriceCalculator";
|
|
5029
|
+
var IndexPriceCalculator = class extends BaseCalculator {
|
|
5030
|
+
constructor() {
|
|
5031
|
+
super(...arguments);
|
|
5032
|
+
this.name = IndexPriceCalculatorName;
|
|
5106
5033
|
}
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
fallbackData: {
|
|
5113
|
-
est_funding_rate: 0,
|
|
5114
|
-
next_funing_time: 0
|
|
5115
|
-
}
|
|
5116
|
-
}
|
|
5117
|
-
);
|
|
5118
|
-
React2.useEffect(() => {
|
|
5119
|
-
if (!data || isLoading) {
|
|
5034
|
+
calc(scope, data, ctx) {
|
|
5035
|
+
return data;
|
|
5036
|
+
}
|
|
5037
|
+
update(data) {
|
|
5038
|
+
if (!data)
|
|
5120
5039
|
return;
|
|
5040
|
+
useIndexPriceStore.getState().actions.updateIndexPrice(data);
|
|
5041
|
+
}
|
|
5042
|
+
static getValue() {
|
|
5043
|
+
return useIndexPriceStore.getState().indexPrices;
|
|
5044
|
+
}
|
|
5045
|
+
};
|
|
5046
|
+
|
|
5047
|
+
// src/orderly/calculator/portfolio.ts
|
|
5048
|
+
var PortfolioCalculatorName = "portfolio";
|
|
5049
|
+
var PortfolioCalculator = class extends BaseCalculator {
|
|
5050
|
+
constructor() {
|
|
5051
|
+
super(...arguments);
|
|
5052
|
+
this.name = PortfolioCalculatorName;
|
|
5053
|
+
}
|
|
5054
|
+
calc(scope, data, ctx) {
|
|
5055
|
+
let markPrices;
|
|
5056
|
+
let indexPrices;
|
|
5057
|
+
const portfolio = this.getPortfolio(ctx);
|
|
5058
|
+
if (scope === "markPrice" /* MARK_PRICE */) {
|
|
5059
|
+
markPrices = data;
|
|
5060
|
+
} else {
|
|
5061
|
+
markPrices = ctx.get(
|
|
5062
|
+
(cache) => cache[MarketCalculatorName]
|
|
5063
|
+
);
|
|
5121
5064
|
}
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
|
-
|
|
5065
|
+
if (scope === "indexPrice" /* INDEX_PRICE */) {
|
|
5066
|
+
indexPrices = data;
|
|
5067
|
+
} else {
|
|
5068
|
+
indexPrices = ctx.get(
|
|
5069
|
+
(cache) => cache[IndexPriceCalculatorName]
|
|
5070
|
+
);
|
|
5125
5071
|
}
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
clearInterval(timerRef.current);
|
|
5072
|
+
const positions3 = ctx.get(
|
|
5073
|
+
(output) => output.positionCalculator_all
|
|
5074
|
+
);
|
|
5075
|
+
let holding = portfolio.holding;
|
|
5076
|
+
if (scope === "portfolio" /* PORTFOLIO */ && data.holding && Array.isArray(holding)) {
|
|
5077
|
+
if (Array.isArray(data.holding)) {
|
|
5078
|
+
holding = data.holding;
|
|
5079
|
+
} else {
|
|
5080
|
+
holding = holding.map((item) => {
|
|
5081
|
+
if (data.holding[item.token]) {
|
|
5082
|
+
return {
|
|
5083
|
+
...item,
|
|
5084
|
+
holding: data.holding[item.token].holding,
|
|
5085
|
+
frozen: data.holding[item.token].frozen
|
|
5086
|
+
};
|
|
5087
|
+
}
|
|
5088
|
+
return item;
|
|
5089
|
+
});
|
|
5145
5090
|
}
|
|
5146
|
-
};
|
|
5147
|
-
}, [data, isLoading]);
|
|
5148
|
-
const est_funding_rate = React2.useMemo(() => {
|
|
5149
|
-
if (!data) {
|
|
5150
|
-
return;
|
|
5151
5091
|
}
|
|
5152
|
-
const
|
|
5153
|
-
|
|
5092
|
+
const accountInfo = ctx.accountInfo;
|
|
5093
|
+
const symbolsInfo = ctx.symbolsInfo;
|
|
5094
|
+
const tokensInfo = ctx.tokensInfo;
|
|
5095
|
+
return this.format({
|
|
5096
|
+
holding,
|
|
5097
|
+
positions: positions3,
|
|
5098
|
+
markPrices,
|
|
5099
|
+
accountInfo,
|
|
5100
|
+
symbolsInfo,
|
|
5101
|
+
indexPrices,
|
|
5102
|
+
tokensInfo: tokensInfo ?? types.EMPTY_LIST
|
|
5103
|
+
});
|
|
5104
|
+
}
|
|
5105
|
+
getPortfolio(ctx) {
|
|
5106
|
+
return ctx.get((output) => output[this.name]) || useAppStore.getState().portfolio;
|
|
5107
|
+
}
|
|
5108
|
+
format(inputs) {
|
|
5109
|
+
const {
|
|
5110
|
+
holding,
|
|
5111
|
+
positions: positions3,
|
|
5112
|
+
markPrices,
|
|
5113
|
+
indexPrices,
|
|
5114
|
+
accountInfo,
|
|
5115
|
+
symbolsInfo,
|
|
5116
|
+
tokensInfo
|
|
5117
|
+
} = inputs;
|
|
5118
|
+
if (!holding || !positions3 || !Array.isArray(positions3.rows) || !markPrices || !indexPrices || !accountInfo) {
|
|
5154
5119
|
return null;
|
|
5155
5120
|
}
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5121
|
+
const unsettledPnL = ramda.pathOr(0, ["total_unsettled_pnl"])(positions3);
|
|
5122
|
+
const unrealizedPnL = ramda.pathOr(0, ["total_unreal_pnl"])(positions3);
|
|
5123
|
+
const [USDC_holding, nonUSDC] = parseHolding(
|
|
5124
|
+
holding,
|
|
5125
|
+
indexPrices,
|
|
5126
|
+
tokensInfo
|
|
5159
5127
|
);
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5128
|
+
const usdc = holding.find((item) => item.token === "USDC");
|
|
5129
|
+
const totalCollateral = perp.account.totalCollateral({
|
|
5130
|
+
USDCHolding: USDC_holding,
|
|
5131
|
+
nonUSDCHolding: nonUSDC,
|
|
5132
|
+
unsettlementPnL: unsettledPnL
|
|
5133
|
+
});
|
|
5134
|
+
const totalValue = perp.account.totalValue({
|
|
5135
|
+
totalUnsettlementPnL: unsettledPnL,
|
|
5136
|
+
USDCHolding: USDC_holding,
|
|
5137
|
+
nonUSDCHolding: nonUSDC
|
|
5138
|
+
});
|
|
5139
|
+
const totalUnrealizedROI = perp.account.totalUnrealizedROI({
|
|
5140
|
+
totalUnrealizedPnL: unrealizedPnL,
|
|
5141
|
+
totalValue: totalValue.toNumber()
|
|
5142
|
+
});
|
|
5143
|
+
const totalInitialMarginWithOrders = perp.account.totalInitialMarginWithQty({
|
|
5144
|
+
positions: positions3.rows,
|
|
5145
|
+
markPrices,
|
|
5146
|
+
IMR_Factors: accountInfo.imr_factor,
|
|
5147
|
+
maxLeverage: accountInfo.max_leverage,
|
|
5148
|
+
symbolInfo: createGetter({ ...symbolsInfo })
|
|
5149
|
+
});
|
|
5150
|
+
const freeCollateral = perp.account.freeCollateral({
|
|
5151
|
+
totalCollateral,
|
|
5152
|
+
totalInitialMarginWithOrders
|
|
5153
|
+
});
|
|
5154
|
+
const availableBalance = perp.account.availableBalance({
|
|
5155
|
+
USDCHolding: usdc?.holding ?? 0,
|
|
5156
|
+
unsettlementPnL: positions3.total_unsettled_pnl ?? 0
|
|
5157
|
+
});
|
|
5158
|
+
return {
|
|
5159
|
+
totalCollateral,
|
|
5160
|
+
totalValue,
|
|
5161
|
+
totalUnrealizedROI,
|
|
5162
|
+
freeCollateral,
|
|
5163
|
+
availableBalance,
|
|
5164
|
+
unsettledPnL,
|
|
5165
|
+
holding
|
|
5166
|
+
};
|
|
5170
5167
|
}
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5168
|
+
update(data, scope) {
|
|
5169
|
+
if (data) {
|
|
5170
|
+
useAppStore.getState().actions.batchUpdateForPortfolio({
|
|
5171
|
+
totalCollateral: data.totalCollateral,
|
|
5172
|
+
totalValue: data.totalValue,
|
|
5173
|
+
freeCollateral: data.freeCollateral,
|
|
5174
|
+
availableBalance: data.availableBalance,
|
|
5175
|
+
totalUnrealizedROI: data.totalUnrealizedROI,
|
|
5176
|
+
unsettledPnL: data.unsettledPnL,
|
|
5177
|
+
holding: Array.isArray(data.holding) ? data.holding : []
|
|
5178
|
+
});
|
|
5179
|
+
}
|
|
5179
5180
|
}
|
|
5180
|
-
const daysMap = {
|
|
5181
|
-
"1d": 1,
|
|
5182
|
-
"3d": 3,
|
|
5183
|
-
"7d": 7,
|
|
5184
|
-
"14d": 14,
|
|
5185
|
-
"30d": 30,
|
|
5186
|
-
"90d": 90
|
|
5187
|
-
};
|
|
5188
|
-
const totalTimes = daysMap[period] * 3;
|
|
5189
|
-
return periodData.positive / totalTimes;
|
|
5190
5181
|
};
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
);
|
|
5195
|
-
const
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
|
-
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5182
|
+
|
|
5183
|
+
// src/useCalculatorService.ts
|
|
5184
|
+
var useCalculatorService = () => {
|
|
5185
|
+
const { get: get3 } = useSimpleDI();
|
|
5186
|
+
const calculatorService = useConstant__default.default(() => {
|
|
5187
|
+
let calculatorService2 = get3(CalculatorServiceID);
|
|
5188
|
+
if (!calculatorService2) {
|
|
5189
|
+
const positionCalculator = new PositionCalculator();
|
|
5190
|
+
const portfolioCalculator = new PortfolioCalculator();
|
|
5191
|
+
const markPriceCalculator = new MarkPriceCalculator();
|
|
5192
|
+
const indexPriceCalculator = new IndexPriceCalculator();
|
|
5193
|
+
calculatorService2 = new CalculatorService(new ShardingScheduler(), [
|
|
5194
|
+
[
|
|
5195
|
+
"markPrice" /* MARK_PRICE */,
|
|
5196
|
+
[
|
|
5197
|
+
markPriceCalculator,
|
|
5198
|
+
positionCalculator,
|
|
5199
|
+
portfolioCalculator,
|
|
5200
|
+
positionCalculator
|
|
5201
|
+
]
|
|
5202
|
+
],
|
|
5203
|
+
["position" /* POSITION */, [positionCalculator, portfolioCalculator]],
|
|
5204
|
+
["portfolio" /* PORTFOLIO */, [portfolioCalculator]],
|
|
5205
|
+
// indexPrice
|
|
5206
|
+
[
|
|
5207
|
+
"indexPrice" /* INDEX_PRICE */,
|
|
5208
|
+
[indexPriceCalculator, positionCalculator]
|
|
5209
|
+
]
|
|
5210
|
+
]);
|
|
5211
|
+
core.SimpleDI.registerByName(CalculatorServiceID, calculatorService2);
|
|
5212
|
+
}
|
|
5213
|
+
return calculatorService2;
|
|
5214
|
+
});
|
|
5215
|
+
return calculatorService;
|
|
5220
5216
|
};
|
|
5217
|
+
|
|
5218
|
+
// src/orderly/usePositionStream/usePositionStream.ts
|
|
5221
5219
|
var scopes = [
|
|
5222
5220
|
"position" /* POSITION */,
|
|
5223
5221
|
"markPrice" /* MARK_PRICE */,
|
|
@@ -7143,6 +7141,252 @@ var useSettleSubscription = (options) => {
|
|
|
7143
7141
|
}
|
|
7144
7142
|
);
|
|
7145
7143
|
};
|
|
7144
|
+
var usePrivateDataObserver = (options) => {
|
|
7145
|
+
const ws = useWS();
|
|
7146
|
+
const ee = useEventEmitter();
|
|
7147
|
+
const { state, account: account9 } = useAccount();
|
|
7148
|
+
const { setAccountInfo, restoreHolding, cleanAll } = useAppStore(
|
|
7149
|
+
(state2) => state2.actions
|
|
7150
|
+
);
|
|
7151
|
+
const statusActions = useApiStatusActions();
|
|
7152
|
+
const calculatorService = useCalculatorService();
|
|
7153
|
+
const positionsActions = usePositionActions();
|
|
7154
|
+
const { data: clientInfo } = usePrivateQuery(
|
|
7155
|
+
"/v1/client/info",
|
|
7156
|
+
{
|
|
7157
|
+
revalidateOnFocus: false
|
|
7158
|
+
}
|
|
7159
|
+
);
|
|
7160
|
+
React2.useEffect(() => {
|
|
7161
|
+
if (clientInfo) {
|
|
7162
|
+
setAccountInfo(clientInfo);
|
|
7163
|
+
}
|
|
7164
|
+
}, [clientInfo, setAccountInfo]);
|
|
7165
|
+
const { data: positions3, isLoading: isPositionLoading } = usePrivateQuery("/v1/positions", {
|
|
7166
|
+
formatter: (data) => data,
|
|
7167
|
+
onError: (error) => {
|
|
7168
|
+
statusActions.updateApiError("positions", error.message);
|
|
7169
|
+
}
|
|
7170
|
+
// revalidateOnFocus: false,
|
|
7171
|
+
});
|
|
7172
|
+
React2.useEffect(() => {
|
|
7173
|
+
const handler = (state2) => {
|
|
7174
|
+
if (!state2.accountId) {
|
|
7175
|
+
calculatorService.stop();
|
|
7176
|
+
cleanAll();
|
|
7177
|
+
positionsActions.clearAll();
|
|
7178
|
+
}
|
|
7179
|
+
};
|
|
7180
|
+
account9.on(core.EVENT_NAMES.statusChanged, handler);
|
|
7181
|
+
return () => {
|
|
7182
|
+
account9.off(core.EVENT_NAMES.statusChanged, handler);
|
|
7183
|
+
};
|
|
7184
|
+
}, []);
|
|
7185
|
+
React2.useEffect(() => {
|
|
7186
|
+
if (isPositionLoading) {
|
|
7187
|
+
statusActions.updateApiLoading("positions", isPositionLoading);
|
|
7188
|
+
}
|
|
7189
|
+
}, [isPositionLoading, statusActions]);
|
|
7190
|
+
React2.useEffect(() => {
|
|
7191
|
+
if (positions3 && Array.isArray(positions3.rows)) {
|
|
7192
|
+
calculatorService.calc("position" /* POSITION */, positions3);
|
|
7193
|
+
}
|
|
7194
|
+
}, [calculatorService, positions3]);
|
|
7195
|
+
const { data: holding } = usePrivateQuery(
|
|
7196
|
+
"/v1/client/holding",
|
|
7197
|
+
{
|
|
7198
|
+
formatter: (data) => data.holding
|
|
7199
|
+
// revalidateOnFocus: false,
|
|
7200
|
+
}
|
|
7201
|
+
);
|
|
7202
|
+
React2.useEffect(() => {
|
|
7203
|
+
if (!account9.accountId)
|
|
7204
|
+
return;
|
|
7205
|
+
const unsubscribe = ws.privateSubscribe(
|
|
7206
|
+
{
|
|
7207
|
+
id: "balance",
|
|
7208
|
+
event: "subscribe",
|
|
7209
|
+
topic: "balance",
|
|
7210
|
+
ts: Date.now()
|
|
7211
|
+
},
|
|
7212
|
+
{
|
|
7213
|
+
onMessage: (data) => {
|
|
7214
|
+
const holding2 = data?.balances ?? {};
|
|
7215
|
+
if (holding2) {
|
|
7216
|
+
calculatorService.calc("portfolio" /* PORTFOLIO */, { holding: holding2 });
|
|
7217
|
+
}
|
|
7218
|
+
}
|
|
7219
|
+
}
|
|
7220
|
+
);
|
|
7221
|
+
return () => unsubscribe?.();
|
|
7222
|
+
}, [account9.accountId]);
|
|
7223
|
+
const isHoldingInit = React2.useRef(false);
|
|
7224
|
+
React2.useEffect(() => {
|
|
7225
|
+
isHoldingInit.current = false;
|
|
7226
|
+
}, [state.address]);
|
|
7227
|
+
React2.useEffect(() => {
|
|
7228
|
+
if (!holding) {
|
|
7229
|
+
return;
|
|
7230
|
+
}
|
|
7231
|
+
if (isHoldingInit.current) {
|
|
7232
|
+
calculatorService.calc("portfolio" /* PORTFOLIO */, { holding });
|
|
7233
|
+
} else {
|
|
7234
|
+
restoreHolding(holding);
|
|
7235
|
+
}
|
|
7236
|
+
isHoldingInit.current = true;
|
|
7237
|
+
}, [holding]);
|
|
7238
|
+
const [subOrder] = useLocalStorage("orderly_subscribe_order", true);
|
|
7239
|
+
const updateOrders = (data, isAlgoOrder) => {
|
|
7240
|
+
const keysMap = options.getKeysMap("orders");
|
|
7241
|
+
const filteredKeys = /* @__PURE__ */ new Map();
|
|
7242
|
+
const keyStartWith = isAlgoOrder ? "algoOrders" : "orders";
|
|
7243
|
+
const keys = keysMap.keys();
|
|
7244
|
+
for (const key of keys) {
|
|
7245
|
+
if (key.startsWith(keyStartWith)) {
|
|
7246
|
+
filteredKeys.set(key, keysMap.get(key));
|
|
7247
|
+
}
|
|
7248
|
+
}
|
|
7249
|
+
let fieldChanges = {};
|
|
7250
|
+
filteredKeys.forEach((getKey, key) => {
|
|
7251
|
+
useSWR.mutate(
|
|
7252
|
+
useSWRInfinite.unstable_serialize((index, prevData) => [
|
|
7253
|
+
getKey(index, prevData),
|
|
7254
|
+
state.accountId
|
|
7255
|
+
]),
|
|
7256
|
+
(prevData) => {
|
|
7257
|
+
try {
|
|
7258
|
+
if (isAlgoOrder) {
|
|
7259
|
+
const res = updateAlgoOrdersHandler(
|
|
7260
|
+
key,
|
|
7261
|
+
data,
|
|
7262
|
+
prevData
|
|
7263
|
+
);
|
|
7264
|
+
fieldChanges = res?.fieldChanges || {};
|
|
7265
|
+
return res?.mergedOrders;
|
|
7266
|
+
}
|
|
7267
|
+
return updateOrdersHandler(key, data, prevData);
|
|
7268
|
+
} catch (error) {
|
|
7269
|
+
return prevData;
|
|
7270
|
+
}
|
|
7271
|
+
},
|
|
7272
|
+
{
|
|
7273
|
+
revalidate: false
|
|
7274
|
+
}
|
|
7275
|
+
);
|
|
7276
|
+
});
|
|
7277
|
+
const formattedData = isAlgoOrder ? AlgoOrderMergeHandler.groupOrders(data) : object2underscore(data);
|
|
7278
|
+
ee.emit("orders:changed", {
|
|
7279
|
+
...formattedData,
|
|
7280
|
+
status: isAlgoOrder ? formattedData.algo_status : data.status,
|
|
7281
|
+
// custom field name
|
|
7282
|
+
fieldChanges
|
|
7283
|
+
});
|
|
7284
|
+
};
|
|
7285
|
+
React2.useEffect(() => {
|
|
7286
|
+
if (!state.accountId) {
|
|
7287
|
+
return;
|
|
7288
|
+
}
|
|
7289
|
+
if (subOrder !== true) {
|
|
7290
|
+
return;
|
|
7291
|
+
}
|
|
7292
|
+
const unsubscribe = ws.privateSubscribe("executionreport", {
|
|
7293
|
+
onMessage: (data) => {
|
|
7294
|
+
updateOrders(data, false);
|
|
7295
|
+
}
|
|
7296
|
+
});
|
|
7297
|
+
return () => unsubscribe?.();
|
|
7298
|
+
}, [state.accountId, subOrder]);
|
|
7299
|
+
React2.useEffect(() => {
|
|
7300
|
+
if (!state.accountId)
|
|
7301
|
+
return;
|
|
7302
|
+
if (subOrder !== true)
|
|
7303
|
+
return;
|
|
7304
|
+
const unsubscribe = ws.privateSubscribe("algoexecutionreport", {
|
|
7305
|
+
onMessage: (data) => {
|
|
7306
|
+
updateOrders(data, true);
|
|
7307
|
+
}
|
|
7308
|
+
});
|
|
7309
|
+
return () => unsubscribe?.();
|
|
7310
|
+
}, [state.accountId, subOrder]);
|
|
7311
|
+
React2.useEffect(() => {
|
|
7312
|
+
if (!state.accountId)
|
|
7313
|
+
return;
|
|
7314
|
+
const key = ["/v1/positions", state.accountId];
|
|
7315
|
+
const unsubscribe = ws.privateSubscribe("account", {
|
|
7316
|
+
onMessage: (data) => {
|
|
7317
|
+
const { symbol, leverage } = data?.accountDetail?.symbolLeverage || {};
|
|
7318
|
+
if (symbol && leverage) {
|
|
7319
|
+
useSWR.mutate(
|
|
7320
|
+
key,
|
|
7321
|
+
(prevPositions) => {
|
|
7322
|
+
if (prevPositions?.rows?.length) {
|
|
7323
|
+
return {
|
|
7324
|
+
...prevPositions,
|
|
7325
|
+
rows: prevPositions.rows.map((row) => {
|
|
7326
|
+
return row.symbol === symbol ? { ...row, leverage } : row;
|
|
7327
|
+
})
|
|
7328
|
+
};
|
|
7329
|
+
}
|
|
7330
|
+
return prevPositions;
|
|
7331
|
+
},
|
|
7332
|
+
{
|
|
7333
|
+
revalidate: false
|
|
7334
|
+
}
|
|
7335
|
+
);
|
|
7336
|
+
}
|
|
7337
|
+
}
|
|
7338
|
+
});
|
|
7339
|
+
return () => unsubscribe?.();
|
|
7340
|
+
}, [state.accountId]);
|
|
7341
|
+
React2.useEffect(() => {
|
|
7342
|
+
if (!state.accountId) {
|
|
7343
|
+
return;
|
|
7344
|
+
}
|
|
7345
|
+
const key = ["/v1/positions", state.accountId];
|
|
7346
|
+
const unsubscribe = ws.privateSubscribe("position", {
|
|
7347
|
+
onMessage: (data) => {
|
|
7348
|
+
const { positions: nextPositions } = data;
|
|
7349
|
+
useSWR.mutate(
|
|
7350
|
+
key,
|
|
7351
|
+
(prevPositions) => {
|
|
7352
|
+
if (!!prevPositions) {
|
|
7353
|
+
const newPositions = {
|
|
7354
|
+
...prevPositions,
|
|
7355
|
+
rows: prevPositions.rows.map((row) => {
|
|
7356
|
+
const itemIndex = nextPositions.findIndex(
|
|
7357
|
+
(item) => item.symbol === row.symbol
|
|
7358
|
+
);
|
|
7359
|
+
if (itemIndex >= 0) {
|
|
7360
|
+
const itemArr = nextPositions.splice(itemIndex, 1);
|
|
7361
|
+
const item = itemArr[0];
|
|
7362
|
+
if (item.averageOpenPrice === 0 && item.positionQty !== 0) {
|
|
7363
|
+
return row;
|
|
7364
|
+
}
|
|
7365
|
+
return object2underscore(item);
|
|
7366
|
+
}
|
|
7367
|
+
return row;
|
|
7368
|
+
})
|
|
7369
|
+
};
|
|
7370
|
+
if (nextPositions.length > 0) {
|
|
7371
|
+
newPositions.rows = [
|
|
7372
|
+
...newPositions.rows,
|
|
7373
|
+
...nextPositions.map(object2underscore)
|
|
7374
|
+
];
|
|
7375
|
+
}
|
|
7376
|
+
return newPositions;
|
|
7377
|
+
}
|
|
7378
|
+
},
|
|
7379
|
+
{
|
|
7380
|
+
revalidate: false
|
|
7381
|
+
}
|
|
7382
|
+
);
|
|
7383
|
+
}
|
|
7384
|
+
});
|
|
7385
|
+
return () => {
|
|
7386
|
+
unsubscribe?.();
|
|
7387
|
+
};
|
|
7388
|
+
}, [state.accountId]);
|
|
7389
|
+
};
|
|
7146
7390
|
var useSymbolPriceRange = (symbol, side, price) => {
|
|
7147
7391
|
const config = useSymbolsInfo();
|
|
7148
7392
|
const priceRange = config?.[symbol]("price_range");
|
|
@@ -7595,12 +7839,12 @@ async function bracketOrderValidator(values, config) {
|
|
|
7595
7839
|
const result = /* @__PURE__ */ Object.create(null);
|
|
7596
7840
|
await Promise.resolve();
|
|
7597
7841
|
const {
|
|
7598
|
-
tp_enable,
|
|
7842
|
+
// tp_enable,
|
|
7843
|
+
// sl_enable,
|
|
7599
7844
|
tp_trigger_price,
|
|
7600
7845
|
tp_order_price,
|
|
7601
7846
|
tp_order_type,
|
|
7602
7847
|
sl_trigger_price,
|
|
7603
|
-
sl_enable,
|
|
7604
7848
|
sl_order_price,
|
|
7605
7849
|
sl_order_type,
|
|
7606
7850
|
side
|
|
@@ -7620,12 +7864,6 @@ async function bracketOrderValidator(values, config) {
|
|
|
7620
7864
|
if (Number(sl_trigger_price) < 0) {
|
|
7621
7865
|
result.sl_trigger_price = OrderValidation.min("sl_trigger_price", 0);
|
|
7622
7866
|
}
|
|
7623
|
-
if (tp_enable && !tp_trigger_price) {
|
|
7624
|
-
result.tp_trigger_price = OrderValidation.required("tp_trigger_price");
|
|
7625
|
-
}
|
|
7626
|
-
if (sl_enable && !sl_trigger_price) {
|
|
7627
|
-
result.sl_trigger_price = OrderValidation.required("sl_trigger_price");
|
|
7628
|
-
}
|
|
7629
7867
|
if (tp_order_type === types.OrderType.LIMIT && !tp_order_price) {
|
|
7630
7868
|
result.tp_order_price = OrderValidation.required("tp_order_price");
|
|
7631
7869
|
}
|
|
@@ -8445,8 +8683,8 @@ var BaseAlgoOrderCreator = class {
|
|
|
8445
8683
|
tp_trigger_price,
|
|
8446
8684
|
sl_trigger_price,
|
|
8447
8685
|
side,
|
|
8448
|
-
tp_enable,
|
|
8449
|
-
sl_enable,
|
|
8686
|
+
// tp_enable,
|
|
8687
|
+
// sl_enable,
|
|
8450
8688
|
tp_order_type,
|
|
8451
8689
|
sl_order_type,
|
|
8452
8690
|
tp_order_price,
|
|
@@ -8475,12 +8713,6 @@ var BaseAlgoOrderCreator = class {
|
|
|
8475
8713
|
if (Number(sl_trigger_price) < 0) {
|
|
8476
8714
|
result.sl_trigger_price = OrderValidation.min("sl_trigger_price", 0);
|
|
8477
8715
|
}
|
|
8478
|
-
if (tp_enable && !tp_trigger_price) {
|
|
8479
|
-
result.tp_trigger_price = OrderValidation.required("tp_trigger_price");
|
|
8480
|
-
}
|
|
8481
|
-
if (sl_enable && !sl_trigger_price) {
|
|
8482
|
-
result.sl_trigger_price = OrderValidation.required("sl_trigger_price");
|
|
8483
|
-
}
|
|
8484
8716
|
if (tp_order_type === types.OrderType.LIMIT && !tp_order_price) {
|
|
8485
8717
|
result.tp_order_price = OrderValidation.required("tp_order_price");
|
|
8486
8718
|
}
|
|
@@ -8991,9 +9223,6 @@ var tpslFields = [
|
|
|
8991
9223
|
"sl_offset_percentage"
|
|
8992
9224
|
];
|
|
8993
9225
|
var isBracketOrder = (order) => {
|
|
8994
|
-
if (order.sl_enable || order.tp_enable) {
|
|
8995
|
-
return true;
|
|
8996
|
-
}
|
|
8997
9226
|
return !!order.tp_trigger_price || !!order.sl_trigger_price;
|
|
8998
9227
|
};
|
|
8999
9228
|
var hasTPSL = (order) => {
|
|
@@ -9523,28 +9752,6 @@ function useSubAccountMaxWithdrawal(options) {
|
|
|
9523
9752
|
}
|
|
9524
9753
|
|
|
9525
9754
|
// src/orderly/useTakeProfitAndStopLoss/useTPSL.ts
|
|
9526
|
-
var checkIsEnableTpSL = (order) => {
|
|
9527
|
-
const result = {
|
|
9528
|
-
tp_enable: true,
|
|
9529
|
-
sl_enable: true
|
|
9530
|
-
};
|
|
9531
|
-
if (!order) {
|
|
9532
|
-
return result;
|
|
9533
|
-
}
|
|
9534
|
-
const tp = order.child_orders.find(
|
|
9535
|
-
(o) => o.algo_type === types.AlgoOrderType.TAKE_PROFIT && o.is_activated
|
|
9536
|
-
);
|
|
9537
|
-
const sl = order.child_orders.find(
|
|
9538
|
-
(o) => o.algo_type === types.AlgoOrderType.STOP_LOSS && o.is_activated
|
|
9539
|
-
);
|
|
9540
|
-
if (!tp) {
|
|
9541
|
-
result.tp_enable = false;
|
|
9542
|
-
}
|
|
9543
|
-
if (!sl) {
|
|
9544
|
-
result.sl_enable = false;
|
|
9545
|
-
}
|
|
9546
|
-
return result;
|
|
9547
|
-
};
|
|
9548
9755
|
var useTaskProfitAndStopLossInternal = (position, options) => {
|
|
9549
9756
|
const isEditing = typeof options?.isEditing !== "undefined" ? options.isEditing : !!options?.defaultOrder;
|
|
9550
9757
|
const [order, setOrder] = React2.useState({
|
|
@@ -9559,8 +9766,12 @@ var useTaskProfitAndStopLossInternal = (position, options) => {
|
|
|
9559
9766
|
// quantity:
|
|
9560
9767
|
// options?.defaultOrder?.quantity || Math.abs(position.position_qty),
|
|
9561
9768
|
algo_type: options?.defaultOrder?.algo_type,
|
|
9562
|
-
tp_enable: isEditing
|
|
9563
|
-
|
|
9769
|
+
// tp_enable: isEditing
|
|
9770
|
+
// ? checkIsEnableTpSL(options?.defaultOrder).tp_enable
|
|
9771
|
+
// : options?.tpslEnable?.tp_enable,
|
|
9772
|
+
// sl_enable: isEditing
|
|
9773
|
+
// ? checkIsEnableTpSL(options?.defaultOrder).sl_enable
|
|
9774
|
+
// : options?.tpslEnable?.sl_enable,
|
|
9564
9775
|
position_type: options?.positionType
|
|
9565
9776
|
});
|
|
9566
9777
|
const symbolInfo = useSymbolsInfo()[position.symbol]();
|
|
@@ -10212,254 +10423,6 @@ var useStorageLedgerAddress = () => {
|
|
|
10212
10423
|
ledgerWallet
|
|
10213
10424
|
};
|
|
10214
10425
|
};
|
|
10215
|
-
|
|
10216
|
-
// src/orderly/usePrivateDataObserver.ts
|
|
10217
|
-
var usePrivateDataObserver = (options) => {
|
|
10218
|
-
const ws = useWS();
|
|
10219
|
-
const ee = useEventEmitter();
|
|
10220
|
-
const { state, account: account9 } = useAccount();
|
|
10221
|
-
const { setAccountInfo, restoreHolding, cleanAll } = useAppStore(
|
|
10222
|
-
(state2) => state2.actions
|
|
10223
|
-
);
|
|
10224
|
-
const statusActions = useApiStatusActions();
|
|
10225
|
-
const calculatorService = useCalculatorService();
|
|
10226
|
-
const positionsActions = usePositionActions();
|
|
10227
|
-
const { data: clientInfo } = usePrivateQuery(
|
|
10228
|
-
"/v1/client/info",
|
|
10229
|
-
{
|
|
10230
|
-
revalidateOnFocus: false
|
|
10231
|
-
}
|
|
10232
|
-
);
|
|
10233
|
-
React2.useEffect(() => {
|
|
10234
|
-
if (clientInfo) {
|
|
10235
|
-
setAccountInfo(clientInfo);
|
|
10236
|
-
}
|
|
10237
|
-
}, [clientInfo, setAccountInfo]);
|
|
10238
|
-
const { data: positions3, isLoading: isPositionLoading } = usePrivateQuery("/v1/positions", {
|
|
10239
|
-
formatter: (data) => data,
|
|
10240
|
-
onError: (error) => {
|
|
10241
|
-
statusActions.updateApiError("positions", error.message);
|
|
10242
|
-
}
|
|
10243
|
-
// revalidateOnFocus: false,
|
|
10244
|
-
});
|
|
10245
|
-
React2.useEffect(() => {
|
|
10246
|
-
const handler = (state2) => {
|
|
10247
|
-
if (!state2.accountId) {
|
|
10248
|
-
calculatorService.stop();
|
|
10249
|
-
cleanAll();
|
|
10250
|
-
positionsActions.clearAll();
|
|
10251
|
-
}
|
|
10252
|
-
};
|
|
10253
|
-
account9.on(core.EVENT_NAMES.statusChanged, handler);
|
|
10254
|
-
return () => {
|
|
10255
|
-
account9.off(core.EVENT_NAMES.statusChanged, handler);
|
|
10256
|
-
};
|
|
10257
|
-
}, []);
|
|
10258
|
-
React2.useEffect(() => {
|
|
10259
|
-
if (isPositionLoading) {
|
|
10260
|
-
statusActions.updateApiLoading("positions", isPositionLoading);
|
|
10261
|
-
}
|
|
10262
|
-
}, [isPositionLoading, statusActions]);
|
|
10263
|
-
React2.useEffect(() => {
|
|
10264
|
-
if (positions3 && Array.isArray(positions3.rows)) {
|
|
10265
|
-
calculatorService.calc("position" /* POSITION */, positions3);
|
|
10266
|
-
}
|
|
10267
|
-
}, [calculatorService, positions3]);
|
|
10268
|
-
const { data: holding } = usePrivateQuery(
|
|
10269
|
-
"/v1/client/holding",
|
|
10270
|
-
{
|
|
10271
|
-
formatter: (data) => data.holding
|
|
10272
|
-
// revalidateOnFocus: false,
|
|
10273
|
-
}
|
|
10274
|
-
);
|
|
10275
|
-
React2.useEffect(() => {
|
|
10276
|
-
if (!account9.accountId)
|
|
10277
|
-
return;
|
|
10278
|
-
const unsubscribe = ws.privateSubscribe(
|
|
10279
|
-
{
|
|
10280
|
-
id: "balance",
|
|
10281
|
-
event: "subscribe",
|
|
10282
|
-
topic: "balance",
|
|
10283
|
-
ts: Date.now()
|
|
10284
|
-
},
|
|
10285
|
-
{
|
|
10286
|
-
onMessage: (data) => {
|
|
10287
|
-
const holding2 = data?.balances ?? {};
|
|
10288
|
-
if (holding2) {
|
|
10289
|
-
calculatorService.calc("portfolio" /* PORTFOLIO */, { holding: holding2 });
|
|
10290
|
-
}
|
|
10291
|
-
}
|
|
10292
|
-
}
|
|
10293
|
-
);
|
|
10294
|
-
return () => unsubscribe?.();
|
|
10295
|
-
}, [account9.accountId]);
|
|
10296
|
-
const isHoldingInit = React2.useRef(false);
|
|
10297
|
-
React2.useEffect(() => {
|
|
10298
|
-
isHoldingInit.current = false;
|
|
10299
|
-
}, [state.address]);
|
|
10300
|
-
React2.useEffect(() => {
|
|
10301
|
-
if (!holding) {
|
|
10302
|
-
return;
|
|
10303
|
-
}
|
|
10304
|
-
if (isHoldingInit.current) {
|
|
10305
|
-
calculatorService.calc("portfolio" /* PORTFOLIO */, { holding });
|
|
10306
|
-
} else {
|
|
10307
|
-
restoreHolding(holding);
|
|
10308
|
-
}
|
|
10309
|
-
isHoldingInit.current = true;
|
|
10310
|
-
}, [holding]);
|
|
10311
|
-
const [subOrder] = useLocalStorage("orderly_subscribe_order", true);
|
|
10312
|
-
const updateOrders = (data, isAlgoOrder) => {
|
|
10313
|
-
const keysMap = options.getKeysMap("orders");
|
|
10314
|
-
const filteredKeys = /* @__PURE__ */ new Map();
|
|
10315
|
-
const keyStartWith = isAlgoOrder ? "algoOrders" : "orders";
|
|
10316
|
-
const keys = keysMap.keys();
|
|
10317
|
-
for (const key of keys) {
|
|
10318
|
-
if (key.startsWith(keyStartWith)) {
|
|
10319
|
-
filteredKeys.set(key, keysMap.get(key));
|
|
10320
|
-
}
|
|
10321
|
-
}
|
|
10322
|
-
let fieldChanges = {};
|
|
10323
|
-
filteredKeys.forEach((getKey, key) => {
|
|
10324
|
-
useSWR.mutate(
|
|
10325
|
-
useSWRInfinite.unstable_serialize((index, prevData) => [
|
|
10326
|
-
getKey(index, prevData),
|
|
10327
|
-
state.accountId
|
|
10328
|
-
]),
|
|
10329
|
-
(prevData) => {
|
|
10330
|
-
try {
|
|
10331
|
-
if (isAlgoOrder) {
|
|
10332
|
-
const res = updateAlgoOrdersHandler(
|
|
10333
|
-
key,
|
|
10334
|
-
data,
|
|
10335
|
-
prevData
|
|
10336
|
-
);
|
|
10337
|
-
fieldChanges = res?.fieldChanges || {};
|
|
10338
|
-
return res?.mergedOrders;
|
|
10339
|
-
}
|
|
10340
|
-
return updateOrdersHandler(key, data, prevData);
|
|
10341
|
-
} catch (error) {
|
|
10342
|
-
return prevData;
|
|
10343
|
-
}
|
|
10344
|
-
},
|
|
10345
|
-
{
|
|
10346
|
-
revalidate: false
|
|
10347
|
-
}
|
|
10348
|
-
);
|
|
10349
|
-
});
|
|
10350
|
-
const formattedData = isAlgoOrder ? AlgoOrderMergeHandler.groupOrders(data) : object2underscore(data);
|
|
10351
|
-
ee.emit("orders:changed", {
|
|
10352
|
-
...formattedData,
|
|
10353
|
-
status: isAlgoOrder ? formattedData.algo_status : data.status,
|
|
10354
|
-
// custom field name
|
|
10355
|
-
fieldChanges
|
|
10356
|
-
});
|
|
10357
|
-
};
|
|
10358
|
-
React2.useEffect(() => {
|
|
10359
|
-
if (!state.accountId) {
|
|
10360
|
-
return;
|
|
10361
|
-
}
|
|
10362
|
-
if (subOrder !== true) {
|
|
10363
|
-
return;
|
|
10364
|
-
}
|
|
10365
|
-
const unsubscribe = ws.privateSubscribe("executionreport", {
|
|
10366
|
-
onMessage: (data) => {
|
|
10367
|
-
updateOrders(data, false);
|
|
10368
|
-
}
|
|
10369
|
-
});
|
|
10370
|
-
return () => unsubscribe?.();
|
|
10371
|
-
}, [state.accountId, subOrder]);
|
|
10372
|
-
React2.useEffect(() => {
|
|
10373
|
-
if (!state.accountId)
|
|
10374
|
-
return;
|
|
10375
|
-
if (subOrder !== true)
|
|
10376
|
-
return;
|
|
10377
|
-
const unsubscribe = ws.privateSubscribe("algoexecutionreport", {
|
|
10378
|
-
onMessage: (data) => {
|
|
10379
|
-
updateOrders(data, true);
|
|
10380
|
-
}
|
|
10381
|
-
});
|
|
10382
|
-
return () => unsubscribe?.();
|
|
10383
|
-
}, [state.accountId, subOrder]);
|
|
10384
|
-
React2.useEffect(() => {
|
|
10385
|
-
if (!state.accountId)
|
|
10386
|
-
return;
|
|
10387
|
-
const key = ["/v1/positions", state.accountId];
|
|
10388
|
-
const unsubscribe = ws.privateSubscribe("account", {
|
|
10389
|
-
onMessage: (data) => {
|
|
10390
|
-
const { symbol, leverage } = data?.accountDetail?.symbolLeverage || {};
|
|
10391
|
-
if (symbol && leverage) {
|
|
10392
|
-
useSWR.mutate(
|
|
10393
|
-
key,
|
|
10394
|
-
(prevPositions) => {
|
|
10395
|
-
if (prevPositions?.rows?.length) {
|
|
10396
|
-
return {
|
|
10397
|
-
...prevPositions,
|
|
10398
|
-
rows: prevPositions.rows.map((row) => {
|
|
10399
|
-
return row.symbol === symbol ? { ...row, leverage } : row;
|
|
10400
|
-
})
|
|
10401
|
-
};
|
|
10402
|
-
}
|
|
10403
|
-
return prevPositions;
|
|
10404
|
-
},
|
|
10405
|
-
{
|
|
10406
|
-
revalidate: false
|
|
10407
|
-
}
|
|
10408
|
-
);
|
|
10409
|
-
}
|
|
10410
|
-
}
|
|
10411
|
-
});
|
|
10412
|
-
return () => unsubscribe?.();
|
|
10413
|
-
}, [state.accountId]);
|
|
10414
|
-
React2.useEffect(() => {
|
|
10415
|
-
if (!state.accountId) {
|
|
10416
|
-
return;
|
|
10417
|
-
}
|
|
10418
|
-
const key = ["/v1/positions", state.accountId];
|
|
10419
|
-
const unsubscribe = ws.privateSubscribe("position", {
|
|
10420
|
-
onMessage: (data) => {
|
|
10421
|
-
const { positions: nextPositions } = data;
|
|
10422
|
-
useSWR.mutate(
|
|
10423
|
-
key,
|
|
10424
|
-
(prevPositions) => {
|
|
10425
|
-
if (!!prevPositions) {
|
|
10426
|
-
const newPositions = {
|
|
10427
|
-
...prevPositions,
|
|
10428
|
-
rows: prevPositions.rows.map((row) => {
|
|
10429
|
-
const itemIndex = nextPositions.findIndex(
|
|
10430
|
-
(item) => item.symbol === row.symbol
|
|
10431
|
-
);
|
|
10432
|
-
if (itemIndex >= 0) {
|
|
10433
|
-
const itemArr = nextPositions.splice(itemIndex, 1);
|
|
10434
|
-
const item = itemArr[0];
|
|
10435
|
-
if (item.averageOpenPrice === 0 && item.positionQty !== 0) {
|
|
10436
|
-
return row;
|
|
10437
|
-
}
|
|
10438
|
-
return object2underscore(item);
|
|
10439
|
-
}
|
|
10440
|
-
return row;
|
|
10441
|
-
})
|
|
10442
|
-
};
|
|
10443
|
-
if (nextPositions.length > 0) {
|
|
10444
|
-
newPositions.rows = [
|
|
10445
|
-
...newPositions.rows,
|
|
10446
|
-
...nextPositions.map(object2underscore)
|
|
10447
|
-
];
|
|
10448
|
-
}
|
|
10449
|
-
return newPositions;
|
|
10450
|
-
}
|
|
10451
|
-
},
|
|
10452
|
-
{
|
|
10453
|
-
revalidate: false
|
|
10454
|
-
}
|
|
10455
|
-
);
|
|
10456
|
-
}
|
|
10457
|
-
});
|
|
10458
|
-
return () => {
|
|
10459
|
-
unsubscribe?.();
|
|
10460
|
-
};
|
|
10461
|
-
}, [state.accountId]);
|
|
10462
|
-
};
|
|
10463
10426
|
var useMarketStore = zustand.create(
|
|
10464
10427
|
(set, get3) => ({
|
|
10465
10428
|
market: [],
|
|
@@ -18149,6 +18112,7 @@ exports.useFeeState = useFeeState;
|
|
|
18149
18112
|
exports.useFundingDetails = useFundingDetails;
|
|
18150
18113
|
exports.useFundingFeeHistory = useFundingFeeHistory;
|
|
18151
18114
|
exports.useFundingRate = useFundingRate;
|
|
18115
|
+
exports.useFundingRateBySymbol = useFundingRateBySymbol;
|
|
18152
18116
|
exports.useFundingRateHistory = useFundingRateHistory;
|
|
18153
18117
|
exports.useFundingRates = useFundingRates;
|
|
18154
18118
|
exports.useFundingRatesStore = useFundingRatesStore;
|