diff --git a/package-lock.json b/package-lock.json index d24870b..9ad0fd0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@parifi/sdk", - "version": "1.0.5-prod", + "version": "1.0.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@parifi/sdk", - "version": "1.0.5-prod", + "version": "1.0.6", "license": "ISC", "dependencies": { "@gelatonetwork/relay-sdk": "^5.5.5", diff --git a/package.json b/package.json index 7db5dab..cbbd65c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@parifi/sdk", - "version": "1.0.5-prod", + "version": "1.0.6", "description": "Parifi SDK with common utility functions", "files": [ "dist", diff --git a/src/core/data-fabric/index.ts b/src/core/data-fabric/index.ts index e24f416..f885529 100644 --- a/src/core/data-fabric/index.ts +++ b/src/core/data-fabric/index.ts @@ -128,4 +128,4 @@ export const getAccruedBorrowFeesInMarket = (position: Position, market: Market) .times(accruedFeesCumulative) .div(new Decimal(100).times(new Decimal(10).pow(18))) .ceil(); -}; +}; \ No newline at end of file diff --git a/src/core/index.ts b/src/core/index.ts index 190a859..a4e8d4c 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -11,7 +11,9 @@ import { } from './data-fabric'; import { Contract, Signer } from 'ethers'; import { + calculateCollateralFromSize, calculatePositionLeverage, + calculateSizeFromCollateral, canBeSettled, canBeSettledPriceId, checkIfOrderCanBeSettledId, @@ -55,6 +57,7 @@ export class Core { //////////////////////////////////////////////////////////////// ////////////////////// DATA FABRIC /////////////////////// //////////////////////////////////////////////////////////////// + getMarketUtilization = (market: Market, isLong: boolean): Decimal => { return getMarketUtilization(market, isLong); }; @@ -85,6 +88,32 @@ export class Core { ////////////////////// ORDER MANAGER ///////////////////// //////////////////////////////////////////////////////////////// + calculateSizeFromCollateral( + amount: Decimal, + leverage: Decimal, + executionFeeInCollateral: Decimal, + openingFee: Decimal, + normalizedMarketPrice: Decimal, + normalizedCollateralPrice: Decimal, + ) { + return calculateSizeFromCollateral( + amount, + leverage, + executionFeeInCollateral, + openingFee, + normalizedMarketPrice, + normalizedCollateralPrice, + ); + } + calculateCollateralFromSize( + collateralSize: Decimal, + leverage: Decimal, + normalizedMarketPrice: Decimal, + normalizedCollateralPrice: Decimal, + ): Decimal { + return calculateCollateralFromSize(collateralSize, leverage, normalizedMarketPrice, normalizedCollateralPrice); + } + getOrderManagerInstance = (): Contract => { return getOrderManagerInstance(this.rpcConfig.chainId); }; diff --git a/src/core/order-manager/index.ts b/src/core/order-manager/index.ts index d6c2e67..eef53db 100644 --- a/src/core/order-manager/index.ts +++ b/src/core/order-manager/index.ts @@ -522,3 +522,50 @@ export const getLiquidationPrice = ( return new Decimal(position.avgPrice ?? 0).add(lossPerToken); } }; + +/** + * @name calculateCollateralFromSize + * @description This function calculates the collateral required based on the given size, leverage and normalized market price and collateral price. + * @param {number} collateralSize - The size of the collateral in eth unit. + * @param {number} leverage - The degree of financial leverage being used. + * @param {Decimal} normalizedMarketPrice - The normalized market price of the underlying asset. + * @param {Decimal} normalizedCollateralPrice - The normalized price of the collateral. + * @returns {Decimal} - The calculated collateral required to maintain the position. + */ + +export const calculateCollateralFromSize = ( + collateralSize: Decimal, + leverage: Decimal, + normalizedMarketPrice: Decimal, + normalizedCollateralPrice: Decimal, +) => { + return normalizedMarketPrice.mul(collateralSize).div(normalizedCollateralPrice).div(leverage); +}; + +/** + * @name calculateSizeFromCollateral + * @description Calculates the position size in the base asset given the collateral amount, leverage, execution fee in collateral, opening fee, and normalised market price and collateral price. + * @param {Decimal} amount - The collateral amount in eth units. + * @param {Decimal} leverage - The total leverage used for this position. + * @param {Decimal} executionFeeInCollateral - The execution fee on collateral units. + * @param {Decimal} openingFee - The opening fee for the trade. + * @param {Decimal} normalizedMarketPrice - The normalised price of the base asset in terms of the quote asset. + * @param {Decimal} normalizedCollateralPrice - The normalised price of the collateral asset in terms of the quote asset. + * @returns {Decimal} - The calculated position size in the base asset. + */ + +export const calculateSizeFromCollateral = ( + amount: Decimal, + leverage: Decimal, + executionFeeInCollateral: Decimal, + openingFee: Decimal, + normalizedMarketPrice: Decimal, + normalizedCollateralPrice: Decimal, +) => { + const collateralInUsd = amount.mul(normalizedCollateralPrice); + const executionFeeInUsd = executionFeeInCollateral.mul(normalizedCollateralPrice); + + const sizeInUsd = collateralInUsd.sub(executionFeeInUsd).div(openingFee.add(1).div(leverage)); + + return sizeInUsd.div(normalizedMarketPrice); +}; diff --git a/src/subgraph/index.ts b/src/subgraph/index.ts index e9f9775..f035622 100644 --- a/src/subgraph/index.ts +++ b/src/subgraph/index.ts @@ -43,6 +43,7 @@ import { getTopAccountsByReferralRewards, } from './accounts'; import { LeaderboardUserData, ReferralRewardsInUsd, UserPortfolioData } from '../interfaces/sdkTypes'; +import { getExecutionFee } from './protocol'; export * from './common'; export * from './markets'; @@ -168,7 +169,7 @@ export class Subgraph { } // @todo Add function to get multiple positions in a single call - + public async getPositionById(positionId: string): Promise { const subgraphEndpoint = this.getSubgraphEndpoint(this.rpcConfig.chainId); return getPositionById(subgraphEndpoint, positionId); @@ -288,4 +289,12 @@ export class Subgraph { const subgraphEndpoint = this.getSubgraphEndpoint(this.rpcConfig.chainId); return await getPoolVolume24h(subgraphEndpoint); } + + //////////////////////////////////////////////////////////////// + ///////////////////// PROTOCOL /////////////////////////// + //////////////////////////////////////////////////////////////// + public async getExecutionFee(): Promise<{ executionFeeEth: Decimal; executionFeeUsdc: Decimal }> { + const subgraphEndpoint = this.getSubgraphEndpoint(this.rpcConfig.chainId); + return getExecutionFee(subgraphEndpoint); + } } diff --git a/src/subgraph/protocol/index.ts b/src/subgraph/protocol/index.ts new file mode 100644 index 0000000..0096ab6 --- /dev/null +++ b/src/subgraph/protocol/index.ts @@ -0,0 +1,28 @@ +import request from 'graphql-request'; +import { fetchExecutionFee } from './subgraphQueries'; +import Decimal from 'decimal.js'; +import { DECIMAL_ZERO } from '../../common'; + +export const getExecutionFee = async ( + subgraphEndpoint: string, +): Promise<{ executionFeeEth: Decimal; executionFeeUsdc: Decimal }> => { + interface SubgraphResponseInterface { + protocolData: { + executionFeeEth: string; + executionFeeUsdc: string; + }; + } + + try { + let subgraphResponse: SubgraphResponseInterface = await request(subgraphEndpoint, fetchExecutionFee()); + + const executionFeeEth = new Decimal(subgraphResponse.protocolData.executionFeeEth); + const executionFeeUsdc = new Decimal(subgraphResponse.protocolData.executionFeeUsdc); + + return { executionFeeEth, executionFeeUsdc }; + } catch (error) { + // Return execution fee as zero in case of an error + console.log(error); + return { executionFeeEth: DECIMAL_ZERO, executionFeeUsdc: DECIMAL_ZERO }; + } +}; diff --git a/src/subgraph/protocol/subgraphQueries.ts b/src/subgraph/protocol/subgraphQueries.ts new file mode 100644 index 0000000..6d88f67 --- /dev/null +++ b/src/subgraph/protocol/subgraphQueries.ts @@ -0,0 +1,11 @@ +import { gql } from 'graphql-request'; + +// Fetch execution fee for protocol from subgraph +export const fetchExecutionFee = () => gql` + { + protocolData(id: "1") { + executionFeeEth + executionFeeUsdc + } + } +`; diff --git a/test/subgraph-tests/protocol.test.ts b/test/subgraph-tests/protocol.test.ts new file mode 100644 index 0000000..d3eee37 --- /dev/null +++ b/test/subgraph-tests/protocol.test.ts @@ -0,0 +1,11 @@ +import { getParifiSdkInstanceForTesting } from '..'; +import { TEST_MARKET_ID1 } from '../common/constants'; + +describe('Protocol data', () => { + it('should return correct execution fee', async () => { + const parifiSdk = await getParifiSdkInstanceForTesting(); + + const res = await parifiSdk.subgraph.getExecutionFee(); + console.log(res); + }); +});