@metamask-previews/perps-controller 13.1.0-preview-8c2a2eeb2 → 13.1.0-preview-b13d916
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/CHANGELOG.md +3 -1
- package/dist/providers/HyperLiquidProvider.cjs +36 -38
- package/dist/providers/HyperLiquidProvider.cjs.map +1 -1
- package/dist/providers/HyperLiquidProvider.d.cts.map +1 -1
- package/dist/providers/HyperLiquidProvider.d.mts.map +1 -1
- package/dist/providers/HyperLiquidProvider.mjs +19 -21
- package/dist/providers/HyperLiquidProvider.mjs.map +1 -1
- package/dist/utils/hyperLiquidAdapter.cjs +2 -2
- package/dist/utils/hyperLiquidAdapter.cjs.map +1 -1
- package/dist/utils/hyperLiquidAdapter.mjs +2 -2
- package/dist/utils/hyperLiquidAdapter.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,7 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
9
|
|
|
10
10
|
### Fixed
|
|
11
11
|
|
|
12
|
-
-
|
|
12
|
+
- Prevent transient HyperLiquid WebSocket disconnects from failing the first TP/SL update by checking builder-fee approval over HTTP ([#9997](https://github.com/MetaMask/core/pull/9997))
|
|
13
|
+
- Stop reporting `TPSL_UPDATE_FAILED` from `updatePositionTPSL` when HyperLiquid accepts a trigger with `waitingForTrigger`; accepted triggers without response order IDs are reconciled before mixed-failure cleanup ([#9995](https://github.com/MetaMask/core/pull/9995))
|
|
13
14
|
|
|
14
15
|
## [13.1.0]
|
|
15
16
|
|
|
@@ -19,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
19
20
|
|
|
20
21
|
### Fixed
|
|
21
22
|
|
|
23
|
+
- Preserve trigger prices and normalized trigger order types in HyperLiquid historical orders while retaining their lifecycle and execution semantics ([#9982](https://github.com/MetaMask/core/pull/9982)).
|
|
22
24
|
- Classify `xyz:CBRS` and `xyz:SPCX` as stocks in the Hyperliquid fallback market map ([#9988](https://github.com/MetaMask/core/pull/9988))
|
|
23
25
|
|
|
24
26
|
## [13.0.0]
|
|
@@ -18,6 +18,7 @@ const bignumber_js_1 = require("bignumber.js");
|
|
|
18
18
|
const uuid_1 = require("uuid");
|
|
19
19
|
const eventNames_js_1 = require("../constants/eventNames.cjs");
|
|
20
20
|
const hyperLiquidConfig_js_1 = require("../constants/hyperLiquidConfig.cjs");
|
|
21
|
+
const orderTypes_js_1 = require("../constants/orderTypes.cjs");
|
|
21
22
|
const perpsConfig_js_1 = require("../constants/perpsConfig.cjs");
|
|
22
23
|
const transactionsHistoryConfig_js_1 = require("../constants/transactionsHistoryConfig.cjs");
|
|
23
24
|
const perpsErrorCodes_js_1 = require("../perpsErrorCodes.cjs");
|
|
@@ -38,10 +39,18 @@ const idUtils_js_1 = require("../utils/idUtils.cjs");
|
|
|
38
39
|
const marketDataTransform_js_1 = require("../utils/marketDataTransform.cjs");
|
|
39
40
|
const marketUtils_js_1 = require("../utils/marketUtils.cjs");
|
|
40
41
|
const orderCalculations_js_1 = require("../utils/orderCalculations.cjs");
|
|
41
|
-
const
|
|
42
|
+
const orderTypes_js_2 = require("../utils/orderTypes.cjs");
|
|
42
43
|
const standaloneInfoClient_js_1 = require("../utils/standaloneInfoClient.cjs");
|
|
43
44
|
const stringParseUtils_js_1 = require("../utils/stringParseUtils.cjs");
|
|
44
45
|
// getStreamManagerInstance removed: use this.#deps.streamManager instead
|
|
46
|
+
const HISTORICAL_ORDER_TYPE_BY_DETAILED_TYPE = {
|
|
47
|
+
[orderTypes_js_1.DETAILED_ORDER_TYPES.LIMIT]: 'limit',
|
|
48
|
+
[orderTypes_js_1.DETAILED_ORDER_TYPES.MARKET]: 'market',
|
|
49
|
+
[orderTypes_js_1.DETAILED_ORDER_TYPES.STOP_LIMIT]: 'limit',
|
|
50
|
+
[orderTypes_js_1.DETAILED_ORDER_TYPES.STOP_MARKET]: 'market',
|
|
51
|
+
[orderTypes_js_1.DETAILED_ORDER_TYPES.TAKE_PROFIT_LIMIT]: 'limit',
|
|
52
|
+
[orderTypes_js_1.DETAILED_ORDER_TYPES.TAKE_PROFIT_MARKET]: 'market',
|
|
53
|
+
};
|
|
45
54
|
/**
|
|
46
55
|
* Type guard to check if a status is an object (not a string literal like "waitingForFill")
|
|
47
56
|
* The SDK returns status as a union of object types and string literals.
|
|
@@ -349,11 +358,11 @@ function collectPositionTriggerOrders(params) {
|
|
|
349
358
|
const triggerOrders = Array.from(byOrderId.values());
|
|
350
359
|
const takeProfitOrders = triggerOrders.filter((order) => order.direction === 'take_profit');
|
|
351
360
|
const stopLossOrders = triggerOrders.filter((order) => order.direction !== 'take_profit');
|
|
352
|
-
const takeProfitSummaryPrice = (0,
|
|
361
|
+
const takeProfitSummaryPrice = (0, orderTypes_js_2.resolvePositionTriggerSummaryPrice)({
|
|
353
362
|
triggerOrders: takeProfitOrders,
|
|
354
363
|
scannedPrice: takeProfitPrice,
|
|
355
364
|
});
|
|
356
|
-
const stopLossSummaryPrice = (0,
|
|
365
|
+
const stopLossSummaryPrice = (0, orderTypes_js_2.resolvePositionTriggerSummaryPrice)({
|
|
357
366
|
triggerOrders: stopLossOrders,
|
|
358
367
|
scannedPrice: stopLossPrice,
|
|
359
368
|
});
|
|
@@ -914,7 +923,7 @@ class HyperLiquidProvider {
|
|
|
914
923
|
// single order, so they leave the shared path here — before the order
|
|
915
924
|
// array, the HIP-3 transfer, and the atomic single-order submit, none of
|
|
916
925
|
// which describe what a TWAP, a ladder, or a chase does.
|
|
917
|
-
if ((0,
|
|
926
|
+
if ((0, orderTypes_js_2.isStrategyOrderType)(params.orderType)) {
|
|
918
927
|
return await __classPrivateFieldGet(this, _HyperLiquidProvider_instances, "m", _HyperLiquidProvider_placeStrategyOrder).call(this, params, params.orderType);
|
|
919
928
|
}
|
|
920
929
|
// Extract DEX name for API calls (main DEX = null)
|
|
@@ -1095,7 +1104,7 @@ class HyperLiquidProvider {
|
|
|
1095
1104
|
if (isMinimumOrderError &&
|
|
1096
1105
|
retryCount === 0 &&
|
|
1097
1106
|
!params.reduceOnly &&
|
|
1098
|
-
!(0,
|
|
1107
|
+
!(0, orderTypes_js_2.isStrategyOrderType)(params.orderType)) {
|
|
1099
1108
|
let adjustedUsdAmount;
|
|
1100
1109
|
let originalValue;
|
|
1101
1110
|
if (params.usdAmount) {
|
|
@@ -1325,7 +1334,7 @@ class HyperLiquidProvider {
|
|
|
1325
1334
|
// `modify` rebuilds an order as a plain limit/market order, so a trigger
|
|
1326
1335
|
// on either side of the edit would be silently dropped. Reject a resting
|
|
1327
1336
|
// trigger order as well as an edit *into* one; cancel and re-place instead.
|
|
1328
|
-
if ((0,
|
|
1337
|
+
if ((0, orderTypes_js_2.isTriggerOrderType)(params.newOrder.orderType)) {
|
|
1329
1338
|
return {
|
|
1330
1339
|
success: false,
|
|
1331
1340
|
error: perpsErrorCodes_js_1.PERPS_ERROR_CODES.ORDER_EDIT_TRIGGER_UNSUPPORTED,
|
|
@@ -1336,7 +1345,7 @@ class HyperLiquidProvider {
|
|
|
1336
1345
|
// FrontendMarket modification and quietly drop the TWAP schedule, the
|
|
1337
1346
|
// ladder, or the chase loop the caller asked for. Cancel by the strategy
|
|
1338
1347
|
// handle and place again.
|
|
1339
|
-
if ((0,
|
|
1348
|
+
if ((0, orderTypes_js_2.isStrategyOrderType)(params.newOrder.orderType)) {
|
|
1340
1349
|
return {
|
|
1341
1350
|
success: false,
|
|
1342
1351
|
error: perpsErrorCodes_js_1.PERPS_ERROR_CODES.ORDER_EDIT_STRATEGY_UNSUPPORTED,
|
|
@@ -1454,7 +1463,7 @@ class HyperLiquidProvider {
|
|
|
1454
1463
|
// A limit order honours the caller's time in force; validation above has
|
|
1455
1464
|
// already rejected one on any other order shape.
|
|
1456
1465
|
t: params.newOrder.orderType === 'limit'
|
|
1457
|
-
? { limit: { tif: (0,
|
|
1466
|
+
? { limit: { tif: (0, orderTypes_js_2.toSDKTimeInForce)(params.newOrder.timeInForce) } }
|
|
1458
1467
|
: { limit: { tif: 'FrontendMarket' } }, // True market order
|
|
1459
1468
|
c: params.newOrder.clientOrderId
|
|
1460
1469
|
? params.newOrder.clientOrderId
|
|
@@ -1515,7 +1524,7 @@ class HyperLiquidProvider {
|
|
|
1515
1524
|
// A strategy handle is not an exchange order ID, so it cannot go through
|
|
1516
1525
|
// the single-order cancel below. Callers that omit `orderType` — every
|
|
1517
1526
|
// existing one — keep the behaviour they have today.
|
|
1518
|
-
if (params.orderType && (0,
|
|
1527
|
+
if (params.orderType && (0, orderTypes_js_2.isStrategyOrderType)(params.orderType)) {
|
|
1519
1528
|
return await __classPrivateFieldGet(this, _HyperLiquidProvider_instances, "m", _HyperLiquidProvider_cancelStrategyOrder).call(this, params);
|
|
1520
1529
|
}
|
|
1521
1530
|
// Resolve ownership before the first await. A reprice can change the child
|
|
@@ -2145,7 +2154,7 @@ class HyperLiquidProvider {
|
|
|
2145
2154
|
orderType,
|
|
2146
2155
|
triggerPrice,
|
|
2147
2156
|
reduceOnly: true,
|
|
2148
|
-
...((0,
|
|
2157
|
+
...((0, orderTypes_js_2.isLimitExecutionOrderType)(orderType) && {
|
|
2149
2158
|
price: order.price,
|
|
2150
2159
|
}),
|
|
2151
2160
|
};
|
|
@@ -2159,9 +2168,9 @@ class HyperLiquidProvider {
|
|
|
2159
2168
|
r: true,
|
|
2160
2169
|
t: {
|
|
2161
2170
|
trigger: {
|
|
2162
|
-
isMarket: !(0,
|
|
2171
|
+
isMarket: !(0, orderTypes_js_2.isLimitExecutionOrderType)(orderType),
|
|
2163
2172
|
triggerPx: triggerPrice,
|
|
2164
|
-
tpsl: (0,
|
|
2173
|
+
tpsl: (0, orderTypes_js_2.getTriggerDirection)(orderType) === 'stop' ? 'sl' : 'tp',
|
|
2165
2174
|
},
|
|
2166
2175
|
},
|
|
2167
2176
|
},
|
|
@@ -3099,11 +3108,11 @@ class HyperLiquidProvider {
|
|
|
3099
3108
|
});
|
|
3100
3109
|
return {
|
|
3101
3110
|
...position,
|
|
3102
|
-
takeProfitPrice: (0,
|
|
3111
|
+
takeProfitPrice: (0, orderTypes_js_2.resolvePositionTriggerSummaryPrice)({
|
|
3103
3112
|
triggerOrders: takeProfitOrders,
|
|
3104
3113
|
scannedPrice: takeProfitPrice,
|
|
3105
3114
|
}),
|
|
3106
|
-
stopLossPrice: (0,
|
|
3115
|
+
stopLossPrice: (0, orderTypes_js_2.resolvePositionTriggerSummaryPrice)({
|
|
3107
3116
|
triggerOrders: stopLossOrders,
|
|
3108
3117
|
scannedPrice: stopLossPrice,
|
|
3109
3118
|
}),
|
|
@@ -3244,8 +3253,6 @@ class HyperLiquidProvider {
|
|
|
3244
3253
|
// Transform HyperLiquid orders to abstract Order type
|
|
3245
3254
|
const orders = (rawOrders || []).map((rawOrder) => {
|
|
3246
3255
|
const { order, status, statusTimestamp } = rawOrder;
|
|
3247
|
-
// Normalize side: HyperLiquid uses 'A' (Ask/Sell) and 'B' (Bid/Buy)
|
|
3248
|
-
const normalizedSide = order.side === 'B' ? 'buy' : 'sell';
|
|
3249
3256
|
// Normalize status
|
|
3250
3257
|
let normalizedStatus;
|
|
3251
3258
|
switch (status) {
|
|
@@ -3278,28 +3285,19 @@ class HyperLiquidProvider {
|
|
|
3278
3285
|
default:
|
|
3279
3286
|
normalizedStatus = 'queued';
|
|
3280
3287
|
}
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
const
|
|
3288
|
+
const adaptedOrder = (0, hyperLiquidAdapter_js_1.adaptOrderFromSDK)(order, undefined);
|
|
3289
|
+
// limitPx is also populated as a slippage cap for market orders, so the
|
|
3290
|
+
// exchange's detailed type is the reliable execution-mode source.
|
|
3291
|
+
const historicalOrderType = (0, utils_1.hasProperty)(HISTORICAL_ORDER_TYPE_BY_DETAILED_TYPE, order.orderType)
|
|
3292
|
+
? HISTORICAL_ORDER_TYPE_BY_DETAILED_TYPE[order.orderType]
|
|
3293
|
+
: 'market';
|
|
3285
3294
|
return {
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
orderType: order.orderType?.toLowerCase().includes('limit')
|
|
3290
|
-
? 'limit'
|
|
3291
|
-
: 'market',
|
|
3292
|
-
size: order.sz,
|
|
3293
|
-
originalSize: order.origSz || order.sz,
|
|
3294
|
-
price: order.limitPx || '0',
|
|
3295
|
-
filledSize: filledSize.toString(),
|
|
3296
|
-
remainingSize: currentSize.toString(),
|
|
3295
|
+
...adaptedOrder,
|
|
3296
|
+
orderType: historicalOrderType,
|
|
3297
|
+
remainingSize: parseFloat(order.sz).toString(),
|
|
3297
3298
|
status: normalizedStatus,
|
|
3298
3299
|
timestamp: statusTimestamp,
|
|
3299
3300
|
lastUpdated: statusTimestamp,
|
|
3300
|
-
detailedOrderType: order.orderType, // Full order type from exchange (e.g., 'Take Profit Limit', 'Stop Market')
|
|
3301
|
-
isTrigger: order.isTrigger,
|
|
3302
|
-
reduceOnly: order.reduceOnly,
|
|
3303
3301
|
};
|
|
3304
3302
|
});
|
|
3305
3303
|
return orders;
|
|
@@ -4166,7 +4164,7 @@ class HyperLiquidProvider {
|
|
|
4166
4164
|
// fallback (plain limit, stop_limit, take_profit_limit)
|
|
4167
4165
|
if (!priceForValidation &&
|
|
4168
4166
|
params.price &&
|
|
4169
|
-
(0,
|
|
4167
|
+
(0, orderTypes_js_2.isLimitExecutionOrderType)(params.orderType)) {
|
|
4170
4168
|
priceForValidation = parseFloat(params.price);
|
|
4171
4169
|
__classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('Using limit price for order validation (limit order):', {
|
|
4172
4170
|
size,
|
|
@@ -4177,7 +4175,7 @@ class HyperLiquidProvider {
|
|
|
4177
4175
|
// have no limit price; the trigger price is the best notional estimate.
|
|
4178
4176
|
if (!priceForValidation &&
|
|
4179
4177
|
params.triggerPrice &&
|
|
4180
|
-
(0,
|
|
4178
|
+
(0, orderTypes_js_2.isTriggerOrderType)(params.orderType)) {
|
|
4181
4179
|
priceForValidation = parseFloat(params.triggerPrice);
|
|
4182
4180
|
__classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('Using trigger price for order validation (trigger order):', {
|
|
4183
4181
|
size,
|
|
@@ -5006,7 +5004,7 @@ class HyperLiquidProvider {
|
|
|
5006
5004
|
// market order (taker), a stop_limit as a limit order, a scale ladder as the
|
|
5007
5005
|
// resting limit orders it fans out into, and a TWAP as the marketable
|
|
5008
5006
|
// suborders it crosses the book with.
|
|
5009
|
-
const isMarketExecution = (0,
|
|
5007
|
+
const isMarketExecution = (0, orderTypes_js_2.getTriggerExecution)(orderType) === 'market';
|
|
5010
5008
|
// A chase is post-only by construction, so it can only ever fill as a maker.
|
|
5011
5009
|
// Quoting it at the taker rate would overstate the fee whatever the caller
|
|
5012
5010
|
// passes for `isMaker`.
|
|
@@ -6998,7 +6996,7 @@ async function _HyperLiquidProvider_queryUserDataAcrossDexs(baseParams, queryFn)
|
|
|
6998
6996
|
* @returns Current max fee rate or null if not approved
|
|
6999
6997
|
*/
|
|
7000
6998
|
async function _HyperLiquidProvider_checkBuilderFeeApproval(builder, userAddress) {
|
|
7001
|
-
const infoClient = __classPrivateFieldGet(this, _HyperLiquidProvider_clientService, "f").getInfoClient();
|
|
6999
|
+
const infoClient = __classPrivateFieldGet(this, _HyperLiquidProvider_clientService, "f").getInfoClient({ useHttp: true });
|
|
7002
7000
|
return infoClient.maxBuilderFee({
|
|
7003
7001
|
user: userAddress,
|
|
7004
7002
|
builder,
|