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