@zofai/zo-sdk 0.1.92 → 0.1.94
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/consts/deployments-slp-mainnet.json +1 -1
- package/dist/consts/deployments-usdz-mainnet.json +1 -1
- package/dist/consts/deployments-zlp-mainnet.json +1 -1
- package/dist/implementations/SLPDataAPI.cjs +227 -51
- package/dist/implementations/SLPDataAPI.cjs.map +1 -1
- package/dist/implementations/SLPDataAPI.d.cts +8 -1
- package/dist/implementations/SLPDataAPI.d.cts.map +1 -1
- package/dist/implementations/SLPDataAPI.d.mts +8 -1
- package/dist/implementations/SLPDataAPI.d.mts.map +1 -1
- package/dist/implementations/SLPDataAPI.mjs +227 -51
- package/dist/implementations/SLPDataAPI.mjs.map +1 -1
- package/dist/implementations/USDZDataAPI.cjs +208 -48
- package/dist/implementations/USDZDataAPI.cjs.map +1 -1
- package/dist/implementations/USDZDataAPI.d.cts +8 -1
- package/dist/implementations/USDZDataAPI.d.cts.map +1 -1
- package/dist/implementations/USDZDataAPI.d.mts +8 -1
- package/dist/implementations/USDZDataAPI.d.mts.map +1 -1
- package/dist/implementations/USDZDataAPI.mjs +208 -48
- package/dist/implementations/USDZDataAPI.mjs.map +1 -1
- package/dist/implementations/ZLPDataAPI.cjs +211 -50
- package/dist/implementations/ZLPDataAPI.cjs.map +1 -1
- package/dist/implementations/ZLPDataAPI.d.cts +8 -1
- package/dist/implementations/ZLPDataAPI.d.cts.map +1 -1
- package/dist/implementations/ZLPDataAPI.d.mts +8 -1
- package/dist/implementations/ZLPDataAPI.d.mts.map +1 -1
- package/dist/implementations/ZLPDataAPI.mjs +211 -50
- package/dist/implementations/ZLPDataAPI.mjs.map +1 -1
- package/dist/interfaces/base.d.cts +22 -0
- package/dist/interfaces/base.d.cts.map +1 -1
- package/dist/interfaces/base.d.mts +22 -0
- package/dist/interfaces/base.d.mts.map +1 -1
- package/dist/interfaces/slp.d.cts +8 -1
- package/dist/interfaces/slp.d.cts.map +1 -1
- package/dist/interfaces/slp.d.mts +8 -1
- package/dist/interfaces/slp.d.mts.map +1 -1
- package/dist/interfaces/usdz.d.cts +8 -1
- package/dist/interfaces/usdz.d.cts.map +1 -1
- package/dist/interfaces/usdz.d.mts +8 -1
- package/dist/interfaces/usdz.d.mts.map +1 -1
- package/dist/interfaces/zlp.d.cts +8 -1
- package/dist/interfaces/zlp.d.cts.map +1 -1
- package/dist/interfaces/zlp.d.mts +8 -1
- package/dist/interfaces/zlp.d.mts.map +1 -1
- package/package.json +4 -1
- package/src/consts/deployments-slp-mainnet.json +1 -1
- package/src/consts/deployments-usdz-mainnet.json +1 -1
- package/src/consts/deployments-zlp-mainnet.json +1 -1
- package/src/implementations/SLPDataAPI.ts +253 -23
- package/src/implementations/USDZDataAPI.ts +232 -20
- package/src/implementations/ZLPDataAPI.ts +233 -21
- package/src/interfaces/base.ts +26 -0
- package/src/interfaces/slp.ts +10 -1
- package/src/interfaces/usdz.ts +10 -1
- package/src/interfaces/zlp.ts +10 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"sudo_core": {
|
|
3
3
|
"package": "0xc44d97a4bc4e5a33ca847b72b123172c88a6328196b71414f32c3070233604b2",
|
|
4
|
-
"upgraded_package": "
|
|
4
|
+
"upgraded_package": "0x133f18548e87ae085905f3dd4c9d5be9b9ceb9a9bd2d55f34a0804eb249db1ae",
|
|
5
5
|
"upgrade_cap": "0x2092387c072fe18f91b57b9dde362f758259ee88d993a5faf569b4f2eb288b12",
|
|
6
6
|
"admin_cap": "0x0b4183c84de542c6f9623acd521294ea7e8205a2a7a23f4fac97e964fe4da30e",
|
|
7
7
|
"market": "0x4d753c2c69109cbeb806393956cfeba28d832354a37d59d9a019ee580f82893d",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"zo_core": {
|
|
3
3
|
"package": "0x7fd8aba1652c58b6397c799fd375e748e5053145cb7e126d303e0a1545fd1fec",
|
|
4
|
-
"upgraded_package": "
|
|
4
|
+
"upgraded_package": "0x43779d65ae051458c5021f6bfe891a117c49b091132c6f3be2c714b02a4bcb25",
|
|
5
5
|
"upgrade_cap": "0x2f67d379d3b9e256a9c4079de50f4bd336dcbda1bd90d1fcd61a9cc1dc369d69",
|
|
6
6
|
"admin_cap": "0x63af8e78701327be98e0c44967389148c374f4ea7c7cf8acf64957b705ffd02d",
|
|
7
7
|
"market": "0x3310c794d0bbc4b0421d2fedc74fbd5a028b09fe4d396cd5458786f4c52fa636",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"zo_core": {
|
|
3
3
|
"package": "0xf7fade57462e56e2eff1d7adef32e4fd285b21fd81f983f407bb7110ca766cda",
|
|
4
|
-
"upgraded_package": "
|
|
4
|
+
"upgraded_package": "0x420dbbc3b14a2e1645a38b111dc1c381cae43f349ddf800540f8991efbce563d",
|
|
5
5
|
"upgrade_cap": "0xcc96f78abe0b868afaab05954ccc6357afb5d379a21389d6eb88dda8b1f60052",
|
|
6
6
|
"admin_cap": "0xbc10f6481f2b5d6185c73ee680aa90a60fe3854d9f638e00f7e00d3b6a88e2b8",
|
|
7
7
|
"market": "0x35c667bd8c401036103992791a924f31df0d104256a9e2313acee5b1bcf05b7e",
|
|
@@ -6,6 +6,12 @@
|
|
|
6
6
|
* SLP DataAPI implementation
|
|
7
7
|
* Implements SLP-specific data access methods for Sudo SDK
|
|
8
8
|
*/
|
|
9
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
10
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
11
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
12
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
13
|
+
};
|
|
14
|
+
var _SLPDataAPI_instances, _a, _SLPDataAPI_getTotalVaultsValueUsd, _SLPDataAPI_getSwapImpactConfig, _SLPDataAPI_getEmaVolatilityFeeConfig, _SLPDataAPI_getMarketDynamicFieldObjectByKeySuffix, _SLPDataAPI_parseSwapImpactConfig, _SLPDataAPI_parseEmaVolatilityFeeConfig, _SLPDataAPI_computeSwapImpactFeeValue, _SLPDataAPI_computeEmaVolatilityFeeValue, _SLPDataAPI_maxEmaDivergenceRate, _SLPDataAPI_emaDivergenceRate;
|
|
9
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
16
|
exports.SLPDataAPI = void 0;
|
|
11
17
|
const transactions_1 = require("@mysten/sui/transactions");
|
|
@@ -19,6 +25,7 @@ const SECONDS_PER_EIGHT_HOUR = 8 * 60 * 60; // 28800 seconds
|
|
|
19
25
|
class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
20
26
|
constructor(network, provider, apiEndpoint, connectionURL) {
|
|
21
27
|
super(network, provider, apiEndpoint, connectionURL, consts_1.LPToken.SLP);
|
|
28
|
+
_SLPDataAPI_instances.add(this);
|
|
22
29
|
}
|
|
23
30
|
static calculateVaultReservingFee(vaultInfo, reservingFeeModel, currentTime) {
|
|
24
31
|
const timeDelta = currentTime - vaultInfo.lastUpdate;
|
|
@@ -26,8 +33,8 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
26
33
|
return vaultInfo.unrealisedReservingFeeAmount
|
|
27
34
|
+ (vaultInfo.reservedAmount * reservingFeeModel.multiplier * periods) / 1e18;
|
|
28
35
|
}
|
|
29
|
-
static calculateSymbolFundingFee(symbol, model, price, lpSupplyAmount, timestamp,
|
|
30
|
-
const accFundingRate =
|
|
36
|
+
static calculateSymbolFundingFee(symbol, model, price, lpSupplyAmount, timestamp, oiState, pairedOpeningSize) {
|
|
37
|
+
const accFundingRate = _a.calcAccFundingFeeRate(symbol, model, price, lpSupplyAmount, timestamp, symbol.long, oiState, pairedOpeningSize);
|
|
31
38
|
return symbol.unrealisedFundingFeeValue + (accFundingRate - symbol.accFundingRate) * symbol.openingSize;
|
|
32
39
|
}
|
|
33
40
|
async getRebaseFeeModel() {
|
|
@@ -41,8 +48,8 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
41
48
|
showContent: true,
|
|
42
49
|
},
|
|
43
50
|
});
|
|
44
|
-
const model =
|
|
45
|
-
const exponent = await
|
|
51
|
+
const model = _a.parseRebaseFeeModel(rawData);
|
|
52
|
+
const exponent = await _a.getRebaseFeeExponent(this.provider, this.consts.sudoCore.rebaseFeeModel, this.consts.sudoCore.upgradedPackage);
|
|
46
53
|
return { ...model, exponent };
|
|
47
54
|
}
|
|
48
55
|
/**
|
|
@@ -128,27 +135,30 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
128
135
|
const marketInfo = await this.getMarketInfo();
|
|
129
136
|
let slpPrice = 0;
|
|
130
137
|
let value = 0;
|
|
131
|
-
const
|
|
138
|
+
const vaultKeys = Object.keys(this.consts.sudoCore.vaults);
|
|
139
|
+
const vaultData = await Promise.all(vaultKeys.map(async (vault) => {
|
|
132
140
|
const vaultInfo = await this.getVaultInfo(vault);
|
|
133
|
-
const reservingFeeDelta =
|
|
141
|
+
const reservingFeeDelta = _a.calculateVaultReservingFee(vaultInfo, vaultInfo.reservingFeeModel, Date.now() / 1000);
|
|
134
142
|
const totalVaultAmount = reservingFeeDelta + vaultInfo.liquidity + vaultInfo.reservedAmount;
|
|
135
143
|
const oraclePrice = (await this.getOraclePrice(vault)).getPriceUnchecked().getPriceAsNumberUnchecked();
|
|
136
144
|
const { decimals } = this.consts.coins[vault];
|
|
137
145
|
const vaultValue = totalVaultAmount * oraclePrice / (10 ** decimals);
|
|
138
|
-
return vaultValue;
|
|
139
|
-
});
|
|
146
|
+
return { vault, oraclePrice, vaultValue };
|
|
147
|
+
}));
|
|
148
|
+
const vaultPrices = Object.fromEntries(vaultData.map(d => [d.vault, d.oraclePrice]));
|
|
149
|
+
const vaultValues = vaultData.map(d => d.vaultValue);
|
|
140
150
|
const symbolPromises = Object.keys(this.consts.sudoCore.symbols).map(async (symbol) => {
|
|
141
151
|
const [direction, tokenId] = (0, utils_2.parseSymbolKey)(symbol);
|
|
142
152
|
const symbolInfo = await this.getSymbolInfo(tokenId, direction === 'long');
|
|
143
153
|
const price = (await this.getOraclePrice(tokenId)).getPriceUnchecked().getPriceAsNumberUnchecked();
|
|
144
|
-
const deltaSize =
|
|
154
|
+
const deltaSize = _a.calcDeltaSize(symbolInfo, price, direction === 'long');
|
|
145
155
|
const oiState = await this.getSymbolOiFundingState(tokenId);
|
|
146
156
|
const pairedInfo = await this.getSymbolInfo(tokenId, direction !== 'long');
|
|
147
|
-
const fundingFeeDelta =
|
|
157
|
+
const fundingFeeDelta = _a.calculateSymbolFundingFee(symbolInfo, symbolInfo.fundingFeeModel, price, marketInfo.lpSupplyWithDecimals, Date.now() / 1000, oiState && oiState.enabled ? oiState : undefined, pairedInfo.openingSize);
|
|
148
158
|
const symbolValue = fundingFeeDelta + deltaSize;
|
|
149
159
|
return symbolValue;
|
|
150
160
|
});
|
|
151
|
-
const
|
|
161
|
+
const symbolValues = await Promise.all(symbolPromises);
|
|
152
162
|
const totalVaultValue = vaultValues.reduce((acc, curr) => acc + curr, 0);
|
|
153
163
|
const totalSymbolValue = symbolValues.reduce((acc, curr) => acc + curr, 0);
|
|
154
164
|
value = totalVaultValue + totalSymbolValue;
|
|
@@ -158,6 +168,7 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
158
168
|
price: slpPrice,
|
|
159
169
|
supply: marketInfo.lpSupplyWithDecimals,
|
|
160
170
|
apr: Number(marketInfo.apr),
|
|
171
|
+
vaultPrices,
|
|
161
172
|
};
|
|
162
173
|
}
|
|
163
174
|
/**
|
|
@@ -204,11 +215,18 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
204
215
|
const marketInfo = await this.getMarketInfo();
|
|
205
216
|
const value = await this.simValuateVaults(this.consts.sudoCore.adminCap);
|
|
206
217
|
const slpPrice = value / marketInfo.lpSupplyWithDecimals;
|
|
218
|
+
const vaultKeys = Object.keys(this.consts.sudoCore.vaults);
|
|
219
|
+
const vaultPricesEntries = await Promise.all(vaultKeys.map(async (vault) => {
|
|
220
|
+
const oraclePrice = (await this.getOraclePrice(vault)).getPriceUnchecked().getPriceAsNumberUnchecked();
|
|
221
|
+
return [vault, oraclePrice];
|
|
222
|
+
}));
|
|
223
|
+
const vaultPrices = Object.fromEntries(vaultPricesEntries);
|
|
207
224
|
return {
|
|
208
225
|
marketCap: value,
|
|
209
226
|
price: slpPrice,
|
|
210
227
|
supply: marketInfo.lpSupplyWithDecimals,
|
|
211
228
|
apr: Number(marketInfo.apr),
|
|
229
|
+
vaultPrices,
|
|
212
230
|
};
|
|
213
231
|
}
|
|
214
232
|
/**
|
|
@@ -227,7 +245,7 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
227
245
|
});
|
|
228
246
|
const apr = await this.getCumulativeApr();
|
|
229
247
|
return {
|
|
230
|
-
...
|
|
248
|
+
..._a.parseMarketInfo(rawData),
|
|
231
249
|
apr,
|
|
232
250
|
};
|
|
233
251
|
}
|
|
@@ -279,7 +297,7 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
279
297
|
value: { dummy_field: false },
|
|
280
298
|
},
|
|
281
299
|
});
|
|
282
|
-
return
|
|
300
|
+
return _a.parseSymbolConfig(rawData);
|
|
283
301
|
}
|
|
284
302
|
catch {
|
|
285
303
|
// If the dynamic field doesn't exist, return null
|
|
@@ -301,7 +319,7 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
301
319
|
value: { dummy_field: false },
|
|
302
320
|
},
|
|
303
321
|
});
|
|
304
|
-
return
|
|
322
|
+
return _a.parsePriceImpactConfig(rawData);
|
|
305
323
|
}
|
|
306
324
|
catch (e) {
|
|
307
325
|
// If the dynamic field doesn't exist, return null (price impact not configured for this symbol)
|
|
@@ -322,7 +340,7 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
322
340
|
value: { dummy_field: false },
|
|
323
341
|
},
|
|
324
342
|
});
|
|
325
|
-
return
|
|
343
|
+
return _a.parseOiFundingState(rawData);
|
|
326
344
|
}
|
|
327
345
|
catch (e) {
|
|
328
346
|
// If the dynamic field doesn't exist, return null
|
|
@@ -330,6 +348,52 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
330
348
|
return null;
|
|
331
349
|
}
|
|
332
350
|
}
|
|
351
|
+
async calculateSwapFeeBreakdown(fromToken, toToken, fromAmount) {
|
|
352
|
+
if (!this.consts.sudoCore) {
|
|
353
|
+
throw new Error('Sudo Core configuration not found. Make sure you are using LPToken.SLP');
|
|
354
|
+
}
|
|
355
|
+
const timestamp = Date.now() / 1000;
|
|
356
|
+
const fromDecimals = this.consts.coins[fromToken]?.decimals;
|
|
357
|
+
const toDecimals = this.consts.coins[toToken]?.decimals;
|
|
358
|
+
if (fromDecimals === undefined || toDecimals === undefined) {
|
|
359
|
+
throw new Error(`Unknown token decimals for swap: ${fromToken} -> ${toToken}`);
|
|
360
|
+
}
|
|
361
|
+
const fromFeed = await this.getOraclePrice(fromToken);
|
|
362
|
+
const toFeed = await this.getOraclePrice(toToken);
|
|
363
|
+
const fromPrice = fromFeed.getPriceUnchecked().getPriceAsNumberUnchecked();
|
|
364
|
+
const toPrice = toFeed.getPriceUnchecked().getPriceAsNumberUnchecked();
|
|
365
|
+
const swapValue = (fromAmount * fromPrice) / (10 ** fromDecimals);
|
|
366
|
+
const totalVaultsValue = await __classPrivateFieldGet(this, _SLPDataAPI_instances, "m", _SLPDataAPI_getTotalVaultsValueUsd).call(this, timestamp);
|
|
367
|
+
const rebaseFeeInRate = await this.rebaseFeeRate(fromToken, true, fromAmount);
|
|
368
|
+
const rebaseFeeInValue = swapValue * rebaseFeeInRate;
|
|
369
|
+
const estimatedToAmount = toPrice !== 0
|
|
370
|
+
? (swapValue * (10 ** toDecimals)) / toPrice
|
|
371
|
+
: 0;
|
|
372
|
+
const rebaseFeeOutRate = await this.rebaseFeeRate(toToken, false, estimatedToAmount);
|
|
373
|
+
const rebaseFeeOutValue = swapValue * rebaseFeeOutRate;
|
|
374
|
+
const swapImpactCfg = await __classPrivateFieldGet(this, _SLPDataAPI_instances, "m", _SLPDataAPI_getSwapImpactConfig).call(this);
|
|
375
|
+
const swapImpactFeeValue = swapImpactCfg?.enabled
|
|
376
|
+
? __classPrivateFieldGet(_a, _a, "m", _SLPDataAPI_computeSwapImpactFeeValue).call(_a, swapValue, totalVaultsValue, swapImpactCfg.impactMultiplier, swapImpactCfg.maxImpactRate)
|
|
377
|
+
: 0;
|
|
378
|
+
const emaCfg = await __classPrivateFieldGet(this, _SLPDataAPI_instances, "m", _SLPDataAPI_getEmaVolatilityFeeConfig).call(this);
|
|
379
|
+
const emaVolatilityFeeValue = emaCfg?.enabled
|
|
380
|
+
? __classPrivateFieldGet(_a, _a, "m", _SLPDataAPI_computeEmaVolatilityFeeValue).call(_a, swapValue, __classPrivateFieldGet(_a, _a, "m", _SLPDataAPI_maxEmaDivergenceRate).call(_a, fromFeed, toFeed), emaCfg.multiplier, emaCfg.maxFeeRate)
|
|
381
|
+
: 0;
|
|
382
|
+
const totalFeeValue = rebaseFeeInValue + rebaseFeeOutValue + swapImpactFeeValue + emaVolatilityFeeValue;
|
|
383
|
+
const totalFeeRate = swapValue !== 0 ? totalFeeValue / swapValue : 0;
|
|
384
|
+
return {
|
|
385
|
+
swapValue,
|
|
386
|
+
totalVaultsValue,
|
|
387
|
+
rebaseFeeInRate,
|
|
388
|
+
rebaseFeeOutRate,
|
|
389
|
+
rebaseFeeInValue,
|
|
390
|
+
rebaseFeeOutValue,
|
|
391
|
+
swapImpactFeeValue,
|
|
392
|
+
emaVolatilityFeeValue,
|
|
393
|
+
totalFeeValue,
|
|
394
|
+
totalFeeRate,
|
|
395
|
+
};
|
|
396
|
+
}
|
|
333
397
|
async getPositionInfoList(positionCapInfoList, owner, batchSize = 10) {
|
|
334
398
|
const positionInfoList = [];
|
|
335
399
|
// Process in batches of 10
|
|
@@ -421,7 +485,7 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
421
485
|
rawCredentialsData = [...rawCredentialsData, ...data];
|
|
422
486
|
}
|
|
423
487
|
const pool = await this.getStakePool();
|
|
424
|
-
const credentials = rawCredentialsData.map((item) =>
|
|
488
|
+
const credentials = rawCredentialsData.map((item) => _a.parseCredential(item, pool));
|
|
425
489
|
return {
|
|
426
490
|
credentials,
|
|
427
491
|
amount: credentials.reduce((acc, cur) => acc + cur.amount, BigInt(0)),
|
|
@@ -438,7 +502,7 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
438
502
|
showContent: true,
|
|
439
503
|
},
|
|
440
504
|
});
|
|
441
|
-
return
|
|
505
|
+
return _a.parseStakePool(raw);
|
|
442
506
|
}
|
|
443
507
|
async getStakePoolV2() {
|
|
444
508
|
const poolId = this.sharedConfig.zoStaking.pools.slp;
|
|
@@ -448,7 +512,7 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
448
512
|
showContent: true,
|
|
449
513
|
},
|
|
450
514
|
});
|
|
451
|
-
return
|
|
515
|
+
return _a.parseStakePool(raw);
|
|
452
516
|
}
|
|
453
517
|
async getStakedV2(owner) {
|
|
454
518
|
let rawCredentialsData = [];
|
|
@@ -481,7 +545,7 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
481
545
|
const credentials = rawCredentialsData
|
|
482
546
|
.filter((item) => item.data.type
|
|
483
547
|
=== `${this.sharedConfig.zoStaking.package}::pool::Credential<${this.consts.sudoCore.package}::slp::SLP, ${this.consts.sudoCore.package}::slp::SLP>`)
|
|
484
|
-
.map((item) =>
|
|
548
|
+
.map((item) => _a.parseCredential(item, pool));
|
|
485
549
|
return {
|
|
486
550
|
credentials,
|
|
487
551
|
amount: credentials.reduce((acc, cur) => acc + cur.amount, BigInt(0)),
|
|
@@ -497,7 +561,7 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
497
561
|
return 0;
|
|
498
562
|
}
|
|
499
563
|
const elapsed = SECONDS_PER_EIGHT_HOUR;
|
|
500
|
-
const deltaRate =
|
|
564
|
+
const deltaRate = _a.calcOiFundingFeeRate(oiState.model, longSymbol.openingSize, shortSymbol.openingSize, elapsed, oiState.maxOiLong, oiState.maxOiShort);
|
|
501
565
|
return long ? deltaRate : -deltaRate;
|
|
502
566
|
}
|
|
503
567
|
const symbol = await this.getSymbolInfo(indexToken, long);
|
|
@@ -508,9 +572,9 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
508
572
|
const lpSupplyAmount = (await this.getMarketInfo()).lpSupplyWithDecimals;
|
|
509
573
|
const model = symbol.fundingFeeModel;
|
|
510
574
|
const elapsed = SECONDS_PER_EIGHT_HOUR;
|
|
511
|
-
const deltaSize =
|
|
575
|
+
const deltaSize = _a.calcDeltaSize(symbol, price, symbol.long);
|
|
512
576
|
const pnlPerLp = (symbol.realisedPnl + symbol.unrealisedFundingFeeValue + deltaSize) / lpSupplyAmount;
|
|
513
|
-
return
|
|
577
|
+
return _a.calcFundingFeeRate(model, pnlPerLp, elapsed);
|
|
514
578
|
}
|
|
515
579
|
async rebaseFeeRate(collateralToken, increase, amount, _sender) {
|
|
516
580
|
let vaultValue = 0;
|
|
@@ -520,7 +584,7 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
520
584
|
const value = amount * (await this.getOraclePrice(collateralToken)).getPriceUnchecked().getPriceAsNumberUnchecked() / (10 ** this.consts.coins[collateralToken].decimals);
|
|
521
585
|
const vaultPromises = Object.keys(this.consts.sudoCore.vaults).map(async (vault) => {
|
|
522
586
|
const vaultInfo = await this.getVaultInfo(vault);
|
|
523
|
-
const reservingFeeDelta =
|
|
587
|
+
const reservingFeeDelta = _a.calculateVaultReservingFee(vaultInfo, vaultInfo.reservingFeeModel, Date.now() / 1000);
|
|
524
588
|
const totalVaultAmount = reservingFeeDelta + vaultInfo.liquidity + vaultInfo.reservedAmount;
|
|
525
589
|
const oraclePrice = (await this.getOraclePrice(vault)).getPriceUnchecked().getPriceAsNumberUnchecked();
|
|
526
590
|
const res = totalVaultAmount * oraclePrice / (10 ** this.consts.coins[vault].decimals);
|
|
@@ -534,7 +598,7 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
534
598
|
const targetRatio = Number.parseInt(this.consts.sudoCore.vaults[collateralToken].weight, 10) / Object.values(this.consts.sudoCore.vaults)
|
|
535
599
|
.map(e => Number.parseInt(e.weight, 10))
|
|
536
600
|
.reduce((acc, curr) => acc + curr, 0);
|
|
537
|
-
return
|
|
601
|
+
return _a.calcRebaseFeeRate(await this.getRebaseFeeModel(), increase, (vaultValue + value) / (totalVaultValue + value), targetRatio);
|
|
538
602
|
}
|
|
539
603
|
async reservingFeeRate(collateralToken, amount, sender) {
|
|
540
604
|
if (!sender) {
|
|
@@ -576,7 +640,7 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
576
640
|
showContent: true,
|
|
577
641
|
},
|
|
578
642
|
});
|
|
579
|
-
return
|
|
643
|
+
return _a.parsePositionConfig(rawData);
|
|
580
644
|
}
|
|
581
645
|
async getOpenPositions(batchSize = 50, symbol = 'sui') {
|
|
582
646
|
let positionDynamicFields = [];
|
|
@@ -794,26 +858,26 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
794
858
|
return aprResponse.apr;
|
|
795
859
|
}
|
|
796
860
|
// Private helper methods
|
|
797
|
-
static calculatePositionFundingFee(position, symbol, model, price, lpSupplyAmount, timestamp,
|
|
798
|
-
const accFundingRate = this.calcAccFundingFeeRate(symbol, model, price, lpSupplyAmount, timestamp, position.long,
|
|
861
|
+
static calculatePositionFundingFee(position, symbol, model, price, lpSupplyAmount, timestamp, oiState, pairedOpeningSize) {
|
|
862
|
+
const accFundingRate = this.calcAccFundingFeeRate(symbol, model, price, lpSupplyAmount, timestamp, position.long, oiState, pairedOpeningSize);
|
|
799
863
|
return position.fundingFeeValue + (accFundingRate - position.lastFundingRate) * position.positionSize;
|
|
800
864
|
}
|
|
801
|
-
static calcAccFundingFeeRate(symbol, model, price, lpSupplyAmount, timestamp, isLong,
|
|
865
|
+
static calcAccFundingFeeRate(symbol, model, price, lpSupplyAmount, timestamp, isLong, oiState, pairedOpeningSize) {
|
|
802
866
|
if (symbol.lastUpdate > 0) {
|
|
803
867
|
const elapsed = timestamp - symbol.lastUpdate;
|
|
804
868
|
if (elapsed > 0) {
|
|
805
|
-
// Prefer OI-based delta when OI
|
|
806
|
-
if (
|
|
869
|
+
// Prefer OI-based delta when OI state and paired side are available
|
|
870
|
+
if (oiState?.enabled && oiState.model && typeof pairedOpeningSize === 'number') {
|
|
807
871
|
const longSize = isLong ? symbol.openingSize : pairedOpeningSize;
|
|
808
872
|
const shortSize = isLong ? pairedOpeningSize : symbol.openingSize;
|
|
809
|
-
const deltaRate =
|
|
873
|
+
const deltaRate = _a.calcOiFundingFeeRate(oiState.model, longSize, shortSize, elapsed, oiState.maxOiLong, oiState.maxOiShort);
|
|
810
874
|
const appliedRate = isLong ? deltaRate : -deltaRate;
|
|
811
875
|
return symbol.accFundingRate + appliedRate;
|
|
812
876
|
}
|
|
813
877
|
// Fallback to PnL-based funding delta
|
|
814
878
|
const deltaSize = this.calcDeltaSize(symbol, price, isLong);
|
|
815
879
|
const pnlPerLp = (symbol.realisedPnl + symbol.unrealisedFundingFeeValue + deltaSize) / lpSupplyAmount;
|
|
816
|
-
return symbol.accFundingRate +
|
|
880
|
+
return symbol.accFundingRate + _a.calcFundingFeeRate(model, pnlPerLp, elapsed);
|
|
817
881
|
}
|
|
818
882
|
}
|
|
819
883
|
return symbol.accFundingRate;
|
|
@@ -827,23 +891,44 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
827
891
|
const secondsRate = dailyRate * elapsed / SECONDS_PER_EIGHT_HOUR;
|
|
828
892
|
return pnlPerRate >= 0 ? -secondsRate : secondsRate;
|
|
829
893
|
}
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
894
|
+
/**
|
|
895
|
+
* OI funding rate matching Move compute_oi_funding_rate_capped.
|
|
896
|
+
* When both maxOiLong and maxOiShort are set and > 0, uses normalized skew (oi/cap);
|
|
897
|
+
* otherwise falls back to (long - short) / total.
|
|
898
|
+
*/
|
|
899
|
+
static calcOiFundingFeeRate(model, oiLong, oiShort, elapsed, maxOiLong, maxOiShort) {
|
|
900
|
+
let skew;
|
|
901
|
+
if (maxOiLong && maxOiShort && maxOiLong > 0 && maxOiShort > 0) {
|
|
902
|
+
const normLong = Math.min(oiLong / maxOiLong, 1);
|
|
903
|
+
const normShort = Math.min(oiShort / maxOiShort, 1);
|
|
904
|
+
skew = normLong - normShort;
|
|
905
|
+
}
|
|
906
|
+
else {
|
|
907
|
+
const total = oiLong + oiShort;
|
|
908
|
+
if (total === 0)
|
|
909
|
+
return 0;
|
|
910
|
+
skew = (oiLong - oiShort) / total;
|
|
911
|
+
}
|
|
912
|
+
if (skew === 0)
|
|
913
|
+
return 0;
|
|
914
|
+
const skewIsPositive = skew > 0;
|
|
915
|
+
const skewAbs = Math.abs(skew);
|
|
916
|
+
const exponentInt = Math.floor(model.exponent);
|
|
917
|
+
const skewPow = skewAbs ** exponentInt;
|
|
918
|
+
const dailyRate = Math.min(model.multiplier * skewPow, model.max);
|
|
919
|
+
const secondsRate = (dailyRate * elapsed) / SECONDS_PER_EIGHT_HOUR;
|
|
920
|
+
return skewIsPositive ? secondsRate : -secondsRate;
|
|
836
921
|
}
|
|
837
922
|
static calculatePositionReserveFee(position, vault, model, timestamp) {
|
|
838
|
-
const accReservingRate =
|
|
923
|
+
const accReservingRate = _a.calcAccReservingFeeRate(vault, model, timestamp);
|
|
839
924
|
return position.reservingFeeAmount + (accReservingRate - position.lastReservingRate) * position.reservedAmount;
|
|
840
925
|
}
|
|
841
926
|
static calcAccReservingFeeRate(vault, model, timestamp) {
|
|
842
927
|
if (vault.lastUpdate > 0) {
|
|
843
928
|
const elapsed = timestamp - vault.lastUpdate;
|
|
844
929
|
if (elapsed > 0) {
|
|
845
|
-
const utilization =
|
|
846
|
-
return vault.accReservingRate +
|
|
930
|
+
const utilization = _a.vaultUtilization(vault);
|
|
931
|
+
return vault.accReservingRate + _a.calcReservingFeeRate(model, utilization, elapsed);
|
|
847
932
|
}
|
|
848
933
|
}
|
|
849
934
|
return vault.accReservingRate;
|
|
@@ -1028,8 +1113,8 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
1028
1113
|
else if (endSkew > 1) {
|
|
1029
1114
|
endSkew = 1;
|
|
1030
1115
|
}
|
|
1031
|
-
const avgDynamicRate =
|
|
1032
|
-
const sizeFactor =
|
|
1116
|
+
const avgDynamicRate = _a.computeIntegralAverage(config.maxDynamicSpreadRate, startSkew, endSkew, config.impactExponent);
|
|
1117
|
+
const sizeFactor = _a.computeSizeFactor(newPositionSize, config.referenceSize);
|
|
1033
1118
|
const scaledDynamicRate = avgDynamicRate * sizeFactor;
|
|
1034
1119
|
let totalSpread = config.baseSpreadRate + scaledDynamicRate;
|
|
1035
1120
|
if (totalSpread > config.maxTotalSpreadRate) {
|
|
@@ -1068,8 +1153,8 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
1068
1153
|
const currentOiOpposite = isLong ? shortSymbol.openingSize : longSymbol.openingSize;
|
|
1069
1154
|
const maxOiThisSide = isLong ? config.maxOiLong : config.maxOiShort;
|
|
1070
1155
|
const maxOiOpposite = isLong ? config.maxOiShort : config.maxOiLong;
|
|
1071
|
-
const spreadRate =
|
|
1072
|
-
const adjustedPrice =
|
|
1156
|
+
const spreadRate = _a.computeAverageSpreadRate(config, currentOiThisSide, positionSizeValue, currentOiOpposite, maxOiThisSide, maxOiOpposite);
|
|
1157
|
+
const adjustedPrice = _a.applyPriceImpact(oraclePrice, spreadRate, isLong, isOpening);
|
|
1073
1158
|
return {
|
|
1074
1159
|
spreadRate,
|
|
1075
1160
|
originalPrice: oraclePrice,
|
|
@@ -1095,6 +1180,8 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
1095
1180
|
exponent: (0, utils_2.parseValue)(content.model.fields.exponent),
|
|
1096
1181
|
max: (0, utils_2.parseValue)(content.model.fields.max),
|
|
1097
1182
|
},
|
|
1183
|
+
maxOiLong: content.max_oi_long !== null && content.max_oi_long !== undefined ? (0, utils_2.parseValue)(content.max_oi_long) : undefined,
|
|
1184
|
+
maxOiShort: content.max_oi_short !== null && content.max_oi_short !== undefined ? (0, utils_2.parseValue)(content.max_oi_short) : undefined,
|
|
1098
1185
|
};
|
|
1099
1186
|
}
|
|
1100
1187
|
static parsePriceImpactConfig(raw) {
|
|
@@ -1130,7 +1217,7 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
1130
1217
|
showContent: true,
|
|
1131
1218
|
},
|
|
1132
1219
|
});
|
|
1133
|
-
const reservingFeeModel =
|
|
1220
|
+
const reservingFeeModel = _a.parseReservingFeeModel(reservingFeeModelRaw);
|
|
1134
1221
|
return {
|
|
1135
1222
|
liquidity: (0, utils_2.parseValue)(vaultFields.liquidity),
|
|
1136
1223
|
reservedAmount: (0, utils_2.parseValue)(vaultFields.reserved_amount),
|
|
@@ -1164,7 +1251,7 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
1164
1251
|
showContent: true,
|
|
1165
1252
|
},
|
|
1166
1253
|
});
|
|
1167
|
-
const fundingFeeModel =
|
|
1254
|
+
const fundingFeeModel = _a.parseFundingFeeModel(fundingFeeModelRaw);
|
|
1168
1255
|
return {
|
|
1169
1256
|
objectId,
|
|
1170
1257
|
openingSize: (0, utils_2.parseValue)(fields.opening_size),
|
|
@@ -1212,11 +1299,11 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
1212
1299
|
};
|
|
1213
1300
|
if (!positionFields.closed) {
|
|
1214
1301
|
try {
|
|
1215
|
-
positionInfo.reservingFeeAmount =
|
|
1302
|
+
positionInfo.reservingFeeAmount = _a.calculatePositionReserveFee(positionInfo, await this.getVaultInfo(positionInfo.collateralToken), (await this.getVaultInfo(positionInfo.collateralToken)).reservingFeeModel, Date.now() / 1000);
|
|
1216
1303
|
// OI context for funding: fetch state and paired side size when enabled
|
|
1217
1304
|
const oiState = await this.getSymbolOiFundingState(positionInfo.indexToken);
|
|
1218
1305
|
const pairedSymbol = await this.getSymbolInfo(positionInfo.indexToken, !positionInfo.long);
|
|
1219
|
-
positionInfo.fundingFeeValue =
|
|
1306
|
+
positionInfo.fundingFeeValue = _a.calculatePositionFundingFee(positionInfo, await this.getSymbolInfo(positionInfo.indexToken, positionInfo.long), (await this.getSymbolInfo(positionInfo.indexToken, positionInfo.long)).fundingFeeModel, (await this.getOraclePrice(positionInfo.indexToken)).getPriceUnchecked().getPriceAsNumberUnchecked(), (await this.getMarketInfo()).lpSupplyWithDecimals, Date.now() / 1000, oiState && oiState.enabled ? oiState : undefined, pairedSymbol.openingSize);
|
|
1220
1307
|
}
|
|
1221
1308
|
catch (e) {
|
|
1222
1309
|
console.error(e);
|
|
@@ -1339,10 +1426,10 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
1339
1426
|
};
|
|
1340
1427
|
// Use appropriate refresh method based on version
|
|
1341
1428
|
if (isNewVersion) {
|
|
1342
|
-
|
|
1429
|
+
_a.refreshPoolV2(pool, Math.floor(Date.now() / 1000));
|
|
1343
1430
|
}
|
|
1344
1431
|
else {
|
|
1345
|
-
|
|
1432
|
+
_a.refreshPool(pool, Math.floor(Date.now() / 1000));
|
|
1346
1433
|
}
|
|
1347
1434
|
return pool;
|
|
1348
1435
|
}
|
|
@@ -1381,4 +1468,93 @@ class SLPDataAPI extends abstract_1.BaseDataAPI {
|
|
|
1381
1468
|
}
|
|
1382
1469
|
}
|
|
1383
1470
|
exports.SLPDataAPI = SLPDataAPI;
|
|
1471
|
+
_a = SLPDataAPI, _SLPDataAPI_instances = new WeakSet(), _SLPDataAPI_getTotalVaultsValueUsd = async function _SLPDataAPI_getTotalVaultsValueUsd(timestamp) {
|
|
1472
|
+
if (!this.consts.sudoCore) {
|
|
1473
|
+
return 0;
|
|
1474
|
+
}
|
|
1475
|
+
const vaultKeys = Object.keys(this.consts.sudoCore.vaults);
|
|
1476
|
+
const vaultValues = await Promise.all(vaultKeys.map(async (vault) => {
|
|
1477
|
+
const vaultInfo = await this.getVaultInfo(vault);
|
|
1478
|
+
const reservingFeeDelta = _a.calculateVaultReservingFee(vaultInfo, vaultInfo.reservingFeeModel, timestamp);
|
|
1479
|
+
const totalVaultAmount = reservingFeeDelta + vaultInfo.liquidity + vaultInfo.reservedAmount;
|
|
1480
|
+
const oraclePrice = (await this.getOraclePrice(vault)).getPriceUnchecked().getPriceAsNumberUnchecked();
|
|
1481
|
+
const { decimals } = this.consts.coins[vault];
|
|
1482
|
+
return totalVaultAmount * oraclePrice / (10 ** decimals);
|
|
1483
|
+
}));
|
|
1484
|
+
return vaultValues.reduce((acc, curr) => acc + curr, 0);
|
|
1485
|
+
}, _SLPDataAPI_getSwapImpactConfig = async function _SLPDataAPI_getSwapImpactConfig() {
|
|
1486
|
+
if (!this.consts.sudoCore) {
|
|
1487
|
+
return null;
|
|
1488
|
+
}
|
|
1489
|
+
const raw = await __classPrivateFieldGet(this, _SLPDataAPI_instances, "m", _SLPDataAPI_getMarketDynamicFieldObjectByKeySuffix).call(this, this.consts.sudoCore.market, 'SwapImpactConfigKey');
|
|
1490
|
+
if (!raw)
|
|
1491
|
+
return null;
|
|
1492
|
+
return __classPrivateFieldGet(_a, _a, "m", _SLPDataAPI_parseSwapImpactConfig).call(_a, raw);
|
|
1493
|
+
}, _SLPDataAPI_getEmaVolatilityFeeConfig = async function _SLPDataAPI_getEmaVolatilityFeeConfig() {
|
|
1494
|
+
if (!this.consts.sudoCore) {
|
|
1495
|
+
return null;
|
|
1496
|
+
}
|
|
1497
|
+
const raw = await __classPrivateFieldGet(this, _SLPDataAPI_instances, "m", _SLPDataAPI_getMarketDynamicFieldObjectByKeySuffix).call(this, this.consts.sudoCore.market, 'EmaVolatilityFeeConfigKey');
|
|
1498
|
+
if (!raw)
|
|
1499
|
+
return null;
|
|
1500
|
+
return __classPrivateFieldGet(_a, _a, "m", _SLPDataAPI_parseEmaVolatilityFeeConfig).call(_a, raw);
|
|
1501
|
+
}, _SLPDataAPI_getMarketDynamicFieldObjectByKeySuffix = async function _SLPDataAPI_getMarketDynamicFieldObjectByKeySuffix(parentId, keyTypeSuffix) {
|
|
1502
|
+
let cursor;
|
|
1503
|
+
let hasNextPage = true;
|
|
1504
|
+
while (hasNextPage) {
|
|
1505
|
+
const page = await this.provider.getDynamicFields({ parentId, cursor });
|
|
1506
|
+
for (const field of page.data) {
|
|
1507
|
+
const type = field.name?.type;
|
|
1508
|
+
if (typeof type === 'string' && type.endsWith(`::${keyTypeSuffix}`)) {
|
|
1509
|
+
return await this.provider.getDynamicFieldObject({
|
|
1510
|
+
parentId,
|
|
1511
|
+
name: field.name,
|
|
1512
|
+
});
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
hasNextPage = page.hasNextPage;
|
|
1516
|
+
cursor = page.nextCursor;
|
|
1517
|
+
}
|
|
1518
|
+
return null;
|
|
1519
|
+
}, _SLPDataAPI_parseSwapImpactConfig = function _SLPDataAPI_parseSwapImpactConfig(raw) {
|
|
1520
|
+
const { fields } = raw.data.content;
|
|
1521
|
+
return {
|
|
1522
|
+
id: fields.id.id,
|
|
1523
|
+
enabled: fields.enabled,
|
|
1524
|
+
impactMultiplier: (0, utils_2.parseValue)(fields.impact_multiplier),
|
|
1525
|
+
maxImpactRate: (0, utils_2.parseValue)(fields.max_impact_rate),
|
|
1526
|
+
};
|
|
1527
|
+
}, _SLPDataAPI_parseEmaVolatilityFeeConfig = function _SLPDataAPI_parseEmaVolatilityFeeConfig(raw) {
|
|
1528
|
+
const { fields } = raw.data.content;
|
|
1529
|
+
return {
|
|
1530
|
+
id: fields.id.id,
|
|
1531
|
+
enabled: fields.enabled,
|
|
1532
|
+
multiplier: (0, utils_2.parseValue)(fields.multiplier),
|
|
1533
|
+
maxFeeRate: (0, utils_2.parseValue)(fields.max_fee_rate),
|
|
1534
|
+
};
|
|
1535
|
+
}, _SLPDataAPI_computeSwapImpactFeeValue = function _SLPDataAPI_computeSwapImpactFeeValue(swapValue, totalVaultsValue, impactMultiplier, maxImpactRate) {
|
|
1536
|
+
if (swapValue <= 0 || totalVaultsValue <= 0)
|
|
1537
|
+
return 0;
|
|
1538
|
+
const utilization = swapValue / totalVaultsValue;
|
|
1539
|
+
const rawImpactRate = impactMultiplier * utilization;
|
|
1540
|
+
const impactRate = Math.min(rawImpactRate, maxImpactRate);
|
|
1541
|
+
return swapValue * impactRate;
|
|
1542
|
+
}, _SLPDataAPI_computeEmaVolatilityFeeValue = function _SLPDataAPI_computeEmaVolatilityFeeValue(swapValue, maxDiv, multiplier, maxFeeRate) {
|
|
1543
|
+
if (swapValue <= 0 || maxDiv <= 0)
|
|
1544
|
+
return 0;
|
|
1545
|
+
const rawFeeRate = multiplier * maxDiv;
|
|
1546
|
+
const feeRate = Math.min(rawFeeRate, maxFeeRate);
|
|
1547
|
+
return swapValue * feeRate;
|
|
1548
|
+
}, _SLPDataAPI_maxEmaDivergenceRate = function _SLPDataAPI_maxEmaDivergenceRate(sourceFeed, destFeed) {
|
|
1549
|
+
const sourceDiv = __classPrivateFieldGet(_a, _a, "m", _SLPDataAPI_emaDivergenceRate).call(_a, sourceFeed);
|
|
1550
|
+
const destDiv = __classPrivateFieldGet(_a, _a, "m", _SLPDataAPI_emaDivergenceRate).call(_a, destFeed);
|
|
1551
|
+
return Math.max(sourceDiv, destDiv);
|
|
1552
|
+
}, _SLPDataAPI_emaDivergenceRate = function _SLPDataAPI_emaDivergenceRate(priceFeed) {
|
|
1553
|
+
const price = priceFeed.getPriceUnchecked().getPriceAsNumberUnchecked();
|
|
1554
|
+
const ema = priceFeed.getEmaPriceUnchecked().getPriceAsNumberUnchecked();
|
|
1555
|
+
const denom = Math.abs(price);
|
|
1556
|
+
if (denom === 0)
|
|
1557
|
+
return 0;
|
|
1558
|
+
return Math.abs(price - ema) / denom;
|
|
1559
|
+
};
|
|
1384
1560
|
//# sourceMappingURL=SLPDataAPI.cjs.map
|