@d8x/perpetuals-sdk 0.0.21 → 0.0.23
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/abi/IPerpetualManager.json +51 -2
- package/abi/LimitOrderBook.json +75 -45
- package/config/defaultConfig.json +5 -4
- package/config/oldConfig.json +5 -4
- package/config/symbolList.json +9 -0
- package/dist/accountTrade.js +2 -2
- package/dist/d8XMath.d.ts +16 -0
- package/dist/d8XMath.js +48 -1
- package/dist/marketData.d.ts +41 -5
- package/dist/marketData.js +139 -6
- package/dist/nodeSDKTypes.d.ts +14 -0
- package/dist/orderReferrerTool.js +4 -4
- package/dist/perpetualDataHandler.d.ts +21 -4
- package/dist/perpetualDataHandler.js +71 -24
- package/dist/perpetualEventHandler.d.ts +181 -0
- package/dist/perpetualEventHandler.js +390 -0
- package/dist/utils.d.ts +18 -0
- package/dist/utils.js +37 -1
- package/dist/writeAccessHandler.js +1 -4
- package/package.json +1 -1
- package/src/accountTrade.ts +2 -2
- package/src/d8XMath.ts +85 -0
- package/src/liquidityProviderTool.ts +0 -8
- package/src/marketData.ts +226 -8
- package/src/nodeSDKTypes.ts +16 -0
- package/src/orderReferrerTool.ts +4 -4
- package/src/perpetualDataHandler.ts +93 -27
- package/src/perpetualEventHandler.ts +441 -0
- package/src/utils.ts +36 -0
- package/src/writeAccessHandler.ts +1 -3
|
@@ -1258,6 +1258,12 @@
|
|
|
1258
1258
|
"name": "perpetualId",
|
|
1259
1259
|
"type": "uint24"
|
|
1260
1260
|
},
|
|
1261
|
+
{
|
|
1262
|
+
"indexed": false,
|
|
1263
|
+
"internalType": "int128",
|
|
1264
|
+
"name": "fMidPricePremium",
|
|
1265
|
+
"type": "int128"
|
|
1266
|
+
},
|
|
1261
1267
|
{
|
|
1262
1268
|
"indexed": false,
|
|
1263
1269
|
"internalType": "int128",
|
|
@@ -2394,9 +2400,9 @@
|
|
|
2394
2400
|
"name": "getAMMState",
|
|
2395
2401
|
"outputs": [
|
|
2396
2402
|
{
|
|
2397
|
-
"internalType": "int128[
|
|
2403
|
+
"internalType": "int128[15]",
|
|
2398
2404
|
"name": "",
|
|
2399
|
-
"type": "int128[
|
|
2405
|
+
"type": "int128[15]"
|
|
2400
2406
|
}
|
|
2401
2407
|
],
|
|
2402
2408
|
"stateMutability": "view",
|
|
@@ -3694,6 +3700,30 @@
|
|
|
3694
3700
|
"stateMutability": "view",
|
|
3695
3701
|
"type": "function"
|
|
3696
3702
|
},
|
|
3703
|
+
{
|
|
3704
|
+
"inputs": [
|
|
3705
|
+
{
|
|
3706
|
+
"internalType": "bytes4",
|
|
3707
|
+
"name": "_baseCurrency",
|
|
3708
|
+
"type": "bytes4"
|
|
3709
|
+
},
|
|
3710
|
+
{
|
|
3711
|
+
"internalType": "bytes4",
|
|
3712
|
+
"name": "_quoteCurrency",
|
|
3713
|
+
"type": "bytes4"
|
|
3714
|
+
}
|
|
3715
|
+
],
|
|
3716
|
+
"name": "isMarketClosed",
|
|
3717
|
+
"outputs": [
|
|
3718
|
+
{
|
|
3719
|
+
"internalType": "bool",
|
|
3720
|
+
"name": "",
|
|
3721
|
+
"type": "bool"
|
|
3722
|
+
}
|
|
3723
|
+
],
|
|
3724
|
+
"stateMutability": "view",
|
|
3725
|
+
"type": "function"
|
|
3726
|
+
},
|
|
3697
3727
|
{
|
|
3698
3728
|
"inputs": [
|
|
3699
3729
|
{
|
|
@@ -3732,6 +3762,25 @@
|
|
|
3732
3762
|
"stateMutability": "view",
|
|
3733
3763
|
"type": "function"
|
|
3734
3764
|
},
|
|
3765
|
+
{
|
|
3766
|
+
"inputs": [
|
|
3767
|
+
{
|
|
3768
|
+
"internalType": "uint24",
|
|
3769
|
+
"name": "_perpetualId",
|
|
3770
|
+
"type": "uint24"
|
|
3771
|
+
}
|
|
3772
|
+
],
|
|
3773
|
+
"name": "isPerpMarketClosed",
|
|
3774
|
+
"outputs": [
|
|
3775
|
+
{
|
|
3776
|
+
"internalType": "bool",
|
|
3777
|
+
"name": "isClosed",
|
|
3778
|
+
"type": "bool"
|
|
3779
|
+
}
|
|
3780
|
+
],
|
|
3781
|
+
"stateMutability": "view",
|
|
3782
|
+
"type": "function"
|
|
3783
|
+
},
|
|
3735
3784
|
{
|
|
3736
3785
|
"inputs": [
|
|
3737
3786
|
{
|
package/abi/LimitOrderBook.json
CHANGED
|
@@ -65,12 +65,6 @@
|
|
|
65
65
|
"name": "perpetualId",
|
|
66
66
|
"type": "uint24"
|
|
67
67
|
},
|
|
68
|
-
{
|
|
69
|
-
"indexed": false,
|
|
70
|
-
"internalType": "uint16",
|
|
71
|
-
"name": "brokerFeeTbps",
|
|
72
|
-
"type": "uint16"
|
|
73
|
-
},
|
|
74
68
|
{
|
|
75
69
|
"indexed": true,
|
|
76
70
|
"internalType": "address",
|
|
@@ -90,46 +84,82 @@
|
|
|
90
84
|
"type": "address"
|
|
91
85
|
},
|
|
92
86
|
{
|
|
87
|
+
"components": [
|
|
88
|
+
{
|
|
89
|
+
"internalType": "uint32",
|
|
90
|
+
"name": "flags",
|
|
91
|
+
"type": "uint32"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"internalType": "uint24",
|
|
95
|
+
"name": "iPerpetualId",
|
|
96
|
+
"type": "uint24"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"internalType": "uint16",
|
|
100
|
+
"name": "brokerFeeTbps",
|
|
101
|
+
"type": "uint16"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"internalType": "address",
|
|
105
|
+
"name": "traderAddr",
|
|
106
|
+
"type": "address"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"internalType": "address",
|
|
110
|
+
"name": "brokerAddr",
|
|
111
|
+
"type": "address"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"internalType": "address",
|
|
115
|
+
"name": "referrerAddr",
|
|
116
|
+
"type": "address"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"internalType": "bytes",
|
|
120
|
+
"name": "brokerSignature",
|
|
121
|
+
"type": "bytes"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"internalType": "int128",
|
|
125
|
+
"name": "fAmount",
|
|
126
|
+
"type": "int128"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"internalType": "int128",
|
|
130
|
+
"name": "fLimitPrice",
|
|
131
|
+
"type": "int128"
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"internalType": "int128",
|
|
135
|
+
"name": "fTriggerPrice",
|
|
136
|
+
"type": "int128"
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"internalType": "int128",
|
|
140
|
+
"name": "fLeverage",
|
|
141
|
+
"type": "int128"
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"internalType": "uint64",
|
|
145
|
+
"name": "iDeadline",
|
|
146
|
+
"type": "uint64"
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"internalType": "uint64",
|
|
150
|
+
"name": "createdTimestamp",
|
|
151
|
+
"type": "uint64"
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"internalType": "uint64",
|
|
155
|
+
"name": "submittedBlock",
|
|
156
|
+
"type": "uint64"
|
|
157
|
+
}
|
|
158
|
+
],
|
|
93
159
|
"indexed": false,
|
|
94
|
-
"internalType": "
|
|
95
|
-
"name": "
|
|
96
|
-
"type": "
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
"indexed": false,
|
|
100
|
-
"internalType": "int128",
|
|
101
|
-
"name": "limitPrice",
|
|
102
|
-
"type": "int128"
|
|
103
|
-
},
|
|
104
|
-
{
|
|
105
|
-
"indexed": false,
|
|
106
|
-
"internalType": "int128",
|
|
107
|
-
"name": "triggerPrice",
|
|
108
|
-
"type": "int128"
|
|
109
|
-
},
|
|
110
|
-
{
|
|
111
|
-
"indexed": false,
|
|
112
|
-
"internalType": "uint64",
|
|
113
|
-
"name": "deadline",
|
|
114
|
-
"type": "uint64"
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
"indexed": false,
|
|
118
|
-
"internalType": "uint32",
|
|
119
|
-
"name": "flags",
|
|
120
|
-
"type": "uint32"
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
"indexed": false,
|
|
124
|
-
"internalType": "int128",
|
|
125
|
-
"name": "leverage",
|
|
126
|
-
"type": "int128"
|
|
127
|
-
},
|
|
128
|
-
{
|
|
129
|
-
"indexed": false,
|
|
130
|
-
"internalType": "uint64",
|
|
131
|
-
"name": "createdTimestamp",
|
|
132
|
-
"type": "uint64"
|
|
160
|
+
"internalType": "struct IPerpetualOrder.Order",
|
|
161
|
+
"name": "order",
|
|
162
|
+
"type": "tuple"
|
|
133
163
|
},
|
|
134
164
|
{
|
|
135
165
|
"indexed": false,
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "v1.
|
|
3
|
-
"proxyAddr": "
|
|
2
|
+
"name": "v1.5",
|
|
3
|
+
"proxyAddr": "0xaB6AD25eE5CA28E7d7b16A33A33897aE34BF9e67",
|
|
4
4
|
"nodeURL": "https://rpc-mumbai.maticvigil.com/",
|
|
5
5
|
"proxyABILocation": "../abi/IPerpetualManager.json",
|
|
6
|
-
"limitOrderBookFactoryAddr": "
|
|
6
|
+
"limitOrderBookFactoryAddr": "0xe95422bf27C62F3b9ae19d6032aC58c1bd13C71E",
|
|
7
7
|
"limitOrderBookFactoryABILocation": "../abi/LimitOrderBookFactory.json",
|
|
8
|
-
"limitOrderBookABILocation": "../abi/LimitOrderBook.json"
|
|
8
|
+
"limitOrderBookABILocation": "../abi/LimitOrderBook.json",
|
|
9
|
+
"symbolListLocation": "../config/symbolList.json"
|
|
9
10
|
}
|
package/config/oldConfig.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "v1.
|
|
3
|
-
"proxyAddr": "
|
|
2
|
+
"name": "v1.4",
|
|
3
|
+
"proxyAddr": "0x7fe419fDE6c47F57B49Ef4D5D1ACD332307a734d",
|
|
4
4
|
"nodeURL": "https://rpc-mumbai.maticvigil.com/",
|
|
5
5
|
"proxyABILocation": "../abi/IPerpetualManager.json",
|
|
6
|
-
"limitOrderBookFactoryAddr": "
|
|
6
|
+
"limitOrderBookFactoryAddr": "0x40aA68C1C33626ecD048a8A38aBF3947813cAF92",
|
|
7
7
|
"limitOrderBookFactoryABILocation": "../abi/LimitOrderBookFactory.json",
|
|
8
|
-
"limitOrderBookABILocation": "../abi/LimitOrderBook.json"
|
|
8
|
+
"limitOrderBookABILocation": "../abi/LimitOrderBook.json",
|
|
9
|
+
"symbolListLocation": "../config/symbolList.json"
|
|
9
10
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
[
|
|
2
|
+
{ "symbol": "USD", "cleanSymbol": "USD" },
|
|
3
|
+
{ "symbol": "BTC", "cleanSymbol": "BTC" },
|
|
4
|
+
{ "symbol": "ETH", "cleanSymbol": "ETH" },
|
|
5
|
+
{ "symbol": "MATIC", "cleanSymbol": "MATC" },
|
|
6
|
+
{ "symbol": "CHF", "cleanSymbol": "CHF" },
|
|
7
|
+
{ "symbol": "GBP", "cleanSymbol": "GBP" },
|
|
8
|
+
{ "symbol": "XAU", "cleanSymbol": "XAU" }
|
|
9
|
+
]
|
package/dist/accountTrade.js
CHANGED
|
@@ -186,13 +186,13 @@ class AccountTrade extends writeAccessHandler_1.default {
|
|
|
186
186
|
*/
|
|
187
187
|
queryExchangeFee(poolSymbolName, brokerAddr) {
|
|
188
188
|
return __awaiter(this, void 0, void 0, function* () {
|
|
189
|
-
if (this.proxyContract == null
|
|
189
|
+
if (this.proxyContract == null) {
|
|
190
190
|
throw Error("no proxy contract or wallet initialized. Use createProxyInstance().");
|
|
191
191
|
}
|
|
192
192
|
if (typeof brokerAddr == "undefined") {
|
|
193
193
|
brokerAddr = nodeSDKTypes_1.ZERO_ADDRESS;
|
|
194
194
|
}
|
|
195
|
-
let poolId =
|
|
195
|
+
let poolId = perpetualDataHandler_1.default._getPoolIdFromSymbol(poolSymbolName, this.poolStaticInfos);
|
|
196
196
|
let feeTbps = yield this.proxyContract.queryExchangeFee(poolId, this.traderAddr, brokerAddr);
|
|
197
197
|
return feeTbps / 100000;
|
|
198
198
|
});
|
package/dist/d8XMath.d.ts
CHANGED
|
@@ -72,3 +72,19 @@ export declare function calculateLiquidationPriceCollateralQuanto(LockedInValueQ
|
|
|
72
72
|
* @returns {number} Amount to be deposited to have the given leverage when trading into position pos
|
|
73
73
|
*/
|
|
74
74
|
export declare function calculateLiquidationPriceCollateralQuote(LockedInValueQC: number, position: number, cash_cc: number, maintenance_margin_rate: number): number;
|
|
75
|
+
/**
|
|
76
|
+
*
|
|
77
|
+
* @param targetLeverage Leverage of the resulting position. It must be positive unless the resulting position is closed.
|
|
78
|
+
* @param currentPosition Current position size, in base currency, signed.
|
|
79
|
+
* @param currentLockedInValue Current locked in value, average entry price times position size, in quote currency.
|
|
80
|
+
* @param tradeAmount Trade amount, in base currency, signed.
|
|
81
|
+
* @param markPrice Mark price, positive.
|
|
82
|
+
* @param indexPriceS2 Index price, positive.
|
|
83
|
+
* @param indexPriceS3 Collateral index price, positive.
|
|
84
|
+
* @param tradePrice Expected price to trade tradeAmount.
|
|
85
|
+
* @param feeRate
|
|
86
|
+
* @returns
|
|
87
|
+
*/
|
|
88
|
+
export declare function getMarginRequiredForLeveragedTrade(targetLeverage: number | undefined, currentPosition: number, currentLockedInValue: number, tradeAmount: number, markPrice: number, indexPriceS2: number, indexPriceS3: number, tradePrice: number, feeRate: number): number;
|
|
89
|
+
export declare function getMaxSignedPositionSize(marginCollateral: number, currentPosition: number, currentLockedInValue: number, direction: number, limitPrice: number, initialMarginRate: number, feeRate: number, markPrice: number, indexPriceS2: number, indexPriceS3: number): number;
|
|
90
|
+
export declare function getNewPositionLeverage(tradeAmount: number, marginCollateral: number, currentPosition: number, currentLockedInValue: number, indexPriceS2: number, indexPriceS3: number, markPrice: number, limitPrice: number, feeRate: number): number;
|
package/dist/d8XMath.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.calculateLiquidationPriceCollateralQuote = exports.calculateLiquidationPriceCollateralQuanto = exports.calculateLiquidationPriceCollateralBase = exports.div64x64 = exports.mul64x64 = exports.floatToDec18 = exports.floatToABK64x64 = exports.dec18ToFloat = exports.ABK64x64ToFloat = void 0;
|
|
3
|
+
exports.getNewPositionLeverage = exports.getMaxSignedPositionSize = exports.getMarginRequiredForLeveragedTrade = exports.calculateLiquidationPriceCollateralQuote = exports.calculateLiquidationPriceCollateralQuanto = exports.calculateLiquidationPriceCollateralBase = exports.div64x64 = exports.mul64x64 = exports.floatToDec18 = exports.floatToABK64x64 = exports.dec18ToFloat = exports.ABK64x64ToFloat = void 0;
|
|
4
4
|
const ethers_1 = require("ethers");
|
|
5
5
|
const nodeSDKTypes_1 = require("./nodeSDKTypes");
|
|
6
6
|
/**
|
|
@@ -162,3 +162,50 @@ function calculateLiquidationPriceCollateralQuote(LockedInValueQC, position, cas
|
|
|
162
162
|
return numerator / denominator;
|
|
163
163
|
}
|
|
164
164
|
exports.calculateLiquidationPriceCollateralQuote = calculateLiquidationPriceCollateralQuote;
|
|
165
|
+
/**
|
|
166
|
+
*
|
|
167
|
+
* @param targetLeverage Leverage of the resulting position. It must be positive unless the resulting position is closed.
|
|
168
|
+
* @param currentPosition Current position size, in base currency, signed.
|
|
169
|
+
* @param currentLockedInValue Current locked in value, average entry price times position size, in quote currency.
|
|
170
|
+
* @param tradeAmount Trade amount, in base currency, signed.
|
|
171
|
+
* @param markPrice Mark price, positive.
|
|
172
|
+
* @param indexPriceS2 Index price, positive.
|
|
173
|
+
* @param indexPriceS3 Collateral index price, positive.
|
|
174
|
+
* @param tradePrice Expected price to trade tradeAmount.
|
|
175
|
+
* @param feeRate
|
|
176
|
+
* @returns
|
|
177
|
+
*/
|
|
178
|
+
function getMarginRequiredForLeveragedTrade(targetLeverage, currentPosition, currentLockedInValue, tradeAmount, markPrice, indexPriceS2, indexPriceS3, tradePrice, feeRate) {
|
|
179
|
+
// we solve for margin in:
|
|
180
|
+
// |new position| * Sm / leverage + fee rate * |trade amount| * S2 = margin * S3 + current position * Sm - L + trade amount * (Sm - trade price)
|
|
181
|
+
// --> M S3 = |P'|Sm/L + FeeQC - PnL + (P'-P)(Price - Sm) = pos value / leverage + fees + price impact - pnl
|
|
182
|
+
let isClosing = currentPosition != 0 && currentPosition * tradeAmount < 0 && currentPosition * (currentPosition + tradeAmount) >= 0;
|
|
183
|
+
let feesCC = (feeRate * Math.abs(tradeAmount) * indexPriceS2) / indexPriceS3;
|
|
184
|
+
let collRequired = feesCC;
|
|
185
|
+
if (!isClosing) {
|
|
186
|
+
if (targetLeverage == undefined || targetLeverage <= 0) {
|
|
187
|
+
throw Error("opening trades must have positive leverage");
|
|
188
|
+
}
|
|
189
|
+
// unrealized pnl (could be + or -) - price impact premium (+)
|
|
190
|
+
let pnlQC = currentPosition * markPrice - currentLockedInValue - tradeAmount * (tradePrice - markPrice);
|
|
191
|
+
collRequired +=
|
|
192
|
+
Math.max(0, (Math.abs(currentPosition + tradeAmount) * markPrice) / targetLeverage - pnlQC) / indexPriceS3;
|
|
193
|
+
}
|
|
194
|
+
return collRequired;
|
|
195
|
+
}
|
|
196
|
+
exports.getMarginRequiredForLeveragedTrade = getMarginRequiredForLeveragedTrade;
|
|
197
|
+
function getMaxSignedPositionSize(marginCollateral, currentPosition, currentLockedInValue, direction, limitPrice, initialMarginRate, feeRate, markPrice, indexPriceS2, indexPriceS3) {
|
|
198
|
+
// we solve for new position in:
|
|
199
|
+
// |new position| * Sm / leverage + fee rate * |trade amount| * S2 = margin * S3 + current position * Sm - L + trade amount * (Sm - entry price)
|
|
200
|
+
// |trade amount| = (new position - current position) * direction
|
|
201
|
+
let availableCash = marginCollateral * indexPriceS3 + currentPosition * markPrice - currentLockedInValue;
|
|
202
|
+
let effectiveMarginRate = markPrice * initialMarginRate + feeRate * indexPriceS2 + direction * (limitPrice - markPrice);
|
|
203
|
+
return availableCash / effectiveMarginRate;
|
|
204
|
+
}
|
|
205
|
+
exports.getMaxSignedPositionSize = getMaxSignedPositionSize;
|
|
206
|
+
function getNewPositionLeverage(tradeAmount, marginCollateral, currentPosition, currentLockedInValue, indexPriceS2, indexPriceS3, markPrice, limitPrice, feeRate) {
|
|
207
|
+
let newPosition = tradeAmount + currentPosition;
|
|
208
|
+
let pnlQC = currentPosition * markPrice - currentLockedInValue + tradeAmount * (markPrice - limitPrice);
|
|
209
|
+
return ((Math.abs(newPosition) * indexPriceS2) / (marginCollateral * indexPriceS3 + pnlQC - feeRate * Math.abs(tradeAmount)));
|
|
210
|
+
}
|
|
211
|
+
exports.getNewPositionLeverage = getNewPositionLeverage;
|
package/dist/marketData.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { ExchangeInfo, NodeSDKConfig, MarginAccount } from "./nodeSDKTypes";
|
|
1
|
+
import { ExchangeInfo, NodeSDKConfig, MarginAccount, PerpetualState, PoolStaticInfo } from "./nodeSDKTypes";
|
|
2
2
|
import { ethers } from "ethers";
|
|
3
3
|
import PerpetualDataHandler from "./perpetualDataHandler";
|
|
4
|
-
import { Order } from "./nodeSDKTypes";
|
|
4
|
+
import { SmartContractOrder, Order } from "./nodeSDKTypes";
|
|
5
5
|
import "./nodeSDKTypes";
|
|
6
6
|
/**
|
|
7
7
|
* Functions to access market data (e.g., information on open orders, information on products that can be traded).
|
|
@@ -36,6 +36,12 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
36
36
|
* @param provider optional provider
|
|
37
37
|
*/
|
|
38
38
|
createProxyInstance(provider?: ethers.providers.JsonRpcProvider): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Convert the smart contract output of an order into a convenient format of type "Order"
|
|
41
|
+
* @param smOrder SmartContractOrder, as obtained e.g., by PerpetualLimitOrderCreated event
|
|
42
|
+
* @returns more convenient format of order, type "Order"
|
|
43
|
+
*/
|
|
44
|
+
smartContractOrderToOrder(smOrder: SmartContractOrder): Order;
|
|
39
45
|
/**
|
|
40
46
|
* Get contract instance. Useful for event listening.
|
|
41
47
|
* @example
|
|
@@ -100,9 +106,9 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
100
106
|
orderIds: string[];
|
|
101
107
|
}>;
|
|
102
108
|
/**
|
|
103
|
-
* Information about the
|
|
109
|
+
* Information about the position open by a given trader in a given perpetual contract.
|
|
104
110
|
* @param {string} traderAddr Address of the trader for which we get the position risk.
|
|
105
|
-
* @param {string} symbol Symbol of the form ETH-USD-MATIC.
|
|
111
|
+
* @param {string} symbol Symbol of the form ETH-USD-MATIC. Can also be the perpetual id as string
|
|
106
112
|
* @example
|
|
107
113
|
* import { MarketData, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
|
|
108
114
|
* async function main() {
|
|
@@ -121,6 +127,8 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
121
127
|
* @returns {MarginAccount}
|
|
122
128
|
*/
|
|
123
129
|
positionRisk(traderAddr: string, symbol: string): Promise<MarginAccount>;
|
|
130
|
+
positionRiskOnTrade(traderAddr: string, order: Order, perpetualState: PerpetualState, currentPositionRisk?: MarginAccount): Promise<MarginAccount>;
|
|
131
|
+
maxOrderSizeForTrader(side: string, positionRisk: MarginAccount, perpetualState: PerpetualState): number;
|
|
124
132
|
/**
|
|
125
133
|
* Uses the Oracle(s) in the exchange to get the latest price of a given index in a given currency, if a route exists.
|
|
126
134
|
* @param {string} base Index name, e.g. ETH.
|
|
@@ -183,6 +191,32 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
183
191
|
* @returns price (number)
|
|
184
192
|
*/
|
|
185
193
|
getPerpetualPrice(symbol: string, quantity: number): Promise<number>;
|
|
194
|
+
/**
|
|
195
|
+
* Query recent perpetual state from blockchain
|
|
196
|
+
* @param symbol symbol of the form ETH-USD-MATIC
|
|
197
|
+
* @returns PerpetualState reference
|
|
198
|
+
*/
|
|
199
|
+
getPerpetualState(symbol: string): Promise<PerpetualState>;
|
|
200
|
+
/**
|
|
201
|
+
* get the current mid-price for a perpetual
|
|
202
|
+
* @param symbol symbol of the form ETH-USD-MATIC
|
|
203
|
+
* @example
|
|
204
|
+
* import { MarketData, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
|
|
205
|
+
* async function main() {
|
|
206
|
+
* console.log(MarketData);
|
|
207
|
+
* // setup
|
|
208
|
+
* const config = PerpetualDataHandler.readSDKConfig("testnet");
|
|
209
|
+
* let mktData = new MarketData(config);
|
|
210
|
+
* await mktData.createProxyInstance();
|
|
211
|
+
* // get perpetual mid price
|
|
212
|
+
* let midPrice = await mktData.getPerpetualMidPrice("ETH-USD-MATIC");
|
|
213
|
+
* console.log(midPrice);
|
|
214
|
+
* }
|
|
215
|
+
* main();
|
|
216
|
+
*
|
|
217
|
+
* @returns {number} price
|
|
218
|
+
*/
|
|
219
|
+
getPerpetualMidPrice(symbol: string): Promise<number>;
|
|
186
220
|
/**
|
|
187
221
|
* Query smart contract to get user orders and convert to user friendly order format.
|
|
188
222
|
* @param {string} traderAddr Address of trader.
|
|
@@ -199,5 +233,7 @@ export default class MarketData extends PerpetualDataHandler {
|
|
|
199
233
|
* @ignore
|
|
200
234
|
*/
|
|
201
235
|
static orderIdsOfTrader(traderAddr: string, orderBookContract: ethers.Contract): Promise<string[]>;
|
|
202
|
-
static _exchangeInfo(_proxyContract: ethers.Contract
|
|
236
|
+
static _exchangeInfo(_proxyContract: ethers.Contract, _poolStaticInfos: Array<PoolStaticInfo>, _symbolList: Array<{
|
|
237
|
+
[key: string]: string;
|
|
238
|
+
}>): Promise<ExchangeInfo>;
|
|
203
239
|
}
|
package/dist/marketData.js
CHANGED
|
@@ -63,6 +63,14 @@ class MarketData extends perpetualDataHandler_1.default {
|
|
|
63
63
|
yield this.initContractsAndData(this.provider);
|
|
64
64
|
});
|
|
65
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Convert the smart contract output of an order into a convenient format of type "Order"
|
|
68
|
+
* @param smOrder SmartContractOrder, as obtained e.g., by PerpetualLimitOrderCreated event
|
|
69
|
+
* @returns more convenient format of order, type "Order"
|
|
70
|
+
*/
|
|
71
|
+
smartContractOrderToOrder(smOrder) {
|
|
72
|
+
return perpetualDataHandler_1.default.fromSmartContractOrder(smOrder, this.symbolToPerpStaticInfo);
|
|
73
|
+
}
|
|
66
74
|
/**
|
|
67
75
|
* Get contract instance. Useful for event listening.
|
|
68
76
|
* @example
|
|
@@ -110,7 +118,7 @@ class MarketData extends perpetualDataHandler_1.default {
|
|
|
110
118
|
if (this.proxyContract == null) {
|
|
111
119
|
throw Error("no proxy contract initialized. Use createProxyInstance().");
|
|
112
120
|
}
|
|
113
|
-
return yield MarketData._exchangeInfo(this.proxyContract);
|
|
121
|
+
return yield MarketData._exchangeInfo(this.proxyContract, this.poolStaticInfos, this.symbolList);
|
|
114
122
|
});
|
|
115
123
|
}
|
|
116
124
|
/**
|
|
@@ -146,9 +154,9 @@ class MarketData extends perpetualDataHandler_1.default {
|
|
|
146
154
|
});
|
|
147
155
|
}
|
|
148
156
|
/**
|
|
149
|
-
* Information about the
|
|
157
|
+
* Information about the position open by a given trader in a given perpetual contract.
|
|
150
158
|
* @param {string} traderAddr Address of the trader for which we get the position risk.
|
|
151
|
-
* @param {string} symbol Symbol of the form ETH-USD-MATIC.
|
|
159
|
+
* @param {string} symbol Symbol of the form ETH-USD-MATIC. Can also be the perpetual id as string
|
|
152
160
|
* @example
|
|
153
161
|
* import { MarketData, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
|
|
154
162
|
* async function main() {
|
|
@@ -175,6 +183,87 @@ class MarketData extends perpetualDataHandler_1.default {
|
|
|
175
183
|
return mgnAcct;
|
|
176
184
|
});
|
|
177
185
|
}
|
|
186
|
+
positionRiskOnTrade(traderAddr, order, perpetualState, currentPositionRisk) {
|
|
187
|
+
var _a, _b, _c;
|
|
188
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
189
|
+
if (this.proxyContract == null) {
|
|
190
|
+
throw Error("no proxy contract initialized. Use createProxyInstance().");
|
|
191
|
+
}
|
|
192
|
+
if (currentPositionRisk == undefined) {
|
|
193
|
+
currentPositionRisk = yield this.positionRisk(traderAddr, order.symbol);
|
|
194
|
+
}
|
|
195
|
+
let tradeAmount = order.quantity * (order.side == nodeSDKTypes_1.BUY_SIDE ? 1 : -1);
|
|
196
|
+
let currentPosition = currentPositionRisk.positionNotionalBaseCCY;
|
|
197
|
+
let newPosition = currentPositionRisk.positionNotionalBaseCCY + tradeAmount;
|
|
198
|
+
let side = newPosition > 0 ? nodeSDKTypes_1.BUY_SIDE : newPosition < 0 ? nodeSDKTypes_1.SELL_SIDE : nodeSDKTypes_1.CLOSED_SIDE;
|
|
199
|
+
let lockedInValue = currentPositionRisk.entryPrice * currentPosition;
|
|
200
|
+
let poolId = perpetualDataHandler_1.default._getPoolIdFromSymbol(order.symbol, this.poolStaticInfos);
|
|
201
|
+
// total fee rate = exchange fee + broker fee
|
|
202
|
+
let feeRate = (yield this.proxyContract.queryExchangeFee(poolId, traderAddr, (_a = order.brokerAddr) !== null && _a !== void 0 ? _a : nodeSDKTypes_1.ZERO_ADDRESS)) +
|
|
203
|
+
((_b = order.brokerFeeTbps) !== null && _b !== void 0 ? _b : 0) / 100000;
|
|
204
|
+
// price for this order = limit price (conservative) if given, else the current perp price
|
|
205
|
+
let tradePrice = (_c = order.limitPrice) !== null && _c !== void 0 ? _c : (yield this.getPerpetualPrice(order.symbol, tradeAmount));
|
|
206
|
+
// need these for leverage/margin calculations
|
|
207
|
+
let [markPrice, indexPriceS2, indexPriceS3] = [
|
|
208
|
+
perpetualState.markPrice,
|
|
209
|
+
perpetualState.indexPrice,
|
|
210
|
+
perpetualState.collToQuoteIndexPrice,
|
|
211
|
+
];
|
|
212
|
+
let newCollateral;
|
|
213
|
+
let newLeverage;
|
|
214
|
+
if (order.keepPositionLvg) {
|
|
215
|
+
// we have a target leverage for the resulting position
|
|
216
|
+
// this gives us the total margin needed in the account so that it satisfies the leverage condition
|
|
217
|
+
newCollateral = (0, d8XMath_1.getMarginRequiredForLeveragedTrade)(currentPositionRisk.leverage, currentPosition, lockedInValue, tradeAmount, markPrice, indexPriceS2, indexPriceS3, tradePrice, feeRate);
|
|
218
|
+
// the new leverage follows from the updated margin and position
|
|
219
|
+
newLeverage = (0, d8XMath_1.getNewPositionLeverage)(tradeAmount, newCollateral, currentPosition, lockedInValue, indexPriceS2, indexPriceS3, markPrice, tradePrice, feeRate);
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
// the order has its own leverage and margin requirements
|
|
223
|
+
let tradeCollateral = (0, d8XMath_1.getMarginRequiredForLeveragedTrade)(order.leverage, 0, 0, tradeAmount, markPrice, indexPriceS2, indexPriceS3, tradePrice, feeRate);
|
|
224
|
+
newCollateral = currentPositionRisk.collateralCC + tradeCollateral;
|
|
225
|
+
// the new leverage corresponds to increasing the position and collateral according to the order
|
|
226
|
+
newLeverage = (0, d8XMath_1.getNewPositionLeverage)(tradeAmount, newCollateral, currentPosition, lockedInValue, indexPriceS2, indexPriceS3, markPrice, tradePrice, feeRate);
|
|
227
|
+
}
|
|
228
|
+
let newLockedInValue = lockedInValue + tradeAmount * tradePrice;
|
|
229
|
+
// liquidation vars
|
|
230
|
+
let S2Liq, S3Liq;
|
|
231
|
+
let tau = this.symbolToPerpStaticInfo.get(order.symbol).maintenanceMarginRate;
|
|
232
|
+
let ccyType = this.symbolToPerpStaticInfo.get(order.symbol).collateralCurrencyType;
|
|
233
|
+
if (ccyType == nodeSDKTypes_1.CollaterlCCY.BASE) {
|
|
234
|
+
S2Liq = (0, d8XMath_1.calculateLiquidationPriceCollateralBase)(newLockedInValue, newPosition, newCollateral, tau);
|
|
235
|
+
S3Liq = S2Liq;
|
|
236
|
+
}
|
|
237
|
+
else if (ccyType == nodeSDKTypes_1.CollaterlCCY.QUANTO) {
|
|
238
|
+
S3Liq = indexPriceS3;
|
|
239
|
+
S2Liq = (0, d8XMath_1.calculateLiquidationPriceCollateralQuanto)(newLockedInValue, newPosition, newCollateral, tau, indexPriceS3, markPrice);
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
S2Liq = (0, d8XMath_1.calculateLiquidationPriceCollateralQuote)(newLockedInValue, newPosition, newCollateral, tau);
|
|
243
|
+
}
|
|
244
|
+
let newPositionRisk = {
|
|
245
|
+
symbol: currentPositionRisk.symbol,
|
|
246
|
+
positionNotionalBaseCCY: newPosition,
|
|
247
|
+
side: side,
|
|
248
|
+
entryPrice: Math.abs(newLockedInValue / newPosition),
|
|
249
|
+
leverage: newLeverage,
|
|
250
|
+
markPrice: markPrice,
|
|
251
|
+
unrealizedPnlQuoteCCY: tradeAmount * (markPrice - tradePrice),
|
|
252
|
+
unrealizedFundingCollateralCCY: currentPositionRisk.unrealizedFundingCollateralCCY,
|
|
253
|
+
collateralCC: newCollateral,
|
|
254
|
+
collToQuoteConversion: indexPriceS3,
|
|
255
|
+
liquidationPrice: [S2Liq, S3Liq],
|
|
256
|
+
liquidationLvg: 1 / tau,
|
|
257
|
+
};
|
|
258
|
+
return newPositionRisk;
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
maxOrderSizeForTrader(side, positionRisk, perpetualState) {
|
|
262
|
+
let initialMarginRate = this.symbolToPerpStaticInfo.get(positionRisk.symbol).initialMarginRate;
|
|
263
|
+
// fees not considered here
|
|
264
|
+
let maxPosition = (0, d8XMath_1.getMaxSignedPositionSize)(positionRisk.collateralCC, positionRisk.positionNotionalBaseCCY, positionRisk.entryPrice * positionRisk.positionNotionalBaseCCY, side == nodeSDKTypes_1.BUY_SIDE ? 1 : -1, perpetualState.markPrice, initialMarginRate, 0, perpetualState.markPrice, perpetualState.indexPrice, perpetualState.collToQuoteIndexPrice);
|
|
265
|
+
return maxPosition - positionRisk.positionNotionalBaseCCY;
|
|
266
|
+
}
|
|
178
267
|
/**
|
|
179
268
|
* Uses the Oracle(s) in the exchange to get the latest price of a given index in a given currency, if a route exists.
|
|
180
269
|
* @param {string} base Index name, e.g. ETH.
|
|
@@ -259,6 +348,47 @@ class MarketData extends perpetualDataHandler_1.default {
|
|
|
259
348
|
return yield perpetualDataHandler_1.default._queryPerpetualPrice(symbol, quantity, this.symbolToPerpStaticInfo, this.proxyContract);
|
|
260
349
|
});
|
|
261
350
|
}
|
|
351
|
+
/**
|
|
352
|
+
* Query recent perpetual state from blockchain
|
|
353
|
+
* @param symbol symbol of the form ETH-USD-MATIC
|
|
354
|
+
* @returns PerpetualState reference
|
|
355
|
+
*/
|
|
356
|
+
getPerpetualState(symbol) {
|
|
357
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
358
|
+
if (this.proxyContract == null) {
|
|
359
|
+
throw Error("no proxy contract initialized. Use createProxyInstance().");
|
|
360
|
+
}
|
|
361
|
+
let state = yield perpetualDataHandler_1.default._queryPerpetualState(symbol, this.symbolToPerpStaticInfo, this.proxyContract);
|
|
362
|
+
return state;
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* get the current mid-price for a perpetual
|
|
367
|
+
* @param symbol symbol of the form ETH-USD-MATIC
|
|
368
|
+
* @example
|
|
369
|
+
* import { MarketData, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
|
|
370
|
+
* async function main() {
|
|
371
|
+
* console.log(MarketData);
|
|
372
|
+
* // setup
|
|
373
|
+
* const config = PerpetualDataHandler.readSDKConfig("testnet");
|
|
374
|
+
* let mktData = new MarketData(config);
|
|
375
|
+
* await mktData.createProxyInstance();
|
|
376
|
+
* // get perpetual mid price
|
|
377
|
+
* let midPrice = await mktData.getPerpetualMidPrice("ETH-USD-MATIC");
|
|
378
|
+
* console.log(midPrice);
|
|
379
|
+
* }
|
|
380
|
+
* main();
|
|
381
|
+
*
|
|
382
|
+
* @returns {number} price
|
|
383
|
+
*/
|
|
384
|
+
getPerpetualMidPrice(symbol) {
|
|
385
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
386
|
+
if (this.proxyContract == null) {
|
|
387
|
+
throw Error("no proxy contract initialized. Use createProxyInstance().");
|
|
388
|
+
}
|
|
389
|
+
return yield this.getPerpetualPrice(symbol, 0);
|
|
390
|
+
});
|
|
391
|
+
}
|
|
262
392
|
/**
|
|
263
393
|
* Query smart contract to get user orders and convert to user friendly order format.
|
|
264
394
|
* @param {string} traderAddr Address of trader.
|
|
@@ -298,7 +428,7 @@ class MarketData extends perpetualDataHandler_1.default {
|
|
|
298
428
|
return digests;
|
|
299
429
|
});
|
|
300
430
|
}
|
|
301
|
-
static _exchangeInfo(_proxyContract) {
|
|
431
|
+
static _exchangeInfo(_proxyContract, _poolStaticInfos, _symbolList) {
|
|
302
432
|
return __awaiter(this, void 0, void 0, function* () {
|
|
303
433
|
let nestedPerpetualIDs = yield perpetualDataHandler_1.default.getNestedPerpetualIds(_proxyContract);
|
|
304
434
|
let factory = yield _proxyContract.getOracleFactory();
|
|
@@ -309,6 +439,7 @@ class MarketData extends perpetualDataHandler_1.default {
|
|
|
309
439
|
let pool = yield _proxyContract.getLiquidityPool(j + 1);
|
|
310
440
|
let PoolState = {
|
|
311
441
|
isRunning: pool.isRunning,
|
|
442
|
+
poolSymbol: _poolStaticInfos[j].poolMarginSymbol,
|
|
312
443
|
marginTokenAddr: pool.marginTokenAddress,
|
|
313
444
|
poolShareTokenAddr: pool.shareTokenAddress,
|
|
314
445
|
defaultFundCashCC: (0, d8XMath_1.ABK64x64ToFloat)(pool.fDefaultFundCashCC),
|
|
@@ -321,6 +452,7 @@ class MarketData extends perpetualDataHandler_1.default {
|
|
|
321
452
|
for (var k = 0; k < perpetualIDs.length; k++) {
|
|
322
453
|
let perp = yield _proxyContract.getPerpetual(perpetualIDs[k]);
|
|
323
454
|
let fIndexS2 = yield _proxyContract.getOraclePrice([perp.S2BaseCCY, perp.S2QuoteCCY]);
|
|
455
|
+
let fMidPrice = yield _proxyContract.queryPerpetualPrice(perpetualIDs[k], ethers_1.BigNumber.from(0));
|
|
324
456
|
let indexS2 = (0, d8XMath_1.ABK64x64ToFloat)(fIndexS2);
|
|
325
457
|
let indexS3 = 1;
|
|
326
458
|
if (perp.eCollateralCurrency == nodeSDKTypes_1.COLLATERAL_CURRENCY_BASE) {
|
|
@@ -335,11 +467,12 @@ class MarketData extends perpetualDataHandler_1.default {
|
|
|
335
467
|
let PerpetualState = {
|
|
336
468
|
id: perp.id,
|
|
337
469
|
state: state,
|
|
338
|
-
baseCurrency: (0, utils_1.
|
|
339
|
-
quoteCurrency: (0, utils_1.
|
|
470
|
+
baseCurrency: (0, utils_1.contractSymbolToSymbol)(perp.S2BaseCCY, _symbolList),
|
|
471
|
+
quoteCurrency: (0, utils_1.contractSymbolToSymbol)(perp.S2QuoteCCY, _symbolList),
|
|
340
472
|
indexPrice: indexS2,
|
|
341
473
|
collToQuoteIndexPrice: indexS3,
|
|
342
474
|
markPrice: indexS2 * (1 + markPremiumRate),
|
|
475
|
+
midPrice: (0, d8XMath_1.ABK64x64ToFloat)(fMidPrice),
|
|
343
476
|
currentFundingRateBps: currentFundingRateBps,
|
|
344
477
|
openInterestBC: (0, d8XMath_1.ABK64x64ToFloat)(perp.fOpenInterest),
|
|
345
478
|
maxPositionBC: (0, d8XMath_1.ABK64x64ToFloat)(perp.fMaxPositionBC),
|