@metamask-previews/perps-controller 0.0.0-preview-ae46ab603 → 0.0.0-preview-e4aa1532

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 (498) hide show
  1. package/CHANGELOG.md +11 -1
  2. package/dist/PerpsController.cjs +2224 -66
  3. package/dist/PerpsController.cjs.map +1 -1
  4. package/dist/PerpsController.d.cts +933 -79
  5. package/dist/PerpsController.d.cts.map +1 -1
  6. package/dist/PerpsController.d.mts +933 -79
  7. package/dist/PerpsController.d.mts.map +1 -1
  8. package/dist/PerpsController.mjs +2221 -64
  9. package/dist/PerpsController.mjs.map +1 -1
  10. package/dist/__mocks__/hyperliquidMock.cjs +68 -0
  11. package/dist/__mocks__/hyperliquidMock.cjs.map +1 -0
  12. package/dist/__mocks__/hyperliquidMock.d.cts +15 -0
  13. package/dist/__mocks__/hyperliquidMock.d.cts.map +1 -0
  14. package/dist/__mocks__/hyperliquidMock.d.mts +15 -0
  15. package/dist/__mocks__/hyperliquidMock.d.mts.map +1 -0
  16. package/dist/__mocks__/hyperliquidMock.mjs +65 -0
  17. package/dist/__mocks__/hyperliquidMock.mjs.map +1 -0
  18. package/dist/__mocks__/providerMocks.cjs +144 -0
  19. package/dist/__mocks__/providerMocks.cjs.map +1 -0
  20. package/dist/__mocks__/providerMocks.d.cts +44 -0
  21. package/dist/__mocks__/providerMocks.d.cts.map +1 -0
  22. package/dist/__mocks__/providerMocks.d.mts +44 -0
  23. package/dist/__mocks__/providerMocks.d.mts.map +1 -0
  24. package/dist/__mocks__/providerMocks.mjs +136 -0
  25. package/dist/__mocks__/providerMocks.mjs.map +1 -0
  26. package/dist/__mocks__/serviceMocks.cjs +187 -0
  27. package/dist/__mocks__/serviceMocks.cjs.map +1 -0
  28. package/dist/__mocks__/serviceMocks.d.cts +58 -0
  29. package/dist/__mocks__/serviceMocks.d.cts.map +1 -0
  30. package/dist/__mocks__/serviceMocks.d.mts +58 -0
  31. package/dist/__mocks__/serviceMocks.d.mts.map +1 -0
  32. package/dist/__mocks__/serviceMocks.mjs +180 -0
  33. package/dist/__mocks__/serviceMocks.mjs.map +1 -0
  34. package/dist/aggregation/SubscriptionMultiplexer.cjs +459 -0
  35. package/dist/aggregation/SubscriptionMultiplexer.cjs.map +1 -0
  36. package/dist/aggregation/SubscriptionMultiplexer.d.cts +222 -0
  37. package/dist/aggregation/SubscriptionMultiplexer.d.cts.map +1 -0
  38. package/dist/aggregation/SubscriptionMultiplexer.d.mts +222 -0
  39. package/dist/aggregation/SubscriptionMultiplexer.d.mts.map +1 -0
  40. package/dist/aggregation/SubscriptionMultiplexer.mjs +455 -0
  41. package/dist/aggregation/SubscriptionMultiplexer.mjs.map +1 -0
  42. package/dist/aggregation/index.cjs +9 -0
  43. package/dist/aggregation/index.cjs.map +1 -0
  44. package/dist/aggregation/index.d.cts +6 -0
  45. package/dist/aggregation/index.d.cts.map +1 -0
  46. package/dist/aggregation/index.d.mts +6 -0
  47. package/dist/aggregation/index.d.mts.map +1 -0
  48. package/dist/aggregation/index.mjs +5 -0
  49. package/dist/aggregation/index.mjs.map +1 -0
  50. package/dist/constants/eventNames.cjs +117 -0
  51. package/dist/constants/eventNames.cjs.map +1 -0
  52. package/dist/constants/eventNames.d.cts +106 -0
  53. package/dist/constants/eventNames.d.cts.map +1 -0
  54. package/dist/constants/eventNames.d.mts +106 -0
  55. package/dist/constants/eventNames.d.mts.map +1 -0
  56. package/dist/constants/eventNames.mjs +114 -0
  57. package/dist/constants/eventNames.mjs.map +1 -0
  58. package/dist/constants/hyperLiquidConfig.cjs +366 -0
  59. package/dist/constants/hyperLiquidConfig.cjs.map +1 -0
  60. package/dist/constants/hyperLiquidConfig.d.cts +276 -0
  61. package/dist/constants/hyperLiquidConfig.d.cts.map +1 -0
  62. package/dist/constants/hyperLiquidConfig.d.mts +276 -0
  63. package/dist/constants/hyperLiquidConfig.d.mts.map +1 -0
  64. package/dist/constants/hyperLiquidConfig.mjs +357 -0
  65. package/dist/constants/hyperLiquidConfig.mjs.map +1 -0
  66. package/dist/constants/index.cjs +23 -0
  67. package/dist/constants/index.cjs.map +1 -0
  68. package/dist/constants/index.d.cts +7 -0
  69. package/dist/constants/index.d.cts.map +1 -0
  70. package/dist/constants/index.d.mts +7 -0
  71. package/dist/constants/index.d.mts.map +1 -0
  72. package/dist/constants/index.mjs +7 -0
  73. package/dist/constants/index.mjs.map +1 -0
  74. package/dist/constants/orderTypes.cjs +31 -0
  75. package/dist/constants/orderTypes.cjs.map +1 -0
  76. package/dist/constants/orderTypes.d.cts +19 -0
  77. package/dist/constants/orderTypes.d.cts.map +1 -0
  78. package/dist/constants/orderTypes.d.mts +19 -0
  79. package/dist/constants/orderTypes.d.mts.map +1 -0
  80. package/dist/constants/orderTypes.mjs +27 -0
  81. package/dist/constants/orderTypes.mjs.map +1 -0
  82. package/dist/constants/performanceMetrics.cjs +61 -0
  83. package/dist/constants/performanceMetrics.cjs.map +1 -0
  84. package/dist/constants/performanceMetrics.d.cts +44 -0
  85. package/dist/constants/performanceMetrics.d.cts.map +1 -0
  86. package/dist/constants/performanceMetrics.d.mts +44 -0
  87. package/dist/constants/performanceMetrics.d.mts.map +1 -0
  88. package/dist/constants/performanceMetrics.mjs +58 -0
  89. package/dist/constants/performanceMetrics.mjs.map +1 -0
  90. package/dist/constants/perpsConfig.cjs +461 -0
  91. package/dist/constants/perpsConfig.cjs.map +1 -0
  92. package/dist/constants/perpsConfig.d.cts +343 -0
  93. package/dist/constants/perpsConfig.d.cts.map +1 -0
  94. package/dist/constants/perpsConfig.d.mts +343 -0
  95. package/dist/constants/perpsConfig.d.mts.map +1 -0
  96. package/dist/constants/perpsConfig.mjs +458 -0
  97. package/dist/constants/perpsConfig.mjs.map +1 -0
  98. package/dist/constants/perpsErrorCodes.cjs +79 -0
  99. package/dist/constants/perpsErrorCodes.cjs.map +1 -0
  100. package/dist/constants/perpsErrorCodes.d.cts +64 -0
  101. package/dist/constants/perpsErrorCodes.d.cts.map +1 -0
  102. package/dist/constants/perpsErrorCodes.d.mts +64 -0
  103. package/dist/constants/perpsErrorCodes.d.mts.map +1 -0
  104. package/dist/constants/perpsErrorCodes.mjs +76 -0
  105. package/dist/constants/perpsErrorCodes.mjs.map +1 -0
  106. package/dist/index.cjs +32 -1
  107. package/dist/index.cjs.map +1 -1
  108. package/dist/index.d.cts +6 -2
  109. package/dist/index.d.cts.map +1 -1
  110. package/dist/index.d.mts +6 -2
  111. package/dist/index.d.mts.map +1 -1
  112. package/dist/index.mjs +9 -1
  113. package/dist/index.mjs.map +1 -1
  114. package/dist/platform-services/HyperLiquidClientService.cjs +857 -0
  115. package/dist/platform-services/HyperLiquidClientService.cjs.map +1 -0
  116. package/dist/platform-services/HyperLiquidClientService.d.cts +263 -0
  117. package/dist/platform-services/HyperLiquidClientService.d.cts.map +1 -0
  118. package/dist/platform-services/HyperLiquidClientService.d.mts +263 -0
  119. package/dist/platform-services/HyperLiquidClientService.d.mts.map +1 -0
  120. package/dist/platform-services/HyperLiquidClientService.mjs +853 -0
  121. package/dist/platform-services/HyperLiquidClientService.mjs.map +1 -0
  122. package/dist/platform-services/HyperLiquidSubscriptionService.cjs +2170 -0
  123. package/dist/platform-services/HyperLiquidSubscriptionService.cjs.map +1 -0
  124. package/dist/platform-services/HyperLiquidSubscriptionService.d.cts +424 -0
  125. package/dist/platform-services/HyperLiquidSubscriptionService.d.cts.map +1 -0
  126. package/dist/platform-services/HyperLiquidSubscriptionService.d.mts +424 -0
  127. package/dist/platform-services/HyperLiquidSubscriptionService.d.mts.map +1 -0
  128. package/dist/platform-services/HyperLiquidSubscriptionService.mjs +2166 -0
  129. package/dist/platform-services/HyperLiquidSubscriptionService.mjs.map +1 -0
  130. package/dist/platform-services/HyperLiquidWalletService.cjs +140 -0
  131. package/dist/platform-services/HyperLiquidWalletService.cjs.map +1 -0
  132. package/dist/platform-services/HyperLiquidWalletService.d.cts +78 -0
  133. package/dist/platform-services/HyperLiquidWalletService.d.cts.map +1 -0
  134. package/dist/platform-services/HyperLiquidWalletService.d.mts +78 -0
  135. package/dist/platform-services/HyperLiquidWalletService.d.mts.map +1 -0
  136. package/dist/platform-services/HyperLiquidWalletService.mjs +136 -0
  137. package/dist/platform-services/HyperLiquidWalletService.mjs.map +1 -0
  138. package/dist/providers/AggregatedPerpsProvider.cjs +777 -0
  139. package/dist/providers/AggregatedPerpsProvider.cjs.map +1 -0
  140. package/dist/providers/AggregatedPerpsProvider.d.cts +466 -0
  141. package/dist/providers/AggregatedPerpsProvider.d.cts.map +1 -0
  142. package/dist/providers/AggregatedPerpsProvider.d.mts +466 -0
  143. package/dist/providers/AggregatedPerpsProvider.d.mts.map +1 -0
  144. package/dist/providers/AggregatedPerpsProvider.mjs +773 -0
  145. package/dist/providers/AggregatedPerpsProvider.mjs.map +1 -0
  146. package/dist/providers/HyperLiquidProvider.cjs +5172 -0
  147. package/dist/providers/HyperLiquidProvider.cjs.map +1 -0
  148. package/dist/providers/HyperLiquidProvider.d.cts +881 -0
  149. package/dist/providers/HyperLiquidProvider.d.cts.map +1 -0
  150. package/dist/providers/HyperLiquidProvider.d.mts +881 -0
  151. package/dist/providers/HyperLiquidProvider.d.mts.map +1 -0
  152. package/dist/providers/HyperLiquidProvider.mjs +5168 -0
  153. package/dist/providers/HyperLiquidProvider.mjs.map +1 -0
  154. package/dist/providers/index.cjs +11 -0
  155. package/dist/providers/index.cjs.map +1 -0
  156. package/dist/providers/index.d.cts +6 -0
  157. package/dist/providers/index.d.cts.map +1 -0
  158. package/dist/providers/index.d.mts +6 -0
  159. package/dist/providers/index.d.mts.map +1 -0
  160. package/dist/providers/index.mjs +6 -0
  161. package/dist/providers/index.mjs.map +1 -0
  162. package/dist/routing/ProviderRouter.cjs +148 -0
  163. package/dist/routing/ProviderRouter.cjs.map +1 -0
  164. package/dist/routing/ProviderRouter.d.cts +124 -0
  165. package/dist/routing/ProviderRouter.d.cts.map +1 -0
  166. package/dist/routing/ProviderRouter.d.mts +124 -0
  167. package/dist/routing/ProviderRouter.d.mts.map +1 -0
  168. package/dist/routing/ProviderRouter.mjs +144 -0
  169. package/dist/routing/ProviderRouter.mjs.map +1 -0
  170. package/dist/routing/index.cjs +9 -0
  171. package/dist/routing/index.cjs.map +1 -0
  172. package/dist/routing/index.d.cts +6 -0
  173. package/dist/routing/index.d.cts.map +1 -0
  174. package/dist/routing/index.d.mts +6 -0
  175. package/dist/routing/index.d.mts.map +1 -0
  176. package/dist/routing/index.mjs +5 -0
  177. package/dist/routing/index.mjs.map +1 -0
  178. package/dist/selectors.cjs +161 -0
  179. package/dist/selectors.cjs.map +1 -0
  180. package/dist/selectors.d.cts +345 -0
  181. package/dist/selectors.d.cts.map +1 -0
  182. package/dist/selectors.d.mts +345 -0
  183. package/dist/selectors.d.mts.map +1 -0
  184. package/dist/selectors.mjs +153 -0
  185. package/dist/selectors.mjs.map +1 -0
  186. package/dist/services/AccountService.cjs +313 -0
  187. package/dist/services/AccountService.cjs.map +1 -0
  188. package/dist/services/AccountService.d.cts +53 -0
  189. package/dist/services/AccountService.d.cts.map +1 -0
  190. package/dist/services/AccountService.d.mts +53 -0
  191. package/dist/services/AccountService.d.mts.map +1 -0
  192. package/dist/services/AccountService.mjs +309 -0
  193. package/dist/services/AccountService.mjs.map +1 -0
  194. package/dist/services/DataLakeService.cjs +219 -0
  195. package/dist/services/DataLakeService.cjs.map +1 -0
  196. package/dist/services/DataLakeService.d.cts +49 -0
  197. package/dist/services/DataLakeService.d.cts.map +1 -0
  198. package/dist/services/DataLakeService.d.mts +49 -0
  199. package/dist/services/DataLakeService.d.mts.map +1 -0
  200. package/dist/services/DataLakeService.mjs +215 -0
  201. package/dist/services/DataLakeService.mjs.map +1 -0
  202. package/dist/services/DepositService.cjs +96 -0
  203. package/dist/services/DepositService.cjs.map +1 -0
  204. package/dist/services/DepositService.d.cts +37 -0
  205. package/dist/services/DepositService.d.cts.map +1 -0
  206. package/dist/services/DepositService.d.mts +37 -0
  207. package/dist/services/DepositService.d.mts.map +1 -0
  208. package/dist/services/DepositService.mjs +92 -0
  209. package/dist/services/DepositService.mjs.map +1 -0
  210. package/dist/services/EligibilityService.cjs +156 -0
  211. package/dist/services/EligibilityService.cjs.map +1 -0
  212. package/dist/services/EligibilityService.d.cts +48 -0
  213. package/dist/services/EligibilityService.d.cts.map +1 -0
  214. package/dist/services/EligibilityService.d.mts +48 -0
  215. package/dist/services/EligibilityService.d.mts.map +1 -0
  216. package/dist/services/EligibilityService.mjs +152 -0
  217. package/dist/services/EligibilityService.mjs.map +1 -0
  218. package/dist/services/FeatureFlagConfigurationService.cjs +258 -0
  219. package/dist/services/FeatureFlagConfigurationService.cjs.map +1 -0
  220. package/dist/services/FeatureFlagConfigurationService.d.cts +100 -0
  221. package/dist/services/FeatureFlagConfigurationService.d.cts.map +1 -0
  222. package/dist/services/FeatureFlagConfigurationService.d.mts +100 -0
  223. package/dist/services/FeatureFlagConfigurationService.d.mts.map +1 -0
  224. package/dist/services/FeatureFlagConfigurationService.mjs +254 -0
  225. package/dist/services/FeatureFlagConfigurationService.mjs.map +1 -0
  226. package/dist/services/MarketDataService.cjs +875 -0
  227. package/dist/services/MarketDataService.cjs.map +1 -0
  228. package/dist/services/MarketDataService.d.cts +289 -0
  229. package/dist/services/MarketDataService.d.cts.map +1 -0
  230. package/dist/services/MarketDataService.d.mts +289 -0
  231. package/dist/services/MarketDataService.d.mts.map +1 -0
  232. package/dist/services/MarketDataService.mjs +871 -0
  233. package/dist/services/MarketDataService.mjs.map +1 -0
  234. package/dist/services/RewardsIntegrationService.cjs +94 -0
  235. package/dist/services/RewardsIntegrationService.cjs.map +1 -0
  236. package/dist/services/RewardsIntegrationService.d.cts +30 -0
  237. package/dist/services/RewardsIntegrationService.d.cts.map +1 -0
  238. package/dist/services/RewardsIntegrationService.d.mts +30 -0
  239. package/dist/services/RewardsIntegrationService.d.mts.map +1 -0
  240. package/dist/services/RewardsIntegrationService.mjs +90 -0
  241. package/dist/services/RewardsIntegrationService.mjs.map +1 -0
  242. package/dist/services/ServiceContext.cjs +3 -0
  243. package/dist/services/ServiceContext.cjs.map +1 -0
  244. package/dist/services/ServiceContext.d.cts +110 -0
  245. package/dist/services/ServiceContext.d.cts.map +1 -0
  246. package/dist/services/ServiceContext.d.mts +110 -0
  247. package/dist/services/ServiceContext.d.mts.map +1 -0
  248. package/dist/services/ServiceContext.mjs +2 -0
  249. package/dist/services/ServiceContext.mjs.map +1 -0
  250. package/dist/services/TradingService.cjs +1481 -0
  251. package/dist/services/TradingService.cjs.map +1 -0
  252. package/dist/services/TradingService.d.cts +308 -0
  253. package/dist/services/TradingService.d.cts.map +1 -0
  254. package/dist/services/TradingService.d.mts +308 -0
  255. package/dist/services/TradingService.d.mts.map +1 -0
  256. package/dist/services/TradingService.mjs +1477 -0
  257. package/dist/services/TradingService.mjs.map +1 -0
  258. package/dist/services/index.cjs +26 -0
  259. package/dist/services/index.cjs.map +1 -0
  260. package/dist/services/index.d.cts +11 -0
  261. package/dist/services/index.d.cts.map +1 -0
  262. package/dist/services/index.d.mts +11 -0
  263. package/dist/services/index.d.mts.map +1 -0
  264. package/dist/services/index.mjs +10 -0
  265. package/dist/services/index.mjs.map +1 -0
  266. package/dist/services/utils.cjs +16 -0
  267. package/dist/services/utils.cjs.map +1 -0
  268. package/dist/services/utils.d.cts +8 -0
  269. package/dist/services/utils.d.cts.map +1 -0
  270. package/dist/services/utils.d.mts +8 -0
  271. package/dist/services/utils.d.mts.map +1 -0
  272. package/dist/services/utils.mjs +12 -0
  273. package/dist/services/utils.mjs.map +1 -0
  274. package/dist/types/chart.cjs +42 -0
  275. package/dist/types/chart.cjs.map +1 -0
  276. package/dist/types/chart.d.cts +62 -0
  277. package/dist/types/chart.d.cts.map +1 -0
  278. package/dist/types/chart.d.mts +62 -0
  279. package/dist/types/chart.d.mts.map +1 -0
  280. package/dist/types/chart.mjs +39 -0
  281. package/dist/types/chart.mjs.map +1 -0
  282. package/dist/types/hyperliquid-types.cjs +3 -0
  283. package/dist/types/hyperliquid-types.cjs.map +1 -0
  284. package/dist/types/hyperliquid-types.d.cts +52 -0
  285. package/dist/types/hyperliquid-types.d.cts.map +1 -0
  286. package/dist/types/hyperliquid-types.d.mts +52 -0
  287. package/dist/types/hyperliquid-types.d.mts.map +1 -0
  288. package/dist/types/hyperliquid-types.mjs +2 -0
  289. package/dist/types/hyperliquid-types.mjs.map +1 -0
  290. package/dist/types/index.cjs +96 -0
  291. package/dist/types/index.cjs.map +1 -0
  292. package/dist/types/index.d.cts +1153 -0
  293. package/dist/types/index.d.cts.map +1 -0
  294. package/dist/types/index.d.mts +1153 -0
  295. package/dist/types/index.d.mts.map +1 -0
  296. package/dist/types/index.mjs +79 -0
  297. package/dist/types/index.mjs.map +1 -0
  298. package/dist/types/transactionTypes.cjs +28 -0
  299. package/dist/types/transactionTypes.cjs.map +1 -0
  300. package/dist/types/transactionTypes.d.cts +64 -0
  301. package/dist/types/transactionTypes.d.cts.map +1 -0
  302. package/dist/types/transactionTypes.d.mts +64 -0
  303. package/dist/types/transactionTypes.d.mts.map +1 -0
  304. package/dist/types/transactionTypes.mjs +23 -0
  305. package/dist/types/transactionTypes.mjs.map +1 -0
  306. package/dist/utils/accountUtils.cjs +65 -0
  307. package/dist/utils/accountUtils.cjs.map +1 -0
  308. package/dist/utils/accountUtils.d.cts +26 -0
  309. package/dist/utils/accountUtils.d.cts.map +1 -0
  310. package/dist/utils/accountUtils.d.mts +26 -0
  311. package/dist/utils/accountUtils.d.mts.map +1 -0
  312. package/dist/utils/accountUtils.mjs +61 -0
  313. package/dist/utils/accountUtils.mjs.map +1 -0
  314. package/dist/utils/amountConversion.cjs +61 -0
  315. package/dist/utils/amountConversion.cjs.map +1 -0
  316. package/dist/utils/amountConversion.d.cts +16 -0
  317. package/dist/utils/amountConversion.d.cts.map +1 -0
  318. package/dist/utils/amountConversion.d.mts +16 -0
  319. package/dist/utils/amountConversion.d.mts.map +1 -0
  320. package/dist/utils/amountConversion.mjs +54 -0
  321. package/dist/utils/amountConversion.mjs.map +1 -0
  322. package/dist/utils/chartUtils.cjs +98 -0
  323. package/dist/utils/chartUtils.cjs.map +1 -0
  324. package/dist/utils/chartUtils.d.cts +14 -0
  325. package/dist/utils/chartUtils.d.cts.map +1 -0
  326. package/dist/utils/chartUtils.d.mts +14 -0
  327. package/dist/utils/chartUtils.d.mts.map +1 -0
  328. package/dist/utils/chartUtils.mjs +94 -0
  329. package/dist/utils/chartUtils.mjs.map +1 -0
  330. package/dist/utils/errorUtils.cjs +22 -0
  331. package/dist/utils/errorUtils.cjs.map +1 -0
  332. package/dist/utils/errorUtils.d.cts +13 -0
  333. package/dist/utils/errorUtils.d.cts.map +1 -0
  334. package/dist/utils/errorUtils.d.mts +13 -0
  335. package/dist/utils/errorUtils.d.mts.map +1 -0
  336. package/dist/utils/errorUtils.mjs +18 -0
  337. package/dist/utils/errorUtils.mjs.map +1 -0
  338. package/dist/utils/formatUtils.cjs +987 -0
  339. package/dist/utils/formatUtils.cjs.map +1 -0
  340. package/dist/utils/formatUtils.d.cts +387 -0
  341. package/dist/utils/formatUtils.d.cts.map +1 -0
  342. package/dist/utils/formatUtils.d.mts +387 -0
  343. package/dist/utils/formatUtils.d.mts.map +1 -0
  344. package/dist/utils/formatUtils.mjs +966 -0
  345. package/dist/utils/formatUtils.mjs.map +1 -0
  346. package/dist/utils/hyperLiquidAdapter.cjs +454 -0
  347. package/dist/utils/hyperLiquidAdapter.cjs.map +1 -0
  348. package/dist/utils/hyperLiquidAdapter.d.cts +158 -0
  349. package/dist/utils/hyperLiquidAdapter.d.cts.map +1 -0
  350. package/dist/utils/hyperLiquidAdapter.d.mts +158 -0
  351. package/dist/utils/hyperLiquidAdapter.d.mts.map +1 -0
  352. package/dist/utils/hyperLiquidAdapter.mjs +439 -0
  353. package/dist/utils/hyperLiquidAdapter.mjs.map +1 -0
  354. package/dist/utils/hyperLiquidOrderBookProcessor.cjs +89 -0
  355. package/dist/utils/hyperLiquidOrderBookProcessor.cjs.map +1 -0
  356. package/dist/utils/hyperLiquidOrderBookProcessor.d.cts +58 -0
  357. package/dist/utils/hyperLiquidOrderBookProcessor.d.cts.map +1 -0
  358. package/dist/utils/hyperLiquidOrderBookProcessor.d.mts +58 -0
  359. package/dist/utils/hyperLiquidOrderBookProcessor.d.mts.map +1 -0
  360. package/dist/utils/hyperLiquidOrderBookProcessor.mjs +84 -0
  361. package/dist/utils/hyperLiquidOrderBookProcessor.mjs.map +1 -0
  362. package/dist/utils/hyperLiquidValidation.cjs +426 -0
  363. package/dist/utils/hyperLiquidValidation.cjs.map +1 -0
  364. package/dist/utils/hyperLiquidValidation.d.cts +143 -0
  365. package/dist/utils/hyperLiquidValidation.d.cts.map +1 -0
  366. package/dist/utils/hyperLiquidValidation.d.mts +143 -0
  367. package/dist/utils/hyperLiquidValidation.d.mts.map +1 -0
  368. package/dist/utils/hyperLiquidValidation.mjs +413 -0
  369. package/dist/utils/hyperLiquidValidation.mjs.map +1 -0
  370. package/dist/utils/idUtils.cjs +50 -0
  371. package/dist/utils/idUtils.cjs.map +1 -0
  372. package/dist/utils/idUtils.d.cts +38 -0
  373. package/dist/utils/idUtils.d.cts.map +1 -0
  374. package/dist/utils/idUtils.d.mts +38 -0
  375. package/dist/utils/idUtils.d.mts.map +1 -0
  376. package/dist/utils/idUtils.mjs +42 -0
  377. package/dist/utils/idUtils.mjs.map +1 -0
  378. package/dist/utils/marginUtils.cjs +137 -0
  379. package/dist/utils/marginUtils.cjs.map +1 -0
  380. package/dist/utils/marginUtils.d.cts +64 -0
  381. package/dist/utils/marginUtils.d.cts.map +1 -0
  382. package/dist/utils/marginUtils.d.mts +64 -0
  383. package/dist/utils/marginUtils.d.mts.map +1 -0
  384. package/dist/utils/marginUtils.mjs +131 -0
  385. package/dist/utils/marginUtils.mjs.map +1 -0
  386. package/dist/utils/marketDataTransform.cjs +227 -0
  387. package/dist/utils/marketDataTransform.cjs.map +1 -0
  388. package/dist/utils/marketDataTransform.d.cts +45 -0
  389. package/dist/utils/marketDataTransform.d.cts.map +1 -0
  390. package/dist/utils/marketDataTransform.d.mts +45 -0
  391. package/dist/utils/marketDataTransform.d.mts.map +1 -0
  392. package/dist/utils/marketDataTransform.mjs +220 -0
  393. package/dist/utils/marketDataTransform.mjs.map +1 -0
  394. package/dist/utils/marketUtils.cjs +420 -0
  395. package/dist/utils/marketUtils.cjs.map +1 -0
  396. package/dist/utils/marketUtils.d.cts +227 -0
  397. package/dist/utils/marketUtils.d.cts.map +1 -0
  398. package/dist/utils/marketUtils.d.mts +227 -0
  399. package/dist/utils/marketUtils.d.mts.map +1 -0
  400. package/dist/utils/marketUtils.mjs +404 -0
  401. package/dist/utils/marketUtils.mjs.map +1 -0
  402. package/dist/utils/orderBookGrouping.cjs +151 -0
  403. package/dist/utils/orderBookGrouping.cjs.map +1 -0
  404. package/dist/utils/orderBookGrouping.d.cts +76 -0
  405. package/dist/utils/orderBookGrouping.d.cts.map +1 -0
  406. package/dist/utils/orderBookGrouping.d.mts +76 -0
  407. package/dist/utils/orderBookGrouping.d.mts.map +1 -0
  408. package/dist/utils/orderBookGrouping.mjs +143 -0
  409. package/dist/utils/orderBookGrouping.mjs.map +1 -0
  410. package/dist/utils/orderCalculations.cjs +283 -0
  411. package/dist/utils/orderCalculations.cjs.map +1 -0
  412. package/dist/utils/orderCalculations.d.cts +107 -0
  413. package/dist/utils/orderCalculations.d.cts.map +1 -0
  414. package/dist/utils/orderCalculations.d.mts +107 -0
  415. package/dist/utils/orderCalculations.d.mts.map +1 -0
  416. package/dist/utils/orderCalculations.mjs +274 -0
  417. package/dist/utils/orderCalculations.mjs.map +1 -0
  418. package/dist/utils/orderUtils.cjs +159 -0
  419. package/dist/utils/orderUtils.cjs.map +1 -0
  420. package/dist/utils/orderUtils.d.cts +66 -0
  421. package/dist/utils/orderUtils.d.cts.map +1 -0
  422. package/dist/utils/orderUtils.d.mts +66 -0
  423. package/dist/utils/orderUtils.d.mts.map +1 -0
  424. package/dist/utils/orderUtils.mjs +151 -0
  425. package/dist/utils/orderUtils.mjs.map +1 -0
  426. package/dist/utils/pnlCalculations.cjs +107 -0
  427. package/dist/utils/pnlCalculations.cjs.map +1 -0
  428. package/dist/utils/pnlCalculations.d.cts +79 -0
  429. package/dist/utils/pnlCalculations.d.cts.map +1 -0
  430. package/dist/utils/pnlCalculations.d.mts +79 -0
  431. package/dist/utils/pnlCalculations.d.mts.map +1 -0
  432. package/dist/utils/pnlCalculations.mjs +97 -0
  433. package/dist/utils/pnlCalculations.mjs.map +1 -0
  434. package/dist/utils/positionCalculations.cjs +176 -0
  435. package/dist/utils/positionCalculations.cjs.map +1 -0
  436. package/dist/utils/positionCalculations.d.cts +85 -0
  437. package/dist/utils/positionCalculations.d.cts.map +1 -0
  438. package/dist/utils/positionCalculations.d.mts +85 -0
  439. package/dist/utils/positionCalculations.d.mts.map +1 -0
  440. package/dist/utils/positionCalculations.mjs +165 -0
  441. package/dist/utils/positionCalculations.mjs.map +1 -0
  442. package/dist/utils/sortMarkets.cjs +88 -0
  443. package/dist/utils/sortMarkets.cjs.map +1 -0
  444. package/dist/utils/sortMarkets.d.cts +21 -0
  445. package/dist/utils/sortMarkets.d.cts.map +1 -0
  446. package/dist/utils/sortMarkets.d.mts +21 -0
  447. package/dist/utils/sortMarkets.d.mts.map +1 -0
  448. package/dist/utils/sortMarkets.mjs +84 -0
  449. package/dist/utils/sortMarkets.mjs.map +1 -0
  450. package/dist/utils/standaloneInfoClient.cjs +34 -0
  451. package/dist/utils/standaloneInfoClient.cjs.map +1 -0
  452. package/dist/utils/standaloneInfoClient.d.cts +31 -0
  453. package/dist/utils/standaloneInfoClient.d.cts.map +1 -0
  454. package/dist/utils/standaloneInfoClient.d.mts +31 -0
  455. package/dist/utils/standaloneInfoClient.d.mts.map +1 -0
  456. package/dist/utils/standaloneInfoClient.mjs +30 -0
  457. package/dist/utils/standaloneInfoClient.mjs.map +1 -0
  458. package/dist/utils/stringParseUtils.cjs +49 -0
  459. package/dist/utils/stringParseUtils.cjs.map +1 -0
  460. package/dist/utils/stringParseUtils.d.cts +35 -0
  461. package/dist/utils/stringParseUtils.d.cts.map +1 -0
  462. package/dist/utils/stringParseUtils.d.mts +35 -0
  463. package/dist/utils/stringParseUtils.d.mts.map +1 -0
  464. package/dist/utils/stringParseUtils.mjs +44 -0
  465. package/dist/utils/stringParseUtils.mjs.map +1 -0
  466. package/dist/utils/time.cjs +37 -0
  467. package/dist/utils/time.cjs.map +1 -0
  468. package/dist/utils/time.d.cts +17 -0
  469. package/dist/utils/time.d.cts.map +1 -0
  470. package/dist/utils/time.d.mts +17 -0
  471. package/dist/utils/time.d.mts.map +1 -0
  472. package/dist/utils/time.mjs +33 -0
  473. package/dist/utils/time.mjs.map +1 -0
  474. package/dist/utils/tpslValidation.cjs +505 -0
  475. package/dist/utils/tpslValidation.cjs.map +1 -0
  476. package/dist/utils/tpslValidation.d.cts +182 -0
  477. package/dist/utils/tpslValidation.d.cts.map +1 -0
  478. package/dist/utils/tpslValidation.d.mts +182 -0
  479. package/dist/utils/tpslValidation.d.mts.map +1 -0
  480. package/dist/utils/tpslValidation.mjs +482 -0
  481. package/dist/utils/tpslValidation.mjs.map +1 -0
  482. package/dist/utils/transactionUtils.cjs +36 -0
  483. package/dist/utils/transactionUtils.cjs.map +1 -0
  484. package/dist/utils/transactionUtils.d.cts +17 -0
  485. package/dist/utils/transactionUtils.d.cts.map +1 -0
  486. package/dist/utils/transactionUtils.d.mts +17 -0
  487. package/dist/utils/transactionUtils.d.mts.map +1 -0
  488. package/dist/utils/transactionUtils.mjs +32 -0
  489. package/dist/utils/transactionUtils.mjs.map +1 -0
  490. package/dist/utils/wait.cjs +12 -0
  491. package/dist/utils/wait.cjs.map +1 -0
  492. package/dist/utils/wait.d.cts +8 -0
  493. package/dist/utils/wait.d.cts.map +1 -0
  494. package/dist/utils/wait.d.mts +8 -0
  495. package/dist/utils/wait.d.mts.map +1 -0
  496. package/dist/utils/wait.mjs +8 -0
  497. package/dist/utils/wait.mjs.map +1 -0
  498. package/package.json +19 -4
@@ -0,0 +1,1481 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TradingService = void 0;
4
+ /* eslint-disable id-denylist, jsdoc/require-param-description, @typescript-eslint/prefer-nullish-coalescing, no-restricted-syntax, @typescript-eslint/naming-convention, @typescript-eslint/unbound-method, no-eq-null, jsdoc/check-param-names */
5
+ // TODO: Fix ESLint errors in this file - tracked for Phase 5 cleanup
6
+ const uuid_1 = require("uuid");
7
+ const eventNames_1 = require("../constants/eventNames.cjs");
8
+ const orderTypes_1 = require("../constants/orderTypes.cjs");
9
+ const performanceMetrics_1 = require("../constants/performanceMetrics.cjs");
10
+ const types_1 = require("../types/index.cjs");
11
+ /**
12
+ * TradingService
13
+ *
14
+ * Handles trading operations with fee discount management.
15
+ * Controller is responsible for analytics, state management, and tracing.
16
+ *
17
+ * Instance-based service with constructor injection of platform dependencies.
18
+ * Controller-level dependencies (RewardsController, NetworkController, etc.)
19
+ * are injected via setControllerDependencies() after construction.
20
+ */
21
+ class TradingService {
22
+ /**
23
+ * Create a new TradingService instance.
24
+ *
25
+ * @param deps - Platform dependencies for logging, metrics, etc.
26
+ */
27
+ constructor(deps) {
28
+ /**
29
+ * Controller-level dependencies for fee discount calculation.
30
+ * Set via setControllerDependencies() after construction.
31
+ */
32
+ this.controllerDeps = null;
33
+ this.deps = deps;
34
+ }
35
+ /**
36
+ * Set controller-level dependencies for fee discount calculation.
37
+ * Called by PerpsController after construction to inject singleton dependencies.
38
+ *
39
+ * @param controllerDeps - Controller-level dependencies (RewardsController, etc.)
40
+ */
41
+ setControllerDependencies(controllerDeps) {
42
+ this.controllerDeps = controllerDeps;
43
+ }
44
+ /**
45
+ * Error context helper for consistent logging.
46
+ *
47
+ * @param method - Method name
48
+ * @param additionalContext - Additional context data
49
+ * @returns Error context object
50
+ */
51
+ getErrorContext(method, additionalContext) {
52
+ return {
53
+ controller: 'TradingService',
54
+ method,
55
+ ...additionalContext,
56
+ };
57
+ }
58
+ /**
59
+ * Track order result analytics event (success or failure).
60
+ *
61
+ * @param options - Tracking options
62
+ * @param options.result
63
+ * @param options.error
64
+ * @param options.params
65
+ * @param options.context
66
+ * @param options.duration
67
+ */
68
+ trackOrderResult(options) {
69
+ const { result, error, params, duration } = options;
70
+ const status = result?.success === true
71
+ ? eventNames_1.PerpsEventValues.STATUS.EXECUTED
72
+ : eventNames_1.PerpsEventValues.STATUS.FAILED;
73
+ // Build base properties
74
+ const properties = {
75
+ [eventNames_1.PerpsEventProperties.STATUS]: status,
76
+ [eventNames_1.PerpsEventProperties.ASSET]: params.symbol,
77
+ [eventNames_1.PerpsEventProperties.DIRECTION]: params.isBuy
78
+ ? eventNames_1.PerpsEventValues.DIRECTION.LONG
79
+ : eventNames_1.PerpsEventValues.DIRECTION.SHORT,
80
+ [eventNames_1.PerpsEventProperties.ORDER_TYPE]: params.orderType,
81
+ [eventNames_1.PerpsEventProperties.LEVERAGE]: parseFloat(String(params.leverage || 1)),
82
+ [eventNames_1.PerpsEventProperties.ORDER_SIZE]: parseFloat(result?.filledSize || params.size),
83
+ [eventNames_1.PerpsEventProperties.COMPLETION_DURATION]: duration,
84
+ };
85
+ // Add optional properties
86
+ if (params.trackingData?.marginUsed != null) {
87
+ properties[eventNames_1.PerpsEventProperties.MARGIN_USED] =
88
+ params.trackingData.marginUsed;
89
+ }
90
+ if (params.trackingData?.totalFee != null) {
91
+ properties[eventNames_1.PerpsEventProperties.FEES] = params.trackingData.totalFee;
92
+ }
93
+ if (result?.averagePrice || params.trackingData?.marketPrice) {
94
+ properties[eventNames_1.PerpsEventProperties.ASSET_PRICE] = result?.averagePrice
95
+ ? parseFloat(result.averagePrice)
96
+ : params.trackingData?.marketPrice;
97
+ }
98
+ if (params.orderType === 'limit' && params.price) {
99
+ properties[eventNames_1.PerpsEventProperties.LIMIT_PRICE] = parseFloat(params.price);
100
+ }
101
+ if (params.trackingData?.source) {
102
+ properties[eventNames_1.PerpsEventProperties.SOURCE] = params.trackingData.source;
103
+ }
104
+ if (params.trackingData?.tradeAction) {
105
+ properties[eventNames_1.PerpsEventProperties.ACTION] = params.trackingData.tradeAction;
106
+ }
107
+ // Add success-specific properties
108
+ if (status === eventNames_1.PerpsEventValues.STATUS.EXECUTED) {
109
+ if (params.trackingData?.metamaskFee != null) {
110
+ properties[eventNames_1.PerpsEventProperties.METAMASK_FEE] =
111
+ params.trackingData.metamaskFee;
112
+ }
113
+ if (params.trackingData?.metamaskFeeRate != null) {
114
+ properties[eventNames_1.PerpsEventProperties.METAMASK_FEE_RATE] =
115
+ params.trackingData.metamaskFeeRate;
116
+ }
117
+ if (params.trackingData?.feeDiscountPercentage != null) {
118
+ properties[eventNames_1.PerpsEventProperties.DISCOUNT_PERCENTAGE] =
119
+ params.trackingData.feeDiscountPercentage;
120
+ }
121
+ if (params.trackingData?.estimatedPoints != null) {
122
+ properties[eventNames_1.PerpsEventProperties.ESTIMATED_REWARDS] =
123
+ params.trackingData.estimatedPoints;
124
+ }
125
+ if (params.takeProfitPrice) {
126
+ properties[eventNames_1.PerpsEventProperties.TAKE_PROFIT_PRICE] = parseFloat(params.takeProfitPrice);
127
+ }
128
+ if (params.stopLossPrice) {
129
+ properties[eventNames_1.PerpsEventProperties.STOP_LOSS_PRICE] = parseFloat(params.stopLossPrice);
130
+ }
131
+ }
132
+ else {
133
+ // Add failure-specific properties
134
+ properties[eventNames_1.PerpsEventProperties.ERROR_MESSAGE] =
135
+ error?.message || result?.error || 'Unknown error';
136
+ }
137
+ this.deps.metrics.trackPerpsEvent(types_1.PerpsAnalyticsEvent.TradeTransaction, properties);
138
+ }
139
+ /**
140
+ * Handle successful order placement (state updates, analytics, data lake reporting).
141
+ *
142
+ * @param options - Options for handling order success
143
+ * @param options.params
144
+ * @param options.context
145
+ * @param options.reportOrderToDataLake
146
+ */
147
+ async handleOrderSuccess(options) {
148
+ const { params, context, reportOrderToDataLake } = options;
149
+ // Update state on success
150
+ if (context.stateManager) {
151
+ context.stateManager.update((state) => {
152
+ state.lastUpdateTimestamp = Date.now();
153
+ });
154
+ }
155
+ // Save executed trade configuration for this market
156
+ if (params.leverage && context.saveTradeConfiguration) {
157
+ context.saveTradeConfiguration(params.symbol, params.leverage);
158
+ }
159
+ // Report to data lake (fire-and-forget with retry)
160
+ reportOrderToDataLake({
161
+ action: 'open',
162
+ symbol: params.symbol,
163
+ sl_price: params.stopLossPrice
164
+ ? parseFloat(params.stopLossPrice)
165
+ : undefined,
166
+ tp_price: params.takeProfitPrice
167
+ ? parseFloat(params.takeProfitPrice)
168
+ : undefined,
169
+ }).catch((caughtError) => {
170
+ const errorObj = caughtError instanceof Error
171
+ ? caughtError
172
+ : new Error(String(caughtError));
173
+ this.deps.logger.error(errorObj, {
174
+ tags: {
175
+ feature: 'perps',
176
+ provider: context.tracingContext.provider,
177
+ network: context.tracingContext.isTestnet ? 'testnet' : 'mainnet',
178
+ },
179
+ context: {
180
+ name: context.errorContext.controller,
181
+ data: {
182
+ method: context.errorContext.method,
183
+ operation: 'reportOrderToDataLake',
184
+ symbol: params.symbol,
185
+ },
186
+ },
187
+ });
188
+ });
189
+ }
190
+ /**
191
+ * Execute a trading operation with fee discount context.
192
+ * Ensures fee discount is always cleared after operation (success or failure).
193
+ *
194
+ * @param options - Options for fee discount context
195
+ * @param options.provider
196
+ * @param options.feeDiscountBips
197
+ * @param options.operation
198
+ * @returns The operation result
199
+ */
200
+ async withFeeDiscount(options) {
201
+ const { provider, feeDiscountBips, operation } = options;
202
+ try {
203
+ // Set discount context in provider for this operation
204
+ if (feeDiscountBips !== undefined && provider.setUserFeeDiscount) {
205
+ provider.setUserFeeDiscount(feeDiscountBips);
206
+ this.deps.debugLogger.log('TradingService: Fee discount set in provider', {
207
+ feeDiscountBips,
208
+ });
209
+ }
210
+ // Execute the operation
211
+ return await operation();
212
+ }
213
+ finally {
214
+ // Always clear discount context, even on exception
215
+ if (provider.setUserFeeDiscount) {
216
+ provider.setUserFeeDiscount(undefined);
217
+ this.deps.debugLogger.log('TradingService: Fee discount cleared from provider');
218
+ }
219
+ }
220
+ }
221
+ /**
222
+ * Place a new order with full orchestration.
223
+ * Handles tracing, fee discounts, state management, analytics, and data lake reporting.
224
+ *
225
+ * @param options - Options for placing order
226
+ * @param options.provider
227
+ * @param options.params
228
+ * @param options.context
229
+ * @param options.reportOrderToDataLake
230
+ * @returns Order result
231
+ */
232
+ async placeOrder(options) {
233
+ const { provider, params, context, reportOrderToDataLake } = options;
234
+ const traceId = (0, uuid_1.v4)();
235
+ const startTime = this.deps.performance.now();
236
+ let traceData;
237
+ try {
238
+ // Start trace for the entire operation
239
+ this.deps.tracer.trace({
240
+ name: types_1.PerpsTraceNames.PlaceOrder,
241
+ id: traceId,
242
+ op: types_1.PerpsTraceOperations.OrderSubmission,
243
+ tags: {
244
+ provider: context.tracingContext.provider,
245
+ orderType: params.orderType,
246
+ market: params.symbol,
247
+ leverage: String(params.leverage || 1),
248
+ isTestnet: String(context.tracingContext.isTestnet),
249
+ },
250
+ data: {
251
+ isBuy: params.isBuy,
252
+ orderPrice: params.price || '',
253
+ },
254
+ });
255
+ // Calculate fee discount at execution time (fresh, secure)
256
+ const feeDiscountBips = await this.calculateFeeDiscountWithMeasurement();
257
+ this.deps.debugLogger.log('TradingService: Fee discount calculated', {
258
+ feeDiscountBips,
259
+ hasDiscount: feeDiscountBips !== undefined,
260
+ });
261
+ this.deps.debugLogger.log('TradingService: Submitting order to provider', {
262
+ symbol: params.symbol,
263
+ orderType: params.orderType,
264
+ isBuy: params.isBuy,
265
+ size: params.size,
266
+ leverage: params.leverage,
267
+ hasTP: Boolean(params.takeProfitPrice),
268
+ hasSL: Boolean(params.stopLossPrice),
269
+ });
270
+ // Execute order with fee discount management
271
+ const result = await this.withFeeDiscount({
272
+ provider,
273
+ feeDiscountBips,
274
+ operation: () => provider.placeOrder(params),
275
+ });
276
+ this.deps.debugLogger.log('TradingService: Provider response received', {
277
+ success: result.success,
278
+ orderId: result.orderId,
279
+ error: result.error,
280
+ });
281
+ // Update state and handle success/failure
282
+ const completionDuration = this.deps.performance.now() - startTime;
283
+ if (result.success) {
284
+ // Handle success: state updates, data lake reporting
285
+ await this.handleOrderSuccess({
286
+ params,
287
+ context,
288
+ reportOrderToDataLake,
289
+ });
290
+ traceData = { success: true, orderId: result.orderId || '' };
291
+ }
292
+ else {
293
+ traceData = { success: false, error: result.error || 'Unknown error' };
294
+ }
295
+ // Track analytics (success or failure)
296
+ this.trackOrderResult({
297
+ result,
298
+ params,
299
+ context,
300
+ duration: completionDuration,
301
+ });
302
+ return result;
303
+ }
304
+ catch (err) {
305
+ const completionDuration = this.deps.performance.now() - startTime;
306
+ const error = err instanceof Error ? err : new Error(String(err));
307
+ // Track analytics for exception
308
+ this.trackOrderResult({
309
+ result: null,
310
+ error,
311
+ params,
312
+ context,
313
+ duration: completionDuration,
314
+ });
315
+ this.deps.logger.error(error, {
316
+ tags: {
317
+ feature: 'perps',
318
+ provider: context.tracingContext.provider,
319
+ network: context.tracingContext.isTestnet ? 'testnet' : 'mainnet',
320
+ },
321
+ context: {
322
+ name: context.errorContext.controller,
323
+ data: {
324
+ method: context.errorContext.method,
325
+ symbol: params.symbol,
326
+ orderType: params.orderType,
327
+ },
328
+ },
329
+ });
330
+ traceData = {
331
+ success: false,
332
+ error: error.message,
333
+ };
334
+ throw err;
335
+ }
336
+ finally {
337
+ // Always end trace on exit (success or failure)
338
+ this.deps.tracer.endTrace({
339
+ name: types_1.PerpsTraceNames.PlaceOrder,
340
+ id: traceId,
341
+ data: traceData,
342
+ });
343
+ }
344
+ }
345
+ /**
346
+ * Load position data with performance measurement.
347
+ *
348
+ * @param options - Options for loading position data
349
+ * @param options.symbol
350
+ * @param options.context
351
+ * @returns The position or undefined
352
+ */
353
+ async loadPositionData(options) {
354
+ const { symbol, context } = options;
355
+ const positionLoadStart = this.deps.performance.now();
356
+ try {
357
+ const positions = context.getPositions
358
+ ? await context.getPositions()
359
+ : [];
360
+ const position = positions.find((pos) => pos.symbol === symbol);
361
+ this.deps.tracer.setMeasurement(performanceMetrics_1.PerpsMeasurementName.PerpsGetPositionsOperation, this.deps.performance.now() - positionLoadStart, 'millisecond');
362
+ return position;
363
+ }
364
+ catch (err) {
365
+ this.deps.debugLogger.log('TradingService: Could not get position data for tracking', err instanceof Error ? err.message : String(err));
366
+ return undefined;
367
+ }
368
+ }
369
+ /**
370
+ * Calculate close position metrics.
371
+ *
372
+ * @param position - The position being closed
373
+ * @param params - Close position parameters
374
+ * @param result - Order result
375
+ * @returns Calculated metrics
376
+ */
377
+ calculateCloseMetrics(position, params, result) {
378
+ const direction = parseFloat(position.size) > 0
379
+ ? eventNames_1.PerpsEventValues.DIRECTION.LONG
380
+ : eventNames_1.PerpsEventValues.DIRECTION.SHORT;
381
+ const filledSize = result.filledSize ? parseFloat(result.filledSize) : 0;
382
+ const requestedSize = params.size
383
+ ? parseFloat(params.size)
384
+ : Math.abs(parseFloat(position.size));
385
+ const isPartiallyFilled = filledSize > 0 && filledSize < requestedSize;
386
+ const orderType = params.orderType || eventNames_1.PerpsEventValues.ORDER_TYPE.MARKET;
387
+ const closePercentage = params.size
388
+ ? (parseFloat(params.size) / Math.abs(parseFloat(position.size))) * 100
389
+ : 100;
390
+ const closeType = closePercentage === 100
391
+ ? eventNames_1.PerpsEventValues.CLOSE_TYPE.FULL
392
+ : eventNames_1.PerpsEventValues.CLOSE_TYPE.PARTIAL;
393
+ return {
394
+ direction,
395
+ closePercentage,
396
+ closeType,
397
+ orderType,
398
+ filledSize,
399
+ requestedSize,
400
+ isPartiallyFilled,
401
+ };
402
+ }
403
+ /**
404
+ * Build event properties for position close analytics.
405
+ *
406
+ * @param position - The position being closed
407
+ * @param params - Close position parameters
408
+ * @param metrics - Calculated metrics
409
+ * @param metrics.direction
410
+ * @param result - Order result
411
+ * @param metrics.closePercentage
412
+ * @param status - Event status
413
+ * @param metrics.closeType
414
+ * @param error - Error message if any
415
+ * @param metrics.orderType
416
+ * @param metrics.requestedSize
417
+ * @returns Event properties
418
+ */
419
+ buildCloseEventProperties(position, params, metrics, result, status, error) {
420
+ const baseProperties = {
421
+ [eventNames_1.PerpsEventProperties.STATUS]: status,
422
+ [eventNames_1.PerpsEventProperties.ASSET]: position.symbol,
423
+ [eventNames_1.PerpsEventProperties.DIRECTION]: metrics.direction,
424
+ [eventNames_1.PerpsEventProperties.ORDER_TYPE]: metrics.orderType,
425
+ [eventNames_1.PerpsEventProperties.ORDER_SIZE]: metrics.requestedSize,
426
+ [eventNames_1.PerpsEventProperties.OPEN_POSITION_SIZE]: Math.abs(parseFloat(position.size)),
427
+ [eventNames_1.PerpsEventProperties.PERCENTAGE_CLOSED]: metrics.closePercentage,
428
+ ...(position.unrealizedPnl && {
429
+ [eventNames_1.PerpsEventProperties.PNL_DOLLAR]: parseFloat(position.unrealizedPnl),
430
+ }),
431
+ ...(position.returnOnEquity && {
432
+ [eventNames_1.PerpsEventProperties.PNL_PERCENT]: parseFloat(position.returnOnEquity) * 100,
433
+ }),
434
+ ...(params.trackingData?.totalFee != null && {
435
+ [eventNames_1.PerpsEventProperties.FEE]: params.trackingData.totalFee,
436
+ }),
437
+ ...(params.trackingData?.metamaskFee != null && {
438
+ [eventNames_1.PerpsEventProperties.METAMASK_FEE]: params.trackingData.metamaskFee,
439
+ }),
440
+ ...(params.trackingData?.metamaskFeeRate != null && {
441
+ [eventNames_1.PerpsEventProperties.METAMASK_FEE_RATE]: params.trackingData.metamaskFeeRate,
442
+ }),
443
+ ...(params.trackingData?.feeDiscountPercentage != null && {
444
+ [eventNames_1.PerpsEventProperties.DISCOUNT_PERCENTAGE]: params.trackingData.feeDiscountPercentage,
445
+ }),
446
+ ...(params.trackingData?.estimatedPoints != null && {
447
+ [eventNames_1.PerpsEventProperties.ESTIMATED_REWARDS]: params.trackingData.estimatedPoints,
448
+ }),
449
+ ...((params.trackingData?.marketPrice || result?.averagePrice) && {
450
+ [eventNames_1.PerpsEventProperties.ASSET_PRICE]: result?.averagePrice
451
+ ? parseFloat(result.averagePrice)
452
+ : params.trackingData?.marketPrice,
453
+ }),
454
+ ...(params.orderType === 'limit' &&
455
+ params.price && {
456
+ [eventNames_1.PerpsEventProperties.LIMIT_PRICE]: parseFloat(params.price),
457
+ }),
458
+ ...(params.trackingData?.receivedAmount != null && {
459
+ [eventNames_1.PerpsEventProperties.RECEIVED_AMOUNT]: params.trackingData.receivedAmount,
460
+ }),
461
+ };
462
+ // Add success-specific properties
463
+ if (status === eventNames_1.PerpsEventValues.STATUS.EXECUTED) {
464
+ return {
465
+ ...baseProperties,
466
+ [eventNames_1.PerpsEventProperties.CLOSE_TYPE]: metrics.closeType,
467
+ };
468
+ }
469
+ // Add error for failures
470
+ return {
471
+ ...baseProperties,
472
+ ...(error && { [eventNames_1.PerpsEventProperties.ERROR_MESSAGE]: error }),
473
+ };
474
+ }
475
+ /**
476
+ * Track position close result analytics (consolidates all tracking logic).
477
+ *
478
+ * @param options - Tracking options
479
+ * @param options.position
480
+ * @param options.result
481
+ * @param options.error
482
+ * @param options.params
483
+ * @param options.context
484
+ * @param options.duration
485
+ */
486
+ trackPositionCloseResult(options) {
487
+ const { position, result, error, params, duration } = options;
488
+ if (!position) {
489
+ return;
490
+ }
491
+ const metrics = result
492
+ ? this.calculateCloseMetrics(position, params, result)
493
+ : {
494
+ direction: parseFloat(position.size) > 0
495
+ ? eventNames_1.PerpsEventValues.DIRECTION.LONG
496
+ : eventNames_1.PerpsEventValues.DIRECTION.SHORT,
497
+ closePercentage: params.size
498
+ ? (parseFloat(params.size) / Math.abs(parseFloat(position.size))) *
499
+ 100
500
+ : 100,
501
+ closeType: eventNames_1.PerpsEventValues.CLOSE_TYPE.FULL,
502
+ orderType: params.orderType || eventNames_1.PerpsEventValues.ORDER_TYPE.MARKET,
503
+ requestedSize: params.size
504
+ ? parseFloat(params.size)
505
+ : Math.abs(parseFloat(position.size)),
506
+ filledSize: 0,
507
+ isPartiallyFilled: false,
508
+ };
509
+ // Track partially filled event if applicable
510
+ if (result?.success && metrics.isPartiallyFilled) {
511
+ const partialProperties = this.buildCloseEventProperties(position, params, metrics, result, eventNames_1.PerpsEventValues.STATUS.PARTIALLY_FILLED);
512
+ this.deps.metrics.trackPerpsEvent(types_1.PerpsAnalyticsEvent.PositionCloseTransaction, {
513
+ ...partialProperties,
514
+ [eventNames_1.PerpsEventProperties.AMOUNT_FILLED]: metrics.filledSize,
515
+ [eventNames_1.PerpsEventProperties.REMAINING_AMOUNT]: metrics.requestedSize - metrics.filledSize,
516
+ [eventNames_1.PerpsEventProperties.COMPLETION_DURATION]: duration,
517
+ });
518
+ }
519
+ // Determine status
520
+ const status = result?.success === true
521
+ ? eventNames_1.PerpsEventValues.STATUS.EXECUTED
522
+ : eventNames_1.PerpsEventValues.STATUS.FAILED;
523
+ const errorMessage = error?.message || result?.error;
524
+ // Track main close event
525
+ const eventProperties = this.buildCloseEventProperties(position, params, metrics, result, status, errorMessage);
526
+ this.deps.metrics.trackPerpsEvent(types_1.PerpsAnalyticsEvent.PositionCloseTransaction, {
527
+ ...eventProperties,
528
+ [eventNames_1.PerpsEventProperties.COMPLETION_DURATION]: duration,
529
+ });
530
+ }
531
+ /**
532
+ * Handle data lake reporting (fire-and-forget).
533
+ *
534
+ * @param reportOrderToDataLake - Data lake reporting function
535
+ * @param symbol - Asset symbol
536
+ * @param context - Service context
537
+ */
538
+ handleDataLakeReporting(reportOrderToDataLake, symbol, context) {
539
+ reportOrderToDataLake({
540
+ action: 'close',
541
+ symbol,
542
+ }).catch((caughtError) => {
543
+ const errorObj = caughtError instanceof Error
544
+ ? caughtError
545
+ : new Error(String(caughtError));
546
+ this.deps.logger.error(errorObj, {
547
+ tags: {
548
+ feature: 'perps',
549
+ provider: context.tracingContext.provider,
550
+ network: context.tracingContext.isTestnet ? 'testnet' : 'mainnet',
551
+ },
552
+ context: {
553
+ name: context.errorContext.controller,
554
+ data: {
555
+ method: context.errorContext.method,
556
+ operation: 'reportOrderToDataLake',
557
+ symbol,
558
+ },
559
+ },
560
+ });
561
+ });
562
+ }
563
+ /**
564
+ * Calculate fee discount with performance measurement.
565
+ * Uses controller dependencies injected via setControllerDependencies().
566
+ * Helper method for placeOrder orchestration.
567
+ *
568
+ * @returns Fee discount in basis points or undefined
569
+ */
570
+ async calculateFeeDiscountWithMeasurement() {
571
+ // Check if controller dependencies are available
572
+ if (!this.controllerDeps) {
573
+ this.deps.debugLogger.log('TradingService: Controller dependencies not set, skipping fee discount');
574
+ return undefined;
575
+ }
576
+ const { controllers, rewardsIntegrationService } = this.controllerDeps;
577
+ const orderExecutionFeeDiscountStartTime = this.deps.performance.now();
578
+ // Calculate fee discount using injected controllers
579
+ const discountBips = await rewardsIntegrationService.calculateUserFeeDiscount({
580
+ controllers,
581
+ });
582
+ const orderExecutionFeeDiscountDuration = this.deps.performance.now() - orderExecutionFeeDiscountStartTime;
583
+ // Record measurement
584
+ this.deps.tracer.setMeasurement(performanceMetrics_1.PerpsMeasurementName.PerpsRewardsOrderExecutionFeeDiscountApiCall, orderExecutionFeeDiscountDuration, 'millisecond');
585
+ this.deps.debugLogger.log('TradingService: Fee discount API call completed', {
586
+ discountBips,
587
+ duration: `${orderExecutionFeeDiscountDuration.toFixed(0)}ms`,
588
+ });
589
+ return discountBips;
590
+ }
591
+ /**
592
+ * Edit an existing order with full orchestration.
593
+ * Handles tracing, fee discounts, state management, and analytics.
594
+ *
595
+ * @param options - Options for editing order
596
+ * @param options.provider
597
+ * @param options.params
598
+ * @param options.context
599
+ * @returns Order result
600
+ */
601
+ async editOrder(options) {
602
+ const { provider, params, context } = options;
603
+ const traceId = (0, uuid_1.v4)();
604
+ const startTime = this.deps.performance.now();
605
+ let traceData;
606
+ try {
607
+ this.deps.tracer.trace({
608
+ name: types_1.PerpsTraceNames.EditOrder,
609
+ id: traceId,
610
+ op: types_1.PerpsTraceOperations.OrderSubmission,
611
+ tags: {
612
+ provider: context.tracingContext.provider,
613
+ orderType: params.newOrder.orderType,
614
+ market: params.newOrder.symbol,
615
+ leverage: String(params.newOrder.leverage || 1),
616
+ isTestnet: String(context.tracingContext.isTestnet),
617
+ },
618
+ data: {
619
+ isBuy: params.newOrder.isBuy,
620
+ orderPrice: params.newOrder.price || '',
621
+ },
622
+ });
623
+ // Calculate fee discount only if required dependencies are available
624
+ const feeDiscountBips = await this.calculateFeeDiscountWithMeasurement();
625
+ // Execute order edit with fee discount management
626
+ const result = await this.withFeeDiscount({
627
+ provider,
628
+ feeDiscountBips,
629
+ operation: () => provider.editOrder(params),
630
+ });
631
+ const completionDuration = this.deps.performance.now() - startTime;
632
+ if (result.success) {
633
+ // Update state on success
634
+ if (context.stateManager) {
635
+ context.stateManager.update((state) => {
636
+ state.lastUpdateTimestamp = Date.now();
637
+ });
638
+ }
639
+ // Track order edit executed
640
+ const editExecutedProps = {
641
+ [eventNames_1.PerpsEventProperties.STATUS]: eventNames_1.PerpsEventValues.STATUS.EXECUTED,
642
+ [eventNames_1.PerpsEventProperties.ASSET]: params.newOrder.symbol,
643
+ [eventNames_1.PerpsEventProperties.DIRECTION]: params.newOrder.isBuy
644
+ ? eventNames_1.PerpsEventValues.DIRECTION.LONG
645
+ : eventNames_1.PerpsEventValues.DIRECTION.SHORT,
646
+ [eventNames_1.PerpsEventProperties.ORDER_TYPE]: params.newOrder.orderType,
647
+ [eventNames_1.PerpsEventProperties.LEVERAGE]: params.newOrder.leverage || 1,
648
+ [eventNames_1.PerpsEventProperties.ORDER_SIZE]: params.newOrder.size,
649
+ [eventNames_1.PerpsEventProperties.COMPLETION_DURATION]: completionDuration,
650
+ };
651
+ if (params.newOrder.price) {
652
+ editExecutedProps[eventNames_1.PerpsEventProperties.LIMIT_PRICE] = parseFloat(params.newOrder.price);
653
+ }
654
+ this.deps.metrics.trackPerpsEvent(types_1.PerpsAnalyticsEvent.TradeTransaction, editExecutedProps);
655
+ traceData = { success: true, orderId: result.orderId || '' };
656
+ }
657
+ else {
658
+ // Track order edit failed
659
+ this.deps.metrics.trackPerpsEvent(types_1.PerpsAnalyticsEvent.TradeTransaction, {
660
+ [eventNames_1.PerpsEventProperties.STATUS]: eventNames_1.PerpsEventValues.STATUS.FAILED,
661
+ [eventNames_1.PerpsEventProperties.ASSET]: params.newOrder.symbol,
662
+ [eventNames_1.PerpsEventProperties.DIRECTION]: params.newOrder.isBuy
663
+ ? eventNames_1.PerpsEventValues.DIRECTION.LONG
664
+ : eventNames_1.PerpsEventValues.DIRECTION.SHORT,
665
+ [eventNames_1.PerpsEventProperties.ORDER_TYPE]: params.newOrder.orderType,
666
+ [eventNames_1.PerpsEventProperties.LEVERAGE]: params.newOrder.leverage || 1,
667
+ [eventNames_1.PerpsEventProperties.ORDER_SIZE]: params.newOrder.size,
668
+ [eventNames_1.PerpsEventProperties.COMPLETION_DURATION]: completionDuration,
669
+ [eventNames_1.PerpsEventProperties.ERROR_MESSAGE]: result.error || 'Unknown error',
670
+ });
671
+ traceData = { success: false, error: result.error || 'Unknown error' };
672
+ }
673
+ return result;
674
+ }
675
+ catch (err) {
676
+ const completionDuration = this.deps.performance.now() - startTime;
677
+ const error = err instanceof Error ? err : new Error(String(err));
678
+ // Track order edit exception
679
+ this.deps.metrics.trackPerpsEvent(types_1.PerpsAnalyticsEvent.TradeTransaction, {
680
+ [eventNames_1.PerpsEventProperties.STATUS]: eventNames_1.PerpsEventValues.STATUS.FAILED,
681
+ [eventNames_1.PerpsEventProperties.ASSET]: params.newOrder.symbol,
682
+ [eventNames_1.PerpsEventProperties.DIRECTION]: params.newOrder.isBuy
683
+ ? eventNames_1.PerpsEventValues.DIRECTION.LONG
684
+ : eventNames_1.PerpsEventValues.DIRECTION.SHORT,
685
+ [eventNames_1.PerpsEventProperties.ORDER_TYPE]: params.newOrder.orderType,
686
+ [eventNames_1.PerpsEventProperties.LEVERAGE]: params.newOrder.leverage || 1,
687
+ [eventNames_1.PerpsEventProperties.ORDER_SIZE]: params.newOrder.size,
688
+ [eventNames_1.PerpsEventProperties.COMPLETION_DURATION]: completionDuration,
689
+ [eventNames_1.PerpsEventProperties.ERROR_MESSAGE]: error.message,
690
+ });
691
+ this.deps.logger.error(error, {
692
+ tags: {
693
+ feature: 'perps',
694
+ provider: context.tracingContext.provider,
695
+ network: context.tracingContext.isTestnet ? 'testnet' : 'mainnet',
696
+ },
697
+ context: {
698
+ name: context.errorContext.controller,
699
+ data: {
700
+ method: context.errorContext.method,
701
+ orderId: params.orderId,
702
+ },
703
+ },
704
+ });
705
+ traceData = {
706
+ success: false,
707
+ error: error.message,
708
+ };
709
+ throw err;
710
+ }
711
+ finally {
712
+ this.deps.tracer.endTrace({
713
+ name: types_1.PerpsTraceNames.EditOrder,
714
+ id: traceId,
715
+ data: traceData,
716
+ });
717
+ }
718
+ }
719
+ /**
720
+ * Cancel a single order with full orchestration.
721
+ * Handles tracing, state management, and analytics.
722
+ *
723
+ * @param options - Options for canceling order
724
+ * @param options.provider
725
+ * @param options.params
726
+ * @param options.context
727
+ * @returns Cancel order result
728
+ */
729
+ async cancelOrder(options) {
730
+ const { provider, params, context } = options;
731
+ const traceId = (0, uuid_1.v4)();
732
+ const startTime = this.deps.performance.now();
733
+ let traceData;
734
+ try {
735
+ // Start trace for the entire operation
736
+ this.deps.tracer.trace({
737
+ name: types_1.PerpsTraceNames.CancelOrder,
738
+ id: traceId,
739
+ op: types_1.PerpsTraceOperations.OrderSubmission,
740
+ tags: {
741
+ provider: context.tracingContext.provider,
742
+ market: params.symbol,
743
+ isTestnet: String(context.tracingContext.isTestnet),
744
+ },
745
+ data: {
746
+ orderId: params.orderId,
747
+ },
748
+ });
749
+ // Execute order cancellation
750
+ const result = await provider.cancelOrder(params);
751
+ const completionDuration = this.deps.performance.now() - startTime;
752
+ if (result.success) {
753
+ // Update state on success
754
+ if (context.stateManager) {
755
+ context.stateManager.update((state) => {
756
+ state.lastUpdateTimestamp = Date.now();
757
+ });
758
+ }
759
+ // Track order cancel executed
760
+ this.deps.metrics.trackPerpsEvent(types_1.PerpsAnalyticsEvent.OrderCancelTransaction, {
761
+ [eventNames_1.PerpsEventProperties.STATUS]: eventNames_1.PerpsEventValues.STATUS.EXECUTED,
762
+ [eventNames_1.PerpsEventProperties.ASSET]: params.symbol,
763
+ [eventNames_1.PerpsEventProperties.COMPLETION_DURATION]: completionDuration,
764
+ });
765
+ traceData = { success: true, orderId: params.orderId };
766
+ }
767
+ else {
768
+ // Track order cancel failed
769
+ this.deps.metrics.trackPerpsEvent(types_1.PerpsAnalyticsEvent.OrderCancelTransaction, {
770
+ [eventNames_1.PerpsEventProperties.STATUS]: eventNames_1.PerpsEventValues.STATUS.FAILED,
771
+ [eventNames_1.PerpsEventProperties.ASSET]: params.symbol,
772
+ [eventNames_1.PerpsEventProperties.COMPLETION_DURATION]: completionDuration,
773
+ [eventNames_1.PerpsEventProperties.ERROR_MESSAGE]: result.error || 'Unknown error',
774
+ });
775
+ traceData = { success: false, error: result.error || 'Unknown error' };
776
+ }
777
+ return result;
778
+ }
779
+ catch (err) {
780
+ const completionDuration = this.deps.performance.now() - startTime;
781
+ const error = err instanceof Error ? err : new Error(String(err));
782
+ // Track order cancel exception
783
+ this.deps.metrics.trackPerpsEvent(types_1.PerpsAnalyticsEvent.OrderCancelTransaction, {
784
+ [eventNames_1.PerpsEventProperties.STATUS]: eventNames_1.PerpsEventValues.STATUS.FAILED,
785
+ [eventNames_1.PerpsEventProperties.ASSET]: params.symbol,
786
+ [eventNames_1.PerpsEventProperties.COMPLETION_DURATION]: completionDuration,
787
+ [eventNames_1.PerpsEventProperties.ERROR_MESSAGE]: error.message,
788
+ });
789
+ this.deps.logger.error(error, this.getErrorContext('cancelOrder', { symbol: params.symbol }));
790
+ traceData = {
791
+ success: false,
792
+ error: error.message,
793
+ };
794
+ throw err;
795
+ }
796
+ finally {
797
+ this.deps.tracer.endTrace({
798
+ name: types_1.PerpsTraceNames.CancelOrder,
799
+ id: traceId,
800
+ data: traceData,
801
+ });
802
+ }
803
+ }
804
+ /**
805
+ * Cancel multiple orders with full orchestration.
806
+ * Handles tracing, stream pausing, filtering, batch operations, and analytics.
807
+ *
808
+ * @param options - Options for canceling multiple orders
809
+ * @param options.provider
810
+ * @param options.params
811
+ * @param options.context
812
+ * @param options.withStreamPause
813
+ * @returns Cancel orders result
814
+ */
815
+ async cancelOrders(options) {
816
+ const { provider, params, context, withStreamPause } = options;
817
+ const traceId = (0, uuid_1.v4)();
818
+ const startTime = this.deps.performance.now();
819
+ let operationResult = null;
820
+ let operationError = null;
821
+ try {
822
+ // Start trace for batch operation
823
+ this.deps.tracer.trace({
824
+ name: types_1.PerpsTraceNames.CancelOrder,
825
+ id: traceId,
826
+ op: types_1.PerpsTraceOperations.OrderSubmission,
827
+ tags: {
828
+ provider: context.tracingContext.provider,
829
+ isBatch: 'true',
830
+ isTestnet: String(context.tracingContext.isTestnet),
831
+ },
832
+ data: {
833
+ cancelAll: params.cancelAll ? 'true' : 'false',
834
+ symbolCount: params.symbols?.length || 0,
835
+ orderIdCount: params.orderIds?.length || 0,
836
+ },
837
+ });
838
+ // Pause orders stream to prevent WebSocket updates during cancellation
839
+ operationResult = await withStreamPause(async () => {
840
+ // Get all open orders
841
+ if (!context.getOpenOrders) {
842
+ throw new Error('getOpenOrders callback not provided in context');
843
+ }
844
+ const orders = await context.getOpenOrders();
845
+ // Filter orders based on params
846
+ let ordersToCancel = orders;
847
+ if (params.cancelAll || (!params.symbols && !params.orderIds)) {
848
+ // Cancel all orders (excluding TP/SL orders for positions)
849
+ ordersToCancel = orders.filter((order) => !(0, orderTypes_1.isTPSLOrder)(order.detailedOrderType));
850
+ }
851
+ else if (params.orderIds && params.orderIds.length > 0) {
852
+ // Cancel specific order IDs
853
+ ordersToCancel = orders.filter((order) => params.orderIds?.includes(order.orderId));
854
+ }
855
+ else if (params.symbols && params.symbols.length > 0) {
856
+ // Cancel orders for specific symbols
857
+ ordersToCancel = orders.filter((order) => params.symbols?.includes(order.symbol));
858
+ }
859
+ if (ordersToCancel.length === 0) {
860
+ return {
861
+ success: false,
862
+ successCount: 0,
863
+ failureCount: 0,
864
+ results: [],
865
+ };
866
+ }
867
+ // Use batch cancel if provider supports it
868
+ if (provider.cancelOrders) {
869
+ return await provider.cancelOrders(ordersToCancel.map((order) => ({
870
+ symbol: order.symbol,
871
+ orderId: order.orderId,
872
+ })));
873
+ }
874
+ // Fallback: Cancel orders in parallel (for providers without batch support)
875
+ const results = await Promise.allSettled(ordersToCancel.map((order) => this.cancelOrder({
876
+ provider,
877
+ params: { symbol: order.symbol, orderId: order.orderId },
878
+ context,
879
+ })));
880
+ // Aggregate results
881
+ const successCount = results.filter((resItem) => resItem.status === 'fulfilled' && resItem.value.success).length;
882
+ const failureCount = results.length - successCount;
883
+ return {
884
+ success: successCount > 0,
885
+ successCount,
886
+ failureCount,
887
+ results: results.map((resItem, index) => {
888
+ let errorMsg;
889
+ if (resItem.status === 'rejected') {
890
+ errorMsg =
891
+ resItem.reason instanceof Error
892
+ ? resItem.reason.message
893
+ : 'Unknown error';
894
+ }
895
+ else if (resItem.status === 'fulfilled' &&
896
+ !resItem.value.success) {
897
+ errorMsg = resItem.value.error;
898
+ }
899
+ return {
900
+ orderId: ordersToCancel[index].orderId,
901
+ symbol: ordersToCancel[index].symbol,
902
+ success: Boolean(resItem.status === 'fulfilled' && resItem.value.success),
903
+ error: errorMsg,
904
+ };
905
+ }),
906
+ };
907
+ }, ['orders']); // Disconnect orders stream during operation
908
+ return operationResult;
909
+ }
910
+ catch (err) {
911
+ operationError = err instanceof Error ? err : new Error(String(err));
912
+ this.deps.logger.error(operationError, this.getErrorContext('cancelOrders'));
913
+ throw err;
914
+ }
915
+ finally {
916
+ const completionDuration = this.deps.performance.now() - startTime;
917
+ // Track batch cancel event (success or failure)
918
+ const batchCancelProps = {
919
+ [eventNames_1.PerpsEventProperties.STATUS]: operationResult?.success && operationResult.successCount > 0
920
+ ? eventNames_1.PerpsEventValues.STATUS.EXECUTED
921
+ : eventNames_1.PerpsEventValues.STATUS.FAILED,
922
+ [eventNames_1.PerpsEventProperties.COMPLETION_DURATION]: completionDuration,
923
+ };
924
+ if (operationError) {
925
+ batchCancelProps[eventNames_1.PerpsEventProperties.ERROR_MESSAGE] =
926
+ operationError.message;
927
+ }
928
+ this.deps.metrics.trackPerpsEvent(types_1.PerpsAnalyticsEvent.OrderCancelTransaction, batchCancelProps);
929
+ this.deps.tracer.endTrace({
930
+ name: types_1.PerpsTraceNames.CancelOrder,
931
+ id: traceId,
932
+ });
933
+ }
934
+ }
935
+ /**
936
+ * Close a single position with full orchestration.
937
+ * Handles tracing, fee discounts, state management, analytics, and data lake reporting.
938
+ *
939
+ * @param options - Options for closing position
940
+ * @param options.provider
941
+ * @param options.params
942
+ * @param options.context
943
+ * @param options.reportOrderToDataLake
944
+ * @returns Order result
945
+ */
946
+ async closePosition(options) {
947
+ const { provider, params, context, reportOrderToDataLake } = options;
948
+ const traceId = (0, uuid_1.v4)();
949
+ const startTime = this.deps.performance.now();
950
+ let position;
951
+ let result;
952
+ let traceData;
953
+ try {
954
+ this.deps.tracer.trace({
955
+ name: types_1.PerpsTraceNames.ClosePosition,
956
+ id: traceId,
957
+ op: types_1.PerpsTraceOperations.PositionManagement,
958
+ tags: {
959
+ provider: context.tracingContext.provider,
960
+ symbol: params.symbol,
961
+ closeSize: params.size || 'full',
962
+ isTestnet: String(context.tracingContext.isTestnet),
963
+ },
964
+ });
965
+ // Load position data with measurement
966
+ position = await this.loadPositionData({
967
+ symbol: params.symbol,
968
+ context,
969
+ });
970
+ // Calculate fee discount with measurement
971
+ const feeDiscountBips = await this.calculateFeeDiscountWithMeasurement();
972
+ // Execute position close with fee discount management
973
+ result = await this.withFeeDiscount({
974
+ provider,
975
+ feeDiscountBips,
976
+ operation: () => provider.closePosition(params),
977
+ });
978
+ const completionDuration = this.deps.performance.now() - startTime;
979
+ if (result.success) {
980
+ // Update state on success
981
+ if (context.stateManager) {
982
+ context.stateManager.update((state) => {
983
+ state.lastUpdateTimestamp = Date.now();
984
+ });
985
+ }
986
+ // Report to data lake (fire-and-forget)
987
+ this.handleDataLakeReporting(reportOrderToDataLake, params.symbol, context);
988
+ traceData = { success: true, filledSize: result.filledSize || '' };
989
+ }
990
+ else {
991
+ traceData = { success: false, error: result.error || 'Unknown error' };
992
+ }
993
+ // Track analytics (success or failure, includes partial fills)
994
+ this.trackPositionCloseResult({
995
+ position,
996
+ result,
997
+ params,
998
+ context,
999
+ duration: completionDuration,
1000
+ });
1001
+ return result;
1002
+ }
1003
+ catch (err) {
1004
+ const completionDuration = this.deps.performance.now() - startTime;
1005
+ const error = err instanceof Error ? err : new Error(String(err));
1006
+ traceData = {
1007
+ success: false,
1008
+ error: error.message,
1009
+ };
1010
+ // Track analytics for exception
1011
+ this.trackPositionCloseResult({
1012
+ position,
1013
+ result: null,
1014
+ error,
1015
+ params,
1016
+ context,
1017
+ duration: completionDuration,
1018
+ });
1019
+ this.deps.logger.error(error, {
1020
+ tags: {
1021
+ feature: 'perps',
1022
+ provider: context.tracingContext.provider,
1023
+ network: context.tracingContext.isTestnet ? 'testnet' : 'mainnet',
1024
+ },
1025
+ context: {
1026
+ name: context.errorContext.controller,
1027
+ data: {
1028
+ method: context.errorContext.method,
1029
+ symbol: params.symbol,
1030
+ },
1031
+ },
1032
+ });
1033
+ throw err;
1034
+ }
1035
+ finally {
1036
+ // Always end trace on exit (success or failure)
1037
+ this.deps.tracer.endTrace({
1038
+ name: types_1.PerpsTraceNames.ClosePosition,
1039
+ id: traceId,
1040
+ data: traceData,
1041
+ });
1042
+ }
1043
+ }
1044
+ /**
1045
+ * Close multiple positions with full orchestration.
1046
+ * Handles tracing, fee discounts, batch operations, and analytics.
1047
+ *
1048
+ * @param options - Options for closing multiple positions
1049
+ * @param options.provider
1050
+ * @param options.params
1051
+ * @param options.context
1052
+ * @returns Close positions result
1053
+ */
1054
+ async closePositions(options) {
1055
+ const { provider, params, context } = options;
1056
+ const traceId = (0, uuid_1.v4)();
1057
+ const startTime = this.deps.performance.now();
1058
+ let operationResult = null;
1059
+ let operationError = null;
1060
+ try {
1061
+ // Start trace for batch operation
1062
+ this.deps.tracer.trace({
1063
+ name: types_1.PerpsTraceNames.ClosePosition,
1064
+ id: traceId,
1065
+ op: types_1.PerpsTraceOperations.PositionManagement,
1066
+ tags: {
1067
+ provider: context.tracingContext.provider,
1068
+ isBatch: 'true',
1069
+ isTestnet: String(context.tracingContext.isTestnet),
1070
+ },
1071
+ data: {
1072
+ closeAll: params.closeAll ? 'true' : 'false',
1073
+ symbolCount: params.symbols?.length || 0,
1074
+ },
1075
+ });
1076
+ this.deps.debugLogger.log('[closePositions] Batch method check', {
1077
+ providerType: provider.protocolId,
1078
+ hasBatchMethod: Boolean(provider.closePositions),
1079
+ methodType: typeof provider.closePositions,
1080
+ providerKeys: Object.keys(provider).filter((key) => key.includes('close')),
1081
+ });
1082
+ // Use batch close if provider supports it (provider handles filtering)
1083
+ if (provider.closePositions) {
1084
+ const feeDiscountBips = await this.calculateFeeDiscountWithMeasurement();
1085
+ operationResult = await this.withFeeDiscount({
1086
+ provider,
1087
+ feeDiscountBips,
1088
+ operation: async () => {
1089
+ if (!provider.closePositions) {
1090
+ throw new Error('closePositions method not available');
1091
+ }
1092
+ return provider.closePositions(params);
1093
+ },
1094
+ });
1095
+ }
1096
+ else {
1097
+ // Fallback: Get positions, filter, and close in parallel
1098
+ if (!context.getPositions) {
1099
+ throw new Error('getPositions callback not provided in context');
1100
+ }
1101
+ const positions = await context.getPositions();
1102
+ const positionsToClose = params.closeAll || !params.symbols || params.symbols.length === 0
1103
+ ? positions
1104
+ : positions.filter((pos) => params.symbols?.includes(pos.symbol));
1105
+ if (positionsToClose.length === 0) {
1106
+ operationResult = {
1107
+ success: false,
1108
+ successCount: 0,
1109
+ failureCount: 0,
1110
+ results: [],
1111
+ };
1112
+ return operationResult;
1113
+ }
1114
+ const results = await Promise.allSettled(positionsToClose.map((pos) => this.closePosition({
1115
+ provider,
1116
+ params: { symbol: pos.symbol },
1117
+ context,
1118
+ reportOrderToDataLake: () => Promise.resolve({ success: true }), // No-op for batch fallback
1119
+ })));
1120
+ // Aggregate results
1121
+ const successCount = results.filter((resItem) => resItem.status === 'fulfilled' && resItem.value.success).length;
1122
+ const failureCount = results.length - successCount;
1123
+ operationResult = {
1124
+ success: successCount > 0,
1125
+ successCount,
1126
+ failureCount,
1127
+ results: results.map((resItem, index) => {
1128
+ let errorMsg;
1129
+ if (resItem.status === 'rejected') {
1130
+ errorMsg =
1131
+ resItem.reason instanceof Error
1132
+ ? resItem.reason.message
1133
+ : 'Unknown error';
1134
+ }
1135
+ else if (resItem.status === 'fulfilled' &&
1136
+ !resItem.value.success) {
1137
+ errorMsg = resItem.value.error;
1138
+ }
1139
+ return {
1140
+ symbol: positionsToClose[index].symbol,
1141
+ success: Boolean(resItem.status === 'fulfilled' && resItem.value.success),
1142
+ error: errorMsg,
1143
+ };
1144
+ }),
1145
+ };
1146
+ }
1147
+ return operationResult;
1148
+ }
1149
+ catch (err) {
1150
+ operationError = err instanceof Error ? err : new Error(String(err));
1151
+ this.deps.logger.error(operationError, this.getErrorContext('closePositions', {
1152
+ symbols: params.symbols?.length || 0,
1153
+ closeAll: params.closeAll,
1154
+ }));
1155
+ throw err;
1156
+ }
1157
+ finally {
1158
+ const completionDuration = this.deps.performance.now() - startTime;
1159
+ // Track batch close event (success or failure)
1160
+ const batchCloseProps = {
1161
+ [eventNames_1.PerpsEventProperties.STATUS]: operationResult?.success && operationResult.successCount > 0
1162
+ ? eventNames_1.PerpsEventValues.STATUS.EXECUTED
1163
+ : eventNames_1.PerpsEventValues.STATUS.FAILED,
1164
+ [eventNames_1.PerpsEventProperties.COMPLETION_DURATION]: completionDuration,
1165
+ };
1166
+ if (operationError) {
1167
+ batchCloseProps[eventNames_1.PerpsEventProperties.ERROR_MESSAGE] =
1168
+ operationError.message;
1169
+ }
1170
+ this.deps.metrics.trackPerpsEvent(types_1.PerpsAnalyticsEvent.PositionCloseTransaction, batchCloseProps);
1171
+ this.deps.tracer.endTrace({
1172
+ name: types_1.PerpsTraceNames.ClosePosition,
1173
+ id: traceId,
1174
+ });
1175
+ }
1176
+ }
1177
+ /**
1178
+ * Update TP/SL for an existing position with full orchestration.
1179
+ * Handles tracing, fee discounts, state management, and analytics.
1180
+ *
1181
+ * @param options - Options for updating TP/SL
1182
+ * @param options.provider
1183
+ * @param options.params
1184
+ * @param options.context
1185
+ * @returns Order result
1186
+ */
1187
+ async updatePositionTPSL(options) {
1188
+ const { provider, params, context } = options;
1189
+ const traceId = (0, uuid_1.v4)();
1190
+ const startTime = this.deps.performance.now();
1191
+ let traceData;
1192
+ let result;
1193
+ let errorMessage;
1194
+ // Extract tracking data with defaults
1195
+ const direction = params.trackingData?.direction;
1196
+ const positionSize = params.trackingData?.positionSize;
1197
+ const source = params.trackingData?.source || eventNames_1.PerpsEventValues.SOURCE.TP_SL_VIEW;
1198
+ const takeProfitPercentage = params.trackingData?.takeProfitPercentage;
1199
+ const stopLossPercentage = params.trackingData?.stopLossPercentage;
1200
+ const isEditingExistingPosition = params.trackingData?.isEditingExistingPosition ?? false;
1201
+ try {
1202
+ this.deps.tracer.trace({
1203
+ name: types_1.PerpsTraceNames.UpdateTpsl,
1204
+ id: traceId,
1205
+ op: types_1.PerpsTraceOperations.PositionManagement,
1206
+ tags: {
1207
+ provider: context.tracingContext.provider,
1208
+ market: params.symbol,
1209
+ isTestnet: String(context.tracingContext.isTestnet),
1210
+ },
1211
+ data: {
1212
+ takeProfitPrice: params.takeProfitPrice || '',
1213
+ stopLossPrice: params.stopLossPrice || '',
1214
+ },
1215
+ });
1216
+ // Get fee discount from rewards
1217
+ const feeDiscountBips = await this.calculateFeeDiscountWithMeasurement();
1218
+ // Execute with fee discount management
1219
+ result = await this.withFeeDiscount({
1220
+ provider,
1221
+ feeDiscountBips,
1222
+ operation: () => provider.updatePositionTPSL(params),
1223
+ });
1224
+ if (result.success) {
1225
+ // Update state on success
1226
+ if (context.stateManager) {
1227
+ context.stateManager.update((state) => {
1228
+ state.lastUpdateTimestamp = Date.now();
1229
+ });
1230
+ }
1231
+ traceData = { success: true };
1232
+ }
1233
+ else {
1234
+ errorMessage = result.error || 'Unknown error';
1235
+ traceData = { success: false, error: errorMessage };
1236
+ }
1237
+ return result;
1238
+ }
1239
+ catch (err) {
1240
+ errorMessage = err instanceof Error ? err.message : 'Unknown error';
1241
+ traceData = { success: false, error: errorMessage };
1242
+ throw err;
1243
+ }
1244
+ finally {
1245
+ const completionDuration = this.deps.performance.now() - startTime;
1246
+ // Determine screen type based on whether editing existing position
1247
+ const screenType = isEditingExistingPosition
1248
+ ? eventNames_1.PerpsEventValues.SCREEN_TYPE.EDIT_TPSL
1249
+ : eventNames_1.PerpsEventValues.SCREEN_TYPE.CREATE_TPSL;
1250
+ // Determine if TP/SL are set
1251
+ const hasTakeProfit = Boolean(params.takeProfitPrice);
1252
+ const hasStopLoss = Boolean(params.stopLossPrice);
1253
+ // Build comprehensive event properties
1254
+ const eventProperties = {
1255
+ [eventNames_1.PerpsEventProperties.STATUS]: result?.success
1256
+ ? eventNames_1.PerpsEventValues.STATUS.EXECUTED
1257
+ : eventNames_1.PerpsEventValues.STATUS.FAILED,
1258
+ [eventNames_1.PerpsEventProperties.ASSET]: params.symbol,
1259
+ [eventNames_1.PerpsEventProperties.COMPLETION_DURATION]: completionDuration,
1260
+ [eventNames_1.PerpsEventProperties.SOURCE]: source,
1261
+ [eventNames_1.PerpsEventProperties.SCREEN_TYPE]: screenType,
1262
+ [eventNames_1.PerpsEventProperties.HAS_TAKE_PROFIT]: hasTakeProfit,
1263
+ [eventNames_1.PerpsEventProperties.HAS_STOP_LOSS]: hasStopLoss,
1264
+ ...(direction && {
1265
+ [eventNames_1.PerpsEventProperties.DIRECTION]: direction === 'long'
1266
+ ? eventNames_1.PerpsEventValues.DIRECTION.LONG
1267
+ : eventNames_1.PerpsEventValues.DIRECTION.SHORT,
1268
+ }),
1269
+ ...(positionSize !== undefined && {
1270
+ [eventNames_1.PerpsEventProperties.POSITION_SIZE]: positionSize,
1271
+ }),
1272
+ ...(params.takeProfitPrice && {
1273
+ [eventNames_1.PerpsEventProperties.TAKE_PROFIT_PRICE]: parseFloat(params.takeProfitPrice),
1274
+ }),
1275
+ ...(params.stopLossPrice && {
1276
+ [eventNames_1.PerpsEventProperties.STOP_LOSS_PRICE]: parseFloat(params.stopLossPrice),
1277
+ }),
1278
+ ...(takeProfitPercentage !== undefined && {
1279
+ [eventNames_1.PerpsEventProperties.TAKE_PROFIT_PERCENTAGE]: takeProfitPercentage,
1280
+ }),
1281
+ ...(stopLossPercentage !== undefined && {
1282
+ [eventNames_1.PerpsEventProperties.STOP_LOSS_PERCENTAGE]: stopLossPercentage,
1283
+ }),
1284
+ ...(errorMessage && {
1285
+ [eventNames_1.PerpsEventProperties.ERROR_MESSAGE]: errorMessage,
1286
+ }),
1287
+ };
1288
+ // Track event once with all properties
1289
+ this.deps.metrics.trackPerpsEvent(types_1.PerpsAnalyticsEvent.RiskManagement, eventProperties);
1290
+ this.deps.tracer.endTrace({
1291
+ name: types_1.PerpsTraceNames.UpdateTpsl,
1292
+ id: traceId,
1293
+ data: traceData,
1294
+ });
1295
+ }
1296
+ }
1297
+ /**
1298
+ * Update margin for an existing position (add or remove).
1299
+ *
1300
+ * @param options - Options for updating margin
1301
+ * @param options.provider
1302
+ * @param options.symbol
1303
+ * @param options.amount
1304
+ * @param options.context
1305
+ * @returns Margin update result
1306
+ */
1307
+ async updateMargin(options) {
1308
+ const { provider, symbol, amount, context } = options;
1309
+ const traceId = (0, uuid_1.v4)();
1310
+ const startTime = this.deps.performance.now();
1311
+ try {
1312
+ this.deps.tracer.trace({
1313
+ name: types_1.PerpsTraceNames.UpdateMargin,
1314
+ id: traceId,
1315
+ op: types_1.PerpsTraceOperations.PositionManagement,
1316
+ tags: {
1317
+ provider: context.tracingContext.provider,
1318
+ symbol,
1319
+ isAdd: String(parseFloat(amount) > 0),
1320
+ isTestnet: String(context.tracingContext.isTestnet),
1321
+ },
1322
+ });
1323
+ // Call provider method
1324
+ const result = await provider.updateMargin?.({ symbol, amount });
1325
+ if (!result) {
1326
+ throw new Error('Provider does not support margin adjustment');
1327
+ }
1328
+ const completionDuration = this.deps.performance.now() - startTime;
1329
+ if (result.success) {
1330
+ // Update state on success
1331
+ if (context.stateManager) {
1332
+ context.stateManager.update((state) => {
1333
+ state.lastUpdateTimestamp = Date.now();
1334
+ });
1335
+ }
1336
+ // Track success analytics
1337
+ this.deps.metrics.trackPerpsEvent(types_1.PerpsAnalyticsEvent.RiskManagement, {
1338
+ [eventNames_1.PerpsEventProperties.STATUS]: eventNames_1.PerpsEventValues.STATUS.EXECUTED,
1339
+ [eventNames_1.PerpsEventProperties.ASSET]: symbol,
1340
+ [eventNames_1.PerpsEventProperties.ACTION]: parseFloat(amount) > 0 ? 'add_margin' : 'remove_margin',
1341
+ [eventNames_1.PerpsEventProperties.MARGIN_USED]: Math.abs(parseFloat(amount)),
1342
+ [eventNames_1.PerpsEventProperties.COMPLETION_DURATION]: completionDuration,
1343
+ });
1344
+ }
1345
+ this.deps.tracer.endTrace({
1346
+ name: types_1.PerpsTraceNames.UpdateMargin,
1347
+ id: traceId,
1348
+ data: { success: result.success, error: result.error || '' },
1349
+ });
1350
+ return result;
1351
+ }
1352
+ catch (err) {
1353
+ const completionDuration = this.deps.performance.now() - startTime;
1354
+ const errorMessage = err instanceof Error ? err.message : 'Unknown error';
1355
+ const error = err instanceof Error ? err : new Error(String(err));
1356
+ this.deps.logger.error(error, this.getErrorContext('updateMargin', { symbol, amount }));
1357
+ // Track failure analytics
1358
+ this.deps.metrics.trackPerpsEvent(types_1.PerpsAnalyticsEvent.RiskManagement, {
1359
+ [eventNames_1.PerpsEventProperties.STATUS]: eventNames_1.PerpsEventValues.STATUS.FAILED,
1360
+ [eventNames_1.PerpsEventProperties.ASSET]: symbol,
1361
+ [eventNames_1.PerpsEventProperties.ACTION]: parseFloat(amount) > 0 ? 'add_margin' : 'remove_margin',
1362
+ [eventNames_1.PerpsEventProperties.MARGIN_USED]: Math.abs(parseFloat(amount)),
1363
+ [eventNames_1.PerpsEventProperties.COMPLETION_DURATION]: completionDuration,
1364
+ [eventNames_1.PerpsEventProperties.ERROR_MESSAGE]: errorMessage,
1365
+ });
1366
+ this.deps.tracer.endTrace({
1367
+ name: types_1.PerpsTraceNames.UpdateMargin,
1368
+ id: traceId,
1369
+ data: { success: false, error: errorMessage },
1370
+ });
1371
+ throw err;
1372
+ }
1373
+ }
1374
+ /**
1375
+ * Flip position (reverse direction while keeping size and leverage).
1376
+ *
1377
+ * @param options - Options for flipping position
1378
+ * @param options.provider
1379
+ * @param options.position
1380
+ * @param options.context
1381
+ * @returns Order result
1382
+ */
1383
+ async flipPosition(options) {
1384
+ const { provider, position, context } = options;
1385
+ const traceId = (0, uuid_1.v4)();
1386
+ const startTime = this.deps.performance.now();
1387
+ try {
1388
+ this.deps.tracer.trace({
1389
+ name: types_1.PerpsTraceNames.FlipPosition,
1390
+ id: traceId,
1391
+ op: types_1.PerpsTraceOperations.PositionManagement,
1392
+ tags: {
1393
+ provider: context.tracingContext.provider,
1394
+ symbol: position.symbol,
1395
+ isTestnet: String(context.tracingContext.isTestnet),
1396
+ },
1397
+ });
1398
+ // Calculate flip parameters
1399
+ const positionSize = Math.abs(parseFloat(position.size));
1400
+ const isCurrentlyLong = parseFloat(position.size) > 0;
1401
+ const oppositeDirection = !isCurrentlyLong;
1402
+ // Validate available balance for fees
1403
+ const accountState = await provider.getAccountState?.();
1404
+ if (!accountState) {
1405
+ throw new Error('Failed to get account state');
1406
+ }
1407
+ const availableBalance = parseFloat(accountState.availableBalance);
1408
+ // Estimate fees (close + open, approximately 0.09% of notional)
1409
+ // Flip requires 2x position size (1x to close, 1x to open opposite)
1410
+ const entryPrice = parseFloat(position.entryPrice);
1411
+ const flipSize = positionSize * 2;
1412
+ const notionalValue = flipSize * entryPrice;
1413
+ const estimatedFees = notionalValue * 0.0009;
1414
+ if (estimatedFees > availableBalance) {
1415
+ throw new Error(`Insufficient balance for flip fees. Need $${estimatedFees.toFixed(2)}, have $${availableBalance.toFixed(2)}`);
1416
+ }
1417
+ // Create order params for flip
1418
+ // Use 2x position size: 1x to close current position + 1x to open opposite position
1419
+ const orderParams = {
1420
+ symbol: position.symbol,
1421
+ isBuy: oppositeDirection,
1422
+ size: flipSize.toString(),
1423
+ orderType: 'market',
1424
+ leverage: position.leverage?.value,
1425
+ currentPrice: entryPrice,
1426
+ };
1427
+ // Place flip order (HyperLiquid handles margin transfer automatically)
1428
+ const result = await provider.placeOrder(orderParams);
1429
+ const completionDuration = this.deps.performance.now() - startTime;
1430
+ if (result.success) {
1431
+ // Update state on success
1432
+ if (context.stateManager) {
1433
+ context.stateManager.update((state) => {
1434
+ state.lastUpdateTimestamp = Date.now();
1435
+ });
1436
+ }
1437
+ // Track success analytics
1438
+ this.deps.metrics.trackPerpsEvent(types_1.PerpsAnalyticsEvent.TradeTransaction, {
1439
+ [eventNames_1.PerpsEventProperties.STATUS]: eventNames_1.PerpsEventValues.STATUS.EXECUTED,
1440
+ [eventNames_1.PerpsEventProperties.ASSET]: position.symbol,
1441
+ [eventNames_1.PerpsEventProperties.DIRECTION]: oppositeDirection
1442
+ ? eventNames_1.PerpsEventValues.DIRECTION.LONG
1443
+ : eventNames_1.PerpsEventValues.DIRECTION.SHORT,
1444
+ [eventNames_1.PerpsEventProperties.ORDER_TYPE]: 'market',
1445
+ [eventNames_1.PerpsEventProperties.LEVERAGE]: position.leverage?.value || 1,
1446
+ [eventNames_1.PerpsEventProperties.ORDER_SIZE]: positionSize,
1447
+ [eventNames_1.PerpsEventProperties.COMPLETION_DURATION]: completionDuration,
1448
+ [eventNames_1.PerpsEventProperties.ACTION]: 'flip_position',
1449
+ });
1450
+ }
1451
+ this.deps.tracer.endTrace({
1452
+ name: types_1.PerpsTraceNames.FlipPosition,
1453
+ id: traceId,
1454
+ data: { success: result.success ?? false, error: result.error || '' },
1455
+ });
1456
+ return result;
1457
+ }
1458
+ catch (err) {
1459
+ const completionDuration = this.deps.performance.now() - startTime;
1460
+ const errorMessage = err instanceof Error ? err.message : 'Unknown error';
1461
+ const error = err instanceof Error ? err : new Error(String(err));
1462
+ this.deps.logger.error(error, this.getErrorContext('flipPosition', { symbol: position.symbol }));
1463
+ // Track failure analytics
1464
+ this.deps.metrics.trackPerpsEvent(types_1.PerpsAnalyticsEvent.TradeTransaction, {
1465
+ [eventNames_1.PerpsEventProperties.STATUS]: eventNames_1.PerpsEventValues.STATUS.FAILED,
1466
+ [eventNames_1.PerpsEventProperties.ASSET]: position.symbol,
1467
+ [eventNames_1.PerpsEventProperties.ACTION]: 'flip_position',
1468
+ [eventNames_1.PerpsEventProperties.COMPLETION_DURATION]: completionDuration,
1469
+ [eventNames_1.PerpsEventProperties.ERROR_MESSAGE]: errorMessage,
1470
+ });
1471
+ this.deps.tracer.endTrace({
1472
+ name: types_1.PerpsTraceNames.FlipPosition,
1473
+ id: traceId,
1474
+ data: { success: false, error: errorMessage },
1475
+ });
1476
+ throw err;
1477
+ }
1478
+ }
1479
+ }
1480
+ exports.TradingService = TradingService;
1481
+ //# sourceMappingURL=TradingService.cjs.map