@lifi/perps-sdk-provider-lighter 34.0.0 → 35.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/cjs/LighterProvider.d.ts +0 -1
  2. package/dist/cjs/LighterProvider.d.ts.map +1 -1
  3. package/dist/cjs/LighterProvider.js +50 -44
  4. package/dist/cjs/LighterProvider.js.map +1 -1
  5. package/dist/cjs/accountSummary.d.ts.map +1 -1
  6. package/dist/cjs/accountSummary.js +3 -6
  7. package/dist/cjs/accountSummary.js.map +1 -1
  8. package/dist/cjs/constants.d.ts +1 -0
  9. package/dist/cjs/constants.d.ts.map +1 -1
  10. package/dist/cjs/constants.js +2 -1
  11. package/dist/cjs/constants.js.map +1 -1
  12. package/dist/cjs/index.d.ts +1 -1
  13. package/dist/cjs/index.d.ts.map +1 -1
  14. package/dist/cjs/index.js +2 -1
  15. package/dist/cjs/index.js.map +1 -1
  16. package/dist/cjs/signers/createAuthToken.d.ts.map +1 -1
  17. package/dist/cjs/signers/createAuthToken.js.map +1 -1
  18. package/dist/cjs/utils/mapPosition.d.ts.map +1 -1
  19. package/dist/cjs/utils/mapPosition.js +4 -1
  20. package/dist/cjs/utils/mapPosition.js.map +1 -1
  21. package/dist/cjs/utils/settlementPool.d.ts +6 -0
  22. package/dist/cjs/utils/settlementPool.d.ts.map +1 -0
  23. package/dist/cjs/utils/settlementPool.js +21 -0
  24. package/dist/cjs/utils/settlementPool.js.map +1 -0
  25. package/dist/cjs/utils/transferMargin.d.ts.map +1 -1
  26. package/dist/cjs/utils/transferMargin.js +1 -6
  27. package/dist/cjs/utils/transferMargin.js.map +1 -1
  28. package/dist/esm/LighterProvider.d.ts +7 -11
  29. package/dist/esm/LighterProvider.d.ts.map +1 -1
  30. package/dist/esm/LighterProvider.js +60 -51
  31. package/dist/esm/LighterProvider.js.map +1 -1
  32. package/dist/esm/accountSummary.d.ts +2 -1
  33. package/dist/esm/accountSummary.d.ts.map +1 -1
  34. package/dist/esm/accountSummary.js +5 -7
  35. package/dist/esm/accountSummary.js.map +1 -1
  36. package/dist/esm/constants.d.ts +8 -0
  37. package/dist/esm/constants.d.ts.map +1 -1
  38. package/dist/esm/constants.js +8 -0
  39. package/dist/esm/constants.js.map +1 -1
  40. package/dist/esm/index.d.ts +1 -1
  41. package/dist/esm/index.d.ts.map +1 -1
  42. package/dist/esm/index.js +1 -1
  43. package/dist/esm/index.js.map +1 -1
  44. package/dist/esm/signers/createAuthToken.d.ts +1 -2
  45. package/dist/esm/signers/createAuthToken.d.ts.map +1 -1
  46. package/dist/esm/signers/createAuthToken.js +1 -2
  47. package/dist/esm/signers/createAuthToken.js.map +1 -1
  48. package/dist/esm/utils/mapPosition.d.ts +4 -3
  49. package/dist/esm/utils/mapPosition.d.ts.map +1 -1
  50. package/dist/esm/utils/mapPosition.js +9 -5
  51. package/dist/esm/utils/mapPosition.js.map +1 -1
  52. package/dist/esm/utils/settlementPool.d.ts +14 -0
  53. package/dist/esm/utils/settlementPool.d.ts.map +1 -0
  54. package/dist/esm/utils/settlementPool.js +23 -0
  55. package/dist/esm/utils/settlementPool.js.map +1 -0
  56. package/dist/esm/utils/transferMargin.d.ts.map +1 -1
  57. package/dist/esm/utils/transferMargin.js +2 -7
  58. package/dist/esm/utils/transferMargin.js.map +1 -1
  59. package/dist/types/LighterProvider.d.ts +7 -11
  60. package/dist/types/LighterProvider.d.ts.map +1 -1
  61. package/dist/types/accountSummary.d.ts +2 -1
  62. package/dist/types/accountSummary.d.ts.map +1 -1
  63. package/dist/types/constants.d.ts +8 -0
  64. package/dist/types/constants.d.ts.map +1 -1
  65. package/dist/types/index.d.ts +1 -1
  66. package/dist/types/index.d.ts.map +1 -1
  67. package/dist/types/signers/createAuthToken.d.ts +1 -2
  68. package/dist/types/signers/createAuthToken.d.ts.map +1 -1
  69. package/dist/types/utils/mapPosition.d.ts +4 -3
  70. package/dist/types/utils/mapPosition.d.ts.map +1 -1
  71. package/dist/types/utils/settlementPool.d.ts +14 -0
  72. package/dist/types/utils/settlementPool.d.ts.map +1 -0
  73. package/dist/types/utils/transferMargin.d.ts.map +1 -1
  74. package/package.json +3 -3
  75. package/src/LighterProvider.ts +98 -90
  76. package/src/accountSummary.ts +10 -10
  77. package/src/constants.ts +9 -0
  78. package/src/index.ts +1 -0
  79. package/src/signers/createAuthToken.ts +1 -2
  80. package/src/utils/mapPosition.ts +12 -5
  81. package/src/utils/settlementPool.ts +36 -0
  82. package/src/utils/transferMargin.ts +4 -10
@@ -50,7 +50,8 @@ export const lighterPortfolioValue = (
50
50
 
51
51
  /**
52
52
  * Roll up settlement equity, spot holdings and non-settlement margin holdings.
53
- * Settlement margin is already included in `totalAssetValue`.
53
+ * The settlement asset counts as `totalAssetValue` plus its spot-route balance,
54
+ * so a row that pools both routes is not counted again.
54
55
  *
55
56
  * @throws {PerpsError} `SDKError` when the account is not a Lighter one.
56
57
  * @public
@@ -61,14 +62,11 @@ export function getAccountSummary(
61
62
  ): AccountSummary {
62
63
  const config = lighterConfig(account)
63
64
  const settlement = LIGHTER_COLLATERAL_ASSETS[config.provider]
64
- const holdings = [
65
- ...account.balances,
66
- ...account.collateralBalances.filter(
67
- ({ asset }) =>
68
- asset.id !== String(settlement.assetIndex) &&
69
- asset.id !== settlement.displaySymbol
70
- ),
71
- ]
65
+ const holdings = [...account.balances, ...account.collateralBalances].filter(
66
+ ({ asset }) =>
67
+ asset.id !== String(settlement.assetIndex) &&
68
+ asset.id !== settlement.displaySymbol
69
+ )
72
70
 
73
71
  let marginUsed = new Big(0)
74
72
  let unrealizedPnl = new Big(0)
@@ -79,7 +77,9 @@ export function getAccountSummary(
79
77
 
80
78
  return {
81
79
  portfolioValue: lighterPortfolioValue(
82
- toRequiredBig(config.totalAssetValue, 'totalAssetValue'),
80
+ toRequiredBig(config.totalAssetValue, 'totalAssetValue').plus(
81
+ toRequiredBig(config.collateralSpotBalance, 'collateralSpotBalance')
82
+ ),
83
83
  holdings.map((balance) => balance.valueUsd)
84
84
  ).toFixed(),
85
85
  availableMargin: atLeastZero(
package/src/constants.ts CHANGED
@@ -193,6 +193,15 @@ export const DEFAULT_TRADES_LIMIT = 50
193
193
  */
194
194
  export const LIGHTER_FEE_TICK_SCALE = 1_000_000
195
195
 
196
+ /**
197
+ * Decimal places a client may use for Lighter leverage. Lighter stores
198
+ * leverage as an integer basis-point IMF (`round(10000 / leverage)`), and at
199
+ * this precision a read-back leverage always re-saves the same IMF.
200
+ *
201
+ * @public
202
+ */
203
+ export const LIGHTER_LEVERAGE_PRECISION = 2
204
+
196
205
  /**
197
206
  * Scale of the integer `initial_margin_fraction` values Lighter publishes on
198
207
  * trade rows and order-book details: the integer is a percent times 100, so
package/src/index.ts CHANGED
@@ -25,6 +25,7 @@ export {
25
25
  DEFAULT_LIGHTER_WS_URL,
26
26
  LIGHTER_CLIENT_ORDER_INDEX_ID_PREFIX,
27
27
  LIGHTER_COLLATERAL_ASSETS,
28
+ LIGHTER_LEVERAGE_PRECISION,
28
29
  LIGHTER_MAINNET_DEPLOYMENT,
29
30
  LIGHTER_MAINNET_SIGNER_CHAIN_ID,
30
31
  LIGHTER_PROVIDER_KEY,
@@ -33,8 +33,7 @@ export interface CreateAuthTokenInputs {
33
33
  * endpoints (`getOrders`, `getOrder`, `getActivity`, etc.).
34
34
  *
35
35
  * This utility carries no SDK-wide coupling — pass an explicit `signer` +
36
- * `apiKey` and consume the returned bearer however the caller likes
37
- * (per-call `options.lighterAuthToken`, persisted cache, etc.).
36
+ * `apiKey` and consume the returned bearer however the caller likes.
38
37
  * @public
39
38
  */
40
39
  export async function createAuthToken(
@@ -1,16 +1,20 @@
1
1
  import type { PerpsMarketDisplay, Position } from '@lifi/perps-types'
2
2
  import { MarginMode, PositionSide } from '@lifi/perps-types'
3
3
  import Big from 'big.js'
4
- import { LIGHTER_IMF_PERCENT_SCALE } from '../constants.js'
4
+ import {
5
+ LIGHTER_IMF_PERCENT_SCALE,
6
+ LIGHTER_LEVERAGE_PRECISION,
7
+ } from '../constants.js'
5
8
  import type { LtAccountPosition } from '../types/index.js'
6
9
  import { LT_MARGIN_MODE_ISOLATED } from '../types/index.js'
7
10
  import { toPositiveRequiredBig, toRequiredBig } from './decimal.js'
8
11
 
9
12
  /**
10
13
  * Display leverage from an IMF percent string: `100 / IMF` in exact decimal
11
- * arithmetic before conversion to `number`. This value is for displaying the
12
- * venue setting; provider risk calculations consume the original decimal IMF
13
- * instead. `undefined` for a non-positive or unparsable IMF.
14
+ * arithmetic, rounded half-up to `LIGHTER_LEVERAGE_PRECISION` before
15
+ * conversion to `number`, so the value a client reads is the value it saved.
16
+ * Provider risk calculations consume the original decimal IMF instead.
17
+ * `undefined` for a non-positive or unparsable IMF.
14
18
  * @public
15
19
  */
16
20
  export const leverageFromImf = (imf: string): number | undefined => {
@@ -23,7 +27,10 @@ export const leverageFromImf = (imf: string): number | undefined => {
23
27
  if (parsed.lte(0)) {
24
28
  return undefined
25
29
  }
26
- return new Big(100).div(parsed).toNumber()
30
+ return new Big(100)
31
+ .div(parsed)
32
+ .round(LIGHTER_LEVERAGE_PRECISION, Big.roundHalfUp)
33
+ .toNumber()
27
34
  }
28
35
 
29
36
  /**
@@ -0,0 +1,36 @@
1
+ import type Big from 'big.js'
2
+ import type { LtAccountAsset } from '../types/account.js'
3
+ import { toRequiredBig } from './decimal.js'
4
+
5
+ /** Both routes of a unified account's settlement asset, as one holding. */
6
+ export const pooledSettlementUnits = (asset: LtAccountAsset): Big =>
7
+ toRequiredBig(asset.balance, 'balance').plus(
8
+ toRequiredBig(asset.margin_balance, 'margin_balance')
9
+ )
10
+
11
+ /**
12
+ * Spot units a unified account can spend from its settlement pool: the free
13
+ * spot route plus the margin route up to the account's `available_balance`.
14
+ * This is `computeSpotAvailableToTradeMarket` in Lighter's `lighter-ts` for an
15
+ * asset priced 1:1 with a `loan_to_value` of 1. The result can be negative.
16
+ */
17
+ export const pooledSettlementSpendable = (
18
+ asset: LtAccountAsset,
19
+ availableBalance: Big
20
+ ): Big => {
21
+ const marginBalance = toRequiredBig(asset.margin_balance, 'margin_balance')
22
+ return toRequiredBig(asset.balance, 'balance')
23
+ .minus(toRequiredBig(asset.locked_balance, 'locked_balance'))
24
+ .plus(marginBalance.lt(availableBalance) ? marginBalance : availableBalance)
25
+ }
26
+
27
+ /** Spot-route `balance` of the collateral asset; `'0'` when the account holds none. */
28
+ export const collateralSpotBalance = (
29
+ assets: readonly LtAccountAsset[],
30
+ settlementAssetIndex: number
31
+ ): string => {
32
+ const asset = assets.find((a) => a.asset_id === settlementAssetIndex)
33
+ return asset === undefined
34
+ ? '0'
35
+ : toRequiredBig(asset.balance, 'balance').toFixed()
36
+ }
@@ -2,6 +2,7 @@ import {
2
2
  PerpsError,
3
3
  positionSupportsMarginAdjustment,
4
4
  positionSupportsMarginRemoval,
5
+ validateDecimalString,
5
6
  } from '@lifi/perps-sdk'
6
7
  import {
7
8
  type DecimalString,
@@ -12,18 +13,11 @@ import Big from 'big.js'
12
13
 
13
14
  const AMOUNT_DECIMALS = 6
14
15
 
15
- function positionAmount(value: string, field: string): Big {
16
- try {
17
- return new Big(value)
18
- } catch {
19
- throw new PerpsError(
20
- PerpsErrorCode.ValidationError,
21
- `Invalid decimal string on Position.${field}: '${value}'`
22
- )
23
- }
16
+ function positionAmount(value: DecimalString, field: string): Big {
17
+ return new Big(validateDecimalString(value, `Position.${field}`))
24
18
  }
25
19
 
26
- function positivePositionAmount(value: string, field: string): Big {
20
+ function positivePositionAmount(value: DecimalString, field: string): Big {
27
21
  const amount = positionAmount(value, field)
28
22
  if (amount.lte(0)) {
29
23
  throw new PerpsError(