All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Add Perps Discovery analytics constants to
PERPS_EVENT_PROPERTYandPERPS_EVENT_VALUEso mobile can import them from@metamask/perps-controllerinstead of maintaining a local mirror (#9178)- New
PERPS_EVENT_PROPERTYkeys:SOURCE_SECTION,RESULT_COUNT,SECTION_NAME,SECTION_INDEX,SECTIONS_DISPLAYED,WATCHLIST_COUNT,WATCHLIST_MARKETS - New
PERPS_EVENT_VALUE.SOURCE_SECTIONgroup: values for home sections (positions,orders,watchlist,whats_happening,products,top_gainers,top_losers,crypto,commodity,stock,forex), explore sections (perps_movers,perps_crypto,perps_stocks_commodities,perps_markets), and market-list sections (all_markets,new,active_search) - New
PERPS_EVENT_VALUE.SECTION_NAMEgroup:balance,positions,orders,watchlist,whats_happening,products,top_movers,explore_crypto,explore_commodities,explore_stocks,explore_forex,recent_activity - Extended
PERPS_EVENT_VALUE.INTERACTION_TYPEwithMARKET_LIST_FILTER - Extended
PERPS_EVENT_VALUE.BUTTON_CLICKEDwithWATCHLIST,TOP_MOVERS,WHATS_HAPPENING - Extended
PERPS_EVENT_VALUE.BUTTON_LOCATIONwithASSET_DETAILS
- New
- Bump
@metamask/utilsfrom^11.9.0to^11.11.0(#9074)
- Add observational hard timeout for order submission: tag the
Perps Order Submissiontrace and emit a breadcrumb when a provider round-trip exceedsPlaceOrderTimeoutMs(60s), without cancelling the in-flight order (#8994) - Add
HYPERLIQUID_ASSET_NAMES(a curatedsymbol → human-readable namemap, e.g.BTC → 'Bitcoin',xyz:AAPL → 'Apple',xyz:GOLD → 'Gold') and thegetHyperLiquidAssetName(symbol, names?)helper, both exported from@metamask/perps-controller/constants, so clients can match and display markets by full name (#9082)- HyperLiquid does not expose a per-asset human-readable name; this map is maintained client-side and keyed like
HIP3_ASSET_MARKET_TYPES(bareSYMBOLfor crypto,dex:SYMBOLfor HIP-3). Unmapped assets fall back to their ticker.
- HyperLiquid does not expose a per-asset human-readable name; this map is maintained client-side and keyed like
- Add
rankMarketsByQuery(markets, query)andgetMarketMatchRank(market, query)helpers (and theMarketMatchRankenum) for relevance-ranked market search by ticker symbol or human-readable name (exact > prefix > substring, stable within a rank) (#9082)- Complements the existing unranked
filterMarketsByQuery; same match semantics (case-insensitive substring onsymbolandname), but ordered by relevance. No fuzzy/phonetic matching.
- Complements the existing unranked
- Deliver HyperLiquid positions, orders, and account/spot balance via per-DEX
clearinghouseStateandopenOrderssubscriptions on all paths, removing the dependency on the deprecatedwebData2snapshot channel (#9081)- The non-HIP-3 (main-DEX-only) user data path previously used
webData2, which HyperLiquid is throttling to a 15s push interval and deprecating. It now uses the same sub-second per-DEX subscriptions as the HIP-3 path, withwebData3retained only for open-interest caps (not latency-sensitive).
- The non-HIP-3 (main-DEX-only) user data path previously used
- Surface late order completions via trace
reason: 'late_success' | 'late_error'(#8994) PerpsMarketData.namereturned bygetMarketDataWithPrices()is now the human-readable market name (resolved viaHYPERLIQUID_ASSET_NAMES) instead of a copy of the ticker symbol; unmapped assets are unchanged (still equal the symbol) (#9082)transformMarketDatagains an optionalassetNamesparameter (defaults to the bundled map) to override the name source.
- Bump
@metamask/controller-utilsfrom^12.1.0to^12.2.0(#9058, #9083)
- Remove unused
Perps Order Submission Toasttrace name from thePerpsTraceNameunion (#8994)
- Fix
late_errornever being emitted in theplaceOrdercatch path when a provider call succeeded pastPlaceOrderTimeoutMsbut a subsequent step threw; the tracereasonnow correctly reflects'late_error'whenever the submission threshold was exceeded, regardless of where the exception originated (#8994)
- Centralise market category classification so consumers share one model instead of re-deriving it per client (#9009)
- Export
getMarketTypeFilter(resolves a market to its UI category filter with singular values aligned toMarketCategory) andisHip3Market.getMarketTypeFilterandmatchesCategorytreat amarketSourceDEX id as a HIP-3 signal consistently, so partial (route-param) markets classify the same way in both. - Export the pure
matchesCategoryandapplyMarketFiltershelpers (moved fromMarketDataService).
- Export
- BREAKING: Align
MarketTypeFilterandMARKET_CATEGORIESvalues withMarketCategorysingular values (#9009)- Replace
stockswithstock,indiceswithindex,etfswithetf, andcommoditieswithcommodity.
- Replace
- Reclassify
xyz:CBRS(Cerebras) fromstocktopre-ipoand addxyz:IPOP(Quantinuum) aspre-ipoinHIP3_ASSET_MARKET_TYPES, so all three Pre-IPO Perpetual markets on trade.xyz (CBRS, SPCX, IPOP) display under the Pre-IPO category (#9038)
- Add
MarketCategoryenum,MARKET_CATEGORIESordered array (7 data-model category pills), andgetMarketCategoriesmessenger action (#8892) - Expand
HIP3_ASSET_MARKET_TYPESwith new stock, ETF, pre-IPO, forex, and commodity markets (#8892) - Add
categories,sortBy,direction,limit, andexcludeSymbolsoptional params toGetMarketDataWithPricesParamsandgetMarketDataWithPrices()for post-processing filtering, sorting, and pagination of market data (#8892) - Export
SortField,SortDirection, andGetMarketDataWithPricesParamstypes from the package root (#8892)
- BREAKING: Replace
'equity'with granularMarketTypevalues:'stock','pre-ipo','index', and'etf'(#8892)- Update any code matching
marketType === 'equity'to use the specific sub-type.
- Update any code matching
- Add slippage controls so users can configure per-order slippage tolerance for market trades (#8871)
- Track
vip_tierandvip_discountproperties on perps trading events for fee analytics (#8871) - Surface an in-app banner during an ongoing HyperLiquid outage so users see degraded trading status (#8871)
- Expose subpath
exportsfor./constants,./constants/*,./types, and./utils/*so consumers using legacynodemodule resolution can deep-import compiled entry points without losing tree-shaking (#8883)
- Prefer the currently selected EVM account when resolving the trading account so account switching is honored across providers (#8871)
- Suppress
User or API Wallet does not existSentry noise from unfunded wallets that have not interacted with HyperLiquid (#8871) - Approve the HyperLiquid builder fee when missing so order submission succeeds after fresh wallet setup (#8871)
- Pass
isInternal: trueto all internaladdTransactioncalls to adopt the explicitisInternalflag introduced in@metamask/transaction-controller(#8633) - Bump
@metamask/transaction-controllerfrom^65.4.0to^66.0.0(#8848)
- Pass the perps builder base fee into rewards discount resolution and treat unhydrated rewards subscription state as retryable instead of a definitive no-discount result (#8803)
- Bump
@metamask/controller-utilsfrom^12.0.0to^12.1.0(#8774) - Bump
@metamask/transaction-controllerfrom^65.3.0to^65.4.0(#8796)
- Defer signing-backed HyperLiquid unified-account setup for hardware wallets across migratable abstraction modes, including Ledger, Trezor, OneKey, Lattice, and QR keyrings, to avoid repeated signing prompts while browsing (#8803)
- Improve logging and retry classification for failed cancel/close/TP-SL operations and SDK-wrapped keyring-locked errors (#8803)
- Bump
@metamask/controller-utilsfrom^11.20.0to^12.0.0(#8755)
- BREAKING: Rename
AccountState.availableBalancetospendableBalanceandAccountState.availableToTradeBalancetowithdrawableBalancefor clearer semantics across abstraction modes (#8678) - Mode-aware spot fold:
addSpotBalanceToAccountStatenow folds free spot USDC into bothspendableBalanceandwithdrawableBalancefor Unified/Portfolio modes, while Standard/DEX-abstraction modes keep spot separate (#8678) - Add throttled WS-driven
userAbstractionrefresh so HL-web mode flips propagate back without requiring a restart or account switch (#8678) - Fix position direction display for flipped positions (#8707)
- BREAKING:
HyperLiquidClientServicenow forces thedexAbstraction → unifiedAccountmigration via a new internal flow, deferred until firstwithdraw,placeOrder, or other action entry point so users see unified collateral on their first trade/withdrawal (#8658) - BREAKING:
addSpotBalanceToAccountStateandHyperLiquidSubscriptionServiceare now mode-aware: spot USDC is only folded into tradeable collateral forunifiedAccount/portfolioMarginmodes, anduserAbstractionis propagated through subscriptions (#8658)
- Bump
@nktkas/hyperliquidfrom^0.30.2to^0.32.2foruserAbstraction/userSetAbstraction/agentSetAbstractionAPI surface (#8658) - Replace
agentSetAbstractionwire-code magic string with a typed constant (#8658) - Bump
@metamask/keyring-controllerfrom^25.3.0to^25.4.0(#8665) - Bump
@metamask/account-tree-controllerfrom^7.1.0to^7.2.0(#8665) - Bump
@metamask/transaction-controllerfrom^64.4.0to^65.0.0(#8613) - Bump
@metamask/messengerfrom^1.1.1to^1.2.0(#8632)
- Keep users on
portfolioMarginmode and recover the resolved abstraction mode after migration instead of evicting it (#8658) - Retry abstraction mode after transient
userAbstractionfailures and reset the memoized readiness promise after silent migration failures (#8658) - Close WebSocket-vs-REST race that could fold spot for Standard users and preserve abstraction REST results across active subscribers (#8658)
- Drop the pre-fetch generation guard so
userAbstractionalways resolves; treat cached balances as an unambiguous spot owner (#8658) - Restore HyperLiquid withdrawal for Unified Account Mode users and support arb USDC withdraw balance in unified mode (#8658)
- Harden unified-account migration handling and close MM Pay
$0+ analytics gaps (#8658)
- Add
coalescePerpsRestRequestutility for deduplicating concurrent REST requests with account-scoped cache keys (#8560) - Add
accountUtilshelpers for resolving the active perps account id and pinning it to forwarded provider params (#8560)
- Account-scope the REST cache and guard cache writes so mount load stays cacheable without cross-account bleed (#8560)
- Make
forceRefreshprovider-agnostic and align rate-limit handling with the extension (#8560) - Regenerate
PerpsControllermethod action types; shrink rate-limit diff and drop verbose history logs (#8560)
- BREAKING: Drop the dead
spotStateparameter fromadaptAccountStateFromSDK. Spot balances are layered on byaddSpotBalanceToAccountState, which enforces the USDC-only policy viaSPOT_COLLATERAL_COINS; removing the dormant branch keeps one source of truth and prevents a future caller from silently getting ALL-coins behavior (#8560)
- HyperLiquid Unified-mode live balance: subscribe to
spotStateWS and compute tradeable/total balance from on-chain math (#8560) - Complete spot-balance parity with the extension consumer (#8560)
- Preserve integer trailing zeros when
szDecimals=0inperpsFormatters(#8560) - Preserve candle pagination cancellation and skip coalesce for explicit-
endTimecandle paging to avoid stale pages (#8560) - Defer account resolution on the non-paginated cache path to prevent race conditions (#8560)
- Force-refresh on activity mount and evict expired coalesce entries so stale promises cannot resolve to cache (#8560)
- Normalize
event.userto lowercase when caching the spot-state WS address so#ensureSpotStatehits the cache instead of triggering a redundant RESTspotClearinghouseStaterefetch when HyperLiquid returns a checksummed address (#8560)
- Add
isAbortErrorutility export fromutilsfor distinguishing expected cancellation errors from real failures (#8515)
TradingService.flipPosition()no longer passes stale positionentryPriceascurrentPriceon reverse-position orders; providers now validate and price flips against live market data (#8515)
- Remove unused
ESTIMATED_FEE_RATEexport fromconstants/hyperLiquidConfig(dead code after reverse-position fee precheck was removed) (#8515)
- Suppress noisy Sentry reports from expected historical-candle fetch cancellations (
AbortError) during navigation, while preserving real error reporting inHyperLiquidClientServiceandMarketDataService(#8515)
- Preserve the
webpackIgnoresafeguard on theMYXProviderdynamic import in built dist files so extension consumers do not statically resolve the intentionally-unpublished MYX provider module (#8473) - Use HTTP transport for HyperLiquid candle snapshots and refresh DEX discovery cache handling to avoid rapid market-switching 429s after syncing the latest mobile perps controller state (#8473)
- Add disk-backed cold-start cache for instant data display on launch (#8460)
- Add
skipTTLoption togetCachedMarketDataForActiveProviderandgetCachedUserDataForActiveProvider(#8460) - Add perps decimal formatters (
perpsFormatters) for shared formatting utilities (#8460) - Add
FUNDING_RATE_CONFIGconstants for funding rate display formatting (#8460) - Add
buildProviderCacheKeyandgetProviderNetworkKeyhelper exports (#8460)
- Bump
@metamask/transaction-controllerfrom^64.0.0to^64.1.0(#8432) - Bump
@metamask/base-controllerfrom^9.0.1to^9.1.0(#8457)
- Fix TP/SL orders disappearing after creating a market order by filtering on
isPositionTpsl(#8460) - Fix missing latest funding payments by using paginated fetch with auto-split (#8460)
- Fix WebSocket reconnection on foreground return when socket is still alive (#8460)
- Export
PerpsControllerGetStateActiontype (#8352) - Expose missing public
PerpsControllermethods through its messenger (#8352)- The following actions are now available:
PerpsController:calculateLiquidationPricePerpsController:calculateMaintenanceMarginPerpsController:clearDepositResultPerpsController:clearWithdrawResultPerpsController:completeWithdrawalFromHistoryPerpsController:depositWithConfirmationPerpsController:depositWithOrderPerpsController:fetchHistoricalCandlesPerpsController:flipPositionPerpsController:getActiveProviderPerpsController:getActiveProviderOrNullPerpsController:getAvailableDexsPerpsController:getBlockExplorerUrlPerpsController:getCachedMarketDataForActiveProviderPerpsController:getCachedUserDataForActiveProviderPerpsController:getCurrentNetworkPerpsController:getMarketDataWithPricesPerpsController:getMaxLeveragePerpsController:getWatchlistMarketsPerpsController:getWebSocketConnectionStatePerpsController:getWithdrawalProgressPerpsController:getWithdrawalRoutesPerpsController:initPerpsController:isCurrentlyReinitializingPerpsController:isFirstTimeUserOnCurrentNetworkPerpsController:isWatchlistMarketPerpsController:reconnectPerpsController:setLiveDataConfigPerpsController:startMarketDataPreloadPerpsController:stopMarketDataPreloadPerpsController:subscribeToAccountPerpsController:subscribeToCandlesPerpsController:subscribeToConnectionStatePerpsController:subscribeToOICapsPerpsController:subscribeToOrderBookPerpsController:subscribeToOrderFillsPerpsController:subscribeToOrdersPerpsController:subscribeToPositionsPerpsController:subscribeToPricesPerpsController:switchProviderPerpsController:toggleWatchlistMarketPerpsController:updateMarginPerpsController:updatePositionTPSLPerpsController:updateWithdrawalProgressPerpsController:updateWithdrawalStatusPerpsController:validateClosePositionPerpsController:validateOrderPerpsController:validateWithdrawal
- Corresponding action types are available as well.
- The following actions are now available:
- Add
completeWithdrawalFromHistorymethod for FIFO-based withdrawal completion matching (#8333) - Add
lastCompletedWithdrawalTimestampandlastCompletedWithdrawalTxHashesstate fields (#8333)
- Refactor pending withdraw/deposit tracking to FIFO queue design (#8333)
- Centralize Arbitrum network check in deposit hooks to prevent missing network errors (#8333)
- Provider credentials, builder fee injection, and env var centralization (#8333)
- Reduce max order amount by 0.5% buffer to avoid insufficient margin rejections (#8333)
- Bump
@metamask/account-tree-controllerfrom^6.0.0to^7.0.0(#8325) - Bump
@metamask/profile-sync-controllerfrom^28.0.1to^28.0.2(#8325) - Bump
@metamask/controller-utilsfrom^11.19.0to^11.20.0(#8344) - Bump
@metamask/messengerfrom^1.0.0to^1.1.1(#8364, #8373) - Move
@myx-trade/sdkfromdependenciestooptionalDependenciesso consumers (extension, mobile) do not install it automatically (#8398)- Combined with the MYX adapter export removal below, this prevents
@myx-trade/sdkfrom entering the consumer's static webpack/metro import graph MYXProvidercontinues to load@myx-trade/sdkvia dynamicimport()whenMM_PERPS_MYX_PROVIDER_ENABLED=true
- Combined with the MYX adapter export removal below, this prevents
- Add
/* webpackIgnore: true */magic comment to theMYXProviderdynamic import so webpack (extension) skips static resolution of the intentionally-unshipped module (#8398)
- BREAKING: Remove
adaptMarketFromMYX,adaptPriceFromMYX,adaptMarketDataFromMYX,filterMYXExclusiveMarkets,isOverlappingMarket,buildPoolSymbolMap,buildSymbolPoolsMap, andextractSymbolFromPoolIdfrom the public package exports to prevent@myx-trade/sdkfrom being included in the static webpack bundle (#8398)- These functions are still used internally by
MYXProvider, which is loaded via dynamic import - Consumers that imported these utilities directly should instead import from
@metamask/perps-controller/src/utils/myxAdapteror duplicate the logic locally
- These functions are still used internally by
- Preserve
/* webpackIgnore: true */magic comment in built dist files by using a variable for the MYXProvider dynamic import path, preventing ts-bridge from rewriting the AST node and stripping the comment (#8424) - Fix incorrect fee estimate when flipping a position (#8333)
- Fix incorrect PnL and order size displayed after SL execution (#8333)
- Fix stop loss not showing up in recent activity (#8333)
- Fix incorrect market categories (#8333)
- Fix TP/SL decimal precision for PUMP (#8333)
- Fix missing decimal on price input when using preset on limit price (#8333)
- Sync mobile perps code to core (mobile branch
feat/perps/core-resolver) (#8291) - Add
@metamask/geolocation-controllerdependency for eligibility geolocation checks (#8291) - Exclude
MYXWalletServicefrom published package files (#8291) - MYX provider improvements: enhanced error handling, wallet service integration (#8291)
- HyperLiquid provider improvements: subscription reliability, order book processing (#8291)
- Eligibility service refactored for geolocation-based region blocking (#8291)
- Bump
@metamask/base-controllerfrom^9.0.0to^9.0.1(#8317) - Bump
@metamask/messengerfrom^0.3.0to^1.0.0(#8317)
- Exclude
@myx-trade/sdkfrom build output by default, reducing bundled size by ~57% (#8234) - MYX provider files are excluded from the package when publishing
- Static import of
MYXProviderreplaced with dynamicimport()that depends uponMM_PERPS_MYX_PROVIDER_ENABLED=trueto break the eager dependency chain
- Add
stopEligibilityMonitoring()method to pause geo-blocking eligibility checks when basic functionality is disabled (#8214)
- feat: defer eligibility to allow for onboarding to proceed without le… (#8197)
- Bump
@metamask/profile-sync-controllerfrom^27.1.0to^28.0.0(#8162) - Bump
@metamask/account-tree-controllerfrom^5.0.0to^5.0.1(#8162)
- Initial release (#7654, #7941)
- Add full
PerpsControllerwith multi-provider architecture, state management, and messenger integration - Add
HyperLiquidProviderwith complete DEX integration: trading, market data, order book, WebSocket subscriptions, wallet operations, and HIP-3 builder-deployed perpetuals support - Add
MYXProviderwith DEX integration: trading, market data, and account management - Add
AggregatedPerpsProviderfor multi-provider aggregation and unified market/position views - Add
ProviderRouterfor routing operations to the appropriate provider based on market configuration - Add
SubscriptionMultiplexerfor real-time WebSocket data aggregation across providers - Add
TradingServicefor order placement, modification, cancellation, and position management - Add
MarketDataServicefor market listing, pricing, funding rates, and order book data - Add
AccountServicefor account state, balances, positions, and open orders - Add
DepositServicefor deposit flow handling - Add
EligibilityServicefor user eligibility verification - Add
FeatureFlagConfigurationServicefor runtime feature flag management - Add
HyperLiquidClientService,HyperLiquidSubscriptionService, andHyperLiquidWalletServicefor HyperLiquid-specific operations - Add
MYXClientServicefor MYX-specific API operations - Add
DataLakeServicefor data lake integration - Add
RewardsIntegrationServicefor rewards system integration - Add
TradingReadinessCachefor caching trading readiness state - Add
ServiceContextfor service dependency injection - Add comprehensive type definitions for perps, HyperLiquid, MYX, configuration, tokens, and transactions
- Add utility functions for market data transformation, order calculations, account operations, validation, and adapters
- Add state selectors for accessing controller state
- Add error code definitions for structured error handling
- Add configuration constants for HyperLiquid, MYX, charts, order types, and performance metrics
- Add platform-agnostic design via
PerpsPlatformDependenciesinjection interface - Add generated method action types for messenger-exposed methods
- Add full
- Bump
@metamask/controller-utilsfrom^11.18.0to^11.19.0(#7995)