@d8x/perpetuals-sdk 2.0.13-alpha → 2.1.0-alpha2

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 (255) hide show
  1. package/dist/cjs/abi/IPerpetualManager.json +124 -3
  2. package/dist/cjs/abi/OracleFactory.json +94 -25
  3. package/dist/cjs/abi/PerpetualManagerProxy.json +212 -2
  4. package/dist/cjs/brokerTool.d.ts +5 -1
  5. package/dist/cjs/brokerTool.js +14 -1
  6. package/dist/cjs/brokerTool.js.map +1 -1
  7. package/dist/cjs/config/priceFeedConfig.json +0 -18
  8. package/dist/cjs/contracts/IPerpetualManager.d.ts +74 -10
  9. package/dist/cjs/contracts/OracleFactory.d.ts +69 -20
  10. package/dist/cjs/contracts/PerpetualManagerProxy.d.ts +109 -4
  11. package/dist/cjs/contracts/factories/IPerpetualManager__factory.d.ts +95 -3
  12. package/dist/cjs/contracts/factories/IPerpetualManager__factory.js +124 -3
  13. package/dist/cjs/contracts/factories/IPerpetualManager__factory.js.map +1 -1
  14. package/dist/cjs/contracts/factories/OracleFactory__factory.d.ts +75 -20
  15. package/dist/cjs/contracts/factories/OracleFactory__factory.js +94 -25
  16. package/dist/cjs/contracts/factories/OracleFactory__factory.js.map +1 -1
  17. package/dist/cjs/contracts/factories/PerpetualManagerProxy__factory.d.ts +159 -2
  18. package/dist/cjs/contracts/factories/PerpetualManagerProxy__factory.js +212 -2
  19. package/dist/cjs/contracts/factories/PerpetualManagerProxy__factory.js.map +1 -1
  20. package/dist/cjs/d8XMath.d.ts +44 -1
  21. package/dist/cjs/d8XMath.js +236 -3
  22. package/dist/cjs/d8XMath.js.map +1 -1
  23. package/dist/cjs/liquidatorTool.d.ts +1 -0
  24. package/dist/cjs/liquidatorTool.js +24 -7
  25. package/dist/cjs/liquidatorTool.js.map +1 -1
  26. package/dist/cjs/marketData.d.ts +42 -20
  27. package/dist/cjs/marketData.js +261 -188
  28. package/dist/cjs/marketData.js.map +1 -1
  29. package/dist/cjs/nodeSDKTypes.d.ts +24 -2
  30. package/dist/cjs/nodeSDKTypes.js.map +1 -1
  31. package/dist/cjs/orderExecutorTool.d.ts +3 -3
  32. package/dist/cjs/orderExecutorTool.js +38 -13
  33. package/dist/cjs/orderExecutorTool.js.map +1 -1
  34. package/dist/cjs/perpetualDataHandler.d.ts +22 -12
  35. package/dist/cjs/perpetualDataHandler.js +59 -44
  36. package/dist/cjs/perpetualDataHandler.js.map +1 -1
  37. package/dist/cjs/perpetualEventHandler.d.ts +1 -1
  38. package/dist/cjs/perpetualEventHandler.js +6 -7
  39. package/dist/cjs/perpetualEventHandler.js.map +1 -1
  40. package/dist/cjs/polyMktsPxFeed.d.ts +6 -4
  41. package/dist/cjs/polyMktsPxFeed.js +24 -3
  42. package/dist/cjs/polyMktsPxFeed.js.map +1 -1
  43. package/dist/cjs/priceFeeds.d.ts +6 -7
  44. package/dist/cjs/priceFeeds.js +36 -14
  45. package/dist/cjs/priceFeeds.js.map +1 -1
  46. package/dist/cjs/version.d.ts +1 -1
  47. package/dist/cjs/version.js +1 -1
  48. package/dist/esm/abi/IPerpetualManager.json +124 -3
  49. package/dist/esm/abi/OracleFactory.json +94 -25
  50. package/dist/esm/abi/PerpetualManagerProxy.json +212 -2
  51. package/dist/esm/brokerTool.d.ts +5 -1
  52. package/dist/esm/brokerTool.js +15 -2
  53. package/dist/esm/brokerTool.js.map +1 -1
  54. package/dist/esm/config/priceFeedConfig.json +0 -18
  55. package/dist/esm/contracts/IPerpetualManager.d.ts +74 -10
  56. package/dist/esm/contracts/OracleFactory.d.ts +69 -20
  57. package/dist/esm/contracts/PerpetualManagerProxy.d.ts +109 -4
  58. package/dist/esm/contracts/factories/IPerpetualManager__factory.d.ts +95 -3
  59. package/dist/esm/contracts/factories/IPerpetualManager__factory.js +124 -3
  60. package/dist/esm/contracts/factories/IPerpetualManager__factory.js.map +1 -1
  61. package/dist/esm/contracts/factories/OracleFactory__factory.d.ts +75 -20
  62. package/dist/esm/contracts/factories/OracleFactory__factory.js +94 -25
  63. package/dist/esm/contracts/factories/OracleFactory__factory.js.map +1 -1
  64. package/dist/{cjs/contracts/factories/MockToken__factory.d.ts → esm/contracts/factories/PerpStorage__factory.d.ts} +115 -128
  65. package/dist/esm/contracts/factories/{MockToken__factory.js → PerpStorage__factory.js} +128 -139
  66. package/dist/esm/contracts/factories/PerpStorage__factory.js.map +1 -0
  67. package/dist/esm/contracts/factories/PerpetualManagerProxy__factory.d.ts +159 -2
  68. package/dist/esm/contracts/factories/PerpetualManagerProxy__factory.js +212 -2
  69. package/dist/esm/contracts/factories/PerpetualManagerProxy__factory.js.map +1 -1
  70. package/dist/esm/d8XMath.d.ts +44 -1
  71. package/dist/esm/d8XMath.js +229 -2
  72. package/dist/esm/d8XMath.js.map +1 -1
  73. package/dist/esm/liquidatorTool.d.ts +1 -0
  74. package/dist/esm/liquidatorTool.js +25 -8
  75. package/dist/esm/liquidatorTool.js.map +1 -1
  76. package/dist/esm/marketData.d.ts +42 -20
  77. package/dist/esm/marketData.js +263 -190
  78. package/dist/esm/marketData.js.map +1 -1
  79. package/dist/esm/nodeSDKTypes.d.ts +24 -2
  80. package/dist/esm/nodeSDKTypes.js.map +1 -1
  81. package/dist/esm/orderExecutorTool.d.ts +3 -3
  82. package/dist/esm/orderExecutorTool.js +38 -13
  83. package/dist/esm/orderExecutorTool.js.map +1 -1
  84. package/dist/esm/perpetualDataHandler.d.ts +22 -12
  85. package/dist/esm/perpetualDataHandler.js +60 -45
  86. package/dist/esm/perpetualDataHandler.js.map +1 -1
  87. package/dist/esm/perpetualEventHandler.d.ts +1 -1
  88. package/dist/esm/perpetualEventHandler.js +6 -7
  89. package/dist/esm/perpetualEventHandler.js.map +1 -1
  90. package/dist/esm/polyMktsPxFeed.d.ts +6 -4
  91. package/dist/esm/polyMktsPxFeed.js +24 -3
  92. package/dist/esm/polyMktsPxFeed.js.map +1 -1
  93. package/dist/esm/priceFeeds.d.ts +6 -7
  94. package/dist/esm/priceFeeds.js +36 -14
  95. package/dist/esm/priceFeeds.js.map +1 -1
  96. package/dist/esm/version.d.ts +1 -1
  97. package/dist/esm/version.js +1 -1
  98. package/package.json +1 -1
  99. package/src/abi/IPerpetualManager.json +124 -3
  100. package/src/abi/OracleFactory.json +523 -454
  101. package/src/abi/PerpetualManagerProxy.json +1596 -1386
  102. package/src/brokerTool.ts +16 -2
  103. package/src/config/priceFeedConfig.json +0 -18
  104. package/src/contracts/IPerpetualManager.ts +107 -7
  105. package/src/contracts/OracleFactory.ts +100 -26
  106. package/src/contracts/PerpetualManagerProxy.ts +192 -3
  107. package/src/contracts/factories/IPerpetualManager__factory.ts +124 -3
  108. package/src/contracts/factories/OracleFactory__factory.ts +94 -25
  109. package/src/contracts/factories/PerpetualManagerProxy__factory.ts +212 -2
  110. package/src/d8XMath.ts +304 -2
  111. package/src/liquidatorTool.ts +29 -14
  112. package/src/marketData.ts +415 -238
  113. package/src/nodeSDKTypes.ts +30 -2
  114. package/src/orderExecutorTool.ts +48 -20
  115. package/src/perpetualDataHandler.ts +87 -45
  116. package/src/perpetualEventHandler.ts +6 -7
  117. package/src/polyMktsPxFeed.ts +30 -5
  118. package/src/priceFeeds.ts +41 -17
  119. package/src/version.ts +1 -1
  120. package/dist/cjs/abi/BeaconProxy.json +0 -71
  121. package/dist/cjs/abi/Maintainer.json +0 -774
  122. package/dist/cjs/abi/MockToken.json +0 -347
  123. package/dist/cjs/abi/UUPSUpgradeable.json +0 -104
  124. package/dist/cjs/abi/WeETH.json +0 -310
  125. package/dist/cjs/abi-zkevm/LimitOrderBook.json +0 -910
  126. package/dist/cjs/abi-zkevm/LimitOrderBookFactory.json +0 -236
  127. package/dist/cjs/contracts/BeaconProxy.d.ts +0 -63
  128. package/dist/cjs/contracts/BeaconProxy.js +0 -3
  129. package/dist/cjs/contracts/BeaconProxy.js.map +0 -1
  130. package/dist/cjs/contracts/Maintainer.d.ts +0 -799
  131. package/dist/cjs/contracts/Maintainer.js +0 -3
  132. package/dist/cjs/contracts/Maintainer.js.map +0 -1
  133. package/dist/cjs/contracts/MockToken.d.ts +0 -263
  134. package/dist/cjs/contracts/MockToken.js +0 -3
  135. package/dist/cjs/contracts/MockToken.js.map +0 -1
  136. package/dist/cjs/contracts/UUPSUpgradeable.d.ts +0 -118
  137. package/dist/cjs/contracts/UUPSUpgradeable.js +0 -3
  138. package/dist/cjs/contracts/UUPSUpgradeable.js.map +0 -1
  139. package/dist/cjs/contracts/WeETH.d.ts +0 -503
  140. package/dist/cjs/contracts/WeETH.js +0 -3
  141. package/dist/cjs/contracts/WeETH.js.map +0 -1
  142. package/dist/cjs/contracts/factories/BeaconProxy__factory.d.ts +0 -61
  143. package/dist/cjs/contracts/factories/BeaconProxy__factory.js +0 -89
  144. package/dist/cjs/contracts/factories/BeaconProxy__factory.js.map +0 -1
  145. package/dist/cjs/contracts/factories/Maintainer__factory.d.ts +0 -609
  146. package/dist/cjs/contracts/factories/Maintainer__factory.js +0 -792
  147. package/dist/cjs/contracts/factories/Maintainer__factory.js.map +0 -1
  148. package/dist/cjs/contracts/factories/MockToken__factory.js +0 -365
  149. package/dist/cjs/contracts/factories/MockToken__factory.js.map +0 -1
  150. package/dist/cjs/contracts/factories/UUPSUpgradeable__factory.d.ts +0 -87
  151. package/dist/cjs/contracts/factories/UUPSUpgradeable__factory.js +0 -122
  152. package/dist/cjs/contracts/factories/UUPSUpgradeable__factory.js.map +0 -1
  153. package/dist/cjs/contracts/factories/WeETH__factory.d.ts +0 -545
  154. package/dist/cjs/contracts/factories/WeETH__factory.js +0 -721
  155. package/dist/cjs/contracts/factories/WeETH__factory.js.map +0 -1
  156. package/dist/cjs/contracts/factories/lean0/IPerpetualManager__factory.d.ts +0 -4136
  157. package/dist/cjs/contracts/factories/lean0/IPerpetualManager__factory.js +0 -5324
  158. package/dist/cjs/contracts/factories/lean0/IPerpetualManager__factory.js.map +0 -1
  159. package/dist/cjs/contracts/factories/lean0/LimitOrderBookFactory__factory.d.ts +0 -189
  160. package/dist/cjs/contracts/factories/lean0/LimitOrderBookFactory__factory.js +0 -254
  161. package/dist/cjs/contracts/factories/lean0/LimitOrderBookFactory__factory.js.map +0 -1
  162. package/dist/cjs/contracts/factories/lean0/LimitOrderBook__factory.d.ts +0 -715
  163. package/dist/cjs/contracts/factories/lean0/LimitOrderBook__factory.js +0 -928
  164. package/dist/cjs/contracts/factories/lean0/LimitOrderBook__factory.js.map +0 -1
  165. package/dist/cjs/contracts/factories/lean0/ShareToken__factory.d.ts +0 -344
  166. package/dist/cjs/contracts/factories/lean0/ShareToken__factory.js +0 -456
  167. package/dist/cjs/contracts/factories/lean0/ShareToken__factory.js.map +0 -1
  168. package/dist/cjs/contracts/factories/lean0/index.d.ts +0 -4
  169. package/dist/cjs/contracts/factories/lean0/index.js +0 -15
  170. package/dist/cjs/contracts/factories/lean0/index.js.map +0 -1
  171. package/dist/cjs/contracts/lean0/IPerpetualManager.d.ts +0 -2821
  172. package/dist/cjs/contracts/lean0/IPerpetualManager.js +0 -3
  173. package/dist/cjs/contracts/lean0/IPerpetualManager.js.map +0 -1
  174. package/dist/cjs/contracts/lean0/LimitOrderBook.d.ts +0 -533
  175. package/dist/cjs/contracts/lean0/LimitOrderBook.js +0 -3
  176. package/dist/cjs/contracts/lean0/LimitOrderBook.js.map +0 -1
  177. package/dist/cjs/contracts/lean0/LimitOrderBookFactory.d.ts +0 -210
  178. package/dist/cjs/contracts/lean0/LimitOrderBookFactory.js +0 -3
  179. package/dist/cjs/contracts/lean0/LimitOrderBookFactory.js.map +0 -1
  180. package/dist/cjs/contracts/lean0/ShareToken.d.ts +0 -320
  181. package/dist/cjs/contracts/lean0/ShareToken.js +0 -3
  182. package/dist/cjs/contracts/lean0/ShareToken.js.map +0 -1
  183. package/dist/cjs/contracts/lean0/index.d.ts +0 -4
  184. package/dist/cjs/contracts/lean0/index.js +0 -3
  185. package/dist/cjs/contracts/lean0/index.js.map +0 -1
  186. package/dist/esm/abi/BeaconProxy.json +0 -71
  187. package/dist/esm/abi/Maintainer.json +0 -774
  188. package/dist/esm/abi/MockToken.json +0 -347
  189. package/dist/esm/abi/UUPSUpgradeable.json +0 -104
  190. package/dist/esm/abi/WeETH.json +0 -310
  191. package/dist/esm/abi/lean0/IPerpetualManager.json +0 -5306
  192. package/dist/esm/abi/lean0/LimitOrderBook.json +0 -910
  193. package/dist/esm/abi/lean0/LimitOrderBookFactory.json +0 -236
  194. package/dist/esm/abi/lean0/ShareToken.json +0 -438
  195. package/dist/esm/abi-zkevm/LimitOrderBook.json +0 -910
  196. package/dist/esm/abi-zkevm/LimitOrderBookFactory.json +0 -236
  197. package/dist/esm/contracts/BeaconProxy.d.ts +0 -63
  198. package/dist/esm/contracts/BeaconProxy.js +0 -2
  199. package/dist/esm/contracts/BeaconProxy.js.map +0 -1
  200. package/dist/esm/contracts/Maintainer.d.ts +0 -799
  201. package/dist/esm/contracts/Maintainer.js +0 -2
  202. package/dist/esm/contracts/Maintainer.js.map +0 -1
  203. package/dist/esm/contracts/MockToken.d.ts +0 -263
  204. package/dist/esm/contracts/MockToken.js +0 -2
  205. package/dist/esm/contracts/MockToken.js.map +0 -1
  206. package/dist/esm/contracts/UUPSUpgradeable.d.ts +0 -118
  207. package/dist/esm/contracts/UUPSUpgradeable.js +0 -2
  208. package/dist/esm/contracts/UUPSUpgradeable.js.map +0 -1
  209. package/dist/esm/contracts/WeETH.d.ts +0 -503
  210. package/dist/esm/contracts/WeETH.js +0 -2
  211. package/dist/esm/contracts/WeETH.js.map +0 -1
  212. package/dist/esm/contracts/factories/BeaconProxy__factory.d.ts +0 -61
  213. package/dist/esm/contracts/factories/BeaconProxy__factory.js +0 -85
  214. package/dist/esm/contracts/factories/BeaconProxy__factory.js.map +0 -1
  215. package/dist/esm/contracts/factories/Maintainer__factory.d.ts +0 -609
  216. package/dist/esm/contracts/factories/Maintainer__factory.js +0 -788
  217. package/dist/esm/contracts/factories/Maintainer__factory.js.map +0 -1
  218. package/dist/esm/contracts/factories/MockToken__factory.d.ts +0 -273
  219. package/dist/esm/contracts/factories/MockToken__factory.js.map +0 -1
  220. package/dist/esm/contracts/factories/UUPSUpgradeable__factory.d.ts +0 -87
  221. package/dist/esm/contracts/factories/UUPSUpgradeable__factory.js +0 -118
  222. package/dist/esm/contracts/factories/UUPSUpgradeable__factory.js.map +0 -1
  223. package/dist/esm/contracts/factories/WeETH__factory.d.ts +0 -545
  224. package/dist/esm/contracts/factories/WeETH__factory.js +0 -717
  225. package/dist/esm/contracts/factories/WeETH__factory.js.map +0 -1
  226. package/dist/esm/contracts/factories/lean0/IPerpetualManager__factory.d.ts +0 -4136
  227. package/dist/esm/contracts/factories/lean0/IPerpetualManager__factory.js +0 -5320
  228. package/dist/esm/contracts/factories/lean0/IPerpetualManager__factory.js.map +0 -1
  229. package/dist/esm/contracts/factories/lean0/LimitOrderBookFactory__factory.d.ts +0 -189
  230. package/dist/esm/contracts/factories/lean0/LimitOrderBookFactory__factory.js +0 -250
  231. package/dist/esm/contracts/factories/lean0/LimitOrderBookFactory__factory.js.map +0 -1
  232. package/dist/esm/contracts/factories/lean0/LimitOrderBook__factory.d.ts +0 -715
  233. package/dist/esm/contracts/factories/lean0/LimitOrderBook__factory.js +0 -924
  234. package/dist/esm/contracts/factories/lean0/LimitOrderBook__factory.js.map +0 -1
  235. package/dist/esm/contracts/factories/lean0/ShareToken__factory.d.ts +0 -344
  236. package/dist/esm/contracts/factories/lean0/ShareToken__factory.js +0 -452
  237. package/dist/esm/contracts/factories/lean0/ShareToken__factory.js.map +0 -1
  238. package/dist/esm/contracts/factories/lean0/index.d.ts +0 -4
  239. package/dist/esm/contracts/factories/lean0/index.js +0 -8
  240. package/dist/esm/contracts/factories/lean0/index.js.map +0 -1
  241. package/dist/esm/contracts/lean0/IPerpetualManager.d.ts +0 -2821
  242. package/dist/esm/contracts/lean0/IPerpetualManager.js +0 -2
  243. package/dist/esm/contracts/lean0/IPerpetualManager.js.map +0 -1
  244. package/dist/esm/contracts/lean0/LimitOrderBook.d.ts +0 -533
  245. package/dist/esm/contracts/lean0/LimitOrderBook.js +0 -2
  246. package/dist/esm/contracts/lean0/LimitOrderBook.js.map +0 -1
  247. package/dist/esm/contracts/lean0/LimitOrderBookFactory.d.ts +0 -210
  248. package/dist/esm/contracts/lean0/LimitOrderBookFactory.js +0 -2
  249. package/dist/esm/contracts/lean0/LimitOrderBookFactory.js.map +0 -1
  250. package/dist/esm/contracts/lean0/ShareToken.d.ts +0 -320
  251. package/dist/esm/contracts/lean0/ShareToken.js +0 -2
  252. package/dist/esm/contracts/lean0/ShareToken.js.map +0 -1
  253. package/dist/esm/contracts/lean0/index.d.ts +0 -4
  254. package/dist/esm/contracts/lean0/index.js +0 -2
  255. package/dist/esm/contracts/lean0/index.js.map +0 -1
package/src/marketData.ts CHANGED
@@ -34,6 +34,10 @@ import {
34
34
  floatToABK64x64,
35
35
  getDepositAmountForLvgTrade,
36
36
  getMaxSignedPositionSize,
37
+ entropy,
38
+ expectedLoss,
39
+ pmExchangeFee,
40
+ pmFindMaxTradeSize,
37
41
  } from "./d8XMath";
38
42
  import {
39
43
  type ExchangeInfo,
@@ -45,6 +49,7 @@ import {
45
49
  type PoolState,
46
50
  type PoolStaticInfo,
47
51
  type SmartContractOrder,
52
+ type IdxPriceInfo,
48
53
  } from "./nodeSDKTypes";
49
54
  import PerpetualDataHandler from "./perpetualDataHandler";
50
55
  import PriceFeeds from "./priceFeeds";
@@ -405,12 +410,14 @@ export default class MarketData extends PerpetualDataHandler {
405
410
  overrides?: Overrides
406
411
  ): Promise<MarginAccount> {
407
412
  let obj = await this.priceFeedGetter.fetchPricesForPerpetual(symbol);
413
+ const isPred = this.isPredictionMarket(symbol);
408
414
  let mgnAcct = await PerpetualDataHandler.getMarginAccount(
409
415
  traderAddr,
410
416
  symbol,
411
417
  this.symbolToPerpStaticInfo,
412
418
  new Contract(this.proxyAddr, this.config.proxyABI!, provider),
413
- [obj.idxPrices[0], obj.idxPrices[1]],
419
+ obj,
420
+ isPred,
414
421
  overrides
415
422
  );
416
423
  return mgnAcct;
@@ -430,142 +437,86 @@ export default class MarketData extends PerpetualDataHandler {
430
437
  overrides?: Overrides
431
438
  ): Promise<MarginAccount[]> {
432
439
  const MAX_SYMBOLS_PER_CALL = 10;
433
- const S2S3 = new Array<[number, number]>();
440
+ const pxInfo = new Array<IdxPriceInfo>();
434
441
  for (let i = 0; i < symbols.length; i++) {
435
442
  let obj = await this.priceFeedGetter.fetchPricesForPerpetual(symbols[i]);
436
- S2S3.push([obj.idxPrices[0], obj.idxPrices[1]]);
443
+ pxInfo.push(obj);
437
444
  }
438
445
  let mgnAcct: MarginAccount[] = [];
439
446
  let callSymbols = symbols.slice(0, MAX_SYMBOLS_PER_CALL);
440
- let pxS2S3 = S2S3.slice(0, MAX_SYMBOLS_PER_CALL);
447
+ let _px = pxInfo.slice(0, MAX_SYMBOLS_PER_CALL);
441
448
  while (callSymbols.length > 0) {
449
+ const isPred = callSymbols.map((_sym) => this.isPredictionMarket(_sym));
442
450
  let acc = await PerpetualDataHandler.getMarginAccounts(
443
451
  Array(callSymbols.length).fill(traderAddr),
444
452
  callSymbols,
445
453
  this.symbolToPerpStaticInfo,
446
454
  Multicall3__factory.connect(this.config.multicall ?? MULTICALL_ADDRESS, provider),
447
455
  new Contract(this.proxyAddr, this.config.proxyABI!, provider),
448
- pxS2S3,
456
+ _px,
457
+ isPred,
449
458
  overrides
450
459
  );
451
460
  mgnAcct = mgnAcct.concat(acc);
452
461
  callSymbols = symbols.slice(mgnAcct.length, mgnAcct.length + MAX_SYMBOLS_PER_CALL);
453
- pxS2S3 = S2S3.slice(mgnAcct.length, mgnAcct.length + MAX_SYMBOLS_PER_CALL);
462
+ _px = pxInfo.slice(mgnAcct.length, mgnAcct.length + MAX_SYMBOLS_PER_CALL);
454
463
  }
455
464
  return mgnAcct;
456
465
  }
457
466
 
458
- /**
459
- * Estimates what the position risk will be if a given order is executed.
460
- * @param traderAddr Address of trader
461
- * @param order Order to be submitted
462
- * @param account Position risk before trade. Defaults to current position if not given.
463
- * @param indexPriceInfo Index prices and market status (open/closed). Defaults to current market status if not given.
464
- * @returns Position risk after trade, including order cost and maximal trade sizes for position
465
- * @example
466
- * import { MarketData, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
467
- * async function main() {
468
- * console.log(MarketData);
469
- * // setup
470
- * const config = PerpetualDataHandler.readSDKConfig("cardona");
471
- * const mktData = new MarketData(config);
472
- * await mktData.createProxyInstance();
473
- * const order: Order = {
474
- * symbol: "MATIC-USD-MATIC",
475
- * side: "BUY",
476
- * type: "MARKET",
477
- * quantity: 100,
478
- * leverage: 2,
479
- * executionTimestamp: Date.now()/1000,
480
- * };
481
- * // Get position risk conditional on this order being executed
482
- * const posRisk = await mktData.positionRiskOnTrade("0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B", order);
483
- * console.log(posRisk);
484
- * }
485
- * main();
486
- */
487
- public async positionRiskOnTrade(
467
+ private async dataForPositionRiskOnTrade(
468
+ symbol: string,
488
469
  traderAddr: string,
489
- order: Order,
490
- account?: MarginAccount,
491
- indexPriceInfo?: [number, number, boolean, boolean],
492
- overrides?: Overrides & { tradingFeeTbps?: number }
493
- ): Promise<{ newPositionRisk: MarginAccount; orderCost: number; maxLongTrade: number; maxShortTrade: number }> {
470
+ tradeAmountBC: number,
471
+ indexPriceInfo: IdxPriceInfo,
472
+ signedPositionNotionalBaseCCY: number,
473
+ overrides?: Overrides
474
+ ): Promise<{ account: MarginAccount; ammPrice: number; maxShortTrade: number; maxLongTrade: number }> {
494
475
  if (this.proxyContract == null || this.multicall == null) {
495
476
  throw Error("no proxy contract initialized. Use createProxyInstance().");
496
477
  }
497
-
498
- // fetch prices
499
- if (indexPriceInfo == undefined) {
500
- let obj = await this.priceFeedGetter.fetchPricesForPerpetual(order.symbol);
501
- indexPriceInfo = [obj.idxPrices[0], obj.idxPrices[1], obj.mktClosed[0], obj.mktClosed[1]];
502
- }
503
-
504
- // override total fee
505
- let tradingFeeTbps: number | undefined;
506
- if (overrides) {
507
- ({ tradingFeeTbps, ...overrides } = overrides);
508
- }
509
-
510
- // signed trade amount
511
- let tradeAmountBC = Math.abs(order.quantity) * (order.side == BUY_SIDE ? 1 : -1);
512
-
513
- const accountGiven = account !== undefined;
514
-
478
+ const isPredMkt = this.isPredictionMarket(symbol);
515
479
  // create all calls
516
- const poolId = PerpetualDataHandler._getPoolIdFromSymbol(order.symbol, this.poolStaticInfos);
517
- const perpId = PerpetualDataHandler.symbolToPerpetualId(order.symbol, this.symbolToPerpStaticInfo);
518
- const fS2S3 = [indexPriceInfo[0], indexPriceInfo[1]].map((x) => floatToABK64x64(x)) as [bigint, bigint];
480
+ const perpId = PerpetualDataHandler.symbolToPerpetualId(symbol, this.symbolToPerpStaticInfo);
481
+ const [fS2, fS3, fEma] = [indexPriceInfo.s2, indexPriceInfo.s3, indexPriceInfo.ema].map((x) =>
482
+ floatToABK64x64(x)
483
+ ) as [bigint, bigint, bigint];
519
484
  const proxyCalls: Multicall3.Call3Struct[] = [
520
485
  // 0: traderState
521
486
  {
522
487
  target: this.proxyContract.target,
523
488
  allowFailure: true,
524
- callData: this.proxyContract.interface.encodeFunctionData("getTraderState", [perpId, traderAddr, fS2S3]),
489
+ callData: this.proxyContract.interface.encodeFunctionData("getTraderState", [perpId, traderAddr, [fEma, fS3]]),
525
490
  },
526
- // 1: ammState
527
- {
528
- target: this.proxyContract.target,
529
- allowFailure: true,
530
- callData: this.proxyContract.interface.encodeFunctionData("getAMMState", [perpId, fS2S3]),
531
- },
532
- // 2: exchangeFee
533
- {
534
- target: this.proxyContract.target,
535
- allowFailure: false,
536
- callData: this.proxyContract.interface.encodeFunctionData("queryExchangeFee", [
537
- poolId,
538
- traderAddr,
539
- order.brokerAddr ?? ZERO_ADDRESS,
540
- ]),
541
- },
542
- // 3: perpetual price
491
+ // 1: perpetual price
543
492
  {
544
493
  target: this.proxyContract.target,
545
494
  allowFailure: true,
546
495
  callData: this.proxyContract.interface.encodeFunctionData("queryPerpetualPrice", [
547
496
  perpId,
548
497
  floatToABK64x64(tradeAmountBC),
549
- fS2S3,
498
+ [fS2, fS3],
499
+ indexPriceInfo.conf,
500
+ indexPriceInfo.predMktCLOBParams,
550
501
  ]),
551
502
  },
552
- // 4: max long pos
503
+ // 2: max long pos
553
504
  {
554
505
  target: this.proxyContract.target,
555
506
  allowFailure: false,
556
507
  callData: this.proxyContract.interface.encodeFunctionData("getMaxSignedOpenTradeSizeForPos", [
557
508
  perpId,
558
- account ? floatToABK64x64(account.positionNotionalBaseCCY * (account.side === BUY_SIDE ? 1 : -1)) : 0n,
509
+ floatToABK64x64(signedPositionNotionalBaseCCY),
559
510
  true,
560
511
  ]),
561
512
  },
562
- // 5: max short pos
513
+ // 3: max short pos
563
514
  {
564
515
  target: this.proxyContract.target,
565
516
  allowFailure: false,
566
517
  callData: this.proxyContract.interface.encodeFunctionData("getMaxSignedOpenTradeSizeForPos", [
567
518
  perpId,
568
- account ? floatToABK64x64(account.positionNotionalBaseCCY * (account.side === BUY_SIDE ? 1 : -1)) : 0n,
519
+ floatToABK64x64(signedPositionNotionalBaseCCY),
569
520
  false,
570
521
  ]),
571
522
  },
@@ -575,58 +526,126 @@ export default class MarketData extends PerpetualDataHandler {
575
526
  const encodedResults = await this.multicall.aggregate3.staticCall(proxyCalls, (overrides || {}) as Overrides);
576
527
 
577
528
  // positionRisk to apply this trade on: if not given, defaults to the current trader's position
578
- if (!account) {
579
- let traderState: bigint[];
580
- if (encodedResults[0].success) {
581
- traderState = this.proxyContract.interface.decodeFunctionResult(
582
- "getTraderState",
583
- encodedResults[0].returnData
584
- )[0];
585
- } else {
586
- traderState = await this.proxyContract.getTraderState(perpId, traderAddr, fS2S3);
587
- }
588
- account = MarketData.buildMarginAccountFromState(order.symbol, traderState, this.symbolToPerpStaticInfo, [
589
- indexPriceInfo[0],
590
- indexPriceInfo[1],
591
- ]);
592
- }
593
-
594
- // perpetualState, for prices
595
- let ammState: bigint[];
596
- if (encodedResults[1].success) {
597
- ammState = this.proxyContract.interface.decodeFunctionResult("getAMMState", encodedResults[1].returnData)[0];
529
+ let traderState: bigint[];
530
+ if (encodedResults[0].success) {
531
+ traderState = this.proxyContract.interface.decodeFunctionResult(
532
+ "getTraderState",
533
+ encodedResults[0].returnData
534
+ )[0];
598
535
  } else {
599
- ammState = await this.proxyContract.getAMMState(perpId, fS2S3);
536
+ traderState = await this.proxyContract.getTraderState(perpId, traderAddr, [fEma, fS3]);
600
537
  }
601
- const perpetualState = PerpetualDataHandler._parseAMMState(
602
- order.symbol,
603
- ammState,
604
- [0n, 0n], // not used below
605
- indexPriceInfo,
606
- this.symbolToPerpStaticInfo
538
+ const account = MarketData.buildMarginAccountFromState(
539
+ symbol,
540
+ traderState,
541
+ this.symbolToPerpStaticInfo,
542
+ indexPriceInfo!,
543
+ isPredMkt
607
544
  );
608
- let [S2, S3, Sm] = [perpetualState.indexPrice, perpetualState.collToQuoteIndexPrice, perpetualState.markPrice];
609
-
610
- // exchange fee based on this trader's address (volume, token holding, etc) and his broker address (if any)
611
- const exchangeFeeTbps = this.proxyContract.interface.decodeFunctionResult(
612
- "queryExchangeFee",
613
- encodedResults[2].returnData
614
- )[0] as bigint;
615
545
 
616
546
  // amm price for this trade amount
617
547
  let ammPrice: number;
618
548
  {
619
549
  let fPrice: bigint;
620
- if (encodedResults[3].success) {
550
+ if (encodedResults[1].success) {
621
551
  fPrice = this.proxyContract.interface.decodeFunctionResult(
622
552
  "queryPerpetualPrice",
623
- encodedResults[3].returnData
553
+ encodedResults[1].returnData
624
554
  )[0];
625
555
  } else {
626
- fPrice = await this.proxyContract.queryPerpetualPrice(perpId, floatToABK64x64(tradeAmountBC), fS2S3);
556
+ fPrice = await this.proxyContract.queryPerpetualPrice(
557
+ perpId,
558
+ floatToABK64x64(tradeAmountBC),
559
+ [indexPriceInfo.s2, indexPriceInfo.s3],
560
+ indexPriceInfo.conf,
561
+ indexPriceInfo.predMktCLOBParams
562
+ );
627
563
  }
628
564
  ammPrice = ABK64x64ToFloat(fPrice);
629
565
  }
566
+
567
+ // max buy
568
+ const fMaxLong = this.proxyContract.interface.decodeFunctionResult(
569
+ "getMaxSignedOpenTradeSizeForPos",
570
+ encodedResults[2].returnData
571
+ )[0] as bigint;
572
+ const maxLongTrade = Math.max(0, ABK64x64ToFloat(fMaxLong) - signedPositionNotionalBaseCCY);
573
+ // max sell
574
+ const fMaxShort = this.proxyContract.interface.decodeFunctionResult(
575
+ "getMaxSignedOpenTradeSizeForPos",
576
+ encodedResults[3].returnData
577
+ )[0] as bigint;
578
+ const maxShortTrade = Math.max(0, Math.abs(ABK64x64ToFloat(fMaxShort)) - signedPositionNotionalBaseCCY);
579
+ return { account: account, ammPrice: ammPrice, maxShortTrade: maxShortTrade, maxLongTrade: maxLongTrade };
580
+ }
581
+
582
+ /**
583
+ * Estimates what the position risk will be if a given order is executed.
584
+ * @param traderAddr Address of trader
585
+ * @param order Order to be submitted
586
+ * @param signedPositionNotionalBaseCCY signed position notional of current position (before trade)
587
+ * @param tradingFeeTbps trading fee in tenth of basis points (exchange fee and broker fee)
588
+ * @param indexPriceInfo Index prices and market status (open/closed). Defaults to current market status if not given.
589
+ * @returns Position risk after trade, including order cost and maximal trade sizes for position
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("cardona");
596
+ * const mktData = new MarketData(config);
597
+ * await mktData.createProxyInstance();
598
+ * const order: Order = {
599
+ * symbol: "MATIC-USD-MATIC",
600
+ * side: "BUY",
601
+ * type: "MARKET",
602
+ * quantity: 100,
603
+ * leverage: 2,
604
+ * executionTimestamp: Date.now()/1000,
605
+ * };
606
+ * // Get position risk conditional on this order being executed
607
+ * const posRisk = await mktData.positionRiskOnTrade("0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B", order, 0, 60);
608
+ * console.log(posRisk);
609
+ * }
610
+ * main();
611
+ */
612
+ public async positionRiskOnTrade(
613
+ traderAddr: string,
614
+ order: Order,
615
+ signedPositionNotionalBaseCCY: number,
616
+ tradingFeeTbps: number,
617
+ indexPriceInfo?: IdxPriceInfo,
618
+ overrides?: Overrides
619
+ ): Promise<{ newPositionRisk: MarginAccount; orderCost: number; maxLongTrade: number; maxShortTrade: number }> {
620
+ if (this.proxyContract == null || this.multicall == null) {
621
+ throw Error("no proxy contract initialized. Use createProxyInstance().");
622
+ }
623
+ const isPredMkt = this.isPredictionMarket(order.symbol);
624
+ // fetch prices
625
+ if (indexPriceInfo == undefined) {
626
+ indexPriceInfo = await this.priceFeedGetter.fetchPricesForPerpetual(order.symbol);
627
+ }
628
+
629
+ // signed trade amount
630
+ let tradeAmountBC = Math.abs(order.quantity) * (order.side == BUY_SIDE ? 1 : -1);
631
+ const symbol = order.symbol;
632
+
633
+ let obj = await this.dataForPositionRiskOnTrade(
634
+ symbol,
635
+ traderAddr,
636
+ tradeAmountBC,
637
+ indexPriceInfo,
638
+ signedPositionNotionalBaseCCY,
639
+ overrides
640
+ );
641
+ const account = obj.account;
642
+ const maxLongTrade = obj.maxLongTrade;
643
+ const maxShortTrade = obj.maxShortTrade;
644
+ const ammPrice = obj.ammPrice;
645
+ let Sm = account.markPrice;
646
+ let S2 = indexPriceInfo.s2;
647
+ let S3 = account.collToQuoteConversion;
648
+
630
649
  // price for this order = amm price if no limit given, else conservatively adjusted
631
650
  let tradePrice: number;
632
651
  if (order.limitPrice == undefined) {
@@ -660,27 +679,6 @@ export default class MarketData extends PerpetualDataHandler {
660
679
  }
661
680
  }
662
681
  }
663
- // max buy
664
- const fMaxLong = this.proxyContract.interface.decodeFunctionResult(
665
- "getMaxSignedOpenTradeSizeForPos",
666
- encodedResults[4].returnData
667
- )[0] as bigint;
668
- const maxLongTrade =
669
- account.side == BUY_SIDE
670
- ? Math.max(0, ABK64x64ToFloat(fMaxLong) - (accountGiven ? 0 : account.positionNotionalBaseCCY))
671
- : ABK64x64ToFloat(fMaxLong) + account.positionNotionalBaseCCY;
672
- // max sell
673
- const fMaxShort = this.proxyContract.interface.decodeFunctionResult(
674
- "getMaxSignedOpenTradeSizeForPos",
675
- encodedResults[5].returnData
676
- )[0] as bigint;
677
- const maxShortTrade =
678
- account.side == SELL_SIDE
679
- ? Math.max(
680
- 0,
681
- Math.abs(ABK64x64ToFloat(fMaxShort)) - (accountGiven ? 0 : Math.abs(account.positionNotionalBaseCCY))
682
- )
683
- : Math.abs(ABK64x64ToFloat(fMaxShort)) + Math.abs(account.positionNotionalBaseCCY);
684
682
 
685
683
  // Current state:
686
684
  let lotSizeBC = MarketData._getLotSize(order.symbol, this.symbolToPerpStaticInfo);
@@ -705,10 +703,6 @@ export default class MarketData extends PerpetualDataHandler {
705
703
  }
706
704
  let newSide = newPositionBC > 0 ? BUY_SIDE : newPositionBC < 0 ? SELL_SIDE : CLOSED_SIDE;
707
705
 
708
- if (tradingFeeTbps === undefined) {
709
- // use usual input if not overriden
710
- tradingFeeTbps = Number(exchangeFeeTbps) + (order.brokerFeeTbps ?? 0);
711
- }
712
706
  let tradingFeeCC = (Math.abs(tradeAmountBC) * tradingFeeTbps * 1e-5 * S2) / S3;
713
707
  let referralFeeCC = this.symbolToPerpStaticInfo.get(account.symbol)!.referralRebate;
714
708
  // Trade type:
@@ -733,7 +727,7 @@ export default class MarketData extends PerpetualDataHandler {
733
727
  let initialMarginRate = this.symbolToPerpStaticInfo.get(account.symbol)!.initialMarginRate;
734
728
  targetLvg = isFlip || isOpen ? order.leverage ?? 1 / initialMarginRate : 0;
735
729
  let [b0, pos0] = isOpen ? [0, 0] : [account.collateralCC, currentPositionBC];
736
- traderDepositCC = getDepositAmountForLvgTrade(pos0, b0, tradeAmountBC, targetLvg, tradePrice, S3, Sm);
730
+ traderDepositCC = getDepositAmountForLvgTrade(pos0, b0, tradeAmountBC, targetLvg, tradePrice, S3, Sm, isPredMkt);
737
731
  // fees are paid from wallet in this case
738
732
  traderDepositCC += tradingFeeCC + referralFeeCC;
739
733
  }
@@ -769,6 +763,7 @@ export default class MarketData extends PerpetualDataHandler {
769
763
  newMarginCashCC,
770
764
  Sm,
771
765
  S3,
766
+ S2,
772
767
  this.symbolToPerpStaticInfo
773
768
  );
774
769
 
@@ -795,6 +790,25 @@ export default class MarketData extends PerpetualDataHandler {
795
790
  };
796
791
  }
797
792
 
793
+ /**
794
+ * Fee is relative to base-currency amount (=trade amount)
795
+ * @param state current perpetual state (need longBC and shortBC)
796
+ * @param maxMaintMgnRate maintenance margin rate param for pred mkts
797
+ * @param Sm Mark price
798
+ * @param tradeAmtBC signed trade amount
799
+ * @param tradeMgnRate margin rate param from perpetual
800
+ * @returns relative exchange fee in decimals
801
+ */
802
+ public static exchangeFeePrdMkts(
803
+ state: PerpetualState,
804
+ maxMaintMgnRate: number,
805
+ Sm: number,
806
+ tradeAmtBC: number,
807
+ tradeMgnRate: number
808
+ ): number {
809
+ return pmExchangeFee(Sm - 1, maxMaintMgnRate, state.shortBC, state.longBC, tradeAmtBC, tradeMgnRate);
810
+ }
811
+
798
812
  /**
799
813
  * Estimates what the position risk will be if given amount of collateral is added/removed from the account.
800
814
  * @param {number} deltaCollateral Amount of collateral to add or remove (signed)
@@ -819,7 +833,7 @@ export default class MarketData extends PerpetualDataHandler {
819
833
  public async positionRiskOnCollateralAction(
820
834
  deltaCollateral: number,
821
835
  account: MarginAccount,
822
- indexPriceInfo?: [number, number, boolean, boolean],
836
+ indexPriceInfo?: IdxPriceInfo,
823
837
  overrides?: Overrides
824
838
  ): Promise<MarginAccount> {
825
839
  if (this.proxyContract == null) {
@@ -829,11 +843,17 @@ export default class MarketData extends PerpetualDataHandler {
829
843
  throw new Error("not enough margin to remove");
830
844
  }
831
845
  if (indexPriceInfo == undefined) {
832
- let obj = await this.priceFeedGetter.fetchPricesForPerpetual(account.symbol);
833
- indexPriceInfo = [obj.idxPrices[0], obj.idxPrices[1], obj.mktClosed[0], obj.mktClosed[1]];
846
+ indexPriceInfo = await this.priceFeedGetter.fetchPricesForPerpetual(account.symbol);
834
847
  }
835
848
  let perpetualState = await this.getPerpetualState(account.symbol, indexPriceInfo, overrides);
836
- let [S2, S3, Sm] = [perpetualState.indexPrice, perpetualState.collToQuoteIndexPrice, perpetualState.markPrice];
849
+ let Sm; //mark price
850
+ if (this.isPredictionMarket(account.symbol)) {
851
+ Sm = indexPriceInfo.ema + perpetualState.markPremium;
852
+ } else {
853
+ Sm = perpetualState.indexPrice * (1 + perpetualState.markPremium);
854
+ }
855
+
856
+ let [S2, S3] = [perpetualState.indexPrice, perpetualState.collToQuoteIndexPrice];
837
857
 
838
858
  // no position: just increase collateral and kill liquidation vars
839
859
  if (account.positionNotionalBaseCCY == 0) {
@@ -884,6 +904,7 @@ export default class MarketData extends PerpetualDataHandler {
884
904
  newMarginCashCC,
885
905
  Sm,
886
906
  S3,
907
+ S2,
887
908
  this.symbolToPerpStaticInfo
888
909
  );
889
910
 
@@ -906,13 +927,15 @@ export default class MarketData extends PerpetualDataHandler {
906
927
  }
907
928
 
908
929
  /**
909
- * Calculates liquidation prices for a given position
930
+ * Calculates liquidation prices for a position
931
+ * constructed in positionRiskOnTrade/positionRiskOnCollateralAction
910
932
  * @param symbol Perpetual symbol
911
933
  * @param lockedInQC Locked in value
912
934
  * @param signedPositionBC Signed position size
913
- * @param marginCashCC Cash in margin account
935
+ * @param marginCashCC Available cash in margin account (includes unpaid funding)
914
936
  * @param markPrice Mark price
915
- * @param collToQuoteConversion Collateral index price
937
+ * @param collToQuoteConversion Collateral index price (S3)
938
+ * @param S2 index price
916
939
  * @param symbolToPerpStaticInfo Symbol-to-perp static info mapping
917
940
  * @returns [Base index price, Collateral index price, Maintenance margin rate]
918
941
  * @ignore
@@ -924,30 +947,35 @@ export default class MarketData extends PerpetualDataHandler {
924
947
  marginCashCC: number,
925
948
  markPrice: number,
926
949
  collToQuoteConversion: number,
950
+ S2: number,
927
951
  symbolToPerpStaticInfo: Map<string, PerpetualStaticInfo>
928
952
  ): [number, number | undefined, number] {
929
953
  let S2Liq: number, S3Liq: number | undefined;
930
- let tau = symbolToPerpStaticInfo.get(symbol)!.maintenanceMarginRate;
931
- let ccyType = symbolToPerpStaticInfo.get(symbol)!.collateralCurrencyType;
932
- if (ccyType == CollaterlCCY.BASE) {
933
- S2Liq = calculateLiquidationPriceCollateralBase(lockedInQC, signedPositionBC, marginCashCC, tau);
934
- S3Liq = S2Liq;
935
- } else if (ccyType == CollaterlCCY.QUANTO) {
936
- S3Liq = collToQuoteConversion;
937
- S2Liq = calculateLiquidationPriceCollateralQuanto(
938
- lockedInQC,
939
- signedPositionBC,
940
- marginCashCC,
941
- tau,
942
- collToQuoteConversion,
943
- markPrice
944
- );
945
- } else {
946
- S2Liq = calculateLiquidationPriceCollateralQuote(lockedInQC, signedPositionBC, marginCashCC, tau);
947
- }
948
- // floor at 0
949
- S2Liq = S2Liq < 0 ? 0 : S2Liq;
950
- S3Liq = S3Liq && S3Liq < 0 ? 0 : S3Liq;
954
+ const staticInfo = symbolToPerpStaticInfo.get(symbol)!;
955
+ let tau = staticInfo.maintenanceMarginRate;
956
+ let ccyType = staticInfo.collateralCurrencyType;
957
+ const isPred = MarketData.isPredictionMarketStatic(staticInfo);
958
+ const idx_availableCashCC = 2;
959
+ const idx_cash = 3;
960
+ const idx_notional = 4;
961
+ const idx_locked_in = 5;
962
+ const idx_mark_price = 8;
963
+ const idx_s3 = 9;
964
+ let traderState = new Array<bigint>(10);
965
+ traderState[idx_availableCashCC] = floatToABK64x64(marginCashCC);
966
+ traderState[idx_cash] = traderState[idx_availableCashCC];
967
+ traderState[idx_notional] = floatToABK64x64(signedPositionBC);
968
+ traderState[idx_locked_in] = floatToABK64x64(lockedInQC);
969
+ traderState[idx_mark_price] = floatToABK64x64(markPrice);
970
+ traderState[idx_s3] = floatToABK64x64(collToQuoteConversion);
971
+
972
+ [S2Liq, S3Liq, tau, ,] = MarketData._calculateLiquidationPrice(
973
+ symbol,
974
+ traderState,
975
+ S2,
976
+ symbolToPerpStaticInfo,
977
+ isPred
978
+ );
951
979
  return [S2Liq, S3Liq, tau];
952
980
  }
953
981
 
@@ -1137,23 +1165,35 @@ export default class MarketData extends PerpetualDataHandler {
1137
1165
  if (!this.proxyContract || !this.multicall) {
1138
1166
  throw new Error("proxy contract not initialized");
1139
1167
  }
1168
+ if (this.isPredictionMarket(symbol)) {
1169
+ // prediction markets
1170
+ return this.pmMaxOrderSizeForTrader(traderAddr, symbol, overrides);
1171
+ }
1172
+ // regular markets
1173
+ return this.rmMaxOrderSizeForTrader(traderAddr, symbol, overrides);
1174
+ }
1175
+
1176
+ private async pmMaxOrderSizeForTrader(
1177
+ traderAddr: string,
1178
+ symbol: string,
1179
+ overrides?: Overrides
1180
+ ): Promise<{ buy: number; sell: number }> {
1181
+ if (!this.proxyContract || !this.multicall) {
1182
+ throw new Error("proxy contract not initialized");
1183
+ }
1184
+ const IERC20 = new Interface(ERC20_ABI) as ERC20Interface;
1140
1185
  const perpId = PerpetualDataHandler.symbolToPerpetualId(symbol, this.symbolToPerpStaticInfo);
1141
- const poolId = this.getPoolIdFromSymbol(symbol);
1142
1186
  const poolInfo = this.poolStaticInfos[this.getPoolStaticInfoIndexFromSymbol(symbol)];
1143
- const perpInfo = this.getPerpetualStaticInfo(symbol);
1144
- const IERC20 = new Interface(ERC20_ABI) as ERC20Interface;
1145
-
1146
- const indexPriceInfo: [number, number, boolean, boolean] = await this.priceFeedGetter
1147
- .fetchPricesForPerpetual(symbol)
1148
- .then((obj) => [obj.idxPrices[0], obj.idxPrices[1], obj.mktClosed[0], obj.mktClosed[1]]);
1149
- const fS2S3 = [indexPriceInfo[0], indexPriceInfo[1]].map((x) => floatToABK64x64(x)) as [bigint, bigint];
1150
- let coll2SettlePromise = this.fetchCollateralToSettlementConversion(symbol);
1187
+ const indexPriceInfo = await this.priceFeedGetter.fetchPricesForPerpetual(symbol);
1188
+ const [fS2, fS3, fEma] = [indexPriceInfo.s2, indexPriceInfo.s3, indexPriceInfo.ema].map((x) =>
1189
+ floatToABK64x64(x)
1190
+ ) as [bigint, bigint, bigint];
1151
1191
  const proxyCalls: Multicall3.Call3Struct[] = [
1152
1192
  // 0: traderState
1153
1193
  {
1154
1194
  target: this.proxyContract.target,
1155
1195
  allowFailure: false,
1156
- callData: this.proxyContract.interface.encodeFunctionData("getTraderState", [perpId, traderAddr, fS2S3]),
1196
+ callData: this.proxyContract.interface.encodeFunctionData("getTraderState", [perpId, traderAddr, [fEma, fS3]]),
1157
1197
  },
1158
1198
 
1159
1199
  // 1: wallet balance
@@ -1162,46 +1202,100 @@ export default class MarketData extends PerpetualDataHandler {
1162
1202
  allowFailure: false,
1163
1203
  callData: IERC20.encodeFunctionData("balanceOf", [traderAddr]),
1164
1204
  },
1165
- // 2: exchange fee
1205
+ // 2: amm state
1166
1206
  {
1167
1207
  target: this.proxyContract.target,
1168
1208
  allowFailure: false,
1169
- callData: this.proxyContract.interface.encodeFunctionData("queryExchangeFee", [
1170
- poolId,
1171
- traderAddr,
1172
- ZERO_ADDRESS,
1173
- ]),
1209
+ callData: this.proxyContract.interface.encodeFunctionData("getAMMState", [perpId, [fS2, fS3]]),
1174
1210
  },
1175
1211
  ];
1176
1212
 
1177
1213
  // multicall
1178
1214
  const encodedResults = await this.multicall.aggregate3.staticCall(proxyCalls, overrides || {});
1179
-
1180
- // position risk
1181
- const idxNotional = 4;
1182
1215
  const traderState = this.proxyContract.interface.decodeFunctionResult(
1183
1216
  "getTraderState",
1184
1217
  encodedResults[0].returnData
1185
1218
  )[0];
1186
- const account = MarketData.buildMarginAccountFromState(symbol, traderState, this.symbolToPerpStaticInfo, [
1187
- indexPriceInfo[0],
1188
- indexPriceInfo[1],
1189
- ]);
1190
-
1191
- // fee rate
1192
- const feeRateTbps = this.proxyContract.interface.decodeFunctionResult(
1193
- "queryExchangeFee",
1194
- encodedResults[2].returnData
1195
- )[0] as bigint;
1196
-
1197
- const feeRate = 1e-5 * Number(feeRateTbps);
1198
-
1199
- // Max based on margin requirements:
1200
1219
  const walletBalance = decNToFloat(
1201
1220
  IERC20.decodeFunctionResult("balanceOf", encodedResults[1].returnData)[0],
1202
1221
  poolInfo.poolSettleTokenDecimals
1203
1222
  );
1223
+ const ammState = this.proxyContract.interface.decodeFunctionResult("getAMMState", encodedResults[2].returnData)[0];
1204
1224
 
1225
+ const account = MarketData.buildMarginAccountFromState(
1226
+ symbol,
1227
+ traderState,
1228
+ this.symbolToPerpStaticInfo,
1229
+ indexPriceInfo,
1230
+ true //isPredMkt
1231
+ );
1232
+ const openInterestBC = ABK64x64ToFloat(ammState[11]);
1233
+ const net = -ABK64x64ToFloat(ammState[1]);
1234
+ let totLong, totShort;
1235
+ if (net < 0) {
1236
+ totLong = openInterestBC;
1237
+ totShort = openInterestBC - Math.abs(net);
1238
+ } else {
1239
+ totLong = openInterestBC - net;
1240
+ totShort = openInterestBC;
1241
+ }
1242
+
1243
+ let currentPositionBC = (account.side == BUY_SIDE ? 1 : -1) * account.positionNotionalBaseCCY;
1244
+ const Sm = ABK64x64ToFloat(traderState[8]);
1245
+ // settlement token must be equal to collateral token for walletBalance to be correct
1246
+ const availCashCC = account.collateralCC + walletBalance + account.unrealizedFundingCollateralCCY;
1247
+ const idxNotional = 4;
1248
+ const [maxShortPosPerp, maxLongPosPerp] = await this.getMaxShortLongPos(
1249
+ perpId,
1250
+ traderState[idxNotional],
1251
+ overrides
1252
+ );
1253
+
1254
+ const maxShort = pmFindMaxTradeSize(
1255
+ -1,
1256
+ currentPositionBC,
1257
+ availCashCC,
1258
+ account.entryPrice * currentPositionBC,
1259
+ Sm,
1260
+ Sm,
1261
+ indexPriceInfo.s3,
1262
+ totLong,
1263
+ totShort,
1264
+ maxShortPosPerp,
1265
+ maxLongPosPerp
1266
+ );
1267
+ const maxLong = pmFindMaxTradeSize(
1268
+ -1,
1269
+ currentPositionBC,
1270
+ availCashCC,
1271
+ account.entryPrice * currentPositionBC,
1272
+ Sm,
1273
+ Sm,
1274
+ indexPriceInfo.s3,
1275
+ totLong,
1276
+ totShort,
1277
+ maxShortPosPerp,
1278
+ maxLongPosPerp
1279
+ );
1280
+ return { buy: maxLong, sell: maxShort };
1281
+ }
1282
+
1283
+ /**
1284
+ * Returns the maximal allowed short pos and long pos (signed) for a trader
1285
+ * with given notional (in ABDK format) in the perpetual, ignoring the traders wallet balance
1286
+ * @param perpId
1287
+ * @param currentTraderPos ABDK64x64 notional position of trader
1288
+ * @param overrides
1289
+ * @returns [maxShortPos, maxLongPos] signed maximal position sizes
1290
+ */
1291
+ public async getMaxShortLongPos(
1292
+ perpId: number,
1293
+ currentTraderPos: bigint,
1294
+ overrides?: Overrides
1295
+ ): Promise<[number, number]> {
1296
+ if (!this.proxyContract || !this.multicall) {
1297
+ throw new Error("proxy contract not initialized");
1298
+ }
1205
1299
  const proxyCalls2: Multicall3.Call3Struct[] = [
1206
1300
  // 0: max long
1207
1301
  {
@@ -1209,7 +1303,7 @@ export default class MarketData extends PerpetualDataHandler {
1209
1303
  allowFailure: false,
1210
1304
  callData: this.proxyContract.interface.encodeFunctionData("getMaxSignedOpenTradeSizeForPos", [
1211
1305
  perpId,
1212
- traderState[idxNotional],
1306
+ currentTraderPos,
1213
1307
  true,
1214
1308
  ]),
1215
1309
  },
@@ -1219,7 +1313,7 @@ export default class MarketData extends PerpetualDataHandler {
1219
1313
  allowFailure: false,
1220
1314
  callData: this.proxyContract.interface.encodeFunctionData("getMaxSignedOpenTradeSizeForPos", [
1221
1315
  perpId,
1222
- traderState[idxNotional],
1316
+ currentTraderPos,
1223
1317
  false,
1224
1318
  ]),
1225
1319
  },
@@ -1236,7 +1330,7 @@ export default class MarketData extends PerpetualDataHandler {
1236
1330
  encodedResults2[0].returnData
1237
1331
  )[0] as bigint
1238
1332
  );
1239
- const maxLongPosPerp = maxLongOrderPerp + ABK64x64ToFloat(traderState[idxNotional]);
1333
+ const maxLongPosPerp = maxLongOrderPerp + ABK64x64ToFloat(currentTraderPos);
1240
1334
  // max short
1241
1335
  const maxShortOrderPerp = ABK64x64ToFloat(
1242
1336
  this.proxyContract.interface.decodeFunctionResult(
@@ -1244,8 +1338,91 @@ export default class MarketData extends PerpetualDataHandler {
1244
1338
  encodedResults2[1].returnData
1245
1339
  )[0] as bigint
1246
1340
  );
1247
- const maxShortPosPerp = maxShortOrderPerp + ABK64x64ToFloat(traderState[idxNotional]);
1341
+ const maxShortPosPerp = maxShortOrderPerp + ABK64x64ToFloat(currentTraderPos);
1342
+ return [maxShortPosPerp, maxLongPosPerp];
1343
+ }
1248
1344
 
1345
+ private async rmMaxOrderSizeForTrader(
1346
+ traderAddr: string,
1347
+ symbol: string,
1348
+ overrides?: Overrides
1349
+ ): Promise<{ buy: number; sell: number }> {
1350
+ const perpId = PerpetualDataHandler.symbolToPerpetualId(symbol, this.symbolToPerpStaticInfo);
1351
+ const poolId = this.getPoolIdFromSymbol(symbol);
1352
+ const poolInfo = this.poolStaticInfos[this.getPoolStaticInfoIndexFromSymbol(symbol)];
1353
+ const perpInfo = this.getPerpetualStaticInfo(symbol);
1354
+ const IERC20 = new Interface(ERC20_ABI) as ERC20Interface;
1355
+ const isPredMkt = false;
1356
+ const indexPriceInfo = await this.priceFeedGetter.fetchPricesForPerpetual(symbol);
1357
+ let coll2SettlePromise = this.fetchCollateralToSettlementConversion(symbol);
1358
+ const [fS2, fS3, fEma] = [indexPriceInfo.s2, indexPriceInfo.s3, indexPriceInfo.ema].map((x) =>
1359
+ floatToABK64x64(x)
1360
+ ) as [bigint, bigint, bigint];
1361
+ if (!this.proxyContract || !this.multicall) {
1362
+ throw new Error("proxy contract not initialized");
1363
+ }
1364
+ const proxyCalls: Multicall3.Call3Struct[] = [
1365
+ // 0: traderState
1366
+ {
1367
+ target: this.proxyContract.target,
1368
+ allowFailure: false,
1369
+ callData: this.proxyContract.interface.encodeFunctionData("getTraderState", [perpId, traderAddr, [fEma, fS3]]),
1370
+ },
1371
+
1372
+ // 1: wallet balance
1373
+ {
1374
+ target: poolInfo.poolSettleTokenAddr,
1375
+ allowFailure: false,
1376
+ callData: IERC20.encodeFunctionData("balanceOf", [traderAddr]),
1377
+ },
1378
+ // 2: exchange fee
1379
+ {
1380
+ target: this.proxyContract.target,
1381
+ allowFailure: false,
1382
+ callData: this.proxyContract.interface.encodeFunctionData("queryExchangeFee", [
1383
+ poolId,
1384
+ traderAddr,
1385
+ ZERO_ADDRESS,
1386
+ ]),
1387
+ },
1388
+ ];
1389
+
1390
+ // multicall
1391
+ const encodedResults = await this.multicall.aggregate3.staticCall(proxyCalls, overrides || {});
1392
+
1393
+ // position risk
1394
+ const idxNotional = 4;
1395
+ const traderState = this.proxyContract.interface.decodeFunctionResult(
1396
+ "getTraderState",
1397
+ encodedResults[0].returnData
1398
+ )[0];
1399
+ const account = MarketData.buildMarginAccountFromState(
1400
+ symbol,
1401
+ traderState,
1402
+ this.symbolToPerpStaticInfo,
1403
+ indexPriceInfo,
1404
+ isPredMkt
1405
+ );
1406
+
1407
+ // fee rate
1408
+ const feeRateTbps = this.proxyContract.interface.decodeFunctionResult(
1409
+ "queryExchangeFee",
1410
+ encodedResults[2].returnData
1411
+ )[0] as bigint;
1412
+
1413
+ const feeRate = 1e-5 * Number(feeRateTbps);
1414
+
1415
+ // Max based on margin requirements:
1416
+ const walletBalance = decNToFloat(
1417
+ IERC20.decodeFunctionResult("balanceOf", encodedResults[1].returnData)[0],
1418
+ poolInfo.poolSettleTokenDecimals
1419
+ );
1420
+
1421
+ const [maxShortPosPerp, maxLongPosPerp] = await this.getMaxShortLongPos(
1422
+ perpId,
1423
+ traderState[idxNotional],
1424
+ overrides
1425
+ );
1249
1426
  const curPos = (account.side == BUY_SIDE ? 1 : -1) * account.positionNotionalBaseCCY;
1250
1427
 
1251
1428
  const px: number = await coll2SettlePromise;
@@ -1259,7 +1436,7 @@ export default class MarketData extends PerpetualDataHandler {
1259
1436
  perpInfo.initialMarginRate,
1260
1437
  feeRate,
1261
1438
  account.markPrice,
1262
- indexPriceInfo[0],
1439
+ indexPriceInfo.s2,
1263
1440
  account.collToQuoteConversion
1264
1441
  );
1265
1442
  const maxShortPosAccount = getMaxSignedPositionSize(
@@ -1271,7 +1448,7 @@ export default class MarketData extends PerpetualDataHandler {
1271
1448
  perpInfo.initialMarginRate,
1272
1449
  feeRate,
1273
1450
  account.markPrice,
1274
- indexPriceInfo[0],
1451
+ indexPriceInfo.s2,
1275
1452
  account.collToQuoteConversion
1276
1453
  );
1277
1454
 
@@ -1420,6 +1597,7 @@ export default class MarketData extends PerpetualDataHandler {
1420
1597
  /**
1421
1598
  * Get the current mark price
1422
1599
  * @param symbol symbol of the form ETH-USD-MATIC
1600
+ * @param indexPrices optional. IdxPriceInfo
1423
1601
  * @example
1424
1602
  * import { MarketData, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
1425
1603
  * async function main() {
@@ -1436,19 +1614,19 @@ export default class MarketData extends PerpetualDataHandler {
1436
1614
  *
1437
1615
  * @returns {number} mark price
1438
1616
  */
1439
- public async getMarkPrice(symbol: string, indexPrices?: [number, number]): Promise<number> {
1617
+ public async getMarkPrice(symbol: string, indexPrices?: IdxPriceInfo): Promise<number> {
1440
1618
  if (this.proxyContract == null) {
1441
1619
  throw Error("no proxy contract initialized. Use createProxyInstance().");
1442
1620
  }
1443
1621
  if (indexPrices == undefined) {
1444
- let obj = await this.priceFeedGetter.fetchPricesForPerpetual(symbol);
1445
- indexPrices = [obj.idxPrices[0], obj.idxPrices[1]];
1622
+ indexPrices = await this.priceFeedGetter.fetchPricesForPerpetual(symbol);
1446
1623
  }
1447
1624
  return await PerpetualDataHandler._queryPerpetualMarkPrice(
1448
1625
  symbol,
1449
1626
  this.symbolToPerpStaticInfo,
1450
1627
  this.proxyContract,
1451
- indexPrices
1628
+ indexPrices,
1629
+ this.isPredictionMarket(symbol)
1452
1630
  );
1453
1631
  }
1454
1632
 
@@ -1456,6 +1634,7 @@ export default class MarketData extends PerpetualDataHandler {
1456
1634
  * get the current price for a given quantity
1457
1635
  * @param symbol symbol of the form ETH-USD-MATIC
1458
1636
  * @param quantity quantity to be traded, negative if short
1637
+ * @param priceInfo [s2, s3, conf, params]; for non-prediction markets conf/params can be 0
1459
1638
  * @example
1460
1639
  * import { MarketData, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
1461
1640
  * async function main() {
@@ -1475,23 +1654,24 @@ export default class MarketData extends PerpetualDataHandler {
1475
1654
  public async getPerpetualPrice(
1476
1655
  symbol: string,
1477
1656
  quantity: number,
1478
- indexPrices?: [number, number],
1657
+ priceInfo?: IdxPriceInfo,
1479
1658
  overrides?: Overrides
1480
1659
  ): Promise<number> {
1481
1660
  if (this.proxyContract == null) {
1482
1661
  throw Error("no proxy contract initialized. Use createProxyInstance().");
1483
1662
  }
1484
- if (indexPrices == undefined) {
1663
+ if (priceInfo == undefined) {
1485
1664
  // fetch from API
1486
- let obj = await this.priceFeedGetter.fetchPricesForPerpetual(symbol);
1487
- indexPrices = [obj.idxPrices[0], obj.idxPrices[1]];
1665
+ priceInfo = await this.priceFeedGetter.fetchPricesForPerpetual(symbol);
1488
1666
  }
1489
1667
  return await PerpetualDataHandler._queryPerpetualPrice(
1490
1668
  symbol,
1491
1669
  quantity,
1492
1670
  this.symbolToPerpStaticInfo,
1493
1671
  this.proxyContract,
1494
- indexPrices,
1672
+ [priceInfo.s2, priceInfo.s3], //s2,s3
1673
+ priceInfo.conf, //conf
1674
+ priceInfo.predMktCLOBParams, //params
1495
1675
  overrides
1496
1676
  );
1497
1677
  }
@@ -1503,15 +1683,14 @@ export default class MarketData extends PerpetualDataHandler {
1503
1683
  */
1504
1684
  public async getPerpetualState(
1505
1685
  symbol: string,
1506
- indexPriceInfo?: [number, number, boolean, boolean],
1686
+ indexPriceInfo?: IdxPriceInfo,
1507
1687
  overrides?: Overrides
1508
1688
  ): Promise<PerpetualState> {
1509
1689
  if (this.proxyContract == null || this.multicall == null) {
1510
1690
  throw Error("no proxy contract initialized. Use createProxyInstance().");
1511
1691
  }
1512
1692
  if (indexPriceInfo == undefined) {
1513
- let obj = await this.priceFeedGetter.fetchPricesForPerpetual(symbol);
1514
- indexPriceInfo = [obj.idxPrices[0], obj.idxPrices[1], obj.mktClosed[0], obj.mktClosed[1]];
1693
+ indexPriceInfo = await this.priceFeedGetter.fetchPricesForPerpetual(symbol);
1515
1694
  }
1516
1695
  let state: PerpetualState = await PerpetualDataHandler._queryPerpetualState(
1517
1696
  symbol,
@@ -1743,7 +1922,7 @@ export default class MarketData extends PerpetualDataHandler {
1743
1922
  * Result is in collateral currency
1744
1923
  * @param {string} traderAddr address of the trader
1745
1924
  * @param {string} symbol perpetual symbol of the form BTC-USD-MATIC
1746
- * @param indexPrices optional index prices, will otherwise fetch from REST API
1925
+ * @param indexPrices optional indexPriceInfo
1747
1926
  * @returns available margin in collateral currency
1748
1927
  * @example
1749
1928
  * import { MarketData, PerpetualDataHandler } from '@d8x/perpetuals-sdk';
@@ -1762,7 +1941,7 @@ export default class MarketData extends PerpetualDataHandler {
1762
1941
  public async getAvailableMargin(
1763
1942
  traderAddr: string,
1764
1943
  symbol: string,
1765
- indexPrices?: [number, number],
1944
+ indexPrices?: IdxPriceInfo,
1766
1945
  overrides?: Overrides
1767
1946
  ): Promise<number> {
1768
1947
  if (!this.proxyContract) {
@@ -1771,14 +1950,16 @@ export default class MarketData extends PerpetualDataHandler {
1771
1950
 
1772
1951
  if (indexPrices == undefined) {
1773
1952
  // fetch from API
1774
- let obj = await this.priceFeedGetter.fetchPricesForPerpetual(symbol);
1775
- indexPrices = [obj.idxPrices[0], obj.idxPrices[1]];
1953
+ indexPrices = await this.priceFeedGetter.fetchPricesForPerpetual(symbol);
1776
1954
  }
1777
1955
  let perpID = PerpetualDataHandler.symbolToPerpetualId(symbol, this.symbolToPerpStaticInfo);
1778
1956
  let traderState = await this.proxyContract.getTraderState(
1779
1957
  perpID,
1780
1958
  traderAddr,
1781
- indexPrices.map((x) => floatToABK64x64(x == undefined || Number.isNaN(x) ? 0 : x)) as [bigint, bigint],
1959
+ [indexPrices.s2, indexPrices.s3].map((x) => floatToABK64x64(x == undefined || Number.isNaN(x) ? 0 : x)) as [
1960
+ bigint,
1961
+ bigint
1962
+ ],
1782
1963
  overrides || {}
1783
1964
  );
1784
1965
  const idx_availableMargin = 1;
@@ -2111,7 +2292,7 @@ export default class MarketData extends PerpetualDataHandler {
2111
2292
  quoteCurrency: contractSymbolToSymbol(perp.S2QuoteCCY!, _symbolList)!,
2112
2293
  indexPrice: 0, //fill later
2113
2294
  collToQuoteIndexPrice: 0, //fill later
2114
- markPrice: ABK64x64ToFloat(perp.currentMarkPremiumRate!.fPrice), // fill later: indexS2 * (1 + markPremiumRate),
2295
+ markPremium: ABK64x64ToFloat(perp.currentMarkPremiumRate!.fPrice),
2115
2296
  midPrice: 0, // fill later
2116
2297
  currentFundingRateBps: 1e4 * ABK64x64ToFloat(perp.fCurrentFundingRate!),
2117
2298
  openInterestBC: ABK64x64ToFloat(perp.fOpenInterest!),
@@ -2188,7 +2369,6 @@ export default class MarketData extends PerpetualDataHandler {
2188
2369
  perp.isMarketClosed = perp.isMarketClosed || idxPriceS3Pair![1];
2189
2370
  }
2190
2371
  perp.indexPrice = idxPriceS2Pair![0];
2191
- perp.markPrice = idxPriceS2Pair![0] * (1 + perp.markPrice); // currently filled with mark premium rate
2192
2372
  let indexS3 = 1;
2193
2373
  if (info!.collateralCurrencyType == COLLATERAL_CURRENCY_BASE) {
2194
2374
  indexS3 = idxPriceS2Pair![0];
@@ -2293,10 +2473,7 @@ export default class MarketData extends PerpetualDataHandler {
2293
2473
  * @param symbol Perpetual symbol of the form BTC-USDc-USDC
2294
2474
  * @returns Prices and market-closed information
2295
2475
  */
2296
- public async fetchPricesForPerpetual(symbol: string): Promise<{
2297
- idxPrices: number[];
2298
- mktClosed: boolean[];
2299
- }> {
2476
+ public async fetchPricesForPerpetual(symbol: string): Promise<IdxPriceInfo> {
2300
2477
  return this.priceFeedGetter.fetchPricesForPerpetual(symbol);
2301
2478
  }
2302
2479
  }