@d8x/perpetuals-sdk 0.7.5 → 0.7.6
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/accountTrade.js +134 -239
- package/dist/cjs/accountTrade.js.map +1 -1
- package/dist/cjs/brokerTool.js +144 -290
- package/dist/cjs/brokerTool.js.map +1 -1
- package/dist/cjs/contracts/factories/ERC20__factory.js +9 -12
- package/dist/cjs/contracts/factories/ERC20__factory.js.map +1 -1
- package/dist/cjs/contracts/factories/IPerpetualManager__factory.js +9 -12
- package/dist/cjs/contracts/factories/IPerpetualManager__factory.js.map +1 -1
- package/dist/cjs/contracts/factories/LimitOrderBookFactory__factory.js +9 -12
- package/dist/cjs/contracts/factories/LimitOrderBookFactory__factory.js.map +1 -1
- package/dist/cjs/contracts/factories/LimitOrderBook__factory.js +9 -12
- package/dist/cjs/contracts/factories/LimitOrderBook__factory.js.map +1 -1
- package/dist/cjs/contracts/factories/MockTokenSwap__factory.js +9 -12
- package/dist/cjs/contracts/factories/MockTokenSwap__factory.js.map +1 -1
- package/dist/cjs/contracts/factories/ShareToken__factory.js +9 -12
- package/dist/cjs/contracts/factories/ShareToken__factory.js.map +1 -1
- package/dist/cjs/contracts/factories/zkevmTestnet/IPerpetualManager__factory.js +9 -12
- package/dist/cjs/contracts/factories/zkevmTestnet/IPerpetualManager__factory.js.map +1 -1
- package/dist/cjs/contracts/factories/zkevmTestnet/LimitOrderBookFactory__factory.js +9 -12
- package/dist/cjs/contracts/factories/zkevmTestnet/LimitOrderBookFactory__factory.js.map +1 -1
- package/dist/cjs/contracts/factories/zkevmTestnet/LimitOrderBook__factory.js +9 -12
- package/dist/cjs/contracts/factories/zkevmTestnet/LimitOrderBook__factory.js.map +1 -1
- package/dist/cjs/contracts/factories/zkevmTestnet/ShareToken__factory.js +9 -12
- package/dist/cjs/contracts/factories/zkevmTestnet/ShareToken__factory.js.map +1 -1
- package/dist/cjs/contracts/index.js +1 -1
- package/dist/cjs/d8XMath.d.ts +7 -0
- package/dist/cjs/d8XMath.js +81 -61
- package/dist/cjs/d8XMath.js.map +1 -1
- package/dist/cjs/index.js +11 -11
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/liquidatorTool.js +80 -137
- package/dist/cjs/liquidatorTool.js.map +1 -1
- package/dist/cjs/liquidityProviderTool.js +33 -64
- package/dist/cjs/liquidityProviderTool.js.map +1 -1
- package/dist/cjs/marketData.js +635 -978
- package/dist/cjs/marketData.js.map +1 -1
- package/dist/cjs/nodeSDKTypes.d.ts +1 -0
- package/dist/cjs/nodeSDKTypes.js +10 -22
- package/dist/cjs/nodeSDKTypes.js.map +1 -1
- package/dist/cjs/orderReferrerTool.js +200 -321
- package/dist/cjs/orderReferrerTool.js.map +1 -1
- package/dist/cjs/perpetualDataHandler.d.ts +11 -0
- package/dist/cjs/perpetualDataHandler.js +422 -535
- package/dist/cjs/perpetualDataHandler.js.map +1 -1
- package/dist/cjs/perpetualEventHandler.js +129 -190
- package/dist/cjs/perpetualEventHandler.js.map +1 -1
- package/dist/cjs/priceFeeds.js +223 -335
- package/dist/cjs/priceFeeds.js.map +1 -1
- package/dist/cjs/traderDigests.js +20 -23
- package/dist/cjs/traderDigests.js.map +1 -1
- package/dist/cjs/traderInterface.js +54 -87
- package/dist/cjs/traderInterface.js.map +1 -1
- package/dist/cjs/triangulator.js +34 -38
- package/dist/cjs/triangulator.js.map +1 -1
- package/dist/cjs/utils.js +18 -32
- package/dist/cjs/utils.js.map +1 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/cjs/writeAccessHandler.js +78 -112
- package/dist/cjs/writeAccessHandler.js.map +1 -1
- package/dist/esm/accountTrade.js +126 -233
- package/dist/esm/accountTrade.js.map +1 -1
- package/dist/esm/brokerTool.js +136 -284
- package/dist/esm/brokerTool.js.map +1 -1
- package/dist/esm/contracts/factories/ERC20__factory.js +8 -12
- package/dist/esm/contracts/factories/ERC20__factory.js.map +1 -1
- package/dist/esm/contracts/factories/IPerpetualManager__factory.js +8 -12
- package/dist/esm/contracts/factories/IPerpetualManager__factory.js.map +1 -1
- package/dist/esm/contracts/factories/LimitOrderBookFactory__factory.js +8 -12
- package/dist/esm/contracts/factories/LimitOrderBookFactory__factory.js.map +1 -1
- package/dist/esm/contracts/factories/LimitOrderBook__factory.js +8 -12
- package/dist/esm/contracts/factories/LimitOrderBook__factory.js.map +1 -1
- package/dist/esm/contracts/factories/MockTokenSwap__factory.js +8 -12
- package/dist/esm/contracts/factories/MockTokenSwap__factory.js.map +1 -1
- package/dist/esm/contracts/factories/ShareToken__factory.js +8 -12
- package/dist/esm/contracts/factories/ShareToken__factory.js.map +1 -1
- package/dist/esm/contracts/factories/zkevmTestnet/IPerpetualManager__factory.js +8 -12
- package/dist/esm/contracts/factories/zkevmTestnet/IPerpetualManager__factory.js.map +1 -1
- package/dist/esm/contracts/factories/zkevmTestnet/LimitOrderBookFactory__factory.js +8 -12
- package/dist/esm/contracts/factories/zkevmTestnet/LimitOrderBookFactory__factory.js.map +1 -1
- package/dist/esm/contracts/factories/zkevmTestnet/LimitOrderBook__factory.js +8 -12
- package/dist/esm/contracts/factories/zkevmTestnet/LimitOrderBook__factory.js.map +1 -1
- package/dist/esm/contracts/factories/zkevmTestnet/ShareToken__factory.js +8 -12
- package/dist/esm/contracts/factories/zkevmTestnet/ShareToken__factory.js.map +1 -1
- package/dist/esm/d8XMath.d.ts +7 -0
- package/dist/esm/d8XMath.js +77 -58
- package/dist/esm/d8XMath.js.map +1 -1
- package/dist/esm/liquidatorTool.js +77 -136
- package/dist/esm/liquidatorTool.js.map +1 -1
- package/dist/esm/liquidityProviderTool.js +30 -63
- package/dist/esm/liquidityProviderTool.js.map +1 -1
- package/dist/esm/marketData.js +626 -971
- package/dist/esm/marketData.js.map +1 -1
- package/dist/esm/nodeSDKTypes.d.ts +1 -0
- package/dist/esm/nodeSDKTypes.js +36 -48
- package/dist/esm/nodeSDKTypes.js.map +1 -1
- package/dist/esm/orderReferrerTool.js +194 -317
- package/dist/esm/orderReferrerTool.js.map +1 -1
- package/dist/esm/perpetualDataHandler.d.ts +11 -0
- package/dist/esm/perpetualDataHandler.js +413 -528
- package/dist/esm/perpetualDataHandler.js.map +1 -1
- package/dist/esm/perpetualEventHandler.js +126 -188
- package/dist/esm/perpetualEventHandler.js.map +1 -1
- package/dist/esm/priceFeeds.js +218 -332
- package/dist/esm/priceFeeds.js.map +1 -1
- package/dist/esm/traderDigests.js +15 -19
- package/dist/esm/traderDigests.js.map +1 -1
- package/dist/esm/traderInterface.js +48 -83
- package/dist/esm/traderInterface.js.map +1 -1
- package/dist/esm/triangulator.js +34 -39
- package/dist/esm/triangulator.js.map +1 -1
- package/dist/esm/utils.js +16 -30
- package/dist/esm/utils.js.map +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/version.js.map +1 -1
- package/dist/esm/writeAccessHandler.js +70 -106
- package/dist/esm/writeAccessHandler.js.map +1 -1
- package/package.json +1 -1
- package/src/d8XMath.ts +21 -0
- package/src/liquidityProviderTool.ts +5 -4
- package/src/nodeSDKTypes.ts +1 -0
- package/src/perpetualDataHandler.ts +27 -0
- package/src/version.ts +1 -1
- package/src/writeAccessHandler.ts +3 -3
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { __awaiter, __generator, __read, __values } from "tslib";
|
|
2
1
|
import { FormatTypes } from "@ethersproject/abi";
|
|
3
2
|
import { Signer } from "@ethersproject/abstract-signer";
|
|
4
3
|
import { BigNumber } from "@ethersproject/bignumber";
|
|
5
4
|
import { AddressZero } from "@ethersproject/constants";
|
|
6
|
-
import { IPerpetualManager__factory, LimitOrderBookFactory__factory, LimitOrderBook__factory, } from "./contracts";
|
|
5
|
+
import { ERC20__factory, IPerpetualManager__factory, LimitOrderBookFactory__factory, LimitOrderBook__factory, } from "./contracts";
|
|
7
6
|
import { ABDK29ToFloat, ABK64x64ToFloat, calculateLiquidationPriceCollateralBase, calculateLiquidationPriceCollateralQuanto, calculateLiquidationPriceCollateralQuote, div64x64, floatToABK64x64, } from "./d8XMath";
|
|
8
7
|
import { BUY_SIDE, CLOSED_SIDE, COLLATERAL_CURRENCY_BASE, COLLATERAL_CURRENCY_QUOTE, CollaterlCCY, DEFAULT_CONFIG, loadABIs, MASK_CLOSE_ONLY, MASK_KEEP_POS_LEVERAGE, MASK_LIMIT_ORDER, MASK_MARKET_ORDER, MASK_STOP_ORDER, MAX_64x64, ORDER_MAX_DURATION_SEC, ORDER_TYPE_LIMIT, ORDER_TYPE_MARKET, ORDER_TYPE_STOP_LIMIT, ORDER_TYPE_STOP_MARKET, PERP_STATE_STR, SELL_SIDE, SYMBOL_LIST, ZERO_ADDRESS, ZERO_ORDER_ID, } from "./nodeSDKTypes";
|
|
9
8
|
import PriceFeeds from "./priceFeeds";
|
|
@@ -12,8 +11,8 @@ import { combineFlags, containsFlag, contractSymbolToSymbol, symbol4BToLongSymbo
|
|
|
12
11
|
* Parent class for MarketData and WriteAccessHandler that handles
|
|
13
12
|
* common data and chain operations.
|
|
14
13
|
*/
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
export default class PerpetualDataHandler {
|
|
15
|
+
constructor(config) {
|
|
17
16
|
this.PRICE_UPDATE_FEE_GWEI = 1;
|
|
18
17
|
this.proxyContract = null;
|
|
19
18
|
// limit order book
|
|
@@ -35,216 +34,168 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
35
34
|
this.symbolList = SYMBOL_LIST;
|
|
36
35
|
this.priceFeedGetter = new PriceFeeds(this, config.priceFeedConfigNetwork);
|
|
37
36
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
case 7:
|
|
63
|
-
if (network.chainId !== this.chainId) {
|
|
64
|
-
throw new Error("Provider: chain id ".concat(network.chainId, " does not match config (").concat(this.chainId, ")"));
|
|
65
|
-
}
|
|
66
|
-
this.proxyContract = IPerpetualManager__factory.connect(this.proxyAddr, signerOrProvider);
|
|
67
|
-
_a = this;
|
|
68
|
-
return [4 /*yield*/, this.proxyContract.getOrderBookFactoryAddress(overrides || {})];
|
|
69
|
-
case 8:
|
|
70
|
-
_a.lobFactoryAddr = _b.sent();
|
|
71
|
-
this.lobFactoryContract = LimitOrderBookFactory__factory.connect(this.lobFactoryAddr, signerOrProvider);
|
|
72
|
-
return [4 /*yield*/, this._fillSymbolMaps(overrides)];
|
|
73
|
-
case 9:
|
|
74
|
-
_b.sent();
|
|
75
|
-
return [2 /*return*/];
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
};
|
|
37
|
+
async initContractsAndData(signerOrProvider, overrides) {
|
|
38
|
+
this.signerOrProvider = signerOrProvider;
|
|
39
|
+
// check network
|
|
40
|
+
let network;
|
|
41
|
+
try {
|
|
42
|
+
if (signerOrProvider instanceof Signer) {
|
|
43
|
+
network = await signerOrProvider.provider.getNetwork();
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
network = await signerOrProvider.getNetwork();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
console.log(error);
|
|
51
|
+
throw new Error(`Unable to connect to network.`);
|
|
52
|
+
}
|
|
53
|
+
if (network.chainId !== this.chainId) {
|
|
54
|
+
throw new Error(`Provider: chain id ${network.chainId} does not match config (${this.chainId})`);
|
|
55
|
+
}
|
|
56
|
+
this.proxyContract = IPerpetualManager__factory.connect(this.proxyAddr, signerOrProvider);
|
|
57
|
+
this.lobFactoryAddr = await this.proxyContract.getOrderBookFactoryAddress(overrides || {});
|
|
58
|
+
this.lobFactoryContract = LimitOrderBookFactory__factory.connect(this.lobFactoryAddr, signerOrProvider);
|
|
59
|
+
await this._fillSymbolMaps(overrides);
|
|
60
|
+
}
|
|
80
61
|
/**
|
|
81
62
|
* Returns the order-book contract for the symbol if found or fails
|
|
82
63
|
* @param symbol symbol of the form ETH-USD-MATIC
|
|
83
64
|
* @returns order book contract for the perpetual
|
|
84
65
|
*/
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
var orderBookAddr = (_a = this.symbolToPerpStaticInfo.get(symbol)) === null || _a === void 0 ? void 0 : _a.limitOrderBookAddr;
|
|
66
|
+
getOrderBookContract(symbol) {
|
|
67
|
+
let orderBookAddr = this.symbolToPerpStaticInfo.get(symbol)?.limitOrderBookAddr;
|
|
88
68
|
if (orderBookAddr == "" || orderBookAddr == undefined || this.signerOrProvider == null) {
|
|
89
|
-
throw Error(
|
|
69
|
+
throw Error(`no limit order book found for ${symbol} or no signer`);
|
|
90
70
|
}
|
|
91
|
-
|
|
71
|
+
let lobContract = LimitOrderBook__factory.connect(orderBookAddr, this.signerOrProvider);
|
|
92
72
|
return lobContract;
|
|
93
|
-
}
|
|
73
|
+
}
|
|
94
74
|
/**
|
|
95
75
|
* Called when initializing. This function fills this.symbolToTokenAddrMap,
|
|
96
76
|
* and this.nestedPerpetualIDs and this.symbolToPerpStaticInfo
|
|
97
77
|
*
|
|
98
78
|
*/
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
if (poolCCY == "") {
|
|
139
|
-
_a = __read(perp.S2Symbol.split("-"), 2), base = _a[0], quote = _a[1];
|
|
140
|
-
base3 = perp.S3Symbol.split("-")[0];
|
|
141
|
-
// we find out the pool currency by looking at all perpetuals
|
|
142
|
-
// from the perpetual.
|
|
143
|
-
if (perp.collateralCurrencyType == COLLATERAL_CURRENCY_BASE) {
|
|
144
|
-
poolCCY = base;
|
|
145
|
-
}
|
|
146
|
-
else if (perp.collateralCurrencyType == COLLATERAL_CURRENCY_QUOTE) {
|
|
147
|
-
poolCCY = quote;
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
poolCCY = base3;
|
|
151
|
-
}
|
|
152
|
-
// set pool currency
|
|
153
|
-
this.poolStaticInfos[perp.poolId - 1].poolMarginSymbol = poolCCY;
|
|
154
|
-
// push pool margin token address into map
|
|
155
|
-
this.symbolToTokenAddrMap.set(poolCCY, this.poolStaticInfos[perp.poolId - 1].poolMarginTokenAddr);
|
|
156
|
-
}
|
|
157
|
-
currentSymbol3 = perp.S2Symbol + "-" + poolCCY;
|
|
158
|
-
this.symbolToPerpStaticInfo.set(currentSymbol3, perpStaticInfos[j]);
|
|
159
|
-
}
|
|
160
|
-
// pre-calculate all triangulation paths so we can easily get from
|
|
161
|
-
// the prices of price-feeds to the index price required, e.g.
|
|
162
|
-
// BTC-USDC : BTC-USD / USDC-USD
|
|
163
|
-
this.priceFeedGetter.initializeTriangulations(requiredPairs);
|
|
164
|
-
try {
|
|
165
|
-
// fill this.perpetualIdToSymbol
|
|
166
|
-
for (_b = __values(this.symbolToPerpStaticInfo), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
167
|
-
_d = __read(_c.value, 2), key = _d[0], info = _d[1];
|
|
168
|
-
this.perpetualIdToSymbol.set(info.id, key);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
172
|
-
finally {
|
|
173
|
-
try {
|
|
174
|
-
if (_c && !_c.done && (_e = _b.return)) _e.call(_b);
|
|
175
|
-
}
|
|
176
|
-
finally { if (e_1) throw e_1.error; }
|
|
177
|
-
}
|
|
178
|
-
return [2 /*return*/];
|
|
79
|
+
async _fillSymbolMaps(overrides) {
|
|
80
|
+
if (!this.proxyContract || !this.lobFactoryContract) {
|
|
81
|
+
throw Error("proxy or limit order book not defined");
|
|
82
|
+
}
|
|
83
|
+
let poolInfo = await PerpetualDataHandler.getPoolStaticInfo(this.proxyContract, overrides);
|
|
84
|
+
this.nestedPerpetualIDs = poolInfo.nestedPerpetualIDs;
|
|
85
|
+
for (let j = 0; j < poolInfo.nestedPerpetualIDs.length; j++) {
|
|
86
|
+
let decimals = await ERC20__factory.connect(poolInfo.poolMarginTokenAddr[j], this.provider).decimals();
|
|
87
|
+
let info = {
|
|
88
|
+
poolId: j + 1,
|
|
89
|
+
poolMarginSymbol: "",
|
|
90
|
+
poolMarginTokenAddr: poolInfo.poolMarginTokenAddr[j],
|
|
91
|
+
poolMarginTokenDecimals: decimals,
|
|
92
|
+
shareTokenAddr: poolInfo.poolShareTokenAddr[j],
|
|
93
|
+
oracleFactoryAddr: poolInfo.oracleFactory,
|
|
94
|
+
isRunning: poolInfo.poolShareTokenAddr[j] != AddressZero,
|
|
95
|
+
};
|
|
96
|
+
this.poolStaticInfos.push(info);
|
|
97
|
+
}
|
|
98
|
+
let perpStaticInfos = await PerpetualDataHandler.getPerpetualStaticInfo(this.proxyContract, this.nestedPerpetualIDs, this.symbolList, overrides);
|
|
99
|
+
let requiredPairs = new Set();
|
|
100
|
+
// 1) determine pool currency based on its perpetuals
|
|
101
|
+
// 2) determine which triangulations we need
|
|
102
|
+
// 3) fill mapping this.symbolToPerpStaticInf
|
|
103
|
+
for (let j = 0; j < perpStaticInfos.length; j++) {
|
|
104
|
+
const perp = perpStaticInfos[j];
|
|
105
|
+
requiredPairs.add(perp.S2Symbol);
|
|
106
|
+
if (perp.S3Symbol != "") {
|
|
107
|
+
requiredPairs.add(perp.S3Symbol);
|
|
108
|
+
}
|
|
109
|
+
let poolCCY = this.poolStaticInfos[perp.poolId - 1].poolMarginSymbol;
|
|
110
|
+
if (poolCCY == "") {
|
|
111
|
+
//not already filled
|
|
112
|
+
const [base, quote] = perp.S2Symbol.split("-");
|
|
113
|
+
const base3 = perp.S3Symbol.split("-")[0];
|
|
114
|
+
// we find out the pool currency by looking at all perpetuals
|
|
115
|
+
// from the perpetual.
|
|
116
|
+
if (perp.collateralCurrencyType == COLLATERAL_CURRENCY_BASE) {
|
|
117
|
+
poolCCY = base;
|
|
179
118
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
119
|
+
else if (perp.collateralCurrencyType == COLLATERAL_CURRENCY_QUOTE) {
|
|
120
|
+
poolCCY = quote;
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
poolCCY = base3;
|
|
124
|
+
}
|
|
125
|
+
// set pool currency
|
|
126
|
+
this.poolStaticInfos[perp.poolId - 1].poolMarginSymbol = poolCCY;
|
|
127
|
+
// push pool margin token address into map
|
|
128
|
+
this.symbolToTokenAddrMap.set(poolCCY, this.poolStaticInfos[perp.poolId - 1].poolMarginTokenAddr);
|
|
129
|
+
}
|
|
130
|
+
let currentSymbol3 = perp.S2Symbol + "-" + poolCCY;
|
|
131
|
+
this.symbolToPerpStaticInfo.set(currentSymbol3, perpStaticInfos[j]);
|
|
132
|
+
}
|
|
133
|
+
// pre-calculate all triangulation paths so we can easily get from
|
|
134
|
+
// the prices of price-feeds to the index price required, e.g.
|
|
135
|
+
// BTC-USDC : BTC-USD / USDC-USD
|
|
136
|
+
this.priceFeedGetter.initializeTriangulations(requiredPairs);
|
|
137
|
+
// fill this.perpetualIdToSymbol
|
|
138
|
+
for (let [key, info] of this.symbolToPerpStaticInfo) {
|
|
139
|
+
this.perpetualIdToSymbol.set(info.id, key);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
183
142
|
/**
|
|
184
143
|
* Get pool symbol given a pool Id.
|
|
185
144
|
* @param {number} poolId Pool Id.
|
|
186
145
|
* @returns {symbol} Pool symbol, e.g. "USDC".
|
|
187
146
|
*/
|
|
188
|
-
|
|
147
|
+
getSymbolFromPoolId(poolId) {
|
|
189
148
|
return PerpetualDataHandler._getSymbolFromPoolId(poolId, this.poolStaticInfos);
|
|
190
|
-
}
|
|
149
|
+
}
|
|
191
150
|
/**
|
|
192
151
|
* Get pool Id given a pool symbol. Pool IDs start at 1.
|
|
193
152
|
* @param {string} symbol Pool symbol.
|
|
194
153
|
* @returns {number} Pool Id.
|
|
195
154
|
*/
|
|
196
|
-
|
|
155
|
+
getPoolIdFromSymbol(symbol) {
|
|
197
156
|
return PerpetualDataHandler._getPoolIdFromSymbol(symbol, this.poolStaticInfos);
|
|
198
|
-
}
|
|
157
|
+
}
|
|
199
158
|
/**
|
|
200
159
|
* Get perpetual Id given a perpetual symbol.
|
|
201
160
|
* @param {string} symbol Perpetual symbol, e.g. "BTC-USD-MATIC".
|
|
202
161
|
* @returns {number} Perpetual Id.
|
|
203
162
|
*/
|
|
204
|
-
|
|
163
|
+
getPerpIdFromSymbol(symbol) {
|
|
205
164
|
return PerpetualDataHandler.symbolToPerpetualId(symbol, this.symbolToPerpStaticInfo);
|
|
206
|
-
}
|
|
165
|
+
}
|
|
207
166
|
/**
|
|
208
167
|
* Get the symbol in long format of the perpetual id
|
|
209
168
|
* @param perpId perpetual id
|
|
210
169
|
*/
|
|
211
|
-
|
|
170
|
+
getSymbolFromPerpId(perpId) {
|
|
212
171
|
return this.perpetualIdToSymbol.get(perpId);
|
|
213
|
-
}
|
|
214
|
-
|
|
172
|
+
}
|
|
173
|
+
symbol4BToLongSymbol(sym) {
|
|
215
174
|
return symbol4BToLongSymbol(sym, this.symbolList);
|
|
216
|
-
}
|
|
175
|
+
}
|
|
217
176
|
/**
|
|
218
177
|
* Get PriceFeedSubmission data required for blockchain queries that involve price data, and the corresponding
|
|
219
178
|
* triangulated prices for the indices S2 and S3
|
|
220
179
|
* @param symbol pool symbol of the form "ETH-USD-MATIC"
|
|
221
180
|
* @returns PriceFeedSubmission and prices for S2 and S3. [S2price, 0] if S3 not defined.
|
|
222
181
|
*/
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
case 0: return [4 /*yield*/, this.priceFeedGetter.fetchFeedPriceInfoAndIndicesForPerpetual(symbol)];
|
|
228
|
-
case 1:
|
|
229
|
-
// fetch prices from required price-feeds (REST)
|
|
230
|
-
return [2 /*return*/, _a.sent()];
|
|
231
|
-
}
|
|
232
|
-
});
|
|
233
|
-
});
|
|
234
|
-
};
|
|
182
|
+
async fetchPriceSubmissionInfoForPerpetual(symbol) {
|
|
183
|
+
// fetch prices from required price-feeds (REST)
|
|
184
|
+
return await this.priceFeedGetter.fetchFeedPriceInfoAndIndicesForPerpetual(symbol);
|
|
185
|
+
}
|
|
235
186
|
/**
|
|
236
187
|
* Get the symbols required as indices for the given perpetual
|
|
237
188
|
* @param symbol of the form ETH-USD-MATIC, specifying the perpetual
|
|
238
189
|
* @returns name of underlying index prices, e.g. ["MATIC-USD", ""]
|
|
239
190
|
*/
|
|
240
|
-
|
|
191
|
+
getIndexSymbols(symbol) {
|
|
241
192
|
// get index
|
|
242
|
-
|
|
193
|
+
let staticInfo = this.symbolToPerpStaticInfo.get(symbol);
|
|
243
194
|
if (staticInfo == undefined) {
|
|
244
|
-
throw new Error(
|
|
195
|
+
throw new Error(`No static info for perpetual with symbol ${symbol}`);
|
|
245
196
|
}
|
|
246
197
|
return [staticInfo.S2Symbol, staticInfo.S3Symbol];
|
|
247
|
-
}
|
|
198
|
+
}
|
|
248
199
|
/**
|
|
249
200
|
* Get the latest prices for a given perpetual from the offchain oracle
|
|
250
201
|
* networks
|
|
@@ -252,68 +203,60 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
252
203
|
* @returns array of price feed updates that can be submitted to the smart contract
|
|
253
204
|
* and corresponding price information
|
|
254
205
|
*/
|
|
255
|
-
|
|
256
|
-
return
|
|
257
|
-
|
|
258
|
-
switch (_a.label) {
|
|
259
|
-
case 0: return [4 /*yield*/, this.priceFeedGetter.fetchLatestFeedPriceInfoForPerpetual(symbol)];
|
|
260
|
-
case 1: return [2 /*return*/, _a.sent()];
|
|
261
|
-
}
|
|
262
|
-
});
|
|
263
|
-
});
|
|
264
|
-
};
|
|
206
|
+
async fetchLatestFeedPriceInfo(symbol) {
|
|
207
|
+
return await this.priceFeedGetter.fetchLatestFeedPriceInfoForPerpetual(symbol);
|
|
208
|
+
}
|
|
265
209
|
/**
|
|
266
210
|
* Get list of required pyth price source IDs for given perpetual
|
|
267
211
|
* @param symbol perpetual symbol, e.g., BTC-USD-MATIC
|
|
268
212
|
* @returns list of required pyth price sources for this perpetual
|
|
269
213
|
*/
|
|
270
|
-
|
|
271
|
-
|
|
214
|
+
getPriceIds(symbol) {
|
|
215
|
+
let perpInfo = this.symbolToPerpStaticInfo.get(symbol);
|
|
272
216
|
if (perpInfo == undefined) {
|
|
273
|
-
throw Error(
|
|
217
|
+
throw Error(`Perpetual with symbol ${symbol} not found. Check symbol or use createProxyInstance().`);
|
|
274
218
|
}
|
|
275
219
|
return perpInfo.priceIds;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
|
|
220
|
+
}
|
|
221
|
+
static _getSymbolFromPoolId(poolId, staticInfos) {
|
|
222
|
+
let idx = poolId - 1;
|
|
279
223
|
return staticInfos[idx].poolMarginSymbol;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
|
|
224
|
+
}
|
|
225
|
+
static _getPoolIdFromSymbol(symbol, staticInfos) {
|
|
226
|
+
let symbols = symbol.split("-");
|
|
283
227
|
//in case user provided ETH-USD-MATIC instead of MATIC; or similar
|
|
284
228
|
if (symbols.length == 3) {
|
|
285
229
|
symbol = symbols[2];
|
|
286
230
|
}
|
|
287
|
-
|
|
231
|
+
let j = 0;
|
|
288
232
|
while (j < staticInfos.length && staticInfos[j].poolMarginSymbol != symbol) {
|
|
289
233
|
j++;
|
|
290
234
|
}
|
|
291
235
|
if (j == staticInfos.length) {
|
|
292
|
-
throw new Error(
|
|
236
|
+
throw new Error(`no pool found for symbol ${symbol}`);
|
|
293
237
|
}
|
|
294
238
|
return j + 1;
|
|
295
|
-
}
|
|
239
|
+
}
|
|
296
240
|
/**
|
|
297
241
|
* Get perpetual symbols for a given pool
|
|
298
242
|
* @param poolSymbol pool symbol such as "MATIC"
|
|
299
243
|
* @returns array of perpetual symbols in this pool
|
|
300
244
|
*/
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
var s = _this.getSymbolFromPerpId(k);
|
|
245
|
+
getPerpetualSymbolsInPool(poolSymbol) {
|
|
246
|
+
const j = PerpetualDataHandler._getPoolIdFromSymbol(poolSymbol, this.poolStaticInfos);
|
|
247
|
+
const perpIds = this.nestedPerpetualIDs[j - 1];
|
|
248
|
+
const perpSymbols = perpIds.map((k) => {
|
|
249
|
+
let s = this.getSymbolFromPerpId(k);
|
|
307
250
|
if (s == undefined) {
|
|
308
251
|
return "";
|
|
309
252
|
}
|
|
310
253
|
return s;
|
|
311
254
|
});
|
|
312
255
|
return perpSymbols;
|
|
313
|
-
}
|
|
314
|
-
|
|
256
|
+
}
|
|
257
|
+
getNestedPerpetualIds() {
|
|
315
258
|
return this.nestedPerpetualIDs;
|
|
316
|
-
}
|
|
259
|
+
}
|
|
317
260
|
/**
|
|
318
261
|
* Collect all perpetuals static info
|
|
319
262
|
* @param {ethers.Contract} _proxyContract perpetuals contract with getter
|
|
@@ -321,65 +264,51 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
321
264
|
* @param {Map<string, string>} symbolList mapping of symbols to convert long-format <-> blockchain-format
|
|
322
265
|
* @returns array with PerpetualStaticInfo for each perpetual
|
|
323
266
|
*/
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
referralRebate: ABK64x64ToFloat(perpInfos[j].fReferralRebateCC),
|
|
358
|
-
priceIds: perpInfos[j].priceIds,
|
|
359
|
-
};
|
|
360
|
-
infoArr.push(info);
|
|
361
|
-
}
|
|
362
|
-
_a.label = 3;
|
|
363
|
-
case 3:
|
|
364
|
-
k++;
|
|
365
|
-
return [3 /*break*/, 1];
|
|
366
|
-
case 4: return [2 /*return*/, infoArr];
|
|
367
|
-
}
|
|
368
|
-
});
|
|
369
|
-
});
|
|
370
|
-
};
|
|
267
|
+
static async getPerpetualStaticInfo(_proxyContract, nestedPerpetualIDs, symbolList, overrides) {
|
|
268
|
+
// flatten perpetual ids into chunks
|
|
269
|
+
const chunkSize = 10;
|
|
270
|
+
let ids = PerpetualDataHandler.nestedIDsToChunks(chunkSize, nestedPerpetualIDs);
|
|
271
|
+
// query blockchain in chunks
|
|
272
|
+
const infoArr = new Array();
|
|
273
|
+
for (let k = 0; k < ids.length; k++) {
|
|
274
|
+
let perpInfos = await _proxyContract.getPerpetualStaticInfo(ids[k], overrides || {});
|
|
275
|
+
for (let j = 0; j < perpInfos.length; j++) {
|
|
276
|
+
let base = contractSymbolToSymbol(perpInfos[j].S2BaseCCY, symbolList);
|
|
277
|
+
let quote = contractSymbolToSymbol(perpInfos[j].S2QuoteCCY, symbolList);
|
|
278
|
+
let base3 = contractSymbolToSymbol(perpInfos[j].S3BaseCCY, symbolList);
|
|
279
|
+
let quote3 = contractSymbolToSymbol(perpInfos[j].S3QuoteCCY, symbolList);
|
|
280
|
+
let sym2 = base + "-" + quote;
|
|
281
|
+
let sym3 = base3 == "" ? "" : base3 + "-" + quote3;
|
|
282
|
+
let info = {
|
|
283
|
+
id: perpInfos[j].id,
|
|
284
|
+
poolId: Math.floor(perpInfos[j].id / 100000),
|
|
285
|
+
limitOrderBookAddr: perpInfos[j].limitOrderBookAddr,
|
|
286
|
+
initialMarginRate: ABDK29ToFloat(perpInfos[j].fInitialMarginRate),
|
|
287
|
+
maintenanceMarginRate: ABDK29ToFloat(perpInfos[j].fMaintenanceMarginRate),
|
|
288
|
+
collateralCurrencyType: perpInfos[j].collCurrencyType,
|
|
289
|
+
S2Symbol: sym2,
|
|
290
|
+
S3Symbol: sym3,
|
|
291
|
+
lotSizeBC: ABK64x64ToFloat(perpInfos[j].fLotSizeBC),
|
|
292
|
+
referralRebate: ABK64x64ToFloat(perpInfos[j].fReferralRebateCC),
|
|
293
|
+
priceIds: perpInfos[j].priceIds,
|
|
294
|
+
};
|
|
295
|
+
infoArr.push(info);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return infoArr;
|
|
299
|
+
}
|
|
371
300
|
/**
|
|
372
301
|
* Breaks up an array of nested arrays into chunks of a specified size.
|
|
373
302
|
* @param {number} chunkSize The size of each chunk.
|
|
374
303
|
* @param {number[][]} nestedIDs The array of nested arrays to chunk.
|
|
375
304
|
* @returns {number[][]} An array of subarrays, each containing `chunkSize` or fewer elements from `nestedIDs`.
|
|
376
305
|
*/
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
for (
|
|
381
|
-
|
|
382
|
-
for (
|
|
306
|
+
static nestedIDsToChunks(chunkSize, nestedIDs) {
|
|
307
|
+
const chunkIDs = [];
|
|
308
|
+
let currentChunk = [];
|
|
309
|
+
for (let k = 0; k < nestedIDs.length; k++) {
|
|
310
|
+
const currentPoolIds = nestedIDs[k];
|
|
311
|
+
for (let j = 0; j < currentPoolIds.length; j++) {
|
|
383
312
|
currentChunk.push(currentPoolIds[j]);
|
|
384
313
|
if (currentChunk.length === chunkSize) {
|
|
385
314
|
chunkIDs.push(currentChunk);
|
|
@@ -391,61 +320,48 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
391
320
|
chunkIDs.push(currentChunk);
|
|
392
321
|
}
|
|
393
322
|
return chunkIDs;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
});
|
|
430
|
-
};
|
|
431
|
-
PerpetualDataHandler.buildMarginAccountFromState = function (symbol, traderState, symbolToPerpStaticInfo, _pxS2S3) {
|
|
432
|
-
var _a;
|
|
433
|
-
var idx_cash = 3;
|
|
434
|
-
var idx_notional = 4;
|
|
435
|
-
var idx_locked_in = 5;
|
|
436
|
-
var idx_mark_price = 8;
|
|
437
|
-
var idx_lvg = 7;
|
|
438
|
-
var idx_s3 = 9;
|
|
439
|
-
var isEmpty = traderState[idx_notional].eq(0);
|
|
440
|
-
var cash = ABK64x64ToFloat(traderState[idx_cash]);
|
|
441
|
-
var S2Liq = 0, S3Liq = 0, tau = Infinity, pnl = 0, unpaidFundingCC = 0, fLockedIn = BigNumber.from(0), side = CLOSED_SIDE, entryPrice = 0;
|
|
323
|
+
}
|
|
324
|
+
static async getPoolStaticInfo(_proxyContract, overrides) {
|
|
325
|
+
let idxFrom = 1;
|
|
326
|
+
const len = 10;
|
|
327
|
+
let lenReceived = 10;
|
|
328
|
+
let nestedPerpetualIDs = [];
|
|
329
|
+
let poolShareTokenAddr = [];
|
|
330
|
+
let poolMarginTokenAddr = [];
|
|
331
|
+
let oracleFactory = "";
|
|
332
|
+
while (lenReceived == len) {
|
|
333
|
+
let res = await _proxyContract.getPoolStaticInfo(idxFrom, idxFrom + len - 1, overrides || {});
|
|
334
|
+
lenReceived = res.length;
|
|
335
|
+
nestedPerpetualIDs = nestedPerpetualIDs.concat(res[0]);
|
|
336
|
+
poolShareTokenAddr = res[1];
|
|
337
|
+
poolMarginTokenAddr = res[2];
|
|
338
|
+
oracleFactory = res[3];
|
|
339
|
+
idxFrom = idxFrom + len;
|
|
340
|
+
}
|
|
341
|
+
return {
|
|
342
|
+
nestedPerpetualIDs: nestedPerpetualIDs,
|
|
343
|
+
poolShareTokenAddr: poolShareTokenAddr,
|
|
344
|
+
poolMarginTokenAddr: poolMarginTokenAddr,
|
|
345
|
+
oracleFactory: oracleFactory,
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
static buildMarginAccountFromState(symbol, traderState, symbolToPerpStaticInfo, _pxS2S3) {
|
|
349
|
+
const idx_cash = 3;
|
|
350
|
+
const idx_notional = 4;
|
|
351
|
+
const idx_locked_in = 5;
|
|
352
|
+
const idx_mark_price = 8;
|
|
353
|
+
const idx_lvg = 7;
|
|
354
|
+
const idx_s3 = 9;
|
|
355
|
+
let isEmpty = traderState[idx_notional].eq(0);
|
|
356
|
+
let cash = ABK64x64ToFloat(traderState[idx_cash]);
|
|
357
|
+
let S2Liq = 0, S3Liq = 0, tau = Infinity, pnl = 0, unpaidFundingCC = 0, fLockedIn = BigNumber.from(0), side = CLOSED_SIDE, entryPrice = 0;
|
|
442
358
|
if (!isEmpty) {
|
|
443
|
-
|
|
359
|
+
[S2Liq, S3Liq, tau, pnl, unpaidFundingCC] = PerpetualDataHandler._calculateLiquidationPrice(symbol, traderState, _pxS2S3[0], symbolToPerpStaticInfo);
|
|
444
360
|
fLockedIn = traderState[idx_locked_in];
|
|
445
361
|
side = traderState[idx_locked_in].gt(0) ? BUY_SIDE : SELL_SIDE;
|
|
446
362
|
entryPrice = ABK64x64ToFloat(div64x64(fLockedIn, traderState[idx_notional]));
|
|
447
363
|
}
|
|
448
|
-
|
|
364
|
+
let mgn = {
|
|
449
365
|
symbol: symbol,
|
|
450
366
|
positionNotionalBaseCCY: isEmpty ? 0 : ABK64x64ToFloat(traderState[idx_notional].abs()),
|
|
451
367
|
side: isEmpty ? CLOSED_SIDE : side,
|
|
@@ -460,96 +376,56 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
460
376
|
collToQuoteConversion: ABK64x64ToFloat(traderState[idx_s3]),
|
|
461
377
|
};
|
|
462
378
|
return mgn;
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
return
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
});
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
});
|
|
514
|
-
};
|
|
515
|
-
PerpetualDataHandler._queryPerpetualState = function (symbol, symbolToPerpStaticInfo, _proxyContract, indexPrices, overrides) {
|
|
516
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
517
|
-
var perpId, staticInfo, ccy, _a, S2, S3, ammState, markPrice, state;
|
|
518
|
-
return __generator(this, function (_b) {
|
|
519
|
-
switch (_b.label) {
|
|
520
|
-
case 0:
|
|
521
|
-
perpId = PerpetualDataHandler.symbolToPerpetualId(symbol, symbolToPerpStaticInfo);
|
|
522
|
-
staticInfo = symbolToPerpStaticInfo.get(symbol);
|
|
523
|
-
ccy = symbol.split("-");
|
|
524
|
-
_a = __read([indexPrices[0], indexPrices[1]], 2), S2 = _a[0], S3 = _a[1];
|
|
525
|
-
if (staticInfo.collateralCurrencyType == CollaterlCCY.BASE) {
|
|
526
|
-
S3 = S2;
|
|
527
|
-
}
|
|
528
|
-
else if (staticInfo.collateralCurrencyType == CollaterlCCY.QUOTE) {
|
|
529
|
-
S3 = 1;
|
|
530
|
-
}
|
|
531
|
-
return [4 /*yield*/, _proxyContract.getAMMState(perpId, [S2, S3].map(floatToABK64x64), overrides || {})];
|
|
532
|
-
case 1:
|
|
533
|
-
ammState = _b.sent();
|
|
534
|
-
markPrice = S2 * (1 + ABK64x64ToFloat(ammState[8]));
|
|
535
|
-
state = {
|
|
536
|
-
id: perpId,
|
|
537
|
-
state: PERP_STATE_STR[ammState[13].toNumber()],
|
|
538
|
-
baseCurrency: ccy[0],
|
|
539
|
-
quoteCurrency: ccy[1],
|
|
540
|
-
indexPrice: S2,
|
|
541
|
-
collToQuoteIndexPrice: S3,
|
|
542
|
-
markPrice: markPrice,
|
|
543
|
-
midPrice: ABK64x64ToFloat(ammState[10]),
|
|
544
|
-
currentFundingRateBps: ABK64x64ToFloat(ammState[14]) * 1e4,
|
|
545
|
-
openInterestBC: ABK64x64ToFloat(ammState[11]),
|
|
546
|
-
isMarketClosed: indexPrices[2] || indexPrices[3],
|
|
547
|
-
};
|
|
548
|
-
return [2 /*return*/, state];
|
|
549
|
-
}
|
|
550
|
-
});
|
|
551
|
-
});
|
|
552
|
-
};
|
|
379
|
+
}
|
|
380
|
+
static async getMarginAccount(traderAddr, symbol, symbolToPerpStaticInfo, _proxyContract, _pxS2S3, overrides) {
|
|
381
|
+
let perpId = Number(symbol);
|
|
382
|
+
if (isNaN(perpId)) {
|
|
383
|
+
perpId = PerpetualDataHandler.symbolToPerpetualId(symbol, symbolToPerpStaticInfo);
|
|
384
|
+
}
|
|
385
|
+
let traderState = await _proxyContract.getTraderState(perpId, traderAddr, _pxS2S3.map((x) => floatToABK64x64(x)), overrides || {});
|
|
386
|
+
return PerpetualDataHandler.buildMarginAccountFromState(symbol, traderState, symbolToPerpStaticInfo, _pxS2S3);
|
|
387
|
+
}
|
|
388
|
+
static async _queryPerpetualPrice(symbol, tradeAmount, symbolToPerpStaticInfo, _proxyContract, indexPrices, overrides) {
|
|
389
|
+
let perpId = PerpetualDataHandler.symbolToPerpetualId(symbol, symbolToPerpStaticInfo);
|
|
390
|
+
let fIndexPrices = indexPrices.map((x) => floatToABK64x64(x == undefined || Number.isNaN(x) ? 0 : x));
|
|
391
|
+
let fPrice = await _proxyContract.queryPerpetualPrice(perpId, floatToABK64x64(tradeAmount), fIndexPrices, overrides || {});
|
|
392
|
+
return ABK64x64ToFloat(fPrice);
|
|
393
|
+
}
|
|
394
|
+
static async _queryPerpetualMarkPrice(symbol, symbolToPerpStaticInfo, _proxyContract, indexPrices, overrides) {
|
|
395
|
+
let perpId = PerpetualDataHandler.symbolToPerpetualId(symbol, symbolToPerpStaticInfo);
|
|
396
|
+
let [S2, S3] = indexPrices.map((x) => floatToABK64x64(x == undefined || Number.isNaN(x) ? 0 : x));
|
|
397
|
+
let ammState = await _proxyContract.getAMMState(perpId, [S2, S3], overrides || {});
|
|
398
|
+
// ammState[6] == S2 == indexPrices[0] up to rounding errors (indexPrices is most accurate)
|
|
399
|
+
return indexPrices[0] * (1 + ABK64x64ToFloat(ammState[8]));
|
|
400
|
+
}
|
|
401
|
+
static async _queryPerpetualState(symbol, symbolToPerpStaticInfo, _proxyContract, indexPrices, overrides) {
|
|
402
|
+
let perpId = PerpetualDataHandler.symbolToPerpetualId(symbol, symbolToPerpStaticInfo);
|
|
403
|
+
let staticInfo = symbolToPerpStaticInfo.get(symbol);
|
|
404
|
+
let ccy = symbol.split("-");
|
|
405
|
+
let [S2, S3] = [indexPrices[0], indexPrices[1]];
|
|
406
|
+
if (staticInfo.collateralCurrencyType == CollaterlCCY.BASE) {
|
|
407
|
+
S3 = S2;
|
|
408
|
+
}
|
|
409
|
+
else if (staticInfo.collateralCurrencyType == CollaterlCCY.QUOTE) {
|
|
410
|
+
S3 = 1;
|
|
411
|
+
}
|
|
412
|
+
let ammState = await _proxyContract.getAMMState(perpId, [S2, S3].map(floatToABK64x64), overrides || {});
|
|
413
|
+
let markPrice = S2 * (1 + ABK64x64ToFloat(ammState[8]));
|
|
414
|
+
let state = {
|
|
415
|
+
id: perpId,
|
|
416
|
+
state: PERP_STATE_STR[ammState[13].toNumber()],
|
|
417
|
+
baseCurrency: ccy[0],
|
|
418
|
+
quoteCurrency: ccy[1],
|
|
419
|
+
indexPrice: S2,
|
|
420
|
+
collToQuoteIndexPrice: S3,
|
|
421
|
+
markPrice: markPrice,
|
|
422
|
+
midPrice: ABK64x64ToFloat(ammState[10]),
|
|
423
|
+
currentFundingRateBps: ABK64x64ToFloat(ammState[14]) * 1e4,
|
|
424
|
+
openInterestBC: ABK64x64ToFloat(ammState[11]),
|
|
425
|
+
isMarketClosed: indexPrices[2] || indexPrices[3],
|
|
426
|
+
};
|
|
427
|
+
return state;
|
|
428
|
+
}
|
|
553
429
|
/**
|
|
554
430
|
* Liquidation price
|
|
555
431
|
* @param symbol symbol of the form BTC-USD-MATIC
|
|
@@ -558,34 +434,34 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
558
434
|
* @param symbolToPerpStaticInfo mapping symbol->PerpStaticInfo
|
|
559
435
|
* @returns liquidation mark-price, corresponding collateral/quote conversion
|
|
560
436
|
*/
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
437
|
+
static _calculateLiquidationPrice(symbol, traderState, S2, symbolToPerpStaticInfo) {
|
|
438
|
+
const idx_availableCashCC = 2;
|
|
439
|
+
const idx_cash = 3;
|
|
440
|
+
const idx_notional = 4;
|
|
441
|
+
const idx_locked_in = 5;
|
|
442
|
+
const idx_mark_price = 8;
|
|
443
|
+
const idx_s3 = 9;
|
|
568
444
|
// const idx_s2 = 10;
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
445
|
+
let S2Liq;
|
|
446
|
+
let S3Liq = ABK64x64ToFloat(traderState[idx_s3]);
|
|
447
|
+
let perpInfo = symbolToPerpStaticInfo.get(symbol);
|
|
572
448
|
if (perpInfo == undefined) {
|
|
573
|
-
throw new Error(
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
449
|
+
throw new Error(`no info for perpetual ${symbol}`);
|
|
450
|
+
}
|
|
451
|
+
let tau = perpInfo.maintenanceMarginRate;
|
|
452
|
+
let lockedInValueQC = ABK64x64ToFloat(traderState[idx_locked_in]);
|
|
453
|
+
let position = ABK64x64ToFloat(traderState[idx_notional]);
|
|
454
|
+
let cashCC = ABK64x64ToFloat(traderState[idx_availableCashCC]);
|
|
455
|
+
let Sm = ABK64x64ToFloat(traderState[idx_mark_price]);
|
|
456
|
+
let unpaidFundingCC = ABK64x64ToFloat(traderState[idx_availableCashCC].sub(traderState[idx_cash]));
|
|
457
|
+
let unpaidFunding = unpaidFundingCC;
|
|
582
458
|
if (perpInfo.collateralCurrencyType == CollaterlCCY.BASE) {
|
|
583
459
|
S2Liq = calculateLiquidationPriceCollateralBase(lockedInValueQC, position, cashCC, tau);
|
|
584
460
|
S3Liq = S2Liq;
|
|
585
461
|
unpaidFunding = unpaidFunding / S2;
|
|
586
462
|
}
|
|
587
463
|
else if (perpInfo.collateralCurrencyType == CollaterlCCY.QUANTO) {
|
|
588
|
-
|
|
464
|
+
let S3 = S3Liq;
|
|
589
465
|
S3Liq = S3;
|
|
590
466
|
S2Liq = calculateLiquidationPriceCollateralQuanto(lockedInValueQC, position, cashCC, tau, S3, Sm);
|
|
591
467
|
unpaidFunding = unpaidFunding / S3;
|
|
@@ -597,9 +473,9 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
597
473
|
S2Liq = S2Liq < 0 ? 0 : S2Liq;
|
|
598
474
|
S3Liq = S3Liq && S3Liq < 0 ? 0 : S3Liq;
|
|
599
475
|
// account cash + pnl = avail cash + pos Sm - L = margin balance
|
|
600
|
-
|
|
476
|
+
let pnl = position * Sm - lockedInValueQC + unpaidFunding;
|
|
601
477
|
return [S2Liq, S3Liq, tau, pnl, unpaidFundingCC];
|
|
602
|
-
}
|
|
478
|
+
}
|
|
603
479
|
/**
|
|
604
480
|
* Finds the perpetual id for a symbol of the form
|
|
605
481
|
* <base>-<quote>-<collateral>. The function first converts the
|
|
@@ -609,57 +485,45 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
609
485
|
* including id mapping
|
|
610
486
|
* @returns perpetual id or it fails
|
|
611
487
|
*/
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
var id = (_a = symbolToPerpStaticInfo.get(symbol)) === null || _a === void 0 ? void 0 : _a.id;
|
|
488
|
+
static symbolToPerpetualId(symbol, symbolToPerpStaticInfo) {
|
|
489
|
+
let id = symbolToPerpStaticInfo.get(symbol)?.id;
|
|
615
490
|
if (id == undefined) {
|
|
616
|
-
throw Error(
|
|
491
|
+
throw Error(`No perpetual found for symbol ${symbol}`);
|
|
617
492
|
}
|
|
618
493
|
return id;
|
|
619
|
-
}
|
|
620
|
-
|
|
494
|
+
}
|
|
495
|
+
static symbolToBytes4Symbol(symbol) {
|
|
621
496
|
//split by dashes BTC-USD-MATIC
|
|
622
|
-
|
|
497
|
+
let symbols = symbol.split("-");
|
|
623
498
|
if (symbols.length != 3) {
|
|
624
|
-
throw Error(
|
|
499
|
+
throw Error(`Symbol ${symbol} not valid. Expecting CCY-CCY-CCY format`);
|
|
625
500
|
}
|
|
626
501
|
//transform into bytes4 currencies (without the space): "BTC", "USD", "MATC"
|
|
627
|
-
symbols = symbols.map(
|
|
628
|
-
|
|
502
|
+
symbols = symbols.map((x) => {
|
|
503
|
+
let v = to4Chars(x);
|
|
629
504
|
v = v.replace(/\0/g, "");
|
|
630
505
|
return v;
|
|
631
506
|
});
|
|
632
507
|
// concatenate and find perpetual Id in map
|
|
633
508
|
return symbols[0] + "-" + symbols[1] + "-" + symbols[2];
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
var _d = __read(_c.value, 2), key = _d[0], value = _d[1];
|
|
640
|
-
if (value[valueField] === searchValue) {
|
|
641
|
-
return key;
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
646
|
-
finally {
|
|
647
|
-
try {
|
|
648
|
-
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
509
|
+
}
|
|
510
|
+
static _getByValue(map, searchValue, valueField) {
|
|
511
|
+
for (let [key, value] of map.entries()) {
|
|
512
|
+
if (value[valueField] === searchValue) {
|
|
513
|
+
return key;
|
|
649
514
|
}
|
|
650
|
-
finally { if (e_2) throw e_2.error; }
|
|
651
515
|
}
|
|
652
516
|
return undefined;
|
|
653
|
-
}
|
|
654
|
-
|
|
517
|
+
}
|
|
518
|
+
static fromSmartContractOrder(order, symbolToPerpInfoMap) {
|
|
655
519
|
// find symbol of perpetual id
|
|
656
|
-
|
|
520
|
+
let symbol = PerpetualDataHandler._getByValue(symbolToPerpInfoMap, order.iPerpetualId, "id");
|
|
657
521
|
if (symbol == undefined) {
|
|
658
|
-
throw Error(
|
|
522
|
+
throw Error(`Perpetual id ${order.iPerpetualId} not found. Check with marketData.exchangeInfo().`);
|
|
659
523
|
}
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
524
|
+
let side = order.fAmount > BigNumber.from(0) ? BUY_SIDE : SELL_SIDE;
|
|
525
|
+
let limitPrice, stopPrice;
|
|
526
|
+
let fLimitPrice = BigNumber.from(order.fLimitPrice);
|
|
663
527
|
if (fLimitPrice.eq(0)) {
|
|
664
528
|
limitPrice = side == BUY_SIDE ? undefined : 0;
|
|
665
529
|
}
|
|
@@ -669,14 +533,14 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
669
533
|
else {
|
|
670
534
|
limitPrice = ABK64x64ToFloat(fLimitPrice);
|
|
671
535
|
}
|
|
672
|
-
|
|
536
|
+
let fStopPrice = BigNumber.from(order.fTriggerPrice);
|
|
673
537
|
if (fStopPrice.eq(0) || fStopPrice.eq(MAX_64x64)) {
|
|
674
538
|
stopPrice = undefined;
|
|
675
539
|
}
|
|
676
540
|
else {
|
|
677
541
|
stopPrice = ABK64x64ToFloat(fStopPrice);
|
|
678
542
|
}
|
|
679
|
-
|
|
543
|
+
let userOrder = {
|
|
680
544
|
symbol: symbol,
|
|
681
545
|
side: side,
|
|
682
546
|
type: PerpetualDataHandler._flagToOrderType(BigNumber.from(order.flags), BigNumber.from(order.fLimitPrice)),
|
|
@@ -694,7 +558,7 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
694
558
|
submittedTimestamp: Number(order.submittedTimestamp),
|
|
695
559
|
};
|
|
696
560
|
return userOrder;
|
|
697
|
-
}
|
|
561
|
+
}
|
|
698
562
|
/**
|
|
699
563
|
* Transform the convenient form of the order into a smart-contract accepted type of order
|
|
700
564
|
* @param order order type
|
|
@@ -702,14 +566,14 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
702
566
|
* @param symbolToPerpetualMap mapping of symbol to perpetual Id
|
|
703
567
|
* @returns SmartContractOrder
|
|
704
568
|
*/
|
|
705
|
-
|
|
569
|
+
static toSmartContractOrder(order, traderAddr, perpStaticInfo) {
|
|
706
570
|
// this revers if order is invalid
|
|
707
571
|
PerpetualDataHandler.checkOrder(order, perpStaticInfo);
|
|
708
572
|
// translate order
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
573
|
+
let flags = PerpetualDataHandler._orderTypeToFlag(order);
|
|
574
|
+
let brokerSig = order.brokerSignature == undefined ? [] : order.brokerSignature;
|
|
575
|
+
let perpetualId = PerpetualDataHandler.symbolToPerpetualId(order.symbol, perpStaticInfo);
|
|
576
|
+
let fAmount;
|
|
713
577
|
if (order.side == BUY_SIDE) {
|
|
714
578
|
fAmount = floatToABK64x64(Math.abs(order.quantity));
|
|
715
579
|
}
|
|
@@ -717,9 +581,9 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
717
581
|
fAmount = floatToABK64x64(-Math.abs(order.quantity));
|
|
718
582
|
}
|
|
719
583
|
else {
|
|
720
|
-
throw Error(
|
|
584
|
+
throw Error(`invalid side in order spec, use ${BUY_SIDE} or ${SELL_SIDE}`);
|
|
721
585
|
}
|
|
722
|
-
|
|
586
|
+
let fLimitPrice;
|
|
723
587
|
if (order.limitPrice == undefined) {
|
|
724
588
|
// we need to set the limit price to infinity or zero for
|
|
725
589
|
// the trade to go through
|
|
@@ -730,9 +594,9 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
730
594
|
else {
|
|
731
595
|
fLimitPrice = floatToABK64x64(order.limitPrice);
|
|
732
596
|
}
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
597
|
+
let iDeadline = order.deadline == undefined ? Date.now() / 1000 + ORDER_MAX_DURATION_SEC : order.deadline;
|
|
598
|
+
let fTriggerPrice = order.stopPrice == undefined ? BigNumber.from(0) : floatToABK64x64(order.stopPrice);
|
|
599
|
+
let smOrder = {
|
|
736
600
|
flags: flags,
|
|
737
601
|
iPerpetualId: perpetualId,
|
|
738
602
|
brokerFeeTbps: order.brokerFeeTbps == undefined ? 0 : order.brokerFeeTbps,
|
|
@@ -749,14 +613,14 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
749
613
|
submittedTimestamp: 0,
|
|
750
614
|
};
|
|
751
615
|
return smOrder;
|
|
752
|
-
}
|
|
616
|
+
}
|
|
753
617
|
/**
|
|
754
618
|
* Converts a smart contract order to a client order
|
|
755
619
|
* @param scOrder Smart contract order
|
|
756
620
|
* @param parentChildIds Optional parent-child dependency
|
|
757
621
|
* @returns Client order that can be submitted to the corresponding LOB
|
|
758
622
|
*/
|
|
759
|
-
|
|
623
|
+
static fromSmartContratOrderToClientOrder(scOrder, parentChildIds) {
|
|
760
624
|
return {
|
|
761
625
|
flags: scOrder.flags,
|
|
762
626
|
iPerpetualId: scOrder.iPerpetualId,
|
|
@@ -774,24 +638,24 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
774
638
|
parentChildDigest1: parentChildIds ? parentChildIds[0] : ZERO_ORDER_ID,
|
|
775
639
|
parentChildDigest2: parentChildIds ? parentChildIds[1] : ZERO_ORDER_ID,
|
|
776
640
|
};
|
|
777
|
-
}
|
|
641
|
+
}
|
|
778
642
|
/**
|
|
779
643
|
* Converts a user-friendly order to a client order
|
|
780
644
|
* @param order Order
|
|
781
645
|
* @param parentChildIds Optional parent-child dependency
|
|
782
646
|
* @returns Client order that can be submitted to the corresponding LOB
|
|
783
647
|
*/
|
|
784
|
-
|
|
785
|
-
|
|
648
|
+
static toClientOrder(order, traderAddr, perpStaticInfo, parentChildIds) {
|
|
649
|
+
const scOrder = PerpetualDataHandler.toSmartContractOrder(order, traderAddr, perpStaticInfo);
|
|
786
650
|
return PerpetualDataHandler.fromSmartContratOrderToClientOrder(scOrder, parentChildIds);
|
|
787
|
-
}
|
|
651
|
+
}
|
|
788
652
|
/**
|
|
789
653
|
* Converts an order as stored in the LOB smart contract into a user-friendly order type
|
|
790
654
|
* @param obOrder Order-book contract order type
|
|
791
655
|
* @returns User friendly order struct
|
|
792
656
|
*/
|
|
793
|
-
|
|
794
|
-
|
|
657
|
+
static fromClientOrder(obOrder, perpStaticInfo) {
|
|
658
|
+
const scOrder = {
|
|
795
659
|
flags: obOrder.flags,
|
|
796
660
|
iPerpetualId: obOrder.iPerpetualId,
|
|
797
661
|
brokerFeeTbps: obOrder.brokerFeeTbps,
|
|
@@ -805,18 +669,18 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
805
669
|
iDeadline: obOrder.iDeadline,
|
|
806
670
|
executionTimestamp: obOrder.executionTimestamp,
|
|
807
671
|
};
|
|
808
|
-
|
|
672
|
+
const order = PerpetualDataHandler.fromSmartContractOrder(scOrder, perpStaticInfo);
|
|
809
673
|
if (obOrder.parentChildDigest1.toString() != ZERO_ORDER_ID ||
|
|
810
674
|
obOrder.parentChildDigest2.toString() != ZERO_ORDER_ID) {
|
|
811
675
|
order.parentChildOrderIds = [obOrder.parentChildDigest1.toString(), obOrder.parentChildDigest2.toString()];
|
|
812
676
|
}
|
|
813
677
|
return order;
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
678
|
+
}
|
|
679
|
+
static _flagToOrderType(orderFlags, orderLimitPrice) {
|
|
680
|
+
let flag = BigNumber.from(orderFlags);
|
|
681
|
+
let isLimit = containsFlag(flag, MASK_LIMIT_ORDER);
|
|
682
|
+
let hasLimit = !BigNumber.from(orderLimitPrice).eq(0) || !BigNumber.from(orderLimitPrice).eq(MAX_64x64);
|
|
683
|
+
let isStop = containsFlag(flag, MASK_STOP_ORDER);
|
|
820
684
|
if (isStop && hasLimit) {
|
|
821
685
|
return ORDER_TYPE_STOP_LIMIT;
|
|
822
686
|
}
|
|
@@ -829,15 +693,15 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
829
693
|
else {
|
|
830
694
|
return ORDER_TYPE_MARKET;
|
|
831
695
|
}
|
|
832
|
-
}
|
|
696
|
+
}
|
|
833
697
|
/**
|
|
834
698
|
* Determine the correct order flags based on the order-properties.
|
|
835
699
|
* Checks for some misspecifications.
|
|
836
700
|
* @param order order type
|
|
837
701
|
* @returns BigNumber flags
|
|
838
702
|
*/
|
|
839
|
-
|
|
840
|
-
|
|
703
|
+
static _orderTypeToFlag(order) {
|
|
704
|
+
let flag;
|
|
841
705
|
order.type = order.type.toUpperCase();
|
|
842
706
|
switch (order.type) {
|
|
843
707
|
case ORDER_TYPE_LIMIT:
|
|
@@ -853,7 +717,7 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
853
717
|
flag = MASK_STOP_ORDER;
|
|
854
718
|
break;
|
|
855
719
|
default: {
|
|
856
|
-
throw Error(
|
|
720
|
+
throw Error(`Order type ${order.type} not found.`);
|
|
857
721
|
}
|
|
858
722
|
}
|
|
859
723
|
if (order.keepPositionLvg != undefined && order.keepPositionLvg) {
|
|
@@ -863,37 +727,37 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
863
727
|
flag = combineFlags(flag, MASK_CLOSE_ONLY);
|
|
864
728
|
}
|
|
865
729
|
if ((order.type == ORDER_TYPE_LIMIT || order.type == ORDER_TYPE_STOP_LIMIT) && order.limitPrice == undefined) {
|
|
866
|
-
throw Error(
|
|
730
|
+
throw Error(`Order type ${order.type} requires limit price.`);
|
|
867
731
|
}
|
|
868
732
|
if ((order.type == ORDER_TYPE_STOP_MARKET || order.type == ORDER_TYPE_STOP_LIMIT) && order.stopPrice == undefined) {
|
|
869
|
-
throw Error(
|
|
733
|
+
throw Error(`Order type ${order.type} requires trigger price.`);
|
|
870
734
|
}
|
|
871
735
|
if ((order.type == ORDER_TYPE_MARKET || order.type == ORDER_TYPE_LIMIT) && order.stopPrice != undefined) {
|
|
872
|
-
throw Error(
|
|
736
|
+
throw Error(`Order type ${order.type} has no trigger price.`);
|
|
873
737
|
}
|
|
874
738
|
if (order.type != ORDER_TYPE_STOP_LIMIT && order.type != ORDER_TYPE_STOP_MARKET && order.stopPrice != undefined) {
|
|
875
|
-
throw Error(
|
|
739
|
+
throw Error(`Order type ${order.type} has no trigger price.`);
|
|
876
740
|
}
|
|
877
741
|
return flag;
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
|
|
742
|
+
}
|
|
743
|
+
static _getLotSize(symbol, symbolToPerpStaticInfo) {
|
|
744
|
+
let perpInfo = symbolToPerpStaticInfo.get(symbol);
|
|
881
745
|
if (perpInfo == undefined) {
|
|
882
|
-
throw new Error(
|
|
746
|
+
throw new Error(`no info for perpetual ${symbol}`);
|
|
883
747
|
}
|
|
884
748
|
return perpInfo.lotSizeBC;
|
|
885
|
-
}
|
|
886
|
-
|
|
749
|
+
}
|
|
750
|
+
static _getMinimalPositionSize(symbol, symbolToPerpStaticInfo) {
|
|
887
751
|
return 10 * PerpetualDataHandler._getLotSize(symbol, symbolToPerpStaticInfo);
|
|
888
|
-
}
|
|
752
|
+
}
|
|
889
753
|
/**
|
|
890
754
|
* Get NodeSDKConfig from a chain ID, known config name, or custom file location..
|
|
891
755
|
* @param configNameOrfileLocation Name of a known default config, or chain ID, or json-file with required variables for config
|
|
892
756
|
* @param version Config version number. Defaults to highest version if name or chain ID are not unique
|
|
893
757
|
* @returns NodeSDKConfig
|
|
894
758
|
*/
|
|
895
|
-
|
|
896
|
-
|
|
759
|
+
static readSDKConfig(configNameOrChainIdOrFileLocation, version) {
|
|
760
|
+
let config;
|
|
897
761
|
if (typeof configNameOrChainIdOrFileLocation === "number") {
|
|
898
762
|
// user entered a chain ID
|
|
899
763
|
config = this.getConfigByChainId(configNameOrChainIdOrFileLocation, version);
|
|
@@ -910,92 +774,92 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
910
774
|
}
|
|
911
775
|
else {
|
|
912
776
|
// error
|
|
913
|
-
throw Error(
|
|
777
|
+
throw Error(`Please specify a chain ID, config name, or custom file location.`);
|
|
914
778
|
}
|
|
915
779
|
if (config == undefined) {
|
|
916
|
-
throw Error(
|
|
780
|
+
throw Error(`Config ${configNameOrChainIdOrFileLocation} not found.`);
|
|
917
781
|
}
|
|
918
782
|
return config;
|
|
919
|
-
}
|
|
783
|
+
}
|
|
920
784
|
/**
|
|
921
785
|
* Get a NodeSDKConfig from its name
|
|
922
786
|
* @param name Name of the known config
|
|
923
787
|
* @param version Version of the config. Defaults to highest available.
|
|
924
788
|
* @returns NodeSDKConfig
|
|
925
789
|
*/
|
|
926
|
-
|
|
927
|
-
|
|
790
|
+
static getConfigByName(name, version) {
|
|
791
|
+
let configFile = DEFAULT_CONFIG.filter((c) => c.name == name);
|
|
928
792
|
if (configFile.length == 0) {
|
|
929
|
-
throw Error(
|
|
793
|
+
throw Error(`No SDK config found with name ${name}.`);
|
|
930
794
|
}
|
|
931
795
|
if (configFile.length == 1) {
|
|
932
796
|
return configFile[0];
|
|
933
797
|
}
|
|
934
798
|
else {
|
|
935
799
|
if (version === undefined) {
|
|
936
|
-
configFile = configFile.sort(
|
|
800
|
+
configFile = configFile.sort((conf) => -conf.version);
|
|
937
801
|
return configFile[0];
|
|
938
802
|
}
|
|
939
803
|
else {
|
|
940
|
-
return configFile.find(
|
|
804
|
+
return configFile.find((conf) => conf.version === version);
|
|
941
805
|
}
|
|
942
806
|
}
|
|
943
|
-
}
|
|
807
|
+
}
|
|
944
808
|
/**
|
|
945
809
|
* Get a NodeSDKConfig from a json file.
|
|
946
810
|
* @param filename Location of the file
|
|
947
811
|
* @param version Version of the config. Defaults to highest available.
|
|
948
812
|
* @returns NodeSDKConfig
|
|
949
813
|
*/
|
|
950
|
-
|
|
814
|
+
static getConfigByLocation(filename) {
|
|
951
815
|
// file path: this throws a warning during build - that's ok, it just won't work in react apps
|
|
952
816
|
// eslint-disable-next-line
|
|
953
|
-
|
|
817
|
+
let configFile = require(filename);
|
|
954
818
|
loadABIs(configFile);
|
|
955
819
|
return configFile;
|
|
956
|
-
}
|
|
820
|
+
}
|
|
957
821
|
/**
|
|
958
822
|
* Get a NodeSDKConfig from its chain Id
|
|
959
823
|
* @param chainId Chain Id
|
|
960
824
|
* @param version Version of the config. Defaults to highest available.
|
|
961
825
|
* @returns NodeSDKConfig
|
|
962
826
|
*/
|
|
963
|
-
|
|
964
|
-
|
|
827
|
+
static getConfigByChainId(chainId, version) {
|
|
828
|
+
let configFile = DEFAULT_CONFIG.filter((c) => c.chainId == chainId);
|
|
965
829
|
if (configFile.length == 0) {
|
|
966
|
-
throw Error(
|
|
830
|
+
throw Error(`No SDK config found for chain ID ${chainId}.`);
|
|
967
831
|
}
|
|
968
832
|
if (configFile.length == 1) {
|
|
969
833
|
return configFile[0];
|
|
970
834
|
}
|
|
971
835
|
else {
|
|
972
836
|
if (version === undefined) {
|
|
973
|
-
configFile = configFile.sort(
|
|
837
|
+
configFile = configFile.sort((conf) => -conf.version);
|
|
974
838
|
return configFile[0];
|
|
975
839
|
}
|
|
976
840
|
else {
|
|
977
|
-
return configFile.find(
|
|
841
|
+
return configFile.find((conf) => conf.version === version);
|
|
978
842
|
}
|
|
979
843
|
}
|
|
980
|
-
}
|
|
844
|
+
}
|
|
981
845
|
/**
|
|
982
846
|
* Get the ABI of a function in a given contract
|
|
983
847
|
* @param contract A contract instance, e.g. this.proxyContract
|
|
984
848
|
* @param functionName Name of the function whose ABI we want
|
|
985
849
|
* @returns Function ABI as a single JSON string
|
|
986
850
|
*/
|
|
987
|
-
|
|
851
|
+
static _getABIFromContract(contract, functionName) {
|
|
988
852
|
return contract.interface.getFunction(functionName).format(FormatTypes.full);
|
|
989
|
-
}
|
|
853
|
+
}
|
|
990
854
|
/**
|
|
991
855
|
* Gets the pool index (starting at 0 in exchangeInfo, not ID!) corresponding to a given symbol.
|
|
992
856
|
* @param symbol Symbol of the form ETH-USD-MATIC
|
|
993
857
|
* @returns Pool index
|
|
994
858
|
*/
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
859
|
+
getPoolStaticInfoIndexFromSymbol(symbol) {
|
|
860
|
+
let pools = this.poolStaticInfos;
|
|
861
|
+
let poolId = PerpetualDataHandler._getPoolIdFromSymbol(symbol, this.poolStaticInfos);
|
|
862
|
+
let k = 0;
|
|
999
863
|
while (k < pools.length) {
|
|
1000
864
|
if (pools[k].poolId == poolId) {
|
|
1001
865
|
// pool found
|
|
@@ -1004,11 +868,16 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
1004
868
|
k++;
|
|
1005
869
|
}
|
|
1006
870
|
return -1;
|
|
1007
|
-
}
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
871
|
+
}
|
|
872
|
+
/**
|
|
873
|
+
*
|
|
874
|
+
* @param symbol Symbol of the form USDC
|
|
875
|
+
* @returns Address of the corresponding token
|
|
876
|
+
*/
|
|
877
|
+
getMarginTokenFromSymbol(symbol) {
|
|
878
|
+
let pools = this.poolStaticInfos;
|
|
879
|
+
let poolId = PerpetualDataHandler._getPoolIdFromSymbol(symbol, this.poolStaticInfos);
|
|
880
|
+
let k = 0;
|
|
1012
881
|
while (k < pools.length) {
|
|
1013
882
|
if (pools[k].poolId == poolId) {
|
|
1014
883
|
// pool found
|
|
@@ -1017,13 +886,31 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
1017
886
|
k++;
|
|
1018
887
|
}
|
|
1019
888
|
return undefined;
|
|
1020
|
-
}
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
*
|
|
892
|
+
* @param symbol Symbol of the form USDC
|
|
893
|
+
* @returns Decimals of the corresponding token
|
|
894
|
+
*/
|
|
895
|
+
getMarginTokenDecimalsFromSymbol(symbol) {
|
|
896
|
+
let pools = this.poolStaticInfos;
|
|
897
|
+
let poolId = PerpetualDataHandler._getPoolIdFromSymbol(symbol, this.poolStaticInfos);
|
|
898
|
+
let k = 0;
|
|
899
|
+
while (k < pools.length) {
|
|
900
|
+
if (pools[k].poolId == poolId) {
|
|
901
|
+
// pool found
|
|
902
|
+
return pools[k].poolMarginTokenDecimals;
|
|
903
|
+
}
|
|
904
|
+
k++;
|
|
905
|
+
}
|
|
906
|
+
return undefined;
|
|
907
|
+
}
|
|
1021
908
|
/**
|
|
1022
909
|
* Get ABI for LimitOrderBook, Proxy, or Share Pool Token
|
|
1023
910
|
* @param contract name of contract: proxy|lob|sharetoken
|
|
1024
911
|
* @returns ABI for the requested contract
|
|
1025
912
|
*/
|
|
1026
|
-
|
|
913
|
+
getABI(contract) {
|
|
1027
914
|
switch (contract) {
|
|
1028
915
|
case "proxy":
|
|
1029
916
|
return this.proxyABI;
|
|
@@ -1034,22 +921,22 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
1034
921
|
default:
|
|
1035
922
|
return undefined;
|
|
1036
923
|
}
|
|
1037
|
-
}
|
|
924
|
+
}
|
|
1038
925
|
/**
|
|
1039
926
|
* Performs basic validity checks on a given order
|
|
1040
927
|
* @param order Order struct
|
|
1041
928
|
* @param traderAccount Trader account
|
|
1042
929
|
* @param perpStaticInfo Symbol to perpetual info map
|
|
1043
930
|
*/
|
|
1044
|
-
|
|
931
|
+
static checkOrder(order,
|
|
1045
932
|
// traderAccount: MarginAccount,
|
|
1046
933
|
perpStaticInfo) {
|
|
1047
934
|
// check side
|
|
1048
935
|
if (order.side != BUY_SIDE && order.side != SELL_SIDE) {
|
|
1049
|
-
throw Error(
|
|
936
|
+
throw Error(`order side must be ${BUY_SIDE} or ${SELL_SIDE}`);
|
|
1050
937
|
}
|
|
1051
938
|
// check amount
|
|
1052
|
-
|
|
939
|
+
let lotSize = perpStaticInfo.get(order.symbol).lotSizeBC;
|
|
1053
940
|
// let curPos =
|
|
1054
941
|
// traderAccount.side == CLOSED_SIDE
|
|
1055
942
|
// ? 0
|
|
@@ -1057,22 +944,20 @@ var PerpetualDataHandler = /** @class */ (function () {
|
|
|
1057
944
|
// let newPos = curPos + (order.side == BUY_SIDE ? 1 : -1) * order.quantity;
|
|
1058
945
|
// if (Math.abs(order.quantity) < lotSize || (Math.abs(newPos) >= lotSize && Math.abs(newPos) < 10 * lotSize)) {
|
|
1059
946
|
if (Math.abs(order.quantity) < lotSize) {
|
|
1060
|
-
throw Error(
|
|
947
|
+
throw Error(`trade amount too small: ${order.quantity} ${perpStaticInfo.get(order.symbol).S2Symbol}`);
|
|
1061
948
|
}
|
|
1062
949
|
// check limit price
|
|
1063
950
|
if (order.side == BUY_SIDE && order.limitPrice != undefined && order.limitPrice <= 0) {
|
|
1064
|
-
throw Error(
|
|
951
|
+
throw Error(`invalid limit price for buy order: ${order.limitPrice}`);
|
|
1065
952
|
}
|
|
1066
953
|
// broker fee
|
|
1067
954
|
if (order.brokerFeeTbps != undefined && order.brokerFeeTbps < 0) {
|
|
1068
|
-
throw Error(
|
|
955
|
+
throw Error(`invalid broker fee: ${order.brokerFeeTbps / 10} bps`);
|
|
1069
956
|
}
|
|
1070
957
|
// stop price
|
|
1071
958
|
if (order.stopPrice != undefined && order.stopPrice < 0) {
|
|
1072
|
-
throw Error(
|
|
959
|
+
throw Error(`invalid stop price: ${order.stopPrice}`);
|
|
1073
960
|
}
|
|
1074
|
-
}
|
|
1075
|
-
|
|
1076
|
-
}());
|
|
1077
|
-
export default PerpetualDataHandler;
|
|
961
|
+
}
|
|
962
|
+
}
|
|
1078
963
|
//# sourceMappingURL=perpetualDataHandler.js.map
|