@lifi/perps-sdk-provider-ondo 0.0.0-preview-7ff840c

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 (280) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +38 -0
  3. package/dist/cjs/OndoProvider.d.ts +8 -0
  4. package/dist/cjs/OndoProvider.d.ts.map +1 -0
  5. package/dist/cjs/OndoProvider.js +338 -0
  6. package/dist/cjs/OndoProvider.js.map +1 -0
  7. package/dist/cjs/accountConfig.d.ts +3 -0
  8. package/dist/cjs/accountConfig.d.ts.map +1 -0
  9. package/dist/cjs/accountConfig.js +59 -0
  10. package/dist/cjs/accountConfig.js.map +1 -0
  11. package/dist/cjs/accountSummary.d.ts +3 -0
  12. package/dist/cjs/accountSummary.d.ts.map +1 -0
  13. package/dist/cjs/accountSummary.js +8 -0
  14. package/dist/cjs/accountSummary.js.map +1 -0
  15. package/dist/cjs/auth/OndoTokenStore.d.ts +13 -0
  16. package/dist/cjs/auth/OndoTokenStore.d.ts.map +1 -0
  17. package/dist/cjs/auth/OndoTokenStore.js +53 -0
  18. package/dist/cjs/auth/OndoTokenStore.js.map +1 -0
  19. package/dist/cjs/auth/completeSiweLogin.d.ts +13 -0
  20. package/dist/cjs/auth/completeSiweLogin.d.ts.map +1 -0
  21. package/dist/cjs/auth/completeSiweLogin.js +15 -0
  22. package/dist/cjs/auth/completeSiweLogin.js.map +1 -0
  23. package/dist/cjs/auth/index.d.ts +4 -0
  24. package/dist/cjs/auth/index.d.ts.map +1 -0
  25. package/dist/cjs/auth/index.js +11 -0
  26. package/dist/cjs/auth/index.js.map +1 -0
  27. package/dist/cjs/auth/signActions.d.ts +13 -0
  28. package/dist/cjs/auth/signActions.d.ts.map +1 -0
  29. package/dist/cjs/auth/signActions.js +86 -0
  30. package/dist/cjs/auth/signActions.js.map +1 -0
  31. package/dist/cjs/constants.d.ts +9 -0
  32. package/dist/cjs/constants.d.ts.map +1 -0
  33. package/dist/cjs/constants.js +12 -0
  34. package/dist/cjs/constants.js.map +1 -0
  35. package/dist/cjs/index.d.ts +9 -0
  36. package/dist/cjs/index.d.ts.map +1 -0
  37. package/dist/cjs/index.js +37 -0
  38. package/dist/cjs/index.js.map +1 -0
  39. package/dist/cjs/package.json +1 -0
  40. package/dist/cjs/types/auth.d.ts +16 -0
  41. package/dist/cjs/types/auth.d.ts.map +1 -0
  42. package/dist/cjs/types/auth.js +3 -0
  43. package/dist/cjs/types/auth.js.map +1 -0
  44. package/dist/cjs/types/index.d.ts +4 -0
  45. package/dist/cjs/types/index.d.ts.map +1 -0
  46. package/dist/cjs/types/index.js +3 -0
  47. package/dist/cjs/types/index.js.map +1 -0
  48. package/dist/cjs/types/wire.d.ts +154 -0
  49. package/dist/cjs/types/wire.d.ts.map +1 -0
  50. package/dist/cjs/types/wire.js +3 -0
  51. package/dist/cjs/types/wire.js.map +1 -0
  52. package/dist/cjs/types/ws.d.ts +92 -0
  53. package/dist/cjs/types/ws.d.ts.map +1 -0
  54. package/dist/cjs/types/ws.js +3 -0
  55. package/dist/cjs/types/ws.js.map +1 -0
  56. package/dist/cjs/utils/activityCursor.d.ts +9 -0
  57. package/dist/cjs/utils/activityCursor.d.ts.map +1 -0
  58. package/dist/cjs/utils/activityCursor.js +79 -0
  59. package/dist/cjs/utils/activityCursor.js.map +1 -0
  60. package/dist/cjs/utils/apiClient.d.ts +43 -0
  61. package/dist/cjs/utils/apiClient.d.ts.map +1 -0
  62. package/dist/cjs/utils/apiClient.js +134 -0
  63. package/dist/cjs/utils/apiClient.js.map +1 -0
  64. package/dist/cjs/utils/index.d.ts +11 -0
  65. package/dist/cjs/utils/index.d.ts.map +1 -0
  66. package/dist/cjs/utils/index.js +39 -0
  67. package/dist/cjs/utils/index.js.map +1 -0
  68. package/dist/cjs/utils/liquidation.d.ts +4 -0
  69. package/dist/cjs/utils/liquidation.d.ts.map +1 -0
  70. package/dist/cjs/utils/liquidation.js +16 -0
  71. package/dist/cjs/utils/liquidation.js.map +1 -0
  72. package/dist/cjs/utils/mapActivity.d.ts +5 -0
  73. package/dist/cjs/utils/mapActivity.d.ts.map +1 -0
  74. package/dist/cjs/utils/mapActivity.js +34 -0
  75. package/dist/cjs/utils/mapActivity.js.map +1 -0
  76. package/dist/cjs/utils/mapFill.d.ts +4 -0
  77. package/dist/cjs/utils/mapFill.d.ts.map +1 -0
  78. package/dist/cjs/utils/mapFill.js +36 -0
  79. package/dist/cjs/utils/mapFill.js.map +1 -0
  80. package/dist/cjs/utils/mapOrder.d.ts +16 -0
  81. package/dist/cjs/utils/mapOrder.d.ts.map +1 -0
  82. package/dist/cjs/utils/mapOrder.js +135 -0
  83. package/dist/cjs/utils/mapOrder.js.map +1 -0
  84. package/dist/cjs/utils/mapPosition.d.ts +5 -0
  85. package/dist/cjs/utils/mapPosition.d.ts.map +1 -0
  86. package/dist/cjs/utils/mapPosition.js +26 -0
  87. package/dist/cjs/utils/mapPosition.js.map +1 -0
  88. package/dist/cjs/utils/ohlcvInterval.d.ts +4 -0
  89. package/dist/cjs/utils/ohlcvInterval.d.ts.map +1 -0
  90. package/dist/cjs/utils/ohlcvInterval.js +49 -0
  91. package/dist/cjs/utils/ohlcvInterval.js.map +1 -0
  92. package/dist/cjs/utils/ondoAsset.d.ts +3 -0
  93. package/dist/cjs/utils/ondoAsset.d.ts.map +1 -0
  94. package/dist/cjs/utils/ondoAsset.js +12 -0
  95. package/dist/cjs/utils/ondoAsset.js.map +1 -0
  96. package/dist/cjs/utils/orderFormatting.d.ts +4 -0
  97. package/dist/cjs/utils/orderFormatting.d.ts.map +1 -0
  98. package/dist/cjs/utils/orderFormatting.js +40 -0
  99. package/dist/cjs/utils/orderFormatting.js.map +1 -0
  100. package/dist/cjs/websocket/OndoWsProvider.d.ts +56 -0
  101. package/dist/cjs/websocket/OndoWsProvider.d.ts.map +1 -0
  102. package/dist/cjs/websocket/OndoWsProvider.js +515 -0
  103. package/dist/cjs/websocket/OndoWsProvider.js.map +1 -0
  104. package/dist/esm/OndoProvider.d.ts +39 -0
  105. package/dist/esm/OndoProvider.d.ts.map +1 -0
  106. package/dist/esm/OndoProvider.js +366 -0
  107. package/dist/esm/OndoProvider.js.map +1 -0
  108. package/dist/esm/accountConfig.d.ts +13 -0
  109. package/dist/esm/accountConfig.d.ts.map +1 -0
  110. package/dist/esm/accountConfig.js +77 -0
  111. package/dist/esm/accountConfig.js.map +1 -0
  112. package/dist/esm/accountSummary.d.ts +12 -0
  113. package/dist/esm/accountSummary.d.ts.map +1 -0
  114. package/dist/esm/accountSummary.js +14 -0
  115. package/dist/esm/accountSummary.js.map +1 -0
  116. package/dist/esm/auth/OndoTokenStore.d.ts +20 -0
  117. package/dist/esm/auth/OndoTokenStore.d.ts.map +1 -0
  118. package/dist/esm/auth/OndoTokenStore.js +61 -0
  119. package/dist/esm/auth/OndoTokenStore.js.map +1 -0
  120. package/dist/esm/auth/completeSiweLogin.d.ts +28 -0
  121. package/dist/esm/auth/completeSiweLogin.d.ts.map +1 -0
  122. package/dist/esm/auth/completeSiweLogin.js +21 -0
  123. package/dist/esm/auth/completeSiweLogin.js.map +1 -0
  124. package/dist/esm/auth/index.d.ts +4 -0
  125. package/dist/esm/auth/index.d.ts.map +1 -0
  126. package/dist/esm/auth/index.js +5 -0
  127. package/dist/esm/auth/index.js.map +1 -0
  128. package/dist/esm/auth/signActions.d.ts +35 -0
  129. package/dist/esm/auth/signActions.d.ts.map +1 -0
  130. package/dist/esm/auth/signActions.js +103 -0
  131. package/dist/esm/auth/signActions.js.map +1 -0
  132. package/dist/esm/constants.d.ts +35 -0
  133. package/dist/esm/constants.d.ts.map +1 -0
  134. package/dist/esm/constants.js +35 -0
  135. package/dist/esm/constants.js.map +1 -0
  136. package/dist/esm/index.d.ts +19 -0
  137. package/dist/esm/index.d.ts.map +1 -0
  138. package/dist/esm/index.js +21 -0
  139. package/dist/esm/index.js.map +1 -0
  140. package/dist/esm/package.json +1 -0
  141. package/dist/esm/types/auth.d.ts +32 -0
  142. package/dist/esm/types/auth.d.ts.map +1 -0
  143. package/dist/esm/types/auth.js +2 -0
  144. package/dist/esm/types/auth.js.map +1 -0
  145. package/dist/esm/types/index.d.ts +4 -0
  146. package/dist/esm/types/index.d.ts.map +1 -0
  147. package/dist/esm/types/index.js +3 -0
  148. package/dist/esm/types/index.js.map +1 -0
  149. package/dist/esm/types/wire.d.ts +195 -0
  150. package/dist/esm/types/wire.d.ts.map +1 -0
  151. package/dist/esm/types/wire.js +7 -0
  152. package/dist/esm/types/wire.js.map +1 -0
  153. package/dist/esm/types/ws.d.ts +108 -0
  154. package/dist/esm/types/ws.d.ts.map +1 -0
  155. package/dist/esm/types/ws.js +7 -0
  156. package/dist/esm/types/ws.js.map +1 -0
  157. package/dist/esm/utils/activityCursor.d.ts +47 -0
  158. package/dist/esm/utils/activityCursor.d.ts.map +1 -0
  159. package/dist/esm/utils/activityCursor.js +93 -0
  160. package/dist/esm/utils/activityCursor.js.map +1 -0
  161. package/dist/esm/utils/apiClient.d.ts +90 -0
  162. package/dist/esm/utils/apiClient.d.ts.map +1 -0
  163. package/dist/esm/utils/apiClient.js +169 -0
  164. package/dist/esm/utils/apiClient.js.map +1 -0
  165. package/dist/esm/utils/index.d.ts +11 -0
  166. package/dist/esm/utils/index.d.ts.map +1 -0
  167. package/dist/esm/utils/index.js +12 -0
  168. package/dist/esm/utils/index.js.map +1 -0
  169. package/dist/esm/utils/liquidation.d.ts +20 -0
  170. package/dist/esm/utils/liquidation.d.ts.map +1 -0
  171. package/dist/esm/utils/liquidation.js +29 -0
  172. package/dist/esm/utils/liquidation.js.map +1 -0
  173. package/dist/esm/utils/mapActivity.d.ts +21 -0
  174. package/dist/esm/utils/mapActivity.d.ts.map +1 -0
  175. package/dist/esm/utils/mapActivity.js +45 -0
  176. package/dist/esm/utils/mapActivity.js.map +1 -0
  177. package/dist/esm/utils/mapFill.d.ts +12 -0
  178. package/dist/esm/utils/mapFill.d.ts.map +1 -0
  179. package/dist/esm/utils/mapFill.js +37 -0
  180. package/dist/esm/utils/mapFill.js.map +1 -0
  181. package/dist/esm/utils/mapOrder.d.ts +50 -0
  182. package/dist/esm/utils/mapOrder.d.ts.map +1 -0
  183. package/dist/esm/utils/mapOrder.js +155 -0
  184. package/dist/esm/utils/mapOrder.js.map +1 -0
  185. package/dist/esm/utils/mapPosition.d.ts +19 -0
  186. package/dist/esm/utils/mapPosition.d.ts.map +1 -0
  187. package/dist/esm/utils/mapPosition.js +32 -0
  188. package/dist/esm/utils/mapPosition.js.map +1 -0
  189. package/dist/esm/utils/ohlcvInterval.d.ts +11 -0
  190. package/dist/esm/utils/ohlcvInterval.d.ts.map +1 -0
  191. package/dist/esm/utils/ohlcvInterval.js +59 -0
  192. package/dist/esm/utils/ohlcvInterval.js.map +1 -0
  193. package/dist/esm/utils/ondoAsset.d.ts +4 -0
  194. package/dist/esm/utils/ondoAsset.d.ts.map +1 -0
  195. package/dist/esm/utils/ondoAsset.js +9 -0
  196. package/dist/esm/utils/ondoAsset.js.map +1 -0
  197. package/dist/esm/utils/orderFormatting.d.ts +33 -0
  198. package/dist/esm/utils/orderFormatting.d.ts.map +1 -0
  199. package/dist/esm/utils/orderFormatting.js +62 -0
  200. package/dist/esm/utils/orderFormatting.js.map +1 -0
  201. package/dist/esm/websocket/OndoWsProvider.d.ts +122 -0
  202. package/dist/esm/websocket/OndoWsProvider.d.ts.map +1 -0
  203. package/dist/esm/websocket/OndoWsProvider.js +591 -0
  204. package/dist/esm/websocket/OndoWsProvider.js.map +1 -0
  205. package/dist/types/OndoProvider.d.ts +39 -0
  206. package/dist/types/OndoProvider.d.ts.map +1 -0
  207. package/dist/types/accountConfig.d.ts +13 -0
  208. package/dist/types/accountConfig.d.ts.map +1 -0
  209. package/dist/types/accountSummary.d.ts +12 -0
  210. package/dist/types/accountSummary.d.ts.map +1 -0
  211. package/dist/types/auth/OndoTokenStore.d.ts +20 -0
  212. package/dist/types/auth/OndoTokenStore.d.ts.map +1 -0
  213. package/dist/types/auth/completeSiweLogin.d.ts +28 -0
  214. package/dist/types/auth/completeSiweLogin.d.ts.map +1 -0
  215. package/dist/types/auth/index.d.ts +4 -0
  216. package/dist/types/auth/index.d.ts.map +1 -0
  217. package/dist/types/auth/signActions.d.ts +35 -0
  218. package/dist/types/auth/signActions.d.ts.map +1 -0
  219. package/dist/types/constants.d.ts +35 -0
  220. package/dist/types/constants.d.ts.map +1 -0
  221. package/dist/types/index.d.ts +19 -0
  222. package/dist/types/index.d.ts.map +1 -0
  223. package/dist/types/types/auth.d.ts +32 -0
  224. package/dist/types/types/auth.d.ts.map +1 -0
  225. package/dist/types/types/index.d.ts +4 -0
  226. package/dist/types/types/index.d.ts.map +1 -0
  227. package/dist/types/types/wire.d.ts +195 -0
  228. package/dist/types/types/wire.d.ts.map +1 -0
  229. package/dist/types/types/ws.d.ts +108 -0
  230. package/dist/types/types/ws.d.ts.map +1 -0
  231. package/dist/types/utils/activityCursor.d.ts +47 -0
  232. package/dist/types/utils/activityCursor.d.ts.map +1 -0
  233. package/dist/types/utils/apiClient.d.ts +90 -0
  234. package/dist/types/utils/apiClient.d.ts.map +1 -0
  235. package/dist/types/utils/index.d.ts +11 -0
  236. package/dist/types/utils/index.d.ts.map +1 -0
  237. package/dist/types/utils/liquidation.d.ts +20 -0
  238. package/dist/types/utils/liquidation.d.ts.map +1 -0
  239. package/dist/types/utils/mapActivity.d.ts +21 -0
  240. package/dist/types/utils/mapActivity.d.ts.map +1 -0
  241. package/dist/types/utils/mapFill.d.ts +12 -0
  242. package/dist/types/utils/mapFill.d.ts.map +1 -0
  243. package/dist/types/utils/mapOrder.d.ts +50 -0
  244. package/dist/types/utils/mapOrder.d.ts.map +1 -0
  245. package/dist/types/utils/mapPosition.d.ts +19 -0
  246. package/dist/types/utils/mapPosition.d.ts.map +1 -0
  247. package/dist/types/utils/ohlcvInterval.d.ts +11 -0
  248. package/dist/types/utils/ohlcvInterval.d.ts.map +1 -0
  249. package/dist/types/utils/ondoAsset.d.ts +4 -0
  250. package/dist/types/utils/ondoAsset.d.ts.map +1 -0
  251. package/dist/types/utils/orderFormatting.d.ts +33 -0
  252. package/dist/types/utils/orderFormatting.d.ts.map +1 -0
  253. package/dist/types/websocket/OndoWsProvider.d.ts +122 -0
  254. package/dist/types/websocket/OndoWsProvider.d.ts.map +1 -0
  255. package/package.json +64 -0
  256. package/src/OndoProvider.ts +635 -0
  257. package/src/accountConfig.ts +105 -0
  258. package/src/accountSummary.ts +22 -0
  259. package/src/auth/OndoTokenStore.ts +83 -0
  260. package/src/auth/completeSiweLogin.ts +43 -0
  261. package/src/auth/index.ts +12 -0
  262. package/src/auth/signActions.ts +160 -0
  263. package/src/constants.ts +38 -0
  264. package/src/index.ts +36 -0
  265. package/src/types/auth.ts +32 -0
  266. package/src/types/index.ts +5 -0
  267. package/src/types/wire.ts +228 -0
  268. package/src/types/ws.ts +79 -0
  269. package/src/utils/activityCursor.ts +140 -0
  270. package/src/utils/apiClient.ts +257 -0
  271. package/src/utils/index.ts +35 -0
  272. package/src/utils/liquidation.ts +37 -0
  273. package/src/utils/mapActivity.ts +61 -0
  274. package/src/utils/mapFill.ts +47 -0
  275. package/src/utils/mapOrder.ts +201 -0
  276. package/src/utils/mapPosition.ts +44 -0
  277. package/src/utils/ohlcvInterval.ts +69 -0
  278. package/src/utils/ondoAsset.ts +10 -0
  279. package/src/utils/orderFormatting.ts +70 -0
  280. package/src/websocket/OndoWsProvider.ts +752 -0
@@ -0,0 +1,35 @@
1
+ // biome-ignore-all lint/performance/noBarrelFile: module public entry point.
2
+
3
+ export {
4
+ decodeActivityCursor,
5
+ encodeActivityCursor,
6
+ type OndoActivityCursor,
7
+ } from './activityCursor.js'
8
+ export {
9
+ type ApiParams,
10
+ ONDO_RETRY_DEFAULTS,
11
+ OndoApiClient,
12
+ type OndoApiClientOptions,
13
+ OndoApiError,
14
+ type OndoHttpMethod,
15
+ type OndoPage,
16
+ type OndoRequestOptions,
17
+ OndoSessionExpiredError,
18
+ } from './apiClient.js'
19
+ export { estimateLiquidationPrice } from './liquidation.js'
20
+ export { mapFundingActivity, mapLiquidationActivity } from './mapActivity.js'
21
+ export { mapFill } from './mapFill.js'
22
+ export {
23
+ classifyAndMapOrders,
24
+ isTriggerOrder,
25
+ mapOrder,
26
+ mapOrderDetail,
27
+ mapOrderStatus,
28
+ mapOrderType,
29
+ mapStatusReason,
30
+ mapTriggerOrder,
31
+ } from './mapOrder.js'
32
+ export { mapOpenPositions, mapPosition } from './mapPosition.js'
33
+ export { intervalFromBarSpan, mapInterval } from './ohlcvInterval.js'
34
+ export { ondoAsset } from './ondoAsset.js'
35
+ export { formatOrderPrice, formatOrderSize } from './orderFormatting.js'
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Ondo liquidation price estimation.
3
+ *
4
+ * The LI.FI backend surfaces Ondo's per-market maintenance margin rate on the
5
+ * generic {@link PerpsMarket} as `maintenanceMarginRate`. The estimate is the
6
+ * standard isolated-margin model parameterised by that rate.
7
+ */
8
+
9
+ import {
10
+ estimateIsolatedLiquidationPrice,
11
+ type LiquidationEstimateParams,
12
+ } from '@lifi/perps-sdk'
13
+ import type { PerpsMarket } from '@lifi/perps-types'
14
+
15
+ /**
16
+ * Estimate the liquidation price of a new position on an Ondo market.
17
+ *
18
+ * @returns The estimated liquidation price, or `undefined` when
19
+ * `market.maintenanceMarginRate` is absent (the model cannot be evaluated
20
+ * without the venue's maintenance margin rate) or the inputs are
21
+ * degenerate.
22
+ * @public
23
+ */
24
+ export function estimateLiquidationPrice(
25
+ market: PerpsMarket,
26
+ params: LiquidationEstimateParams
27
+ ): number | undefined {
28
+ if (market.maintenanceMarginRate === undefined) {
29
+ return undefined
30
+ }
31
+ return estimateIsolatedLiquidationPrice({
32
+ entryPrice: params.entryPrice,
33
+ leverage: params.leverage,
34
+ isLong: params.isLong,
35
+ maintenanceMarginRate: market.maintenanceMarginRate,
36
+ })
37
+ }
@@ -0,0 +1,61 @@
1
+ import type {
2
+ FundingActivity,
3
+ LiquidationActivity,
4
+ MarketDisplay,
5
+ } from '@lifi/perps-types'
6
+ import { ActivityType } from '@lifi/perps-types'
7
+ import { ONDO_PROVIDER_KEY } from '../constants.js'
8
+ import type {
9
+ OndoFundingFeeTransfer,
10
+ OndoLiquidationEvent,
11
+ } from '../types/wire.js'
12
+
13
+ /**
14
+ * Map an Ondo funding-fee transfer to a {@link FundingActivity}. Ondo carries
15
+ * no transfer id on the wire, so a deterministic `funding:<market>:<ISO time>`
16
+ * id is synthesized — funding settles at most once per market per interval,
17
+ * so the pair is unique.
18
+ *
19
+ * @param market - Backend-resolved market identity for `transfer.market`.
20
+ * @public
21
+ */
22
+ export const mapFundingActivity = (
23
+ transfer: OndoFundingFeeTransfer,
24
+ market: MarketDisplay
25
+ ): FundingActivity => {
26
+ const timestamp = new Date(transfer.time).toISOString()
27
+ return {
28
+ id: `funding:${transfer.market}:${timestamp}`,
29
+ provider: ONDO_PROVIDER_KEY,
30
+ timestamp,
31
+ type: ActivityType.FUNDING,
32
+ market,
33
+ amount: transfer.amount,
34
+ positionSize: transfer.positionSize,
35
+ fundingRate: transfer.rate,
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Map an Ondo liquidation event to a {@link LiquidationActivity}. Ondo does
41
+ * not report the account value at liquidation time, and its margin accounts
42
+ * are cross-only, so `accountValue` is `'0'` and `leverageType` is `'cross'`.
43
+ *
44
+ * @public
45
+ */
46
+ export const mapLiquidationActivity = (
47
+ event: OndoLiquidationEvent,
48
+ resolveMarket: (market: string) => MarketDisplay
49
+ ): LiquidationActivity => ({
50
+ id: event.id,
51
+ provider: ONDO_PROVIDER_KEY,
52
+ timestamp: new Date(event.time).toISOString(),
53
+ type: ActivityType.LIQUIDATION,
54
+ liquidatedNotionalPosition: event.filledQuoteSize ?? '0',
55
+ accountValue: '0',
56
+ leverageType: 'cross',
57
+ liquidatedPositions: (event.triggeringPositions ?? []).map((p) => ({
58
+ market: resolveMarket(p.market),
59
+ size: p.netQuantity,
60
+ })),
61
+ })
@@ -0,0 +1,47 @@
1
+ import type { Fill, MarketDisplay } from '@lifi/perps-types'
2
+ import {
3
+ FillClassification,
4
+ FillStatus,
5
+ LiquidityRole,
6
+ OrderSide,
7
+ } from '@lifi/perps-types'
8
+ import Big from 'big.js'
9
+ import type { OndoFill, OndoFillDirection } from '../types/wire.js'
10
+
11
+ const DIRECTION_CLASSIFICATIONS: Record<OndoFillDirection, FillClassification> =
12
+ {
13
+ openLong: FillClassification.OPENED_LONG,
14
+ openShort: FillClassification.OPENED_SHORT,
15
+ closeLong: FillClassification.CLOSED_LONG,
16
+ closeShort: FillClassification.CLOSED_SHORT,
17
+ flipLongToShort: FillClassification.SWITCHED_SHORT,
18
+ flipShortToLong: FillClassification.SWITCHED_LONG,
19
+ }
20
+
21
+ /**
22
+ * Map a raw Ondo fill to the generic {@link Fill}. The fee is netted against
23
+ * Ondo's `feeRebate`; when the wire `direction` is absent the classification
24
+ * falls back to the fill side.
25
+ *
26
+ * @param market - Backend-resolved market identity for `fill.market`.
27
+ * @public
28
+ */
29
+ export const mapFill = (fill: OndoFill, market: MarketDisplay): Fill => ({
30
+ id: fill.id,
31
+ orderId: fill.orderId,
32
+ market,
33
+ side: fill.side === 'buy' ? OrderSide.BUY : OrderSide.SELL,
34
+ size: fill.size,
35
+ price: fill.price,
36
+ status: FillStatus.FILLED,
37
+ liquidity: fill.isMaker ? LiquidityRole.MAKER : LiquidityRole.TAKER,
38
+ fee: new Big(fill.fee).minus(fill.feeRebate ?? '0').toFixed(),
39
+ realizedPnl: fill.pnl,
40
+ classification:
41
+ fill.direction !== undefined
42
+ ? DIRECTION_CLASSIFICATIONS[fill.direction]
43
+ : fill.side === 'buy'
44
+ ? FillClassification.OPENED_LONG
45
+ : FillClassification.OPENED_SHORT,
46
+ createdAt: new Date(fill.time).toISOString(),
47
+ })
@@ -0,0 +1,201 @@
1
+ import type {
2
+ MarketDisplay,
3
+ OpenOrder,
4
+ Order,
5
+ TriggerOrder,
6
+ } from '@lifi/perps-types'
7
+ import {
8
+ OrderSide,
9
+ OrderStatus,
10
+ OrderType,
11
+ TimeInForce,
12
+ } from '@lifi/perps-types'
13
+ import Big from 'big.js'
14
+ import type {
15
+ OndoOrder,
16
+ OndoOrderStatus,
17
+ OndoOrderType,
18
+ } from '../types/wire.js'
19
+
20
+ const toIso = (time: string): string => new Date(time).toISOString()
21
+
22
+ const mapSide = (side: OndoOrder['side']): OrderSide =>
23
+ side === 'buy' ? OrderSide.BUY : OrderSide.SELL
24
+
25
+ /** @public */
26
+ export const mapOrderType = (type: OndoOrderType): OrderType => {
27
+ switch (type) {
28
+ case 'limit':
29
+ return OrderType.LIMIT
30
+ case 'market':
31
+ return OrderType.MARKET
32
+ case 'stopMarket':
33
+ return OrderType.STOP_MARKET
34
+ case 'takeProfitMarket':
35
+ return OrderType.TAKE_PROFIT_MARKET
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Map Ondo's order status onto the generic enum. `untriggered` stop orders
41
+ * are active resting orders from the trader's point of view, so they map to
42
+ * OPEN.
43
+ * @public
44
+ */
45
+ export const mapOrderStatus = (status: OndoOrderStatus): OrderStatus => {
46
+ switch (status) {
47
+ case 'open':
48
+ case 'untriggered':
49
+ return OrderStatus.OPEN
50
+ case 'pending':
51
+ return OrderStatus.PENDING
52
+ case 'fullyfilled':
53
+ return OrderStatus.FILLED
54
+ case 'canceled':
55
+ return OrderStatus.CANCELLED
56
+ }
57
+ }
58
+
59
+ const CANCEL_REASON_SENTENCES: Record<string, string> = {
60
+ liquidation: 'Order cancelled: position was liquidated.',
61
+ selfMatchPrevention:
62
+ 'Order cancelled: would self-match against your own resting order.',
63
+ immediateOrCancel: 'Order cancelled: immediate-or-cancel remainder.',
64
+ }
65
+
66
+ /**
67
+ * Plain-English `statusReason` for a cancelled order; `undefined` for every
68
+ * other status. Unknown wire reasons fall back to the generic sentence rather
69
+ * than leaking raw enum values into the UI.
70
+ * @public
71
+ */
72
+ export const mapStatusReason = (order: OndoOrder): string | undefined => {
73
+ if (order.status !== 'canceled') {
74
+ return undefined
75
+ }
76
+ return CANCEL_REASON_SENTENCES[order.cancelReason ?? ''] ?? 'Order cancelled.'
77
+ }
78
+
79
+ /**
80
+ * Whether an order rests on a trigger. Checks `stopOrderType` and
81
+ * `triggerPrice` besides the type so a lagging `type` field cannot
82
+ * misclassify a trigger as a plain order.
83
+ * @public
84
+ */
85
+ export const isTriggerOrder = (order: OndoOrder): boolean =>
86
+ order.type === 'stopMarket' ||
87
+ order.type === 'takeProfitMarket' ||
88
+ order.stopOrderType !== undefined ||
89
+ order.triggerPrice !== undefined
90
+
91
+ /** Map an active non-trigger Ondo order to an {@link OpenOrder}. @public */
92
+ export const mapOrder = (
93
+ order: OndoOrder,
94
+ market: MarketDisplay
95
+ ): OpenOrder => ({
96
+ orderId: order.orderId,
97
+ market,
98
+ side: mapSide(order.side),
99
+ type: mapOrderType(order.type),
100
+ size: order.size,
101
+ price: order.price,
102
+ filledSize: order.filledSize,
103
+ reduceOnly: order.reduceOnly ?? false,
104
+ createdAt: toIso(order.createdAt),
105
+ })
106
+
107
+ /** Map an active trigger Ondo order to a {@link TriggerOrder}. @public */
108
+ export const mapTriggerOrder = (
109
+ order: OndoOrder,
110
+ market: MarketDisplay
111
+ ): TriggerOrder => ({
112
+ orderId: order.orderId,
113
+ market,
114
+ type: mapOrderType(order.type),
115
+ size: order.size,
116
+ triggerPrice: order.triggerPrice ?? '0',
117
+ createdAt: toIso(order.createdAt),
118
+ })
119
+
120
+ const TERMINAL_STATUSES: ReadonlySet<OndoOrderStatus> = new Set([
121
+ 'canceled',
122
+ 'fullyfilled',
123
+ ])
124
+
125
+ /**
126
+ * Bucket a venue order list into active open/trigger orders (mapped) and
127
+ * terminal order ids. Orders whose market the resolver does not know are
128
+ * skipped.
129
+ * @public
130
+ */
131
+ export const classifyAndMapOrders = (
132
+ orders: OndoOrder[],
133
+ resolveMarket: (market: string) => MarketDisplay | undefined
134
+ ): {
135
+ openOrders: OpenOrder[]
136
+ triggerOrders: TriggerOrder[]
137
+ terminated: string[]
138
+ } => {
139
+ const openOrders: OpenOrder[] = []
140
+ const triggerOrders: TriggerOrder[] = []
141
+ const terminated: string[] = []
142
+ for (const order of orders) {
143
+ if (TERMINAL_STATUSES.has(order.status)) {
144
+ terminated.push(order.orderId)
145
+ continue
146
+ }
147
+ const market = resolveMarket(order.market)
148
+ if (market === undefined) {
149
+ continue
150
+ }
151
+ if (isTriggerOrder(order)) {
152
+ triggerOrders.push(mapTriggerOrder(order, market))
153
+ } else {
154
+ openOrders.push(mapOrder(order, market))
155
+ }
156
+ }
157
+ return { openOrders, triggerOrders, terminated }
158
+ }
159
+
160
+ /**
161
+ * Map a single venue order onto the rich {@link Order} detail shape.
162
+ * `remainingSize` and `averagePrice` are derived (`size − filledSize`,
163
+ * `filledCost ÷ filledSize`); `updatedAt` is the latest transition timestamp
164
+ * Ondo exposes, falling back to `createdAt`.
165
+ * @public
166
+ */
167
+ export const mapOrderDetail = (
168
+ order: OndoOrder,
169
+ market: MarketDisplay
170
+ ): Order => {
171
+ const filled = new Big(order.filledSize)
172
+ const trigger = isTriggerOrder(order)
173
+ return {
174
+ orderId: order.orderId,
175
+ market,
176
+ side: mapSide(order.side),
177
+ type: mapOrderType(order.type),
178
+ price: order.price,
179
+ originalSize: order.size,
180
+ remainingSize: new Big(order.size).minus(filled).toFixed(),
181
+ filledSize: order.filledSize,
182
+ timeInForce:
183
+ order.timeInForce === undefined
184
+ ? undefined
185
+ : TimeInForce[order.timeInForce],
186
+ reduceOnly: order.reduceOnly ?? false,
187
+ isTrigger: trigger,
188
+ ...(trigger && order.triggerPrice !== undefined
189
+ ? { triggerPrice: order.triggerPrice }
190
+ : {}),
191
+ status: mapOrderStatus(order.status),
192
+ ...(mapStatusReason(order) !== undefined
193
+ ? { statusReason: mapStatusReason(order) }
194
+ : {}),
195
+ ...(filled.gt(0)
196
+ ? { averagePrice: new Big(order.filledCost).div(filled).toFixed() }
197
+ : {}),
198
+ createdAt: toIso(order.createdAt),
199
+ updatedAt: toIso(order.canceledAt ?? order.filledAt ?? order.createdAt),
200
+ }
201
+ }
@@ -0,0 +1,44 @@
1
+ import type { MarketDisplay, Position } from '@lifi/perps-types'
2
+ import { MarginMode, PositionSide } from '@lifi/perps-types'
3
+ import Big from 'big.js'
4
+ import type { OndoPosition } from '../types/wire.js'
5
+
6
+ /**
7
+ * Map a raw Ondo position to the generic Position type. Ondo margin accounts
8
+ * are cross-margined only.
9
+ *
10
+ * @param market - Backend-resolved market identity for `pos.market`.
11
+ * @public
12
+ */
13
+ export const mapPosition = (
14
+ pos: OndoPosition,
15
+ market: MarketDisplay
16
+ ): Position => ({
17
+ market,
18
+ side: pos.direction === 'short' ? PositionSide.SHORT : PositionSide.LONG,
19
+ size: new Big(pos.netQuantity).abs().toFixed(),
20
+ entryPrice: pos.averageEntryPrice,
21
+ markPrice: pos.markPrice,
22
+ liquidationPrice: pos.liquidationPrice,
23
+ unrealizedPnl: pos.unrealizedPnl,
24
+ leverage: Number.parseFloat(pos.leverage),
25
+ marginUsed: pos.usedMargin,
26
+ marginMode: MarginMode.CROSS,
27
+ })
28
+
29
+ /**
30
+ * Map raw Ondo positions to open {@link Position}s, dropping neutral and
31
+ * zero-quantity rows. Only valid for payloads carrying the full position
32
+ * set — dropping zeros from a partial frame would make closes unobservable.
33
+ *
34
+ * @public
35
+ */
36
+ export const mapOpenPositions = (
37
+ positions: OndoPosition[],
38
+ resolveMarket: (market: string) => MarketDisplay
39
+ ): Position[] =>
40
+ positions
41
+ .filter(
42
+ (p) => p.direction !== 'neutral' && Number.parseFloat(p.netQuantity) !== 0
43
+ )
44
+ .map((p) => mapPosition(p, resolveMarket(p.market)))
@@ -0,0 +1,69 @@
1
+ import { PerpsError } from '@lifi/perps-sdk'
2
+ import type { OhlcvInterval } from '@lifi/perps-types'
3
+ import { PerpsErrorCode } from '@lifi/perps-types'
4
+
5
+ /**
6
+ * Map our `OhlcvInterval` literal to Ondo's kline `resolution` enum.
7
+ *
8
+ * Ondo exposes only the timeframes listed below. SDK intervals without a
9
+ * direct match (3m, 2h, 8h, 12h, 3d) raise a validation error rather than
10
+ * silently rounding — the caller picks a supported timeframe.
11
+ */
12
+ const ONDO_SUPPORTED_INTERVALS: Record<string, string> = {
13
+ '1m': '1',
14
+ '5m': '5',
15
+ '15m': '15',
16
+ '30m': '30',
17
+ '1h': '1H',
18
+ '4h': '4H',
19
+ '1d': '1D',
20
+ '1w': '1W',
21
+ '1M': '1M',
22
+ }
23
+
24
+ const INTERVAL_SECONDS: Record<string, OhlcvInterval> = {
25
+ 60: '1m',
26
+ 300: '5m',
27
+ 900: '15m',
28
+ 1800: '30m',
29
+ 3600: '1h',
30
+ 14400: '4h',
31
+ 86400: '1d',
32
+ 604800: '1w',
33
+ }
34
+
35
+ const MONTH_MIN_SECS = 28 * 86400
36
+ const MONTH_MAX_SECS = 31 * 86400
37
+
38
+ /** @public */
39
+ export const mapInterval = (interval: string): string => {
40
+ const resolution = ONDO_SUPPORTED_INTERVALS[interval]
41
+ if (!resolution) {
42
+ throw new PerpsError(
43
+ PerpsErrorCode.ValidationError,
44
+ `Ondo does not support OHLCV interval '${interval}'. ` +
45
+ `Supported: ${Object.keys(ONDO_SUPPORTED_INTERVALS).join(', ')}.`
46
+ )
47
+ }
48
+ return resolution
49
+ }
50
+
51
+ /**
52
+ * Recover the SDK interval from a kline frame's bar span in seconds. Ondo's
53
+ * kline updates carry no resolution field — only the interval start/end —
54
+ * so the span is the only way to route a frame to its subscription.
55
+ * @public
56
+ */
57
+ export const intervalFromBarSpan = (
58
+ spanSecs: number
59
+ ): OhlcvInterval | undefined => {
60
+ const fixed = INTERVAL_SECONDS[spanSecs]
61
+ if (fixed !== undefined) {
62
+ return fixed
63
+ }
64
+ // Monthly bars span a calendar month, so their second-count varies by month.
65
+ if (spanSecs >= MONTH_MIN_SECS && spanSecs <= MONTH_MAX_SECS) {
66
+ return '1M'
67
+ }
68
+ return undefined
69
+ }
@@ -0,0 +1,10 @@
1
+ import type { Asset } from '@lifi/perps-types'
2
+ import { ONDO_PROVIDER_KEY } from '../constants.js'
3
+
4
+ /** @public */
5
+ export const ondoAsset = (id: string, displaySymbol: string): Asset => ({
6
+ providerId: ONDO_PROVIDER_KEY,
7
+ id,
8
+ displaySymbol,
9
+ logoURI: '',
10
+ })
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Ondo order size and price formatting for exchange submission.
3
+ *
4
+ * Ondo's tick and lot grids are exact contract increments (`quoteIncrement` /
5
+ * `baseIncrement`) that need not be powers of ten. When the generic
6
+ * {@link Market} carries the raw increment (`priceIncrement` / `sizeIncrement`)
7
+ * these helpers snap onto that grid; otherwise they fall back to the
8
+ * power-of-ten grid implied by `priceDecimals` / `szDecimals`. Prices round
9
+ * half-up to the nearest tick; sizes truncate toward zero to the lot.
10
+ */
11
+
12
+ import { PerpsError } from '@lifi/perps-sdk'
13
+ import { type Market, PerpsErrorCode } from '@lifi/perps-types'
14
+ import Big from 'big.js'
15
+
16
+ const powerOfTenIncrement = (decimals: number): Big => new Big(`1e-${decimals}`)
17
+
18
+ const priceGrid = (market: Market): Big => {
19
+ if (market.priceIncrement !== undefined) {
20
+ return new Big(market.priceIncrement)
21
+ }
22
+ if (market.priceDecimals !== undefined) {
23
+ return powerOfTenIncrement(market.priceDecimals)
24
+ }
25
+ throw new PerpsError(
26
+ PerpsErrorCode.ValidationError,
27
+ `Market '${market.id}' carries no price grid; Ondo order prices cannot ` +
28
+ `be formatted without the market's tick increment.`
29
+ )
30
+ }
31
+
32
+ /**
33
+ * Format a price onto an Ondo market's tick grid: snapped half-up to the
34
+ * nearest `priceIncrement` (or the grid implied by `priceDecimals`), trailing
35
+ * zeros stripped.
36
+ *
37
+ * @throws {PerpsError} `ValidationError` when the market carries neither
38
+ * `priceIncrement` nor `priceDecimals` — without the venue's tick grid no
39
+ * correct price can be produced.
40
+ * @public
41
+ */
42
+ export function formatOrderPrice(market: Market, price: number): string {
43
+ const increment = priceGrid(market)
44
+ const snapped = new Big(price)
45
+ .div(increment)
46
+ .round(0, Big.roundHalfUp)
47
+ .times(increment)
48
+ return snapped.eq(0) ? '0' : snapped.toFixed()
49
+ }
50
+
51
+ /**
52
+ * Format a size onto an Ondo market's lot grid: truncated toward zero (never
53
+ * rounded up, so the size cannot exceed the user's balance) to the market's
54
+ * `sizeIncrement` (or the grid implied by `szDecimals`), trailing zeros
55
+ * stripped.
56
+ *
57
+ * @param size - Size in base-asset units as a non-negative magnitude.
58
+ * @public
59
+ */
60
+ export function formatOrderSize(market: Market, size: number): string {
61
+ const increment =
62
+ market.sizeIncrement !== undefined
63
+ ? new Big(market.sizeIncrement)
64
+ : powerOfTenIncrement(market.szDecimals)
65
+ const snapped = new Big(size)
66
+ .div(increment)
67
+ .round(0, Big.roundDown)
68
+ .times(increment)
69
+ return snapped.eq(0) ? '0' : snapped.toFixed()
70
+ }