@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
|
@@ -5,6 +5,12 @@
|
|
|
5
5
|
* SLP DataAPI implementation
|
|
6
6
|
* Implements SLP-specific data access methods for Sudo SDK
|
|
7
7
|
*/
|
|
8
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
10
|
+
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");
|
|
11
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
+
};
|
|
13
|
+
var _SLPDataAPI_instances, _a, _SLPDataAPI_getTotalVaultsValueUsd, _SLPDataAPI_getSwapImpactConfig, _SLPDataAPI_getEmaVolatilityFeeConfig, _SLPDataAPI_getMarketDynamicFieldObjectByKeySuffix, _SLPDataAPI_parseSwapImpactConfig, _SLPDataAPI_parseEmaVolatilityFeeConfig, _SLPDataAPI_computeSwapImpactFeeValue, _SLPDataAPI_computeEmaVolatilityFeeValue, _SLPDataAPI_maxEmaDivergenceRate, _SLPDataAPI_emaDivergenceRate;
|
|
8
14
|
import { Transaction } from "@mysten/sui/transactions";
|
|
9
15
|
import { SUI_CLOCK_OBJECT_ID } from "@mysten/sui/utils";
|
|
10
16
|
import { BaseDataAPI } from "../abstract/index.mjs";
|
|
@@ -16,6 +22,7 @@ const SECONDS_PER_EIGHT_HOUR = 8 * 60 * 60; // 28800 seconds
|
|
|
16
22
|
export class SLPDataAPI extends BaseDataAPI {
|
|
17
23
|
constructor(network, provider, apiEndpoint, connectionURL) {
|
|
18
24
|
super(network, provider, apiEndpoint, connectionURL, LPToken.SLP);
|
|
25
|
+
_SLPDataAPI_instances.add(this);
|
|
19
26
|
}
|
|
20
27
|
static calculateVaultReservingFee(vaultInfo, reservingFeeModel, currentTime) {
|
|
21
28
|
const timeDelta = currentTime - vaultInfo.lastUpdate;
|
|
@@ -23,8 +30,8 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
23
30
|
return vaultInfo.unrealisedReservingFeeAmount
|
|
24
31
|
+ (vaultInfo.reservedAmount * reservingFeeModel.multiplier * periods) / 1e18;
|
|
25
32
|
}
|
|
26
|
-
static calculateSymbolFundingFee(symbol, model, price, lpSupplyAmount, timestamp,
|
|
27
|
-
const accFundingRate =
|
|
33
|
+
static calculateSymbolFundingFee(symbol, model, price, lpSupplyAmount, timestamp, oiState, pairedOpeningSize) {
|
|
34
|
+
const accFundingRate = _a.calcAccFundingFeeRate(symbol, model, price, lpSupplyAmount, timestamp, symbol.long, oiState, pairedOpeningSize);
|
|
28
35
|
return symbol.unrealisedFundingFeeValue + (accFundingRate - symbol.accFundingRate) * symbol.openingSize;
|
|
29
36
|
}
|
|
30
37
|
async getRebaseFeeModel() {
|
|
@@ -38,8 +45,8 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
38
45
|
showContent: true,
|
|
39
46
|
},
|
|
40
47
|
});
|
|
41
|
-
const model =
|
|
42
|
-
const exponent = await
|
|
48
|
+
const model = _a.parseRebaseFeeModel(rawData);
|
|
49
|
+
const exponent = await _a.getRebaseFeeExponent(this.provider, this.consts.sudoCore.rebaseFeeModel, this.consts.sudoCore.upgradedPackage);
|
|
43
50
|
return { ...model, exponent };
|
|
44
51
|
}
|
|
45
52
|
/**
|
|
@@ -125,27 +132,30 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
125
132
|
const marketInfo = await this.getMarketInfo();
|
|
126
133
|
let slpPrice = 0;
|
|
127
134
|
let value = 0;
|
|
128
|
-
const
|
|
135
|
+
const vaultKeys = Object.keys(this.consts.sudoCore.vaults);
|
|
136
|
+
const vaultData = await Promise.all(vaultKeys.map(async (vault) => {
|
|
129
137
|
const vaultInfo = await this.getVaultInfo(vault);
|
|
130
|
-
const reservingFeeDelta =
|
|
138
|
+
const reservingFeeDelta = _a.calculateVaultReservingFee(vaultInfo, vaultInfo.reservingFeeModel, Date.now() / 1000);
|
|
131
139
|
const totalVaultAmount = reservingFeeDelta + vaultInfo.liquidity + vaultInfo.reservedAmount;
|
|
132
140
|
const oraclePrice = (await this.getOraclePrice(vault)).getPriceUnchecked().getPriceAsNumberUnchecked();
|
|
133
141
|
const { decimals } = this.consts.coins[vault];
|
|
134
142
|
const vaultValue = totalVaultAmount * oraclePrice / (10 ** decimals);
|
|
135
|
-
return vaultValue;
|
|
136
|
-
});
|
|
143
|
+
return { vault, oraclePrice, vaultValue };
|
|
144
|
+
}));
|
|
145
|
+
const vaultPrices = Object.fromEntries(vaultData.map(d => [d.vault, d.oraclePrice]));
|
|
146
|
+
const vaultValues = vaultData.map(d => d.vaultValue);
|
|
137
147
|
const symbolPromises = Object.keys(this.consts.sudoCore.symbols).map(async (symbol) => {
|
|
138
148
|
const [direction, tokenId] = parseSymbolKey(symbol);
|
|
139
149
|
const symbolInfo = await this.getSymbolInfo(tokenId, direction === 'long');
|
|
140
150
|
const price = (await this.getOraclePrice(tokenId)).getPriceUnchecked().getPriceAsNumberUnchecked();
|
|
141
|
-
const deltaSize =
|
|
151
|
+
const deltaSize = _a.calcDeltaSize(symbolInfo, price, direction === 'long');
|
|
142
152
|
const oiState = await this.getSymbolOiFundingState(tokenId);
|
|
143
153
|
const pairedInfo = await this.getSymbolInfo(tokenId, direction !== 'long');
|
|
144
|
-
const fundingFeeDelta =
|
|
154
|
+
const fundingFeeDelta = _a.calculateSymbolFundingFee(symbolInfo, symbolInfo.fundingFeeModel, price, marketInfo.lpSupplyWithDecimals, Date.now() / 1000, oiState && oiState.enabled ? oiState : undefined, pairedInfo.openingSize);
|
|
145
155
|
const symbolValue = fundingFeeDelta + deltaSize;
|
|
146
156
|
return symbolValue;
|
|
147
157
|
});
|
|
148
|
-
const
|
|
158
|
+
const symbolValues = await Promise.all(symbolPromises);
|
|
149
159
|
const totalVaultValue = vaultValues.reduce((acc, curr) => acc + curr, 0);
|
|
150
160
|
const totalSymbolValue = symbolValues.reduce((acc, curr) => acc + curr, 0);
|
|
151
161
|
value = totalVaultValue + totalSymbolValue;
|
|
@@ -155,6 +165,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
155
165
|
price: slpPrice,
|
|
156
166
|
supply: marketInfo.lpSupplyWithDecimals,
|
|
157
167
|
apr: Number(marketInfo.apr),
|
|
168
|
+
vaultPrices,
|
|
158
169
|
};
|
|
159
170
|
}
|
|
160
171
|
/**
|
|
@@ -201,11 +212,18 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
201
212
|
const marketInfo = await this.getMarketInfo();
|
|
202
213
|
const value = await this.simValuateVaults(this.consts.sudoCore.adminCap);
|
|
203
214
|
const slpPrice = value / marketInfo.lpSupplyWithDecimals;
|
|
215
|
+
const vaultKeys = Object.keys(this.consts.sudoCore.vaults);
|
|
216
|
+
const vaultPricesEntries = await Promise.all(vaultKeys.map(async (vault) => {
|
|
217
|
+
const oraclePrice = (await this.getOraclePrice(vault)).getPriceUnchecked().getPriceAsNumberUnchecked();
|
|
218
|
+
return [vault, oraclePrice];
|
|
219
|
+
}));
|
|
220
|
+
const vaultPrices = Object.fromEntries(vaultPricesEntries);
|
|
204
221
|
return {
|
|
205
222
|
marketCap: value,
|
|
206
223
|
price: slpPrice,
|
|
207
224
|
supply: marketInfo.lpSupplyWithDecimals,
|
|
208
225
|
apr: Number(marketInfo.apr),
|
|
226
|
+
vaultPrices,
|
|
209
227
|
};
|
|
210
228
|
}
|
|
211
229
|
/**
|
|
@@ -224,7 +242,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
224
242
|
});
|
|
225
243
|
const apr = await this.getCumulativeApr();
|
|
226
244
|
return {
|
|
227
|
-
...
|
|
245
|
+
..._a.parseMarketInfo(rawData),
|
|
228
246
|
apr,
|
|
229
247
|
};
|
|
230
248
|
}
|
|
@@ -276,7 +294,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
276
294
|
value: { dummy_field: false },
|
|
277
295
|
},
|
|
278
296
|
});
|
|
279
|
-
return
|
|
297
|
+
return _a.parseSymbolConfig(rawData);
|
|
280
298
|
}
|
|
281
299
|
catch {
|
|
282
300
|
// If the dynamic field doesn't exist, return null
|
|
@@ -298,7 +316,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
298
316
|
value: { dummy_field: false },
|
|
299
317
|
},
|
|
300
318
|
});
|
|
301
|
-
return
|
|
319
|
+
return _a.parsePriceImpactConfig(rawData);
|
|
302
320
|
}
|
|
303
321
|
catch (e) {
|
|
304
322
|
// If the dynamic field doesn't exist, return null (price impact not configured for this symbol)
|
|
@@ -319,7 +337,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
319
337
|
value: { dummy_field: false },
|
|
320
338
|
},
|
|
321
339
|
});
|
|
322
|
-
return
|
|
340
|
+
return _a.parseOiFundingState(rawData);
|
|
323
341
|
}
|
|
324
342
|
catch (e) {
|
|
325
343
|
// If the dynamic field doesn't exist, return null
|
|
@@ -327,6 +345,52 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
327
345
|
return null;
|
|
328
346
|
}
|
|
329
347
|
}
|
|
348
|
+
async calculateSwapFeeBreakdown(fromToken, toToken, fromAmount) {
|
|
349
|
+
if (!this.consts.sudoCore) {
|
|
350
|
+
throw new Error('Sudo Core configuration not found. Make sure you are using LPToken.SLP');
|
|
351
|
+
}
|
|
352
|
+
const timestamp = Date.now() / 1000;
|
|
353
|
+
const fromDecimals = this.consts.coins[fromToken]?.decimals;
|
|
354
|
+
const toDecimals = this.consts.coins[toToken]?.decimals;
|
|
355
|
+
if (fromDecimals === undefined || toDecimals === undefined) {
|
|
356
|
+
throw new Error(`Unknown token decimals for swap: ${fromToken} -> ${toToken}`);
|
|
357
|
+
}
|
|
358
|
+
const fromFeed = await this.getOraclePrice(fromToken);
|
|
359
|
+
const toFeed = await this.getOraclePrice(toToken);
|
|
360
|
+
const fromPrice = fromFeed.getPriceUnchecked().getPriceAsNumberUnchecked();
|
|
361
|
+
const toPrice = toFeed.getPriceUnchecked().getPriceAsNumberUnchecked();
|
|
362
|
+
const swapValue = (fromAmount * fromPrice) / (10 ** fromDecimals);
|
|
363
|
+
const totalVaultsValue = await __classPrivateFieldGet(this, _SLPDataAPI_instances, "m", _SLPDataAPI_getTotalVaultsValueUsd).call(this, timestamp);
|
|
364
|
+
const rebaseFeeInRate = await this.rebaseFeeRate(fromToken, true, fromAmount);
|
|
365
|
+
const rebaseFeeInValue = swapValue * rebaseFeeInRate;
|
|
366
|
+
const estimatedToAmount = toPrice !== 0
|
|
367
|
+
? (swapValue * (10 ** toDecimals)) / toPrice
|
|
368
|
+
: 0;
|
|
369
|
+
const rebaseFeeOutRate = await this.rebaseFeeRate(toToken, false, estimatedToAmount);
|
|
370
|
+
const rebaseFeeOutValue = swapValue * rebaseFeeOutRate;
|
|
371
|
+
const swapImpactCfg = await __classPrivateFieldGet(this, _SLPDataAPI_instances, "m", _SLPDataAPI_getSwapImpactConfig).call(this);
|
|
372
|
+
const swapImpactFeeValue = swapImpactCfg?.enabled
|
|
373
|
+
? __classPrivateFieldGet(_a, _a, "m", _SLPDataAPI_computeSwapImpactFeeValue).call(_a, swapValue, totalVaultsValue, swapImpactCfg.impactMultiplier, swapImpactCfg.maxImpactRate)
|
|
374
|
+
: 0;
|
|
375
|
+
const emaCfg = await __classPrivateFieldGet(this, _SLPDataAPI_instances, "m", _SLPDataAPI_getEmaVolatilityFeeConfig).call(this);
|
|
376
|
+
const emaVolatilityFeeValue = emaCfg?.enabled
|
|
377
|
+
? __classPrivateFieldGet(_a, _a, "m", _SLPDataAPI_computeEmaVolatilityFeeValue).call(_a, swapValue, __classPrivateFieldGet(_a, _a, "m", _SLPDataAPI_maxEmaDivergenceRate).call(_a, fromFeed, toFeed), emaCfg.multiplier, emaCfg.maxFeeRate)
|
|
378
|
+
: 0;
|
|
379
|
+
const totalFeeValue = rebaseFeeInValue + rebaseFeeOutValue + swapImpactFeeValue + emaVolatilityFeeValue;
|
|
380
|
+
const totalFeeRate = swapValue !== 0 ? totalFeeValue / swapValue : 0;
|
|
381
|
+
return {
|
|
382
|
+
swapValue,
|
|
383
|
+
totalVaultsValue,
|
|
384
|
+
rebaseFeeInRate,
|
|
385
|
+
rebaseFeeOutRate,
|
|
386
|
+
rebaseFeeInValue,
|
|
387
|
+
rebaseFeeOutValue,
|
|
388
|
+
swapImpactFeeValue,
|
|
389
|
+
emaVolatilityFeeValue,
|
|
390
|
+
totalFeeValue,
|
|
391
|
+
totalFeeRate,
|
|
392
|
+
};
|
|
393
|
+
}
|
|
330
394
|
async getPositionInfoList(positionCapInfoList, owner, batchSize = 10) {
|
|
331
395
|
const positionInfoList = [];
|
|
332
396
|
// Process in batches of 10
|
|
@@ -418,7 +482,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
418
482
|
rawCredentialsData = [...rawCredentialsData, ...data];
|
|
419
483
|
}
|
|
420
484
|
const pool = await this.getStakePool();
|
|
421
|
-
const credentials = rawCredentialsData.map((item) =>
|
|
485
|
+
const credentials = rawCredentialsData.map((item) => _a.parseCredential(item, pool));
|
|
422
486
|
return {
|
|
423
487
|
credentials,
|
|
424
488
|
amount: credentials.reduce((acc, cur) => acc + cur.amount, BigInt(0)),
|
|
@@ -435,7 +499,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
435
499
|
showContent: true,
|
|
436
500
|
},
|
|
437
501
|
});
|
|
438
|
-
return
|
|
502
|
+
return _a.parseStakePool(raw);
|
|
439
503
|
}
|
|
440
504
|
async getStakePoolV2() {
|
|
441
505
|
const poolId = this.sharedConfig.zoStaking.pools.slp;
|
|
@@ -445,7 +509,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
445
509
|
showContent: true,
|
|
446
510
|
},
|
|
447
511
|
});
|
|
448
|
-
return
|
|
512
|
+
return _a.parseStakePool(raw);
|
|
449
513
|
}
|
|
450
514
|
async getStakedV2(owner) {
|
|
451
515
|
let rawCredentialsData = [];
|
|
@@ -478,7 +542,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
478
542
|
const credentials = rawCredentialsData
|
|
479
543
|
.filter((item) => item.data.type
|
|
480
544
|
=== `${this.sharedConfig.zoStaking.package}::pool::Credential<${this.consts.sudoCore.package}::slp::SLP, ${this.consts.sudoCore.package}::slp::SLP>`)
|
|
481
|
-
.map((item) =>
|
|
545
|
+
.map((item) => _a.parseCredential(item, pool));
|
|
482
546
|
return {
|
|
483
547
|
credentials,
|
|
484
548
|
amount: credentials.reduce((acc, cur) => acc + cur.amount, BigInt(0)),
|
|
@@ -494,7 +558,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
494
558
|
return 0;
|
|
495
559
|
}
|
|
496
560
|
const elapsed = SECONDS_PER_EIGHT_HOUR;
|
|
497
|
-
const deltaRate =
|
|
561
|
+
const deltaRate = _a.calcOiFundingFeeRate(oiState.model, longSymbol.openingSize, shortSymbol.openingSize, elapsed, oiState.maxOiLong, oiState.maxOiShort);
|
|
498
562
|
return long ? deltaRate : -deltaRate;
|
|
499
563
|
}
|
|
500
564
|
const symbol = await this.getSymbolInfo(indexToken, long);
|
|
@@ -505,9 +569,9 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
505
569
|
const lpSupplyAmount = (await this.getMarketInfo()).lpSupplyWithDecimals;
|
|
506
570
|
const model = symbol.fundingFeeModel;
|
|
507
571
|
const elapsed = SECONDS_PER_EIGHT_HOUR;
|
|
508
|
-
const deltaSize =
|
|
572
|
+
const deltaSize = _a.calcDeltaSize(symbol, price, symbol.long);
|
|
509
573
|
const pnlPerLp = (symbol.realisedPnl + symbol.unrealisedFundingFeeValue + deltaSize) / lpSupplyAmount;
|
|
510
|
-
return
|
|
574
|
+
return _a.calcFundingFeeRate(model, pnlPerLp, elapsed);
|
|
511
575
|
}
|
|
512
576
|
async rebaseFeeRate(collateralToken, increase, amount, _sender) {
|
|
513
577
|
let vaultValue = 0;
|
|
@@ -517,7 +581,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
517
581
|
const value = amount * (await this.getOraclePrice(collateralToken)).getPriceUnchecked().getPriceAsNumberUnchecked() / (10 ** this.consts.coins[collateralToken].decimals);
|
|
518
582
|
const vaultPromises = Object.keys(this.consts.sudoCore.vaults).map(async (vault) => {
|
|
519
583
|
const vaultInfo = await this.getVaultInfo(vault);
|
|
520
|
-
const reservingFeeDelta =
|
|
584
|
+
const reservingFeeDelta = _a.calculateVaultReservingFee(vaultInfo, vaultInfo.reservingFeeModel, Date.now() / 1000);
|
|
521
585
|
const totalVaultAmount = reservingFeeDelta + vaultInfo.liquidity + vaultInfo.reservedAmount;
|
|
522
586
|
const oraclePrice = (await this.getOraclePrice(vault)).getPriceUnchecked().getPriceAsNumberUnchecked();
|
|
523
587
|
const res = totalVaultAmount * oraclePrice / (10 ** this.consts.coins[vault].decimals);
|
|
@@ -531,7 +595,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
531
595
|
const targetRatio = Number.parseInt(this.consts.sudoCore.vaults[collateralToken].weight, 10) / Object.values(this.consts.sudoCore.vaults)
|
|
532
596
|
.map(e => Number.parseInt(e.weight, 10))
|
|
533
597
|
.reduce((acc, curr) => acc + curr, 0);
|
|
534
|
-
return
|
|
598
|
+
return _a.calcRebaseFeeRate(await this.getRebaseFeeModel(), increase, (vaultValue + value) / (totalVaultValue + value), targetRatio);
|
|
535
599
|
}
|
|
536
600
|
async reservingFeeRate(collateralToken, amount, sender) {
|
|
537
601
|
if (!sender) {
|
|
@@ -573,7 +637,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
573
637
|
showContent: true,
|
|
574
638
|
},
|
|
575
639
|
});
|
|
576
|
-
return
|
|
640
|
+
return _a.parsePositionConfig(rawData);
|
|
577
641
|
}
|
|
578
642
|
async getOpenPositions(batchSize = 50, symbol = 'sui') {
|
|
579
643
|
let positionDynamicFields = [];
|
|
@@ -791,26 +855,26 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
791
855
|
return aprResponse.apr;
|
|
792
856
|
}
|
|
793
857
|
// Private helper methods
|
|
794
|
-
static calculatePositionFundingFee(position, symbol, model, price, lpSupplyAmount, timestamp,
|
|
795
|
-
const accFundingRate = this.calcAccFundingFeeRate(symbol, model, price, lpSupplyAmount, timestamp, position.long,
|
|
858
|
+
static calculatePositionFundingFee(position, symbol, model, price, lpSupplyAmount, timestamp, oiState, pairedOpeningSize) {
|
|
859
|
+
const accFundingRate = this.calcAccFundingFeeRate(symbol, model, price, lpSupplyAmount, timestamp, position.long, oiState, pairedOpeningSize);
|
|
796
860
|
return position.fundingFeeValue + (accFundingRate - position.lastFundingRate) * position.positionSize;
|
|
797
861
|
}
|
|
798
|
-
static calcAccFundingFeeRate(symbol, model, price, lpSupplyAmount, timestamp, isLong,
|
|
862
|
+
static calcAccFundingFeeRate(symbol, model, price, lpSupplyAmount, timestamp, isLong, oiState, pairedOpeningSize) {
|
|
799
863
|
if (symbol.lastUpdate > 0) {
|
|
800
864
|
const elapsed = timestamp - symbol.lastUpdate;
|
|
801
865
|
if (elapsed > 0) {
|
|
802
|
-
// Prefer OI-based delta when OI
|
|
803
|
-
if (
|
|
866
|
+
// Prefer OI-based delta when OI state and paired side are available
|
|
867
|
+
if (oiState?.enabled && oiState.model && typeof pairedOpeningSize === 'number') {
|
|
804
868
|
const longSize = isLong ? symbol.openingSize : pairedOpeningSize;
|
|
805
869
|
const shortSize = isLong ? pairedOpeningSize : symbol.openingSize;
|
|
806
|
-
const deltaRate =
|
|
870
|
+
const deltaRate = _a.calcOiFundingFeeRate(oiState.model, longSize, shortSize, elapsed, oiState.maxOiLong, oiState.maxOiShort);
|
|
807
871
|
const appliedRate = isLong ? deltaRate : -deltaRate;
|
|
808
872
|
return symbol.accFundingRate + appliedRate;
|
|
809
873
|
}
|
|
810
874
|
// Fallback to PnL-based funding delta
|
|
811
875
|
const deltaSize = this.calcDeltaSize(symbol, price, isLong);
|
|
812
876
|
const pnlPerLp = (symbol.realisedPnl + symbol.unrealisedFundingFeeValue + deltaSize) / lpSupplyAmount;
|
|
813
|
-
return symbol.accFundingRate +
|
|
877
|
+
return symbol.accFundingRate + _a.calcFundingFeeRate(model, pnlPerLp, elapsed);
|
|
814
878
|
}
|
|
815
879
|
}
|
|
816
880
|
return symbol.accFundingRate;
|
|
@@ -824,23 +888,44 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
824
888
|
const secondsRate = dailyRate * elapsed / SECONDS_PER_EIGHT_HOUR;
|
|
825
889
|
return pnlPerRate >= 0 ? -secondsRate : secondsRate;
|
|
826
890
|
}
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
891
|
+
/**
|
|
892
|
+
* OI funding rate matching Move compute_oi_funding_rate_capped.
|
|
893
|
+
* When both maxOiLong and maxOiShort are set and > 0, uses normalized skew (oi/cap);
|
|
894
|
+
* otherwise falls back to (long - short) / total.
|
|
895
|
+
*/
|
|
896
|
+
static calcOiFundingFeeRate(model, oiLong, oiShort, elapsed, maxOiLong, maxOiShort) {
|
|
897
|
+
let skew;
|
|
898
|
+
if (maxOiLong && maxOiShort && maxOiLong > 0 && maxOiShort > 0) {
|
|
899
|
+
const normLong = Math.min(oiLong / maxOiLong, 1);
|
|
900
|
+
const normShort = Math.min(oiShort / maxOiShort, 1);
|
|
901
|
+
skew = normLong - normShort;
|
|
902
|
+
}
|
|
903
|
+
else {
|
|
904
|
+
const total = oiLong + oiShort;
|
|
905
|
+
if (total === 0)
|
|
906
|
+
return 0;
|
|
907
|
+
skew = (oiLong - oiShort) / total;
|
|
908
|
+
}
|
|
909
|
+
if (skew === 0)
|
|
910
|
+
return 0;
|
|
911
|
+
const skewIsPositive = skew > 0;
|
|
912
|
+
const skewAbs = Math.abs(skew);
|
|
913
|
+
const exponentInt = Math.floor(model.exponent);
|
|
914
|
+
const skewPow = skewAbs ** exponentInt;
|
|
915
|
+
const dailyRate = Math.min(model.multiplier * skewPow, model.max);
|
|
916
|
+
const secondsRate = (dailyRate * elapsed) / SECONDS_PER_EIGHT_HOUR;
|
|
917
|
+
return skewIsPositive ? secondsRate : -secondsRate;
|
|
833
918
|
}
|
|
834
919
|
static calculatePositionReserveFee(position, vault, model, timestamp) {
|
|
835
|
-
const accReservingRate =
|
|
920
|
+
const accReservingRate = _a.calcAccReservingFeeRate(vault, model, timestamp);
|
|
836
921
|
return position.reservingFeeAmount + (accReservingRate - position.lastReservingRate) * position.reservedAmount;
|
|
837
922
|
}
|
|
838
923
|
static calcAccReservingFeeRate(vault, model, timestamp) {
|
|
839
924
|
if (vault.lastUpdate > 0) {
|
|
840
925
|
const elapsed = timestamp - vault.lastUpdate;
|
|
841
926
|
if (elapsed > 0) {
|
|
842
|
-
const utilization =
|
|
843
|
-
return vault.accReservingRate +
|
|
927
|
+
const utilization = _a.vaultUtilization(vault);
|
|
928
|
+
return vault.accReservingRate + _a.calcReservingFeeRate(model, utilization, elapsed);
|
|
844
929
|
}
|
|
845
930
|
}
|
|
846
931
|
return vault.accReservingRate;
|
|
@@ -1025,8 +1110,8 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
1025
1110
|
else if (endSkew > 1) {
|
|
1026
1111
|
endSkew = 1;
|
|
1027
1112
|
}
|
|
1028
|
-
const avgDynamicRate =
|
|
1029
|
-
const sizeFactor =
|
|
1113
|
+
const avgDynamicRate = _a.computeIntegralAverage(config.maxDynamicSpreadRate, startSkew, endSkew, config.impactExponent);
|
|
1114
|
+
const sizeFactor = _a.computeSizeFactor(newPositionSize, config.referenceSize);
|
|
1030
1115
|
const scaledDynamicRate = avgDynamicRate * sizeFactor;
|
|
1031
1116
|
let totalSpread = config.baseSpreadRate + scaledDynamicRate;
|
|
1032
1117
|
if (totalSpread > config.maxTotalSpreadRate) {
|
|
@@ -1065,8 +1150,8 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
1065
1150
|
const currentOiOpposite = isLong ? shortSymbol.openingSize : longSymbol.openingSize;
|
|
1066
1151
|
const maxOiThisSide = isLong ? config.maxOiLong : config.maxOiShort;
|
|
1067
1152
|
const maxOiOpposite = isLong ? config.maxOiShort : config.maxOiLong;
|
|
1068
|
-
const spreadRate =
|
|
1069
|
-
const adjustedPrice =
|
|
1153
|
+
const spreadRate = _a.computeAverageSpreadRate(config, currentOiThisSide, positionSizeValue, currentOiOpposite, maxOiThisSide, maxOiOpposite);
|
|
1154
|
+
const adjustedPrice = _a.applyPriceImpact(oraclePrice, spreadRate, isLong, isOpening);
|
|
1070
1155
|
return {
|
|
1071
1156
|
spreadRate,
|
|
1072
1157
|
originalPrice: oraclePrice,
|
|
@@ -1092,6 +1177,8 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
1092
1177
|
exponent: parseValue(content.model.fields.exponent),
|
|
1093
1178
|
max: parseValue(content.model.fields.max),
|
|
1094
1179
|
},
|
|
1180
|
+
maxOiLong: content.max_oi_long !== null && content.max_oi_long !== undefined ? parseValue(content.max_oi_long) : undefined,
|
|
1181
|
+
maxOiShort: content.max_oi_short !== null && content.max_oi_short !== undefined ? parseValue(content.max_oi_short) : undefined,
|
|
1095
1182
|
};
|
|
1096
1183
|
}
|
|
1097
1184
|
static parsePriceImpactConfig(raw) {
|
|
@@ -1127,7 +1214,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
1127
1214
|
showContent: true,
|
|
1128
1215
|
},
|
|
1129
1216
|
});
|
|
1130
|
-
const reservingFeeModel =
|
|
1217
|
+
const reservingFeeModel = _a.parseReservingFeeModel(reservingFeeModelRaw);
|
|
1131
1218
|
return {
|
|
1132
1219
|
liquidity: parseValue(vaultFields.liquidity),
|
|
1133
1220
|
reservedAmount: parseValue(vaultFields.reserved_amount),
|
|
@@ -1161,7 +1248,7 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
1161
1248
|
showContent: true,
|
|
1162
1249
|
},
|
|
1163
1250
|
});
|
|
1164
|
-
const fundingFeeModel =
|
|
1251
|
+
const fundingFeeModel = _a.parseFundingFeeModel(fundingFeeModelRaw);
|
|
1165
1252
|
return {
|
|
1166
1253
|
objectId,
|
|
1167
1254
|
openingSize: parseValue(fields.opening_size),
|
|
@@ -1209,11 +1296,11 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
1209
1296
|
};
|
|
1210
1297
|
if (!positionFields.closed) {
|
|
1211
1298
|
try {
|
|
1212
|
-
positionInfo.reservingFeeAmount =
|
|
1299
|
+
positionInfo.reservingFeeAmount = _a.calculatePositionReserveFee(positionInfo, await this.getVaultInfo(positionInfo.collateralToken), (await this.getVaultInfo(positionInfo.collateralToken)).reservingFeeModel, Date.now() / 1000);
|
|
1213
1300
|
// OI context for funding: fetch state and paired side size when enabled
|
|
1214
1301
|
const oiState = await this.getSymbolOiFundingState(positionInfo.indexToken);
|
|
1215
1302
|
const pairedSymbol = await this.getSymbolInfo(positionInfo.indexToken, !positionInfo.long);
|
|
1216
|
-
positionInfo.fundingFeeValue =
|
|
1303
|
+
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);
|
|
1217
1304
|
}
|
|
1218
1305
|
catch (e) {
|
|
1219
1306
|
console.error(e);
|
|
@@ -1336,10 +1423,10 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
1336
1423
|
};
|
|
1337
1424
|
// Use appropriate refresh method based on version
|
|
1338
1425
|
if (isNewVersion) {
|
|
1339
|
-
|
|
1426
|
+
_a.refreshPoolV2(pool, Math.floor(Date.now() / 1000));
|
|
1340
1427
|
}
|
|
1341
1428
|
else {
|
|
1342
|
-
|
|
1429
|
+
_a.refreshPool(pool, Math.floor(Date.now() / 1000));
|
|
1343
1430
|
}
|
|
1344
1431
|
return pool;
|
|
1345
1432
|
}
|
|
@@ -1377,4 +1464,93 @@ export class SLPDataAPI extends BaseDataAPI {
|
|
|
1377
1464
|
pool.lastUpdatedTime = calculationEndTime;
|
|
1378
1465
|
}
|
|
1379
1466
|
}
|
|
1467
|
+
_a = SLPDataAPI, _SLPDataAPI_instances = new WeakSet(), _SLPDataAPI_getTotalVaultsValueUsd = async function _SLPDataAPI_getTotalVaultsValueUsd(timestamp) {
|
|
1468
|
+
if (!this.consts.sudoCore) {
|
|
1469
|
+
return 0;
|
|
1470
|
+
}
|
|
1471
|
+
const vaultKeys = Object.keys(this.consts.sudoCore.vaults);
|
|
1472
|
+
const vaultValues = await Promise.all(vaultKeys.map(async (vault) => {
|
|
1473
|
+
const vaultInfo = await this.getVaultInfo(vault);
|
|
1474
|
+
const reservingFeeDelta = _a.calculateVaultReservingFee(vaultInfo, vaultInfo.reservingFeeModel, timestamp);
|
|
1475
|
+
const totalVaultAmount = reservingFeeDelta + vaultInfo.liquidity + vaultInfo.reservedAmount;
|
|
1476
|
+
const oraclePrice = (await this.getOraclePrice(vault)).getPriceUnchecked().getPriceAsNumberUnchecked();
|
|
1477
|
+
const { decimals } = this.consts.coins[vault];
|
|
1478
|
+
return totalVaultAmount * oraclePrice / (10 ** decimals);
|
|
1479
|
+
}));
|
|
1480
|
+
return vaultValues.reduce((acc, curr) => acc + curr, 0);
|
|
1481
|
+
}, _SLPDataAPI_getSwapImpactConfig = async function _SLPDataAPI_getSwapImpactConfig() {
|
|
1482
|
+
if (!this.consts.sudoCore) {
|
|
1483
|
+
return null;
|
|
1484
|
+
}
|
|
1485
|
+
const raw = await __classPrivateFieldGet(this, _SLPDataAPI_instances, "m", _SLPDataAPI_getMarketDynamicFieldObjectByKeySuffix).call(this, this.consts.sudoCore.market, 'SwapImpactConfigKey');
|
|
1486
|
+
if (!raw)
|
|
1487
|
+
return null;
|
|
1488
|
+
return __classPrivateFieldGet(_a, _a, "m", _SLPDataAPI_parseSwapImpactConfig).call(_a, raw);
|
|
1489
|
+
}, _SLPDataAPI_getEmaVolatilityFeeConfig = async function _SLPDataAPI_getEmaVolatilityFeeConfig() {
|
|
1490
|
+
if (!this.consts.sudoCore) {
|
|
1491
|
+
return null;
|
|
1492
|
+
}
|
|
1493
|
+
const raw = await __classPrivateFieldGet(this, _SLPDataAPI_instances, "m", _SLPDataAPI_getMarketDynamicFieldObjectByKeySuffix).call(this, this.consts.sudoCore.market, 'EmaVolatilityFeeConfigKey');
|
|
1494
|
+
if (!raw)
|
|
1495
|
+
return null;
|
|
1496
|
+
return __classPrivateFieldGet(_a, _a, "m", _SLPDataAPI_parseEmaVolatilityFeeConfig).call(_a, raw);
|
|
1497
|
+
}, _SLPDataAPI_getMarketDynamicFieldObjectByKeySuffix = async function _SLPDataAPI_getMarketDynamicFieldObjectByKeySuffix(parentId, keyTypeSuffix) {
|
|
1498
|
+
let cursor;
|
|
1499
|
+
let hasNextPage = true;
|
|
1500
|
+
while (hasNextPage) {
|
|
1501
|
+
const page = await this.provider.getDynamicFields({ parentId, cursor });
|
|
1502
|
+
for (const field of page.data) {
|
|
1503
|
+
const type = field.name?.type;
|
|
1504
|
+
if (typeof type === 'string' && type.endsWith(`::${keyTypeSuffix}`)) {
|
|
1505
|
+
return await this.provider.getDynamicFieldObject({
|
|
1506
|
+
parentId,
|
|
1507
|
+
name: field.name,
|
|
1508
|
+
});
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
hasNextPage = page.hasNextPage;
|
|
1512
|
+
cursor = page.nextCursor;
|
|
1513
|
+
}
|
|
1514
|
+
return null;
|
|
1515
|
+
}, _SLPDataAPI_parseSwapImpactConfig = function _SLPDataAPI_parseSwapImpactConfig(raw) {
|
|
1516
|
+
const { fields } = raw.data.content;
|
|
1517
|
+
return {
|
|
1518
|
+
id: fields.id.id,
|
|
1519
|
+
enabled: fields.enabled,
|
|
1520
|
+
impactMultiplier: parseValue(fields.impact_multiplier),
|
|
1521
|
+
maxImpactRate: parseValue(fields.max_impact_rate),
|
|
1522
|
+
};
|
|
1523
|
+
}, _SLPDataAPI_parseEmaVolatilityFeeConfig = function _SLPDataAPI_parseEmaVolatilityFeeConfig(raw) {
|
|
1524
|
+
const { fields } = raw.data.content;
|
|
1525
|
+
return {
|
|
1526
|
+
id: fields.id.id,
|
|
1527
|
+
enabled: fields.enabled,
|
|
1528
|
+
multiplier: parseValue(fields.multiplier),
|
|
1529
|
+
maxFeeRate: parseValue(fields.max_fee_rate),
|
|
1530
|
+
};
|
|
1531
|
+
}, _SLPDataAPI_computeSwapImpactFeeValue = function _SLPDataAPI_computeSwapImpactFeeValue(swapValue, totalVaultsValue, impactMultiplier, maxImpactRate) {
|
|
1532
|
+
if (swapValue <= 0 || totalVaultsValue <= 0)
|
|
1533
|
+
return 0;
|
|
1534
|
+
const utilization = swapValue / totalVaultsValue;
|
|
1535
|
+
const rawImpactRate = impactMultiplier * utilization;
|
|
1536
|
+
const impactRate = Math.min(rawImpactRate, maxImpactRate);
|
|
1537
|
+
return swapValue * impactRate;
|
|
1538
|
+
}, _SLPDataAPI_computeEmaVolatilityFeeValue = function _SLPDataAPI_computeEmaVolatilityFeeValue(swapValue, maxDiv, multiplier, maxFeeRate) {
|
|
1539
|
+
if (swapValue <= 0 || maxDiv <= 0)
|
|
1540
|
+
return 0;
|
|
1541
|
+
const rawFeeRate = multiplier * maxDiv;
|
|
1542
|
+
const feeRate = Math.min(rawFeeRate, maxFeeRate);
|
|
1543
|
+
return swapValue * feeRate;
|
|
1544
|
+
}, _SLPDataAPI_maxEmaDivergenceRate = function _SLPDataAPI_maxEmaDivergenceRate(sourceFeed, destFeed) {
|
|
1545
|
+
const sourceDiv = __classPrivateFieldGet(_a, _a, "m", _SLPDataAPI_emaDivergenceRate).call(_a, sourceFeed);
|
|
1546
|
+
const destDiv = __classPrivateFieldGet(_a, _a, "m", _SLPDataAPI_emaDivergenceRate).call(_a, destFeed);
|
|
1547
|
+
return Math.max(sourceDiv, destDiv);
|
|
1548
|
+
}, _SLPDataAPI_emaDivergenceRate = function _SLPDataAPI_emaDivergenceRate(priceFeed) {
|
|
1549
|
+
const price = priceFeed.getPriceUnchecked().getPriceAsNumberUnchecked();
|
|
1550
|
+
const ema = priceFeed.getEmaPriceUnchecked().getPriceAsNumberUnchecked();
|
|
1551
|
+
const denom = Math.abs(price);
|
|
1552
|
+
if (denom === 0)
|
|
1553
|
+
return 0;
|
|
1554
|
+
return Math.abs(price - ema) / denom;
|
|
1555
|
+
};
|
|
1380
1556
|
//# sourceMappingURL=SLPDataAPI.mjs.map
|