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