@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
|
@@ -15,6 +15,7 @@ import type {
|
|
|
15
15
|
IBaseHistoryResponse,
|
|
16
16
|
IBaseOrderType,
|
|
17
17
|
IBaseStaked,
|
|
18
|
+
ISwapFeeBreakdown,
|
|
18
19
|
IZLPCredential,
|
|
19
20
|
IZLPDataAPI,
|
|
20
21
|
IZLPFundingFeeModel,
|
|
@@ -37,6 +38,20 @@ import type {
|
|
|
37
38
|
} from '../interfaces'
|
|
38
39
|
import { joinSymbol, parseSymbolKey, parseValue, suiSymbolToSymbol } from '../utils'
|
|
39
40
|
|
|
41
|
+
interface SwapImpactConfig {
|
|
42
|
+
id: string
|
|
43
|
+
enabled: boolean
|
|
44
|
+
impactMultiplier: number
|
|
45
|
+
maxImpactRate: number
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface EmaVolatilityFeeConfig {
|
|
49
|
+
id: string
|
|
50
|
+
enabled: boolean
|
|
51
|
+
multiplier: number
|
|
52
|
+
maxFeeRate: number
|
|
53
|
+
}
|
|
54
|
+
|
|
40
55
|
export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
|
|
41
56
|
constructor(
|
|
42
57
|
network: Network,
|
|
@@ -197,11 +212,17 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
|
|
|
197
212
|
let zlpPrice = 0
|
|
198
213
|
let value = 0
|
|
199
214
|
|
|
200
|
-
const
|
|
215
|
+
const vaultKeys = Object.keys(this.consts.zoCore.vaults)
|
|
216
|
+
const vaultData = await Promise.all(vaultKeys.map(async (vault) => {
|
|
201
217
|
const vaultInfo = await this.getVaultInfo(vault)
|
|
202
218
|
const reservingFeeDelta = ZLPDataAPI.calculateVaultReservingFee(vaultInfo, vaultInfo.reservingFeeModel, Date.now() / 1000)
|
|
203
|
-
|
|
204
|
-
|
|
219
|
+
const totalVaultAmount = reservingFeeDelta + vaultInfo.liquidity + vaultInfo.reservedAmount
|
|
220
|
+
const oraclePrice = (await this.getOraclePrice(vault)).getPriceUnchecked().getPriceAsNumberUnchecked()
|
|
221
|
+
const vaultValue = totalVaultAmount * oraclePrice / (10 ** this.consts.coins[vault].decimals)
|
|
222
|
+
return { vault, oraclePrice, vaultValue }
|
|
223
|
+
}))
|
|
224
|
+
const vaultPrices = Object.fromEntries(vaultData.map(d => [d.vault, d.oraclePrice]))
|
|
225
|
+
const vaultValues = vaultData.map(d => d.vaultValue)
|
|
205
226
|
|
|
206
227
|
const symbolPromises = Object.keys(this.consts.zoCore.symbols).map(async (symbol) => {
|
|
207
228
|
const [direction, tokenId] = parseSymbolKey(symbol)
|
|
@@ -217,13 +238,13 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
|
|
|
217
238
|
price,
|
|
218
239
|
marketInfo.lpSupplyWithDecimals,
|
|
219
240
|
Date.now() / 1000,
|
|
220
|
-
oiState && oiState.enabled ? oiState
|
|
241
|
+
oiState && oiState.enabled ? oiState : undefined,
|
|
221
242
|
pairedInfo.openingSize,
|
|
222
243
|
)
|
|
223
244
|
return fundingFeeDelta + deltaSize
|
|
224
245
|
})
|
|
225
246
|
|
|
226
|
-
const
|
|
247
|
+
const symbolValues = await Promise.all(symbolPromises)
|
|
227
248
|
|
|
228
249
|
value = vaultValues.reduce((acc: number, curr: number) => acc + curr, 0)
|
|
229
250
|
value += symbolValues.reduce((acc: number, curr: number) => acc + curr, 0)
|
|
@@ -235,6 +256,7 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
|
|
|
235
256
|
price: zlpPrice,
|
|
236
257
|
supply: marketInfo.lpSupplyWithDecimals,
|
|
237
258
|
apr: Number(marketInfo.apr),
|
|
259
|
+
vaultPrices,
|
|
238
260
|
}
|
|
239
261
|
}
|
|
240
262
|
|
|
@@ -375,6 +397,165 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
|
|
|
375
397
|
}
|
|
376
398
|
}
|
|
377
399
|
|
|
400
|
+
public async calculateSwapFeeBreakdown(fromToken: string, toToken: string, fromAmount: number): Promise<ISwapFeeBreakdown> {
|
|
401
|
+
const timestamp = Date.now() / 1000
|
|
402
|
+
|
|
403
|
+
const fromDecimals = this.consts.coins[fromToken]?.decimals
|
|
404
|
+
const toDecimals = this.consts.coins[toToken]?.decimals
|
|
405
|
+
if (fromDecimals === undefined || toDecimals === undefined) {
|
|
406
|
+
throw new Error(`Unknown token decimals for swap: ${fromToken} -> ${toToken}`)
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
const fromFeed = await this.getOraclePrice(fromToken)
|
|
410
|
+
const toFeed = await this.getOraclePrice(toToken)
|
|
411
|
+
const fromPrice = fromFeed.getPriceUnchecked().getPriceAsNumberUnchecked()
|
|
412
|
+
const toPrice = toFeed.getPriceUnchecked().getPriceAsNumberUnchecked()
|
|
413
|
+
|
|
414
|
+
const swapValue = (fromAmount * fromPrice) / (10 ** fromDecimals)
|
|
415
|
+
const totalVaultsValue = await this.#getTotalVaultsValueUsd(timestamp)
|
|
416
|
+
|
|
417
|
+
const rebaseFeeInRate = await this.rebaseFeeRate(fromToken, true, fromAmount)
|
|
418
|
+
const rebaseFeeInValue = swapValue * rebaseFeeInRate
|
|
419
|
+
|
|
420
|
+
// Estimate out-amount by notional value (ignoring price impact / spread / fees).
|
|
421
|
+
const estimatedToAmount = toPrice !== 0
|
|
422
|
+
? (swapValue * (10 ** toDecimals)) / toPrice
|
|
423
|
+
: 0
|
|
424
|
+
const rebaseFeeOutRate = await this.rebaseFeeRate(toToken, false, estimatedToAmount)
|
|
425
|
+
const rebaseFeeOutValue = swapValue * rebaseFeeOutRate
|
|
426
|
+
|
|
427
|
+
const swapImpactCfg = await this.#getSwapImpactConfig()
|
|
428
|
+
const swapImpactFeeValue = swapImpactCfg?.enabled
|
|
429
|
+
? ZLPDataAPI.#computeSwapImpactFeeValue(swapValue, totalVaultsValue, swapImpactCfg.impactMultiplier, swapImpactCfg.maxImpactRate)
|
|
430
|
+
: 0
|
|
431
|
+
|
|
432
|
+
const emaCfg = await this.#getEmaVolatilityFeeConfig()
|
|
433
|
+
const emaVolatilityFeeValue = emaCfg?.enabled
|
|
434
|
+
? ZLPDataAPI.#computeEmaVolatilityFeeValue(
|
|
435
|
+
swapValue,
|
|
436
|
+
ZLPDataAPI.#maxEmaDivergenceRate(fromFeed, toFeed),
|
|
437
|
+
emaCfg.multiplier,
|
|
438
|
+
emaCfg.maxFeeRate,
|
|
439
|
+
)
|
|
440
|
+
: 0
|
|
441
|
+
|
|
442
|
+
const totalFeeValue = rebaseFeeInValue + rebaseFeeOutValue + swapImpactFeeValue + emaVolatilityFeeValue
|
|
443
|
+
const totalFeeRate = swapValue !== 0 ? totalFeeValue / swapValue : 0
|
|
444
|
+
|
|
445
|
+
return {
|
|
446
|
+
swapValue,
|
|
447
|
+
totalVaultsValue,
|
|
448
|
+
rebaseFeeInRate,
|
|
449
|
+
rebaseFeeOutRate,
|
|
450
|
+
rebaseFeeInValue,
|
|
451
|
+
rebaseFeeOutValue,
|
|
452
|
+
swapImpactFeeValue,
|
|
453
|
+
emaVolatilityFeeValue,
|
|
454
|
+
totalFeeValue,
|
|
455
|
+
totalFeeRate,
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
async #getTotalVaultsValueUsd(timestamp: number): Promise<number> {
|
|
460
|
+
const vaultKeys = Object.keys(this.consts.zoCore.vaults)
|
|
461
|
+
const vaultValues = await Promise.all(vaultKeys.map(async (vault) => {
|
|
462
|
+
const vaultInfo = await this.getVaultInfo(vault)
|
|
463
|
+
const reservingFeeDelta = ZLPDataAPI.calculateVaultReservingFee(vaultInfo, vaultInfo.reservingFeeModel, timestamp)
|
|
464
|
+
const totalVaultAmount = reservingFeeDelta + vaultInfo.liquidity + vaultInfo.reservedAmount
|
|
465
|
+
const oraclePrice = (await this.getOraclePrice(vault)).getPriceUnchecked().getPriceAsNumberUnchecked()
|
|
466
|
+
const { decimals } = this.consts.coins[vault]
|
|
467
|
+
return totalVaultAmount * oraclePrice / (10 ** decimals)
|
|
468
|
+
}))
|
|
469
|
+
return vaultValues.reduce((acc, curr) => acc + curr, 0)
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
async #getSwapImpactConfig(): Promise<SwapImpactConfig | null> {
|
|
473
|
+
const raw = await this.#getMarketDynamicFieldObjectByKeySuffix(this.consts.zoCore.market, 'SwapImpactConfigKey')
|
|
474
|
+
if (!raw)
|
|
475
|
+
return null
|
|
476
|
+
return ZLPDataAPI.#parseSwapImpactConfig(raw)
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
async #getEmaVolatilityFeeConfig(): Promise<EmaVolatilityFeeConfig | null> {
|
|
480
|
+
const raw = await this.#getMarketDynamicFieldObjectByKeySuffix(this.consts.zoCore.market, 'EmaVolatilityFeeConfigKey')
|
|
481
|
+
if (!raw)
|
|
482
|
+
return null
|
|
483
|
+
return ZLPDataAPI.#parseEmaVolatilityFeeConfig(raw)
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
async #getMarketDynamicFieldObjectByKeySuffix(parentId: string, keyTypeSuffix: string): Promise<any | null> {
|
|
487
|
+
let cursor: string | null | undefined
|
|
488
|
+
let hasNextPage = true
|
|
489
|
+
|
|
490
|
+
while (hasNextPage) {
|
|
491
|
+
const page = await this.provider.getDynamicFields({ parentId, cursor })
|
|
492
|
+
for (const field of page.data) {
|
|
493
|
+
const type = (field.name as any)?.type
|
|
494
|
+
if (typeof type === 'string' && type.endsWith(`::${keyTypeSuffix}`)) {
|
|
495
|
+
return await this.provider.getDynamicFieldObject({
|
|
496
|
+
parentId,
|
|
497
|
+
name: field.name as any,
|
|
498
|
+
})
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
hasNextPage = page.hasNextPage
|
|
502
|
+
cursor = page.nextCursor
|
|
503
|
+
}
|
|
504
|
+
return null
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
static #parseSwapImpactConfig(raw: any): SwapImpactConfig {
|
|
508
|
+
const { fields } = raw.data.content
|
|
509
|
+
return {
|
|
510
|
+
id: fields.id.id,
|
|
511
|
+
enabled: fields.enabled,
|
|
512
|
+
impactMultiplier: parseValue(fields.impact_multiplier),
|
|
513
|
+
maxImpactRate: parseValue(fields.max_impact_rate),
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
static #parseEmaVolatilityFeeConfig(raw: any): EmaVolatilityFeeConfig {
|
|
518
|
+
const { fields } = raw.data.content
|
|
519
|
+
return {
|
|
520
|
+
id: fields.id.id,
|
|
521
|
+
enabled: fields.enabled,
|
|
522
|
+
multiplier: parseValue(fields.multiplier),
|
|
523
|
+
maxFeeRate: parseValue(fields.max_fee_rate),
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
static #computeSwapImpactFeeValue(swapValue: number, totalVaultsValue: number, impactMultiplier: number, maxImpactRate: number): number {
|
|
528
|
+
if (swapValue <= 0 || totalVaultsValue <= 0)
|
|
529
|
+
return 0
|
|
530
|
+
const utilization = swapValue / totalVaultsValue
|
|
531
|
+
const rawImpactRate = impactMultiplier * utilization
|
|
532
|
+
const impactRate = Math.min(rawImpactRate, maxImpactRate)
|
|
533
|
+
return swapValue * impactRate
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
static #computeEmaVolatilityFeeValue(swapValue: number, maxDiv: number, multiplier: number, maxFeeRate: number): number {
|
|
537
|
+
if (swapValue <= 0 || maxDiv <= 0)
|
|
538
|
+
return 0
|
|
539
|
+
const rawFeeRate = multiplier * maxDiv
|
|
540
|
+
const feeRate = Math.min(rawFeeRate, maxFeeRate)
|
|
541
|
+
return swapValue * feeRate
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
static #maxEmaDivergenceRate(sourceFeed: any, destFeed: any): number {
|
|
545
|
+
const sourceDiv = ZLPDataAPI.#emaDivergenceRate(sourceFeed)
|
|
546
|
+
const destDiv = ZLPDataAPI.#emaDivergenceRate(destFeed)
|
|
547
|
+
return Math.max(sourceDiv, destDiv)
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
static #emaDivergenceRate(priceFeed: any): number {
|
|
551
|
+
const price = priceFeed.getPriceUnchecked().getPriceAsNumberUnchecked()
|
|
552
|
+
const ema = priceFeed.getEmaPriceUnchecked().getPriceAsNumberUnchecked()
|
|
553
|
+
const denom = Math.abs(price)
|
|
554
|
+
if (denom === 0)
|
|
555
|
+
return 0
|
|
556
|
+
return Math.abs(price - ema) / denom
|
|
557
|
+
}
|
|
558
|
+
|
|
378
559
|
public async getPositionCapInfoList(owner: string): Promise<IZLPPositionCapInfo[]> {
|
|
379
560
|
const positionCapInfoList: IZLPPositionCapInfo[] = []
|
|
380
561
|
let cursor: string | undefined | null
|
|
@@ -664,7 +845,7 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
|
|
|
664
845
|
const longSize = longSymbol.openingSize
|
|
665
846
|
const shortSize = shortSymbol.openingSize
|
|
666
847
|
|
|
667
|
-
const deltaRate = ZLPDataAPI.calcOiFundingFeeRate(oiState.model, longSize, shortSize, elapsed)
|
|
848
|
+
const deltaRate = ZLPDataAPI.calcOiFundingFeeRate(oiState.model, longSize, shortSize, elapsed, oiState.maxOiLong, oiState.maxOiShort)
|
|
668
849
|
return long ? deltaRate : -deltaRate
|
|
669
850
|
}
|
|
670
851
|
|
|
@@ -751,13 +932,42 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
|
|
|
751
932
|
return pnlPerRate >= 0 ? -secondsRate : secondsRate
|
|
752
933
|
}
|
|
753
934
|
|
|
754
|
-
|
|
755
|
-
|
|
935
|
+
/**
|
|
936
|
+
* OI funding rate matching Move compute_oi_funding_rate_capped.
|
|
937
|
+
* When both maxOiLong and maxOiShort are set and > 0, uses normalized skew (oi/cap);
|
|
938
|
+
* otherwise falls back to (long - short) / total.
|
|
939
|
+
*/
|
|
940
|
+
private static calcOiFundingFeeRate(
|
|
941
|
+
model: IZLPOiFundingModel,
|
|
942
|
+
oiLong: number,
|
|
943
|
+
oiShort: number,
|
|
944
|
+
elapsed: number,
|
|
945
|
+
maxOiLong?: number,
|
|
946
|
+
maxOiShort?: number,
|
|
947
|
+
): number {
|
|
948
|
+
let skew: number
|
|
949
|
+
if (maxOiLong && maxOiShort && maxOiLong > 0 && maxOiShort > 0) {
|
|
950
|
+
const normLong = Math.min(oiLong / maxOiLong, 1)
|
|
951
|
+
const normShort = Math.min(oiShort / maxOiShort, 1)
|
|
952
|
+
skew = normLong - normShort
|
|
953
|
+
}
|
|
954
|
+
else {
|
|
955
|
+
const total = oiLong + oiShort
|
|
956
|
+
if (total === 0)
|
|
957
|
+
return 0
|
|
958
|
+
skew = (oiLong - oiShort) / total
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
if (skew === 0)
|
|
962
|
+
return 0
|
|
756
963
|
|
|
757
|
-
|
|
758
|
-
const
|
|
759
|
-
const
|
|
760
|
-
|
|
964
|
+
const skewIsPositive = skew > 0
|
|
965
|
+
const skewAbs = Math.abs(skew)
|
|
966
|
+
const exponentInt = Math.floor(model.exponent)
|
|
967
|
+
const skewPow = skewAbs ** exponentInt
|
|
968
|
+
const dailyRate = Math.min(model.multiplier * skewPow, model.max)
|
|
969
|
+
const secondsRate = (dailyRate * elapsed) / SECONDS_PER_EIGHT_HOUR
|
|
970
|
+
return skewIsPositive ? secondsRate : -secondsRate
|
|
761
971
|
}
|
|
762
972
|
|
|
763
973
|
private static calcAccFundingFeeRate(
|
|
@@ -766,17 +976,17 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
|
|
|
766
976
|
price: number,
|
|
767
977
|
lpSupplyAmount: number,
|
|
768
978
|
timestamp: number,
|
|
769
|
-
|
|
979
|
+
oiState?: IZLPOiFundingState,
|
|
770
980
|
pairedOpeningSize?: number,
|
|
771
981
|
): number {
|
|
772
982
|
if (symbol.lastUpdate > 0) {
|
|
773
983
|
const elapsed = timestamp - symbol.lastUpdate
|
|
774
984
|
if (elapsed > 0) {
|
|
775
|
-
// Prefer OI-based delta when
|
|
776
|
-
if (
|
|
985
|
+
// Prefer OI-based delta when state and paired side are available
|
|
986
|
+
if (oiState?.enabled && oiState.model && typeof pairedOpeningSize === 'number') {
|
|
777
987
|
const longSize = symbol.long ? symbol.openingSize : pairedOpeningSize
|
|
778
988
|
const shortSize = symbol.long ? pairedOpeningSize : symbol.openingSize
|
|
779
|
-
const deltaRate = ZLPDataAPI.calcOiFundingFeeRate(
|
|
989
|
+
const deltaRate = ZLPDataAPI.calcOiFundingFeeRate(oiState.model, longSize, shortSize, elapsed, oiState.maxOiLong, oiState.maxOiShort)
|
|
780
990
|
const appliedRate = symbol.long ? deltaRate : -deltaRate
|
|
781
991
|
return symbol.accFundingRate + appliedRate
|
|
782
992
|
}
|
|
@@ -796,7 +1006,7 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
|
|
|
796
1006
|
price: number,
|
|
797
1007
|
lpSupplyAmount: number,
|
|
798
1008
|
timestamp: number,
|
|
799
|
-
|
|
1009
|
+
oiState?: IZLPOiFundingState,
|
|
800
1010
|
pairedOpeningSize?: number,
|
|
801
1011
|
): number {
|
|
802
1012
|
const accFundingRate = ZLPDataAPI.calcAccFundingFeeRate(
|
|
@@ -805,7 +1015,7 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
|
|
|
805
1015
|
price,
|
|
806
1016
|
lpSupplyAmount,
|
|
807
1017
|
timestamp,
|
|
808
|
-
|
|
1018
|
+
oiState,
|
|
809
1019
|
pairedOpeningSize,
|
|
810
1020
|
)
|
|
811
1021
|
return symbol.unrealisedFundingFeeValue + (accFundingRate - symbol.accFundingRate) * symbol.openingSize
|
|
@@ -999,7 +1209,7 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
|
|
|
999
1209
|
// OI context for funding: fetch state and paired side size when enabled
|
|
1000
1210
|
const oiState = await this.getSymbolOiFundingState(positionInfo.indexToken)
|
|
1001
1211
|
const pairedSymbol = await this.getSymbolInfo(positionInfo.indexToken, !positionInfo.long)
|
|
1002
|
-
positionInfo.fundingFeeValue = ZLPDataAPI.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
|
|
1212
|
+
positionInfo.fundingFeeValue = ZLPDataAPI.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)
|
|
1003
1213
|
|
|
1004
1214
|
return positionInfo
|
|
1005
1215
|
}
|
|
@@ -1011,7 +1221,7 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
|
|
|
1011
1221
|
price: number,
|
|
1012
1222
|
lpSupplyAmount: number,
|
|
1013
1223
|
timestamp: number,
|
|
1014
|
-
|
|
1224
|
+
oiState?: IZLPOiFundingState,
|
|
1015
1225
|
pairedOpeningSize?: number,
|
|
1016
1226
|
): number {
|
|
1017
1227
|
const accFundingRate = ZLPDataAPI.calcAccFundingFeeRate(
|
|
@@ -1020,7 +1230,7 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
|
|
|
1020
1230
|
price,
|
|
1021
1231
|
lpSupplyAmount,
|
|
1022
1232
|
timestamp,
|
|
1023
|
-
|
|
1233
|
+
oiState,
|
|
1024
1234
|
pairedOpeningSize,
|
|
1025
1235
|
)
|
|
1026
1236
|
return position.fundingFeeValue + (accFundingRate - position.lastFundingRate) * position.positionSize
|
|
@@ -1093,6 +1303,8 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
|
|
|
1093
1303
|
exponent: parseValue(content.model.fields.exponent),
|
|
1094
1304
|
max: parseValue(content.model.fields.max),
|
|
1095
1305
|
},
|
|
1306
|
+
maxOiLong: content.max_oi_long !== null && content.max_oi_long !== undefined ? parseValue(content.max_oi_long) : undefined,
|
|
1307
|
+
maxOiShort: content.max_oi_short !== null && content.max_oi_short !== undefined ? parseValue(content.max_oi_short) : undefined,
|
|
1096
1308
|
}
|
|
1097
1309
|
}
|
|
1098
1310
|
|
package/src/interfaces/base.ts
CHANGED
|
@@ -18,6 +18,32 @@ export interface IBaseMarketValuationInfo {
|
|
|
18
18
|
apr?: number
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
export interface ISwapFeeBreakdown {
|
|
22
|
+
/** Swap notional value (in USD terms using oracle prices) */
|
|
23
|
+
swapValue: number
|
|
24
|
+
/** Total value of all vaults (in USD terms using oracle prices) */
|
|
25
|
+
totalVaultsValue: number
|
|
26
|
+
|
|
27
|
+
/** Rebase fee rate applied to swap-in leg (source token) */
|
|
28
|
+
rebaseFeeInRate: number
|
|
29
|
+
/** Rebase fee rate applied to swap-out leg (dest token) */
|
|
30
|
+
rebaseFeeOutRate: number
|
|
31
|
+
/** Rebase fee value for swap-in leg (USD value) */
|
|
32
|
+
rebaseFeeInValue: number
|
|
33
|
+
/** Rebase fee value for swap-out leg (USD value) */
|
|
34
|
+
rebaseFeeOutValue: number
|
|
35
|
+
|
|
36
|
+
/** Swap impact fee value (USD value) */
|
|
37
|
+
swapImpactFeeValue: number
|
|
38
|
+
/** EMA volatility fee value (USD value) */
|
|
39
|
+
emaVolatilityFeeValue: number
|
|
40
|
+
|
|
41
|
+
/** Sum of all fee components (USD value) */
|
|
42
|
+
totalFeeValue: number
|
|
43
|
+
/** totalFeeValue / swapValue (0 when swapValue is 0) */
|
|
44
|
+
totalFeeRate: number
|
|
45
|
+
}
|
|
46
|
+
|
|
21
47
|
export interface IBaseMarketInfo {
|
|
22
48
|
lpSupply: string
|
|
23
49
|
positionId: string
|
package/src/interfaces/slp.ts
CHANGED
|
@@ -25,10 +25,14 @@ import type {
|
|
|
25
25
|
IBaseStakePool,
|
|
26
26
|
IBaseSymbolInfo,
|
|
27
27
|
IBaseVaultInfo,
|
|
28
|
+
ISwapFeeBreakdown,
|
|
28
29
|
} from './base'
|
|
29
30
|
|
|
30
31
|
// SLP-specific interfaces
|
|
31
|
-
export interface ISLPMarketValuationInfo extends IBaseMarketValuationInfo {
|
|
32
|
+
export interface ISLPMarketValuationInfo extends IBaseMarketValuationInfo {
|
|
33
|
+
/** Oracle price per vault token at valuation time (e.g. { sui: 1.5, usdc: 1.0 }) */
|
|
34
|
+
vaultPrices?: Record<string, number>
|
|
35
|
+
}
|
|
32
36
|
|
|
33
37
|
export interface ISLPVaultInfo extends IBaseVaultInfo { }
|
|
34
38
|
|
|
@@ -99,6 +103,10 @@ export interface ISLPOiFundingState {
|
|
|
99
103
|
enabled: boolean
|
|
100
104
|
last_update: number
|
|
101
105
|
model: ISLPOiFundingModel
|
|
106
|
+
/** OI cap for long side (optional; when set with maxOiShort, uses capped skew formula) */
|
|
107
|
+
maxOiLong?: number
|
|
108
|
+
/** OI cap for short side (optional; when set with maxOiLong, uses capped skew formula) */
|
|
109
|
+
maxOiShort?: number
|
|
102
110
|
}
|
|
103
111
|
|
|
104
112
|
/**
|
|
@@ -208,6 +216,7 @@ export interface ISLPDataAPI extends IBaseDataAPI {
|
|
|
208
216
|
getCumulativeApr: () => Promise<number>
|
|
209
217
|
getSymbolConfig: (indexToken: string, long: boolean) => Promise<ISLPSymbolConfig | null>
|
|
210
218
|
getPriceImpactConfig: (indexToken: string) => Promise<ISLPPriceImpactConfig | null>
|
|
219
|
+
calculateSwapFeeBreakdown: (fromToken: string, toToken: string, fromAmount: number) => Promise<ISwapFeeBreakdown>
|
|
211
220
|
}
|
|
212
221
|
|
|
213
222
|
// SLP-specific API interface
|
package/src/interfaces/usdz.ts
CHANGED
|
@@ -23,10 +23,14 @@ import type {
|
|
|
23
23
|
IBaseStakePool,
|
|
24
24
|
IBaseSymbolInfo,
|
|
25
25
|
IBaseVaultInfo,
|
|
26
|
+
ISwapFeeBreakdown,
|
|
26
27
|
} from './base'
|
|
27
28
|
|
|
28
29
|
// USDZ-specific interfaces
|
|
29
|
-
export interface IUSDZMarketValuationInfo extends IBaseMarketValuationInfo {
|
|
30
|
+
export interface IUSDZMarketValuationInfo extends IBaseMarketValuationInfo {
|
|
31
|
+
/** Oracle price per vault token at valuation time (e.g. { sui: 1.5, usdc: 1.0 }) */
|
|
32
|
+
vaultPrices?: Record<string, number>
|
|
33
|
+
}
|
|
30
34
|
|
|
31
35
|
export interface IUSDZVaultInfo extends IBaseVaultInfo { }
|
|
32
36
|
|
|
@@ -100,6 +104,10 @@ export interface IUSDZOiFundingState {
|
|
|
100
104
|
enabled: boolean
|
|
101
105
|
last_update: number
|
|
102
106
|
model: IUSDZOiFundingModel
|
|
107
|
+
/** OI cap for long side (optional; when set with maxOiShort, uses capped skew formula) */
|
|
108
|
+
maxOiLong?: number
|
|
109
|
+
/** OI cap for short side (optional; when set with maxOiLong, uses capped skew formula) */
|
|
110
|
+
maxOiShort?: number
|
|
103
111
|
}
|
|
104
112
|
|
|
105
113
|
/**
|
|
@@ -130,6 +138,7 @@ export interface IUSDZPriceImpactConfig {
|
|
|
130
138
|
export interface IUSDZDataAPI extends IBaseDataAPI {
|
|
131
139
|
getSymbolConfig: (indexToken: string, long: boolean) => Promise<IUSDZSymbolConfig | null>
|
|
132
140
|
getPriceImpactConfig: (indexToken: string) => Promise<IUSDZPriceImpactConfig | null>
|
|
141
|
+
calculateSwapFeeBreakdown: (fromToken: string, toToken: string, fromAmount: number) => Promise<ISwapFeeBreakdown>
|
|
133
142
|
}
|
|
134
143
|
|
|
135
144
|
// USDZ-specific API interface
|
package/src/interfaces/zlp.ts
CHANGED
|
@@ -23,10 +23,14 @@ import type {
|
|
|
23
23
|
IBaseStakePool,
|
|
24
24
|
IBaseSymbolInfo,
|
|
25
25
|
IBaseVaultInfo,
|
|
26
|
+
ISwapFeeBreakdown,
|
|
26
27
|
} from './base'
|
|
27
28
|
|
|
28
29
|
// ZLP-specific interfaces
|
|
29
|
-
export interface IZLPMarketValuationInfo extends IBaseMarketValuationInfo {
|
|
30
|
+
export interface IZLPMarketValuationInfo extends IBaseMarketValuationInfo {
|
|
31
|
+
/** Oracle price per vault token at valuation time (e.g. { sui: 1.5, usdc: 1.0 }) */
|
|
32
|
+
vaultPrices?: Record<string, number>
|
|
33
|
+
}
|
|
30
34
|
|
|
31
35
|
export interface IZLPVaultInfo extends IBaseVaultInfo { }
|
|
32
36
|
|
|
@@ -100,6 +104,10 @@ export interface IZLPOiFundingState {
|
|
|
100
104
|
enabled: boolean
|
|
101
105
|
last_update: number
|
|
102
106
|
model: IZLPOiFundingModel
|
|
107
|
+
/** OI cap for long side (optional; when set with maxOiShort, uses capped skew formula) */
|
|
108
|
+
maxOiLong?: number
|
|
109
|
+
/** OI cap for short side (optional; when set with maxOiLong, uses capped skew formula) */
|
|
110
|
+
maxOiShort?: number
|
|
103
111
|
}
|
|
104
112
|
|
|
105
113
|
/**
|
|
@@ -130,6 +138,7 @@ export interface IZLPPriceImpactConfig {
|
|
|
130
138
|
export interface IZLPDataAPI extends IBaseDataAPI {
|
|
131
139
|
getSymbolConfig: (indexToken: string, long: boolean) => Promise<IZLPSymbolConfig | null>
|
|
132
140
|
getPriceImpactConfig: (indexToken: string) => Promise<IZLPPriceImpactConfig | null>
|
|
141
|
+
calculateSwapFeeBreakdown: (fromToken: string, toToken: string, fromAmount: number) => Promise<ISwapFeeBreakdown>
|
|
133
142
|
}
|
|
134
143
|
|
|
135
144
|
// ZLP-specific API interface
|