@d8x/perpetuals-sdk 0.1.12 → 0.2.0
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/dist/cjs/abi/testnet/IPerpetualManager.json +5215 -0
- package/dist/cjs/abi/testnet/LimitOrderBook.json +1075 -0
- package/dist/cjs/abi/zkevmTestnet/IPerpetualManager.json +5215 -0
- package/dist/cjs/abi/zkevmTestnet/LimitOrderBook.json +1075 -0
- package/dist/cjs/abi/zkevmTestnet/LimitOrderBookFactory.json +135 -0
- package/dist/cjs/accountTrade.js +441 -0
- package/dist/cjs/accountTrade.js.map +1 -0
- package/dist/{src → cjs}/brokerTool.js +31 -84
- package/dist/cjs/brokerTool.js.map +1 -0
- package/dist/cjs/config/defaultConfig.json +47 -0
- package/dist/cjs/config/mockSwap.json +4 -0
- package/dist/cjs/config/priceFeedConfig.json +104 -0
- package/dist/cjs/config/symbolList.json +13 -0
- package/dist/cjs/d8XMath.js.map +1 -0
- package/dist/cjs/index.js +29 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/liquidatorTool.js +287 -0
- package/dist/cjs/liquidatorTool.js.map +1 -0
- package/dist/{src → cjs}/liquidityProviderTool.js +12 -65
- package/dist/cjs/liquidityProviderTool.js.map +1 -0
- package/dist/{src → cjs}/marketData.js +52 -134
- package/dist/cjs/marketData.js.map +1 -0
- package/dist/{src → cjs}/nodeSDKTypes.d.ts +5 -5
- package/dist/cjs/nodeSDKTypes.js +64 -0
- package/dist/cjs/nodeSDKTypes.js.map +1 -0
- package/dist/{src → cjs}/orderReferrerTool.d.ts +12 -5
- package/dist/{src → cjs}/orderReferrerTool.js +114 -112
- package/dist/cjs/orderReferrerTool.js.map +1 -0
- package/dist/{src → cjs}/perpetualDataHandler.d.ts +1 -1
- package/dist/{src → cjs}/perpetualDataHandler.js +47 -109
- package/dist/cjs/perpetualDataHandler.js.map +1 -0
- package/dist/{src → cjs}/perpetualEventHandler.d.ts +3 -3
- package/dist/{src → cjs}/perpetualEventHandler.js +12 -74
- package/dist/cjs/perpetualEventHandler.js.map +1 -0
- package/dist/cjs/priceFeeds.js +466 -0
- package/dist/cjs/priceFeeds.js.map +1 -0
- package/dist/{src → cjs}/traderDigests.js +7 -43
- package/dist/cjs/traderDigests.js.map +1 -0
- package/dist/{src → cjs}/traderInterface.js +13 -66
- package/dist/cjs/traderInterface.js.map +1 -0
- package/dist/{src → cjs}/triangulator.js +2 -17
- package/dist/cjs/triangulator.js.map +1 -0
- package/dist/{src → cjs}/utils.js +3 -29
- package/dist/cjs/utils.js.map +1 -0
- package/dist/cjs/version.d.ts +1 -0
- package/dist/{src → cjs}/version.js +1 -1
- package/dist/cjs/version.js.map +1 -0
- package/dist/{src → cjs}/writeAccessHandler.js +12 -65
- package/dist/cjs/writeAccessHandler.js.map +1 -0
- package/dist/esm/abi/ERC20.json +288 -0
- package/dist/esm/abi/MockTokenSwap.json +186 -0
- package/dist/{abi/testnet → esm/abi/central-park}/IPerpetualManager.json +404 -214
- package/dist/{abi/testnet → esm/abi/central-park}/LimitOrderBook.json +197 -15
- package/dist/esm/abi/central-park/LimitOrderBookFactory.json +135 -0
- package/dist/esm/abi/testnet/IPerpetualManager.json +5215 -0
- package/dist/esm/abi/testnet/LimitOrderBook.json +1075 -0
- package/dist/esm/abi/testnet/LimitOrderBookFactory.json +135 -0
- package/dist/esm/abi/zkevmTestnet/IPerpetualManager.json +5215 -0
- package/dist/esm/abi/zkevmTestnet/LimitOrderBook.json +1075 -0
- package/dist/esm/abi/zkevmTestnet/LimitOrderBookFactory.json +135 -0
- package/dist/esm/accountTrade.d.ts +221 -0
- package/dist/{src → esm}/accountTrade.js +22 -93
- package/dist/esm/accountTrade.js.map +1 -0
- package/dist/esm/brokerTool.d.ts +318 -0
- package/dist/esm/brokerTool.js +572 -0
- package/dist/esm/brokerTool.js.map +1 -0
- package/dist/esm/config/defaultConfig.json +47 -0
- package/dist/esm/config/mockSwap.json +4 -0
- package/dist/esm/config/priceFeedConfig.json +104 -0
- package/dist/esm/config/symbolList.json +13 -0
- package/dist/esm/d8XMath.d.ts +122 -0
- package/dist/esm/d8XMath.js +247 -0
- package/dist/esm/d8XMath.js.map +1 -0
- package/{src/index.ts → dist/esm/index.d.ts} +1 -15
- package/dist/esm/index.js +16 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/liquidatorTool.d.ts +158 -0
- package/dist/{src → esm}/liquidatorTool.js +10 -65
- package/dist/esm/liquidatorTool.js.map +1 -0
- package/dist/esm/liquidityProviderTool.d.ts +126 -0
- package/dist/esm/liquidityProviderTool.js +218 -0
- package/dist/esm/liquidityProviderTool.js.map +1 -0
- package/dist/esm/marketData.d.ts +309 -0
- package/dist/esm/marketData.js +1007 -0
- package/dist/esm/marketData.js.map +1 -0
- package/dist/esm/nodeSDKTypes.d.ts +266 -0
- package/dist/esm/nodeSDKTypes.js +60 -0
- package/dist/esm/nodeSDKTypes.js.map +1 -0
- package/dist/esm/orderReferrerTool.d.ts +196 -0
- package/dist/esm/orderReferrerTool.js +491 -0
- package/dist/esm/orderReferrerTool.js.map +1 -0
- package/dist/esm/perpetualDataHandler.d.ts +220 -0
- package/dist/esm/perpetualDataHandler.js +1060 -0
- package/dist/esm/perpetualDataHandler.js.map +1 -0
- package/dist/esm/perpetualEventHandler.d.ts +179 -0
- package/dist/esm/perpetualEventHandler.js +435 -0
- package/dist/esm/perpetualEventHandler.js.map +1 -0
- package/dist/esm/priceFeeds.d.ts +115 -0
- package/dist/{src → esm}/priceFeeds.js +16 -83
- package/dist/esm/priceFeeds.js.map +1 -0
- package/dist/esm/traderDigests.d.ts +21 -0
- package/dist/esm/traderDigests.js +80 -0
- package/dist/esm/traderDigests.js.map +1 -0
- package/dist/esm/traderInterface.d.ts +79 -0
- package/dist/esm/traderInterface.js +196 -0
- package/dist/esm/traderInterface.js.map +1 -0
- package/dist/esm/triangulator.d.ts +27 -0
- package/dist/esm/triangulator.js +110 -0
- package/dist/esm/triangulator.js.map +1 -0
- package/dist/esm/utils.d.ts +59 -0
- package/dist/esm/utils.js +138 -0
- package/dist/esm/utils.js.map +1 -0
- package/dist/esm/version.d.ts +1 -0
- package/dist/esm/version.js +2 -0
- package/dist/esm/version.js.map +1 -0
- package/dist/esm/writeAccessHandler.d.ts +50 -0
- package/dist/esm/writeAccessHandler.js +157 -0
- package/dist/esm/writeAccessHandler.js.map +1 -0
- package/package.json +16 -26
- package/dist/bundle.js +0 -36793
- package/dist/config/defaultConfig.json +0 -47
- package/dist/config/mockSwap.json +0 -4
- package/dist/config/priceFeedConfig.json +0 -104
- package/dist/config/symbolList.json +0 -13
- package/dist/src/index.js +0 -45
- package/dist/src/nodeSDKTypes.js +0 -115
- package/dist/src/version.d.ts +0 -1
- package/module.d.ts +0 -1
- package/src/accountTrade.ts +0 -392
- package/src/brokerTool.ts +0 -507
- package/src/d8XMath.ts +0 -319
- package/src/liquidatorTool.ts +0 -258
- package/src/liquidityProviderTool.ts +0 -186
- package/src/marketData.ts +0 -946
- package/src/nodeSDKTypes.ts +0 -293
- package/src/orderReferrerTool.ts +0 -389
- package/src/perpetualDataHandler.ts +0 -1061
- package/src/perpetualEventHandler.ts +0 -455
- package/src/priceFeeds.ts +0 -381
- package/src/traderDigests.ts +0 -91
- package/src/traderInterface.ts +0 -159
- package/src/triangulator.ts +0 -105
- package/src/utils.ts +0 -134
- package/src/version.ts +0 -1
- package/src/writeAccessHandler.ts +0 -127
- /package/dist/{abi → cjs/abi}/ERC20.json +0 -0
- /package/dist/{abi → cjs/abi}/MockTokenSwap.json +0 -0
- /package/dist/{abi → cjs/abi}/central-park/IPerpetualManager.json +0 -0
- /package/dist/{abi → cjs/abi}/central-park/LimitOrderBook.json +0 -0
- /package/dist/{abi → cjs/abi}/central-park/LimitOrderBookFactory.json +0 -0
- /package/dist/{abi → cjs/abi}/testnet/LimitOrderBookFactory.json +0 -0
- /package/dist/{src → cjs}/accountTrade.d.ts +0 -0
- /package/dist/{src → cjs}/brokerTool.d.ts +0 -0
- /package/dist/{src → cjs}/d8XMath.d.ts +0 -0
- /package/dist/{src → cjs}/d8XMath.js +0 -0
- /package/dist/{src → cjs}/index.d.ts +0 -0
- /package/dist/{src → cjs}/liquidatorTool.d.ts +0 -0
- /package/dist/{src → cjs}/liquidityProviderTool.d.ts +0 -0
- /package/dist/{src → cjs}/marketData.d.ts +0 -0
- /package/dist/{src → cjs}/priceFeeds.d.ts +0 -0
- /package/dist/{src → cjs}/traderDigests.d.ts +0 -0
- /package/dist/{src → cjs}/traderInterface.d.ts +0 -0
- /package/dist/{src → cjs}/triangulator.d.ts +0 -0
- /package/dist/{src → cjs}/utils.d.ts +0 -0
- /package/dist/{src → cjs}/writeAccessHandler.d.ts +0 -0
package/src/d8XMath.ts
DELETED
|
@@ -1,319 +0,0 @@
|
|
|
1
|
-
import { BigNumber } from "ethers";
|
|
2
|
-
import { DECIMALS, ONE_64x64 } from "./nodeSDKTypes";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @module d8xMath
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Convert ABK64x64 bigint-format to float.
|
|
10
|
-
* Result = x/2^64 if big number, x/2^29 if number
|
|
11
|
-
* @param {BigNumber|number} x number in ABDK-format or 2^29
|
|
12
|
-
* @returns {number} x/2^64 in number-format (float)
|
|
13
|
-
*/
|
|
14
|
-
export function ABK64x64ToFloat(x: BigNumber | number): number {
|
|
15
|
-
if (typeof x == "number") {
|
|
16
|
-
return x / 2 ** 29;
|
|
17
|
-
}
|
|
18
|
-
let s = x.lt(0) ? -1 : 1;
|
|
19
|
-
x = x.mul(s);
|
|
20
|
-
let xInt = x.div(ONE_64x64);
|
|
21
|
-
let dec18 = BigNumber.from(10).pow(BigNumber.from(18));
|
|
22
|
-
let xDec = x.sub(xInt.mul(ONE_64x64));
|
|
23
|
-
xDec = xDec.mul(dec18).div(ONE_64x64);
|
|
24
|
-
let k = 18 - xDec.toString().length;
|
|
25
|
-
// console.assert(k >= 0);
|
|
26
|
-
let sPad = "0".repeat(k);
|
|
27
|
-
let NumberStr = xInt.toString() + "." + sPad + xDec.toString();
|
|
28
|
-
return parseFloat(NumberStr) * s;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
*
|
|
33
|
-
* @param {BigNumber} x BigNumber in Dec-N format
|
|
34
|
-
* @returns {number} x as a float (number)
|
|
35
|
-
*/
|
|
36
|
-
export function decNToFloat(x: BigNumber, numDec: number) {
|
|
37
|
-
//x: BigNumber in DecN format to float
|
|
38
|
-
const DECIMALS = BigNumber.from(10).pow(BigNumber.from(numDec));
|
|
39
|
-
let s = x.lt(0) ? -1 : 1;
|
|
40
|
-
x = x.mul(s);
|
|
41
|
-
let xInt = x.div(DECIMALS);
|
|
42
|
-
let xDec = x.sub(xInt.mul(DECIMALS));
|
|
43
|
-
let k = numDec - xDec.toString().length;
|
|
44
|
-
let sPad = "0".repeat(k);
|
|
45
|
-
let NumberStr = xInt.toString() + "." + sPad + xDec.toString();
|
|
46
|
-
return parseFloat(NumberStr) * s;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
*
|
|
51
|
-
* @param {BigNumber} x BigNumber in Dec18 format
|
|
52
|
-
* @returns {number} x as a float (number)
|
|
53
|
-
*/
|
|
54
|
-
export function dec18ToFloat(x: BigNumber): number {
|
|
55
|
-
//x: BigNumber in Dec18 format to float
|
|
56
|
-
let s = x.lt(0) ? -1 : 1;
|
|
57
|
-
x = x.mul(s);
|
|
58
|
-
let xInt = x.div(DECIMALS);
|
|
59
|
-
let xDec = x.sub(xInt.mul(DECIMALS));
|
|
60
|
-
let k = 18 - xDec.toString().length;
|
|
61
|
-
let sPad = "0".repeat(k);
|
|
62
|
-
let NumberStr = xInt.toString() + "." + sPad + xDec.toString();
|
|
63
|
-
return parseFloat(NumberStr) * s;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Converts x into ABDK64x64 format
|
|
68
|
-
* @param {number} x number (float)
|
|
69
|
-
* @returns {BigNumber} x^64 in big number format
|
|
70
|
-
*/
|
|
71
|
-
export function floatToABK64x64(x: number): BigNumber {
|
|
72
|
-
// convert float to ABK64x64 bigint-format
|
|
73
|
-
// Create string from number with 18 decimals
|
|
74
|
-
if (x === 0) {
|
|
75
|
-
return BigNumber.from(0);
|
|
76
|
-
}
|
|
77
|
-
let sg = Math.sign(x);
|
|
78
|
-
x = Math.abs(x);
|
|
79
|
-
let strX = Number(x).toFixed(18);
|
|
80
|
-
const arrX = strX.split(".");
|
|
81
|
-
let xInt = BigNumber.from(arrX[0]);
|
|
82
|
-
let xDec = BigNumber.from(arrX[1]);
|
|
83
|
-
let xIntBig = xInt.mul(ONE_64x64);
|
|
84
|
-
let dec18 = BigNumber.from(10).pow(BigNumber.from(18));
|
|
85
|
-
let xDecBig = xDec.mul(ONE_64x64).div(dec18);
|
|
86
|
-
return xIntBig.add(xDecBig).mul(sg);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
*
|
|
91
|
-
* @param {number} x number (float)
|
|
92
|
-
* @returns {BigNumber} x as a BigNumber in Dec18 format
|
|
93
|
-
*/
|
|
94
|
-
export function floatToDec18(x: number): BigNumber {
|
|
95
|
-
// float number to dec 18
|
|
96
|
-
if (x === 0) {
|
|
97
|
-
return BigNumber.from(0);
|
|
98
|
-
}
|
|
99
|
-
let sg = Math.sign(x);
|
|
100
|
-
x = Math.abs(x);
|
|
101
|
-
let strX = x.toFixed(18);
|
|
102
|
-
const arrX = strX.split(".");
|
|
103
|
-
let xInt = BigNumber.from(arrX[0]);
|
|
104
|
-
let xDec = BigNumber.from(arrX[1]);
|
|
105
|
-
let xIntBig = xInt.mul(DECIMALS);
|
|
106
|
-
return xIntBig.add(xDec).mul(sg);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
*
|
|
111
|
-
* @param {BigNumber} x
|
|
112
|
-
* @param {BigNumber} y
|
|
113
|
-
* @returns {BigNumber} x * y
|
|
114
|
-
*/
|
|
115
|
-
export function mul64x64(x: BigNumber, y: BigNumber) {
|
|
116
|
-
return x.mul(y).div(ONE_64x64);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
*
|
|
121
|
-
* @param {BigNumber} x
|
|
122
|
-
* @param {BigNumber} y
|
|
123
|
-
* @returns {BigNumber} x / y
|
|
124
|
-
*/
|
|
125
|
-
export function div64x64(x: BigNumber, y: BigNumber) {
|
|
126
|
-
return x.mul(ONE_64x64).div(y);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Determine the liquidation price
|
|
131
|
-
* @param {number} LockedInValueQC - trader locked in value in quote currency
|
|
132
|
-
* @param {number} position - trader position in base currency
|
|
133
|
-
* @param {number} cash_cc - trader available margin cash in collateral currency
|
|
134
|
-
* @param {number} maintenance_margin_rate - maintenance margin ratio
|
|
135
|
-
* @param {number} S3 - collateral to quote conversion (=S2 if base-collateral, =1 if quuote collateral, = index S3 if quanto)
|
|
136
|
-
* @returns {number} Amount to be deposited to have the given leverage when trading into position pos
|
|
137
|
-
*/
|
|
138
|
-
export function calculateLiquidationPriceCollateralBase(
|
|
139
|
-
LockedInValueQC: number,
|
|
140
|
-
position: number,
|
|
141
|
-
cash_cc: number,
|
|
142
|
-
maintenance_margin_rate: number
|
|
143
|
-
): number {
|
|
144
|
-
// correct only if markprice = spot price
|
|
145
|
-
// m_r <= (Sm * Pi - L + cash * S3) / (Sm * |Pi|)
|
|
146
|
-
// -> Sm * (Pi + cash - m_r|Pi|) => L
|
|
147
|
-
return LockedInValueQC / (position - maintenance_margin_rate * Math.abs(position) + cash_cc);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Determine the liquidation price
|
|
152
|
-
* @param {number} LockedInValueQC - trader locked in value in quote currency
|
|
153
|
-
* @param {number} position - trader position in base currency
|
|
154
|
-
* @param {number} cash_cc - trader available margin cash in collateral currency
|
|
155
|
-
* @param {number} maintenance_margin_rate - maintenance margin ratio
|
|
156
|
-
* @param {number} S3 - collateral to quote conversion (=S2 if base-collateral, =1 if quuote collateral, = index S3 if quanto)
|
|
157
|
-
* @param {number} Sm - mark price
|
|
158
|
-
* @returns {number} Amount to be deposited to have the given leverage when trading into position pos
|
|
159
|
-
*/
|
|
160
|
-
export function calculateLiquidationPriceCollateralQuanto(
|
|
161
|
-
LockedInValueQC: number,
|
|
162
|
-
position: number,
|
|
163
|
-
cash_cc: number,
|
|
164
|
-
maintenance_margin_rate: number,
|
|
165
|
-
S3: number,
|
|
166
|
-
Sm: number
|
|
167
|
-
): number {
|
|
168
|
-
// correct only if markprice = spot price and S3 co-moves with Sm
|
|
169
|
-
// m_r = (Sm * Pi - L + cash * S3) / (Sm * |Pi|)
|
|
170
|
-
// m_r = [Sm * Pi - L + cash * S3(0) * (1 + sign(Pi) (Sm / Sm(0) - 1)] / (Sm * |Pi|)
|
|
171
|
-
// -> Sm * (m_r |Pi| - Pi - cash * S3(0) * sign(Pi) / Sm(0)) = - L + cash * S3(0) * (1 - sign(Pi))
|
|
172
|
-
let numerator = -LockedInValueQC + cash_cc * S3 * (1 - Math.sign(position));
|
|
173
|
-
let denominator = maintenance_margin_rate * Math.abs(position) - position - (cash_cc * S3 * Math.sign(position)) / Sm;
|
|
174
|
-
return numerator / denominator;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Determine the liquidation price
|
|
179
|
-
* @param {number} LockedInValueQC - trader locked in value in quote currency
|
|
180
|
-
* @param {number} position - trader position in base currency
|
|
181
|
-
* @param {number} cash_cc - trader available margin cash in collateral currency
|
|
182
|
-
* @param {number} maintenance_margin_rate - maintenance margin ratio
|
|
183
|
-
* @param {number} S3 - collateral to quote conversion (=S2 if base-collateral, =1 if quuote collateral, = index S3 if quanto)
|
|
184
|
-
* @returns {number} Amount to be deposited to have the given leverage when trading into position pos
|
|
185
|
-
*/
|
|
186
|
-
export function calculateLiquidationPriceCollateralQuote(
|
|
187
|
-
LockedInValueQC: number,
|
|
188
|
-
position: number,
|
|
189
|
-
cash_cc: number,
|
|
190
|
-
maintenance_margin_rate: number
|
|
191
|
-
): number {
|
|
192
|
-
// m_r = (Sm * Pi - L + cash ) / (Sm * |Pi|)
|
|
193
|
-
// -> Sm * (m_r |Pi| - Pi) = - L + cash
|
|
194
|
-
let numerator = -LockedInValueQC + cash_cc;
|
|
195
|
-
let denominator = maintenance_margin_rate * Math.abs(position) - position;
|
|
196
|
-
return numerator / denominator;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
*
|
|
201
|
-
* @param targetLeverage Leverage of the resulting position. It must be positive unless the resulting position is closed.
|
|
202
|
-
* @param currentPosition Current position size, in base currency, signed.
|
|
203
|
-
* @param currentLockedInValue Current locked in value, average entry price times position size, in quote currency.
|
|
204
|
-
* @param tradeAmount Trade amount, in base currency, signed.
|
|
205
|
-
* @param markPrice Mark price, positive.
|
|
206
|
-
* @param indexPriceS2 Index price, positive.
|
|
207
|
-
* @param indexPriceS3 Collateral index price, positive.
|
|
208
|
-
* @param tradePrice Expected price to trade tradeAmount.
|
|
209
|
-
* @param feeRate
|
|
210
|
-
* @returns {number} Total collateral amount needed for the new position to have he desired leverage.
|
|
211
|
-
*/
|
|
212
|
-
export function getMarginRequiredForLeveragedTrade(
|
|
213
|
-
targetLeverage: number | undefined,
|
|
214
|
-
currentPosition: number,
|
|
215
|
-
currentLockedInValue: number,
|
|
216
|
-
tradeAmount: number,
|
|
217
|
-
markPrice: number,
|
|
218
|
-
indexPriceS2: number,
|
|
219
|
-
indexPriceS3: number,
|
|
220
|
-
tradePrice: number,
|
|
221
|
-
feeRate: number
|
|
222
|
-
): number {
|
|
223
|
-
// we solve for margin in:
|
|
224
|
-
// |new position| * Sm / leverage + fee rate * |trade amount| * S2 = margin * S3 + current position * Sm - L + trade amount * (Sm - trade price)
|
|
225
|
-
// --> M S3 = |P'|Sm/L + FeeQC - PnL + (P'-P)(Price - Sm) = pos value / leverage + fees + price impact - pnl
|
|
226
|
-
let isClosing =
|
|
227
|
-
currentPosition != 0 && currentPosition * tradeAmount < 0 && currentPosition * (currentPosition + tradeAmount) >= 0;
|
|
228
|
-
let feesCC = (feeRate * Math.abs(tradeAmount) * indexPriceS2) / indexPriceS3;
|
|
229
|
-
let collRequired = feesCC;
|
|
230
|
-
|
|
231
|
-
if (!isClosing) {
|
|
232
|
-
if (targetLeverage == undefined || targetLeverage <= 0) {
|
|
233
|
-
throw Error("opening trades must have positive leverage");
|
|
234
|
-
}
|
|
235
|
-
// unrealized pnl (could be + or -) - price impact premium (+)
|
|
236
|
-
let pnlQC = currentPosition * markPrice - currentLockedInValue - tradeAmount * (tradePrice - markPrice);
|
|
237
|
-
collRequired +=
|
|
238
|
-
Math.max(0, (Math.abs(currentPosition + tradeAmount) * markPrice) / targetLeverage - pnlQC) / indexPriceS3;
|
|
239
|
-
}
|
|
240
|
-
return collRequired;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
export function getMaxSignedPositionSize(
|
|
244
|
-
marginCollateral: number,
|
|
245
|
-
currentPosition: number,
|
|
246
|
-
currentLockedInValue: number,
|
|
247
|
-
direction: number,
|
|
248
|
-
limitPrice: number,
|
|
249
|
-
initialMarginRate: number,
|
|
250
|
-
feeRate: number,
|
|
251
|
-
markPrice: number,
|
|
252
|
-
indexPriceS2: number,
|
|
253
|
-
indexPriceS3: number
|
|
254
|
-
): number {
|
|
255
|
-
// we solve for new position in:
|
|
256
|
-
// |new position| * Sm / leverage + fee rate * |trade amount| * S2 = margin * S3 + current position * Sm - L + trade amount * (Sm - entry price)
|
|
257
|
-
// |trade amount| = (new position - current position) * direction
|
|
258
|
-
let availableCash = marginCollateral * indexPriceS3 + currentPosition * markPrice - currentLockedInValue;
|
|
259
|
-
let effectiveMarginRate =
|
|
260
|
-
markPrice * initialMarginRate + feeRate * indexPriceS2 + direction * (limitPrice - markPrice);
|
|
261
|
-
|
|
262
|
-
return availableCash / effectiveMarginRate;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Compute the leverage resulting from a trade
|
|
267
|
-
* @param tradeAmount Amount to trade, in base currency, signed
|
|
268
|
-
* @param marginCollateral Amount of cash in the margin account, in collateral currency
|
|
269
|
-
* @param currentPosition Position size before the trade
|
|
270
|
-
* @param currentLockedInValue Locked-in value before the trade
|
|
271
|
-
* @param price Price charged to trade tradeAmount
|
|
272
|
-
* @param indexPriceS3 Spot price of the collateral currency when the trade happens
|
|
273
|
-
* @param markPrice Mark price of the index when the trade happens
|
|
274
|
-
* @returns Leverage of the resulting position
|
|
275
|
-
*/
|
|
276
|
-
export function getNewPositionLeverage(
|
|
277
|
-
tradeAmount: number,
|
|
278
|
-
marginCollateral: number,
|
|
279
|
-
currentPosition: number,
|
|
280
|
-
currentLockedInValue: number,
|
|
281
|
-
price: number,
|
|
282
|
-
indexPriceS3: number,
|
|
283
|
-
markPrice: number
|
|
284
|
-
): number {
|
|
285
|
-
let newPosition = tradeAmount + currentPosition;
|
|
286
|
-
let pnlQC = currentPosition * markPrice - currentLockedInValue + tradeAmount * (markPrice - price);
|
|
287
|
-
return (Math.abs(newPosition) * markPrice) / (marginCollateral * indexPriceS3 + pnlQC);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
/**
|
|
291
|
-
* Determine amount to be deposited into margin account so that the given leverage
|
|
292
|
-
* is obtained when trading a position pos (trade amount = position)
|
|
293
|
-
* Does NOT include fees
|
|
294
|
-
* Smart contract equivalent: calcMarginForTargetLeverage(..., _ignorePosBalance = false & balance = b0)
|
|
295
|
-
* @param {number} pos0 - current position
|
|
296
|
-
* @param {number} b0 - current balance
|
|
297
|
-
* @param {number} tradeAmnt - amount to trade
|
|
298
|
-
* @param {number} targetLvg - target leverage
|
|
299
|
-
* @param {number} price - price to trade amount 'tradeAmnt'
|
|
300
|
-
* @param {number} S3 - collateral to quote conversion (=S2 if base-collateral, =1 if quote collateral, = index S3 if quanto)
|
|
301
|
-
* @param {number} S2Mark - mark price
|
|
302
|
-
* @returns {number} Amount to be deposited to have the given leverage when trading into position pos before fees
|
|
303
|
-
*/
|
|
304
|
-
export function getDepositAmountForLvgTrade(
|
|
305
|
-
pos0: number,
|
|
306
|
-
b0: number,
|
|
307
|
-
tradeAmnt: number,
|
|
308
|
-
targetLvg: number,
|
|
309
|
-
price: number,
|
|
310
|
-
S3: number,
|
|
311
|
-
S2Mark: number
|
|
312
|
-
) {
|
|
313
|
-
let pnl = (tradeAmnt * (S2Mark - price)) / S3;
|
|
314
|
-
if (targetLvg == 0) {
|
|
315
|
-
targetLvg = (Math.abs(pos0) * S2Mark) / S3 / b0;
|
|
316
|
-
}
|
|
317
|
-
let b = (Math.abs(pos0 + tradeAmnt) * S2Mark) / S3 / targetLvg;
|
|
318
|
-
return -(b0 + pnl - b);
|
|
319
|
-
}
|
package/src/liquidatorTool.ts
DELETED
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
import WriteAccessHandler from "./writeAccessHandler";
|
|
2
|
-
import { NodeSDKConfig, PriceFeedSubmission } from "./nodeSDKTypes";
|
|
3
|
-
import { ethers } from "ethers";
|
|
4
|
-
import { ABK64x64ToFloat, floatToABK64x64 } from "./d8XMath";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Functions to liquidate traders. This class requires a private key
|
|
8
|
-
* and executes smart-contract interactions that require gas-payments.
|
|
9
|
-
* @extends WriteAccessHandler
|
|
10
|
-
*/
|
|
11
|
-
export default class LiquidatorTool extends WriteAccessHandler {
|
|
12
|
-
/**
|
|
13
|
-
* Constructs a LiquidatorTool instance for a given configuration and private key.
|
|
14
|
-
* @param {NodeSDKConfig} config Configuration object, see PerpetualDataHandler.
|
|
15
|
-
* readSDKConfig.
|
|
16
|
-
* @example
|
|
17
|
-
* import { LiquidatorTool, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
|
|
18
|
-
* async function main() {
|
|
19
|
-
* console.log(LiquidatorTool);
|
|
20
|
-
* // load configuration for testnet
|
|
21
|
-
* const config = PerpetualDataHandler.readSDKConfig("testnet");
|
|
22
|
-
* // LiquidatorTool (authentication required, PK is an environment variable with a private key)
|
|
23
|
-
* const pk: string = <string>process.env.PK;
|
|
24
|
-
* let lqudtrTool = new LiquidatorTool(config, pk);
|
|
25
|
-
* // Create a proxy instance to access the blockchain
|
|
26
|
-
* await lqudtrTool.createProxyInstance();
|
|
27
|
-
* }
|
|
28
|
-
* main();
|
|
29
|
-
*
|
|
30
|
-
* @param {string} privateKey Private key of account that liquidates.
|
|
31
|
-
*/
|
|
32
|
-
public constructor(config: NodeSDKConfig, privateKey: string) {
|
|
33
|
-
super(config, privateKey);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Liquidate a trader.
|
|
38
|
-
* @param {string} symbol Symbol of the form ETH-USD-MATIC.
|
|
39
|
-
* @param {string} traderAddr Address of the trader to be liquidated.
|
|
40
|
-
* @param {string=} liquidatorAddr Address to be credited if the liquidation succeeds.
|
|
41
|
-
* @param {PriceFeedSubmission} priceFeedData optional. VAA and timestamps for oracle. If not provided will query from REST API.
|
|
42
|
-
* Defaults to the wallet used to execute the liquidation.
|
|
43
|
-
* @example
|
|
44
|
-
* import { LiquidatorTool, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
|
|
45
|
-
* async function main() {
|
|
46
|
-
* console.log(LiquidatorTool);
|
|
47
|
-
* // Setup (authentication required, PK is an environment variable with a private key)
|
|
48
|
-
* const config = PerpetualDataHandler.readSDKConfig("testnet");
|
|
49
|
-
* const pk: string = <string>process.env.PK;
|
|
50
|
-
* let lqudtrTool = new LiquidatorTool(config, pk);
|
|
51
|
-
* await lqudtrTool.createProxyInstance();
|
|
52
|
-
* // liquidate trader
|
|
53
|
-
* let liqAmount = await lqudtrTool.liquidateTrader("ETH-USD-MATIC",
|
|
54
|
-
* "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B");
|
|
55
|
-
* console.log(liqAmount);
|
|
56
|
-
* }
|
|
57
|
-
* main();
|
|
58
|
-
*
|
|
59
|
-
* @returns Transaction object.
|
|
60
|
-
*/
|
|
61
|
-
public async liquidateTrader(
|
|
62
|
-
symbol: string,
|
|
63
|
-
traderAddr: string,
|
|
64
|
-
liquidatorAddr: string = "",
|
|
65
|
-
priceFeedData?: PriceFeedSubmission
|
|
66
|
-
): Promise<ethers.ContractTransaction> {
|
|
67
|
-
// this operation spends gas, so signer is required
|
|
68
|
-
if (this.proxyContract == null || this.signer == null) {
|
|
69
|
-
throw Error("no proxy contract or wallet initialized. Use createProxyInstance().");
|
|
70
|
-
}
|
|
71
|
-
// liquidator is signer unless specified otherwise
|
|
72
|
-
if (liquidatorAddr == "") {
|
|
73
|
-
liquidatorAddr = this.traderAddr;
|
|
74
|
-
}
|
|
75
|
-
let perpID = LiquidatorTool.symbolToPerpetualId(symbol, this.symbolToPerpStaticInfo);
|
|
76
|
-
if (priceFeedData == undefined) {
|
|
77
|
-
priceFeedData = await this.fetchLatestFeedPriceInfo(symbol);
|
|
78
|
-
}
|
|
79
|
-
return await this._liquidateByAMM(perpID, liquidatorAddr, traderAddr, priceFeedData, {
|
|
80
|
-
gasLimit: this.gasLimit,
|
|
81
|
-
value: this.PRICE_UPDATE_FEE_GWEI * priceFeedData.priceFeedVaas.length,
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Check if the collateral of a trader is above the maintenance margin ("maintenance margin safe").
|
|
87
|
-
* If not, the position can be liquidated.
|
|
88
|
-
* @param {string} symbol Symbol of the form ETH-USD-MATIC.
|
|
89
|
-
* @param {string} traderAddr Address of the trader whose position you want to assess.
|
|
90
|
-
* @param {number[]} indexPrices optional, index price S2/S3 for which we test
|
|
91
|
-
* @example
|
|
92
|
-
* import { LiquidatorTool, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
|
|
93
|
-
* async function main() {
|
|
94
|
-
* console.log(LiquidatorTool);
|
|
95
|
-
* // Setup (authentication required, PK is an environment variable with a private key)
|
|
96
|
-
* const config = PerpetualDataHandler.readSDKConfig("testnet");
|
|
97
|
-
* const pk: string = <string>process.env.PK;
|
|
98
|
-
* let lqudtrTool = new LiquidatorTool(config, pk);
|
|
99
|
-
* await lqudtrTool.createProxyInstance();
|
|
100
|
-
* // check if trader can be liquidated
|
|
101
|
-
* let safe = await lqudtrTool.isMaintenanceMarginSafe("ETH-USD-MATIC",
|
|
102
|
-
* "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B");
|
|
103
|
-
* console.log(safe);
|
|
104
|
-
* }
|
|
105
|
-
* main();
|
|
106
|
-
*
|
|
107
|
-
* @returns {boolean} True if the trader is maintenance margin safe in the perpetual.
|
|
108
|
-
* False means that the trader's position can be liquidated.
|
|
109
|
-
*/
|
|
110
|
-
public async isMaintenanceMarginSafe(
|
|
111
|
-
symbol: string,
|
|
112
|
-
traderAddr: string,
|
|
113
|
-
indexPrices?: [number, number]
|
|
114
|
-
): Promise<boolean> {
|
|
115
|
-
if (this.proxyContract == null) {
|
|
116
|
-
throw Error("no proxy contract initialized. Use createProxyInstance().");
|
|
117
|
-
}
|
|
118
|
-
const idx_notional = 4;
|
|
119
|
-
let perpID = LiquidatorTool.symbolToPerpetualId(symbol, this.symbolToPerpStaticInfo);
|
|
120
|
-
if (indexPrices == undefined) {
|
|
121
|
-
// fetch from API
|
|
122
|
-
let obj = await this.priceFeedGetter.fetchPricesForPerpetual(symbol);
|
|
123
|
-
indexPrices = [obj.idxPrices[0], obj.idxPrices[1]];
|
|
124
|
-
}
|
|
125
|
-
let traderState = await this.proxyContract.getTraderState(
|
|
126
|
-
perpID,
|
|
127
|
-
traderAddr,
|
|
128
|
-
indexPrices.map((x) => floatToABK64x64(x))
|
|
129
|
-
);
|
|
130
|
-
if (traderState[idx_notional] == 0) {
|
|
131
|
-
// trader does not have open position
|
|
132
|
-
return true;
|
|
133
|
-
}
|
|
134
|
-
// calculate margin from traderstate
|
|
135
|
-
const idx_maintenanceMgnRate = 10;
|
|
136
|
-
const idx_marginAccountPositionBC = 4;
|
|
137
|
-
const idx_collateralToQuoteConversion = 9;
|
|
138
|
-
const idx_marginBalance = 0;
|
|
139
|
-
const maintMgnRate = ABK64x64ToFloat(traderState[idx_maintenanceMgnRate]);
|
|
140
|
-
const pos = ABK64x64ToFloat(traderState[idx_marginAccountPositionBC]);
|
|
141
|
-
const marginbalance = ABK64x64ToFloat(traderState[idx_marginBalance]);
|
|
142
|
-
const coll2quote = ABK64x64ToFloat(traderState[idx_collateralToQuoteConversion]);
|
|
143
|
-
const base2collateral = indexPrices[0] / coll2quote;
|
|
144
|
-
const threshold = Math.abs(pos * base2collateral * maintMgnRate);
|
|
145
|
-
return marginbalance >= threshold;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
*
|
|
150
|
-
* @param perpetualId Perpetual id.
|
|
151
|
-
* @param liquidatorAddr Address to be credited for the liquidation.
|
|
152
|
-
* @param traderAddr Address of the trader to be liquidated.
|
|
153
|
-
* @param priceFeedData contains VAA and timestamps required
|
|
154
|
-
* @param options E.g., Gas limit, fee.
|
|
155
|
-
* @ignore
|
|
156
|
-
*/
|
|
157
|
-
public async _liquidateByAMM(
|
|
158
|
-
perpetualId: number,
|
|
159
|
-
liquidatorAddr: string,
|
|
160
|
-
traderAddr: string,
|
|
161
|
-
priceFeedData: PriceFeedSubmission,
|
|
162
|
-
options: object
|
|
163
|
-
) {
|
|
164
|
-
return await this.proxyContract!.liquidateByAMM(
|
|
165
|
-
perpetualId,
|
|
166
|
-
liquidatorAddr,
|
|
167
|
-
traderAddr,
|
|
168
|
-
priceFeedData.priceFeedVaas,
|
|
169
|
-
priceFeedData.timestamps,
|
|
170
|
-
options
|
|
171
|
-
);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Total number of active accounts for this symbol, i.e. accounts with positions that are currently open.
|
|
176
|
-
* @param {string} symbol Symbol of the form ETH-USD-MATIC.
|
|
177
|
-
* @example
|
|
178
|
-
* import { LiquidatorTool, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
|
|
179
|
-
* async function main() {
|
|
180
|
-
* console.log(LiquidatorTool);
|
|
181
|
-
* // Setup (authentication required, PK is an environment variable with a private key)
|
|
182
|
-
* const config = PerpetualDataHandler.readSDKConfig("testnet");
|
|
183
|
-
* const pk: string = <string>process.env.PK;
|
|
184
|
-
* let lqudtrTool = new LiquidatorTool(config, pk);
|
|
185
|
-
* await lqudtrTool.createProxyInstance();
|
|
186
|
-
* // get number of active accounts
|
|
187
|
-
* let accounts = await lqudtrTool.countActivePerpAccounts("ETH-USD-MATIC");
|
|
188
|
-
* console.log(accounts);
|
|
189
|
-
* }
|
|
190
|
-
* main();
|
|
191
|
-
*
|
|
192
|
-
* @returns {number} Number of active accounts.
|
|
193
|
-
*/
|
|
194
|
-
public async countActivePerpAccounts(symbol: string): Promise<number> {
|
|
195
|
-
if (this.proxyContract == null) {
|
|
196
|
-
throw Error("no proxy contract initialized. Use createProxyInstance().");
|
|
197
|
-
}
|
|
198
|
-
let perpID = LiquidatorTool.symbolToPerpetualId(symbol, this.symbolToPerpStaticInfo);
|
|
199
|
-
let numAccounts = await this.proxyContract.countActivePerpAccounts(perpID);
|
|
200
|
-
return Number(numAccounts);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Get addresses of active accounts by chunks.
|
|
205
|
-
* @param {string} symbol Symbol of the form ETH-USD-MATIC.
|
|
206
|
-
* @param {number} from From which account we start counting (0-indexed).
|
|
207
|
-
* @param {number} to Until which account we count, non inclusive.
|
|
208
|
-
* @example
|
|
209
|
-
* import { LiquidatorTool, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
|
|
210
|
-
* async function main() {
|
|
211
|
-
* console.log(LiquidatorTool);
|
|
212
|
-
* // Setup (authentication required, PK is an environment variable with a private key)
|
|
213
|
-
* const config = PerpetualDataHandler.readSDKConfig("testnet");
|
|
214
|
-
* const pk: string = <string>process.env.PK;
|
|
215
|
-
* let lqudtrTool = new LiquidatorTool(config, pk);
|
|
216
|
-
* await lqudtrTool.createProxyInstance();
|
|
217
|
-
* // get all active accounts in chunks
|
|
218
|
-
* let accounts = await lqudtrTool.getActiveAccountsByChunks("ETH-USD-MATIC", 0, 4);
|
|
219
|
-
* console.log(accounts);
|
|
220
|
-
* }
|
|
221
|
-
* main();
|
|
222
|
-
*
|
|
223
|
-
* @returns {string[]} Array of addresses at locations 'from', 'from'+1 ,..., 'to'-1.
|
|
224
|
-
*/
|
|
225
|
-
public async getActiveAccountsByChunks(symbol: string, from: number, to: number): Promise<string[]> {
|
|
226
|
-
if (this.proxyContract == null) {
|
|
227
|
-
throw Error("no proxy contract initialized. Use createProxyInstance().");
|
|
228
|
-
}
|
|
229
|
-
let perpID = LiquidatorTool.symbolToPerpetualId(symbol, this.symbolToPerpStaticInfo);
|
|
230
|
-
return await this.proxyContract.getActivePerpAccountsByChunks(perpID, from, to);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/**
|
|
234
|
-
* Addresses for all the active accounts in this perpetual symbol.
|
|
235
|
-
* @param {string} symbol Symbol of the form ETH-USD-MATIC.
|
|
236
|
-
* @example
|
|
237
|
-
* import { LiquidatorTool, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
|
|
238
|
-
* async function main() {
|
|
239
|
-
* console.log(LiquidatorTool);
|
|
240
|
-
* // Setup (authentication required, PK is an environment variable with a private key)
|
|
241
|
-
* const config = PerpetualDataHandler.readSDKConfig("testnet");
|
|
242
|
-
* const pk: string = <string>process.env.PK;
|
|
243
|
-
* let lqudtrTool = new LiquidatorTool(config, pk);
|
|
244
|
-
* await lqudtrTool.createProxyInstance();
|
|
245
|
-
* // get all active accounts
|
|
246
|
-
* let accounts = await lqudtrTool.getAllActiveAccounts("ETH-USD-MATIC");
|
|
247
|
-
* console.log(accounts);
|
|
248
|
-
* }
|
|
249
|
-
* main();
|
|
250
|
-
*
|
|
251
|
-
* @returns {string[]} Array of addresses.
|
|
252
|
-
*/
|
|
253
|
-
public async getAllActiveAccounts(symbol: string): Promise<string[]> {
|
|
254
|
-
// checks are done inside the intermediate functions
|
|
255
|
-
let totalAccounts = await this.countActivePerpAccounts(symbol);
|
|
256
|
-
return await this.getActiveAccountsByChunks(symbol, 0, totalAccounts);
|
|
257
|
-
}
|
|
258
|
-
}
|