@zofai/zo-sdk 0.1.93 → 0.1.95

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.
Files changed (87) hide show
  1. package/README.md +4 -3
  2. package/dist/consts/deployments-slp-mainnet.json +1 -1
  3. package/dist/consts/deployments-usdz-mainnet.json +1 -1
  4. package/dist/consts/deployments-zlp-mainnet.json +1 -1
  5. package/dist/implementations/SLPAPI.cjs +34 -0
  6. package/dist/implementations/SLPAPI.cjs.map +1 -1
  7. package/dist/implementations/SLPAPI.d.cts +6 -0
  8. package/dist/implementations/SLPAPI.d.cts.map +1 -1
  9. package/dist/implementations/SLPAPI.d.mts +6 -0
  10. package/dist/implementations/SLPAPI.d.mts.map +1 -1
  11. package/dist/implementations/SLPAPI.mjs +34 -0
  12. package/dist/implementations/SLPAPI.mjs.map +1 -1
  13. package/dist/implementations/SLPDataAPI.cjs +212 -47
  14. package/dist/implementations/SLPDataAPI.cjs.map +1 -1
  15. package/dist/implementations/SLPDataAPI.d.cts +8 -1
  16. package/dist/implementations/SLPDataAPI.d.cts.map +1 -1
  17. package/dist/implementations/SLPDataAPI.d.mts +8 -1
  18. package/dist/implementations/SLPDataAPI.d.mts.map +1 -1
  19. package/dist/implementations/SLPDataAPI.mjs +212 -47
  20. package/dist/implementations/SLPDataAPI.mjs.map +1 -1
  21. package/dist/implementations/USDZAPI.cjs +32 -0
  22. package/dist/implementations/USDZAPI.cjs.map +1 -1
  23. package/dist/implementations/USDZAPI.d.cts +6 -0
  24. package/dist/implementations/USDZAPI.d.cts.map +1 -1
  25. package/dist/implementations/USDZAPI.d.mts +6 -0
  26. package/dist/implementations/USDZAPI.d.mts.map +1 -1
  27. package/dist/implementations/USDZAPI.mjs +32 -0
  28. package/dist/implementations/USDZAPI.mjs.map +1 -1
  29. package/dist/implementations/USDZDataAPI.cjs +197 -44
  30. package/dist/implementations/USDZDataAPI.cjs.map +1 -1
  31. package/dist/implementations/USDZDataAPI.d.cts +8 -1
  32. package/dist/implementations/USDZDataAPI.d.cts.map +1 -1
  33. package/dist/implementations/USDZDataAPI.d.mts +8 -1
  34. package/dist/implementations/USDZDataAPI.d.mts.map +1 -1
  35. package/dist/implementations/USDZDataAPI.mjs +197 -44
  36. package/dist/implementations/USDZDataAPI.mjs.map +1 -1
  37. package/dist/implementations/ZLPAPI.cjs +34 -0
  38. package/dist/implementations/ZLPAPI.cjs.map +1 -1
  39. package/dist/implementations/ZLPAPI.d.cts +6 -0
  40. package/dist/implementations/ZLPAPI.d.cts.map +1 -1
  41. package/dist/implementations/ZLPAPI.d.mts +6 -0
  42. package/dist/implementations/ZLPAPI.d.mts.map +1 -1
  43. package/dist/implementations/ZLPAPI.mjs +34 -0
  44. package/dist/implementations/ZLPAPI.mjs.map +1 -1
  45. package/dist/implementations/ZLPDataAPI.cjs +200 -46
  46. package/dist/implementations/ZLPDataAPI.cjs.map +1 -1
  47. package/dist/implementations/ZLPDataAPI.d.cts +8 -1
  48. package/dist/implementations/ZLPDataAPI.d.cts.map +1 -1
  49. package/dist/implementations/ZLPDataAPI.d.mts +8 -1
  50. package/dist/implementations/ZLPDataAPI.d.mts.map +1 -1
  51. package/dist/implementations/ZLPDataAPI.mjs +200 -46
  52. package/dist/implementations/ZLPDataAPI.mjs.map +1 -1
  53. package/dist/interfaces/base.d.cts +22 -0
  54. package/dist/interfaces/base.d.cts.map +1 -1
  55. package/dist/interfaces/base.d.mts +22 -0
  56. package/dist/interfaces/base.d.mts.map +1 -1
  57. package/dist/interfaces/slp.d.cts +11 -1
  58. package/dist/interfaces/slp.d.cts.map +1 -1
  59. package/dist/interfaces/slp.d.mts +11 -1
  60. package/dist/interfaces/slp.d.mts.map +1 -1
  61. package/dist/interfaces/usdz.d.cts +11 -1
  62. package/dist/interfaces/usdz.d.cts.map +1 -1
  63. package/dist/interfaces/usdz.d.mts +11 -1
  64. package/dist/interfaces/usdz.d.mts.map +1 -1
  65. package/dist/interfaces/zlp.d.cts +11 -1
  66. package/dist/interfaces/zlp.d.cts.map +1 -1
  67. package/dist/interfaces/zlp.d.mts +11 -1
  68. package/dist/interfaces/zlp.d.mts.map +1 -1
  69. package/docs/SUMMARY.md +1 -0
  70. package/docs/getting-started.md +4 -4
  71. package/docs/introduction.md +3 -3
  72. package/docs/swap-integration.md +183 -0
  73. package/docs/type-safety.md +1 -1
  74. package/package.json +1 -1
  75. package/src/consts/deployments-slp-mainnet.json +1 -1
  76. package/src/consts/deployments-usdz-mainnet.json +1 -1
  77. package/src/consts/deployments-zlp-mainnet.json +1 -1
  78. package/src/implementations/SLPAPI.ts +46 -0
  79. package/src/implementations/SLPDataAPI.ts +235 -19
  80. package/src/implementations/USDZAPI.ts +41 -0
  81. package/src/implementations/USDZDataAPI.ts +221 -16
  82. package/src/implementations/ZLPAPI.ts +43 -0
  83. package/src/implementations/ZLPDataAPI.ts +222 -17
  84. package/src/interfaces/base.ts +26 -0
  85. package/src/interfaces/slp.ts +19 -0
  86. package/src/interfaces/usdz.ts +19 -0
  87. package/src/interfaces/zlp.ts +19 -0
@@ -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,
@@ -223,7 +238,7 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
223
238
  price,
224
239
  marketInfo.lpSupplyWithDecimals,
225
240
  Date.now() / 1000,
226
- oiState && oiState.enabled ? oiState.model : undefined,
241
+ oiState && oiState.enabled ? oiState : undefined,
227
242
  pairedInfo.openingSize,
228
243
  )
229
244
  return fundingFeeDelta + deltaSize
@@ -382,6 +397,165 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
382
397
  }
383
398
  }
384
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
+
385
559
  public async getPositionCapInfoList(owner: string): Promise<IZLPPositionCapInfo[]> {
386
560
  const positionCapInfoList: IZLPPositionCapInfo[] = []
387
561
  let cursor: string | undefined | null
@@ -671,7 +845,7 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
671
845
  const longSize = longSymbol.openingSize
672
846
  const shortSize = shortSymbol.openingSize
673
847
 
674
- const deltaRate = ZLPDataAPI.calcOiFundingFeeRate(oiState.model, longSize, shortSize, elapsed)
848
+ const deltaRate = ZLPDataAPI.calcOiFundingFeeRate(oiState.model, longSize, shortSize, elapsed, oiState.maxOiLong, oiState.maxOiShort)
675
849
  return long ? deltaRate : -deltaRate
676
850
  }
677
851
 
@@ -758,13 +932,42 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
758
932
  return pnlPerRate >= 0 ? -secondsRate : secondsRate
759
933
  }
760
934
 
761
- private static calcOiFundingFeeRate(model: IZLPOiFundingModel, longSize: number, shortSize: number, elapsed: number): number {
762
- const imbalance = Math.abs(longSize - shortSize)
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
763
963
 
764
- // multiplier = 0.1%, exponent = 1
765
- const dailyRate = Math.min(model.multiplier * (imbalance ** model.exponent) / (longSize + shortSize > 0 ? longSize + shortSize : 1), model.max)
766
- const secondsRate = dailyRate * elapsed / SECONDS_PER_EIGHT_HOUR
767
- return longSize >= shortSize ? secondsRate : -secondsRate
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
768
971
  }
769
972
 
770
973
  private static calcAccFundingFeeRate(
@@ -773,17 +976,17 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
773
976
  price: number,
774
977
  lpSupplyAmount: number,
775
978
  timestamp: number,
776
- oiModel?: IZLPOiFundingModel,
979
+ oiState?: IZLPOiFundingState,
777
980
  pairedOpeningSize?: number,
778
981
  ): number {
779
982
  if (symbol.lastUpdate > 0) {
780
983
  const elapsed = timestamp - symbol.lastUpdate
781
984
  if (elapsed > 0) {
782
- // Prefer OI-based delta when model and paired side are available
783
- if (oiModel && typeof pairedOpeningSize === 'number') {
985
+ // Prefer OI-based delta when state and paired side are available
986
+ if (oiState?.enabled && oiState.model && typeof pairedOpeningSize === 'number') {
784
987
  const longSize = symbol.long ? symbol.openingSize : pairedOpeningSize
785
988
  const shortSize = symbol.long ? pairedOpeningSize : symbol.openingSize
786
- const deltaRate = ZLPDataAPI.calcOiFundingFeeRate(oiModel, longSize, shortSize, elapsed)
989
+ const deltaRate = ZLPDataAPI.calcOiFundingFeeRate(oiState.model, longSize, shortSize, elapsed, oiState.maxOiLong, oiState.maxOiShort)
787
990
  const appliedRate = symbol.long ? deltaRate : -deltaRate
788
991
  return symbol.accFundingRate + appliedRate
789
992
  }
@@ -803,7 +1006,7 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
803
1006
  price: number,
804
1007
  lpSupplyAmount: number,
805
1008
  timestamp: number,
806
- oiModel?: IZLPOiFundingModel,
1009
+ oiState?: IZLPOiFundingState,
807
1010
  pairedOpeningSize?: number,
808
1011
  ): number {
809
1012
  const accFundingRate = ZLPDataAPI.calcAccFundingFeeRate(
@@ -812,7 +1015,7 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
812
1015
  price,
813
1016
  lpSupplyAmount,
814
1017
  timestamp,
815
- oiModel,
1018
+ oiState,
816
1019
  pairedOpeningSize,
817
1020
  )
818
1021
  return symbol.unrealisedFundingFeeValue + (accFundingRate - symbol.accFundingRate) * symbol.openingSize
@@ -1006,7 +1209,7 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
1006
1209
  // OI context for funding: fetch state and paired side size when enabled
1007
1210
  const oiState = await this.getSymbolOiFundingState(positionInfo.indexToken)
1008
1211
  const pairedSymbol = await this.getSymbolInfo(positionInfo.indexToken, !positionInfo.long)
1009
- 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.model : undefined, pairedSymbol.openingSize)
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)
1010
1213
 
1011
1214
  return positionInfo
1012
1215
  }
@@ -1018,7 +1221,7 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
1018
1221
  price: number,
1019
1222
  lpSupplyAmount: number,
1020
1223
  timestamp: number,
1021
- oiModel?: IZLPOiFundingModel,
1224
+ oiState?: IZLPOiFundingState,
1022
1225
  pairedOpeningSize?: number,
1023
1226
  ): number {
1024
1227
  const accFundingRate = ZLPDataAPI.calcAccFundingFeeRate(
@@ -1027,7 +1230,7 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
1027
1230
  price,
1028
1231
  lpSupplyAmount,
1029
1232
  timestamp,
1030
- oiModel,
1233
+ oiState,
1031
1234
  pairedOpeningSize,
1032
1235
  )
1033
1236
  return position.fundingFeeValue + (accFundingRate - position.lastFundingRate) * position.positionSize
@@ -1100,6 +1303,8 @@ export class ZLPDataAPI extends BaseDataAPI implements IZLPDataAPI {
1100
1303
  exponent: parseValue(content.model.fields.exponent),
1101
1304
  max: parseValue(content.model.fields.max),
1102
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,
1103
1308
  }
1104
1309
  }
1105
1310
 
@@ -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
@@ -25,6 +25,7 @@ import type {
25
25
  IBaseStakePool,
26
26
  IBaseSymbolInfo,
27
27
  IBaseVaultInfo,
28
+ ISwapFeeBreakdown,
28
29
  } from './base'
29
30
 
30
31
  // SLP-specific interfaces
@@ -102,6 +103,10 @@ export interface ISLPOiFundingState {
102
103
  enabled: boolean
103
104
  last_update: number
104
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
105
110
  }
106
111
 
107
112
  /**
@@ -211,6 +216,7 @@ export interface ISLPDataAPI extends IBaseDataAPI {
211
216
  getCumulativeApr: () => Promise<number>
212
217
  getSymbolConfig: (indexToken: string, long: boolean) => Promise<ISLPSymbolConfig | null>
213
218
  getPriceImpactConfig: (indexToken: string) => Promise<ISLPPriceImpactConfig | null>
219
+ calculateSwapFeeBreakdown: (fromToken: string, toToken: string, fromAmount: number) => Promise<ISwapFeeBreakdown>
214
220
  }
215
221
 
216
222
  // SLP-specific API interface
@@ -268,4 +274,17 @@ export interface ISLPAPI extends IBaseAPI {
268
274
  pool: string,
269
275
  tx: Transaction,
270
276
  ) => TransactionObjectArgument[]
277
+
278
+ /**
279
+ * Swaps tokens and returns the output coin to the user (PTB).
280
+ * Same as swap() but returns the output coin for use in composed transactions.
281
+ */
282
+ swapV2Ptb: (
283
+ fromToken: string,
284
+ toToken: string,
285
+ fromAmount: bigint,
286
+ fromCoinObjects: string[],
287
+ minAmountOut?: number,
288
+ tx?: Transaction,
289
+ ) => Promise<TransactionObjectArgument>
271
290
  }
@@ -23,6 +23,7 @@ import type {
23
23
  IBaseStakePool,
24
24
  IBaseSymbolInfo,
25
25
  IBaseVaultInfo,
26
+ ISwapFeeBreakdown,
26
27
  } from './base'
27
28
 
28
29
  // USDZ-specific interfaces
@@ -103,6 +104,10 @@ export interface IUSDZOiFundingState {
103
104
  enabled: boolean
104
105
  last_update: number
105
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
106
111
  }
107
112
 
108
113
  /**
@@ -133,6 +138,7 @@ export interface IUSDZPriceImpactConfig {
133
138
  export interface IUSDZDataAPI extends IBaseDataAPI {
134
139
  getSymbolConfig: (indexToken: string, long: boolean) => Promise<IUSDZSymbolConfig | null>
135
140
  getPriceImpactConfig: (indexToken: string) => Promise<IUSDZPriceImpactConfig | null>
141
+ calculateSwapFeeBreakdown: (fromToken: string, toToken: string, fromAmount: number) => Promise<ISwapFeeBreakdown>
136
142
  }
137
143
 
138
144
  // USDZ-specific API interface
@@ -181,4 +187,17 @@ export interface IUSDZAPI extends IBaseAPI {
181
187
  pool: string,
182
188
  tx: Transaction,
183
189
  ) => TransactionObjectArgument[]
190
+
191
+ /**
192
+ * Swaps tokens and returns the output coin to the user (PTB).
193
+ * Same as swap() but returns the output coin for use in composed transactions.
194
+ */
195
+ swapV2Ptb: (
196
+ fromToken: string,
197
+ toToken: string,
198
+ fromAmount: bigint,
199
+ fromCoinObjects: string[],
200
+ minAmountOut?: number,
201
+ tx?: Transaction,
202
+ ) => Promise<TransactionObjectArgument>
184
203
  }
@@ -23,6 +23,7 @@ import type {
23
23
  IBaseStakePool,
24
24
  IBaseSymbolInfo,
25
25
  IBaseVaultInfo,
26
+ ISwapFeeBreakdown,
26
27
  } from './base'
27
28
 
28
29
  // ZLP-specific interfaces
@@ -103,6 +104,10 @@ export interface IZLPOiFundingState {
103
104
  enabled: boolean
104
105
  last_update: number
105
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
106
111
  }
107
112
 
108
113
  /**
@@ -133,6 +138,7 @@ export interface IZLPPriceImpactConfig {
133
138
  export interface IZLPDataAPI extends IBaseDataAPI {
134
139
  getSymbolConfig: (indexToken: string, long: boolean) => Promise<IZLPSymbolConfig | null>
135
140
  getPriceImpactConfig: (indexToken: string) => Promise<IZLPPriceImpactConfig | null>
141
+ calculateSwapFeeBreakdown: (fromToken: string, toToken: string, fromAmount: number) => Promise<ISwapFeeBreakdown>
136
142
  }
137
143
 
138
144
  // ZLP-specific API interface
@@ -244,4 +250,17 @@ export interface IZLPAPI extends IBaseAPI {
244
250
  pool: string,
245
251
  tx: Transaction,
246
252
  ) => TransactionObjectArgument[]
253
+
254
+ /**
255
+ * Swaps tokens and returns the output coin to the user (PTB).
256
+ * Same as swap() but returns the output coin for use in composed transactions.
257
+ */
258
+ swapV2Ptb: (
259
+ fromToken: string,
260
+ toToken: string,
261
+ fromAmount: bigint,
262
+ fromCoinObjects: string[],
263
+ minAmountOut?: number,
264
+ tx?: Transaction,
265
+ ) => Promise<TransactionObjectArgument>
247
266
  }