@gainsnetwork/sdk 1.0.5-rc1 → 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.
- package/lib/constants.js +1 -1
- package/lib/markets/price/signedPrices.d.ts +15 -0
- package/lib/markets/price/signedPrices.js +82 -0
- package/lib/trade/fees/borrowingV2/fetcher.d.ts +1 -0
- package/package.json +1 -1
- package/lib/trade/liquidation.d.ts +0 -12
- package/lib/trade/liquidation.js +0 -55
- package/lib/trade/pnl.d.ts +0 -10
- package/lib/trade/pnl.js +0 -33
package/lib/constants.js
CHANGED
|
@@ -473,7 +473,7 @@ exports.delistedPairIxs = new Set([
|
|
|
473
473
|
99, 101, 106, 111, 113, 114, 116, 118, 120, 122, 123, 125, 127, 130, 147, 152,
|
|
474
474
|
160, 163, 170, 179, 182, 183, 188, 189, 190, 208, 209, 225, 229, 230, 231,
|
|
475
475
|
238, 239, 241, 250, 253, 254, 258, 270, 275, 276, 278, 279, 282, 285, 290,
|
|
476
|
-
294, 296, 305, 311, 330, 349, 352, 353, 354, 355, 357, 365, 366, 395, 396,
|
|
476
|
+
294, 296, 305, 311, 330, 349, 352, 353, 354, 355, 357, 365, 366, 395, 396,
|
|
477
477
|
]);
|
|
478
478
|
exports.delistedGroupsIxs = new Set([]);
|
|
479
479
|
exports.DEFAULT_PROTECTION_CLOSE_FACTOR = 1;
|
|
@@ -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;
|
package/package.json
CHANGED
|
@@ -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;
|
package/lib/trade/liquidation.js
DELETED
|
@@ -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;
|
package/lib/trade/pnl.d.ts
DELETED
|
@@ -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;
|