@gainsnetwork/sdk 0.0.0-v10.rc10 → 0.0.0-v10.rc14

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.
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @dev Holding fees calculation utilities for v10+ markets
3
+ * @dev Combines funding fees and borrowing v2 fees
4
+ */
5
+ import { FundingFeeParams, PairFundingFeeData, PairOiAfterV10 } from "../../trade/fees/fundingFees/types";
6
+ import { BorrowingFeeParams, PairBorrowingFeeData } from "../../trade/fees/borrowingV2/types";
7
+ export type HoldingFeeRates = {
8
+ longHourlyRate: number;
9
+ shortHourlyRate: number;
10
+ fundingFeeLongHourlyRate: number;
11
+ fundingFeeShortHourlyRate: number;
12
+ borrowingFeeHourlyRate: number;
13
+ currentFundingRatePerSecondP: number;
14
+ currentBorrowingRatePerSecondP: number;
15
+ };
16
+ export type GetPairHoldingFeeRatesInput = {
17
+ fundingParams: FundingFeeParams;
18
+ fundingData: PairFundingFeeData;
19
+ pairOiToken: PairOiAfterV10;
20
+ netExposureToken: number;
21
+ netExposureUsd: number;
22
+ borrowingParams: BorrowingFeeParams | null;
23
+ borrowingData: PairBorrowingFeeData | null;
24
+ currentPairPrice: number;
25
+ currentTimestamp: number;
26
+ };
27
+ /**
28
+ * @dev Calculates current holding fee rates per hour for display
29
+ * @param input Input parameters for calculation
30
+ * @returns Holding fee rates per hour with breakdown
31
+ */
32
+ export declare const getPairHoldingFeeRates: (input: GetPairHoldingFeeRatesInput) => HoldingFeeRates;
33
+ /**
34
+ * @dev Converts a per-second rate to annual percentage rate (APR)
35
+ * @param ratePerSecond Rate per second
36
+ * @returns Annual percentage rate
37
+ */
38
+ export declare const convertRatePerSecondToAPR: (ratePerSecond: number) => number;
39
+ /**
40
+ * @dev Formats a holding fee rate for display
41
+ * @param rate Hourly rate (can be negative)
42
+ * @param decimals Number of decimal places
43
+ * @returns Formatted string with sign
44
+ */
45
+ export declare const formatHoldingFeeRate: (rate: number, decimals?: number) => string;
46
+ export * as HoldingFees from "./types";
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ /**
3
+ * @dev Holding fees calculation utilities for v10+ markets
4
+ * @dev Combines funding fees and borrowing v2 fees
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || function (mod) {
23
+ if (mod && mod.__esModule) return mod;
24
+ var result = {};
25
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
26
+ __setModuleDefault(result, mod);
27
+ return result;
28
+ };
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ exports.HoldingFees = exports.formatHoldingFeeRate = exports.convertRatePerSecondToAPR = exports.getPairHoldingFeeRates = void 0;
31
+ const fundingFees_1 = require("../../trade/fees/fundingFees");
32
+ const SECONDS_PER_HOUR = 3600;
33
+ const SECONDS_PER_YEAR = 365 * 24 * 60 * 60;
34
+ const PERCENTAGE_PRECISION = 100;
35
+ /**
36
+ * @dev Calculates current holding fee rates per hour for display
37
+ * @param input Input parameters for calculation
38
+ * @returns Holding fee rates per hour with breakdown
39
+ */
40
+ const getPairHoldingFeeRates = (input) => {
41
+ const { fundingParams, fundingData, pairOiToken, netExposureToken, netExposureUsd, borrowingParams, borrowingData, currentPairPrice, currentTimestamp, } = input;
42
+ // Calculate funding fee rates
43
+ let fundingFeeLongHourlyRate = 0;
44
+ let fundingFeeShortHourlyRate = 0;
45
+ let currentFundingRatePerSecondP = 0;
46
+ if (fundingParams.fundingFeesEnabled) {
47
+ // Get current funding rate
48
+ const pendingFunding = (0, fundingFees_1.getPairPendingAccFundingFees)(fundingParams, fundingData, currentPairPrice, pairOiToken, netExposureToken, netExposureUsd, currentTimestamp);
49
+ currentFundingRatePerSecondP = pendingFunding.currentFundingRatePerSecondP;
50
+ // Get APR multipliers
51
+ const { longAprMultiplier, shortAprMultiplier } = (0, fundingFees_1.getLongShortAprMultiplier)(currentFundingRatePerSecondP, pairOiToken.oiLongToken, pairOiToken.oiShortToken, fundingParams.aprMultiplierEnabled);
52
+ // Calculate hourly rates
53
+ // Funding rate * seconds per hour * current price * APR multiplier / 100
54
+ const baseHourlyRate = (currentFundingRatePerSecondP * SECONDS_PER_HOUR * currentPairPrice) /
55
+ PERCENTAGE_PRECISION;
56
+ // Long side pays when rate is positive, earns when negative
57
+ fundingFeeLongHourlyRate = baseHourlyRate * longAprMultiplier;
58
+ // Short side is opposite
59
+ fundingFeeShortHourlyRate = -baseHourlyRate * shortAprMultiplier;
60
+ }
61
+ // Calculate borrowing v2 rates
62
+ let borrowingFeeHourlyRate = 0;
63
+ let currentBorrowingRatePerSecondP = 0;
64
+ if (borrowingParams && borrowingData) {
65
+ currentBorrowingRatePerSecondP = borrowingParams.borrowingRatePerSecondP;
66
+ // Borrowing rate * seconds per hour * current price / 100
67
+ borrowingFeeHourlyRate =
68
+ (currentBorrowingRatePerSecondP * SECONDS_PER_HOUR * currentPairPrice) /
69
+ PERCENTAGE_PRECISION;
70
+ }
71
+ // Total holding fees (funding can be negative/positive, borrowing always positive cost)
72
+ const longHourlyRate = fundingFeeLongHourlyRate + borrowingFeeHourlyRate;
73
+ const shortHourlyRate = fundingFeeShortHourlyRate + borrowingFeeHourlyRate;
74
+ return {
75
+ longHourlyRate,
76
+ shortHourlyRate,
77
+ fundingFeeLongHourlyRate,
78
+ fundingFeeShortHourlyRate,
79
+ borrowingFeeHourlyRate,
80
+ currentFundingRatePerSecondP,
81
+ currentBorrowingRatePerSecondP,
82
+ };
83
+ };
84
+ exports.getPairHoldingFeeRates = getPairHoldingFeeRates;
85
+ /**
86
+ * @dev Converts a per-second rate to annual percentage rate (APR)
87
+ * @param ratePerSecond Rate per second
88
+ * @returns Annual percentage rate
89
+ */
90
+ const convertRatePerSecondToAPR = (ratePerSecond) => {
91
+ return ratePerSecond * SECONDS_PER_YEAR * PERCENTAGE_PRECISION;
92
+ };
93
+ exports.convertRatePerSecondToAPR = convertRatePerSecondToAPR;
94
+ /**
95
+ * @dev Formats a holding fee rate for display
96
+ * @param rate Hourly rate (can be negative)
97
+ * @param decimals Number of decimal places
98
+ * @returns Formatted string with sign
99
+ */
100
+ const formatHoldingFeeRate = (rate, decimals = 4) => {
101
+ const sign = rate > 0 ? "+" : "";
102
+ return `${sign}${rate.toFixed(decimals)}%`;
103
+ };
104
+ exports.formatHoldingFeeRate = formatHoldingFeeRate;
105
+ exports.HoldingFees = __importStar(require("./types"));
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @dev Type definitions for holding fees (funding + borrowing v2)
3
+ */
4
+ export interface HoldingFeeRates {
5
+ longHourlyRate: number;
6
+ shortHourlyRate: number;
7
+ fundingFeeLongHourlyRate: number;
8
+ fundingFeeShortHourlyRate: number;
9
+ borrowingFeeHourlyRate: number;
10
+ currentFundingRatePerSecondP: number;
11
+ currentBorrowingRatePerSecondP: number;
12
+ }
13
+ export interface GetPairHoldingFeeRatesInput {
14
+ fundingParams: import("../../trade/fees/fundingFees/types").FundingFeeParams;
15
+ fundingData: import("../../trade/fees/fundingFees/types").PairFundingFeeData;
16
+ pairOiToken: import("../../trade/fees/fundingFees/types").PairOiAfterV10;
17
+ netExposureToken: number;
18
+ netExposureUsd: number;
19
+ borrowingParams: import("../../trade/fees/borrowingV2/types").BorrowingFeeParams | null;
20
+ borrowingData: import("../../trade/fees/borrowingV2/types").PairBorrowingFeeData | null;
21
+ currentPairPrice: number;
22
+ currentTimestamp: number;
23
+ }
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ /**
3
+ * @dev Type definitions for holding fees (funding + borrowing v2)
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -6,3 +6,4 @@ export * from "./commodities";
6
6
  export * from "./oi";
7
7
  export * from "./collateral";
8
8
  export * from "./price";
9
+ export * from "./holdingFees";
@@ -22,3 +22,4 @@ __exportStar(require("./commodities"), exports);
22
22
  __exportStar(require("./oi"), exports);
23
23
  __exportStar(require("./collateral"), exports);
24
24
  __exportStar(require("./price"), exports);
25
+ __exportStar(require("./holdingFees"), exports);
@@ -7,10 +7,9 @@ import { UnifiedPairOi, ComputedOi } from "./types";
7
7
  /**
8
8
  * @dev Converts pre-v10 OI from contract format
9
9
  * @param contractOi Contract OpenInterest struct from BorrowingFeesStorage
10
- * @param precision Collateral precision for conversion
11
10
  * @returns Normalized OI with long/short values
12
11
  */
13
- export declare const convertBeforeV10Collateral: (contractOi: IBorrowingFees.OpenInterestStructOutput, precision: number) => {
12
+ export declare const convertBeforeV10Collateral: (contractOi: IBorrowingFees.OpenInterestStructOutput) => {
14
13
  long: number;
15
14
  short: number;
16
15
  };
@@ -8,13 +8,12 @@ exports.computeOiValues = exports.convertPairOiArray = exports.convertPairOi = e
8
8
  /**
9
9
  * @dev Converts pre-v10 OI from contract format
10
10
  * @param contractOi Contract OpenInterest struct from BorrowingFeesStorage
11
- * @param precision Collateral precision for conversion
12
11
  * @returns Normalized OI with long/short values
13
12
  */
14
- const convertBeforeV10Collateral = (contractOi, precision) => {
13
+ const convertBeforeV10Collateral = (contractOi) => {
15
14
  return {
16
- long: Number(contractOi.long) / precision,
17
- short: Number(contractOi.short) / precision,
15
+ long: Number(contractOi.long) / 1e10,
16
+ short: Number(contractOi.short) / 1e10,
18
17
  };
19
18
  };
20
19
  exports.convertBeforeV10Collateral = convertBeforeV10Collateral;
@@ -54,8 +53,8 @@ exports.convertTokenOi = convertTokenOi;
54
53
  */
55
54
  const convertPairOi = (beforeV10, afterV10Collateral, afterV10Token, collateralPrecision) => {
56
55
  return {
57
- maxCollateral: Number(beforeV10.max) / collateralPrecision,
58
- beforeV10Collateral: (0, exports.convertBeforeV10Collateral)(beforeV10, collateralPrecision),
56
+ maxCollateral: Number(beforeV10.max) / 1e10,
57
+ beforeV10Collateral: (0, exports.convertBeforeV10Collateral)(beforeV10),
59
58
  collateral: (0, exports.convertCollateralOi)(afterV10Collateral, collateralPrecision),
60
59
  token: (0, exports.convertTokenOi)(afterV10Token),
61
60
  };
@@ -2,9 +2,48 @@
2
2
  * @dev Main export file for OI module
3
3
  * @dev Provides unified Open Interest management functionality
4
4
  */
5
- export { UnifiedPairOi, GroupOi, OiUsageMetadata, ComputedOi } from "./types";
5
+ import { GenericPairOiContext } from "./types";
6
+ export declare const getPairTotalOisCollateral: (pairIndex: number, context: GenericPairOiContext) => {
7
+ long: number;
8
+ short: number;
9
+ };
10
+ /**
11
+ * @dev Returns pair total dynamic open interest (before v10 + after v10) in collateral tokens
12
+ * @param pairIndex index of pair
13
+ * @param context contains UnifiedPairOi array and current pair price
14
+ * @returns dynamic OI for long and short sides in collateral precision
15
+ */
16
+ export declare const getPairTotalOisDynamicCollateral: (pairIndex: number, context: GenericPairOiContext & {
17
+ currentPairPrice: number;
18
+ }) => {
19
+ long: number;
20
+ short: number;
21
+ };
22
+ /**
23
+ * @dev Returns pair total dynamic open interest (before v10 + after v10) in collateral tokens on one side only
24
+ * @param pairIndex index of pair
25
+ * @param long true if long, false if short
26
+ * @param context contains UnifiedPairOi array and current pair price
27
+ * @returns dynamic OI for the specified side in collateral precision
28
+ */
29
+ export declare const getPairTotalOiDynamicCollateral: (pairIndex: number, long: boolean, context: GenericPairOiContext & {
30
+ currentPairPrice: number;
31
+ }) => number;
32
+ /**
33
+ * @dev Returns pair open interest skew (v10 only) in tokens
34
+ * @param pairIndex index of pair
35
+ * @param context contains UnifiedPairOi array
36
+ * @returns skew in token amount (positive = more longs, negative = more shorts)
37
+ */
38
+ export declare const getPairV10OiTokenSkewCollateral: (pairIndex: number, context: GenericPairOiContext) => number;
39
+ /**
40
+ * @dev Returns pair dynamic skew (v10 only) in collateral tokens
41
+ * @param pairIndex index of pair
42
+ * @param context contains UnifiedPairOi array and current pair price
43
+ * @returns dynamic skew in collateral precision
44
+ */
45
+ export declare const getPairV10OiDynamicSkewCollateral: (pairIndex: number, context: GenericPairOiContext & {
46
+ currentPairPrice: number;
47
+ }) => number;
48
+ export { UnifiedPairOi, GroupOi, ComputedOi } from "./types";
6
49
  export { convertBeforeV10Collateral, convertCollateralOi, convertTokenOi, convertPairOi, convertPairOiArray, computeOiValues, } from "./converter";
7
- export { fetchPairOi, fetchMultiplePairOi, createOiContext, fetchOiForUseCase, } from "./fetcher";
8
- export { withinMaxPairOi, calculateDynamicOi, getRemainingOiCapacity, withinMaxGroupOiDynamic, getGroupDynamicOi, validateOiLimits, } from "./validation";
9
- import { OiUsageMetadata } from "./types";
10
- export declare const OI_USAGE: OiUsageMetadata;
@@ -4,7 +4,69 @@
4
4
  * @dev Provides unified Open Interest management functionality
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.OI_USAGE = exports.validateOiLimits = exports.getGroupDynamicOi = exports.withinMaxGroupOiDynamic = exports.getRemainingOiCapacity = exports.calculateDynamicOi = exports.withinMaxPairOi = exports.fetchOiForUseCase = exports.createOiContext = exports.fetchMultiplePairOi = exports.fetchPairOi = exports.computeOiValues = exports.convertPairOiArray = exports.convertPairOi = exports.convertTokenOi = exports.convertCollateralOi = exports.convertBeforeV10Collateral = void 0;
7
+ exports.computeOiValues = exports.convertPairOiArray = exports.convertPairOi = exports.convertTokenOi = exports.convertCollateralOi = exports.convertBeforeV10Collateral = exports.getPairV10OiDynamicSkewCollateral = exports.getPairV10OiTokenSkewCollateral = exports.getPairTotalOiDynamicCollateral = exports.getPairTotalOisDynamicCollateral = exports.getPairTotalOisCollateral = void 0;
8
+ const getPairTotalOisCollateral = (pairIndex, context) => {
9
+ return {
10
+ long: context.pairOis[pairIndex].beforeV10Collateral.long +
11
+ context.pairOis[pairIndex].collateral.long,
12
+ short: context.pairOis[pairIndex].beforeV10Collateral.short +
13
+ context.pairOis[pairIndex].collateral.short,
14
+ };
15
+ };
16
+ exports.getPairTotalOisCollateral = getPairTotalOisCollateral;
17
+ /**
18
+ * @dev Returns pair total dynamic open interest (before v10 + after v10) in collateral tokens
19
+ * @param pairIndex index of pair
20
+ * @param context contains UnifiedPairOi array and current pair price
21
+ * @returns dynamic OI for long and short sides in collateral precision
22
+ */
23
+ const getPairTotalOisDynamicCollateral = (pairIndex, context) => {
24
+ const pairOi = context.pairOis[pairIndex];
25
+ // We have to use the initial collateral OIs for pre-v10 trades because we don't have OIs in token amount
26
+ const oiLongCollateralDynamicAfterV10 = pairOi.beforeV10Collateral.long +
27
+ pairOi.token.long * context.currentPairPrice;
28
+ const oiShortCollateralDynamicAfterV10 = pairOi.beforeV10Collateral.short +
29
+ pairOi.token.short * context.currentPairPrice;
30
+ return {
31
+ long: oiLongCollateralDynamicAfterV10,
32
+ short: oiShortCollateralDynamicAfterV10,
33
+ };
34
+ };
35
+ exports.getPairTotalOisDynamicCollateral = getPairTotalOisDynamicCollateral;
36
+ /**
37
+ * @dev Returns pair total dynamic open interest (before v10 + after v10) in collateral tokens on one side only
38
+ * @param pairIndex index of pair
39
+ * @param long true if long, false if short
40
+ * @param context contains UnifiedPairOi array and current pair price
41
+ * @returns dynamic OI for the specified side in collateral precision
42
+ */
43
+ const getPairTotalOiDynamicCollateral = (pairIndex, long, context) => {
44
+ const dynamicOis = (0, exports.getPairTotalOisDynamicCollateral)(pairIndex, context);
45
+ return long ? dynamicOis.long : dynamicOis.short;
46
+ };
47
+ exports.getPairTotalOiDynamicCollateral = getPairTotalOiDynamicCollateral;
48
+ /**
49
+ * @dev Returns pair open interest skew (v10 only) in tokens
50
+ * @param pairIndex index of pair
51
+ * @param context contains UnifiedPairOi array
52
+ * @returns skew in token amount (positive = more longs, negative = more shorts)
53
+ */
54
+ const getPairV10OiTokenSkewCollateral = (pairIndex, context) => {
55
+ const pairOi = context.pairOis[pairIndex];
56
+ return pairOi.token.long - pairOi.token.short;
57
+ };
58
+ exports.getPairV10OiTokenSkewCollateral = getPairV10OiTokenSkewCollateral;
59
+ /**
60
+ * @dev Returns pair dynamic skew (v10 only) in collateral tokens
61
+ * @param pairIndex index of pair
62
+ * @param context contains UnifiedPairOi array and current pair price
63
+ * @returns dynamic skew in collateral precision
64
+ */
65
+ const getPairV10OiDynamicSkewCollateral = (pairIndex, context) => {
66
+ return ((0, exports.getPairV10OiTokenSkewCollateral)(pairIndex, context) *
67
+ context.currentPairPrice);
68
+ };
69
+ exports.getPairV10OiDynamicSkewCollateral = getPairV10OiDynamicSkewCollateral;
8
70
  // Converters
9
71
  var converter_1 = require("./converter");
10
72
  Object.defineProperty(exports, "convertBeforeV10Collateral", { enumerable: true, get: function () { return converter_1.convertBeforeV10Collateral; } });
@@ -13,25 +75,3 @@ Object.defineProperty(exports, "convertTokenOi", { enumerable: true, get: functi
13
75
  Object.defineProperty(exports, "convertPairOi", { enumerable: true, get: function () { return converter_1.convertPairOi; } });
14
76
  Object.defineProperty(exports, "convertPairOiArray", { enumerable: true, get: function () { return converter_1.convertPairOiArray; } });
15
77
  Object.defineProperty(exports, "computeOiValues", { enumerable: true, get: function () { return converter_1.computeOiValues; } });
16
- // Fetchers
17
- var fetcher_1 = require("./fetcher");
18
- Object.defineProperty(exports, "fetchPairOi", { enumerable: true, get: function () { return fetcher_1.fetchPairOi; } });
19
- Object.defineProperty(exports, "fetchMultiplePairOi", { enumerable: true, get: function () { return fetcher_1.fetchMultiplePairOi; } });
20
- Object.defineProperty(exports, "createOiContext", { enumerable: true, get: function () { return fetcher_1.createOiContext; } });
21
- Object.defineProperty(exports, "fetchOiForUseCase", { enumerable: true, get: function () { return fetcher_1.fetchOiForUseCase; } });
22
- // Validation
23
- var validation_1 = require("./validation");
24
- Object.defineProperty(exports, "withinMaxPairOi", { enumerable: true, get: function () { return validation_1.withinMaxPairOi; } });
25
- Object.defineProperty(exports, "calculateDynamicOi", { enumerable: true, get: function () { return validation_1.calculateDynamicOi; } });
26
- Object.defineProperty(exports, "getRemainingOiCapacity", { enumerable: true, get: function () { return validation_1.getRemainingOiCapacity; } });
27
- Object.defineProperty(exports, "withinMaxGroupOiDynamic", { enumerable: true, get: function () { return validation_1.withinMaxGroupOiDynamic; } });
28
- Object.defineProperty(exports, "getGroupDynamicOi", { enumerable: true, get: function () { return validation_1.getGroupDynamicOi; } });
29
- Object.defineProperty(exports, "validateOiLimits", { enumerable: true, get: function () { return validation_1.validateOiLimits; } });
30
- exports.OI_USAGE = {
31
- borrowingV1: ["beforeV10Collateral", "token"],
32
- fundingFees: ["token"],
33
- skewImpact: ["token"],
34
- maxPairOi: ["beforeV10Collateral", "token"],
35
- maxGroupOi: ["beforeV10Collateral", "token"],
36
- maxSkew: ["token"], // V10+ only: uses token OI
37
- };
@@ -37,23 +37,14 @@ export interface UnifiedPairOi {
37
37
  short: number;
38
38
  };
39
39
  }
40
+ export type GenericPairOiContext = {
41
+ pairOis: UnifiedPairOi[];
42
+ };
40
43
  /**
41
44
  * @dev Group OI remains unchanged - only used by borrowing v1
42
45
  * @dev Re-export existing type for consistency
43
46
  */
44
47
  export { OpenInterest as GroupOi } from "../../trade/types";
45
- /**
46
- * @dev Metadata describing which OI systems are used by different features
47
- * @dev Helps consumers understand OI usage patterns
48
- */
49
- export interface OiUsageMetadata {
50
- borrowingV1: Array<"beforeV10Collateral" | "token">;
51
- fundingFees: Array<"token">;
52
- skewImpact: Array<"token">;
53
- maxPairOi: Array<"beforeV10Collateral" | "token">;
54
- maxGroupOi: Array<"beforeV10Collateral" | "token">;
55
- maxSkew: Array<"token">;
56
- }
57
48
  /**
58
49
  * @dev Helper type for computed OI values
59
50
  */
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @dev Holding fees calculation utilities for v10+ markets
3
+ * @dev Combines funding fees and borrowing v2 fees
4
+ */
5
+ import { FundingFeeParams, PairFundingFeeData, PairOiAfterV10 } from "../fundingFees/types";
6
+ import { BorrowingFeeParams, PairBorrowingFeeData } from "../borrowingV2/types";
7
+ export type HoldingFeeRates = {
8
+ longHourlyRate: number;
9
+ shortHourlyRate: number;
10
+ fundingFeeLongHourlyRate: number;
11
+ fundingFeeShortHourlyRate: number;
12
+ borrowingFeeHourlyRate: number;
13
+ currentFundingRatePerSecondP: number;
14
+ currentBorrowingRatePerSecondP: number;
15
+ };
16
+ export type GetPairHoldingFeeRatesInput = {
17
+ fundingParams: FundingFeeParams;
18
+ fundingData: PairFundingFeeData;
19
+ pairOiToken: PairOiAfterV10;
20
+ netExposureToken: number;
21
+ netExposureUsd: number;
22
+ borrowingParams: BorrowingFeeParams | null;
23
+ borrowingData: PairBorrowingFeeData | null;
24
+ currentPairPrice: number;
25
+ currentTimestamp: number;
26
+ };
27
+ /**
28
+ * @dev Calculates current holding fee rates per hour for display
29
+ * @param input Input parameters for calculation
30
+ * @returns Holding fee rates per hour with breakdown
31
+ */
32
+ export declare const getPairHoldingFeeRates: (input: GetPairHoldingFeeRatesInput) => HoldingFeeRates;
33
+ /**
34
+ * @dev Converts a per-second rate to annual percentage rate (APR)
35
+ * @param ratePerSecond Rate per second
36
+ * @returns Annual percentage rate
37
+ */
38
+ export declare const convertRatePerSecondToAPR: (ratePerSecond: number) => number;
39
+ /**
40
+ * @dev Formats a holding fee rate for display
41
+ * @param rate Hourly rate (can be negative)
42
+ * @param decimals Number of decimal places
43
+ * @returns Formatted string with sign
44
+ */
45
+ export declare const formatHoldingFeeRate: (rate: number, decimals?: number) => string;
46
+ export * as HoldingFees from "./types";
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ /**
3
+ * @dev Holding fees calculation utilities for v10+ markets
4
+ * @dev Combines funding fees and borrowing v2 fees
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || function (mod) {
23
+ if (mod && mod.__esModule) return mod;
24
+ var result = {};
25
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
26
+ __setModuleDefault(result, mod);
27
+ return result;
28
+ };
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ exports.HoldingFees = exports.formatHoldingFeeRate = exports.convertRatePerSecondToAPR = exports.getPairHoldingFeeRates = void 0;
31
+ const fundingFees_1 = require("../fundingFees");
32
+ const SECONDS_PER_HOUR = 3600;
33
+ const SECONDS_PER_YEAR = 365 * 24 * 60 * 60;
34
+ const PERCENTAGE_PRECISION = 100;
35
+ /**
36
+ * @dev Calculates current holding fee rates per hour for display
37
+ * @param input Input parameters for calculation
38
+ * @returns Holding fee rates per hour with breakdown
39
+ */
40
+ const getPairHoldingFeeRates = (input) => {
41
+ const { fundingParams, fundingData, pairOiToken, netExposureToken, netExposureUsd, borrowingParams, borrowingData, currentPairPrice, currentTimestamp, } = input;
42
+ // Calculate funding fee rates
43
+ let fundingFeeLongHourlyRate = 0;
44
+ let fundingFeeShortHourlyRate = 0;
45
+ let currentFundingRatePerSecondP = 0;
46
+ if (fundingParams.fundingFeesEnabled) {
47
+ // Get current funding rate
48
+ const pendingFunding = (0, fundingFees_1.getPairPendingAccFundingFees)(fundingParams, fundingData, currentPairPrice, pairOiToken, netExposureToken, netExposureUsd, currentTimestamp);
49
+ currentFundingRatePerSecondP = pendingFunding.currentFundingRatePerSecondP;
50
+ // Get APR multipliers
51
+ const { longAprMultiplier, shortAprMultiplier } = (0, fundingFees_1.getLongShortAprMultiplier)(currentFundingRatePerSecondP, pairOiToken.oiLongToken, pairOiToken.oiShortToken, fundingParams.aprMultiplierEnabled);
52
+ // Calculate hourly rates
53
+ // Funding rate * seconds per hour * current price * APR multiplier / 100
54
+ const baseHourlyRate = (currentFundingRatePerSecondP * SECONDS_PER_HOUR * currentPairPrice) /
55
+ PERCENTAGE_PRECISION;
56
+ // Long side pays when rate is positive, earns when negative
57
+ fundingFeeLongHourlyRate = baseHourlyRate * longAprMultiplier;
58
+ // Short side is opposite
59
+ fundingFeeShortHourlyRate = -baseHourlyRate * shortAprMultiplier;
60
+ }
61
+ // Calculate borrowing v2 rates
62
+ let borrowingFeeHourlyRate = 0;
63
+ let currentBorrowingRatePerSecondP = 0;
64
+ if (borrowingParams && borrowingData) {
65
+ currentBorrowingRatePerSecondP = borrowingParams.borrowingRatePerSecondP;
66
+ // Borrowing rate * seconds per hour * current price / 100
67
+ borrowingFeeHourlyRate =
68
+ (currentBorrowingRatePerSecondP * SECONDS_PER_HOUR * currentPairPrice) /
69
+ PERCENTAGE_PRECISION;
70
+ }
71
+ // Total holding fees (funding can be negative/positive, borrowing always positive cost)
72
+ const longHourlyRate = fundingFeeLongHourlyRate + borrowingFeeHourlyRate;
73
+ const shortHourlyRate = fundingFeeShortHourlyRate + borrowingFeeHourlyRate;
74
+ return {
75
+ longHourlyRate,
76
+ shortHourlyRate,
77
+ fundingFeeLongHourlyRate,
78
+ fundingFeeShortHourlyRate,
79
+ borrowingFeeHourlyRate,
80
+ currentFundingRatePerSecondP,
81
+ currentBorrowingRatePerSecondP,
82
+ };
83
+ };
84
+ exports.getPairHoldingFeeRates = getPairHoldingFeeRates;
85
+ /**
86
+ * @dev Converts a per-second rate to annual percentage rate (APR)
87
+ * @param ratePerSecond Rate per second
88
+ * @returns Annual percentage rate
89
+ */
90
+ const convertRatePerSecondToAPR = (ratePerSecond) => {
91
+ return ratePerSecond * SECONDS_PER_YEAR * PERCENTAGE_PRECISION;
92
+ };
93
+ exports.convertRatePerSecondToAPR = convertRatePerSecondToAPR;
94
+ /**
95
+ * @dev Formats a holding fee rate for display
96
+ * @param rate Hourly rate (can be negative)
97
+ * @param decimals Number of decimal places
98
+ * @returns Formatted string with sign
99
+ */
100
+ const formatHoldingFeeRate = (rate, decimals = 4) => {
101
+ const sign = rate > 0 ? "+" : "";
102
+ return `${sign}${rate.toFixed(decimals)}%`;
103
+ };
104
+ exports.formatHoldingFeeRate = formatHoldingFeeRate;
105
+ exports.HoldingFees = __importStar(require("./types"));
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @dev Type definitions for holding fees (funding + borrowing v2)
3
+ */
4
+ export interface HoldingFeeRates {
5
+ longHourlyRate: number;
6
+ shortHourlyRate: number;
7
+ fundingFeeLongHourlyRate: number;
8
+ fundingFeeShortHourlyRate: number;
9
+ borrowingFeeHourlyRate: number;
10
+ currentFundingRatePerSecondP: number;
11
+ currentBorrowingRatePerSecondP: number;
12
+ }
13
+ export interface GetPairHoldingFeeRatesInput {
14
+ fundingParams: import("../fundingFees/types").FundingFeeParams;
15
+ fundingData: import("../fundingFees/types").PairFundingFeeData;
16
+ pairOiToken: import("../fundingFees/types").PairOiAfterV10;
17
+ netExposureToken: number;
18
+ netExposureUsd: number;
19
+ borrowingParams: import("../borrowingV2/types").BorrowingFeeParams | null;
20
+ borrowingData: import("../borrowingV2/types").PairBorrowingFeeData | null;
21
+ currentPairPrice: number;
22
+ currentTimestamp: number;
23
+ }
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ /**
3
+ * @dev Type definitions for holding fees (funding + borrowing v2)
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,6 +1,7 @@
1
1
  export * from "./borrowing";
2
2
  export * from "./tiers";
3
3
  export * from "./trading";
4
+ export * from "../../markets/holdingFees";
4
5
  export { convertTradeFeesData, convertTradeFeesDataArray, convertUiRealizedPnlData, convertUiRealizedPnlDataArray, encodeTradeFeesData, encodeUiRealizedPnlData, } from "./converter";
5
6
  export { BorrowingFeeV2, borrowingFeeV2Utils, getPairPendingAccBorrowingFees as getPairPendingAccBorrowingFeesV2, getTradeBorrowingFeesCollateral as getTradeBorrowingFeesCollateralV2, getPairBorrowingFees as getPairBorrowingFeesV2, MAX_BORROWING_RATE_PER_SECOND as MAX_BORROWING_RATE_PER_SECOND_V2, BORROWING_V2_PRECISION, } from "./borrowingV2";
6
7
  export { convertBorrowingFeeParams as convertBorrowingFeeParamsV2, convertBorrowingFeeParamsArray as convertBorrowingFeeParamsArrayV2, convertPairBorrowingFeeData as convertPairBorrowingFeeDataV2, convertPairBorrowingFeeDataArray as convertPairBorrowingFeeDataArrayV2, convertTradeInitialAccFees as convertTradeInitialAccFeesV2, convertTradeInitialAccFeesArray as convertTradeInitialAccFeesArrayV2, createBorrowingV2Context, isValidBorrowingRate as isValidBorrowingRateV2, borrowingRateToAPR as borrowingRateToAPRV2, aprToBorrowingRate as aprToBorrowingRateV2, } from "./borrowingV2/converter";
@@ -19,6 +19,7 @@ exports.FUNDING_FEES_PRECISION = exports.calculateVelocityFromSkew = exports.apr
19
19
  __exportStar(require("./borrowing"), exports);
20
20
  __exportStar(require("./tiers"), exports);
21
21
  __exportStar(require("./trading"), exports);
22
+ __exportStar(require("../../markets/holdingFees"), exports);
22
23
  // TradeFeesData and UiRealizedPnlData converters
23
24
  var converter_1 = require("./converter");
24
25
  Object.defineProperty(exports, "convertTradeFeesData", { enumerable: true, get: function () { return converter_1.convertTradeFeesData; } });
@@ -2,10 +2,21 @@
2
2
  * @dev PnL calculation module
3
3
  * @dev Provides functions matching v10 contract implementations
4
4
  */
5
- import { Trade, TradeInfo, LiquidationParams, Fee, GlobalTradeFeeParams } from "../types";
5
+ import { Trade, TradeInfo, LiquidationParams, Fee, GlobalTradeFeeParams, TradeFeesData } from "../types";
6
6
  import { ComprehensivePnlResult, GetComprehensivePnlContext } from "./types";
7
7
  import { BorrowingFee } from "../fees/borrowing";
8
8
  import { ContractsVersion } from "../../contracts/types";
9
+ /**
10
+ * @dev Gets trade realized PnL components from TradeFeesData
11
+ * @dev Mirrors contract's getTradeRealizedPnlCollateral function
12
+ * @param tradeFeesData Trade fees data containing realized components
13
+ * @returns Tuple of [realizedPnlCollateral, realizedTradingFeesCollateral, totalRealizedPnlCollateral]
14
+ */
15
+ export declare const getTradeRealizedPnlCollateral: (tradeFeesData: TradeFeesData) => {
16
+ realizedPnlCollateral: number;
17
+ realizedTradingFeesCollateral: number;
18
+ totalRealizedPnlCollateral: number;
19
+ };
9
20
  /**
10
21
  * @dev Calculates PnL percentage for a position
11
22
  * @dev Mirrors contract's getPnlPercent function
@@ -18,10 +18,27 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
18
18
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
19
19
  };
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.getPriceForTargetPnlPercentage = exports.getPnl = exports.getComprehensivePnl = exports.getTradeValue = exports.getPnlPercent = void 0;
21
+ exports.getPriceForTargetPnlPercentage = exports.getPnl = exports.getComprehensivePnl = exports.getTradeValue = exports.getPnlPercent = exports.getTradeRealizedPnlCollateral = void 0;
22
22
  const borrowing_1 = require("../fees/borrowing");
23
23
  const trading_1 = require("../fees/trading");
24
24
  const liquidation_1 = require("../liquidation");
25
+ /**
26
+ * @dev Gets trade realized PnL components from TradeFeesData
27
+ * @dev Mirrors contract's getTradeRealizedPnlCollateral function
28
+ * @param tradeFeesData Trade fees data containing realized components
29
+ * @returns Tuple of [realizedPnlCollateral, realizedTradingFeesCollateral, totalRealizedPnlCollateral]
30
+ */
31
+ const getTradeRealizedPnlCollateral = (tradeFeesData) => {
32
+ const realizedPnlCollateral = tradeFeesData.realizedPnlCollateral;
33
+ const realizedTradingFeesCollateral = tradeFeesData.realizedTradingFeesCollateral;
34
+ const totalRealizedPnlCollateral = realizedPnlCollateral - realizedTradingFeesCollateral;
35
+ return {
36
+ realizedPnlCollateral,
37
+ realizedTradingFeesCollateral,
38
+ totalRealizedPnlCollateral,
39
+ };
40
+ };
41
+ exports.getTradeRealizedPnlCollateral = getTradeRealizedPnlCollateral;
25
42
  /**
26
43
  * @dev Calculates PnL percentage for a position
27
44
  * @dev Mirrors contract's getPnlPercent function
@@ -93,7 +110,8 @@ const getComprehensivePnl = (trade, currentPrice, tradeInfo, context) => {
93
110
  traderFeeMultiplier: context.trading.traderFeeMultiplier,
94
111
  });
95
112
  // Total fees
96
- const totalFees = borrowingFeeV1 + borrowingFeeV2 + fundingFee + closingFee;
113
+ const totalHoldingFees = borrowingFeeV1 + borrowingFeeV2 + fundingFee;
114
+ const totalFees = totalHoldingFees + closingFee;
97
115
  // Check liquidation
98
116
  const liquidationThreshold = ((_a = context.tradeData) === null || _a === void 0 ? void 0 : _a.liquidationParams)
99
117
  ? (0, liquidation_1.getLiqPnlThresholdP)(context.tradeData.liquidationParams, trade.leverage) *
@@ -104,20 +122,19 @@ const getComprehensivePnl = (trade, currentPrice, tradeInfo, context) => {
104
122
  if (isLiquidated) {
105
123
  pnlPercent = -100;
106
124
  }
125
+ // Get realized PnL components from TradeFeesData
126
+ const { totalRealizedPnlCollateral } = (0, exports.getTradeRealizedPnlCollateral)(context.tradeData.tradeFeesData);
107
127
  // Calculate final trade value
108
128
  const tradeValue = (0, exports.getTradeValue)(trade.collateralAmount, pnlPercent, totalFees);
109
129
  // Calculate PnL in collateral
110
130
  const pnlCollateral = trade.collateralAmount * (pnlPercent / 100);
111
131
  // Calculate leveraged position size
112
132
  const leveragedPositionSize = trade.collateralAmount * trade.leverage;
113
- // Calculate net PnL after fees
114
- const netPnlAfterFees = pnlCollateral - totalFees;
115
133
  // Calculate unrealized PnL (before closing fee, after holding fees)
116
- const totalHoldingFees = borrowingFeeV1 + borrowingFeeV2 + fundingFee;
117
- const uPnlCollateral = pnlCollateral - totalHoldingFees;
134
+ const uPnlCollateral = pnlCollateral - totalHoldingFees + totalRealizedPnlCollateral;
118
135
  const uPnlPercent = (uPnlCollateral / trade.collateralAmount) * 100;
119
136
  // Realized PnL (after all fees including closing)
120
- const realizedPnlCollateral = pnlCollateral - totalFees;
137
+ const realizedPnlCollateral = pnlCollateral - totalFees + totalRealizedPnlCollateral;
121
138
  const realizedPnlPercent = (realizedPnlCollateral / trade.collateralAmount) * 100;
122
139
  return {
123
140
  // Core PnL values
@@ -143,7 +160,6 @@ const getComprehensivePnl = (trade, currentPrice, tradeInfo, context) => {
143
160
  isProfitable: pnlPercent > 0,
144
161
  // Additional info
145
162
  leveragedPositionSize,
146
- netPnlAfterFees,
147
163
  };
148
164
  };
149
165
  exports.getComprehensivePnl = getComprehensivePnl;
@@ -52,7 +52,6 @@ export type ComprehensivePnlResult = {
52
52
  isLiquidated: boolean;
53
53
  isProfitable: boolean;
54
54
  leveragedPositionSize: number;
55
- netPnlAfterFees: number;
56
55
  };
57
56
  /**
58
57
  * @dev Context for comprehensive PnL calculations with nested sub-contexts
@@ -12,17 +12,20 @@ const types_1 = require("../../../contracts/types");
12
12
  var builder_1 = require("./builder");
13
13
  Object.defineProperty(exports, "buildTradeClosingPriceImpactContext", { enumerable: true, get: function () { return builder_1.buildTradeClosingPriceImpactContext; } });
14
14
  /**
15
- * @dev Calculates position size in tokens for partial close
16
- * @param originalPositionSizeToken Original position size in tokens
15
+ * @dev Calculates position size in tokens for the portion being closed
16
+ * @param positionSizeCollateral Position size in collateral units being closed
17
+ * @param originalPositionSizeToken Original total position size in tokens
17
18
  * @param originalCollateral Original collateral amount
18
- * @param closingCollateral Collateral amount being closed
19
- * @returns Proportional position size in tokens
19
+ * @param originalLeverage Original leverage
20
+ * @returns Position size in tokens for the closing portion
20
21
  */
21
- const calculateClosingPositionSizeToken = (originalPositionSizeToken, originalCollateral, closingCollateral) => {
22
- if (originalCollateral === 0)
22
+ const calculateClosingPositionSizeToken = (positionSizeCollateral, originalPositionSizeToken, originalCollateral, originalLeverage) => {
23
+ const totalPositionSizeCollateral = originalCollateral * originalLeverage;
24
+ if (totalPositionSizeCollateral === 0)
23
25
  return 0;
24
- // Proportional calculation: (closingCollateral / originalCollateral) * originalPositionSizeToken
25
- return (closingCollateral * originalPositionSizeToken) / originalCollateral;
26
+ // Match contract logic: (positionSizeCollateral * originalPositionSizeToken) / totalPositionSizeCollateral
27
+ return ((positionSizeCollateral * originalPositionSizeToken) /
28
+ totalPositionSizeCollateral);
26
29
  };
27
30
  /**
28
31
  * @dev Calculates all price impacts for trade closing
@@ -46,7 +49,7 @@ const getTradeClosingPriceImpact = (input, context) => {
46
49
  }
47
50
  // Calculate position size in tokens (proportional to collateral being closed)
48
51
  const positionSizeToken = input.trade.positionSizeToken
49
- ? calculateClosingPositionSizeToken(input.trade.positionSizeToken, input.trade.collateralAmount, input.positionSizeCollateral)
52
+ ? calculateClosingPositionSizeToken(input.positionSizeCollateral, input.trade.positionSizeToken, input.trade.collateralAmount, input.trade.leverage)
50
53
  : 0;
51
54
  // Calculate fixed spread (reversed for closing)
52
55
  const fixedSpreadP = (0, cumulVol_1.getFixedSpreadP)(input.pairSpreadP, input.trade.long, false // closing
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gainsnetwork/sdk",
3
- "version": "0.0.0-v10.rc10",
3
+ "version": "0.0.0-v10.rc14",
4
4
  "description": "Gains Network SDK",
5
5
  "main": "./lib/index.js",
6
6
  "files": [