Skip to main content
Notice: These documents are currently in progress. For any questions or clarifications, please contact the team.
Current version: https://www.npmjs.com/package/@gainsnetwork/sdk/v/1.0.0-rc12

v10 Changes - Overview

  • New funding fees (skew-based, only on v10 positions)
  • New borrowing fees v2 (alongside existing v1)
  • New P&L withdrawal feature (withdraw profits without closing)
  • New counter trade type (fee discounts for improving skew)
  • New skew price impact
  • New market max skew limits
  • Fees no longer impact position size (exact position sizes)
  • Modified borrowing fees v1 (uses dynamic OI)
  • Modified partial update requirements (use effective leverage)
  • Modified liquidation, pnl, fees calculations
  • Pre and post v10 OI stored separately
  • Pre-v10 trades cannot partial add
  • New accounting: TradeFeesData and UiRealizedPnlData
  • New Trade fields: positionSizeToken and isCounterTrade

Developer Notes - Overview

  • SDK has been updated to support v10 more effectively than previous versions
    • Backend transforms and converters are available (fetching is still separate)
      • Transform trading variables: transformGlobalTradingVariables
      • Transform global trades: transformGlobalTrades
      • All functions expect backend types
    • Additional feature support
      • Holding fees
      • Action fees
      • Price impact
      • PnL
      • Liquidations
      • Counter trade validation
      • Effective leverage
      • Market holding rates
      • Market leverage requirements
      • Market open interest
      • Market price
    • New context builders
      • More declarative development pattern
      • SDK functions mirror contract functions. But they don’t fetch data, instead rely on all data provided
      • Provide large trading variables object and context builder will prepare struct for specific functions with all expected data

Integration Guide

NOTE: For tradingVariables and any trade struct (trade, tradeInfo, etc), consume from backends first: Backend

1. New Funding Fees

Funding fees are skew-based fees that balance long/short exposure. Trade-Specific Funding Fees:
import { buildFundingContext } from "@gainsnetwork/sdk/trade/fees/fundingFees/builder";
import {
  getTradeFundingFeesCollateral,
  getAvgFundingRatePerSecondP,
} from "@gainsnetwork/sdk/trade/fees/fundingFees";

// Build funding context
const fundingContext = buildFundingContext(
  tradingVariables,
  collateralIndex,
  pairIndex,
  currentTimestamp
);

// Calculate funding fees for a trade
const fundingFees = getTradeFundingFeesCollateral(
  trade,
  currentTimestamp,
  fundingContext
);

// Get current funding rate
const { avgFundingRatePerSecondP, currentFundingRatePerSecondP } =
  getAvgFundingRatePerSecondP(fundingContext, currentTimestamp);
Display helpers:
import {
  convertRatePerSecondToAPR,
  formatHoldingFeeRate,
} from "@gainsnetwork/sdk/markets/holdingFees";
import { fundingRateToAPR } from "@gainsnetwork/sdk/trade/fees/fundingFees/converter";

// Convert to annual percentage rate
const apr = convertRatePerSecondToAPR(ratePerSecond);
const fundingAPR = fundingRateToAPR(fundingRatePerSecond);

// Format for display (e.g., "0.25%")
const formatted = formatHoldingFeeRate(rate);

2. New Borrowing Fees v2

Borrowing fees v2 work alongside funding fees with a simplified rate-based model. Context Builder & Calculation:
import { buildBorrowingV2Context } from "@gainsnetworks/sdk/trade/fees/borrowingV2/builder";
import { getTradeBorrowingFeesCollateral } from "@gainsnetworks/sdk/trade/fees/borrowingV2";

// Build borrowing v2 context
const borrowingV2Context = buildBorrowingV2Context(
  tradingVariables,
  collateralIndex,
  pairIndex,
  currentTimestamp
);

// Calculate borrowing fees for a trade
const borrowingFees = getTradeBorrowingFeesCollateral(
  trade,
  currentTimestamp,
  oraclePrice,
  borrowingV2Context
);
Display helpers:
import { borrowingRateToAPR } from "@gainsnetworks/sdk/trade/fees/borrowingV2/converter";

// Convert borrowing rate to APR for display
const borrowingAPR = borrowingRateToAPR(borrowingRatePerSecond);

3. P&L Withdrawal Feature

Users can withdraw profits without closing their position. This maintains leverage while extracting gains. Contract Interaction:
// Direct contract call (no SDK wrapper currently)
const tx = await gnsMultiCollatDiamond.withdrawPositivePnl(
  tradeIndex,
  amountCollateral // in collateral precision (e.g., 6 decimals for USDC)
);
Important behavior: If amountCollateral exceeds available positive PnL, the contract will automatically withdraw only the maximum available amount (no revert). To withdraw all available PnL:
const MAX_UINT120 = BigNumber.from(2).pow(120).sub(1);
const tx = await gnsMultiCollatDiamond.withdrawPositivePnl(
  tradeIndex,
  MAX_UINT120 // Will be capped to available PnL
);
Integration requirements:
  • Calculate withdrawable P&L: tradeValue - initialCollateral (when positive)
  • Show withdrawable amount in UI when position is in profit
  • Listen for TradePositivePnlWithdrawn event to update UI
  • Update position display after withdrawal:
    • collateralAmount increases
    • positionSizeToken remains unchanged
    • Track pnlWithdrawnCollateral for total withdrawn

4. Counter Trade Type

Counter trades improve market balance and receive fee discounts. Creating a Counter Trade:
// When opening a trade, set the isCounterTrade flag
const tradeStruct = {
  // ... other trade parameters ...
  isCounterTrade: true, // Request counter trade discount
};

// Open trade with counter trade flag
const tx = await gnsMultiCollatDiamond.openTrade(
  tradeStruct,
  slippagePercent,
  referrer
);
Note: The contract will validate if the trade actually qualifies as a counter trade. If not, it will be rejected. If the trade size is larger than the max skew limit, it will be reduced in size but still opened. Pre-validation:
import { validateCounterTrade } from "@gainsnetworks/sdk/trade/counterTrade/validateCounterTrade";

// Check if trade qualifies as counter trade before submitting
const validation = validateCounterTrade(
  isLong,
  positionSizeCollateral,
  leverage,
  pairIndex,
  tradingVariables
);
Detection (for existing trades):
// Check Trade struct field
const isCounterTrade = trade.isCounterTrade; // boolean field in v10 trades

5. Skew Price Impact

Price impact based on market skew (imbalance between long/short OI). NOTE: The SDK offers wrapper utilities for open and close price impact which can be used to calculate all price impact data. More in SDK convenience functions. Context Builder & Calculation:
import { buildSkewPriceImpactContext } from "@gainsnetwork/sdk/trade/priceImpact/skew/builder";
import { getTradeSkewPriceImpact } from "@gainsnetwork/sdk/trade/priceImpact/skew";

// Build context
const skewContext = buildSkewPriceImpactContext(
  tradingVariables,
  collateralIndex,
  pairIndex
);

// Calculate skew price impact
const skewImpact = getTradeSkewPriceImpact(
  isLong,
  oraclePrice,
  positionSizeToken,
  skewContext
);
Helper functions:
import {
  getNetSkewToken,
  getNetSkewCollateral,
} from "@gainsnetwork/sdk/trade/priceImpact/skew";

// Get current market skew
const skewToken = getNetSkewToken(pairOiData);
const skewCollateral = getNetSkewCollateral(pairOiData, oraclePrice);

6. Market Max Skew Limits

Markets have maximum allowed skew to prevent excessive imbalance. Check skew using computeOiValues:
import { computeOiValues } from "@gainsnetworks/sdk/markets/oi/converter";

// Compute current OI values including skew
const { skewToken } = computeOiValues(
  pairOi,
  oraclePrice / collateralPriceUsd // Convert to token price in collateral
);

// Get max skew from trading variables
const maxSkewCollateral =
  tradingVariables.pairs[pairIndex]?.params?.maxSkewCollateral;

// Convert skewToken to collateral for comparison
const skewCollateral = Math.abs(skewToken) * (oraclePrice / collateralPriceUsd);
const skewExceeded = skewCollateral > maxSkewCollateral;
Note: For counter trade validation and position sizing, use validateCounterTrade (see section 5).

7. Effective Leverage in Partial Updates

Partial position updates now validate against effective leverage (accounts for unrealized P&L). Calculation:
import { getEffectiveLeverage } from "@gainsnetworks/sdk/trade/effectiveLeverage";

// Calculate effective leverage
const effectiveLeverage = getEffectiveLeverage(
  trade.leverage,
  trade.collateralAmount,
  pnlCollateral
);
Validation Requirements: For Position Increases (Partial Add):
  • Effective leverage must not exceed pairMaxLeverage
  • Counter trades must not exceed pairCounterTradeMaxLeverage
  • Adjusted initial leverage must be between 0.1x and max uint24 (~16,777x)
  • Pre-v10 trades cannot partial add
For Position Decreases (Partial Close):
  • No effective leverage maximum check
  • Only validates adjusted initial leverage (≥ 0.1x)
For Leverage Increases:
  • Same as position increases - effective leverage validated
For Leverage Decreases (Add Collateral):
  • Same as position decreases - no effective leverage check
// Example validation
const maxLeverage = isCounterTrade
  ? tradingVariables.pairs[pairIndex].maxLeverageCounterTrade
  : tradingVariables.pairs[pairIndex].maxLeverage;

const isValid = effectiveLeverage <= maxLeverage;
const MIN_LEVERAGE = 0.1; // 0.1x minimum

8. Modified Borrowing Fees v1

Borrowing fees v1 now use dynamic OI (position size adjusted by current price vs entry price). Context Builder & Calculation:
import { buildBorrowingV1Context } from "@gainsnetworks/sdk/trade/fees/borrowing/builder";
import { getBorrowingFee } from "@gainsnetworks/sdk/trade/fees/borrowing";

// Build borrowing v1 context
const borrowingV1Context = buildBorrowingV1Context(
  tradingVariables,
  collateralIndex,
  currentBlock
);

// Calculate borrowing fee for a trade
const borrowingFee = getBorrowingFee(
  positionSizeCollateral,
  pairIndex,
  isLong,
  initialAccFees,
  currentPairPrice,
  borrowingV1Context
);
Utility functions:
import { borrowingFeeUtils } from "@gainsnetworks/sdk/trade/fees/borrowing";

// Get pending accumulated fees for a pair
const pendingFees = borrowingFeeUtils.getPairPendingAccFees(
  pairs,
  pairGroups,
  groups,
  initialAccFees,
  pairIndex,
  currentBlock,
  feePerBlockCaps
);

// Check if within max group OI
const withinLimit = borrowingFeeUtils.withinMaxGroupOi(
  pairs,
  pairGroups,
  groups,
  positionSizeCollateral,
  pairIndex,
  isLong
);

9. Modified Liquidation Calculations

Liquidation now accounts for pending fees and realized P&L. Context Builder & Calculation:
import { buildLiquidationPriceContext } from "@gainsnetwork/sdk/trade/liquidation/builder";
import { getLiquidationPrice } from "@gainsnetwork/sdk/trade/liquidation";

// Build comprehensive context
const liquidationContext = buildLiquidationPriceContext(
  tradingVariables,
  tradeContainer,
  {
    currentBlock,
    currentTimestamp,
    currentPairPrice,
    spreadP,
    traderFeeMultiplier,
    userPriceImpact,
  }
);

// Calculate liquidation price
const liqPrice = getLiquidationPrice(trade, liquidationContext);
Additional functions:
import { getLiquidationPriceAfterPositionUpdate } from "@gainsnetwork/sdk/trade/liquidation";

// Calculate after position update
const newLiqPrice = getLiquidationPriceAfterPositionUpdate(
  existingTrade,
  existingLiquidationContext,
  newCollateralAmount,
  newLeverage
);

10. Modified PnL Calculations

Comprehensive PnL includes all v10 components: funding fees, borrowing fees, and realized P&L. Context Builder & Calculation:
import { buildComprehensivePnlContext } from "@gainsnetwork/sdk/trade/pnl/builder";
import { getComprehensivePnl } from "@gainsnetwork/sdk/trade/pnl";

// Build context
const pnlContext = buildComprehensivePnlContext(
  tradingVariables,
  tradeContainer,
  {
    currentBlock,
    currentTimestamp,
    traderFeeMultiplier,
  }
);

// Calculate comprehensive PnL
const pnl = getComprehensivePnl(
  trade,
  marketPrice,
  executionPrice, // price after spreads/impacts
  tradeInfo,
  pnlContext
);
Helper functions:
import { getPnlPercent, getTradeValue } from "@gainsnetwork/sdk/trade/pnl";

// Calculate PnL percentage
const pnlPercent = getPnlPercent(openPrice, currentPrice, isLong, leverage);

// Get trade value (collateral + PnL)
const tradeValue = getTradeValue(collateralAmount, pnlCollateral, 0); // pass 0 for raw trade value calculation

11. New Trade Fields

v10 trades have additional fields that must be parsed and stored. New fields in Trade struct:
interface Trade {
  // ... existing fields ...
  positionSizeToken: bigint; // Position size in token units (1e18 precision)
  isCounterTrade: boolean; // Whether trade qualified for counter trade discount
}

12. V10 OI Tracking

OI is tracked separately for pre-v10 and post-v10 trades. OI Functions:
import {
  getPairTotalOisCollateral,
  getPairTotalOisDynamicCollateral,
  getPairV10OiTokenSkewCollateral,
  getPairV10OiDynamicSkewCollateral,
} from "@gainsnetworks/sdk/markets/oi";

// Get total OI (pre-v10 only)
const staticOI = getPairTotalOisCollateral(pairOi);

// Get dynamic OI (pre-v10 + v10 adjusted by price)
const dynamicOI = getPairTotalOisDynamicCollateral(pairOi, oraclePrice);

// Get v10 skew in collateral
const skewCollateral = getPairV10OiTokenSkewCollateral(pairOi, oraclePrice);

// Get v10 dynamic skew
const dynamicSkew = getPairV10OiDynamicSkewCollateral(pairOi, oraclePrice);
Comprehensive OI Values:
import { computeOiValues } from "@gainsnetwork/sdk/markets/oi/converter";

// Get all computed OI values at once
const oiValues = computeOiValues(
  pairOi,
  oraclePrice / collateralPriceUsd // Convert to token price in collateral
);
Important notes:
  • Funding fees only apply to v10 OI
  • Skew calculations use v10 OI only
  • Max OI checks use combined OI (pre-v10 + v10)
  • Counter trade validation uses v10 skew

Market Price Concept

Market price is a v10 feature that applies to markets with funding fees and skew price impact. It represents the oracle price adjusted for current market skew. Calculate Market Price:
import { getCurrentMarketPrice } from "@gainsnetworks/sdk/markets/price/marketPrice";
import { buildMarketPriceContext } from "@gainsnetworks/sdk/markets/price/builder";

// Build context for market price calculation
const marketPriceContext = buildMarketPriceContext(tradingVariables, pairIndex);

// Calculate market price from oracle price
const { marketPrice, skewImpactP } = getCurrentMarketPrice(
  pairIndex,
  oraclePrice,
  marketPriceContext
);

SDK Wrapper Functions

The SDK provides high-level wrapper functions that combine multiple calculations for common operations.

Price Impact

Opening a Trade:
import { getTradeOpeningPriceImpact } from "@gainsnetwork/sdk/trade/priceImpact/open";
import { buildTradeOpeningPriceImpactContext } from "@gainsnetwork/sdk/trade/priceImpact/open/builder";

// Build context with all required data
const openContext = buildTradeOpeningPriceImpactContext(
  tradingVariables,
  collateralIndex,
  pairIndex,
  currentBlock
);

// Calculate total price impact and execution price
const openImpact = getTradeOpeningPriceImpact(
  oraclePrice, // Always pass oracle price
  isLong,
  positionSizeCollateral,
  leverage,
  openContext
);
Understanding Price Impact Results:
// The function returns multiple price impact values:
const {
  priceAfterImpact, // Final execution price
  totalPriceImpactP, // Total impact from oracle price
  totalPriceImpactPFromMarketPrice, // Total impact from market price
  baseSkewPriceImpactP, // Market skew before trade
  tradeSkewPriceImpactP, // Additional skew from this trade
  totalSkewPriceImpactP, // Total skew impact (base + trade)
} = openImpact;

// For UI display:
// If showing market price: use totalPriceImpactPFromMarketPrice
// If showing oracle price: use totalPriceImpactP
Closing a Trade:
import { getTradeClosingPriceImpact } from "@gainsnetwork/sdk/trade/priceImpact/close";
import { buildTradeClosingPriceImpactContext } from "@gainsnetwork/sdk/trade/priceImpact/close/builder";

// Build context
const closeContext = buildTradeClosingPriceImpactContext(
  tradingVariables,
  tradeContainer,
  currentBlock
);

// Calculate price impact for closing
const closeImpact = getTradeClosingPriceImpact(
  trade,
  oraclePrice, // Always pass oracle price
  closeContext
);

// Similar to opening, returns multiple impact values
const {
  priceAfterImpact,
  tradeValueCollateral,
  totalPriceImpactP, // From oracle price
  totalPriceImpactPFromMarketPrice, // From market price
  // ... other impact components
} = closeImpact;

Action Fees (Trading Fees)

Calculate Total Trading Fees:
import { getTotalTradeFeesCollateral } from "@gainsnetwork/sdk/trade/fees/trading";
import { buildTradingFeesContext } from "@gainsnetwork/sdk/trade/fees/trading/builder";

// Build context
const feesContext = buildTradingFeesContext(
  tradingVariables,
  collateralIndex,
  pairIndex
);

// Calculate total fees
const totalFees = getTotalTradeFeesCollateral(
  positionSizeCollateral,
  isCounterTrade,
  tradeTier,
  feesContext
);
Get Detailed Fee Breakdown:
import { getTradeFeesCollateral } from "@gainsnetwork/sdk/trade/fees/trading";

// Get breakdown of all fee components
const feeBreakdown = getTradeFeesCollateral(
  positionSizeCollateral,
  pairOpenFeeP,
  tradeTierMultiplier,
  referralFeeP,
  pairTriggerOrderFeeP,
  pairOtcFeeP,
  collateralPrecision
);
// Returns: referralFees, govFees, triggerFees, gnsOtcFees, gTokenFees
Calculate Pending Holding Fees:
import { getTradePendingHoldingFeesCollateral } from "@gainsnetwork/sdk/trade/fees/trading";

// Calculate all accumulated holding fees
const holdingFees = getTradePendingHoldingFeesCollateral(
  trade,
  currentBlock,
  currentTimestamp,
  oraclePrice,
  collateralPrecision,
  holdingFeesContext // combines funding + borrowing contexts
);

Summary

The SDK provides all necessary functions to integrate v10 features. Key patterns:
  1. Use Context Builders: Most complex calculations require a context object built from trading variables
  2. Transform Backend Data: Use transformGlobalTradingVariables and transformGlobalTrades before passing to SDK functions
  3. Handle Pre-v10 Trades: Check trade.contractsVersion to determine if a trade uses v10 features
  4. Display Market Rates: Use functions in “Current Market Rates” section for market-wide statistics