@lifi/perps-sdk-provider-lighter 35.0.0 → 36.0.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.
- package/dist/cjs/LighterProvider.d.ts.map +1 -1
- package/dist/cjs/LighterProvider.js +101 -58
- package/dist/cjs/LighterProvider.js.map +1 -1
- package/dist/cjs/accountSummary.d.ts +1 -2
- package/dist/cjs/accountSummary.d.ts.map +1 -1
- package/dist/cjs/accountSummary.js +9 -16
- package/dist/cjs/accountSummary.js.map +1 -1
- package/dist/cjs/availableToTrade.d.ts +1 -2
- package/dist/cjs/availableToTrade.d.ts.map +1 -1
- package/dist/cjs/availableToTrade.js +8 -12
- package/dist/cjs/availableToTrade.js.map +1 -1
- package/dist/cjs/constants.d.ts +1 -0
- package/dist/cjs/constants.d.ts.map +1 -1
- package/dist/cjs/constants.js +2 -1
- package/dist/cjs/constants.js.map +1 -1
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +2 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/signers/LighterSigner.d.ts.map +1 -1
- package/dist/cjs/signers/LighterSigner.js +2 -6
- package/dist/cjs/signers/LighterSigner.js.map +1 -1
- package/dist/cjs/types/submit.d.ts +5 -0
- package/dist/cjs/types/submit.d.ts.map +1 -1
- package/dist/cjs/utils/index.d.ts +3 -3
- package/dist/cjs/utils/index.d.ts.map +1 -1
- package/dist/cjs/utils/index.js +5 -6
- package/dist/cjs/utils/index.js.map +1 -1
- package/dist/cjs/utils/mapFill.d.ts +1 -1
- package/dist/cjs/utils/mapFill.d.ts.map +1 -1
- package/dist/cjs/utils/mapFill.js +44 -31
- package/dist/cjs/utils/mapFill.js.map +1 -1
- package/dist/cjs/utils/mapOpenPositions.d.ts +3 -1
- package/dist/cjs/utils/mapOpenPositions.d.ts.map +1 -1
- package/dist/cjs/utils/mapOpenPositions.js +20 -4
- package/dist/cjs/utils/mapOpenPositions.js.map +1 -1
- package/dist/cjs/utils/mapOrder.d.ts +1 -1
- package/dist/cjs/utils/mapOrder.d.ts.map +1 -1
- package/dist/cjs/utils/mapOrder.js +64 -26
- package/dist/cjs/utils/mapOrder.js.map +1 -1
- package/dist/cjs/utils/mapPortfolioHistory.d.ts +1 -2
- package/dist/cjs/utils/mapPortfolioHistory.d.ts.map +1 -1
- package/dist/cjs/utils/mapPortfolioHistory.js +29 -21
- package/dist/cjs/utils/mapPortfolioHistory.js.map +1 -1
- package/dist/cjs/utils/mapPosition.d.ts +3 -3
- package/dist/cjs/utils/mapPosition.d.ts.map +1 -1
- package/dist/cjs/utils/mapPosition.js +35 -35
- package/dist/cjs/utils/mapPosition.js.map +1 -1
- package/dist/cjs/utils/rowTimestamp.d.ts +2 -0
- package/dist/cjs/utils/rowTimestamp.d.ts.map +1 -0
- package/dist/cjs/utils/rowTimestamp.js +14 -0
- package/dist/cjs/utils/rowTimestamp.js.map +1 -0
- package/dist/cjs/utils/settlementPool.d.ts +2 -3
- package/dist/cjs/utils/settlementPool.d.ts.map +1 -1
- package/dist/cjs/utils/settlementPool.js +8 -7
- package/dist/cjs/utils/settlementPool.js.map +1 -1
- package/dist/cjs/utils/spotPrice.d.ts +3 -4
- package/dist/cjs/utils/spotPrice.d.ts.map +1 -1
- package/dist/cjs/utils/spotPrice.js +6 -11
- package/dist/cjs/utils/spotPrice.js.map +1 -1
- package/dist/cjs/utils/time.d.ts.map +1 -1
- package/dist/cjs/utils/time.js +3 -2
- package/dist/cjs/utils/time.js.map +1 -1
- package/dist/cjs/utils/transferMargin.d.ts.map +1 -1
- package/dist/cjs/utils/transferMargin.js +7 -15
- package/dist/cjs/utils/transferMargin.js.map +1 -1
- package/dist/cjs/utils/withdrawableBalances.d.ts +1 -1
- package/dist/cjs/utils/withdrawableBalances.d.ts.map +1 -1
- package/dist/cjs/utils/withdrawableBalances.js +12 -17
- package/dist/cjs/utils/withdrawableBalances.js.map +1 -1
- package/dist/cjs/utils/withdrawalTypes.d.ts +17 -0
- package/dist/cjs/utils/withdrawalTypes.d.ts.map +1 -0
- package/dist/cjs/utils/withdrawalTypes.js +58 -0
- package/dist/cjs/utils/withdrawalTypes.js.map +1 -0
- package/dist/cjs/websocket/LighterWsProvider.d.ts.map +1 -1
- package/dist/cjs/websocket/LighterWsProvider.js +46 -58
- package/dist/cjs/websocket/LighterWsProvider.js.map +1 -1
- package/dist/cjs/websocket/orderBookSide.d.ts +19 -0
- package/dist/cjs/websocket/orderBookSide.d.ts.map +1 -0
- package/dist/cjs/websocket/orderBookSide.js +71 -0
- package/dist/cjs/websocket/orderBookSide.js.map +1 -0
- package/dist/esm/LighterProvider.d.ts.map +1 -1
- package/dist/esm/LighterProvider.js +116 -62
- package/dist/esm/LighterProvider.js.map +1 -1
- package/dist/esm/accountSummary.d.ts +1 -2
- package/dist/esm/accountSummary.d.ts.map +1 -1
- package/dist/esm/accountSummary.js +10 -14
- package/dist/esm/accountSummary.js.map +1 -1
- package/dist/esm/availableToTrade.d.ts +1 -2
- package/dist/esm/availableToTrade.d.ts.map +1 -1
- package/dist/esm/availableToTrade.js +9 -10
- package/dist/esm/availableToTrade.js.map +1 -1
- package/dist/esm/constants.d.ts +8 -0
- package/dist/esm/constants.d.ts.map +1 -1
- package/dist/esm/constants.js +8 -0
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/signers/LighterSigner.d.ts.map +1 -1
- package/dist/esm/signers/LighterSigner.js +3 -4
- package/dist/esm/signers/LighterSigner.js.map +1 -1
- package/dist/esm/types/submit.d.ts +14 -0
- package/dist/esm/types/submit.d.ts.map +1 -1
- package/dist/esm/utils/index.d.ts +3 -3
- package/dist/esm/utils/index.d.ts.map +1 -1
- package/dist/esm/utils/index.js +2 -3
- package/dist/esm/utils/index.js.map +1 -1
- package/dist/esm/utils/mapFill.d.ts +1 -1
- package/dist/esm/utils/mapFill.d.ts.map +1 -1
- package/dist/esm/utils/mapFill.js +51 -35
- package/dist/esm/utils/mapFill.js.map +1 -1
- package/dist/esm/utils/mapOpenPositions.d.ts +17 -3
- package/dist/esm/utils/mapOpenPositions.d.ts.map +1 -1
- package/dist/esm/utils/mapOpenPositions.js +31 -5
- package/dist/esm/utils/mapOpenPositions.js.map +1 -1
- package/dist/esm/utils/mapOrder.d.ts +6 -2
- package/dist/esm/utils/mapOrder.d.ts.map +1 -1
- package/dist/esm/utils/mapOrder.js +70 -25
- package/dist/esm/utils/mapOrder.js.map +1 -1
- package/dist/esm/utils/mapPortfolioHistory.d.ts +6 -3
- package/dist/esm/utils/mapPortfolioHistory.d.ts.map +1 -1
- package/dist/esm/utils/mapPortfolioHistory.js +34 -19
- package/dist/esm/utils/mapPortfolioHistory.js.map +1 -1
- package/dist/esm/utils/mapPosition.d.ts +12 -8
- package/dist/esm/utils/mapPosition.d.ts.map +1 -1
- package/dist/esm/utils/mapPosition.js +45 -38
- package/dist/esm/utils/mapPosition.js.map +1 -1
- package/dist/esm/utils/rowTimestamp.d.ts +6 -0
- package/dist/esm/utils/rowTimestamp.d.ts.map +1 -0
- package/dist/esm/utils/rowTimestamp.js +14 -0
- package/dist/esm/utils/rowTimestamp.js.map +1 -0
- package/dist/esm/utils/settlementPool.d.ts +2 -3
- package/dist/esm/utils/settlementPool.d.ts.map +1 -1
- package/dist/esm/utils/settlementPool.js +8 -7
- package/dist/esm/utils/settlementPool.js.map +1 -1
- package/dist/esm/utils/spotPrice.d.ts +3 -4
- package/dist/esm/utils/spotPrice.d.ts.map +1 -1
- package/dist/esm/utils/spotPrice.js +6 -8
- package/dist/esm/utils/spotPrice.js.map +1 -1
- package/dist/esm/utils/time.d.ts +10 -2
- package/dist/esm/utils/time.d.ts.map +1 -1
- package/dist/esm/utils/time.js +13 -4
- package/dist/esm/utils/time.js.map +1 -1
- package/dist/esm/utils/transferMargin.d.ts.map +1 -1
- package/dist/esm/utils/transferMargin.js +8 -13
- package/dist/esm/utils/transferMargin.js.map +1 -1
- package/dist/esm/utils/withdrawableBalances.d.ts +5 -3
- package/dist/esm/utils/withdrawableBalances.d.ts.map +1 -1
- package/dist/esm/utils/withdrawableBalances.js +17 -17
- package/dist/esm/utils/withdrawableBalances.js.map +1 -1
- package/dist/esm/utils/withdrawalTypes.d.ts +45 -0
- package/dist/esm/utils/withdrawalTypes.d.ts.map +1 -0
- package/dist/esm/utils/withdrawalTypes.js +68 -0
- package/dist/esm/utils/withdrawalTypes.js.map +1 -0
- package/dist/esm/websocket/LighterWsProvider.d.ts.map +1 -1
- package/dist/esm/websocket/LighterWsProvider.js +48 -57
- package/dist/esm/websocket/LighterWsProvider.js.map +1 -1
- package/dist/esm/websocket/orderBookSide.d.ts +33 -0
- package/dist/esm/websocket/orderBookSide.d.ts.map +1 -0
- package/dist/esm/websocket/orderBookSide.js +76 -0
- package/dist/esm/websocket/orderBookSide.js.map +1 -0
- package/dist/types/LighterProvider.d.ts.map +1 -1
- package/dist/types/accountSummary.d.ts +1 -2
- package/dist/types/accountSummary.d.ts.map +1 -1
- package/dist/types/availableToTrade.d.ts +1 -2
- package/dist/types/availableToTrade.d.ts.map +1 -1
- package/dist/types/constants.d.ts +8 -0
- package/dist/types/constants.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/signers/LighterSigner.d.ts.map +1 -1
- package/dist/types/types/submit.d.ts +14 -0
- package/dist/types/types/submit.d.ts.map +1 -1
- package/dist/types/utils/index.d.ts +3 -3
- package/dist/types/utils/index.d.ts.map +1 -1
- package/dist/types/utils/mapFill.d.ts +1 -1
- package/dist/types/utils/mapFill.d.ts.map +1 -1
- package/dist/types/utils/mapOpenPositions.d.ts +17 -3
- package/dist/types/utils/mapOpenPositions.d.ts.map +1 -1
- package/dist/types/utils/mapOrder.d.ts +6 -2
- package/dist/types/utils/mapOrder.d.ts.map +1 -1
- package/dist/types/utils/mapPortfolioHistory.d.ts +6 -3
- package/dist/types/utils/mapPortfolioHistory.d.ts.map +1 -1
- package/dist/types/utils/mapPosition.d.ts +12 -8
- package/dist/types/utils/mapPosition.d.ts.map +1 -1
- package/dist/types/utils/rowTimestamp.d.ts +6 -0
- package/dist/types/utils/rowTimestamp.d.ts.map +1 -0
- package/dist/types/utils/settlementPool.d.ts +2 -3
- package/dist/types/utils/settlementPool.d.ts.map +1 -1
- package/dist/types/utils/spotPrice.d.ts +3 -4
- package/dist/types/utils/spotPrice.d.ts.map +1 -1
- package/dist/types/utils/time.d.ts +10 -2
- package/dist/types/utils/time.d.ts.map +1 -1
- package/dist/types/utils/transferMargin.d.ts.map +1 -1
- package/dist/types/utils/withdrawableBalances.d.ts +5 -3
- package/dist/types/utils/withdrawableBalances.d.ts.map +1 -1
- package/dist/types/utils/withdrawalTypes.d.ts +45 -0
- package/dist/types/utils/withdrawalTypes.d.ts.map +1 -0
- package/dist/types/websocket/LighterWsProvider.d.ts.map +1 -1
- package/dist/types/websocket/orderBookSide.d.ts +33 -0
- package/dist/types/websocket/orderBookSide.d.ts.map +1 -0
- package/package.json +3 -3
- package/src/LighterProvider.ts +236 -100
- package/src/accountSummary.ts +41 -22
- package/src/availableToTrade.ts +38 -15
- package/src/constants.ts +9 -0
- package/src/index.ts +1 -0
- package/src/signers/LighterSigner.ts +11 -4
- package/src/types/submit.ts +15 -0
- package/src/utils/index.ts +9 -3
- package/src/utils/mapFill.ts +82 -43
- package/src/utils/mapOpenPositions.ts +45 -6
- package/src/utils/mapOrder.ts +99 -28
- package/src/utils/mapPortfolioHistory.ts +78 -24
- package/src/utils/mapPosition.ts +67 -44
- package/src/utils/rowTimestamp.ts +15 -0
- package/src/utils/settlementPool.ts +36 -12
- package/src/utils/spotPrice.ts +18 -12
- package/src/utils/time.ts +14 -4
- package/src/utils/transferMargin.ts +28 -17
- package/src/utils/withdrawableBalances.ts +34 -20
- package/src/utils/withdrawalTypes.ts +125 -0
- package/src/websocket/LighterWsProvider.ts +75 -92
- package/src/websocket/orderBookSide.ts +106 -0
- package/dist/cjs/utils/decimal.d.ts +0 -5
- package/dist/cjs/utils/decimal.d.ts.map +0 -1
- package/dist/cjs/utils/decimal.js +0 -38
- package/dist/cjs/utils/decimal.js.map +0 -1
- package/dist/cjs/utils/liquidation.d.ts +0 -4
- package/dist/cjs/utils/liquidation.d.ts.map +0 -1
- package/dist/cjs/utils/liquidation.js +0 -16
- package/dist/cjs/utils/liquidation.js.map +0 -1
- package/dist/esm/utils/decimal.d.ts +0 -15
- package/dist/esm/utils/decimal.d.ts.map +0 -1
- package/dist/esm/utils/decimal.js +0 -39
- package/dist/esm/utils/decimal.js.map +0 -1
- package/dist/esm/utils/liquidation.d.ts +0 -22
- package/dist/esm/utils/liquidation.d.ts.map +0 -1
- package/dist/esm/utils/liquidation.js +0 -31
- package/dist/esm/utils/liquidation.js.map +0 -1
- package/dist/types/utils/decimal.d.ts +0 -15
- package/dist/types/utils/decimal.d.ts.map +0 -1
- package/dist/types/utils/liquidation.d.ts +0 -22
- package/dist/types/utils/liquidation.d.ts.map +0 -1
- package/src/utils/decimal.ts +0 -52
- package/src/utils/liquidation.ts +0 -39
|
@@ -1,31 +1,40 @@
|
|
|
1
1
|
import {
|
|
2
|
+
addDecimalString,
|
|
3
|
+
isDecimalString,
|
|
4
|
+
isDecimalStringGreaterThan,
|
|
2
5
|
PerpsError,
|
|
3
6
|
positionSupportsMarginAdjustment,
|
|
4
7
|
positionSupportsMarginRemoval,
|
|
8
|
+
roundDecimalString,
|
|
9
|
+
subtractDecimalString,
|
|
5
10
|
} from '@lifi/perps-sdk'
|
|
6
11
|
import {
|
|
7
12
|
type DecimalString,
|
|
8
13
|
PerpsErrorCode,
|
|
9
14
|
type Position,
|
|
10
15
|
} from '@lifi/perps-types'
|
|
11
|
-
import Big from 'big.js'
|
|
12
16
|
|
|
13
17
|
const AMOUNT_DECIMALS = 6
|
|
14
18
|
|
|
15
|
-
function positionAmount(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
function positionAmount(
|
|
20
|
+
value: DecimalString | undefined,
|
|
21
|
+
field: string
|
|
22
|
+
): DecimalString {
|
|
23
|
+
if (!isDecimalString(value)) {
|
|
19
24
|
throw new PerpsError(
|
|
20
25
|
PerpsErrorCode.ValidationError,
|
|
21
|
-
`Invalid
|
|
26
|
+
`Invalid \`Position.${field}\`: '${value}' is not a decimal string.`
|
|
22
27
|
)
|
|
23
28
|
}
|
|
29
|
+
return value
|
|
24
30
|
}
|
|
25
31
|
|
|
26
|
-
function positivePositionAmount(
|
|
32
|
+
function positivePositionAmount(
|
|
33
|
+
value: DecimalString | undefined,
|
|
34
|
+
field: string
|
|
35
|
+
): DecimalString {
|
|
27
36
|
const amount = positionAmount(value, field)
|
|
28
|
-
if (amount
|
|
37
|
+
if (!isDecimalStringGreaterThan(amount, '0')) {
|
|
29
38
|
throw new PerpsError(
|
|
30
39
|
PerpsErrorCode.ValidationError,
|
|
31
40
|
`Position.${field} must be greater than zero.`
|
|
@@ -57,16 +66,18 @@ export function positionRemovableMargin(
|
|
|
57
66
|
if (!positionSupportsMarginRemoval(position)) {
|
|
58
67
|
return '0'
|
|
59
68
|
}
|
|
60
|
-
const removable =
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
69
|
+
const removable = subtractDecimalString(
|
|
70
|
+
addDecimalString(
|
|
71
|
+
positivePositionAmount(position.marginUsed, 'marginUsed'),
|
|
72
|
+
positionAmount(position.unrealizedPnl, 'unrealizedPnl')
|
|
73
|
+
),
|
|
74
|
+
positivePositionAmount(
|
|
75
|
+
position.initialMarginRequirement,
|
|
76
|
+
'initialMarginRequirement'
|
|
67
77
|
)
|
|
68
|
-
|
|
78
|
+
)
|
|
79
|
+
if (!isDecimalStringGreaterThan(removable, '0')) {
|
|
69
80
|
return '0'
|
|
70
81
|
}
|
|
71
|
-
return removable
|
|
82
|
+
return roundDecimalString(removable, AMOUNT_DECIMALS, 'truncate')
|
|
72
83
|
}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
calculateTransferable,
|
|
3
3
|
calculateWithdrawMax,
|
|
4
|
+
isDecimalStringGreaterThan,
|
|
4
5
|
type ProviderWithdrawableBalance,
|
|
6
|
+
subtractDecimalString,
|
|
7
|
+
unknownToDecimalString,
|
|
5
8
|
} from '@lifi/perps-sdk'
|
|
6
|
-
import
|
|
9
|
+
import { LIGHTER_PROVIDER_KEY, LIGHTER_SPOT_CATEGORY_ID } from '../constants.js'
|
|
7
10
|
import type { LtAccount } from '../types/account.js'
|
|
8
|
-
import { toRequiredBig } from './decimal.js'
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
|
-
* Split each held asset into the two
|
|
12
|
-
* spot draws on `balance` net of `locked_balance`, perps draws on
|
|
13
|
+
* Split each held asset into the two categories a Lighter withdrawal can
|
|
14
|
+
* name: spot draws on `balance` net of `locked_balance`, perps draws on
|
|
13
15
|
* `margin_balance`. The settlement asset's perps route is also capped by the
|
|
14
16
|
* account `available_balance`, which excludes the margin open positions use.
|
|
15
17
|
* Every other asset's perps route reports its full `margin_balance`, uncapped,
|
|
@@ -20,42 +22,54 @@ import { toRequiredBig } from './decimal.js'
|
|
|
20
22
|
*
|
|
21
23
|
* @param settlementAssetIndex - L2 asset index of the deployment's collateral
|
|
22
24
|
* asset, the only asset that `available_balance` is denominated in.
|
|
25
|
+
* @param perpsCategoryId - The instance's perps category id, the
|
|
26
|
+
* `categoryId` its collateral `Balance` rows carry.
|
|
23
27
|
* @public
|
|
24
28
|
*/
|
|
25
29
|
export const lighterWithdrawableBalances = (
|
|
26
30
|
account: Pick<LtAccount, 'assets' | 'available_balance'>,
|
|
27
|
-
settlementAssetIndex: number
|
|
31
|
+
settlementAssetIndex: number,
|
|
32
|
+
perpsCategoryId: string
|
|
28
33
|
): ProviderWithdrawableBalance[] => {
|
|
29
34
|
const rows: ProviderWithdrawableBalance[] = []
|
|
30
35
|
for (const asset of account.assets) {
|
|
31
36
|
const assetId = String(asset.asset_id)
|
|
32
|
-
const spot =
|
|
33
|
-
|
|
37
|
+
const spot = subtractDecimalString(
|
|
38
|
+
unknownToDecimalString(asset.balance, 'balance', LIGHTER_PROVIDER_KEY),
|
|
39
|
+
unknownToDecimalString(
|
|
40
|
+
asset.locked_balance,
|
|
41
|
+
'locked_balance',
|
|
42
|
+
LIGHTER_PROVIDER_KEY
|
|
43
|
+
)
|
|
34
44
|
)
|
|
35
|
-
if (spot
|
|
36
|
-
const available = spot.toFixed()
|
|
45
|
+
if (isDecimalStringGreaterThan(spot, '0')) {
|
|
37
46
|
rows.push({
|
|
38
47
|
assetId,
|
|
39
|
-
|
|
40
|
-
available,
|
|
41
|
-
max: calculateWithdrawMax({ available }),
|
|
48
|
+
categoryId: LIGHTER_SPOT_CATEGORY_ID,
|
|
49
|
+
available: spot,
|
|
50
|
+
max: calculateWithdrawMax({ available: spot }),
|
|
42
51
|
})
|
|
43
52
|
}
|
|
44
|
-
const marginBalance =
|
|
53
|
+
const marginBalance = unknownToDecimalString(
|
|
54
|
+
asset.margin_balance,
|
|
55
|
+
'margin_balance',
|
|
56
|
+
LIGHTER_PROVIDER_KEY
|
|
57
|
+
)
|
|
45
58
|
const perps =
|
|
46
59
|
asset.asset_id === settlementAssetIndex
|
|
47
60
|
? calculateTransferable(
|
|
48
|
-
|
|
61
|
+
unknownToDecimalString(
|
|
49
62
|
account.available_balance,
|
|
50
|
-
'available_balance'
|
|
51
|
-
|
|
52
|
-
|
|
63
|
+
'available_balance',
|
|
64
|
+
LIGHTER_PROVIDER_KEY
|
|
65
|
+
),
|
|
66
|
+
marginBalance
|
|
53
67
|
)
|
|
54
|
-
: marginBalance
|
|
55
|
-
if (
|
|
68
|
+
: marginBalance
|
|
69
|
+
if (isDecimalStringGreaterThan(perps, '0')) {
|
|
56
70
|
rows.push({
|
|
57
71
|
assetId,
|
|
58
|
-
|
|
72
|
+
categoryId: perpsCategoryId,
|
|
59
73
|
available: perps,
|
|
60
74
|
max: calculateWithdrawMax({ available: perps }),
|
|
61
75
|
})
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import {
|
|
2
|
+
divideDecimalString,
|
|
3
|
+
isDecimalStringGreaterThan,
|
|
4
|
+
type ProviderWithdrawableBalance,
|
|
5
|
+
unknownToDecimalString,
|
|
6
|
+
type WithdrawalAssetRef,
|
|
7
|
+
type WithdrawalSourceTypes,
|
|
8
|
+
type WithdrawalTypeOption,
|
|
9
|
+
} from '@lifi/perps-sdk'
|
|
10
|
+
import { WithdrawalType } from '@lifi/perps-types'
|
|
11
|
+
import { LIGHTER_PROVIDER_KEY } from '../constants.js'
|
|
12
|
+
import type {
|
|
13
|
+
LtFastwithdrawInfoResponse,
|
|
14
|
+
LtTransferFeeInfoResponse,
|
|
15
|
+
} from '../types/submit.js'
|
|
16
|
+
|
|
17
|
+
const LIGHTER_SUCCESS_CODE = 200
|
|
18
|
+
const L2_COLLATERAL_SCALE = '1000000'
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The `withdrawalOptions` a Lighter withdrawal accepts. `fast` sends the
|
|
22
|
+
* amount to the fast-withdraw operator account `toAccountIndex`; `fee` is the
|
|
23
|
+
* transfer fee in L2 6-decimal integer units.
|
|
24
|
+
*
|
|
25
|
+
* @public
|
|
26
|
+
*/
|
|
27
|
+
export type LighterWithdrawalOptions =
|
|
28
|
+
| { mode: 'standard' }
|
|
29
|
+
| { mode: 'fast'; toAccountIndex: number; fee: number }
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The fast-withdraw terms Lighter offers an account.
|
|
33
|
+
*
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
export interface LighterFastWithdrawal {
|
|
37
|
+
toAccountIndex: number
|
|
38
|
+
fee: number
|
|
39
|
+
/** The lower of `withdraw_limit` and `max_withdrawal_amount`, in collateral units. */
|
|
40
|
+
limit: string
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The fast-withdraw terms from `/fastwithdraw/info` and `/transferFeeInfo`, or
|
|
45
|
+
* `undefined` when either read reports a code other than 200 or no operator
|
|
46
|
+
* account is set.
|
|
47
|
+
*
|
|
48
|
+
* @throws {PerpsError} When a limit is not a decimal.
|
|
49
|
+
* @public
|
|
50
|
+
*/
|
|
51
|
+
export const lighterFastWithdrawal = (
|
|
52
|
+
info: LtFastwithdrawInfoResponse,
|
|
53
|
+
feeInfo: LtTransferFeeInfoResponse
|
|
54
|
+
): LighterFastWithdrawal | undefined => {
|
|
55
|
+
if (
|
|
56
|
+
info.code !== LIGHTER_SUCCESS_CODE ||
|
|
57
|
+
feeInfo.code !== LIGHTER_SUCCESS_CODE ||
|
|
58
|
+
!(info.to_account_index > 0)
|
|
59
|
+
) {
|
|
60
|
+
return undefined
|
|
61
|
+
}
|
|
62
|
+
const withdrawLimit = unknownToDecimalString(
|
|
63
|
+
info.withdraw_limit,
|
|
64
|
+
'withdraw_limit',
|
|
65
|
+
LIGHTER_PROVIDER_KEY
|
|
66
|
+
)
|
|
67
|
+
const maxWithdrawalAmount = unknownToDecimalString(
|
|
68
|
+
info.max_withdrawal_amount,
|
|
69
|
+
'max_withdrawal_amount',
|
|
70
|
+
LIGHTER_PROVIDER_KEY
|
|
71
|
+
)
|
|
72
|
+
const limit = isDecimalStringGreaterThan(withdrawLimit, maxWithdrawalAmount)
|
|
73
|
+
? maxWithdrawalAmount
|
|
74
|
+
: withdrawLimit
|
|
75
|
+
return {
|
|
76
|
+
toAccountIndex: info.to_account_index,
|
|
77
|
+
fee: feeInfo.transfer_fee_usdc,
|
|
78
|
+
limit: divideDecimalString(limit, L2_COLLATERAL_SCALE),
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* The withdrawal types per withdrawable row. Every row offers `STANDARD` up to
|
|
84
|
+
* its `max`. The `fastSource` row also offers `FAST` when `fast` is set, up to
|
|
85
|
+
* the lower of its `max` and `fast.limit`.
|
|
86
|
+
*
|
|
87
|
+
* @public
|
|
88
|
+
*/
|
|
89
|
+
export const lighterWithdrawalTypes = (
|
|
90
|
+
rows: ProviderWithdrawableBalance[],
|
|
91
|
+
fastSource: WithdrawalAssetRef,
|
|
92
|
+
fast: LighterFastWithdrawal | undefined
|
|
93
|
+
): WithdrawalSourceTypes[] =>
|
|
94
|
+
rows.map((row) => {
|
|
95
|
+
const standard: LighterWithdrawalOptions = { mode: 'standard' }
|
|
96
|
+
const options: WithdrawalTypeOption[] = [
|
|
97
|
+
{
|
|
98
|
+
type: WithdrawalType.STANDARD,
|
|
99
|
+
max: row.max,
|
|
100
|
+
withdrawalOptions: standard,
|
|
101
|
+
},
|
|
102
|
+
]
|
|
103
|
+
if (
|
|
104
|
+
fast !== undefined &&
|
|
105
|
+
row.categoryId === fastSource.categoryId &&
|
|
106
|
+
row.assetId === fastSource.asset.id
|
|
107
|
+
) {
|
|
108
|
+
const fastOptions: LighterWithdrawalOptions = {
|
|
109
|
+
mode: 'fast',
|
|
110
|
+
toAccountIndex: fast.toAccountIndex,
|
|
111
|
+
fee: fast.fee,
|
|
112
|
+
}
|
|
113
|
+
options.push({
|
|
114
|
+
type: WithdrawalType.FAST,
|
|
115
|
+
max: isDecimalStringGreaterThan(row.max, fast.limit)
|
|
116
|
+
? fast.limit
|
|
117
|
+
: row.max,
|
|
118
|
+
withdrawalOptions: fastOptions,
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
source: { categoryId: row.categoryId, asset: { id: row.assetId } },
|
|
123
|
+
options,
|
|
124
|
+
}
|
|
125
|
+
})
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
+
addDecimalString,
|
|
2
3
|
cachePromise,
|
|
3
4
|
getMarketRegistry,
|
|
5
|
+
isDecimalStringGreaterThan,
|
|
4
6
|
type MarketRegistry,
|
|
5
7
|
PerpsError,
|
|
6
8
|
type PerpsProvider,
|
|
@@ -10,7 +12,9 @@ import {
|
|
|
10
12
|
ReconnectingWebSocket,
|
|
11
13
|
resolveRetryPolicy,
|
|
12
14
|
resolveSubscribeQuote,
|
|
15
|
+
subtractDecimalString,
|
|
13
16
|
toPerpsMarketDisplay,
|
|
17
|
+
unknownToDecimalString,
|
|
14
18
|
WsProviderBase,
|
|
15
19
|
type WsProviderFactory,
|
|
16
20
|
type WsProviderFactoryParams,
|
|
@@ -24,7 +28,6 @@ import {
|
|
|
24
28
|
type Position,
|
|
25
29
|
type Subscription,
|
|
26
30
|
} from '@lifi/perps-types'
|
|
27
|
-
import Big from 'big.js'
|
|
28
31
|
import type { Address } from 'viem'
|
|
29
32
|
import { lighterPortfolioValue } from '../accountSummary.js'
|
|
30
33
|
import {
|
|
@@ -48,7 +51,6 @@ import type {
|
|
|
48
51
|
LtWsMarketStats,
|
|
49
52
|
LtWsMarketStatsAllMessage,
|
|
50
53
|
LtWsMessage,
|
|
51
|
-
LtWsOrderBook,
|
|
52
54
|
LtWsOrderBookMessage,
|
|
53
55
|
LtWsSpotMarketStats,
|
|
54
56
|
LtWsSpotMarketStatsAllMessage,
|
|
@@ -58,13 +60,14 @@ import type {
|
|
|
58
60
|
import { LIGHTER_RETRY_DEFAULTS, LighterApiClient } from '../utils/apiClient.js'
|
|
59
61
|
import {
|
|
60
62
|
fetchDetailedAccount,
|
|
63
|
+
isOpenPosition,
|
|
61
64
|
mapFill,
|
|
62
65
|
mapMarketContext,
|
|
63
66
|
mapOrderUpdates,
|
|
64
67
|
mapPosition,
|
|
65
|
-
toRequiredBig,
|
|
66
68
|
} from '../utils/index.js'
|
|
67
69
|
import { spotPriceByAssetId, spotValuation } from '../utils/spotPrice.js'
|
|
70
|
+
import { askOrder, bidOrder, OrderBookSide } from './orderBookSide.js'
|
|
68
71
|
|
|
69
72
|
// Public channels: `marketsContext` (market_stats/all + spot_market_stats/all),
|
|
70
73
|
// `marketContext` (market_stats/N or spot_market_stats/N), `orderbook`
|
|
@@ -139,26 +142,16 @@ interface SubState {
|
|
|
139
142
|
needsAuth: boolean
|
|
140
143
|
}
|
|
141
144
|
|
|
142
|
-
/**
|
|
143
|
-
* A maintained book level, keyed in {@link OrderbookState} by its price string.
|
|
144
|
-
* `priceNum` is the price parsed once on insert so the emit-time sort orders by
|
|
145
|
-
* a cached number instead of re-parsing every price on every comparison.
|
|
146
|
-
*/
|
|
147
|
-
interface BookLevel {
|
|
148
|
-
size: string
|
|
149
|
-
priceNum: number
|
|
150
|
-
}
|
|
151
|
-
|
|
152
145
|
/** Settlement equity and per-asset route quantities for account valuation. */
|
|
153
146
|
interface AccountSummaryInputs {
|
|
154
|
-
perps?: { equity:
|
|
155
|
-
balances?: Map<number, { spot:
|
|
147
|
+
perps?: { equity: string } & Omit<AccountSummary, 'portfolioValue'>
|
|
148
|
+
balances?: Map<number, { spot: string; margin: string }>
|
|
156
149
|
lastPortfolioValue?: string
|
|
157
150
|
}
|
|
158
151
|
|
|
159
152
|
interface OrderbookState {
|
|
160
|
-
bids:
|
|
161
|
-
asks:
|
|
153
|
+
bids: OrderBookSide
|
|
154
|
+
asks: OrderBookSide
|
|
162
155
|
assetId: string
|
|
163
156
|
}
|
|
164
157
|
|
|
@@ -730,38 +723,47 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
|
|
|
730
723
|
return
|
|
731
724
|
}
|
|
732
725
|
|
|
733
|
-
const portfolio =
|
|
726
|
+
const portfolio = unknownToDecimalString(
|
|
734
727
|
stats.portfolio_value,
|
|
735
|
-
'stats.portfolio_value'
|
|
728
|
+
'stats.portfolio_value',
|
|
729
|
+
this.providerKey
|
|
730
|
+
)
|
|
731
|
+
const collateral = unknownToDecimalString(
|
|
732
|
+
stats.collateral,
|
|
733
|
+
'stats.collateral',
|
|
734
|
+
this.providerKey
|
|
736
735
|
)
|
|
737
|
-
const collateral = toRequiredBig(stats.collateral, 'stats.collateral')
|
|
738
736
|
|
|
739
|
-
let available:
|
|
740
|
-
let marginUsed:
|
|
737
|
+
let available: string
|
|
738
|
+
let marginUsed: string
|
|
741
739
|
if (stats.cross_stats === undefined) {
|
|
742
740
|
// Compatibility with legacy gateways that omitted the entire
|
|
743
741
|
// cross_stats object.
|
|
744
|
-
available =
|
|
742
|
+
available = unknownToDecimalString(
|
|
745
743
|
stats.available_balance,
|
|
746
|
-
'stats.available_balance'
|
|
744
|
+
'stats.available_balance',
|
|
745
|
+
this.providerKey
|
|
747
746
|
)
|
|
748
|
-
marginUsed = portfolio
|
|
747
|
+
marginUsed = subtractDecimalString(portfolio, available)
|
|
749
748
|
} else {
|
|
750
|
-
const crossCollateral =
|
|
749
|
+
const crossCollateral = unknownToDecimalString(
|
|
751
750
|
stats.cross_stats.collateral,
|
|
752
|
-
'stats.cross_stats.collateral'
|
|
751
|
+
'stats.cross_stats.collateral',
|
|
752
|
+
this.providerKey
|
|
753
753
|
)
|
|
754
|
-
const crossPortfolio =
|
|
754
|
+
const crossPortfolio = unknownToDecimalString(
|
|
755
755
|
stats.cross_stats.portfolio_value,
|
|
756
|
-
'stats.cross_stats.portfolio_value'
|
|
756
|
+
'stats.cross_stats.portfolio_value',
|
|
757
|
+
this.providerKey
|
|
757
758
|
)
|
|
758
|
-
available =
|
|
759
|
+
available = unknownToDecimalString(
|
|
759
760
|
stats.cross_stats.available_balance,
|
|
760
|
-
'stats.cross_stats.available_balance'
|
|
761
|
+
'stats.cross_stats.available_balance',
|
|
762
|
+
this.providerKey
|
|
761
763
|
)
|
|
762
|
-
const isolatedMargin = collateral
|
|
763
|
-
const crossMargin = crossPortfolio
|
|
764
|
-
marginUsed = isolatedMargin
|
|
764
|
+
const isolatedMargin = subtractDecimalString(collateral, crossCollateral)
|
|
765
|
+
const crossMargin = subtractDecimalString(crossPortfolio, available)
|
|
766
|
+
marginUsed = addDecimalString(isolatedMargin, crossMargin)
|
|
765
767
|
}
|
|
766
768
|
|
|
767
769
|
const inputs = this.accountSummaryInputs.get(address)
|
|
@@ -770,9 +772,9 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
|
|
|
770
772
|
}
|
|
771
773
|
inputs.perps = {
|
|
772
774
|
equity: portfolio,
|
|
773
|
-
availableMargin: available
|
|
774
|
-
marginUsed
|
|
775
|
-
unrealizedPnl: portfolio
|
|
775
|
+
availableMargin: available,
|
|
776
|
+
marginUsed,
|
|
777
|
+
unrealizedPnl: subtractDecimalString(portfolio, collateral),
|
|
776
778
|
}
|
|
777
779
|
this.emitAccountSummary(address)
|
|
778
780
|
}
|
|
@@ -793,14 +795,18 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
|
|
|
793
795
|
}
|
|
794
796
|
const parsed = Object.values(msg.assets ?? {}).map((asset) => ({
|
|
795
797
|
assetId: asset.asset_id,
|
|
796
|
-
spot:
|
|
798
|
+
spot: unknownToDecimalString(asset.balance, 'balance', this.providerKey),
|
|
797
799
|
margin:
|
|
798
800
|
asset.margin_balance === undefined
|
|
799
801
|
? undefined
|
|
800
|
-
:
|
|
802
|
+
: unknownToDecimalString(
|
|
803
|
+
asset.margin_balance,
|
|
804
|
+
'margin_balance',
|
|
805
|
+
this.providerKey
|
|
806
|
+
),
|
|
801
807
|
}))
|
|
802
808
|
const balances = isSnapshot
|
|
803
|
-
? new Map<number, { spot:
|
|
809
|
+
? new Map<number, { spot: string; margin: string }>()
|
|
804
810
|
: inputs.balances
|
|
805
811
|
if (balances === undefined) {
|
|
806
812
|
return
|
|
@@ -808,7 +814,7 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
|
|
|
808
814
|
for (const { assetId, spot, margin } of parsed) {
|
|
809
815
|
balances.set(assetId, {
|
|
810
816
|
spot,
|
|
811
|
-
margin: margin ?? balances.get(assetId)?.margin ??
|
|
817
|
+
margin: margin ?? balances.get(assetId)?.margin ?? '0',
|
|
812
818
|
})
|
|
813
819
|
}
|
|
814
820
|
inputs.balances = balances
|
|
@@ -827,10 +833,12 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
|
|
|
827
833
|
([assetId, { spot, margin }]) =>
|
|
828
834
|
[
|
|
829
835
|
assetId,
|
|
830
|
-
assetId === settlementAssetIndex
|
|
836
|
+
assetId === settlementAssetIndex
|
|
837
|
+
? spot
|
|
838
|
+
: addDecimalString(spot, margin),
|
|
831
839
|
] as const
|
|
832
840
|
)
|
|
833
|
-
.filter(([, balance]) => balance
|
|
841
|
+
.filter(([, balance]) => isDecimalStringGreaterThan(balance, '0'))
|
|
834
842
|
const spotPrices = spotPriceByAssetId(
|
|
835
843
|
this.registry?.markets ?? [],
|
|
836
844
|
LIGHTER_SPOT_CATEGORY_ID,
|
|
@@ -845,14 +853,10 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
|
|
|
845
853
|
inputs.perps.equity,
|
|
846
854
|
held.map(
|
|
847
855
|
([assetId, balance]) =>
|
|
848
|
-
spotValuation(
|
|
849
|
-
|
|
850
|
-
balance.toFixed(),
|
|
851
|
-
settlementAssetIndex,
|
|
852
|
-
spotPrices
|
|
853
|
-
).valueUsd
|
|
856
|
+
spotValuation(assetId, balance, settlementAssetIndex, spotPrices)
|
|
857
|
+
.valueUsd
|
|
854
858
|
)
|
|
855
|
-
)
|
|
859
|
+
)
|
|
856
860
|
if (onlyOnChange && portfolioValue === inputs.lastPortfolioValue) {
|
|
857
861
|
return
|
|
858
862
|
}
|
|
@@ -887,7 +891,8 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
|
|
|
887
891
|
const raw = collectAuthChannelItems<LtTrade>(msg, 'trades')
|
|
888
892
|
const fills: Fill[] = raw.flatMap((t) => {
|
|
889
893
|
const market = this.registry?.get(String(t.market_id))
|
|
890
|
-
|
|
894
|
+
const mapped = market && mapFill(t, accountIndex, market)
|
|
895
|
+
return mapped ? [mapped] : []
|
|
891
896
|
})
|
|
892
897
|
this.emit(`fills:${address}`, { channel: 'fills', data: fills })
|
|
893
898
|
}
|
|
@@ -910,13 +915,18 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
|
|
|
910
915
|
this.positionsByAddress.set(address, state)
|
|
911
916
|
}
|
|
912
917
|
for (const p of raw) {
|
|
913
|
-
if (
|
|
914
|
-
state.delete(p.market_id)
|
|
915
|
-
} else {
|
|
918
|
+
if (isOpenPosition(p)) {
|
|
916
919
|
const market = this.registry?.get(String(p.market_id))
|
|
917
|
-
|
|
918
|
-
|
|
920
|
+
const position = market
|
|
921
|
+
? mapPosition(p, toPerpsMarketDisplay(market))
|
|
922
|
+
: undefined
|
|
923
|
+
if (position) {
|
|
924
|
+
state.set(p.market_id, position)
|
|
925
|
+
} else {
|
|
926
|
+
state.delete(p.market_id)
|
|
919
927
|
}
|
|
928
|
+
} else {
|
|
929
|
+
state.delete(p.market_id)
|
|
920
930
|
}
|
|
921
931
|
}
|
|
922
932
|
this.emit(`positions:${address}`, {
|
|
@@ -1006,20 +1016,24 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
|
|
|
1006
1016
|
|
|
1007
1017
|
let state = this.orderbooks.get(marketId)
|
|
1008
1018
|
if (!state || isSnapshot) {
|
|
1009
|
-
state = {
|
|
1019
|
+
state = {
|
|
1020
|
+
bids: new OrderBookSide(bidOrder, this.providerKey),
|
|
1021
|
+
asks: new OrderBookSide(askOrder, this.providerKey),
|
|
1022
|
+
assetId,
|
|
1023
|
+
}
|
|
1010
1024
|
this.orderbooks.set(marketId, state)
|
|
1011
1025
|
}
|
|
1012
1026
|
|
|
1013
|
-
|
|
1014
|
-
|
|
1027
|
+
state.bids.apply(msg.order_book.bids)
|
|
1028
|
+
state.asks.apply(msg.order_book.asks)
|
|
1015
1029
|
|
|
1016
1030
|
this.emit(`orderbook:${assetId}`, {
|
|
1017
1031
|
channel: 'orderbook',
|
|
1018
1032
|
data: {
|
|
1019
1033
|
provider: this.providerKey,
|
|
1020
1034
|
marketId: assetId,
|
|
1021
|
-
bids:
|
|
1022
|
-
asks:
|
|
1035
|
+
bids: state.bids.toLevels(),
|
|
1036
|
+
asks: state.asks.toLevels(),
|
|
1023
1037
|
timestamp: Date.now(),
|
|
1024
1038
|
},
|
|
1025
1039
|
})
|
|
@@ -1121,37 +1135,6 @@ function isMarketStatsEntry(
|
|
|
1121
1135
|
return isObject(value) && typeof value.market_id === 'number'
|
|
1122
1136
|
}
|
|
1123
1137
|
|
|
1124
|
-
function applyLevels(
|
|
1125
|
-
book: Map<string, BookLevel>,
|
|
1126
|
-
levels: LtWsOrderBook['bids']
|
|
1127
|
-
): void {
|
|
1128
|
-
for (const level of levels) {
|
|
1129
|
-
if (level.size === '0' || Number(level.size) === 0) {
|
|
1130
|
-
book.delete(level.price)
|
|
1131
|
-
} else {
|
|
1132
|
-
const existing = book.get(level.price)
|
|
1133
|
-
if (existing) {
|
|
1134
|
-
existing.size = level.size
|
|
1135
|
-
} else {
|
|
1136
|
-
book.set(level.price, {
|
|
1137
|
-
size: level.size,
|
|
1138
|
-
priceNum: Number(level.price),
|
|
1139
|
-
})
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
|
-
}
|
|
1143
|
-
}
|
|
1144
|
-
|
|
1145
|
-
function mapToLevels(
|
|
1146
|
-
book: Map<string, BookLevel>,
|
|
1147
|
-
descending: boolean
|
|
1148
|
-
): Array<{ price: string; size: string }> {
|
|
1149
|
-
const entries = [...book].sort(([, a], [, b]) =>
|
|
1150
|
-
descending ? b.priceNum - a.priceNum : a.priceNum - b.priceNum
|
|
1151
|
-
)
|
|
1152
|
-
return entries.map(([price, { size }]) => ({ price, size }))
|
|
1153
|
-
}
|
|
1154
|
-
|
|
1155
1138
|
/**
|
|
1156
1139
|
* Extract items from an auth-channel payload field. The field may be:
|
|
1157
1140
|
* - a flat array (e.g. `trades: []` on the initial subscribed snapshot)
|