@metamask-previews/perps-controller 4.0.0-preview-e0eba6dbb → 4.0.0-preview-56dd1249f

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.
Files changed (64) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/constants/eventNames.cjs +5 -0
  3. package/dist/constants/eventNames.cjs.map +1 -1
  4. package/dist/constants/eventNames.d.cts +4 -0
  5. package/dist/constants/eventNames.d.cts.map +1 -1
  6. package/dist/constants/eventNames.d.mts +4 -0
  7. package/dist/constants/eventNames.d.mts.map +1 -1
  8. package/dist/constants/eventNames.mjs +5 -0
  9. package/dist/constants/eventNames.mjs.map +1 -1
  10. package/dist/providers/HyperLiquidProvider.cjs +230 -57
  11. package/dist/providers/HyperLiquidProvider.cjs.map +1 -1
  12. package/dist/providers/HyperLiquidProvider.d.cts +1 -1
  13. package/dist/providers/HyperLiquidProvider.d.cts.map +1 -1
  14. package/dist/providers/HyperLiquidProvider.d.mts +1 -1
  15. package/dist/providers/HyperLiquidProvider.d.mts.map +1 -1
  16. package/dist/providers/HyperLiquidProvider.mjs +230 -57
  17. package/dist/providers/HyperLiquidProvider.mjs.map +1 -1
  18. package/dist/services/HyperLiquidSubscriptionService.cjs +108 -20
  19. package/dist/services/HyperLiquidSubscriptionService.cjs.map +1 -1
  20. package/dist/services/HyperLiquidSubscriptionService.d.cts +19 -0
  21. package/dist/services/HyperLiquidSubscriptionService.d.cts.map +1 -1
  22. package/dist/services/HyperLiquidSubscriptionService.d.mts +19 -0
  23. package/dist/services/HyperLiquidSubscriptionService.d.mts.map +1 -1
  24. package/dist/services/HyperLiquidSubscriptionService.mjs +108 -20
  25. package/dist/services/HyperLiquidSubscriptionService.mjs.map +1 -1
  26. package/dist/services/HyperLiquidWalletService.cjs +20 -0
  27. package/dist/services/HyperLiquidWalletService.cjs.map +1 -1
  28. package/dist/services/HyperLiquidWalletService.d.cts +6 -0
  29. package/dist/services/HyperLiquidWalletService.d.cts.map +1 -1
  30. package/dist/services/HyperLiquidWalletService.d.mts +6 -0
  31. package/dist/services/HyperLiquidWalletService.d.mts.map +1 -1
  32. package/dist/services/HyperLiquidWalletService.mjs +22 -2
  33. package/dist/services/HyperLiquidWalletService.mjs.map +1 -1
  34. package/dist/services/TradingReadinessCache.cjs +16 -16
  35. package/dist/services/TradingReadinessCache.cjs.map +1 -1
  36. package/dist/services/TradingReadinessCache.d.cts +12 -12
  37. package/dist/services/TradingReadinessCache.d.mts +12 -12
  38. package/dist/services/TradingReadinessCache.mjs +16 -16
  39. package/dist/services/TradingReadinessCache.mjs.map +1 -1
  40. package/dist/types/hyperliquid-types.cjs +39 -0
  41. package/dist/types/hyperliquid-types.cjs.map +1 -1
  42. package/dist/types/hyperliquid-types.d.cts +34 -2
  43. package/dist/types/hyperliquid-types.d.cts.map +1 -1
  44. package/dist/types/hyperliquid-types.d.mts +34 -2
  45. package/dist/types/hyperliquid-types.d.mts.map +1 -1
  46. package/dist/types/hyperliquid-types.mjs +37 -1
  47. package/dist/types/hyperliquid-types.mjs.map +1 -1
  48. package/dist/types/index.cjs +1 -0
  49. package/dist/types/index.cjs.map +1 -1
  50. package/dist/types/index.d.cts +2 -1
  51. package/dist/types/index.d.cts.map +1 -1
  52. package/dist/types/index.d.mts +2 -1
  53. package/dist/types/index.d.mts.map +1 -1
  54. package/dist/types/index.mjs +1 -0
  55. package/dist/types/index.mjs.map +1 -1
  56. package/dist/utils/accountUtils.cjs +20 -8
  57. package/dist/utils/accountUtils.cjs.map +1 -1
  58. package/dist/utils/accountUtils.d.cts +9 -5
  59. package/dist/utils/accountUtils.d.cts.map +1 -1
  60. package/dist/utils/accountUtils.d.mts +9 -5
  61. package/dist/utils/accountUtils.d.mts.map +1 -1
  62. package/dist/utils/accountUtils.mjs +20 -8
  63. package/dist/utils/accountUtils.mjs.map +1 -1
  64. package/package.json +3 -3
@@ -10,11 +10,12 @@ 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_useDexAbstraction, _HyperLiquidProvider_dexDiscoveryComplete, _HyperLiquidProvider_pendingValidatedDexsPromise, _HyperLiquidProvider_cachedUsdcTokenId, _HyperLiquidProvider_errorMappings, _HyperLiquidProvider_clientsInitialized, _HyperLiquidProvider_initializationPromise, _HyperLiquidProvider_messenger, _HyperLiquidProvider_builderAddressTestnet, _HyperLiquidProvider_builderAddressMainnet, _HyperLiquidProvider_compilePatternsSafely, _HyperLiquidProvider_ensureClientsInitialized, _HyperLiquidProvider_ensureDexAbstractionEnabled, _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_isUsdhCollateralDex, _HyperLiquidProvider_getSpotUsdhBalance, _HyperLiquidProvider_getSpotUsdcBalance, _HyperLiquidProvider_transferUsdcToSpot, _HyperLiquidProvider_swapUsdcToUsdh, _HyperLiquidProvider_ensureUsdhCollateralForOrder, _HyperLiquidProvider_buildAssetMapping, _HyperLiquidProvider_queryUserDataAcrossDexs, _HyperLiquidProvider_mapError, _HyperLiquidProvider_getErrorContext, _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_getStandaloneValidatedDexs, _HyperLiquidProvider_getAllMids, _HyperLiquidProvider_fetchSingleDexFresh, _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_compilePatternsSafely, _HyperLiquidProvider_ensureClientsInitialized, _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_isUsdhCollateralDex, _HyperLiquidProvider_getSpotUsdhBalance, _HyperLiquidProvider_getSpotUsdcBalance, _HyperLiquidProvider_transferUsdcToSpot, _HyperLiquidProvider_swapUsdcToUsdh, _HyperLiquidProvider_ensureUsdhCollateralForOrder, _HyperLiquidProvider_buildAssetMapping, _HyperLiquidProvider_queryUserDataAcrossDexs, _HyperLiquidProvider_mapError, _HyperLiquidProvider_getErrorContext, _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_getStandaloneValidatedDexs, _HyperLiquidProvider_getAllMids, _HyperLiquidProvider_fetchSingleDexFresh, _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");
17
17
  const uuid_1 = require("uuid");
18
+ const eventNames_1 = require("../constants/eventNames.cjs");
18
19
  const hyperLiquidConfig_1 = require("../constants/hyperLiquidConfig.cjs");
19
20
  const perpsConfig_1 = require("../constants/perpsConfig.cjs");
20
21
  const transactionsHistoryConfig_1 = require("../constants/transactionsHistoryConfig.cjs");
@@ -24,6 +25,8 @@ const HyperLiquidClientService_1 = require("../services/HyperLiquidClientService
24
25
  const HyperLiquidSubscriptionService_1 = require("../services/HyperLiquidSubscriptionService.cjs");
25
26
  const HyperLiquidWalletService_1 = require("../services/HyperLiquidWalletService.cjs");
26
27
  const TradingReadinessCache_1 = require("../services/TradingReadinessCache.cjs");
28
+ const types_1 = require("../types/index.cjs");
29
+ const hyperliquid_types_1 = require("../types/hyperliquid-types.cjs");
27
30
  const accountUtils_1 = require("../utils/accountUtils.cjs");
28
31
  const errorUtils_1 = require("../utils/errorUtils.cjs");
29
32
  const hyperLiquidAdapter_1 = require("../utils/hyperLiquidAdapter.cjs");
@@ -99,11 +102,23 @@ class HyperLiquidProvider {
99
102
  _HyperLiquidProvider_hip3Enabled.set(this, void 0);
100
103
  _HyperLiquidProvider_allowlistMarkets.set(this, void 0);
101
104
  _HyperLiquidProvider_blocklistMarkets.set(this, void 0);
102
- _HyperLiquidProvider_useDexAbstraction.set(this, void 0);
105
+ // Emergency kill-switch for the Unified Account migration flow. Defaults
106
+ // to true and is the expected production state after HL's DEX Abstraction
107
+ // deprecation. Kept as a constructor option (not removed) so we can
108
+ // disable the migration via a hot-fix release if a regression surfaces
109
+ // in the wild — flipping this to false reverts to the legacy programmatic
110
+ // HIP-3 transfer path that already lives in the codebase.
111
+ _HyperLiquidProvider_useUnifiedAccount.set(this, void 0);
103
112
  // True once DEX discovery has succeeded with real data (not a fallback).
104
113
  // When false, #ensureReadyPromise is reset after each init so the next
105
114
  // caller retries DEX discovery instead of reusing a degraded mapping.
106
115
  _HyperLiquidProvider_dexDiscoveryComplete.set(this, false);
116
+ // True when the most recent #ensureUnifiedAccountEnabled run ended in a
117
+ // transient state that warrants retry (silent agent-key failure, REST
118
+ // userAbstraction lookup failure, or keyring locked). #ensureReady resets
119
+ // its memoized promise when this is set so the next entry retries the
120
+ // migration instead of returning the cached resolved promise.
121
+ _HyperLiquidProvider_unifiedAccountSetupNeedsRetry.set(this, false);
107
122
  // Pending promise to deduplicate concurrent getValidatedDexs() calls
108
123
  _HyperLiquidProvider_pendingValidatedDexsPromise.set(this, null);
109
124
  // Cache for USDC token ID from spot metadata
@@ -144,8 +159,8 @@ class HyperLiquidProvider {
144
159
  __classPrivateFieldSet(this, _HyperLiquidProvider_hip3Enabled, options.hip3Enabled ?? false, "f");
145
160
  __classPrivateFieldSet(this, _HyperLiquidProvider_allowlistMarkets, options.allowlistMarkets ?? [], "f");
146
161
  __classPrivateFieldSet(this, _HyperLiquidProvider_blocklistMarkets, options.blocklistMarkets ?? [], "f");
147
- // Attempt native balance abstraction, fallback to programmatic transfer if unsupported
148
- __classPrivateFieldSet(this, _HyperLiquidProvider_useDexAbstraction, options.useDexAbstraction ?? true, "f");
162
+ // Attempt unified account mode, fallback to programmatic transfer if unsupported
163
+ __classPrivateFieldSet(this, _HyperLiquidProvider_useUnifiedAccount, options.useUnifiedAccount ?? true, "f");
149
164
  // Initialize services with injected platform dependencies
150
165
  __classPrivateFieldSet(this, _HyperLiquidProvider_clientService, new HyperLiquidClientService_1.HyperLiquidClientService(__classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f"), {
151
166
  isTestnet,
@@ -744,7 +759,7 @@ class HyperLiquidProvider {
744
759
  const closeSize = Math.abs(positionSize);
745
760
  const totalMarginUsed = parseFloat(position.marginUsed);
746
761
  // Track HIP-3 transfers (full position close means all margin is freed)
747
- if (isHip3Position && dexName && !__classPrivateFieldGet(this, _HyperLiquidProvider_useDexAbstraction, "f")) {
762
+ if (isHip3Position && dexName && !__classPrivateFieldGet(this, _HyperLiquidProvider_useUnifiedAccount, "f")) {
748
763
  hip3Transfers.push({
749
764
  sourceDex: dexName,
750
765
  freedMargin: totalMarginUsed,
@@ -798,7 +813,7 @@ class HyperLiquidProvider {
798
813
  ((0, utils_1.hasProperty)(stat, 'filled') || (0, utils_1.hasProperty)(stat, 'resting'))).length;
799
814
  const failureCount = statuses.length - successCount;
800
815
  // Handle HIP-3 margin transfers for successful closes
801
- if (!__classPrivateFieldGet(this, _HyperLiquidProvider_useDexAbstraction, "f")) {
816
+ if (!__classPrivateFieldGet(this, _HyperLiquidProvider_useUnifiedAccount, "f")) {
802
817
  for (let i = 0; i < statuses.length; i++) {
803
818
  const status = statuses[i];
804
819
  const isSuccess = isStatusObject(status) &&
@@ -1166,7 +1181,7 @@ class HyperLiquidProvider {
1166
1181
  if (result.success &&
1167
1182
  isHip3Position &&
1168
1183
  hip3Dex &&
1169
- !__classPrivateFieldGet(this, _HyperLiquidProvider_useDexAbstraction, "f")) {
1184
+ !__classPrivateFieldGet(this, _HyperLiquidProvider_useUnifiedAccount, "f")) {
1170
1185
  __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('Position closed successfully, initiating manual auto-transfer back');
1171
1186
  // Non-blocking: Transfer freed margin back to main DEX
1172
1187
  await __classPrivateFieldGet(this, _HyperLiquidProvider_instances, "m", _HyperLiquidProvider_autoTransferBackAfterClose).call(this, {
@@ -1177,8 +1192,8 @@ class HyperLiquidProvider {
1177
1192
  else if (result.success &&
1178
1193
  isHip3Position &&
1179
1194
  hip3Dex &&
1180
- __classPrivateFieldGet(this, _HyperLiquidProvider_useDexAbstraction, "f")) {
1181
- __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('Position closed - DEX abstraction will auto-return freed margin', {
1195
+ __classPrivateFieldGet(this, _HyperLiquidProvider_useUnifiedAccount, "f")) {
1196
+ __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('Position closed - Unified Account will auto-return freed margin', {
1182
1197
  coin: params.symbol,
1183
1198
  dex: hip3Dex,
1184
1199
  note: 'HyperLiquid handles return automatically',
@@ -1935,7 +1950,7 @@ class HyperLiquidProvider {
1935
1950
  isTestnet: __classPrivateFieldGet(this, _HyperLiquidProvider_clientService, "f").isTestnetMode(),
1936
1951
  });
1937
1952
  const dexs = await __classPrivateFieldGet(this, _HyperLiquidProvider_instances, "m", _HyperLiquidProvider_getStandaloneValidatedDexs).call(this);
1938
- const [standaloneSpotStateResult, standalonePerpsResults] = await Promise.all([
1953
+ const [standaloneSpotStateResult, standalonePerpsResults, standaloneAbstractionResult,] = await Promise.all([
1939
1954
  standaloneInfoClient
1940
1955
  .spotClearinghouseState({ user: userAddress })
1941
1956
  .catch((error) => {
@@ -1945,11 +1960,21 @@ class HyperLiquidProvider {
1945
1960
  return null;
1946
1961
  }),
1947
1962
  (0, standaloneInfoClient_1.queryStandaloneClearinghouseStates)(standaloneInfoClient, userAddress, dexs),
1963
+ standaloneInfoClient
1964
+ .userAbstraction({ user: userAddress })
1965
+ .catch((error) => {
1966
+ __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('Standalone userAbstraction fetch failed; spot fold disabled until the mode resolves', {
1967
+ error: (0, errorUtils_1.ensureError)(error, 'HyperLiquidProvider.getAccountState.standalone.abstraction').message,
1968
+ });
1969
+ return null;
1970
+ }),
1948
1971
  ]);
1949
1972
  // Aggregate account states across all DEXs, then apply spot-backed
1950
1973
  // adjustments so streamed/standalone/full paths report the same totals.
1951
1974
  const dexAccountStates = standalonePerpsResults.map((perpsState) => (0, hyperLiquidAdapter_1.adaptAccountStateFromSDK)(perpsState));
1952
- const aggregatedAccountState = (0, accountUtils_1.addSpotBalanceToAccountState)((0, accountUtils_1.aggregateAccountStates)(dexAccountStates), standaloneSpotStateResult);
1975
+ const aggregatedAccountState = (0, accountUtils_1.addSpotBalanceToAccountState)((0, accountUtils_1.aggregateAccountStates)(dexAccountStates), standaloneSpotStateResult, {
1976
+ foldIntoCollateral: (0, hyperliquid_types_1.hyperLiquidModeFoldsSpot)(standaloneAbstractionResult),
1977
+ });
1953
1978
  __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('HyperLiquidProvider: standalone account state fetched', { totalBalance: aggregatedAccountState.totalBalance });
1954
1979
  return aggregatedAccountState;
1955
1980
  }
@@ -1963,11 +1988,20 @@ class HyperLiquidProvider {
1963
1988
  __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('Network mode:', __classPrivateFieldGet(this, _HyperLiquidProvider_clientService, "f").isTestnetMode() ? 'TESTNET' : 'MAINNET');
1964
1989
  // Get Spot balance (global, not DEX-specific) and Perps states across all DEXs.
1965
1990
  // One transient DEX failure should not blank the entire account state.
1966
- const [spotStateResult, perpsStateResult] = await Promise.allSettled([
1991
+ const [spotStateResult, perpsStateResult, abstractionResult] = await Promise.allSettled([
1967
1992
  infoClient.spotClearinghouseState({ user: userAddress }),
1968
1993
  __classPrivateFieldGet(this, _HyperLiquidProvider_instances, "m", _HyperLiquidProvider_queryUserDataAcrossDexs).call(this, { user: userAddress }, (userParam) => infoClient.clearinghouseState(userParam)),
1994
+ infoClient.userAbstraction({ user: userAddress }),
1969
1995
  ]);
1970
1996
  const spotState = spotStateResult.status === 'fulfilled' ? spotStateResult.value : null;
1997
+ const abstractionMode = abstractionResult.status === 'fulfilled'
1998
+ ? abstractionResult.value
1999
+ : null;
2000
+ if (abstractionResult.status === 'rejected') {
2001
+ __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('User abstraction fetch failed; spot fold disabled until the mode resolves', {
2002
+ error: (0, errorUtils_1.ensureError)(abstractionResult.reason, 'HyperLiquidProvider.getAccountState.abstraction').message,
2003
+ });
2004
+ }
1971
2005
  const perpsResponse = perpsStateResult.status === 'fulfilled'
1972
2006
  ? perpsStateResult.value
1973
2007
  : {
@@ -2014,7 +2048,9 @@ class HyperLiquidProvider {
2014
2048
  });
2015
2049
  return dexAccountState;
2016
2050
  });
2017
- const aggregatedAccountState = (0, accountUtils_1.addSpotBalanceToAccountState)((0, accountUtils_1.aggregateAccountStates)(dexAccountStates), spotState);
2051
+ const aggregatedAccountState = (0, accountUtils_1.addSpotBalanceToAccountState)((0, accountUtils_1.aggregateAccountStates)(dexAccountStates), spotState, {
2052
+ foldIntoCollateral: (0, hyperliquid_types_1.hyperLiquidModeFoldsSpot)(abstractionMode),
2053
+ });
2018
2054
  // Build per-sub-account breakdown (HIP-3 DEXs map to sub-accounts)
2019
2055
  const subAccountBreakdown = {};
2020
2056
  perpsStateResults.forEach((result) => {
@@ -2688,14 +2724,20 @@ class HyperLiquidProvider {
2688
2724
  // Step 4: Ensure client is ready
2689
2725
  __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('HyperLiquidProvider: ENSURING CLIENT READY');
2690
2726
  await __classPrivateFieldGet(this, _HyperLiquidProvider_instances, "m", _HyperLiquidProvider_ensureReady).call(this);
2727
+ await __classPrivateFieldGet(this, _HyperLiquidProvider_instances, "m", _HyperLiquidProvider_ensureUnifiedAccountEnabled).call(this, { allowUserSigning: true });
2691
2728
  const exchangeClient = __classPrivateFieldGet(this, _HyperLiquidProvider_clientService, "f").getExchangeClient();
2692
2729
  __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('HyperLiquidProvider: CLIENT READY');
2693
2730
  // Step 5: Validate amount against account balance
2694
2731
  __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('HyperLiquidProvider: CHECKING ACCOUNT BALANCE');
2695
2732
  const accountState = await this.getAccountState();
2696
- const availableBalance = parseFloat(accountState.availableBalance);
2733
+ // Release-branch bridge for Unified Account: availableToTradeBalance
2734
+ // includes collateral HL can draw in target mode. The larger balance
2735
+ // contract will replace this with an explicit withdrawableBalance field.
2736
+ const availableBalance = parseFloat(accountState.availableToTradeBalance ?? accountState.availableBalance);
2697
2737
  __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('HyperLiquidProvider: ACCOUNT BALANCE', {
2698
2738
  availableBalance,
2739
+ clearinghouseAvailableBalance: accountState.availableBalance,
2740
+ availableToTradeBalance: accountState.availableToTradeBalance,
2699
2741
  totalBalance: accountState.totalBalance,
2700
2742
  marginUsed: accountState.marginUsed,
2701
2743
  unrealizedPnl: accountState.unrealizedPnl,
@@ -3508,7 +3550,7 @@ class HyperLiquidProvider {
3508
3550
  // Clear session caches (ensures fresh state on reconnect/account switch)
3509
3551
  __classPrivateFieldGet(this, _HyperLiquidProvider_referralCheckCache, "f").clear();
3510
3552
  __classPrivateFieldGet(this, _HyperLiquidProvider_builderFeeCheckCache, "f").clear();
3511
- // NOTE: DexAbstractionCache is global and NOT cleared on disconnect
3553
+ // NOTE: UnifiedAccountCache is global and NOT cleared on disconnect
3512
3554
  // to prevent repeated signing requests across reconnections
3513
3555
  __classPrivateFieldGet(this, _HyperLiquidProvider_cachedMetaByDex, "f").clear();
3514
3556
  __classPrivateFieldSet(this, _HyperLiquidProvider_cachedSpotMeta, null, "f");
@@ -3689,7 +3731,7 @@ class HyperLiquidProvider {
3689
3731
  }
3690
3732
  }
3691
3733
  exports.HyperLiquidProvider = HyperLiquidProvider;
3692
- _HyperLiquidProvider_deps = new WeakMap(), _HyperLiquidProvider_clientService = new WeakMap(), _HyperLiquidProvider_walletService = new WeakMap(), _HyperLiquidProvider_subscriptionService = new WeakMap(), _HyperLiquidProvider_symbolToAssetId = new WeakMap(), _HyperLiquidProvider_userFeeCache = new WeakMap(), _HyperLiquidProvider_maxLeverageCache = new WeakMap(), _HyperLiquidProvider_cachedMetaByDex = new WeakMap(), _HyperLiquidProvider_cachedMarketDataWithPrices = new WeakMap(), _HyperLiquidProvider_cachedSpotMeta = new WeakMap(), _HyperLiquidProvider_dexDiscoveryCache = new WeakMap(), _HyperLiquidProvider_referralCheckCache = new WeakMap(), _HyperLiquidProvider_builderFeeCheckCache = new WeakMap(), _HyperLiquidProvider_ensureReadyPromise = new WeakMap(), _HyperLiquidProvider_pendingBuilderFeeApprovals = new WeakMap(), _HyperLiquidProvider_compiledAllowlistPatterns = new WeakMap(), _HyperLiquidProvider_compiledBlocklistPatterns = new WeakMap(), _HyperLiquidProvider_userFeeDiscountBips = new WeakMap(), _HyperLiquidProvider_hip3Enabled = new WeakMap(), _HyperLiquidProvider_allowlistMarkets = new WeakMap(), _HyperLiquidProvider_blocklistMarkets = new WeakMap(), _HyperLiquidProvider_useDexAbstraction = new WeakMap(), _HyperLiquidProvider_dexDiscoveryComplete = new WeakMap(), _HyperLiquidProvider_pendingValidatedDexsPromise = new WeakMap(), _HyperLiquidProvider_cachedUsdcTokenId = new WeakMap(), _HyperLiquidProvider_errorMappings = new WeakMap(), _HyperLiquidProvider_clientsInitialized = new WeakMap(), _HyperLiquidProvider_initializationPromise = new WeakMap(), _HyperLiquidProvider_messenger = new WeakMap(), _HyperLiquidProvider_builderAddressTestnet = new WeakMap(), _HyperLiquidProvider_builderAddressMainnet = new WeakMap(), _HyperLiquidProvider_tradingSetupPromise = new WeakMap(), _HyperLiquidProvider_tradingSetupComplete = new WeakMap(), _HyperLiquidProvider_instances = new WeakSet(), _HyperLiquidProvider_compilePatternsSafely = function _HyperLiquidProvider_compilePatternsSafely(patterns, listName) {
3734
+ _HyperLiquidProvider_deps = new WeakMap(), _HyperLiquidProvider_clientService = new WeakMap(), _HyperLiquidProvider_walletService = new WeakMap(), _HyperLiquidProvider_subscriptionService = new WeakMap(), _HyperLiquidProvider_symbolToAssetId = new WeakMap(), _HyperLiquidProvider_userFeeCache = new WeakMap(), _HyperLiquidProvider_maxLeverageCache = new WeakMap(), _HyperLiquidProvider_cachedMetaByDex = new WeakMap(), _HyperLiquidProvider_cachedMarketDataWithPrices = new WeakMap(), _HyperLiquidProvider_cachedSpotMeta = new WeakMap(), _HyperLiquidProvider_dexDiscoveryCache = new WeakMap(), _HyperLiquidProvider_referralCheckCache = new WeakMap(), _HyperLiquidProvider_builderFeeCheckCache = new WeakMap(), _HyperLiquidProvider_ensureReadyPromise = new WeakMap(), _HyperLiquidProvider_pendingBuilderFeeApprovals = new WeakMap(), _HyperLiquidProvider_compiledAllowlistPatterns = new WeakMap(), _HyperLiquidProvider_compiledBlocklistPatterns = new WeakMap(), _HyperLiquidProvider_userFeeDiscountBips = new WeakMap(), _HyperLiquidProvider_hip3Enabled = new WeakMap(), _HyperLiquidProvider_allowlistMarkets = new WeakMap(), _HyperLiquidProvider_blocklistMarkets = new WeakMap(), _HyperLiquidProvider_useUnifiedAccount = new WeakMap(), _HyperLiquidProvider_dexDiscoveryComplete = new WeakMap(), _HyperLiquidProvider_unifiedAccountSetupNeedsRetry = new WeakMap(), _HyperLiquidProvider_pendingValidatedDexsPromise = new WeakMap(), _HyperLiquidProvider_cachedUsdcTokenId = new WeakMap(), _HyperLiquidProvider_errorMappings = new WeakMap(), _HyperLiquidProvider_clientsInitialized = new WeakMap(), _HyperLiquidProvider_initializationPromise = new WeakMap(), _HyperLiquidProvider_messenger = new WeakMap(), _HyperLiquidProvider_builderAddressTestnet = new WeakMap(), _HyperLiquidProvider_builderAddressMainnet = new WeakMap(), _HyperLiquidProvider_tradingSetupPromise = new WeakMap(), _HyperLiquidProvider_tradingSetupComplete = new WeakMap(), _HyperLiquidProvider_instances = new WeakSet(), _HyperLiquidProvider_compilePatternsSafely = function _HyperLiquidProvider_compilePatternsSafely(patterns, listName) {
3693
3735
  const compiled = [];
3694
3736
  for (const pattern of patterns) {
3695
3737
  try {
@@ -3760,9 +3802,9 @@ async function _HyperLiquidProvider_ensureClientsInitialized() {
3760
3802
  // so future calls can retry if needed
3761
3803
  __classPrivateFieldSet(this, _HyperLiquidProvider_initializationPromise, null, "f");
3762
3804
  }
3763
- }, _HyperLiquidProvider_ensureDexAbstractionEnabled =
3805
+ }, _HyperLiquidProvider_ensureUnifiedAccountEnabled =
3764
3806
  /**
3765
- * Attempt to enable HIP-3 native balance abstraction
3807
+ * Attempt to enable HyperLiquid Unified Account mode for HIP-3 orders
3766
3808
  *
3767
3809
  * If successful, HyperLiquid automatically manages collateral transfers for HIP-3 orders.
3768
3810
  * If not supported, disables the flag to trigger programmatic transfer fallback.
@@ -3770,10 +3812,24 @@ async function _HyperLiquidProvider_ensureClientsInitialized() {
3770
3812
  * IMPORTANT: Uses global singleton cache to prevent repeated signing requests
3771
3813
  * across provider reconnections (critical for hardware wallets).
3772
3814
  *
3815
+ * @param options - Optional configuration.
3816
+ * @param options.allowUserSigning - When true, runs the EIP-712 user-signed migration for `dexAbstraction` accounts. Defaults to false so init does not surface a signing prompt; action-time entry points (trading, withdraw) pass true.
3773
3817
  * @private
3774
3818
  */
3775
- async function _HyperLiquidProvider_ensureDexAbstractionEnabled() {
3776
- if (!__classPrivateFieldGet(this, _HyperLiquidProvider_useDexAbstraction, "f")) {
3819
+ async function _HyperLiquidProvider_ensureUnifiedAccountEnabled(options) {
3820
+ // dexAbstraction unifiedAccount requires an EIP-712 prompt (HL blocks
3821
+ // the agent path for that transition). Init calls with allowUserSigning=false so
3822
+ // viewing the Perps section never surfaces a signing dialog. Trading and
3823
+ // withdraw entry points pass allowUserSigning=true to drive the migration when
3824
+ // the user actually intends to act.
3825
+ const allowUserSigning = options?.allowUserSigning ?? false;
3826
+ // Optimistic reset — set true below only at the failure points that
3827
+ // warrant retry (silent agent failure, REST lookup failure, keyring
3828
+ // locked). Final-state outcomes (success, prompted-failure cached,
3829
+ // already-on-compatible, defer, unknown mode, feature off) leave it
3830
+ // false so #ensureReady can keep the memoized promise.
3831
+ __classPrivateFieldSet(this, _HyperLiquidProvider_unifiedAccountSetupNeedsRetry, false, "f");
3832
+ if (!__classPrivateFieldGet(this, _HyperLiquidProvider_useUnifiedAccount, "f")) {
3777
3833
  return; // Feature disabled
3778
3834
  }
3779
3835
  const userAddress = await __classPrivateFieldGet(this, _HyperLiquidProvider_walletService, "f").getUserAddressWithDefault();
@@ -3782,7 +3838,7 @@ async function _HyperLiquidProvider_ensureDexAbstractionEnabled() {
3782
3838
  // This is CRITICAL for hardware wallets to prevent QR popup spam
3783
3839
  const cachedStatus = TradingReadinessCache_1.TradingReadinessCache.get(network, userAddress);
3784
3840
  if (cachedStatus?.attempted) {
3785
- __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('HyperLiquidProvider: DEX abstraction already attempted (from global cache)', {
3841
+ __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('HyperLiquidProvider: Unified Account setup already attempted (from global cache)', {
3786
3842
  user: userAddress,
3787
3843
  network,
3788
3844
  enabled: cachedStatus.enabled,
@@ -3792,75 +3848,178 @@ async function _HyperLiquidProvider_ensureDexAbstractionEnabled() {
3792
3848
  }
3793
3849
  // Check if another provider instance is currently attempting this operation
3794
3850
  // This prevents concurrent signing attempts across providers during reconnection
3795
- const inFlightPromise = TradingReadinessCache_1.PerpsSigningCache.isInFlight('dexAbstraction', network, userAddress);
3851
+ const inFlightPromise = TradingReadinessCache_1.PerpsSigningCache.isInFlight('unifiedAccount', network, userAddress);
3796
3852
  if (inFlightPromise) {
3797
- __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('HyperLiquidProvider: DEX abstraction in-flight, waiting...', { network, userAddress });
3853
+ __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('HyperLiquidProvider: Unified Account setup in-flight, waiting...', { network, userAddress });
3798
3854
  await inFlightPromise;
3799
- return; // After waiting, the cache should be set by the other provider
3855
+ // The other instance may have finished without writing the cache (e.g.
3856
+ // an init-time call deferred a dexAbstraction migration). If the cache
3857
+ // is still empty and we are an action-time caller (allowUserSigning=true),
3858
+ // we must run our own attempt — otherwise the trade/withdraw would
3859
+ // proceed in the deprecated mode.
3860
+ const postWaitCache = TradingReadinessCache_1.TradingReadinessCache.get(network, userAddress);
3861
+ if (postWaitCache?.attempted) {
3862
+ return;
3863
+ }
3864
+ // Fall through to acquire our own lock and retry.
3800
3865
  }
3801
3866
  // Set in-flight lock to prevent concurrent attempts
3802
- const completeInFlight = TradingReadinessCache_1.PerpsSigningCache.setInFlight('dexAbstraction', network, userAddress);
3867
+ const completeInFlight = TradingReadinessCache_1.PerpsSigningCache.setInFlight('unifiedAccount', network, userAddress);
3868
+ let currentMode;
3803
3869
  try {
3804
3870
  // Re-check cache after acquiring lock (another provider might have finished)
3805
3871
  const recheckCache = TradingReadinessCache_1.TradingReadinessCache.get(network, userAddress);
3806
3872
  if (recheckCache?.attempted) {
3807
- __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('HyperLiquidProvider: DEX abstraction completed by another provider', { network, userAddress });
3873
+ __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('HyperLiquidProvider: Unified Account setup completed by another provider', { network, userAddress });
3808
3874
  completeInFlight();
3809
3875
  return;
3810
3876
  }
3811
3877
  const infoClient = __classPrivateFieldGet(this, _HyperLiquidProvider_clientService, "f").getInfoClient();
3812
- // Check if already enabled on-chain (returns boolean | null)
3813
- const isEnabled = await infoClient.userDexAbstraction({
3878
+ // Check current abstraction mode on-chain
3879
+ currentMode = await infoClient.userAbstraction({
3814
3880
  user: userAddress,
3815
3881
  });
3816
- if (isEnabled === true) {
3817
- __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('HyperLiquidProvider: DEX abstraction already enabled on-chain', { user: userAddress, network });
3818
- // Cache the enabled status to skip future checks
3882
+ if (currentMode === 'unifiedAccount' ||
3883
+ currentMode === 'portfolioMargin') {
3884
+ // portfolioMargin is a superset of unifiedAccount it already supports
3885
+ // auto-collateral management for HIP-3 orders and is more capital-efficient.
3886
+ // Downgrading portfolio margin users to unifiedAccount would be harmful,
3887
+ // so we treat both modes as already-enabled and skip migration.
3888
+ __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('HyperLiquidProvider: Account already in a compatible mode, skipping migration', { user: userAddress, network, mode: currentMode });
3889
+ __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").metrics.trackPerpsEvent(types_1.PerpsAnalyticsEvent.AccountSetup, {
3890
+ [eventNames_1.PERPS_EVENT_PROPERTY.ABSTRACTION_MODE]: currentMode,
3891
+ [eventNames_1.PERPS_EVENT_PROPERTY.STATUS]: eventNames_1.PERPS_EVENT_VALUE.STATUS.ALREADY_ENABLED,
3892
+ });
3819
3893
  TradingReadinessCache_1.TradingReadinessCache.set(network, userAddress, {
3820
3894
  attempted: true,
3821
3895
  enabled: true,
3822
3896
  });
3897
+ // Record the resolved mode in the subscription service so the next
3898
+ // aggregation folds spot correctly without waiting for #refreshSpotState.
3899
+ __classPrivateFieldGet(this, _HyperLiquidProvider_subscriptionService, "f").setUserAbstractionMode(userAddress, currentMode);
3900
+ completeInFlight();
3901
+ return;
3902
+ }
3903
+ // Defer the user-signed transition until the user attempts an action.
3904
+ // Cache is intentionally left untouched so the next entry re-evaluates;
3905
+ // the read-only userAbstraction call is cheap and gated by the in-flight
3906
+ // lock, preventing concurrent prompts.
3907
+ if (currentMode === 'dexAbstraction' && !allowUserSigning) {
3908
+ __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('HyperLiquidProvider: Deferring dexAbstraction → unifiedAccount migration to action time', { user: userAddress, network });
3823
3909
  completeInFlight();
3824
3910
  return;
3825
3911
  }
3826
- // Enable DEX abstraction (one-time, irreversible, requires signature)
3827
- __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('HyperLiquidProvider: Enabling DEX abstraction (requires signature)', {
3912
+ // Bail on unknown modes BEFORE firing analytics or attempting dispatch.
3913
+ // Keeps `migration_required` actionable (only fires for modes we can
3914
+ // actually migrate) and avoids re-emitting on every reconnection.
3915
+ if (currentMode !== 'dexAbstraction' &&
3916
+ currentMode !== 'default' &&
3917
+ currentMode !== 'disabled') {
3918
+ __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('HyperLiquidProvider: Unknown abstraction mode, skipping Unified Account migration', { user: userAddress, network, mode: currentMode });
3919
+ completeInFlight();
3920
+ return;
3921
+ }
3922
+ // Track which mode users are currently on before we attempt migration.
3923
+ // This tells us the distribution of legacy modes across our user base.
3924
+ __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").metrics.trackPerpsEvent(types_1.PerpsAnalyticsEvent.AccountSetup, {
3925
+ [eventNames_1.PERPS_EVENT_PROPERTY.ABSTRACTION_MODE]: currentMode,
3926
+ [eventNames_1.PERPS_EVENT_PROPERTY.STATUS]: eventNames_1.PERPS_EVENT_VALUE.STATUS.MIGRATION_REQUIRED,
3927
+ });
3928
+ // Enable Unified Account mode.
3929
+ // - default / disabled: agent wallet can do this silently (no prompt)
3930
+ // - dexAbstraction: HL blocks the agent transition — requires the user's main
3931
+ // wallet to sign an EIP-712 action via userSetAbstraction (one-time prompt)
3932
+ __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('HyperLiquidProvider: Enabling Unified Account mode', {
3828
3933
  user: userAddress,
3829
3934
  network,
3935
+ previousMode: currentMode,
3830
3936
  note: 'HyperLiquid will auto-manage collateral for HIP-3 orders',
3831
3937
  });
3832
3938
  const exchangeClient = __classPrivateFieldGet(this, _HyperLiquidProvider_clientService, "f").getExchangeClient();
3833
- await exchangeClient.agentEnableDexAbstraction();
3834
- __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log(' HyperLiquidProvider: DEX abstraction enabled successfully');
3835
- // Cache success to prevent re-attempts on reconnection
3939
+ if (currentMode === 'dexAbstraction') {
3940
+ // Requires EIP-712 signature from the user's main wallet (one-time migration).
3941
+ // HL blocks the dexAbstraction unifiedAccount transition via the agent wallet,
3942
+ // so userSetAbstraction (user-signed) is the only path for legacy users.
3943
+ await exchangeClient.userSetAbstraction({
3944
+ user: userAddress,
3945
+ abstraction: hyperliquid_types_1.HL_UNIFIED_ACCOUNT_MODE,
3946
+ });
3947
+ }
3948
+ else {
3949
+ // default / disabled — silent agent transition, no user prompt
3950
+ await exchangeClient.agentSetAbstraction({
3951
+ abstraction: hyperliquid_types_1.HL_ABSTRACTION_WIRE.unifiedAccount,
3952
+ });
3953
+ }
3954
+ __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('✅ HyperLiquidProvider: Unified Account enabled successfully');
3955
+ __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").metrics.trackPerpsEvent(types_1.PerpsAnalyticsEvent.AccountSetup, {
3956
+ [eventNames_1.PERPS_EVENT_PROPERTY.PREVIOUS_ABSTRACTION_MODE]: currentMode,
3957
+ [eventNames_1.PERPS_EVENT_PROPERTY.ABSTRACTION_MODE]: hyperliquid_types_1.HL_UNIFIED_ACCOUNT_MODE,
3958
+ [eventNames_1.PERPS_EVENT_PROPERTY.STATUS]: eventNames_1.PERPS_EVENT_VALUE.STATUS.SUCCESS,
3959
+ });
3836
3960
  TradingReadinessCache_1.TradingReadinessCache.set(network, userAddress, {
3837
3961
  attempted: true,
3838
3962
  enabled: true,
3839
3963
  });
3964
+ // Record the post-migration mode in the subscription service so it
3965
+ // immediately re-aggregates with fold=true and surfaces the unified
3966
+ // balance rather than waiting for the next #refreshSpotState.
3967
+ __classPrivateFieldGet(this, _HyperLiquidProvider_subscriptionService, "f").setUserAbstractionMode(userAddress, hyperliquid_types_1.HL_UNIFIED_ACCOUNT_MODE);
3840
3968
  completeInFlight();
3841
3969
  }
3842
3970
  catch (error) {
3843
3971
  // If keyring is locked, don't cache so it retries when unlocked
3844
3972
  if ((0, errorUtils_1.ensureError)(error).message === perpsErrorCodes_1.PERPS_ERROR_CODES.KEYRING_LOCKED) {
3845
- __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('[ensureDexAbstractionEnabled] Keyring locked, will retry later');
3973
+ __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('[ensureUnifiedAccountEnabled] Keyring locked, will retry later');
3974
+ __classPrivateFieldSet(this, _HyperLiquidProvider_unifiedAccountSetupNeedsRetry, true, "f");
3846
3975
  completeInFlight();
3847
3976
  return;
3848
3977
  }
3849
- // Cache the attempt (even on failure) to prevent repeated signing requests
3850
- // This is CRITICAL for hardware wallets - if user rejects, don't ask again
3851
- TradingReadinessCache_1.TradingReadinessCache.set(network, userAddress, {
3852
- attempted: true,
3853
- enabled: false,
3854
- });
3855
- __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('HyperLiquidProvider: DEX abstraction failed, cached to prevent retries', {
3978
+ // Cache failure ONLY for the user-prompted path
3979
+ // (`dexAbstraction unifiedAccount` via `userSetAbstraction`). The
3980
+ // rationale for caching is "don't re-prompt a user who already saw the
3981
+ // signature dialog and rejected it" — that doesn't apply to:
3982
+ // - Read-only userAbstraction lookup failures (no prompt; transient).
3983
+ // - Silent agent-key paths (`default`/`disabled` → `agentSetAbstraction`
3984
+ // does not show a UI prompt; failures are typically transient HL
3985
+ // outages and pinning them would leave users stuck in the
3986
+ // deprecated mode for the rest of the session).
3987
+ // Action-time retries pick up the unmigrated state and try again.
3988
+ if (currentMode === 'dexAbstraction') {
3989
+ TradingReadinessCache_1.TradingReadinessCache.set(network, userAddress, {
3990
+ attempted: true,
3991
+ enabled: false,
3992
+ });
3993
+ }
3994
+ else {
3995
+ // Silent agent-key failure (default/disabled) or read-only
3996
+ // userAbstraction lookup failure — neither is a final state, so
3997
+ // signal #ensureReady to drop its memoized promise and retry on
3998
+ // the next entry instead of pinning the user in the deprecated
3999
+ // mode for the provider's lifetime.
4000
+ __classPrivateFieldSet(this, _HyperLiquidProvider_unifiedAccountSetupNeedsRetry, true, "f");
4001
+ }
4002
+ const errorMessage = (0, errorUtils_1.ensureError)(error, 'HyperLiquidProvider.ensureUnifiedAccountEnabled').message;
4003
+ __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('HyperLiquidProvider: Unified Account setup failed', {
3856
4004
  user: userAddress,
3857
4005
  network,
3858
- error: (0, errorUtils_1.ensureError)(error, 'HyperLiquidProvider.ensureDexAbstractionEnabled').message,
4006
+ error: errorMessage,
4007
+ // Cache writes only happen on the user-prompted dexAbstraction
4008
+ // path (see P2-B logic above). Reflect that here so retry
4009
+ // behaviour is debuggable from the log alone.
4010
+ cached: currentMode === 'dexAbstraction',
4011
+ });
4012
+ __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").metrics.trackPerpsEvent(types_1.PerpsAnalyticsEvent.AccountSetup, {
4013
+ ...(currentMode && {
4014
+ [eventNames_1.PERPS_EVENT_PROPERTY.PREVIOUS_ABSTRACTION_MODE]: currentMode,
4015
+ [eventNames_1.PERPS_EVENT_PROPERTY.ABSTRACTION_MODE]: hyperliquid_types_1.HL_UNIFIED_ACCOUNT_MODE,
4016
+ }),
4017
+ [eventNames_1.PERPS_EVENT_PROPERTY.STATUS]: eventNames_1.PERPS_EVENT_VALUE.STATUS.FAILED,
4018
+ [eventNames_1.PERPS_EVENT_PROPERTY.ERROR_MESSAGE]: errorMessage,
3859
4019
  });
3860
4020
  completeInFlight();
3861
- // Don't blindly disable the flag on any error
3862
- __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").logger.error((0, errorUtils_1.ensureError)(error, 'HyperLiquidProvider.ensureDexAbstractionEnabled'), __classPrivateFieldGet(this, _HyperLiquidProvider_instances, "m", _HyperLiquidProvider_getErrorContext).call(this, 'ensureDexAbstractionEnabled', {
3863
- note: 'Could not enable DEX abstraction (may already be enabled, user rejected, or network error)',
4021
+ __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").logger.error((0, errorUtils_1.ensureError)(error, 'HyperLiquidProvider.ensureUnifiedAccountEnabled'), __classPrivateFieldGet(this, _HyperLiquidProvider_instances, "m", _HyperLiquidProvider_getErrorContext).call(this, 'ensureUnifiedAccountEnabled', {
4022
+ note: 'Could not enable Unified Account (user rejected, or network error)',
3864
4023
  }));
3865
4024
  }
3866
4025
  }, _HyperLiquidProvider_ensureReady =
@@ -3894,9 +4053,14 @@ async function _HyperLiquidProvider_ensureReady() {
3894
4053
  });
3895
4054
  await __classPrivateFieldGet(this, _HyperLiquidProvider_instances, "m", _HyperLiquidProvider_buildAssetMapping).call(this);
3896
4055
  }
3897
- // NOTE: Signing operations (DEX abstraction, builder fee, referral) are now DEFERRED
3898
- // They are called on-demand in ensureReadyForTrading() when user attempts to trade
3899
- // This prevents QR popups when just viewing the Perps section (critical for hardware wallets)
4056
+ // Attempt Unified Account migration as early as possible so users aren't
4057
+ // blocked when they try to trade. Software-wallet dexAbstraction users can
4058
+ // complete the one-time EIP-712 migration during initial setup so the first
4059
+ // trade sees the unified balance. Hardware wallets remain deferred to
4060
+ // action time to avoid QR / Ledger prompt spam while browsing.
4061
+ await __classPrivateFieldGet(this, _HyperLiquidProvider_instances, "m", _HyperLiquidProvider_ensureUnifiedAccountEnabled).call(this, {
4062
+ allowUserSigning: !__classPrivateFieldGet(this, _HyperLiquidProvider_walletService, "f").isSelectedHardwareWallet(),
4063
+ });
3900
4064
  })(), "f");
3901
4065
  // Await initialization - keep the promise so subsequent calls resolve immediately
3902
4066
  // The promise is only reset in disconnect() for clean reconnection,
@@ -3908,10 +4072,21 @@ async function _HyperLiquidProvider_ensureReady() {
3908
4072
  // will be re-discovered on the next #ensureReady() call.
3909
4073
  __classPrivateFieldSet(this, _HyperLiquidProvider_ensureReadyPromise, null, "f");
3910
4074
  }
4075
+ else if (__classPrivateFieldGet(this, _HyperLiquidProvider_unifiedAccountSetupNeedsRetry, "f")) {
4076
+ // Silent migration / lookup / keyring-locked failure left the cache
4077
+ // empty. Without resetting the memoized promise, subsequent
4078
+ // #ensureReady calls would skip retry and the user would be stuck
4079
+ // in the deprecated mode for the provider's lifetime.
4080
+ __classPrivateFieldSet(this, _HyperLiquidProvider_ensureReadyPromise, null, "f");
4081
+ }
3911
4082
  __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('[ensureReady] Initialization complete');
3912
4083
  }, _HyperLiquidProvider_ensureReadyForTrading = async function _HyperLiquidProvider_ensureReadyForTrading() {
3913
4084
  // First ensure basic initialization is complete
3914
4085
  await __classPrivateFieldGet(this, _HyperLiquidProvider_instances, "m", _HyperLiquidProvider_ensureReady).call(this);
4086
+ // dexAbstraction users were deferred during init to avoid an EIP-712 prompt
4087
+ // on Perps section open. Drive the migration here, gated by its own cache so
4088
+ // already-migrated or already-rejected users are not re-prompted.
4089
+ await __classPrivateFieldGet(this, _HyperLiquidProvider_instances, "m", _HyperLiquidProvider_ensureUnifiedAccountEnabled).call(this, { allowUserSigning: true });
3915
4090
  // If trading setup already complete, return immediately
3916
4091
  if (__classPrivateFieldGet(this, _HyperLiquidProvider_tradingSetupComplete, "f")) {
3917
4092
  return;
@@ -3935,8 +4110,6 @@ async function _HyperLiquidProvider_ensureReady() {
3935
4110
  // Don't throw - spotMeta will be fetched on-demand if needed
3936
4111
  }
3937
4112
  }
3938
- // Attempt to enable native balance abstraction
3939
- await __classPrivateFieldGet(this, _HyperLiquidProvider_instances, "m", _HyperLiquidProvider_ensureDexAbstractionEnabled).call(this);
3940
4113
  // Set up builder fee approval
3941
4114
  try {
3942
4115
  await __classPrivateFieldGet(this, _HyperLiquidProvider_instances, "m", _HyperLiquidProvider_ensureBuilderFeeApproval).call(this);
@@ -5559,11 +5732,11 @@ async function _HyperLiquidProvider_handleHip3PreOrder(params) {
5559
5732
  isBuy,
5560
5733
  });
5561
5734
  await __classPrivateFieldGet(this, _HyperLiquidProvider_instances, "m", _HyperLiquidProvider_ensureUsdhCollateralForOrder).call(this, dexName, requiredMargin);
5562
- // DEX abstraction will pull USDH from spot automatically
5735
+ // Unified Account will pull USDH from spot automatically
5563
5736
  return { transferInfo: null };
5564
5737
  }
5565
- if (__classPrivateFieldGet(this, _HyperLiquidProvider_useDexAbstraction, "f")) {
5566
- __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('Using DEX abstraction (no manual transfer)', {
5738
+ if (__classPrivateFieldGet(this, _HyperLiquidProvider_useUnifiedAccount, "f")) {
5739
+ __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('Using Unified Account (no manual transfer)', {
5567
5740
  symbol,
5568
5741
  dex: dexName,
5569
5742
  });
@@ -5592,7 +5765,7 @@ async function _HyperLiquidProvider_handleHip3PreOrder(params) {
5592
5765
  const errorMsg = transferError?.message || '';
5593
5766
  if (errorMsg.includes('Cannot transfer with DEX abstraction enabled')) {
5594
5767
  __classPrivateFieldGet(this, _HyperLiquidProvider_deps, "f").debugLogger.log('Detected DEX abstraction is enabled, switching mode');
5595
- __classPrivateFieldSet(this, _HyperLiquidProvider_useDexAbstraction, true, "f");
5768
+ __classPrivateFieldSet(this, _HyperLiquidProvider_useUnifiedAccount, true, "f");
5596
5769
  return { transferInfo: null };
5597
5770
  }
5598
5771
  throw transferError;