@metamask-previews/perps-controller 16.0.0-preview-2d576f0c9 → 16.1.0-preview-7dd72ded9
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 +11 -1
- package/dist/providers/HyperLiquidProvider.cjs +26 -7
- 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 +26 -7
- package/dist/providers/HyperLiquidProvider.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [16.1.0]
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Revalidate HyperLiquid positions over HTTP before reporting a WebSocket cache miss during a TP/SL update. ([#10101](https://github.com/MetaMask/core/pull/10101))
|
|
15
|
+
- A current DEX slice is stamped with the connection epoch, which proves it belongs to the live subscription but not that it has caught up with the most recent fill. `updatePositionTPSL` therefore treated the post-fill window, where the position exists on the venue but has not yet been published, as identical to a position that was closed, and returned `POSITION_NOT_FOUND` without making a request.
|
|
16
|
+
- Only `updatePositionTPSL` opts in. `closePosition`, `closePositions` and the margin operations keep failing closed on a cache miss, because they act on a position the user is looking at: an unpublished position is not rendered, so those flows cannot reach the post-fill window. TP/SL attachment is the one path a client fires automatically within milliseconds of placing an order, with no human in the loop. Keeping the opt-in narrow also keeps the added REST traffic off the batch paths.
|
|
17
|
+
- A cache hit still returns the WebSocket slice untouched, so a stale size on a symbol that is present is resolved exactly as before, and the reduce-only sizing guarantees added in [#10037](https://github.com/MetaMask/core/pull/10037) are unaffected.
|
|
18
|
+
|
|
10
19
|
## [16.0.0]
|
|
11
20
|
|
|
12
21
|
### Added
|
|
@@ -866,7 +875,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
866
875
|
|
|
867
876
|
- Bump `@metamask/controller-utils` from `^11.18.0` to `^11.19.0` ([#7995](https://github.com/MetaMask/core/pull/7995))
|
|
868
877
|
|
|
869
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/perps-controller@16.
|
|
878
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/perps-controller@16.1.0...HEAD
|
|
879
|
+
[16.1.0]: https://github.com/MetaMask/core/compare/@metamask/perps-controller@16.0.0...@metamask/perps-controller@16.1.0
|
|
870
880
|
[16.0.0]: https://github.com/MetaMask/core/compare/@metamask/perps-controller@15.1.0...@metamask/perps-controller@16.0.0
|
|
871
881
|
[15.1.0]: https://github.com/MetaMask/core/compare/@metamask/perps-controller@15.0.0...@metamask/perps-controller@15.1.0
|
|
872
882
|
[15.0.0]: https://github.com/MetaMask/core/compare/@metamask/perps-controller@14.0.0...@metamask/perps-controller@15.0.0
|
|
@@ -2188,7 +2188,7 @@ class HyperLiquidProvider {
|
|
|
2188
2188
|
// when available, otherwise query that DEX over HTTP. If neither source
|
|
2189
2189
|
// answers, fail closed: trusting the snapshot would recreate the stale
|
|
2190
2190
|
// side/size reduce-only rejection this method is meant to prevent.
|
|
2191
|
-
const currentPositions = await __classPrivateFieldGet(this, _HyperLiquidProvider_instances, "m", _HyperLiquidProvider_getPositionsForOperation).call(this, (0, hyperLiquidAdapter_js_1.parseAssetName)(symbol).dex ?? '');
|
|
2191
|
+
const currentPositions = await __classPrivateFieldGet(this, _HyperLiquidProvider_instances, "m", _HyperLiquidProvider_getPositionsForOperation).call(this, (0, hyperLiquidAdapter_js_1.parseAssetName)(symbol).dex ?? '', { revalidateMissingSymbol: symbol });
|
|
2192
2192
|
const position = currentPositions.find((pos) => pos.symbol === symbol);
|
|
2193
2193
|
if (livePosition &&
|
|
2194
2194
|
position &&
|
|
@@ -10246,8 +10246,11 @@ async function _HyperLiquidProvider_getStandaloneValidatedDexs() {
|
|
|
10246
10246
|
*
|
|
10247
10247
|
* A symbol-specific caller can use its current-connection DEX slice directly.
|
|
10248
10248
|
* The current-epoch slice wins before any REST request because it is the
|
|
10249
|
-
* provider's live subscription source for that exact DEX.
|
|
10250
|
-
*
|
|
10249
|
+
* provider's live subscription source for that exact DEX. A caller may opt
|
|
10250
|
+
* into one targeted REST revalidation when a required symbol is absent, which
|
|
10251
|
+
* covers the post-fill window before the next WebSocket position update. If
|
|
10252
|
+
* the target DEX has not published, the caller uses REST instead of a stale
|
|
10253
|
+
* aggregate.
|
|
10251
10254
|
*
|
|
10252
10255
|
* A whole-list caller uses one shallow-copied WebSocket snapshot only when
|
|
10253
10256
|
* every configured DEX is current. Otherwise it falls back to REST. No path
|
|
@@ -10256,15 +10259,31 @@ async function _HyperLiquidProvider_getStandaloneValidatedDexs() {
|
|
|
10256
10259
|
*
|
|
10257
10260
|
* @param targetDex - DEX for a single-symbol lookup, or undefined for a full
|
|
10258
10261
|
* position list.
|
|
10262
|
+
* @param options - Optional lookup behavior for a symbol-specific operation.
|
|
10263
|
+
* @param options.revalidateMissingSymbol - Query the target DEX over REST when
|
|
10264
|
+
* its current WebSocket slice does not contain this symbol.
|
|
10259
10265
|
* @returns Positions from one provenance-safe cache/REST path.
|
|
10260
10266
|
*/
|
|
10261
|
-
async function _HyperLiquidProvider_getPositionsForOperation(targetDex) {
|
|
10267
|
+
async function _HyperLiquidProvider_getPositionsForOperation(targetDex, options = {}) {
|
|
10262
10268
|
if (targetDex !== undefined) {
|
|
10263
10269
|
const targetPositions = __classPrivateFieldGet(this, _HyperLiquidProvider_subscriptionService, "f").getCachedPositionsForDex(targetDex);
|
|
10264
|
-
if (targetPositions
|
|
10265
|
-
|
|
10270
|
+
if (targetPositions === null) {
|
|
10271
|
+
__classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('Target DEX position cache unavailable: fetching REST positions', { dex: targetDex || 'main' });
|
|
10272
|
+
}
|
|
10273
|
+
else {
|
|
10274
|
+
const { revalidateMissingSymbol } = options;
|
|
10275
|
+
const shouldRevalidate = revalidateMissingSymbol !== undefined &&
|
|
10276
|
+
targetPositions.find((position) => position.symbol === revalidateMissingSymbol) === undefined;
|
|
10277
|
+
if (shouldRevalidate) {
|
|
10278
|
+
__classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('Target symbol missing from position cache: revalidating REST positions', {
|
|
10279
|
+
dex: targetDex || 'main',
|
|
10280
|
+
symbol: revalidateMissingSymbol,
|
|
10281
|
+
});
|
|
10282
|
+
}
|
|
10283
|
+
else {
|
|
10284
|
+
return [...targetPositions];
|
|
10285
|
+
}
|
|
10266
10286
|
}
|
|
10267
|
-
__classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('Target DEX position cache unavailable: fetching REST positions', { dex: targetDex || 'main' });
|
|
10268
10287
|
const { answered, positions } = await __classPrivateFieldGet(this, _HyperLiquidProvider_instances, "m", _HyperLiquidProvider_queryDexPositions).call(this, targetDex || null);
|
|
10269
10288
|
if (!answered) {
|
|
10270
10289
|
throw new Error(perpsErrorCodes_js_1.PERPS_ERROR_CODES.PROVIDER_NOT_AVAILABLE);
|