@lifi/perps-sdk-provider-lighter 24.0.2 → 25.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/README.md +55 -0
- package/dist/cjs/LighterProvider.d.ts.map +1 -1
- package/dist/cjs/LighterProvider.js +64 -49
- package/dist/cjs/LighterProvider.js.map +1 -1
- package/dist/cjs/accountConfig.d.ts.map +1 -1
- package/dist/cjs/accountConfig.js +1 -7
- package/dist/cjs/accountConfig.js.map +1 -1
- package/dist/cjs/signers/LighterSigner.d.ts.map +1 -1
- package/dist/cjs/signers/LighterSigner.js +2 -1
- package/dist/cjs/signers/LighterSigner.js.map +1 -1
- package/dist/cjs/types/submit.d.ts.map +1 -1
- package/dist/cjs/utils/activityCursor.d.ts.map +1 -1
- package/dist/cjs/utils/activityCursor.js +29 -6
- package/dist/cjs/utils/activityCursor.js.map +1 -1
- package/dist/cjs/utils/index.d.ts +1 -1
- package/dist/cjs/utils/index.d.ts.map +1 -1
- package/dist/cjs/utils/index.js +2 -7
- package/dist/cjs/utils/index.js.map +1 -1
- package/dist/cjs/utils/mapFill.d.ts.map +1 -1
- package/dist/cjs/utils/mapFill.js +0 -1
- package/dist/cjs/utils/mapFill.js.map +1 -1
- package/dist/cjs/utils/mapOrder.d.ts +4 -11
- package/dist/cjs/utils/mapOrder.d.ts.map +1 -1
- package/dist/cjs/utils/mapOrder.js +109 -120
- package/dist/cjs/utils/mapOrder.js.map +1 -1
- package/dist/cjs/websocket/LighterWsProvider.js +1 -1
- package/dist/cjs/websocket/LighterWsProvider.js.map +1 -1
- package/dist/esm/LighterProvider.d.ts.map +1 -1
- package/dist/esm/LighterProvider.js +71 -58
- package/dist/esm/LighterProvider.js.map +1 -1
- package/dist/esm/accountConfig.d.ts.map +1 -1
- package/dist/esm/accountConfig.js +5 -16
- package/dist/esm/accountConfig.js.map +1 -1
- package/dist/esm/signers/LighterSigner.d.ts.map +1 -1
- package/dist/esm/signers/LighterSigner.js +2 -1
- package/dist/esm/signers/LighterSigner.js.map +1 -1
- package/dist/esm/types/submit.d.ts +16 -6
- package/dist/esm/types/submit.d.ts.map +1 -1
- package/dist/esm/utils/activityCursor.d.ts +2 -11
- package/dist/esm/utils/activityCursor.d.ts.map +1 -1
- package/dist/esm/utils/activityCursor.js +35 -7
- package/dist/esm/utils/activityCursor.js.map +1 -1
- package/dist/esm/utils/index.d.ts +1 -1
- package/dist/esm/utils/index.d.ts.map +1 -1
- package/dist/esm/utils/index.js +1 -1
- package/dist/esm/utils/index.js.map +1 -1
- package/dist/esm/utils/mapFill.d.ts.map +1 -1
- package/dist/esm/utils/mapFill.js +1 -2
- package/dist/esm/utils/mapFill.js.map +1 -1
- package/dist/esm/utils/mapOrder.d.ts +6 -68
- package/dist/esm/utils/mapOrder.d.ts.map +1 -1
- package/dist/esm/utils/mapOrder.js +108 -180
- package/dist/esm/utils/mapOrder.js.map +1 -1
- package/dist/esm/websocket/LighterWsProvider.js +2 -2
- package/dist/esm/websocket/LighterWsProvider.js.map +1 -1
- package/dist/types/LighterProvider.d.ts.map +1 -1
- package/dist/types/accountConfig.d.ts.map +1 -1
- package/dist/types/signers/LighterSigner.d.ts.map +1 -1
- package/dist/types/types/submit.d.ts +16 -6
- package/dist/types/types/submit.d.ts.map +1 -1
- package/dist/types/utils/activityCursor.d.ts +2 -11
- package/dist/types/utils/activityCursor.d.ts.map +1 -1
- package/dist/types/utils/index.d.ts +1 -1
- package/dist/types/utils/index.d.ts.map +1 -1
- package/dist/types/utils/mapFill.d.ts.map +1 -1
- package/dist/types/utils/mapOrder.d.ts +6 -68
- package/dist/types/utils/mapOrder.d.ts.map +1 -1
- package/dist/wasm/lighter-signer.wasm +0 -0
- package/package.json +3 -3
- package/src/LighterProvider.ts +79 -91
- package/src/accountConfig.ts +5 -18
- package/src/signers/LighterSigner.ts +2 -0
- package/src/types/submit.ts +16 -6
- package/src/utils/activityCursor.ts +50 -18
- package/src/utils/index.ts +1 -9
- package/src/utils/mapFill.ts +1 -7
- package/src/utils/mapOrder.ts +127 -207
- package/src/websocket/LighterWsProvider.ts +2 -2
- package/dist/cjs/utils/mapTwap.d.ts +0 -4
- package/dist/cjs/utils/mapTwap.d.ts.map +0 -1
- package/dist/cjs/utils/mapTwap.js +0 -31
- package/dist/cjs/utils/mapTwap.js.map +0 -1
- package/dist/esm/utils/mapTwap.d.ts +0 -5
- package/dist/esm/utils/mapTwap.d.ts.map +0 -1
- package/dist/esm/utils/mapTwap.js +0 -25
- package/dist/esm/utils/mapTwap.js.map +0 -1
- package/dist/types/utils/mapTwap.d.ts +0 -5
- package/dist/types/utils/mapTwap.d.ts.map +0 -1
- package/src/utils/mapTwap.ts +0 -31
|
@@ -1,72 +1,10 @@
|
|
|
1
|
-
import type { MarketDisplay,
|
|
2
|
-
import { OrderType } from '@lifi/perps-types';
|
|
1
|
+
import type { MarketDisplay, Order } from '@lifi/perps-types';
|
|
3
2
|
import type { LtOrder } from '../types/index.js';
|
|
4
|
-
/**
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
*/
|
|
10
|
-
export declare const mapStatusReason: (status: string) => string | undefined;
|
|
11
|
-
/**
|
|
12
|
-
* True for order types Lighter exposes as TP/SL legs. Mirrors the
|
|
13
|
-
* Hyperliquid helper of the same name so the backend can split a raw
|
|
14
|
-
* Lighter order list into the same `openOrders` / `triggerOrders`
|
|
15
|
-
* buckets the SDK declares on `OrdersResponse`.
|
|
16
|
-
* @public
|
|
17
|
-
*/
|
|
18
|
-
export declare const isTriggerType: (type: OrderType) => boolean;
|
|
19
|
-
/**
|
|
20
|
-
* Decide whether a raw Lighter order belongs in the cross-provider
|
|
21
|
-
* `triggerOrders` bucket. Single source of truth for both the REST
|
|
22
|
-
* `getOrders` path and the `account_all_orders` WS handler.
|
|
23
|
-
*
|
|
24
|
-
* Authoritative signals, in order:
|
|
25
|
-
* 1. `trigger_status` — Lighter's own enum. `'ready' | 'mark-price' |
|
|
26
|
-
* 'parent-order'` all mean "this order has trigger semantics" (TP/SL
|
|
27
|
-
* waiting on price, or a TP/SL leg of a parent placeOrder). `'twap'`
|
|
28
|
-
* is intentionally excluded — TWAP child orders are scheduled resting
|
|
29
|
-
* limits, not TP/SL triggers. `'na'` is "regular order".
|
|
30
|
-
* 2. `trigger_price > 0` — catches cases where `trigger_status`
|
|
31
|
-
* momentarily lags during state transitions (e.g. right after an OCO
|
|
32
|
-
* sibling cancels).
|
|
33
|
-
* 3. `type` — final fallback via the mapped `OrderType`.
|
|
34
|
-
* @public
|
|
35
|
-
*/
|
|
36
|
-
export declare const isTriggerOrder: (raw: LtOrder) => boolean;
|
|
37
|
-
/**
|
|
38
|
-
* Map a raw Lighter trigger order (stop/take-profit, market or limit) to
|
|
39
|
-
* the generic `TriggerOrder` shape. For market variants the `limitPrice`
|
|
40
|
-
* field is omitted; for limit variants `order.price` is the limit and
|
|
41
|
-
* `order.trigger_price` is the activation level.
|
|
42
|
-
* @public
|
|
43
|
-
*/
|
|
44
|
-
export declare const mapTriggerOrder: (order: LtOrder, market: MarketDisplay) => TriggerOrder;
|
|
45
|
-
/**
|
|
46
|
-
* Map a raw Lighter order to the generic OpenOrder type.
|
|
47
|
-
* @param market - Backend-resolved market identity for `order.market_index`.
|
|
48
|
-
* @public
|
|
49
|
-
*/
|
|
50
|
-
export declare const mapOrder: (order: LtOrder, market: MarketDisplay) => OpenOrder;
|
|
51
|
-
/**
|
|
52
|
-
* Walk a flat list of raw Lighter orders and bucket each into the
|
|
53
|
-
* `OpenOrder` / `TriggerOrder` arrays the cross-provider `OrdersResponse`
|
|
54
|
-
* declares, plus a `terminated` list of orderIds whose status has reached
|
|
55
|
-
* a terminal state (filled / cancelled / rejected / expired) — consumers
|
|
56
|
-
* applying WS deltas evict those from the cached buckets. REST callers
|
|
57
|
-
* see `terminated: []` because `accountActiveOrders` returns active only.
|
|
58
|
-
* An order whose market the resolver does not know is skipped.
|
|
59
|
-
* @public
|
|
60
|
-
*/
|
|
61
|
-
export declare const classifyAndMapOrders: (orders: LtOrder[], resolveMarket: (marketIndex: number) => MarketDisplay | undefined) => {
|
|
62
|
-
openOrders: OpenOrder[];
|
|
63
|
-
triggerOrders: TriggerOrder[];
|
|
3
|
+
/** Map a Lighter order with its venue identity, lifecycle, and execution fields. */
|
|
4
|
+
export declare const mapOrder: (order: LtOrder, market: MarketDisplay) => Order;
|
|
5
|
+
/** Include terminal rows and their ids so consumers can update history and active caches. */
|
|
6
|
+
export declare const mapOrderUpdates: (rawOrders: LtOrder[], resolveMarket: (marketIndex: number) => MarketDisplay | undefined) => {
|
|
7
|
+
orders: Order[];
|
|
64
8
|
terminated: string[];
|
|
65
9
|
};
|
|
66
|
-
/**
|
|
67
|
-
* Map a raw Lighter order to the rich Order type — adds status, time-in-force
|
|
68
|
-
* and remaining/filled sizes on top of the OpenOrder fields.
|
|
69
|
-
* @public
|
|
70
|
-
*/
|
|
71
|
-
export declare const mapOrderDetail: (order: LtOrder, market: MarketDisplay) => Order;
|
|
72
10
|
//# sourceMappingURL=mapOrder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mapOrder.d.ts","sourceRoot":"","sources":["../../../src/utils/mapOrder.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mapOrder.d.ts","sourceRoot":"","sources":["../../../src/utils/mapOrder.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,KAAK,EAAa,MAAM,mBAAmB,CAAA;AASxE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAiFhD,oFAAoF;AACpF,eAAO,MAAM,QAAQ,GAAI,OAAO,OAAO,EAAE,QAAQ,aAAa,KAAG,KA8DhE,CAAA;AAED,6FAA6F;AAC7F,eAAO,MAAM,eAAe,GAC1B,WAAW,OAAO,EAAE,EACpB,eAAe,CAAC,WAAW,EAAE,MAAM,KAAK,aAAa,GAAG,SAAS,KAChE;IAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAczC,CAAA"}
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lifi/perps-sdk-provider-lighter",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "25.0.0",
|
|
4
4
|
"description": "Lighter provider plugin for @lifi/perps-sdk",
|
|
5
5
|
"homepage": "https://github.com/lifinance/perps-sdk",
|
|
6
6
|
"bugs": {
|
|
@@ -44,10 +44,10 @@
|
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"big.js": "^7.0.1",
|
|
46
46
|
"viem": "^2.55.18",
|
|
47
|
-
"@lifi/perps-types": "^
|
|
47
|
+
"@lifi/perps-types": "^13.0.0"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"@lifi/perps-sdk": "^
|
|
50
|
+
"@lifi/perps-sdk": "^14.0.0"
|
|
51
51
|
},
|
|
52
52
|
"publishConfig": {
|
|
53
53
|
"access": "public"
|
package/src/LighterProvider.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ACTIVE_ORDER_STATUSES,
|
|
2
3
|
type DepositFlow,
|
|
3
4
|
explorerTxUrlFromBase,
|
|
4
5
|
getAssetRegistry,
|
|
@@ -20,7 +21,6 @@ import {
|
|
|
20
21
|
type ProviderGetPortfolioHistoryParams,
|
|
21
22
|
type ProviderGetPositionsParams,
|
|
22
23
|
type ProviderGetQuoteParams,
|
|
23
|
-
type ProviderGetRunningTwapsParams,
|
|
24
24
|
type ProviderGetWithdrawableBalancesParams,
|
|
25
25
|
type ProviderWithdrawableBalance,
|
|
26
26
|
paginateActivity,
|
|
@@ -55,7 +55,6 @@ import type {
|
|
|
55
55
|
Quote,
|
|
56
56
|
SignedActionStep,
|
|
57
57
|
SigningMethod,
|
|
58
|
-
TwapOrder,
|
|
59
58
|
} from '@lifi/perps-types'
|
|
60
59
|
import {
|
|
61
60
|
ActionType,
|
|
@@ -97,7 +96,6 @@ import type {
|
|
|
97
96
|
LtAccountPnL,
|
|
98
97
|
LtDepositHistoryItem,
|
|
99
98
|
LtDepositHistoryResponse,
|
|
100
|
-
LtDetailedAccountPosition,
|
|
101
99
|
LtLiquidation,
|
|
102
100
|
LtLiquidationsResponse,
|
|
103
101
|
LtOrder,
|
|
@@ -128,7 +126,6 @@ import {
|
|
|
128
126
|
} from './utils/apiClient.js'
|
|
129
127
|
import { isAssetMarginEnabled } from './utils/assetCollateral.js'
|
|
130
128
|
import {
|
|
131
|
-
classifyAndMapOrders,
|
|
132
129
|
estimateLiquidationPrice,
|
|
133
130
|
fetchDetailedAccount,
|
|
134
131
|
formatOrderPrice,
|
|
@@ -138,7 +135,7 @@ import {
|
|
|
138
135
|
lighterWithdrawableBalances,
|
|
139
136
|
mapFill,
|
|
140
137
|
mapOpenPositions,
|
|
141
|
-
|
|
138
|
+
mapOrder,
|
|
142
139
|
mapPortfolioHistory,
|
|
143
140
|
positionMarginConstraints,
|
|
144
141
|
toBigOrNull,
|
|
@@ -146,7 +143,6 @@ import {
|
|
|
146
143
|
toIsoFromSeconds,
|
|
147
144
|
toRequiredBig,
|
|
148
145
|
} from './utils/index.js'
|
|
149
|
-
import { mapRunningTwap } from './utils/mapTwap.js'
|
|
150
146
|
import {
|
|
151
147
|
fetchRegisteredApiKey,
|
|
152
148
|
normalizeLighterPublicKey,
|
|
@@ -165,11 +161,6 @@ const projectFeeTier = (
|
|
|
165
161
|
taker: tickToFeeString(limits.current_taker_fee_tick),
|
|
166
162
|
})
|
|
167
163
|
|
|
168
|
-
const orderCountFor = (p: LtDetailedAccountPosition): number =>
|
|
169
|
-
(p.open_order_count ?? 0) +
|
|
170
|
-
(p.pending_order_count ?? 0) +
|
|
171
|
-
(p.position_tied_order_count ?? 0)
|
|
172
|
-
|
|
173
164
|
/**
|
|
174
165
|
* Lighter `sendTx` returns a bare lowercase-hex tx hash (40 bytes → 80 hex
|
|
175
166
|
* chars). `Order.order_id` is a different identifier the matching engine
|
|
@@ -647,11 +638,6 @@ export const createLighterProvider = (
|
|
|
647
638
|
return wireList(response.orders)
|
|
648
639
|
}
|
|
649
640
|
|
|
650
|
-
const deriveOrderBearingMarketIds = (account: LtAccount): number[] =>
|
|
651
|
-
account.positions
|
|
652
|
-
.filter((p) => orderCountFor(p) > 0)
|
|
653
|
-
.map((p) => p.market_id)
|
|
654
|
-
|
|
655
641
|
const fetchAllHistory = async (
|
|
656
642
|
client: LighterApiClient,
|
|
657
643
|
token: string,
|
|
@@ -897,23 +883,26 @@ export const createLighterProvider = (
|
|
|
897
883
|
),
|
|
898
884
|
units: availableMargin.toString(),
|
|
899
885
|
valueUsd: availableMargin.toString(),
|
|
886
|
+
price: '1',
|
|
900
887
|
},
|
|
901
888
|
]
|
|
902
889
|
: []
|
|
903
890
|
// Spot token holdings — non-collateral. The instance's settlement asset
|
|
904
891
|
// is valued 1:1; other tokens have no price source at this boundary, so
|
|
905
|
-
// their USD value
|
|
892
|
+
// their price and USD value are unknown.
|
|
906
893
|
const balances: Balance[] = account.assets
|
|
907
894
|
.filter((asset) => toRequiredBig(asset.balance, 'balance').gt(0))
|
|
908
895
|
.map((a) => {
|
|
909
896
|
const assetId = String(a.asset_id)
|
|
897
|
+
const settlement = a.asset_id === collateral.assetIndex
|
|
910
898
|
return {
|
|
911
899
|
categoryId: spotCategoryId,
|
|
912
900
|
asset:
|
|
913
901
|
assetRegistry.get(assetId) ??
|
|
914
902
|
lighterAsset(assetId, a.symbol, providerKey),
|
|
915
903
|
units: a.balance,
|
|
916
|
-
valueUsd:
|
|
904
|
+
valueUsd: settlement ? a.balance : '0',
|
|
905
|
+
...(settlement ? { price: '1' } : {}),
|
|
917
906
|
}
|
|
918
907
|
})
|
|
919
908
|
|
|
@@ -1063,24 +1052,22 @@ export const createLighterProvider = (
|
|
|
1063
1052
|
}
|
|
1064
1053
|
},
|
|
1065
1054
|
|
|
1066
|
-
/**
|
|
1067
|
-
* Lighter's `accountActiveOrders` endpoint takes no limit/cursor and
|
|
1068
|
-
* returns every active order for the account, so the response is always
|
|
1069
|
-
* the complete set: `params.limit` is not honoured and `pagination` is
|
|
1070
|
-
* reported as `{ limit: <count returned>, hasMore: false }` with no cursor.
|
|
1071
|
-
*/
|
|
1072
1055
|
async getOrders(
|
|
1073
1056
|
params: ProviderGetOrdersParams,
|
|
1074
1057
|
opts?: SDKRequestOptions
|
|
1075
1058
|
): Promise<OrdersResponse> {
|
|
1059
|
+
const statuses = new Set(params.statuses ?? ACTIVE_ORDER_STATUSES)
|
|
1060
|
+
const empty: OrdersResponse = {
|
|
1061
|
+
provider: providerKey,
|
|
1062
|
+
orders: [],
|
|
1063
|
+
pagination: { limit: params.limit ?? 0, hasMore: false },
|
|
1064
|
+
}
|
|
1065
|
+
if (statuses.size === 0) {
|
|
1066
|
+
return empty
|
|
1067
|
+
}
|
|
1076
1068
|
const token = await resolveAuthToken(opts, params.address)
|
|
1077
1069
|
if (token === undefined) {
|
|
1078
|
-
return
|
|
1079
|
-
provider: providerKey,
|
|
1080
|
-
openOrders: [],
|
|
1081
|
-
triggerOrders: [],
|
|
1082
|
-
pagination: { limit: params.limit ?? 0, hasMore: false },
|
|
1083
|
-
}
|
|
1070
|
+
return empty
|
|
1084
1071
|
}
|
|
1085
1072
|
|
|
1086
1073
|
const client = apiClient(opts)
|
|
@@ -1089,69 +1076,73 @@ export const createLighterProvider = (
|
|
|
1089
1076
|
fetchDetailedAccount(client, params.address),
|
|
1090
1077
|
registry.sync(),
|
|
1091
1078
|
])
|
|
1092
|
-
|
|
1093
1079
|
const marketId =
|
|
1094
1080
|
params.marketId === undefined
|
|
1095
1081
|
? LIGHTER_ALL_MARKETS_WILDCARD
|
|
1096
1082
|
: Number(registry.require(params.marketId).id)
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
)
|
|
1106
|
-
|
|
1107
|
-
const total = openOrders.length + triggerOrders.length
|
|
1108
|
-
return {
|
|
1109
|
-
provider: providerKey,
|
|
1110
|
-
openOrders,
|
|
1111
|
-
triggerOrders,
|
|
1112
|
-
pagination: { limit: total, hasMore: false },
|
|
1113
|
-
}
|
|
1114
|
-
},
|
|
1115
|
-
|
|
1116
|
-
async getRunningTwaps(
|
|
1117
|
-
params: ProviderGetRunningTwapsParams,
|
|
1118
|
-
opts?: SDKRequestOptions
|
|
1119
|
-
): Promise<TwapOrder[]> {
|
|
1120
|
-
const token = await resolveAuthToken(opts, params.address)
|
|
1121
|
-
if (token === undefined) {
|
|
1122
|
-
return []
|
|
1083
|
+
let active = false
|
|
1084
|
+
let terminal = false
|
|
1085
|
+
for (const status of statuses) {
|
|
1086
|
+
if (isActiveOrderStatus(status)) {
|
|
1087
|
+
active = true
|
|
1088
|
+
} else {
|
|
1089
|
+
terminal = true
|
|
1090
|
+
}
|
|
1123
1091
|
}
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1092
|
+
const [activeResponse, inactiveResponse] = await retryOnRevoked(
|
|
1093
|
+
opts,
|
|
1094
|
+
params.address,
|
|
1095
|
+
token,
|
|
1096
|
+
(t) =>
|
|
1097
|
+
Promise.all([
|
|
1098
|
+
active && params.cursor === undefined
|
|
1099
|
+
? fetchActiveOrders(client, t, account.index, marketId)
|
|
1100
|
+
: undefined,
|
|
1101
|
+
terminal
|
|
1102
|
+
? client.getAuthed<LtOrdersResponse>(
|
|
1103
|
+
'/api/v1/accountInactiveOrders',
|
|
1104
|
+
t,
|
|
1105
|
+
{
|
|
1106
|
+
account_index: account.index,
|
|
1107
|
+
market_id: marketId,
|
|
1108
|
+
limit: params.limit ?? LIGHTER_HISTORY_PAGE_SIZE,
|
|
1109
|
+
...(params.cursor === undefined
|
|
1110
|
+
? {}
|
|
1111
|
+
: { cursor: params.cursor }),
|
|
1112
|
+
}
|
|
1113
|
+
)
|
|
1114
|
+
: undefined,
|
|
1115
|
+
])
|
|
1139
1116
|
)
|
|
1140
|
-
|
|
1141
|
-
const
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1117
|
+
const orders: Order[] = []
|
|
1118
|
+
for (const response of [activeResponse, inactiveResponse]) {
|
|
1119
|
+
for (const raw of wireList(response?.orders)) {
|
|
1120
|
+
// `get`, not `require`: a market id the backend list no longer
|
|
1121
|
+
// carries drops only its own row instead of rejecting the whole
|
|
1122
|
+
// page. The registry warns once per unresolved id. A delisted
|
|
1123
|
+
// market still resolves, so its rows stay.
|
|
1124
|
+
const market = registry.get(String(raw.market_index))
|
|
1125
|
+
if (market === undefined) {
|
|
1126
|
+
continue
|
|
1127
|
+
}
|
|
1128
|
+
const order = mapOrder(raw, market)
|
|
1129
|
+
if (statuses.has(order.status)) {
|
|
1130
|
+
orders.push(order)
|
|
1151
1131
|
}
|
|
1152
1132
|
}
|
|
1153
1133
|
}
|
|
1154
|
-
|
|
1134
|
+
const cursor = inactiveResponse?.next_cursor || undefined
|
|
1135
|
+
return {
|
|
1136
|
+
provider: providerKey,
|
|
1137
|
+
orders,
|
|
1138
|
+
pagination: {
|
|
1139
|
+
limit: terminal
|
|
1140
|
+
? (params.limit ?? LIGHTER_HISTORY_PAGE_SIZE)
|
|
1141
|
+
: orders.length,
|
|
1142
|
+
hasMore: cursor !== undefined,
|
|
1143
|
+
...(cursor === undefined ? {} : { cursor }),
|
|
1144
|
+
},
|
|
1145
|
+
}
|
|
1155
1146
|
},
|
|
1156
1147
|
|
|
1157
1148
|
/**
|
|
@@ -1189,7 +1180,7 @@ export const createLighterProvider = (
|
|
|
1189
1180
|
`Lighter order ${params.id} not found for ${params.address}`
|
|
1190
1181
|
)
|
|
1191
1182
|
const detail = (order: LtOrder): Order =>
|
|
1192
|
-
|
|
1183
|
+
mapOrder(order, registry.require(String(order.market_index)))
|
|
1193
1184
|
|
|
1194
1185
|
// A tx-hash route would require mapping the caller's executeAction tx
|
|
1195
1186
|
// hash → wasm nonce → matching order, which the LI.FI backend did via
|
|
@@ -1433,9 +1424,6 @@ export const createLighterProvider = (
|
|
|
1433
1424
|
: Promise.resolve(),
|
|
1434
1425
|
])
|
|
1435
1426
|
|
|
1436
|
-
const assetSymbol = (assetId: number): string =>
|
|
1437
|
-
assetRegistry.get(String(assetId))?.displaySymbol ?? String(assetId)
|
|
1438
|
-
|
|
1439
1427
|
const items: ActivityItem[] = [
|
|
1440
1428
|
...history.deposits.deposits.map(
|
|
1441
1429
|
(d): ActivityItem => ({
|
|
@@ -1443,7 +1431,7 @@ export const createLighterProvider = (
|
|
|
1443
1431
|
provider: providerKey,
|
|
1444
1432
|
timestamp: toIsoFromMs(d.timestamp),
|
|
1445
1433
|
type: ActivityType.DEPOSIT,
|
|
1446
|
-
asset:
|
|
1434
|
+
asset: assetRegistry.require(String(d.asset_id)),
|
|
1447
1435
|
amount: d.amount,
|
|
1448
1436
|
explorerLink: d.l1_tx_hash
|
|
1449
1437
|
? `https://scan.li.fi/tx/${d.l1_tx_hash}`
|
|
@@ -1458,7 +1446,7 @@ export const createLighterProvider = (
|
|
|
1458
1446
|
provider: providerKey,
|
|
1459
1447
|
timestamp: toIsoFromMs(w.timestamp),
|
|
1460
1448
|
type: ActivityType.WITHDRAWAL,
|
|
1461
|
-
asset:
|
|
1449
|
+
asset: assetRegistry.require(String(w.asset_id)),
|
|
1462
1450
|
amount: w.amount,
|
|
1463
1451
|
explorerLink: w.l1_tx_hash
|
|
1464
1452
|
? `https://scan.li.fi/tx/${w.l1_tx_hash}`
|
|
@@ -1555,7 +1543,7 @@ export const createLighterProvider = (
|
|
|
1555
1543
|
type: ActivityType.TRANSFER,
|
|
1556
1544
|
direction,
|
|
1557
1545
|
counterpartyAccountIndex,
|
|
1558
|
-
asset:
|
|
1546
|
+
asset: assetRegistry.require(String(t.asset_id)),
|
|
1559
1547
|
amount: t.amount,
|
|
1560
1548
|
// The venue charges the transfer fee in the deployment's
|
|
1561
1549
|
// settlement asset, not in the asset the row moves, so a spot
|
package/src/accountConfig.ts
CHANGED
|
@@ -16,21 +16,6 @@ function assertNever(value: never): never {
|
|
|
16
16
|
)
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
const LIGHTER_ACCOUNT_TYPE_STANDARD = 0
|
|
20
|
-
const LIGHTER_ACCOUNT_TYPE_PREMIUM = 1
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Tier decode for the unauthenticated read, where `/accountLimits` — and with
|
|
24
|
-
* it the tier string — is out of reach. Neither official Lighter client
|
|
25
|
-
* documents an integer for any tier, so `0` (the `account_type` every sampled
|
|
26
|
-
* public account reports) reads as the default tier `standard`, and `1` as
|
|
27
|
-
* `premium`. No integer is known for `plus`: that account projects `null` here.
|
|
28
|
-
*/
|
|
29
|
-
const ACCOUNT_TYPE_INT_TO_WIRE: Readonly<Record<number, string>> = {
|
|
30
|
-
[LIGHTER_ACCOUNT_TYPE_STANDARD]: 'standard',
|
|
31
|
-
[LIGHTER_ACCOUNT_TYPE_PREMIUM]: 'premium',
|
|
32
|
-
}
|
|
33
|
-
|
|
34
19
|
// Wire strings match the backend descriptor's ParamOption values. An unmapped
|
|
35
20
|
// int projects to null.
|
|
36
21
|
const ACCOUNT_MODE_INT_TO_WIRE: Readonly<Record<number, string>> = {
|
|
@@ -43,8 +28,10 @@ const ACCOUNT_MODE_INT_TO_WIRE: Readonly<Record<number, string>> = {
|
|
|
43
28
|
* `userTierName` decides it, but only when the descriptor enumerates the
|
|
44
29
|
* string: Lighter owns that vocabulary, so an unrecognised value projects
|
|
45
30
|
* `null` instead of a mis-reported tier. A descriptor whose parameter carries
|
|
46
|
-
* no `values` array enumerates nothing, so it also projects `null`.
|
|
47
|
-
*
|
|
31
|
+
* no `values` array enumerates nothing, so it also projects `null`. The
|
|
32
|
+
* unauthenticated read reaches no `/accountLimits` and so carries no tier
|
|
33
|
+
* string, which projects `null` as well: `config.accountType` is Lighter's
|
|
34
|
+
* `SubAccountType`, not a tier, so nothing else in the config decides it.
|
|
48
35
|
*/
|
|
49
36
|
function resolveAccountTier(
|
|
50
37
|
descriptor: ProviderAction,
|
|
@@ -52,7 +39,7 @@ function resolveAccountTier(
|
|
|
52
39
|
): string | null {
|
|
53
40
|
const { userTierName } = config
|
|
54
41
|
if (userTierName === undefined) {
|
|
55
|
-
return
|
|
42
|
+
return null
|
|
56
43
|
}
|
|
57
44
|
const enumerated = descriptor.params?.[0]?.values ?? []
|
|
58
45
|
return enumerated.some((option) => option.value === userTierName)
|
|
@@ -109,6 +109,7 @@ const NIL_INTEGRATOR_MAKER_FEE = 0
|
|
|
109
109
|
const SELF_TRADE_BEHAVIOR_EXPIRE_MAKER = 0
|
|
110
110
|
const SELF_TRADE_EQUALITY_ACCOUNT_INDEX = 0
|
|
111
111
|
const SKIP_NONCE_DISABLED = 0
|
|
112
|
+
const NIL_ORDER_VERSION = 0
|
|
112
113
|
// CancelAll across every market (lighter-go `NilMarketIndex`); a real index
|
|
113
114
|
// scopes the cancel to a single market.
|
|
114
115
|
const NIL_MARKET_INDEX = 255
|
|
@@ -552,6 +553,7 @@ export class LighterSigner {
|
|
|
552
553
|
SELF_TRADE_EQUALITY_ACCOUNT_INDEX,
|
|
553
554
|
SKIP_NONCE_DISABLED,
|
|
554
555
|
nonce,
|
|
556
|
+
NIL_ORDER_VERSION,
|
|
555
557
|
ctx.apiKeyIndex,
|
|
556
558
|
ctx.accountIndex
|
|
557
559
|
)
|
package/src/types/submit.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
// Lighter submit/execute-path wire shapes (sendTx, fastwithdraw, changeAccountTier).
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Request body for Lighter's `/api/v1/sendTx` endpoint
|
|
5
|
-
* `tx_info` are the signed WASM transaction
|
|
6
|
-
*
|
|
4
|
+
* Request body for Lighter's `/api/v1/sendTx` endpoint (spec schema
|
|
5
|
+
* `ReqSendTx`). `tx_type` and `tx_info` are the signed WASM transaction
|
|
6
|
+
* envelope. `price_protection` is a venue-side execution guard the spec
|
|
7
|
+
* defaults to `true`, so an absent member leaves the guard on.
|
|
8
|
+
*
|
|
9
|
+
* The generated client carries the same members as `SendTxRequest` in
|
|
10
|
+
* `zklighter-perps/apis/TransactionApi` — the call signature of
|
|
11
|
+
* `TransactionApi.sendTx`, not a `models/` wire model.
|
|
7
12
|
*
|
|
8
13
|
* @public
|
|
9
14
|
*/
|
|
@@ -28,9 +33,14 @@ export interface LtSendTxResponse {
|
|
|
28
33
|
}
|
|
29
34
|
|
|
30
35
|
/**
|
|
31
|
-
* Batch request body for Lighter's
|
|
32
|
-
* `tx_types` is a JSON-encoded number array and `tx_infos` a
|
|
33
|
-
* string array; corresponding entries are submitted in array
|
|
36
|
+
* Batch request body for Lighter's `/api/v1/sendTxBatch` endpoint (spec schema
|
|
37
|
+
* `ReqSendTxBatch`). `tx_types` is a JSON-encoded number array and `tx_infos` a
|
|
38
|
+
* JSON-encoded string array; corresponding entries are submitted in array
|
|
39
|
+
* order.
|
|
40
|
+
*
|
|
41
|
+
* The generated client carries the same members as `SendTxBatchRequest` in
|
|
42
|
+
* `zklighter-perps/apis/TransactionApi` — the call signature of
|
|
43
|
+
* `TransactionApi.sendTxBatch`, not a `models/` wire model.
|
|
34
44
|
*
|
|
35
45
|
* @public
|
|
36
46
|
*/
|
|
@@ -1,18 +1,13 @@
|
|
|
1
1
|
import { PerpsError } from '@lifi/perps-sdk'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
type ActivityItem,
|
|
4
|
+
ActivityType,
|
|
5
|
+
PerpsErrorCode,
|
|
6
|
+
} from '@lifi/perps-types'
|
|
3
7
|
|
|
4
8
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* Each key holds the upstream `cursor` / `next_cursor` returned by that
|
|
8
|
-
* endpoint on the previous call. When a key is **present** with a non-empty
|
|
9
|
-
* string the corresponding endpoint will be re-fetched at that cursor on the
|
|
10
|
-
* next call; when a key is **absent** the endpoint is treated as exhausted
|
|
11
|
-
* (or never paged because the type filter excluded it) and skipped.
|
|
12
|
-
*
|
|
13
|
-
* The envelope is round-tripped through `cursor` as base64url JSON so callers
|
|
14
|
-
* don't need to know the per-endpoint shape. The encoding mirrors the LI.FI
|
|
15
|
-
* backend's wire format so cursors created by the backend remain usable.
|
|
9
|
+
* Endpoint-keyed activity cursor; absent endpoints are exhausted or excluded.
|
|
10
|
+
* Nonempty overflow requires a version-2 base64url JSON envelope.
|
|
16
11
|
* @public
|
|
17
12
|
*/
|
|
18
13
|
export interface LighterActivityCursor {
|
|
@@ -66,7 +61,7 @@ export const encodeActivityCursor = (
|
|
|
66
61
|
if (Object.keys(compact).length === 0) {
|
|
67
62
|
return undefined
|
|
68
63
|
}
|
|
69
|
-
return toBase64Url(JSON.stringify(compact))
|
|
64
|
+
return toBase64Url(JSON.stringify({ version: 2, ...compact }))
|
|
70
65
|
}
|
|
71
66
|
|
|
72
67
|
/**
|
|
@@ -120,20 +115,57 @@ export const decodeActivityCursor = (
|
|
|
120
115
|
'Invalid Lighter activity cursor: overflow must be an array'
|
|
121
116
|
)
|
|
122
117
|
}
|
|
123
|
-
|
|
118
|
+
if (overflow.length > 0 && cursorRecord.version !== 2) {
|
|
119
|
+
throw new PerpsError(
|
|
120
|
+
PerpsErrorCode.ValidationError,
|
|
121
|
+
'Invalid Lighter activity cursor: legacy overflow format; restart pagination'
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
env.overflow = overflow.map(toOverflowItem)
|
|
124
125
|
}
|
|
125
126
|
return env
|
|
126
127
|
}
|
|
127
128
|
|
|
129
|
+
const ACTIVITY_TYPES: readonly string[] = Object.values(ActivityType)
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* A cursor travels through consumer storage, so an overflow row may arrive
|
|
133
|
+
* corrupted or from an incompatible build. Reject it here rather than let a
|
|
134
|
+
* malformed row reach a consumer as a typed activity.
|
|
135
|
+
*/
|
|
136
|
+
const toOverflowItem = (row: unknown, index: number): ActivityItem => {
|
|
137
|
+
const invalid = (detail: string): PerpsError =>
|
|
138
|
+
new PerpsError(
|
|
139
|
+
PerpsErrorCode.ValidationError,
|
|
140
|
+
`Invalid Lighter activity cursor: overflow[${index}] ${detail}`
|
|
141
|
+
)
|
|
142
|
+
if (row === null || typeof row !== 'object' || Array.isArray(row)) {
|
|
143
|
+
throw invalid('must be an object')
|
|
144
|
+
}
|
|
145
|
+
const item = row as Record<string, unknown>
|
|
146
|
+
for (const field of ['id', 'provider', 'timestamp'] as const) {
|
|
147
|
+
if (typeof item[field] !== 'string') {
|
|
148
|
+
throw invalid(`${field} must be a string`)
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (typeof item.type !== 'string' || !ACTIVITY_TYPES.includes(item.type)) {
|
|
152
|
+
throw invalid('carries an unknown activity type')
|
|
153
|
+
}
|
|
154
|
+
return row as ActivityItem
|
|
155
|
+
}
|
|
156
|
+
|
|
128
157
|
const toBase64Url = (s: string): string => {
|
|
129
|
-
|
|
130
|
-
|
|
158
|
+
let binary = ''
|
|
159
|
+
for (const byte of new TextEncoder().encode(s)) {
|
|
160
|
+
binary += String.fromCharCode(byte)
|
|
161
|
+
}
|
|
162
|
+
return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
|
|
131
163
|
}
|
|
132
164
|
|
|
133
165
|
const fromBase64Url = (s: string): string => {
|
|
134
166
|
const padded = s.replace(/-/g, '+').replace(/_/g, '/') + padFor(s)
|
|
135
|
-
const
|
|
136
|
-
return
|
|
167
|
+
const bytes = Uint8Array.from(atob(padded), (char) => char.charCodeAt(0))
|
|
168
|
+
return new TextDecoder().decode(bytes)
|
|
137
169
|
}
|
|
138
170
|
|
|
139
171
|
const padFor = (s: string): string => {
|
package/src/utils/index.ts
CHANGED
|
@@ -16,15 +16,7 @@ export { estimateLiquidationPrice } from './liquidation.js'
|
|
|
16
16
|
export { mapFill } from './mapFill.js'
|
|
17
17
|
export { mapMarketContext } from './mapMarketContext.js'
|
|
18
18
|
export { mapOpenPositions } from './mapOpenPositions.js'
|
|
19
|
-
export {
|
|
20
|
-
classifyAndMapOrders,
|
|
21
|
-
isTriggerOrder,
|
|
22
|
-
isTriggerType,
|
|
23
|
-
mapOrder,
|
|
24
|
-
mapOrderDetail,
|
|
25
|
-
mapStatusReason,
|
|
26
|
-
mapTriggerOrder,
|
|
27
|
-
} from './mapOrder.js'
|
|
19
|
+
export { mapOrder, mapOrderUpdates } from './mapOrder.js'
|
|
28
20
|
export { mapPortfolioHistory } from './mapPortfolioHistory.js'
|
|
29
21
|
export { leverageFromImf, mapPosition } from './mapPosition.js'
|
|
30
22
|
export { mapMarketOrderLimits } from './marketLimits.js'
|
package/src/utils/mapFill.ts
CHANGED
|
@@ -4,12 +4,7 @@ import {
|
|
|
4
4
|
explorerTxUrl,
|
|
5
5
|
} from '@lifi/perps-sdk'
|
|
6
6
|
import type { Fill, MarketDisplay } from '@lifi/perps-types'
|
|
7
|
-
import {
|
|
8
|
-
FillStatus,
|
|
9
|
-
LiquidityRole,
|
|
10
|
-
OrderSide,
|
|
11
|
-
OrderType,
|
|
12
|
-
} from '@lifi/perps-types'
|
|
7
|
+
import { LiquidityRole, OrderSide, OrderType } from '@lifi/perps-types'
|
|
13
8
|
import Big from 'big.js'
|
|
14
9
|
import {
|
|
15
10
|
LIGHTER_FEE_TICK_SCALE,
|
|
@@ -131,7 +126,6 @@ export const mapFill = (
|
|
|
131
126
|
type: OrderType.LIMIT,
|
|
132
127
|
size: trade.size,
|
|
133
128
|
price: trade.price,
|
|
134
|
-
status: FillStatus.FILLED,
|
|
135
129
|
liquidity: isMaker ? LiquidityRole.MAKER : LiquidityRole.TAKER,
|
|
136
130
|
// Lighter charges the fill fee in the market's quote asset.
|
|
137
131
|
fee:
|