@gainsnetwork/sdk 1.0.5-rc2 → 1.0.5-rc3

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,15 @@
1
+ import { SignedPricesResponse } from "./types";
2
+ export interface FetchSingedPricesInput {
3
+ oracles: string[];
4
+ pairs: number[];
5
+ chainId: number;
6
+ authKey?: string;
7
+ minAnswer?: number;
8
+ timeoutMs?: number;
9
+ }
10
+ export declare const fetchSignedPrices: (input: FetchSingedPricesInput) => Promise<SignedPricesResponse[] | null>;
11
+ export declare const isValidSignedPricesChain: (chainId: number) => boolean;
12
+ export declare const validateSignedPricesPairs: (pairs: number[]) => {
13
+ valid: boolean;
14
+ pairs: number[];
15
+ };
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateSignedPricesPairs = exports.isValidSignedPricesChain = exports.fetchSignedPrices = void 0;
4
+ const types_1 = require("../../contracts/types");
5
+ const fetchSignedPrices = async (input) => {
6
+ const { minAnswers, timeoutMs, oracles, pairs, chainId, authKey } = {
7
+ minAnswers: input.chainId === types_1.ChainId.ARBITRUM_SEPOLIA ? 2 : 3,
8
+ timeoutMs: 1000,
9
+ ...input,
10
+ };
11
+ if (!(0, exports.isValidSignedPricesChain)(chainId))
12
+ throw new Error(`Invalid chainId ${chainId}`);
13
+ const { valid, pairs: validPairs } = (0, exports.validateSignedPricesPairs)(pairs);
14
+ if (!valid)
15
+ throw new Error(`Invalid pairs array`);
16
+ try {
17
+ // Fetch signed prices from all oracles in parallel
18
+ const signedPrices = await Promise.allSettled(oracles.map(signerUrl => _getSignedPricesFromSigner(signerUrl, validPairs, chainId, authKey, timeoutMs)));
19
+ // Filter out failed requests and null responses, then sort by signerId
20
+ const successfulResponses = signedPrices.filter(res => res.status === "fulfilled" && res.value !== null // Filter out failed or null responses
21
+ )
22
+ // Extract `value`
23
+ .map((res) => res.value)
24
+ // Sort by signerId, contracts expect signerId ascending
25
+ .sort((a, b) => a.signedData.signerId - b.signedData.signerId);
26
+ // Ensure we have at least `minAnswers` valid responses
27
+ if (successfulResponses.length < minAnswers) {
28
+ throw new Error(`Not enough valid signed prices. Wanted ${minAnswers} but got ${successfulResponses.length}`);
29
+ }
30
+ return successfulResponses;
31
+ }
32
+ catch (e) {
33
+ console.error("Error processing signed prices", e);
34
+ throw e;
35
+ }
36
+ };
37
+ exports.fetchSignedPrices = fetchSignedPrices;
38
+ const _getSignedPricesFromSigner = async (signerUrl, pairIndices, chainId, authKey, timeoutMs) => {
39
+ try {
40
+ const controller = new AbortController();
41
+ const timeout = setTimeout(() => {
42
+ controller.abort();
43
+ }, timeoutMs || 1000);
44
+ // @todo add retries
45
+ const response = await fetch(`${signerUrl}/signPrices`, {
46
+ method: "POST",
47
+ headers: {
48
+ "Content-Type": "application/json",
49
+ "x-api-key": authKey || "",
50
+ },
51
+ body: JSON.stringify({ pairs: pairIndices, chain: chainId }),
52
+ signal: controller.signal,
53
+ });
54
+ clearTimeout(timeout);
55
+ if (!response.ok) {
56
+ throw new Error(`Failed to fetch signed prices from ${signerUrl}: ${response.statusText}`);
57
+ }
58
+ return (await response.json());
59
+ }
60
+ catch (error) {
61
+ console.error(`Error fetching signed prices from ${signerUrl}`, error);
62
+ return null;
63
+ }
64
+ };
65
+ const isValidSignedPricesChain = (chainId) => {
66
+ return (!isNaN(chainId) &&
67
+ [
68
+ types_1.ChainId.POLYGON,
69
+ types_1.ChainId.BASE,
70
+ types_1.ChainId.ARBITRUM,
71
+ types_1.ChainId.ARBITRUM_SEPOLIA,
72
+ types_1.ChainId.APECHAIN,
73
+ ].includes(chainId));
74
+ };
75
+ exports.isValidSignedPricesChain = isValidSignedPricesChain;
76
+ const validateSignedPricesPairs = (pairs) => {
77
+ if (!Array.isArray(pairs) || pairs?.length === 0 || pairs.some(p => isNaN(p)))
78
+ return { valid: false, pairs: [] };
79
+ // Pairs must always be in ascending order
80
+ return { valid: true, pairs: [...new Set(pairs)].sort((a, b) => a - b) };
81
+ };
82
+ exports.validateSignedPricesPairs = validateSignedPricesPairs;
@@ -1,3 +1,4 @@
1
+ /// <reference types="mocha" />
1
2
  import type { GNSMultiCollatDiamond } from "../../../contracts/types/generated";
2
3
  import { BorrowingFeeV2 } from ".";
3
4
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gainsnetwork/sdk",
3
- "version": "1.0.5-rc2",
3
+ "version": "1.0.5-rc3",
4
4
  "description": "Gains Network SDK",
5
5
  "main": "./lib/index.js",
6
6
  "files": [
@@ -1,12 +0,0 @@
1
- import { GetBorrowingFeeContext, BorrowingFee } from "./fees";
2
- import { Fee, LiquidationParams, Trade, UserPriceImpact } from "./types";
3
- import { ContractsVersion } from "../contracts/types";
4
- export type GetLiquidationPriceContext = GetBorrowingFeeContext & {
5
- liquidationParams: LiquidationParams | undefined;
6
- pairSpreadP: number | undefined;
7
- collateralPriceUsd: number | undefined;
8
- contractsVersion: ContractsVersion | undefined;
9
- userPriceImpact?: UserPriceImpact | undefined;
10
- };
11
- export declare const getLiquidationPrice: (trade: Trade, fee: Fee, initialAccFees: BorrowingFee.InitialAccFees, context: GetLiquidationPriceContext) => number;
12
- export declare const getLiqPnlThresholdP: (liquidationParams: LiquidationParams | undefined, leverage: number | undefined) => number;
@@ -1,55 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getLiqPnlThresholdP = exports.getLiquidationPrice = void 0;
4
- const fees_1 = require("./fees");
5
- const spread_1 = require("./spread");
6
- const types_1 = require("../contracts/types");
7
- const getLiquidationPrice = (trade, fee, initialAccFees, context) => {
8
- var _a, _b;
9
- const closingFee = (0, fees_1.getClosingFee)(trade.collateralAmount, trade.leverage, trade.pairIndex, fee, context.collateralPriceUsd);
10
- const borrowingFee = (0, fees_1.getBorrowingFee)(trade.collateralAmount * trade.leverage, trade.pairIndex, trade.long, initialAccFees, context);
11
- const liqThresholdP = (0, exports.getLiqPnlThresholdP)(context.liquidationParams, trade.leverage);
12
- let liqPriceDistance = (trade.openPrice *
13
- (trade.collateralAmount * liqThresholdP - (borrowingFee + closingFee))) /
14
- trade.collateralAmount /
15
- trade.leverage;
16
- if ((context === null || context === void 0 ? void 0 : context.contractsVersion) !== undefined &&
17
- context.contractsVersion >= types_1.ContractsVersion.V9_2 &&
18
- ((((_a = context === null || context === void 0 ? void 0 : context.liquidationParams) === null || _a === void 0 ? void 0 : _a.maxLiqSpreadP) !== undefined &&
19
- context.liquidationParams.maxLiqSpreadP > 0) ||
20
- (((_b = context === null || context === void 0 ? void 0 : context.userPriceImpact) === null || _b === void 0 ? void 0 : _b.fixedSpreadP) !== undefined &&
21
- context.userPriceImpact.fixedSpreadP > 0))) {
22
- const closingSpreadP = (0, spread_1.getSpreadP)(context.pairSpreadP, true, context.liquidationParams, context.userPriceImpact);
23
- liqPriceDistance -= trade.openPrice * closingSpreadP;
24
- }
25
- return trade.long
26
- ? Math.max(trade.openPrice - liqPriceDistance, 0)
27
- : Math.max(trade.openPrice + liqPriceDistance, 0);
28
- };
29
- exports.getLiquidationPrice = getLiquidationPrice;
30
- const getLiqPnlThresholdP = (liquidationParams, leverage) => {
31
- if (liquidationParams === undefined ||
32
- leverage === undefined ||
33
- liquidationParams.maxLiqSpreadP === 0 ||
34
- liquidationParams.startLiqThresholdP === 0 ||
35
- liquidationParams.endLiqThresholdP === 0 ||
36
- liquidationParams.startLeverage === 0 ||
37
- liquidationParams.endLeverage === 0) {
38
- return 0.9;
39
- }
40
- if (leverage < liquidationParams.startLeverage) {
41
- return liquidationParams.startLiqThresholdP;
42
- }
43
- if (leverage > liquidationParams.endLeverage) {
44
- return liquidationParams.endLiqThresholdP;
45
- }
46
- if (liquidationParams.startLiqThresholdP === liquidationParams.endLiqThresholdP) {
47
- return liquidationParams.endLiqThresholdP;
48
- }
49
- return (liquidationParams.startLiqThresholdP -
50
- ((leverage - liquidationParams.startLeverage) *
51
- (liquidationParams.startLiqThresholdP -
52
- liquidationParams.endLiqThresholdP)) /
53
- (liquidationParams.endLeverage - liquidationParams.startLeverage));
54
- };
55
- exports.getLiqPnlThresholdP = getLiqPnlThresholdP;
@@ -1,10 +0,0 @@
1
- import { GetBorrowingFeeContext } from "./fees";
2
- import { Fee, LiquidationParams, Trade, TradeInfo, TradeInitialAccFees } from "./types";
3
- import { ContractsVersion } from "../contracts/types";
4
- export type GetPnlContext = GetBorrowingFeeContext & {
5
- fee: Fee | undefined;
6
- collateralPriceUsd: number | undefined;
7
- contractsVersion: ContractsVersion | undefined;
8
- feeMultiplier: number | undefined;
9
- };
10
- export declare const getPnl: (price: number | undefined, trade: Trade, tradeInfo: TradeInfo, initialAccFees: TradeInitialAccFees, liquidationParams: LiquidationParams, useFees: boolean, context: GetPnlContext) => number[] | undefined;
package/lib/trade/pnl.js DELETED
@@ -1,33 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getPnl = void 0;
4
- const fees_1 = require("./fees");
5
- const liquidation_1 = require("./liquidation");
6
- const getPnl = (price, trade, tradeInfo, initialAccFees, liquidationParams, useFees, context) => {
7
- if (!price) {
8
- return;
9
- }
10
- const posCollat = trade.collateralAmount;
11
- const { openPrice, leverage } = trade;
12
- const { fee } = context;
13
- let pnlCollat = trade.long
14
- ? ((price - openPrice) / openPrice) * leverage * posCollat
15
- : ((openPrice - price) / openPrice) * leverage * posCollat;
16
- if (useFees) {
17
- pnlCollat -= (0, fees_1.getBorrowingFee)(posCollat * trade.leverage, trade.pairIndex, trade.long, initialAccFees, context);
18
- }
19
- let pnlPercentage = (pnlCollat / posCollat) * 100;
20
- // Can be liquidated
21
- if (pnlPercentage <=
22
- (0, liquidation_1.getLiqPnlThresholdP)(liquidationParams, leverage) * -100) {
23
- pnlPercentage = -100;
24
- }
25
- else {
26
- pnlCollat -= (0, fees_1.getClosingFee)(posCollat, trade.leverage, trade.pairIndex, fee, context.collateralPriceUsd, context.feeMultiplier);
27
- pnlPercentage = (pnlCollat / posCollat) * 100;
28
- }
29
- pnlPercentage = pnlPercentage < -100 ? -100 : pnlPercentage;
30
- pnlCollat = (posCollat * pnlPercentage) / 100;
31
- return [pnlCollat, pnlPercentage];
32
- };
33
- exports.getPnl = getPnl;