@metamask-previews/perps-controller 10.0.0-preview-beea66146 → 10.0.0-preview-7b60eca
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 +5 -0
- package/dist/providers/HyperLiquidProvider.cjs +76 -1
- 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 +77 -2
- package/dist/providers/HyperLiquidProvider.mjs.map +1 -1
- package/dist/utils/errorUtils.cjs +17 -1
- package/dist/utils/errorUtils.cjs.map +1 -1
- package/dist/utils/errorUtils.d.cts +12 -0
- package/dist/utils/errorUtils.d.cts.map +1 -1
- package/dist/utils/errorUtils.d.mts +12 -0
- package/dist/utils/errorUtils.d.mts.map +1 -1
- package/dist/utils/errorUtils.mjs +15 -0
- package/dist/utils/errorUtils.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -34,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
34
34
|
- **BREAKING:** Add `EXCHANGE_MULTI_SIG_REQUIRED` and `EXCHANGE_INVALID_NONCE` to `PERPS_ERROR_CODES` for HyperLiquid exchange rejections that previously surfaced as raw `"multi-sig required"` / `"invalid nonce"` strings (TAT-3633) ([#9750](https://github.com/MetaMask/core/pull/9750))
|
|
35
35
|
- Like `EXCHANGE_ACCOUNT_NOT_FOUND` above, this widens the exported `PerpsErrorCode` union, so consumers that key an exhaustive `Record<PerpsErrorCode, …>` stop compiling until they add entries for both new codes — including Mobile's `app/components/UI/Perps/utils/translatePerpsError.ts` and Extension's `ui/components/app/perps/utils/translate-perps-error.ts`.
|
|
36
36
|
- To migrate: add translation entries for both codes before bumping. `EXCHANGE_MULTI_SIG_REQUIRED` means the account requires a multi-sig wrapper for exchange writes; `EXCHANGE_INVALID_NONCE` means the action nonce was stale or reused and the request should be retried.
|
|
37
|
+
- Add `isHyperLiquidMultiSigRequiredError(error)` (exported from `@metamask/perps-controller/utils/*`), which classifies HyperLiquid's `Multi-sig required` rejection — matching the hyphenated spelling observed in the wild and the unhyphenated variant defensively (TAT-3214) ([#9769](https://github.com/MetaMask/core/pull/9769))
|
|
37
38
|
|
|
38
39
|
### Changed
|
|
39
40
|
|
|
@@ -91,6 +92,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
91
92
|
- Size the max order amount off the price a resting limit order is submitted at, fixing `order 0: insufficient margin to place order` rejections on max-size limit orders resting above the market price ([#9694](https://github.com/MetaMask/core/pull/9694))
|
|
92
93
|
- `getMaxAllowedAmount` derived the maximum from the market price, but HyperLiquid reserves initial margin for a resting order against the price that order is submitted at. A max-size limit order resting above the market price - typically a sell - therefore reserved more margin than the account had and the exchange rejected it.
|
|
93
94
|
- `getMaxAllowedAmount` now accepts optional `orderType` and `limitPrice` params. When a limit order rests above the market price the maximum is scaled by `limitPrice / marketPrice`; orders at or below the market price, and market orders, are unchanged. Both params are optional, so existing callers keep the previous behavior.
|
|
95
|
+
- Skip the unified-account migration for HyperLiquid multi-sig accounts, fixing the `ApiRequestError: Multi-sig required` error raised on every Perps entry for such an account (TAT-3214) ([#9769](https://github.com/MetaMask/core/pull/9769))
|
|
96
|
+
- HyperLiquid rejects every single-signer exchange write for an account converted to multi-sig, so the silent `agentSetAbstraction` (and user-signed `userSetAbstraction`) migration could never succeed. `HyperLiquidProvider` now reads `userToMultiSigSigners` immediately before the migration write and, for a multi-sig account, skips it, emits the `Perp Account Setup` event with `status: not_applicable` / `error_message: multi_sig_account`, and records `{ attempted: true, enabled: false }` in the trading-readiness cache so the attempt is not repeated. The signer lookup only runs when a migration write would otherwise be made, so accounts already on `unifiedAccount` / `portfolioMargin` and deferred `dexAbstraction` accounts are unaffected.
|
|
97
|
+
- The same rejection is now classified in the migration's error handler, covering the case where the account is converted between the lookup and the write, so it is no longer reported to the error logger as a failed setup.
|
|
98
|
+
- Unified account mode stays off for these accounts; HIP-3 collateral continues to be handled by the existing programmatic transfer fallback.
|
|
94
99
|
|
|
95
100
|
## [10.0.0]
|
|
96
101
|
|
|
@@ -10,7 +10,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
10
10
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
11
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
12
|
};
|
|
13
|
-
var _HyperLiquidProvider_instances, _HyperLiquidProvider_deps, _HyperLiquidProvider_clientService, _HyperLiquidProvider_walletService, _HyperLiquidProvider_subscriptionService, _HyperLiquidProvider_symbolToAssetId, _HyperLiquidProvider_userFeeCache, _HyperLiquidProvider_maxLeverageCache, _HyperLiquidProvider_cachedMetaByDex, _HyperLiquidProvider_cachedMarketDataWithPrices, _HyperLiquidProvider_cachedSpotMeta, _HyperLiquidProvider_dexDiscoveryCache, _HyperLiquidProvider_referralCheckCache, _HyperLiquidProvider_builderFeeCheckCache, _HyperLiquidProvider_ensureReadyPromise, _HyperLiquidProvider_pendingBuilderFeeApprovals, _HyperLiquidProvider_compiledAllowlistPatterns, _HyperLiquidProvider_compiledBlocklistPatterns, _HyperLiquidProvider_userFeeDiscountBips, _HyperLiquidProvider_hip3Enabled, _HyperLiquidProvider_allowlistMarkets, _HyperLiquidProvider_blocklistMarkets, _HyperLiquidProvider_useUnifiedAccount, _HyperLiquidProvider_dexDiscoveryComplete, _HyperLiquidProvider_unifiedAccountSetupNeedsRetry, _HyperLiquidProvider_pendingValidatedDexsPromise, _HyperLiquidProvider_cachedUsdcTokenId, _HyperLiquidProvider_errorMappings, _HyperLiquidProvider_clientsInitialized, _HyperLiquidProvider_initializationPromise, _HyperLiquidProvider_messenger, _HyperLiquidProvider_builderAddressTestnet, _HyperLiquidProvider_builderAddressMainnet, _HyperLiquidProvider_priceDeviationLimit, _HyperLiquidProvider_compilePatternsSafely, _HyperLiquidProvider_ensureClientsInitialized, _HyperLiquidProvider_isWalletOnHyperliquid, _HyperLiquidProvider_ensureUnifiedAccountEnabled, _HyperLiquidProvider_ensureReady, _HyperLiquidProvider_tradingSetupPromise, _HyperLiquidProvider_tradingSetupComplete, _HyperLiquidProvider_ensureReadyForTrading, _HyperLiquidProvider_getOrFetchPrice, _HyperLiquidProvider_filterFills, _HyperLiquidProvider_getAllAvailableDexs, _HyperLiquidProvider_getValidatedDexs, _HyperLiquidProvider_fetchValidatedDexsInternal, _HyperLiquidProvider_getCachedMeta, _HyperLiquidProvider_backfillAssetMapForDex, _HyperLiquidProvider_getAssetIdWithRepair, _HyperLiquidProvider_getCachedSpotMeta, _HyperLiquidProvider_getCachedPerpDexs, _HyperLiquidProvider_calculateHip3FeeMultiplier, _HyperLiquidProvider_getCacheKey, _HyperLiquidProvider_fetchMarketsForDex, _HyperLiquidProvider_getUsdcTokenId, _HyperLiquidProvider_isUsdcCollateralDex, _HyperLiquidProvider_buildAssetMapping, _HyperLiquidProvider_queryUserDataAcrossDexs, _HyperLiquidProvider_mapError, _HyperLiquidProvider_getErrorContext, _HyperLiquidProvider_isMappedAccountModeExchangeError, _HyperLiquidProvider_getTradingErrorContext, _HyperLiquidProvider_checkBuilderFeeApproval, _HyperLiquidProvider_ensureBuilderFeeApproval, _HyperLiquidProvider_checkBuilderFeeStatus, _HyperLiquidProvider_getBalanceForDex, _HyperLiquidProvider_findSourceDexWithBalance, _HyperLiquidProvider_autoTransferForHip3Order, _HyperLiquidProvider_autoTransferBackAfterClose, _HyperLiquidProvider_calculateHip3RequiredMargin, _HyperLiquidProvider_handleHip3PostOrderRebalance, _HyperLiquidProvider_handleHip3OrderRollback, _HyperLiquidProvider_validateOrderBeforePlacement, _HyperLiquidProvider_getAssetInfo, _HyperLiquidProvider_prepareAssetForTrading, _HyperLiquidProvider_handleHip3PreOrder, _HyperLiquidProvider_submitOrderWithRollback, _HyperLiquidProvider_handleOrderError, _HyperLiquidProvider_fetchOpenOrders, _HyperLiquidProvider_resolveReplacementOrderId, _HyperLiquidProvider_getStandaloneValidatedDexs, _HyperLiquidProvider_queryDexPositions, _HyperLiquidProvider_getAllMids, _HyperLiquidProvider_fetchSingleDexFresh, _HyperLiquidProvider_excludeNonUsdcCollateralResults, _HyperLiquidProvider_mergeDexResultsInto, _HyperLiquidProvider_cacheFreshMarketDataSnapshot, _HyperLiquidProvider_getStaleMarketDataSnapshot, _HyperLiquidProvider_isFeeCacheValid, _HyperLiquidProvider_getBuilderAddress, _HyperLiquidProvider_getReferralCode, _HyperLiquidProvider_ensureReferralSet, _HyperLiquidProvider_isReferralCodeReady, _HyperLiquidProvider_checkReferralSet, _HyperLiquidProvider_setReferralCode;
|
|
13
|
+
var _HyperLiquidProvider_instances, _HyperLiquidProvider_deps, _HyperLiquidProvider_clientService, _HyperLiquidProvider_walletService, _HyperLiquidProvider_subscriptionService, _HyperLiquidProvider_symbolToAssetId, _HyperLiquidProvider_userFeeCache, _HyperLiquidProvider_maxLeverageCache, _HyperLiquidProvider_cachedMetaByDex, _HyperLiquidProvider_cachedMarketDataWithPrices, _HyperLiquidProvider_cachedSpotMeta, _HyperLiquidProvider_dexDiscoveryCache, _HyperLiquidProvider_referralCheckCache, _HyperLiquidProvider_builderFeeCheckCache, _HyperLiquidProvider_ensureReadyPromise, _HyperLiquidProvider_pendingBuilderFeeApprovals, _HyperLiquidProvider_compiledAllowlistPatterns, _HyperLiquidProvider_compiledBlocklistPatterns, _HyperLiquidProvider_userFeeDiscountBips, _HyperLiquidProvider_hip3Enabled, _HyperLiquidProvider_allowlistMarkets, _HyperLiquidProvider_blocklistMarkets, _HyperLiquidProvider_useUnifiedAccount, _HyperLiquidProvider_dexDiscoveryComplete, _HyperLiquidProvider_unifiedAccountSetupNeedsRetry, _HyperLiquidProvider_pendingValidatedDexsPromise, _HyperLiquidProvider_cachedUsdcTokenId, _HyperLiquidProvider_errorMappings, _HyperLiquidProvider_clientsInitialized, _HyperLiquidProvider_initializationPromise, _HyperLiquidProvider_messenger, _HyperLiquidProvider_builderAddressTestnet, _HyperLiquidProvider_builderAddressMainnet, _HyperLiquidProvider_priceDeviationLimit, _HyperLiquidProvider_compilePatternsSafely, _HyperLiquidProvider_ensureClientsInitialized, _HyperLiquidProvider_isWalletOnHyperliquid, _HyperLiquidProvider_isHyperliquidMultiSigAccount, _HyperLiquidProvider_ensureUnifiedAccountEnabled, _HyperLiquidProvider_ensureReady, _HyperLiquidProvider_tradingSetupPromise, _HyperLiquidProvider_tradingSetupComplete, _HyperLiquidProvider_ensureReadyForTrading, _HyperLiquidProvider_getOrFetchPrice, _HyperLiquidProvider_filterFills, _HyperLiquidProvider_getAllAvailableDexs, _HyperLiquidProvider_getValidatedDexs, _HyperLiquidProvider_fetchValidatedDexsInternal, _HyperLiquidProvider_getCachedMeta, _HyperLiquidProvider_backfillAssetMapForDex, _HyperLiquidProvider_getAssetIdWithRepair, _HyperLiquidProvider_getCachedSpotMeta, _HyperLiquidProvider_getCachedPerpDexs, _HyperLiquidProvider_calculateHip3FeeMultiplier, _HyperLiquidProvider_getCacheKey, _HyperLiquidProvider_fetchMarketsForDex, _HyperLiquidProvider_getUsdcTokenId, _HyperLiquidProvider_isUsdcCollateralDex, _HyperLiquidProvider_buildAssetMapping, _HyperLiquidProvider_queryUserDataAcrossDexs, _HyperLiquidProvider_mapError, _HyperLiquidProvider_getErrorContext, _HyperLiquidProvider_isMappedAccountModeExchangeError, _HyperLiquidProvider_getTradingErrorContext, _HyperLiquidProvider_checkBuilderFeeApproval, _HyperLiquidProvider_ensureBuilderFeeApproval, _HyperLiquidProvider_checkBuilderFeeStatus, _HyperLiquidProvider_getBalanceForDex, _HyperLiquidProvider_findSourceDexWithBalance, _HyperLiquidProvider_autoTransferForHip3Order, _HyperLiquidProvider_autoTransferBackAfterClose, _HyperLiquidProvider_calculateHip3RequiredMargin, _HyperLiquidProvider_handleHip3PostOrderRebalance, _HyperLiquidProvider_handleHip3OrderRollback, _HyperLiquidProvider_validateOrderBeforePlacement, _HyperLiquidProvider_getAssetInfo, _HyperLiquidProvider_prepareAssetForTrading, _HyperLiquidProvider_handleHip3PreOrder, _HyperLiquidProvider_submitOrderWithRollback, _HyperLiquidProvider_handleOrderError, _HyperLiquidProvider_fetchOpenOrders, _HyperLiquidProvider_resolveReplacementOrderId, _HyperLiquidProvider_getStandaloneValidatedDexs, _HyperLiquidProvider_queryDexPositions, _HyperLiquidProvider_getAllMids, _HyperLiquidProvider_fetchSingleDexFresh, _HyperLiquidProvider_excludeNonUsdcCollateralResults, _HyperLiquidProvider_mergeDexResultsInto, _HyperLiquidProvider_cacheFreshMarketDataSnapshot, _HyperLiquidProvider_getStaleMarketDataSnapshot, _HyperLiquidProvider_isFeeCacheValid, _HyperLiquidProvider_getBuilderAddress, _HyperLiquidProvider_getReferralCode, _HyperLiquidProvider_ensureReferralSet, _HyperLiquidProvider_isReferralCodeReady, _HyperLiquidProvider_checkReferralSet, _HyperLiquidProvider_setReferralCode;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.HyperLiquidProvider = void 0;
|
|
16
16
|
const utils_1 = require("@metamask/utils");
|
|
@@ -4395,6 +4395,38 @@ async function _HyperLiquidProvider_isWalletOnHyperliquid(userAddress, network)
|
|
|
4395
4395
|
});
|
|
4396
4396
|
return true;
|
|
4397
4397
|
}
|
|
4398
|
+
}, _HyperLiquidProvider_isHyperliquidMultiSigAccount =
|
|
4399
|
+
/**
|
|
4400
|
+
* Decide whether the Hyperliquid account is a multi-sig account.
|
|
4401
|
+
*
|
|
4402
|
+
* Hyperliquid rejects every single-signer exchange write for a converted
|
|
4403
|
+
* multi-sig account with `ApiRequestError: Multi-sig required`, so the
|
|
4404
|
+
* unified-account migration must not be attempted for those accounts.
|
|
4405
|
+
*
|
|
4406
|
+
* If the probe throws (transient network), returns `false` — fail open so
|
|
4407
|
+
* one bad probe never blocks migration for a normal single-signer account.
|
|
4408
|
+
* The `isHyperLiquidMultiSigRequiredError` fallback in the write's catch
|
|
4409
|
+
* block remains the safety net.
|
|
4410
|
+
*
|
|
4411
|
+
* @param userAddress - The wallet address to check.
|
|
4412
|
+
* @returns True only when Hyperliquid reports a multi-sig signer set.
|
|
4413
|
+
* @private
|
|
4414
|
+
*/
|
|
4415
|
+
async function _HyperLiquidProvider_isHyperliquidMultiSigAccount(userAddress) {
|
|
4416
|
+
try {
|
|
4417
|
+
const infoClient = __classPrivateFieldGet(this, _HyperLiquidProvider_clientService, "f").getInfoClient();
|
|
4418
|
+
const signers = await infoClient.userToMultiSigSigners({
|
|
4419
|
+
user: userAddress,
|
|
4420
|
+
});
|
|
4421
|
+
return signers !== null && signers !== undefined;
|
|
4422
|
+
}
|
|
4423
|
+
catch (error) {
|
|
4424
|
+
__classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('[isHyperliquidMultiSigAccount] Probe failed, assuming single-signer', {
|
|
4425
|
+
user: userAddress,
|
|
4426
|
+
error: (0, errorUtils_js_1.ensureError)(error, 'HyperLiquidProvider.isHyperliquidMultiSigAccount').message,
|
|
4427
|
+
});
|
|
4428
|
+
return false;
|
|
4429
|
+
}
|
|
4398
4430
|
}, _HyperLiquidProvider_ensureUnifiedAccountEnabled =
|
|
4399
4431
|
/**
|
|
4400
4432
|
* Attempt to enable HyperLiquid Unified Account mode for HIP-3 orders
|
|
@@ -4533,6 +4565,29 @@ async function _HyperLiquidProvider_ensureUnifiedAccountEnabled(options) {
|
|
|
4533
4565
|
completeInFlight();
|
|
4534
4566
|
return;
|
|
4535
4567
|
}
|
|
4568
|
+
// Hyperliquid rejects every single-signer exchange write for a converted
|
|
4569
|
+
// multi-sig account with "ApiRequestError: Multi-sig required", which
|
|
4570
|
+
// surfaced on the Perps tab on every entry (TAT-3214). Probe right
|
|
4571
|
+
// before the write so accounts that never reach one (already compatible,
|
|
4572
|
+
// deferred, unknown mode) do not pay the extra round trip.
|
|
4573
|
+
const isMultiSig = await __classPrivateFieldGet(this, _HyperLiquidProvider_instances, "m", _HyperLiquidProvider_isHyperliquidMultiSigAccount).call(this, userAddress);
|
|
4574
|
+
if (isMultiSig) {
|
|
4575
|
+
__classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('[ensureUnifiedAccountEnabled] Multi-sig account, skipping unified account migration', { user: userAddress, network, mode: currentMode });
|
|
4576
|
+
__classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").metrics.trackPerpsEvent(index_js_1.PerpsAnalyticsEvent.AccountSetup, {
|
|
4577
|
+
[eventNames_js_1.PERPS_EVENT_PROPERTY.PREVIOUS_ABSTRACTION_MODE]: currentMode,
|
|
4578
|
+
[eventNames_js_1.PERPS_EVENT_PROPERTY.STATUS]: eventNames_js_1.PERPS_EVENT_VALUE.STATUS.NOT_APPLICABLE,
|
|
4579
|
+
[eventNames_js_1.PERPS_EVENT_PROPERTY.ERROR_MESSAGE]: 'multi_sig_account',
|
|
4580
|
+
});
|
|
4581
|
+
// Final state: the write can never succeed for this account, so cache
|
|
4582
|
+
// it as attempted with unified mode off. Perps keeps working through
|
|
4583
|
+
// the programmatic collateral-transfer fallback.
|
|
4584
|
+
TradingReadinessCache_js_1.TradingReadinessCache.set(network, userAddress, {
|
|
4585
|
+
attempted: true,
|
|
4586
|
+
enabled: false,
|
|
4587
|
+
});
|
|
4588
|
+
completeInFlight();
|
|
4589
|
+
return;
|
|
4590
|
+
}
|
|
4536
4591
|
// Track which mode users are currently on before we attempt migration.
|
|
4537
4592
|
// This tells us the distribution of legacy modes across our user base.
|
|
4538
4593
|
__classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").metrics.trackPerpsEvent(index_js_1.PerpsAnalyticsEvent.AccountSetup, {
|
|
@@ -4610,6 +4665,26 @@ async function _HyperLiquidProvider_ensureUnifiedAccountEnabled(options) {
|
|
|
4610
4665
|
completeInFlight();
|
|
4611
4666
|
return;
|
|
4612
4667
|
}
|
|
4668
|
+
// Safety net for the multi-sig probe: the account can be converted
|
|
4669
|
+
// between the lookup and the write, and the probe fails open on
|
|
4670
|
+
// transient info-API errors. Either way the rejection is a permanent
|
|
4671
|
+
// account-shape condition, not a failure worth reporting or retrying.
|
|
4672
|
+
if ((0, errorUtils_js_1.isHyperLiquidMultiSigRequiredError)(error)) {
|
|
4673
|
+
__classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('[ensureUnifiedAccountEnabled] Multi-sig account (race/probe fallback), skipping unified account migration', { user: userAddress, network, mode: currentMode });
|
|
4674
|
+
__classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").metrics.trackPerpsEvent(index_js_1.PerpsAnalyticsEvent.AccountSetup, {
|
|
4675
|
+
...(currentMode && {
|
|
4676
|
+
[eventNames_js_1.PERPS_EVENT_PROPERTY.PREVIOUS_ABSTRACTION_MODE]: currentMode,
|
|
4677
|
+
}),
|
|
4678
|
+
[eventNames_js_1.PERPS_EVENT_PROPERTY.STATUS]: eventNames_js_1.PERPS_EVENT_VALUE.STATUS.NOT_APPLICABLE,
|
|
4679
|
+
[eventNames_js_1.PERPS_EVENT_PROPERTY.ERROR_MESSAGE]: 'multi_sig_account',
|
|
4680
|
+
});
|
|
4681
|
+
TradingReadinessCache_js_1.TradingReadinessCache.set(network, userAddress, {
|
|
4682
|
+
attempted: true,
|
|
4683
|
+
enabled: false,
|
|
4684
|
+
});
|
|
4685
|
+
completeInFlight();
|
|
4686
|
+
return;
|
|
4687
|
+
}
|
|
4613
4688
|
// Cache failure ONLY for the user-prompted path
|
|
4614
4689
|
// (`dexAbstraction → unifiedAccount` via `userSetAbstraction`). The
|
|
4615
4690
|
// rationale for caching is "don't re-prompt a user who already saw the
|