@d8x/perpetuals-sdk 0.1.12 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/dist/cjs/abi/testnet/IPerpetualManager.json +5215 -0
  2. package/dist/cjs/abi/testnet/LimitOrderBook.json +1075 -0
  3. package/dist/cjs/abi/zkevmTestnet/IPerpetualManager.json +5215 -0
  4. package/dist/cjs/abi/zkevmTestnet/LimitOrderBook.json +1075 -0
  5. package/dist/cjs/abi/zkevmTestnet/LimitOrderBookFactory.json +135 -0
  6. package/dist/cjs/accountTrade.js +441 -0
  7. package/dist/cjs/accountTrade.js.map +1 -0
  8. package/dist/{src → cjs}/brokerTool.js +31 -84
  9. package/dist/cjs/brokerTool.js.map +1 -0
  10. package/dist/cjs/config/defaultConfig.json +47 -0
  11. package/dist/cjs/config/mockSwap.json +4 -0
  12. package/dist/cjs/config/priceFeedConfig.json +104 -0
  13. package/dist/cjs/config/symbolList.json +13 -0
  14. package/dist/cjs/d8XMath.js.map +1 -0
  15. package/dist/cjs/index.js +29 -0
  16. package/dist/cjs/index.js.map +1 -0
  17. package/dist/cjs/liquidatorTool.js +287 -0
  18. package/dist/cjs/liquidatorTool.js.map +1 -0
  19. package/dist/{src → cjs}/liquidityProviderTool.js +12 -65
  20. package/dist/cjs/liquidityProviderTool.js.map +1 -0
  21. package/dist/{src → cjs}/marketData.js +52 -134
  22. package/dist/cjs/marketData.js.map +1 -0
  23. package/dist/{src → cjs}/nodeSDKTypes.d.ts +5 -5
  24. package/dist/cjs/nodeSDKTypes.js +64 -0
  25. package/dist/cjs/nodeSDKTypes.js.map +1 -0
  26. package/dist/{src → cjs}/orderReferrerTool.d.ts +12 -5
  27. package/dist/{src → cjs}/orderReferrerTool.js +114 -112
  28. package/dist/cjs/orderReferrerTool.js.map +1 -0
  29. package/dist/{src → cjs}/perpetualDataHandler.d.ts +1 -1
  30. package/dist/{src → cjs}/perpetualDataHandler.js +47 -109
  31. package/dist/cjs/perpetualDataHandler.js.map +1 -0
  32. package/dist/{src → cjs}/perpetualEventHandler.d.ts +3 -3
  33. package/dist/{src → cjs}/perpetualEventHandler.js +12 -74
  34. package/dist/cjs/perpetualEventHandler.js.map +1 -0
  35. package/dist/cjs/priceFeeds.js +466 -0
  36. package/dist/cjs/priceFeeds.js.map +1 -0
  37. package/dist/{src → cjs}/traderDigests.js +7 -43
  38. package/dist/cjs/traderDigests.js.map +1 -0
  39. package/dist/{src → cjs}/traderInterface.js +13 -66
  40. package/dist/cjs/traderInterface.js.map +1 -0
  41. package/dist/{src → cjs}/triangulator.js +2 -17
  42. package/dist/cjs/triangulator.js.map +1 -0
  43. package/dist/{src → cjs}/utils.js +3 -29
  44. package/dist/cjs/utils.js.map +1 -0
  45. package/dist/cjs/version.d.ts +1 -0
  46. package/dist/{src → cjs}/version.js +1 -1
  47. package/dist/cjs/version.js.map +1 -0
  48. package/dist/{src → cjs}/writeAccessHandler.js +12 -65
  49. package/dist/cjs/writeAccessHandler.js.map +1 -0
  50. package/dist/esm/abi/ERC20.json +288 -0
  51. package/dist/esm/abi/MockTokenSwap.json +186 -0
  52. package/dist/{abi/testnet → esm/abi/central-park}/IPerpetualManager.json +404 -214
  53. package/dist/{abi/testnet → esm/abi/central-park}/LimitOrderBook.json +197 -15
  54. package/dist/esm/abi/central-park/LimitOrderBookFactory.json +135 -0
  55. package/dist/esm/abi/testnet/IPerpetualManager.json +5215 -0
  56. package/dist/esm/abi/testnet/LimitOrderBook.json +1075 -0
  57. package/dist/esm/abi/testnet/LimitOrderBookFactory.json +135 -0
  58. package/dist/esm/abi/zkevmTestnet/IPerpetualManager.json +5215 -0
  59. package/dist/esm/abi/zkevmTestnet/LimitOrderBook.json +1075 -0
  60. package/dist/esm/abi/zkevmTestnet/LimitOrderBookFactory.json +135 -0
  61. package/dist/esm/accountTrade.d.ts +221 -0
  62. package/dist/{src → esm}/accountTrade.js +22 -93
  63. package/dist/esm/accountTrade.js.map +1 -0
  64. package/dist/esm/brokerTool.d.ts +318 -0
  65. package/dist/esm/brokerTool.js +572 -0
  66. package/dist/esm/brokerTool.js.map +1 -0
  67. package/dist/esm/config/defaultConfig.json +47 -0
  68. package/dist/esm/config/mockSwap.json +4 -0
  69. package/dist/esm/config/priceFeedConfig.json +104 -0
  70. package/dist/esm/config/symbolList.json +13 -0
  71. package/dist/esm/d8XMath.d.ts +122 -0
  72. package/dist/esm/d8XMath.js +247 -0
  73. package/dist/esm/d8XMath.js.map +1 -0
  74. package/{src/index.ts → dist/esm/index.d.ts} +1 -15
  75. package/dist/esm/index.js +16 -0
  76. package/dist/esm/index.js.map +1 -0
  77. package/dist/esm/liquidatorTool.d.ts +158 -0
  78. package/dist/{src → esm}/liquidatorTool.js +10 -65
  79. package/dist/esm/liquidatorTool.js.map +1 -0
  80. package/dist/esm/liquidityProviderTool.d.ts +126 -0
  81. package/dist/esm/liquidityProviderTool.js +218 -0
  82. package/dist/esm/liquidityProviderTool.js.map +1 -0
  83. package/dist/esm/marketData.d.ts +309 -0
  84. package/dist/esm/marketData.js +1007 -0
  85. package/dist/esm/marketData.js.map +1 -0
  86. package/dist/esm/nodeSDKTypes.d.ts +266 -0
  87. package/dist/esm/nodeSDKTypes.js +60 -0
  88. package/dist/esm/nodeSDKTypes.js.map +1 -0
  89. package/dist/esm/orderReferrerTool.d.ts +196 -0
  90. package/dist/esm/orderReferrerTool.js +491 -0
  91. package/dist/esm/orderReferrerTool.js.map +1 -0
  92. package/dist/esm/perpetualDataHandler.d.ts +220 -0
  93. package/dist/esm/perpetualDataHandler.js +1060 -0
  94. package/dist/esm/perpetualDataHandler.js.map +1 -0
  95. package/dist/esm/perpetualEventHandler.d.ts +179 -0
  96. package/dist/esm/perpetualEventHandler.js +435 -0
  97. package/dist/esm/perpetualEventHandler.js.map +1 -0
  98. package/dist/esm/priceFeeds.d.ts +115 -0
  99. package/dist/{src → esm}/priceFeeds.js +16 -83
  100. package/dist/esm/priceFeeds.js.map +1 -0
  101. package/dist/esm/traderDigests.d.ts +21 -0
  102. package/dist/esm/traderDigests.js +80 -0
  103. package/dist/esm/traderDigests.js.map +1 -0
  104. package/dist/esm/traderInterface.d.ts +79 -0
  105. package/dist/esm/traderInterface.js +196 -0
  106. package/dist/esm/traderInterface.js.map +1 -0
  107. package/dist/esm/triangulator.d.ts +27 -0
  108. package/dist/esm/triangulator.js +110 -0
  109. package/dist/esm/triangulator.js.map +1 -0
  110. package/dist/esm/utils.d.ts +59 -0
  111. package/dist/esm/utils.js +138 -0
  112. package/dist/esm/utils.js.map +1 -0
  113. package/dist/esm/version.d.ts +1 -0
  114. package/dist/esm/version.js +2 -0
  115. package/dist/esm/version.js.map +1 -0
  116. package/dist/esm/writeAccessHandler.d.ts +50 -0
  117. package/dist/esm/writeAccessHandler.js +157 -0
  118. package/dist/esm/writeAccessHandler.js.map +1 -0
  119. package/package.json +16 -26
  120. package/dist/bundle.js +0 -36793
  121. package/dist/config/defaultConfig.json +0 -47
  122. package/dist/config/mockSwap.json +0 -4
  123. package/dist/config/priceFeedConfig.json +0 -104
  124. package/dist/config/symbolList.json +0 -13
  125. package/dist/src/index.js +0 -45
  126. package/dist/src/nodeSDKTypes.js +0 -115
  127. package/dist/src/version.d.ts +0 -1
  128. package/module.d.ts +0 -1
  129. package/src/accountTrade.ts +0 -392
  130. package/src/brokerTool.ts +0 -507
  131. package/src/d8XMath.ts +0 -319
  132. package/src/liquidatorTool.ts +0 -258
  133. package/src/liquidityProviderTool.ts +0 -186
  134. package/src/marketData.ts +0 -946
  135. package/src/nodeSDKTypes.ts +0 -293
  136. package/src/orderReferrerTool.ts +0 -389
  137. package/src/perpetualDataHandler.ts +0 -1061
  138. package/src/perpetualEventHandler.ts +0 -455
  139. package/src/priceFeeds.ts +0 -381
  140. package/src/traderDigests.ts +0 -91
  141. package/src/traderInterface.ts +0 -159
  142. package/src/triangulator.ts +0 -105
  143. package/src/utils.ts +0 -134
  144. package/src/version.ts +0 -1
  145. package/src/writeAccessHandler.ts +0 -127
  146. /package/dist/{abi → cjs/abi}/ERC20.json +0 -0
  147. /package/dist/{abi → cjs/abi}/MockTokenSwap.json +0 -0
  148. /package/dist/{abi → cjs/abi}/central-park/IPerpetualManager.json +0 -0
  149. /package/dist/{abi → cjs/abi}/central-park/LimitOrderBook.json +0 -0
  150. /package/dist/{abi → cjs/abi}/central-park/LimitOrderBookFactory.json +0 -0
  151. /package/dist/{abi → cjs/abi}/testnet/LimitOrderBookFactory.json +0 -0
  152. /package/dist/{src → cjs}/accountTrade.d.ts +0 -0
  153. /package/dist/{src → cjs}/brokerTool.d.ts +0 -0
  154. /package/dist/{src → cjs}/d8XMath.d.ts +0 -0
  155. /package/dist/{src → cjs}/d8XMath.js +0 -0
  156. /package/dist/{src → cjs}/index.d.ts +0 -0
  157. /package/dist/{src → cjs}/liquidatorTool.d.ts +0 -0
  158. /package/dist/{src → cjs}/liquidityProviderTool.d.ts +0 -0
  159. /package/dist/{src → cjs}/marketData.d.ts +0 -0
  160. /package/dist/{src → cjs}/priceFeeds.d.ts +0 -0
  161. /package/dist/{src → cjs}/traderDigests.d.ts +0 -0
  162. /package/dist/{src → cjs}/traderInterface.d.ts +0 -0
  163. /package/dist/{src → cjs}/triangulator.d.ts +0 -0
  164. /package/dist/{src → cjs}/utils.d.ts +0 -0
  165. /package/dist/{src → cjs}/writeAccessHandler.d.ts +0 -0
@@ -0,0 +1,1007 @@
1
+ import { __awaiter, __extends, __generator, __read, __values } from "tslib";
2
+ import { BigNumber, ethers } from "ethers";
3
+ import { ABK64x64ToFloat, calculateLiquidationPriceCollateralBase, calculateLiquidationPriceCollateralQuanto, calculateLiquidationPriceCollateralQuote, floatToABK64x64, getDepositAmountForLvgTrade, } from "./d8XMath";
4
+ import "./nodeSDKTypes";
5
+ import { BUY_SIDE, CLOSED_SIDE, COLLATERAL_CURRENCY_BASE, COLLATERAL_CURRENCY_QUANTO, CollaterlCCY, ERC20_ABI, PERP_STATE_STR, SELL_SIDE, ZERO_ADDRESS, } from "./nodeSDKTypes";
6
+ import PerpetualDataHandler from "./perpetualDataHandler";
7
+ import { contractSymbolToSymbol, toBytes4 } from "./utils";
8
+ /**
9
+ * Functions to access market data (e.g., information on open orders, information on products that can be traded).
10
+ * This class requires no private key and is blockchain read-only.
11
+ * No gas required for the queries here.
12
+ * @extends PerpetualDataHandler
13
+ */
14
+ var MarketData = /** @class */ (function (_super) {
15
+ __extends(MarketData, _super);
16
+ /**
17
+ * Constructor
18
+ * @param {NodeSDKConfig} config Configuration object, see
19
+ * PerpetualDataHandler.readSDKConfig.
20
+ * @example
21
+ * import { MarketData, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
22
+ * async function main() {
23
+ * console.log(MarketData);
24
+ * // load configuration for testnet
25
+ * const config = PerpetualDataHandler.readSDKConfig("testnet");
26
+ * // MarketData (read only, no authentication needed)
27
+ * let mktData = new MarketData(config);
28
+ * // Create a proxy instance to access the blockchain
29
+ * await mktData.createProxyInstance();
30
+ * }
31
+ * main();
32
+ *
33
+ */
34
+ function MarketData(config) {
35
+ return _super.call(this, config) || this;
36
+ }
37
+ /**
38
+ * Initialize the marketData-Class with this function
39
+ * to create instance of D8X perpetual contract and gather information
40
+ * about perpetual currencies
41
+ * @param provider optional provider
42
+ */
43
+ MarketData.prototype.createProxyInstance = function (provider) {
44
+ return __awaiter(this, void 0, void 0, function () {
45
+ return __generator(this, function (_a) {
46
+ switch (_a.label) {
47
+ case 0:
48
+ if (provider == undefined) {
49
+ this.provider = new ethers.providers.JsonRpcProvider(this.nodeURL);
50
+ }
51
+ else {
52
+ this.provider = provider;
53
+ }
54
+ return [4 /*yield*/, this.initContractsAndData(this.provider)];
55
+ case 1:
56
+ _a.sent();
57
+ return [2 /*return*/];
58
+ }
59
+ });
60
+ });
61
+ };
62
+ /**
63
+ * Get the proxy address
64
+ * @returns Address of the perpetual proxy contract
65
+ */
66
+ MarketData.prototype.getProxyAddress = function () {
67
+ if (this.proxyContract == null) {
68
+ throw Error("no proxy contract initialized. Use createProxyInstance().");
69
+ }
70
+ return this.proxyContract.address;
71
+ };
72
+ /**
73
+ * Convert the smart contract output of an order into a convenient format of type "Order"
74
+ * @param smOrder SmartContractOrder, as obtained e.g., by PerpetualLimitOrderCreated event
75
+ * @returns more convenient format of order, type "Order"
76
+ */
77
+ MarketData.prototype.smartContractOrderToOrder = function (smOrder) {
78
+ return PerpetualDataHandler.fromSmartContractOrder(smOrder, this.symbolToPerpStaticInfo);
79
+ };
80
+ /**
81
+ * Get contract instance. Useful for event listening.
82
+ * @example
83
+ * import { MarketData, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
84
+ * async function main() {
85
+ * console.log(MarketData);
86
+ * // setup
87
+ * const config = PerpetualDataHandler.readSDKConfig("testnet");
88
+ * let mktData = new MarketData(config);
89
+ * await mktData.createProxyInstance();
90
+ * // Get contract instance
91
+ * let proxy = await mktData.getReadOnlyProxyInstance();
92
+ * console.log(proxy);
93
+ * }
94
+ * main();
95
+ *
96
+ * @returns read-only proxy instance
97
+ */
98
+ MarketData.prototype.getReadOnlyProxyInstance = function () {
99
+ if (this.proxyContract == null) {
100
+ throw Error("no proxy contract initialized. Use createProxyInstance().");
101
+ }
102
+ return this.proxyContract;
103
+ };
104
+ /**
105
+ * Information about the products traded in the exchange.
106
+ * @example
107
+ * import { MarketData, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
108
+ * async function main() {
109
+ * console.log(MarketData);
110
+ * // setup
111
+ * const config = PerpetualDataHandler.readSDKConfig("testnet");
112
+ * let mktData = new MarketData(config);
113
+ * await mktData.createProxyInstance();
114
+ * // Get exchange info
115
+ * let info = await mktData.exchangeInfo();
116
+ * console.log(info);
117
+ * }
118
+ * main();
119
+ *
120
+ * @returns {ExchangeInfo} Array of static data for all the pools and perpetuals in the system.
121
+ */
122
+ MarketData.prototype.exchangeInfo = function () {
123
+ return __awaiter(this, void 0, void 0, function () {
124
+ return __generator(this, function (_a) {
125
+ switch (_a.label) {
126
+ case 0:
127
+ if (this.proxyContract == null) {
128
+ throw Error("no proxy contract initialized. Use createProxyInstance().");
129
+ }
130
+ return [4 /*yield*/, MarketData._exchangeInfo(this.proxyContract, this.poolStaticInfos, this.symbolToPerpStaticInfo, this.symbolList, this.priceFeedGetter)];
131
+ case 1: return [2 /*return*/, _a.sent()];
132
+ }
133
+ });
134
+ });
135
+ };
136
+ /**
137
+ * All open orders for a trader-address and a symbol.
138
+ * @param {string} traderAddr Address of the trader for which we get the open orders.
139
+ * @param {string} symbol Symbol of the form ETH-USD-MATIC.
140
+ * @example
141
+ * import { MarketData, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
142
+ * async function main() {
143
+ * console.log(MarketData);
144
+ * // setup
145
+ * const config = PerpetualDataHandler.readSDKConfig("testnet");
146
+ * let mktData = new MarketData(config);
147
+ * await mktData.createProxyInstance();
148
+ * // Get all open orders for a trader/symbol
149
+ * let opOrder = await mktData.openOrders("0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B",
150
+ * "ETH-USD-MATIC");
151
+ * console.log(opOrder);
152
+ * }
153
+ * main();
154
+ *
155
+ * @returns {Array<Array<Order>, Array<string>>} Array of open orders and corresponding order-ids.
156
+ */
157
+ MarketData.prototype.openOrders = function (traderAddr, symbol) {
158
+ return __awaiter(this, void 0, void 0, function () {
159
+ var orderBookContract, _a, orders, digests;
160
+ return __generator(this, function (_b) {
161
+ switch (_b.label) {
162
+ case 0:
163
+ orderBookContract = this.getOrderBookContract(symbol);
164
+ return [4 /*yield*/, Promise.all([
165
+ this.openOrdersOnOrderBook(traderAddr, orderBookContract),
166
+ MarketData.orderIdsOfTrader(traderAddr, orderBookContract),
167
+ ])];
168
+ case 1:
169
+ _a = __read.apply(void 0, [_b.sent(), 2]), orders = _a[0], digests = _a[1];
170
+ return [2 /*return*/, { orders: orders, orderIds: digests }];
171
+ }
172
+ });
173
+ });
174
+ };
175
+ /**
176
+ * Information about the position open by a given trader in a given perpetual contract.
177
+ * @param {string} traderAddr Address of the trader for which we get the position risk.
178
+ * @param {string} symbol Symbol of the form ETH-USD-MATIC. Can also be the perpetual id as string
179
+ * @example
180
+ * import { MarketData, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
181
+ * async function main() {
182
+ * console.log(MarketData);
183
+ * // setup
184
+ * const config = PerpetualDataHandler.readSDKConfig("testnet");
185
+ * let mktData = new MarketData(config);
186
+ * await mktData.createProxyInstance();
187
+ * // Get position risk info
188
+ * let posRisk = await mktData.positionRisk("0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B",
189
+ * "ETH-USD-MATIC");
190
+ * console.log(posRisk);
191
+ * }
192
+ * main();
193
+ *
194
+ * @returns {MarginAccount} Position risk of trader.
195
+ */
196
+ MarketData.prototype.positionRisk = function (traderAddr, symbol) {
197
+ return __awaiter(this, void 0, void 0, function () {
198
+ var obj, mgnAcct;
199
+ return __generator(this, function (_a) {
200
+ switch (_a.label) {
201
+ case 0:
202
+ if (this.proxyContract == null) {
203
+ throw Error("no proxy contract initialized. Use createProxyInstance().");
204
+ }
205
+ return [4 /*yield*/, this.priceFeedGetter.fetchPricesForPerpetual(symbol)];
206
+ case 1:
207
+ obj = _a.sent();
208
+ return [4 /*yield*/, PerpetualDataHandler.getMarginAccount(traderAddr, symbol, this.symbolToPerpStaticInfo, this.proxyContract, [obj.idxPrices[0], obj.idxPrices[1]])];
209
+ case 2:
210
+ mgnAcct = _a.sent();
211
+ return [2 /*return*/, mgnAcct];
212
+ }
213
+ });
214
+ });
215
+ };
216
+ /**
217
+ * Estimates what the position risk will be if a given order is executed.
218
+ * @param traderAddr Address of trader
219
+ * @param order Order to be submitted
220
+ * @param account Position risk before trade
221
+ * @param indexPriceInfo Index prices and market status (open/closed)
222
+ * @returns {MarginAccount} Position risk after trade
223
+ */
224
+ MarketData.prototype.positionRiskOnTrade = function (traderAddr, order, account, indexPriceInfo) {
225
+ var _a, _b, _c, _d, _e;
226
+ return __awaiter(this, void 0, void 0, function () {
227
+ var obj, lotSizeBC, perpetualState, _f, S2, S3, Sm, currentMarginCashCC, currentPositionBC, currentLockedInQC, tradeAmountBC, newPositionBC, newSide, tradePrice, _g, poolId, exchangeFeeTbps, exchangeFeeCC, brokerFeeCC, referralFeeCC, isClose, isOpen, isFlip, keepPositionLvgOnClose, traderDepositCC, targetLvg, initialMarginRate, _h, b0, pos0, deltaCashCC, deltaLockedQC, pnl, newLockedInValueQC, newMarginCashCC, newEntryPrice, newMarginBalanceCC, newLeverage, _j, S2Liq, S3Liq, tau, newPositionRisk;
228
+ return __generator(this, function (_k) {
229
+ switch (_k.label) {
230
+ case 0:
231
+ if (this.proxyContract == null) {
232
+ throw Error("no proxy contract initialized. Use createProxyInstance().");
233
+ }
234
+ if (!(account == undefined)) return [3 /*break*/, 2];
235
+ return [4 /*yield*/, this.positionRisk(traderAddr, order.symbol)];
236
+ case 1:
237
+ account = _k.sent();
238
+ _k.label = 2;
239
+ case 2:
240
+ if (!(indexPriceInfo == undefined)) return [3 /*break*/, 4];
241
+ return [4 /*yield*/, this.priceFeedGetter.fetchPricesForPerpetual(account.symbol)];
242
+ case 3:
243
+ obj = _k.sent();
244
+ indexPriceInfo = [obj.idxPrices[0], obj.idxPrices[1], obj.mktClosed[0], obj.mktClosed[1]];
245
+ _k.label = 4;
246
+ case 4:
247
+ lotSizeBC = MarketData._getLotSize(account.symbol, this.symbolToPerpStaticInfo);
248
+ // Too small, no change to account
249
+ if (Math.abs(order.quantity) < lotSizeBC) {
250
+ return [2 /*return*/, { newPositionRisk: account, orderCost: 0 }];
251
+ }
252
+ return [4 /*yield*/, this.getPerpetualState(order.symbol, indexPriceInfo)];
253
+ case 5:
254
+ perpetualState = _k.sent();
255
+ _f = __read([perpetualState.indexPrice, perpetualState.collToQuoteIndexPrice, perpetualState.markPrice], 3), S2 = _f[0], S3 = _f[1], Sm = _f[2];
256
+ currentMarginCashCC = account.collateralCC;
257
+ currentPositionBC = (account.side == BUY_SIDE ? 1 : -1) * account.positionNotionalBaseCCY;
258
+ currentLockedInQC = account.entryPrice * currentPositionBC;
259
+ tradeAmountBC = Math.abs(order.quantity) * (order.side == BUY_SIDE ? 1 : -1);
260
+ newPositionBC = currentPositionBC + tradeAmountBC;
261
+ if (Math.abs(newPositionBC) < 10 * lotSizeBC) {
262
+ // fully closed
263
+ tradeAmountBC = -currentPositionBC;
264
+ newPositionBC = 0;
265
+ }
266
+ newSide = newPositionBC > 0 ? BUY_SIDE : newPositionBC < 0 ? SELL_SIDE : CLOSED_SIDE;
267
+ if (!((_a = order.limitPrice) !== null && _a !== void 0)) return [3 /*break*/, 6];
268
+ _g = _a;
269
+ return [3 /*break*/, 8];
270
+ case 6: return [4 /*yield*/, this.getPerpetualPrice(order.symbol, tradeAmountBC)];
271
+ case 7:
272
+ _g = (_k.sent());
273
+ _k.label = 8;
274
+ case 8:
275
+ tradePrice = _g;
276
+ poolId = PerpetualDataHandler._getPoolIdFromSymbol(order.symbol, this.poolStaticInfos);
277
+ return [4 /*yield*/, this.proxyContract.queryExchangeFee(poolId, traderAddr, (_b = order.brokerAddr) !== null && _b !== void 0 ? _b : ZERO_ADDRESS)];
278
+ case 9:
279
+ exchangeFeeTbps = _k.sent();
280
+ exchangeFeeCC = (Math.abs(tradeAmountBC) * exchangeFeeTbps * 1e-5 * S2) / S3;
281
+ brokerFeeCC = (Math.abs(tradeAmountBC) * ((_c = order.brokerFeeTbps) !== null && _c !== void 0 ? _c : 0) * 1e-5 * S2) / S3;
282
+ referralFeeCC = this.symbolToPerpStaticInfo.get(account.symbol).referralRebate;
283
+ isClose = newPositionBC == 0 || newPositionBC * tradeAmountBC < 0;
284
+ isOpen = newPositionBC != 0 && (currentPositionBC == 0 || tradeAmountBC * currentPositionBC > 0);
285
+ isFlip = Math.abs(newPositionBC) > Math.abs(currentPositionBC) && !isOpen;
286
+ keepPositionLvgOnClose = ((_d = order.keepPositionLvg) !== null && _d !== void 0 ? _d : false) && !isOpen;
287
+ if (order.leverage == undefined || newPositionBC == 0 || (!isOpen && !isFlip && !keepPositionLvgOnClose)) {
288
+ traderDepositCC = 0;
289
+ targetLvg = 0;
290
+ }
291
+ else {
292
+ initialMarginRate = this.symbolToPerpStaticInfo.get(account.symbol).initialMarginRate;
293
+ targetLvg = isFlip || isOpen ? (_e = order.leverage) !== null && _e !== void 0 ? _e : 1 / initialMarginRate : 0;
294
+ _h = __read(isOpen ? [0, 0] : [account.collateralCC, currentPositionBC], 2), b0 = _h[0], pos0 = _h[1];
295
+ traderDepositCC = getDepositAmountForLvgTrade(b0, pos0, tradeAmountBC, targetLvg, tradePrice, S3, Sm);
296
+ // fees are paid from wallet in this case
297
+ traderDepositCC += exchangeFeeCC + brokerFeeCC + referralFeeCC;
298
+ }
299
+ deltaCashCC = (-tradeAmountBC * (tradePrice - S2)) / S3;
300
+ deltaLockedQC = tradeAmountBC * S2;
301
+ if (isClose) {
302
+ pnl = account.entryPrice * tradeAmountBC - deltaLockedQC;
303
+ deltaLockedQC += pnl;
304
+ deltaCashCC += pnl / S3;
305
+ }
306
+ // funding and fees
307
+ deltaCashCC = deltaCashCC + account.unrealizedFundingCollateralCCY - exchangeFeeCC - brokerFeeCC - referralFeeCC;
308
+ newLockedInValueQC = currentLockedInQC + deltaLockedQC;
309
+ newMarginCashCC = currentMarginCashCC + deltaCashCC + traderDepositCC;
310
+ newEntryPrice = newPositionBC == 0 ? 0 : Math.abs(newLockedInValueQC / newPositionBC);
311
+ newMarginBalanceCC = newMarginCashCC + (newPositionBC * Sm - newLockedInValueQC) / S3;
312
+ newLeverage = newPositionBC == 0
313
+ ? 0
314
+ : newMarginBalanceCC <= 0
315
+ ? Infinity
316
+ : (Math.abs(newPositionBC) * Sm) / S3 / newMarginBalanceCC;
317
+ _j = __read(MarketData._getLiquidationParams(account.symbol, newLockedInValueQC, newPositionBC, newMarginCashCC, Sm, S3, this.symbolToPerpStaticInfo), 3), S2Liq = _j[0], S3Liq = _j[1], tau = _j[2];
318
+ newPositionRisk = {
319
+ symbol: account.symbol,
320
+ positionNotionalBaseCCY: Math.abs(newPositionBC),
321
+ side: newSide,
322
+ entryPrice: newEntryPrice,
323
+ leverage: newLeverage,
324
+ markPrice: Sm,
325
+ unrealizedPnlQuoteCCY: newPositionBC * Sm - newLockedInValueQC,
326
+ unrealizedFundingCollateralCCY: 0,
327
+ collateralCC: newMarginCashCC,
328
+ collToQuoteConversion: S3,
329
+ liquidationPrice: [S2Liq, S3Liq],
330
+ liquidationLvg: 1 / tau,
331
+ };
332
+ return [2 /*return*/, { newPositionRisk: newPositionRisk, orderCost: traderDepositCC }];
333
+ }
334
+ });
335
+ });
336
+ };
337
+ /**
338
+ * Estimates what the position risk will be if given amount of collateral is added/removed from the account.
339
+ * @param traderAddr Address of trader
340
+ * @param deltaCollateral Amount of collateral to add or remove (signed)
341
+ * @param currentPositionRisk Position risk before
342
+ * @returns {MarginAccount} Position risk after
343
+ */
344
+ MarketData.prototype.positionRiskOnCollateralAction = function (deltaCollateral, account, indexPriceInfo) {
345
+ return __awaiter(this, void 0, void 0, function () {
346
+ var obj, perpetualState, _a, S2, S3, Sm, positionBC, lockedInQC, newMarginCashCC, newMarginBalanceCC, newLeverage, _b, S2Liq, S3Liq, tau, newPositionRisk;
347
+ return __generator(this, function (_c) {
348
+ switch (_c.label) {
349
+ case 0:
350
+ if (this.proxyContract == null) {
351
+ throw Error("no proxy contract initialized. Use createProxyInstance().");
352
+ }
353
+ if (deltaCollateral + account.collateralCC + account.unrealizedFundingCollateralCCY < 0) {
354
+ throw Error("not enough margin to remove");
355
+ }
356
+ if (!(indexPriceInfo == undefined)) return [3 /*break*/, 2];
357
+ return [4 /*yield*/, this.priceFeedGetter.fetchPricesForPerpetual(account.symbol)];
358
+ case 1:
359
+ obj = _c.sent();
360
+ indexPriceInfo = [obj.idxPrices[0], obj.idxPrices[1], obj.mktClosed[0], obj.mktClosed[1]];
361
+ _c.label = 2;
362
+ case 2: return [4 /*yield*/, this.getPerpetualState(account.symbol, indexPriceInfo)];
363
+ case 3:
364
+ perpetualState = _c.sent();
365
+ _a = __read([perpetualState.indexPrice, perpetualState.collToQuoteIndexPrice, perpetualState.markPrice], 3), S2 = _a[0], S3 = _a[1], Sm = _a[2];
366
+ // no position: just increase collateral and kill liquidation vars
367
+ if (account.positionNotionalBaseCCY == 0) {
368
+ return [2 /*return*/, {
369
+ symbol: account.symbol,
370
+ positionNotionalBaseCCY: account.positionNotionalBaseCCY,
371
+ side: account.side,
372
+ entryPrice: account.entryPrice,
373
+ leverage: account.leverage,
374
+ markPrice: Sm,
375
+ unrealizedPnlQuoteCCY: account.unrealizedPnlQuoteCCY,
376
+ unrealizedFundingCollateralCCY: account.unrealizedFundingCollateralCCY,
377
+ collateralCC: account.collateralCC + deltaCollateral,
378
+ collToQuoteConversion: S3,
379
+ liquidationPrice: [0, undefined],
380
+ liquidationLvg: Infinity,
381
+ }];
382
+ }
383
+ positionBC = account.positionNotionalBaseCCY * (account.side == BUY_SIDE ? 1 : -1);
384
+ lockedInQC = account.entryPrice * positionBC;
385
+ newMarginCashCC = account.collateralCC + deltaCollateral;
386
+ newMarginBalanceCC = newMarginCashCC + account.unrealizedFundingCollateralCCY + (positionBC * Sm - lockedInQC) / S3;
387
+ if (newMarginBalanceCC <= 0) {
388
+ return [2 /*return*/, {
389
+ symbol: account.symbol,
390
+ positionNotionalBaseCCY: account.positionNotionalBaseCCY,
391
+ side: account.side,
392
+ entryPrice: account.entryPrice,
393
+ leverage: Infinity,
394
+ markPrice: Sm,
395
+ unrealizedPnlQuoteCCY: account.unrealizedPnlQuoteCCY,
396
+ unrealizedFundingCollateralCCY: account.unrealizedFundingCollateralCCY,
397
+ collateralCC: newMarginCashCC,
398
+ collToQuoteConversion: S3,
399
+ liquidationPrice: [S2, S3],
400
+ liquidationLvg: 0,
401
+ }];
402
+ }
403
+ newLeverage = (Math.abs(positionBC) * Sm) / S3 / newMarginBalanceCC;
404
+ _b = __read(MarketData._getLiquidationParams(account.symbol, lockedInQC, positionBC, newMarginCashCC, Sm, S3, this.symbolToPerpStaticInfo), 3), S2Liq = _b[0], S3Liq = _b[1], tau = _b[2];
405
+ newPositionRisk = {
406
+ symbol: account.symbol,
407
+ positionNotionalBaseCCY: account.positionNotionalBaseCCY,
408
+ side: account.side,
409
+ entryPrice: account.entryPrice,
410
+ leverage: newLeverage,
411
+ markPrice: Sm,
412
+ unrealizedPnlQuoteCCY: account.unrealizedPnlQuoteCCY,
413
+ unrealizedFundingCollateralCCY: account.unrealizedFundingCollateralCCY,
414
+ collateralCC: newMarginCashCC,
415
+ collToQuoteConversion: S3,
416
+ liquidationPrice: [S2Liq, S3Liq],
417
+ liquidationLvg: 1 / tau,
418
+ };
419
+ return [2 /*return*/, newPositionRisk];
420
+ }
421
+ });
422
+ });
423
+ };
424
+ MarketData._getLiquidationParams = function (symbol, lockedInQC, signedPositionBC, marginCashCC, markPrice, collToQuoteConversion, symbolToPerpStaticInfo) {
425
+ var S2Liq, S3Liq;
426
+ var tau = symbolToPerpStaticInfo.get(symbol).maintenanceMarginRate;
427
+ var ccyType = symbolToPerpStaticInfo.get(symbol).collateralCurrencyType;
428
+ if (ccyType == CollaterlCCY.BASE) {
429
+ S2Liq = calculateLiquidationPriceCollateralBase(lockedInQC, signedPositionBC, marginCashCC, tau);
430
+ S3Liq = S2Liq;
431
+ }
432
+ else if (ccyType == CollaterlCCY.QUANTO) {
433
+ S3Liq = collToQuoteConversion;
434
+ S2Liq = calculateLiquidationPriceCollateralQuanto(lockedInQC, signedPositionBC, marginCashCC, tau, collToQuoteConversion, markPrice);
435
+ }
436
+ else {
437
+ S2Liq = calculateLiquidationPriceCollateralQuote(lockedInQC, signedPositionBC, marginCashCC, tau);
438
+ }
439
+ // floor at 0
440
+ S2Liq = S2Liq < 0 ? 0 : S2Liq;
441
+ S3Liq = S3Liq && S3Liq < 0 ? 0 : S3Liq;
442
+ return [S2Liq, S3Liq, tau];
443
+ };
444
+ /**
445
+ * Gets the wallet balance in the collateral currency corresponding to a given perpetual symbol.
446
+ * @param address Address to check
447
+ * @param symbol Symbol of the form ETH-USD-MATIC.
448
+ * @returns Balance
449
+ */
450
+ MarketData.prototype.getWalletBalance = function (address, symbol) {
451
+ return __awaiter(this, void 0, void 0, function () {
452
+ var poolIdx, marginTokenAddr, token, walletBalanceDec18;
453
+ return __generator(this, function (_a) {
454
+ switch (_a.label) {
455
+ case 0:
456
+ poolIdx = this.getPoolIndexFromSymbol(symbol);
457
+ marginTokenAddr = this.poolStaticInfos[poolIdx].poolMarginTokenAddr;
458
+ token = new ethers.Contract(marginTokenAddr, ERC20_ABI, this.provider);
459
+ return [4 /*yield*/, token.balanceOf(address)];
460
+ case 1:
461
+ walletBalanceDec18 = _a.sent();
462
+ return [2 /*return*/, walletBalanceDec18 / Math.pow(10, 18)];
463
+ }
464
+ });
465
+ });
466
+ };
467
+ /**
468
+ * Gets the maximal order size to open positions (increase size),
469
+ * considering the existing position, state of the perpetual
470
+ * Ignores users wallet balance.
471
+ * @param side BUY or SELL
472
+ * @param positionRisk Current position risk (as seen in positionRisk)
473
+ * @returns Maximal trade size, not signed
474
+ */
475
+ MarketData.prototype.maxOrderSizeForTrader = function (side, positionRisk) {
476
+ return __awaiter(this, void 0, void 0, function () {
477
+ var curPosition, perpId, perpMaxPositionABK;
478
+ return __generator(this, function (_a) {
479
+ switch (_a.label) {
480
+ case 0:
481
+ curPosition = side == BUY_SIDE ? positionRisk.positionNotionalBaseCCY : -positionRisk.positionNotionalBaseCCY;
482
+ perpId = this.getPerpIdFromSymbol(positionRisk.symbol);
483
+ return [4 /*yield*/, this.proxyContract.getMaxSignedOpenTradeSizeForPos(perpId, floatToABK64x64(curPosition), side == BUY_SIDE)];
484
+ case 1:
485
+ perpMaxPositionABK = _a.sent();
486
+ return [2 /*return*/, ABK64x64ToFloat(perpMaxPositionABK.abs())];
487
+ }
488
+ });
489
+ });
490
+ };
491
+ /**
492
+ *
493
+ * @param side BUY_SIDE or SELL_SIDE
494
+ * @param symbol of the form ETH-USD-MATIC.
495
+ * @returns signed maximal position size in base currency
496
+ */
497
+ MarketData.prototype.maxSignedPosition = function (side, symbol) {
498
+ return __awaiter(this, void 0, void 0, function () {
499
+ var perpId, isBuy, maxSignedPos;
500
+ return __generator(this, function (_a) {
501
+ switch (_a.label) {
502
+ case 0:
503
+ perpId = this.getPerpIdFromSymbol(symbol);
504
+ isBuy = side == BUY_SIDE;
505
+ return [4 /*yield*/, this.proxyContract.getMaxSignedOpenTradeSizeForPos(perpId, BigNumber.from(0), isBuy)];
506
+ case 1:
507
+ maxSignedPos = _a.sent();
508
+ return [2 /*return*/, ABK64x64ToFloat(maxSignedPos)];
509
+ }
510
+ });
511
+ });
512
+ };
513
+ /**
514
+ * Uses the Oracle(s) in the exchange to get the latest price of a given index in a given currency, if a route exists.
515
+ * @param {string} base Index name, e.g. ETH.
516
+ * @param {string} quote Quote currency, e.g. USD.
517
+ * @example
518
+ * import { MarketData, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
519
+ * async function main() {
520
+ * console.log(MarketData);
521
+ * // setup
522
+ * const config = PerpetualDataHandler.readSDKConfig("testnet");
523
+ * let mktData = new MarketData(config);
524
+ * await mktData.createProxyInstance();
525
+ * // get oracle price
526
+ * let price = await mktData.getOraclePrice("ETH", "USD");
527
+ * console.log(price);
528
+ * }
529
+ * main();
530
+ *
531
+ * @returns {number} Price of index in given currency.
532
+ */
533
+ MarketData.prototype.getOraclePrice = function (base, quote) {
534
+ return __awaiter(this, void 0, void 0, function () {
535
+ var px;
536
+ return __generator(this, function (_a) {
537
+ switch (_a.label) {
538
+ case 0:
539
+ if (this.proxyContract == null) {
540
+ throw Error("no proxy contract initialized. Use createProxyInstance().");
541
+ }
542
+ return [4 /*yield*/, this.proxyContract.getOraclePrice([toBytes4(base), toBytes4(quote)])];
543
+ case 1:
544
+ px = _a.sent();
545
+ return [2 /*return*/, px == undefined ? undefined : ABK64x64ToFloat(px)];
546
+ }
547
+ });
548
+ });
549
+ };
550
+ MarketData.prototype.getOrderStatus = function (symbol, orderId) {
551
+ return __awaiter(this, void 0, void 0, function () {
552
+ var orderBookContract, status;
553
+ return __generator(this, function (_a) {
554
+ switch (_a.label) {
555
+ case 0:
556
+ if (this.proxyContract == null) {
557
+ throw Error("no proxy contract initialized. Use createProxyInstance().");
558
+ }
559
+ orderBookContract = null;
560
+ orderBookContract = this.getOrderBookContract(symbol);
561
+ return [4 /*yield*/, orderBookContract.getOrderStatus(orderId)];
562
+ case 1:
563
+ status = _a.sent();
564
+ return [2 /*return*/, status];
565
+ }
566
+ });
567
+ });
568
+ };
569
+ /**
570
+ * Get the current mark price
571
+ * @param symbol symbol of the form ETH-USD-MATIC
572
+ * @example
573
+ * import { MarketData, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
574
+ * async function main() {
575
+ * console.log(MarketData);
576
+ * // setup
577
+ * const config = PerpetualDataHandler.readSDKConfig("testnet");
578
+ * let mktData = new MarketData(config);
579
+ * await mktData.createProxyInstance();
580
+ * // get mark price
581
+ * let price = await mktData.getMarkPrice("ETH-USD-MATIC");
582
+ * console.log(price);
583
+ * }
584
+ * main();
585
+ *
586
+ * @returns mark price
587
+ */
588
+ MarketData.prototype.getMarkPrice = function (symbol, indexPrices) {
589
+ return __awaiter(this, void 0, void 0, function () {
590
+ var obj;
591
+ return __generator(this, function (_a) {
592
+ switch (_a.label) {
593
+ case 0:
594
+ if (this.proxyContract == null) {
595
+ throw Error("no proxy contract initialized. Use createProxyInstance().");
596
+ }
597
+ if (!(indexPrices == undefined)) return [3 /*break*/, 2];
598
+ return [4 /*yield*/, this.priceFeedGetter.fetchPricesForPerpetual(symbol)];
599
+ case 1:
600
+ obj = _a.sent();
601
+ indexPrices = [obj.idxPrices[0], obj.idxPrices[1]];
602
+ _a.label = 2;
603
+ case 2: return [4 /*yield*/, PerpetualDataHandler._queryPerpetualMarkPrice(symbol, this.symbolToPerpStaticInfo, this.proxyContract, indexPrices)];
604
+ case 3: return [2 /*return*/, _a.sent()];
605
+ }
606
+ });
607
+ });
608
+ };
609
+ /**
610
+ * get the current price for a given quantity
611
+ * @param symbol symbol of the form ETH-USD-MATIC
612
+ * @param quantity quantity to be traded, negative if short
613
+ * @example
614
+ * import { MarketData, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
615
+ * async function main() {
616
+ * console.log(MarketData);
617
+ * // setup
618
+ * const config = PerpetualDataHandler.readSDKConfig("testnet");
619
+ * let mktData = new MarketData(config);
620
+ * await mktData.createProxyInstance();
621
+ * // get perpetual price
622
+ * let price = await mktData.getPerpetualPrice("ETH-USD-MATIC", 1);
623
+ * console.log(price);
624
+ * }
625
+ * main();
626
+ *
627
+ * @returns price (number)
628
+ */
629
+ MarketData.prototype.getPerpetualPrice = function (symbol, quantity, indexPrices) {
630
+ return __awaiter(this, void 0, void 0, function () {
631
+ var obj;
632
+ return __generator(this, function (_a) {
633
+ switch (_a.label) {
634
+ case 0:
635
+ if (this.proxyContract == null) {
636
+ throw Error("no proxy contract initialized. Use createProxyInstance().");
637
+ }
638
+ if (!(indexPrices == undefined)) return [3 /*break*/, 2];
639
+ return [4 /*yield*/, this.priceFeedGetter.fetchPricesForPerpetual(symbol)];
640
+ case 1:
641
+ obj = _a.sent();
642
+ indexPrices = [obj.idxPrices[0], obj.idxPrices[1]];
643
+ _a.label = 2;
644
+ case 2: return [4 /*yield*/, PerpetualDataHandler._queryPerpetualPrice(symbol, quantity, this.symbolToPerpStaticInfo, this.proxyContract, indexPrices)];
645
+ case 3: return [2 /*return*/, _a.sent()];
646
+ }
647
+ });
648
+ });
649
+ };
650
+ /**
651
+ * Query recent perpetual state from blockchain
652
+ * @param symbol symbol of the form ETH-USD-MATIC
653
+ * @param indexPrices S2 and S3 prices/isMarketOpen if not provided fetch via REST API
654
+ * @returns PerpetualState reference
655
+ */
656
+ MarketData.prototype.getPerpetualState = function (symbol, indexPriceInfo) {
657
+ return __awaiter(this, void 0, void 0, function () {
658
+ var obj, state;
659
+ return __generator(this, function (_a) {
660
+ switch (_a.label) {
661
+ case 0:
662
+ if (this.proxyContract == null) {
663
+ throw Error("no proxy contract initialized. Use createProxyInstance().");
664
+ }
665
+ if (!(indexPriceInfo == undefined)) return [3 /*break*/, 2];
666
+ return [4 /*yield*/, this.priceFeedGetter.fetchPricesForPerpetual(symbol)];
667
+ case 1:
668
+ obj = _a.sent();
669
+ indexPriceInfo = [obj.idxPrices[0], obj.idxPrices[1], obj.mktClosed[0], obj.mktClosed[1]];
670
+ _a.label = 2;
671
+ case 2: return [4 /*yield*/, PerpetualDataHandler._queryPerpetualState(symbol, this.symbolToPerpStaticInfo, this.proxyContract, indexPriceInfo)];
672
+ case 3:
673
+ state = _a.sent();
674
+ return [2 /*return*/, state];
675
+ }
676
+ });
677
+ });
678
+ };
679
+ /**
680
+ * Query perpetual static info.
681
+ * This information is queried once at createProxyInstance-time and remains static after that.
682
+ * @param symbol symbol of the form ETH-USD-MATIC
683
+ * @returns PerpetualStaticInfo copy.
684
+ */
685
+ MarketData.prototype.getPerpetualStaticInfo = function (symbol) {
686
+ var perpInfo = this.symbolToPerpStaticInfo.get(symbol);
687
+ if (perpInfo == undefined) {
688
+ throw Error("Perpetual with symbol ".concat(symbol, " not found. Check symbol or use createProxyInstance()."));
689
+ }
690
+ // return new copy, not a reference
691
+ var res = {
692
+ id: perpInfo.id,
693
+ limitOrderBookAddr: perpInfo.limitOrderBookAddr,
694
+ initialMarginRate: perpInfo.initialMarginRate,
695
+ maintenanceMarginRate: perpInfo.maintenanceMarginRate,
696
+ collateralCurrencyType: perpInfo.collateralCurrencyType,
697
+ S2Symbol: perpInfo.S2Symbol,
698
+ S3Symbol: perpInfo.S3Symbol,
699
+ lotSizeBC: perpInfo.lotSizeBC,
700
+ referralRebate: perpInfo.referralRebate,
701
+ priceIds: perpInfo.priceIds,
702
+ };
703
+ return res;
704
+ };
705
+ /**
706
+ * get the current mid-price for a perpetual
707
+ * @param symbol symbol of the form ETH-USD-MATIC
708
+ * @example
709
+ * import { MarketData, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
710
+ * async function main() {
711
+ * console.log(MarketData);
712
+ * // setup
713
+ * const config = PerpetualDataHandler.readSDKConfig("testnet");
714
+ * let mktData = new MarketData(config);
715
+ * await mktData.createProxyInstance();
716
+ * // get perpetual mid price
717
+ * let midPrice = await mktData.getPerpetualMidPrice("ETH-USD-MATIC");
718
+ * console.log(midPrice);
719
+ * }
720
+ * main();
721
+ *
722
+ * @returns {number} price
723
+ */
724
+ MarketData.prototype.getPerpetualMidPrice = function (symbol) {
725
+ return __awaiter(this, void 0, void 0, function () {
726
+ return __generator(this, function (_a) {
727
+ switch (_a.label) {
728
+ case 0:
729
+ if (this.proxyContract == null) {
730
+ throw Error("no proxy contract initialized. Use createProxyInstance().");
731
+ }
732
+ return [4 /*yield*/, this.getPerpetualPrice(symbol, 0)];
733
+ case 1: return [2 /*return*/, _a.sent()];
734
+ }
735
+ });
736
+ });
737
+ };
738
+ /**
739
+ * Query smart contract to get user orders and convert to user friendly order format.
740
+ * @param {string} traderAddr Address of trader.
741
+ * @param {ethers.Contract} orderBookContract Instance of order book.
742
+ * @returns {Order[]} Array of user friendly order struct.
743
+ * @ignore
744
+ */
745
+ MarketData.prototype.openOrdersOnOrderBook = function (traderAddr, orderBookContract) {
746
+ return __awaiter(this, void 0, void 0, function () {
747
+ var orders, userFriendlyOrders, k;
748
+ return __generator(this, function (_a) {
749
+ switch (_a.label) {
750
+ case 0: return [4 /*yield*/, orderBookContract.getOrders(traderAddr, 0, 15)];
751
+ case 1:
752
+ orders = _a.sent();
753
+ userFriendlyOrders = new Array();
754
+ k = 0;
755
+ while (k < orders.length && orders[k].traderAddr != ZERO_ADDRESS) {
756
+ userFriendlyOrders.push(PerpetualDataHandler.fromClientOrder(orders[k], this.symbolToPerpStaticInfo));
757
+ k++;
758
+ }
759
+ return [2 /*return*/, userFriendlyOrders];
760
+ }
761
+ });
762
+ });
763
+ };
764
+ /**
765
+ *
766
+ * @param traderAddr Address of the trader
767
+ * @param orderBookContract Instance of order book contract
768
+ * @returns Array of order-id's
769
+ * @ignore
770
+ */
771
+ MarketData.orderIdsOfTrader = function (traderAddr, orderBookContract) {
772
+ return __awaiter(this, void 0, void 0, function () {
773
+ var digestsRaw, k, digests;
774
+ return __generator(this, function (_a) {
775
+ switch (_a.label) {
776
+ case 0: return [4 /*yield*/, orderBookContract.limitDigestsOfTrader(traderAddr, 0, 15)];
777
+ case 1:
778
+ digestsRaw = _a.sent();
779
+ k = 0;
780
+ digests = [];
781
+ while (k < digestsRaw.length && BigNumber.from(digestsRaw[k]).gt(0)) {
782
+ digests.push(digestsRaw[k]);
783
+ k++;
784
+ }
785
+ return [2 /*return*/, digests];
786
+ }
787
+ });
788
+ });
789
+ };
790
+ /**
791
+ * Query the available margin conditional on the given (or current) index prices
792
+ * Result is in collateral currency
793
+ * @param traderAddr address of the trader
794
+ * @param symbol perpetual symbol of the form BTC-USD-MATIC
795
+ * @param indexPrices optional index prices, will otherwise fetch from REST API
796
+ * @returns available margin in collateral currency
797
+ */
798
+ MarketData.prototype.getAvailableMargin = function (traderAddr, symbol, indexPrices) {
799
+ return __awaiter(this, void 0, void 0, function () {
800
+ var obj, perpID, traderState, idx_availableMargin, mgn;
801
+ return __generator(this, function (_a) {
802
+ switch (_a.label) {
803
+ case 0:
804
+ if (this.proxyContract == null) {
805
+ throw Error("no proxy contract initialized. Use createProxyInstance().");
806
+ }
807
+ if (!(indexPrices == undefined)) return [3 /*break*/, 2];
808
+ return [4 /*yield*/, this.priceFeedGetter.fetchPricesForPerpetual(symbol)];
809
+ case 1:
810
+ obj = _a.sent();
811
+ indexPrices = [obj.idxPrices[0], obj.idxPrices[1]];
812
+ _a.label = 2;
813
+ case 2:
814
+ perpID = PerpetualDataHandler.symbolToPerpetualId(symbol, this.symbolToPerpStaticInfo);
815
+ return [4 /*yield*/, this.proxyContract.getTraderState(perpID, traderAddr, indexPrices.map(function (x) { return floatToABK64x64(x); }))];
816
+ case 3:
817
+ traderState = _a.sent();
818
+ idx_availableMargin = 1;
819
+ mgn = ABK64x64ToFloat(traderState[idx_availableMargin]);
820
+ return [2 /*return*/, mgn];
821
+ }
822
+ });
823
+ });
824
+ };
825
+ /**
826
+ * Calculate a type of exchange loyality score based on trader volume
827
+ * @param traderAddr address of the trader
828
+ * @param brokerAddr address of the trader's broker or undefined
829
+ * @returns a loyality score (4 worst, 1 best)
830
+ */
831
+ MarketData.prototype.getTraderLoyalityScore = function (traderAddr, brokerAddr) {
832
+ return __awaiter(this, void 0, void 0, function () {
833
+ var brokerProm, traderProm, k, brkrVol_1, trdrVol_1, totalBrokerVolume, totalTraderVolume, brkrVol, trdrVol, k, volumeCap, score, rank4;
834
+ return __generator(this, function (_a) {
835
+ switch (_a.label) {
836
+ case 0:
837
+ if (this.proxyContract == null) {
838
+ throw Error("no proxy contract or wallet initialized. Use createProxyInstance().");
839
+ }
840
+ brokerProm = [];
841
+ traderProm = [];
842
+ for (k = 0; k < this.poolStaticInfos.length; k++) {
843
+ if (brokerAddr != "" && brokerAddr != undefined) {
844
+ brkrVol_1 = this.proxyContract.getCurrentBrokerVolume(this.poolStaticInfos[k].poolId, brokerAddr);
845
+ brokerProm.push(brkrVol_1);
846
+ }
847
+ trdrVol_1 = this.proxyContract.getCurrentTraderVolume(this.poolStaticInfos[k].poolId, traderAddr);
848
+ traderProm.push(trdrVol_1);
849
+ }
850
+ totalBrokerVolume = 0;
851
+ totalTraderVolume = 0;
852
+ return [4 /*yield*/, Promise.all(brokerProm)];
853
+ case 1:
854
+ brkrVol = _a.sent();
855
+ return [4 /*yield*/, Promise.all(traderProm)];
856
+ case 2:
857
+ trdrVol = _a.sent();
858
+ for (k = 0; k < this.poolStaticInfos.length; k++) {
859
+ if (brokerAddr != "" && brokerAddr != undefined) {
860
+ totalBrokerVolume += ABK64x64ToFloat(brkrVol[k]);
861
+ }
862
+ totalTraderVolume += ABK64x64ToFloat(trdrVol[k]);
863
+ }
864
+ volumeCap = 500000;
865
+ score = totalBrokerVolume == 0 ? totalTraderVolume / volumeCap : totalBrokerVolume;
866
+ rank4 = 1 + Math.floor(Math.min(score, 1 - 1e-15) * 4);
867
+ // desired ranking starts at 4 (worst) and ends at 1 (best)
868
+ return [2 /*return*/, 5 - rank4];
869
+ }
870
+ });
871
+ });
872
+ };
873
+ MarketData._exchangeInfo = function (_proxyContract, _poolStaticInfos, _symbolToPerpStaticInfo, _symbolList, _priceFeedGetter) {
874
+ return __awaiter(this, void 0, void 0, function () {
875
+ var nestedPerpetualIDs, factory, info, numPools, allSym, _a, _b, perpSymbol, sInfo, allSymArr, idxPriceMap, j, perpetualIDs, pool, PoolState, k, perp, symS2, symS3, res, _c, indexS2, isS2MktClosed, indexS3, isS3MktClosed, fMidPrice, markPremiumRate, currentFundingRateBps, state, isMktClosed, PerpetualState;
876
+ var e_1, _d;
877
+ return __generator(this, function (_e) {
878
+ switch (_e.label) {
879
+ case 0: return [4 /*yield*/, PerpetualDataHandler.getNestedPerpetualIds(_proxyContract)];
880
+ case 1:
881
+ nestedPerpetualIDs = _e.sent();
882
+ return [4 /*yield*/, _proxyContract.getOracleFactory()];
883
+ case 2:
884
+ factory = _e.sent();
885
+ info = { pools: [], oracleFactoryAddr: factory, proxyAddr: _proxyContract.address };
886
+ numPools = nestedPerpetualIDs.length;
887
+ allSym = new Set();
888
+ try {
889
+ for (_a = __values(_symbolToPerpStaticInfo.keys()), _b = _a.next(); !_b.done; _b = _a.next()) {
890
+ perpSymbol = _b.value;
891
+ sInfo = _symbolToPerpStaticInfo.get(perpSymbol);
892
+ allSym.add(sInfo.S2Symbol);
893
+ if (sInfo.S3Symbol != "") {
894
+ allSym.add(sInfo.S3Symbol);
895
+ }
896
+ }
897
+ }
898
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
899
+ finally {
900
+ try {
901
+ if (_b && !_b.done && (_d = _a.return)) _d.call(_a);
902
+ }
903
+ finally { if (e_1) throw e_1.error; }
904
+ }
905
+ allSymArr = Array.from(allSym.values());
906
+ return [4 /*yield*/, _priceFeedGetter.fetchPrices(allSymArr)];
907
+ case 3:
908
+ idxPriceMap = _e.sent();
909
+ j = 0;
910
+ _e.label = 4;
911
+ case 4:
912
+ if (!(j < numPools)) return [3 /*break*/, 12];
913
+ perpetualIDs = nestedPerpetualIDs[j];
914
+ return [4 /*yield*/, _proxyContract.getLiquidityPool(j + 1)];
915
+ case 5:
916
+ pool = _e.sent();
917
+ PoolState = {
918
+ isRunning: pool.isRunning,
919
+ poolSymbol: _poolStaticInfos[j].poolMarginSymbol,
920
+ marginTokenAddr: pool.marginTokenAddress,
921
+ poolShareTokenAddr: pool.shareTokenAddress,
922
+ defaultFundCashCC: ABK64x64ToFloat(pool.fDefaultFundCashCC),
923
+ pnlParticipantCashCC: ABK64x64ToFloat(pool.fPnLparticipantsCashCC),
924
+ totalAMMFundCashCC: ABK64x64ToFloat(pool.fAMMFundCashCC),
925
+ totalTargetAMMFundSizeCC: ABK64x64ToFloat(pool.fTargetAMMFundSize),
926
+ brokerCollateralLotSize: ABK64x64ToFloat(pool.fBrokerCollateralLotSize),
927
+ perpetuals: [],
928
+ };
929
+ k = 0;
930
+ _e.label = 6;
931
+ case 6:
932
+ if (!(k < perpetualIDs.length)) return [3 /*break*/, 10];
933
+ return [4 /*yield*/, _proxyContract.getPerpetual(perpetualIDs[k])];
934
+ case 7:
935
+ perp = _e.sent();
936
+ symS2 = contractSymbolToSymbol(perp.S2BaseCCY, _symbolList) +
937
+ "-" +
938
+ contractSymbolToSymbol(perp.S2QuoteCCY, _symbolList);
939
+ symS3 = contractSymbolToSymbol(perp.S3BaseCCY, _symbolList) +
940
+ "-" +
941
+ contractSymbolToSymbol(perp.S3QuoteCCY, _symbolList);
942
+ res = idxPriceMap.get(symS2);
943
+ if (res == undefined) {
944
+ throw new Error("Price for index ".concat(symS2, " could not be fetched - config issue"));
945
+ }
946
+ _c = __read([res[0], res[1]], 2), indexS2 = _c[0], isS2MktClosed = _c[1];
947
+ indexS3 = 1;
948
+ isS3MktClosed = false;
949
+ if (perp.eCollateralCurrency == COLLATERAL_CURRENCY_BASE) {
950
+ indexS3 = indexS2;
951
+ }
952
+ else if (perp.eCollateralCurrency == COLLATERAL_CURRENCY_QUANTO) {
953
+ res = idxPriceMap.get(symS3);
954
+ if (res == undefined) {
955
+ throw new Error("Price for index ".concat(symS3, " could not be fetched - config issue"));
956
+ }
957
+ else {
958
+ indexS3 = res[0];
959
+ isS3MktClosed = res[1];
960
+ }
961
+ }
962
+ return [4 /*yield*/, _proxyContract.queryPerpetualPrice(perpetualIDs[k], BigNumber.from(0), [
963
+ floatToABK64x64(indexS2),
964
+ floatToABK64x64(indexS3),
965
+ ])];
966
+ case 8:
967
+ fMidPrice = _e.sent();
968
+ markPremiumRate = ABK64x64ToFloat(perp.currentMarkPremiumRate.fPrice);
969
+ currentFundingRateBps = 1e4 * ABK64x64ToFloat(perp.fCurrentFundingRate);
970
+ state = PERP_STATE_STR[perp.state];
971
+ isMktClosed = isS2MktClosed || isS3MktClosed;
972
+ if (state == "NORMAL" && isMktClosed) {
973
+ state = "CLOSED";
974
+ }
975
+ PerpetualState = {
976
+ id: perp.id,
977
+ state: state,
978
+ baseCurrency: contractSymbolToSymbol(perp.S2BaseCCY, _symbolList),
979
+ quoteCurrency: contractSymbolToSymbol(perp.S2QuoteCCY, _symbolList),
980
+ indexPrice: indexS2,
981
+ collToQuoteIndexPrice: indexS3,
982
+ markPrice: indexS2 * (1 + markPremiumRate),
983
+ midPrice: ABK64x64ToFloat(fMidPrice),
984
+ currentFundingRateBps: currentFundingRateBps,
985
+ openInterestBC: ABK64x64ToFloat(perp.fOpenInterest),
986
+ isMarketClosed: isMktClosed,
987
+ };
988
+ PoolState.perpetuals.push(PerpetualState);
989
+ _e.label = 9;
990
+ case 9:
991
+ k++;
992
+ return [3 /*break*/, 6];
993
+ case 10:
994
+ info.pools.push(PoolState);
995
+ _e.label = 11;
996
+ case 11:
997
+ j++;
998
+ return [3 /*break*/, 4];
999
+ case 12: return [2 /*return*/, info];
1000
+ }
1001
+ });
1002
+ });
1003
+ };
1004
+ return MarketData;
1005
+ }(PerpetualDataHandler));
1006
+ export default MarketData;
1007
+ //# sourceMappingURL=marketData.js.map