@metamask-previews/perps-controller 11.0.0-preview-9efd0b754 → 12.0.0-preview-4e64b66e8
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 +30 -1
- package/dist/PerpsController-method-action-types.cjs.map +1 -1
- package/dist/PerpsController-method-action-types.d.cts +36 -1
- package/dist/PerpsController-method-action-types.d.cts.map +1 -1
- package/dist/PerpsController-method-action-types.d.mts +36 -1
- package/dist/PerpsController-method-action-types.d.mts.map +1 -1
- package/dist/PerpsController-method-action-types.mjs.map +1 -1
- package/dist/PerpsController.cjs +600 -119
- package/dist/PerpsController.cjs.map +1 -1
- package/dist/PerpsController.d.cts +35 -4
- package/dist/PerpsController.d.cts.map +1 -1
- package/dist/PerpsController.d.mts +35 -4
- package/dist/PerpsController.d.mts.map +1 -1
- package/dist/PerpsController.mjs +603 -122
- package/dist/PerpsController.mjs.map +1 -1
- package/dist/constants/eventNames.cjs +3 -0
- package/dist/constants/eventNames.cjs.map +1 -1
- package/dist/constants/eventNames.d.cts +1 -0
- package/dist/constants/eventNames.d.cts.map +1 -1
- package/dist/constants/eventNames.d.mts +1 -0
- package/dist/constants/eventNames.d.mts.map +1 -1
- package/dist/constants/eventNames.mjs +3 -0
- package/dist/constants/eventNames.mjs.map +1 -1
- package/dist/constants/hyperLiquidConfig.cjs +14 -2
- package/dist/constants/hyperLiquidConfig.cjs.map +1 -1
- package/dist/constants/hyperLiquidConfig.d.cts +7 -0
- package/dist/constants/hyperLiquidConfig.d.cts.map +1 -1
- package/dist/constants/hyperLiquidConfig.d.mts +7 -0
- package/dist/constants/hyperLiquidConfig.d.mts.map +1 -1
- package/dist/constants/hyperLiquidConfig.mjs +11 -0
- package/dist/constants/hyperLiquidConfig.mjs.map +1 -1
- package/dist/constants/perpsConfig.cjs +19 -2
- package/dist/constants/perpsConfig.cjs.map +1 -1
- package/dist/constants/perpsConfig.d.cts +39 -7
- package/dist/constants/perpsConfig.d.cts.map +1 -1
- package/dist/constants/perpsConfig.d.mts +39 -7
- package/dist/constants/perpsConfig.d.mts.map +1 -1
- package/dist/constants/perpsConfig.mjs +18 -1
- package/dist/constants/perpsConfig.mjs.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/providers/AggregatedPerpsProvider.cjs +16 -0
- package/dist/providers/AggregatedPerpsProvider.cjs.map +1 -1
- package/dist/providers/AggregatedPerpsProvider.d.cts +3 -1
- package/dist/providers/AggregatedPerpsProvider.d.cts.map +1 -1
- package/dist/providers/AggregatedPerpsProvider.d.mts +3 -1
- package/dist/providers/AggregatedPerpsProvider.d.mts.map +1 -1
- package/dist/providers/AggregatedPerpsProvider.mjs +16 -0
- package/dist/providers/AggregatedPerpsProvider.mjs.map +1 -1
- package/dist/providers/HyperLiquidProvider.cjs +325 -59
- package/dist/providers/HyperLiquidProvider.cjs.map +1 -1
- package/dist/providers/HyperLiquidProvider.d.cts +27 -1
- package/dist/providers/HyperLiquidProvider.d.cts.map +1 -1
- package/dist/providers/HyperLiquidProvider.d.mts +27 -1
- package/dist/providers/HyperLiquidProvider.d.mts.map +1 -1
- package/dist/providers/HyperLiquidProvider.mjs +326 -60
- package/dist/providers/HyperLiquidProvider.mjs.map +1 -1
- package/dist/services/HyperLiquidClientService.cjs +74 -25
- package/dist/services/HyperLiquidClientService.cjs.map +1 -1
- package/dist/services/HyperLiquidClientService.d.cts.map +1 -1
- package/dist/services/HyperLiquidClientService.d.mts.map +1 -1
- package/dist/services/HyperLiquidClientService.mjs +74 -25
- package/dist/services/HyperLiquidClientService.mjs.map +1 -1
- package/dist/services/HyperLiquidSubscriptionService.cjs +16 -5
- package/dist/services/HyperLiquidSubscriptionService.cjs.map +1 -1
- package/dist/services/HyperLiquidSubscriptionService.d.cts +1 -1
- package/dist/services/HyperLiquidSubscriptionService.d.cts.map +1 -1
- package/dist/services/HyperLiquidSubscriptionService.d.mts +1 -1
- package/dist/services/HyperLiquidSubscriptionService.d.mts.map +1 -1
- package/dist/services/HyperLiquidSubscriptionService.mjs +16 -5
- package/dist/services/HyperLiquidSubscriptionService.mjs.map +1 -1
- package/dist/services/MarketDataService.cjs +49 -5
- package/dist/services/MarketDataService.cjs.map +1 -1
- package/dist/services/MarketDataService.d.cts +2 -2
- package/dist/services/MarketDataService.d.cts.map +1 -1
- package/dist/services/MarketDataService.d.mts +2 -2
- package/dist/services/MarketDataService.d.mts.map +1 -1
- package/dist/services/MarketDataService.mjs +49 -5
- package/dist/services/MarketDataService.mjs.map +1 -1
- package/dist/services/RewardsIntegrationService.cjs +330 -68
- package/dist/services/RewardsIntegrationService.cjs.map +1 -1
- package/dist/services/RewardsIntegrationService.d.cts +61 -5
- package/dist/services/RewardsIntegrationService.d.cts.map +1 -1
- package/dist/services/RewardsIntegrationService.d.mts +61 -5
- package/dist/services/RewardsIntegrationService.d.mts.map +1 -1
- package/dist/services/RewardsIntegrationService.mjs +330 -68
- package/dist/services/RewardsIntegrationService.mjs.map +1 -1
- package/dist/services/ServiceContext.cjs.map +1 -1
- package/dist/services/ServiceContext.d.cts +17 -1
- package/dist/services/ServiceContext.d.cts.map +1 -1
- package/dist/services/ServiceContext.d.mts +17 -1
- package/dist/services/ServiceContext.d.mts.map +1 -1
- package/dist/services/ServiceContext.mjs.map +1 -1
- package/dist/services/TerminalMarketService.cjs +422 -7
- package/dist/services/TerminalMarketService.cjs.map +1 -1
- package/dist/services/TerminalMarketService.d.cts +10 -1
- package/dist/services/TerminalMarketService.d.cts.map +1 -1
- package/dist/services/TerminalMarketService.d.mts +10 -1
- package/dist/services/TerminalMarketService.d.mts.map +1 -1
- package/dist/services/TerminalMarketService.mjs +423 -8
- package/dist/services/TerminalMarketService.mjs.map +1 -1
- package/dist/services/TradingService.cjs +52 -28
- package/dist/services/TradingService.cjs.map +1 -1
- package/dist/services/TradingService.d.cts.map +1 -1
- package/dist/services/TradingService.d.mts.map +1 -1
- package/dist/services/TradingService.mjs +52 -28
- package/dist/services/TradingService.mjs.map +1 -1
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.d.cts +156 -7
- package/dist/types/index.d.cts.map +1 -1
- package/dist/types/index.d.mts +156 -7
- package/dist/types/index.d.mts.map +1 -1
- package/dist/types/index.mjs.map +1 -1
- package/dist/utils/marketUtils.cjs +16 -1
- package/dist/utils/marketUtils.cjs.map +1 -1
- package/dist/utils/marketUtils.d.cts +1 -0
- package/dist/utils/marketUtils.d.cts.map +1 -1
- package/dist/utils/marketUtils.d.mts +1 -0
- package/dist/utils/marketUtils.d.mts.map +1 -1
- package/dist/utils/marketUtils.mjs +14 -0
- package/dist/utils/marketUtils.mjs.map +1 -1
- package/dist/utils/perpsDiskPersistence.cjs +19 -12
- package/dist/utils/perpsDiskPersistence.cjs.map +1 -1
- package/dist/utils/perpsDiskPersistence.d.cts +5 -1
- package/dist/utils/perpsDiskPersistence.d.cts.map +1 -1
- package/dist/utils/perpsDiskPersistence.d.mts +5 -1
- package/dist/utils/perpsDiskPersistence.d.mts.map +1 -1
- package/dist/utils/perpsDiskPersistence.mjs +19 -12
- package/dist/utils/perpsDiskPersistence.mjs.map +1 -1
- package/package.json +1 -1
package/dist/PerpsController.mjs
CHANGED
|
@@ -9,15 +9,15 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
10
10
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
11
11
|
};
|
|
12
|
-
var _PerpsController_instances, _a, _PerpsController_initializationPromise, _PerpsController_isReinitializing, _PerpsController_myxRegistrationPromise, _PerpsController_blockedRegionListVersion, _PerpsController_hip3Enabled, _PerpsController_hip3AllowlistMarkets, _PerpsController_hip3BlocklistMarkets, _PerpsController_hip3ConfigSource, _PerpsController_priceDeviationLimit, _PerpsController_attributionContext, _PerpsController_isMYXProviderEnabled, _PerpsController_standaloneProvider, _PerpsController_handlersRegistered, _PerpsController_standaloneProviderIsTestnet, _PerpsController_standaloneProviderHip3Version, _PerpsController_eligibilityCheckDeferred, _PerpsController_ausQueue, _PerpsController_options, _PerpsController_tradingService, _PerpsController_marketDataService, _PerpsController_accountService, _PerpsController_eligibilityService, _PerpsController_dataLakeService, _PerpsController_depositService, _PerpsController_featureFlagConfigurationService, _PerpsController_rewardsIntegrationService, _PerpsController_logError, _PerpsController_debugLog, _PerpsController_getAggregatedCacheProviderIds, _PerpsController_getOrCreateStandaloneProvider, _PerpsController_cleanupStandaloneProvider, _PerpsController_getMetrics, _PerpsController_findNetworkClientIdForChain, _PerpsController_submitTransaction, _PerpsController_migrateRequestsIfNeeded, _PerpsController_withStreamPause, _PerpsController_performInitialization, _PerpsController_createProviders, _PerpsController_assignActiveProvider, _PerpsController_getErrorContext, _PerpsController_getControllerState, _PerpsController_buildMarketAllowedFilter, _PerpsController_compilePatternsSafely, _PerpsController_createServiceContext, _PerpsController_ensureTradingServiceDeps, _PerpsController_preloadWatchedPaths, _PerpsController_preloadTimer, _PerpsController_isPreloading, _PerpsController_isPreloadingUserData, _PerpsController_preloadStateUnsubscribe, _PerpsController_accountChangeUnsubscribe, _PerpsController_previousIsTestnet, _PerpsController_previousHip3ConfigVersion, _PerpsController_preloadRefreshMs, _PerpsController_preloadGuardMs, _PerpsController_hydrateCacheFromDiskSync, _PerpsController_performMarketDataPreload, _PerpsController_performUserDataPreload, _PerpsController_persistWatchlistToRemote, _PerpsController_syncWatchlistFromRemote;
|
|
12
|
+
var _PerpsController_instances, _a, _PerpsController_initializationPromise, _PerpsController_isReinitializing, _PerpsController_myxRegistrationPromise, _PerpsController_blockedRegionListVersion, _PerpsController_hip3Enabled, _PerpsController_hip3AllowlistMarkets, _PerpsController_hip3BlocklistMarkets, _PerpsController_hip3ConfigSource, _PerpsController_priceDeviationLimit, _PerpsController_attributionContext, _PerpsController_isMYXProviderEnabled, _PerpsController_standaloneProvider, _PerpsController_handlersRegistered, _PerpsController_standaloneProviderIsTestnet, _PerpsController_standaloneProviderHip3Version, _PerpsController_standaloneProviderOperations, _PerpsController_eligibilityCheckDeferred, _PerpsController_ausQueue, _PerpsController_userDiskWrite, _PerpsController_options, _PerpsController_tradingService, _PerpsController_marketDataService, _PerpsController_accountService, _PerpsController_eligibilityService, _PerpsController_dataLakeService, _PerpsController_depositService, _PerpsController_featureFlagConfigurationService, _PerpsController_rewardsIntegrationService, _PerpsController_logError, _PerpsController_debugLog, _PerpsController_awaitInitializationIfInProgress, _PerpsController_getAggregatedCacheProviderIds, _PerpsController_isMarketCacheEntryCurrent, _PerpsController_isUserCacheIdentityCurrent, _PerpsController_fetchAndCacheUserDataSnapshot, _PerpsController_getOrCreateStandaloneProvider, _PerpsController_trackStandaloneProviderOperation, _PerpsController_retireStandaloneProvider, _PerpsController_cleanupStandaloneProvider, _PerpsController_getMetrics, _PerpsController_findNetworkClientIdForChain, _PerpsController_submitTransaction, _PerpsController_migrateRequestsIfNeeded, _PerpsController_withStreamPause, _PerpsController_performInitialization, _PerpsController_createProviders, _PerpsController_assignActiveProvider, _PerpsController_getErrorContext, _PerpsController_getControllerState, _PerpsController_buildMarketAllowedFilter, _PerpsController_compilePatternsSafely, _PerpsController_createServiceContext, _PerpsController_ensureTradingServiceDeps, _PerpsController_getActiveProviderWhenReady, _PerpsController_buildGlobalSnapshotContext, _PerpsController_getStaticSnapshotDexes, _PerpsController_preloadWatchedPaths, _PerpsController_preloadTimer, _PerpsController_isPreloading, _PerpsController_marketPreloadQueued, _PerpsController_isPreloadingUserData, _PerpsController_userPreloadQueued, _PerpsController_userSnapshotRequests, _PerpsController_preloadStateUnsubscribe, _PerpsController_accountChangeUnsubscribe, _PerpsController_previousIsTestnet, _PerpsController_previousHip3ConfigVersion, _PerpsController_preloadRefreshMs, _PerpsController_preloadGuardMs, _PerpsController_hydrateCacheFromDiskSync, _PerpsController_persistUserCacheToDisk, _PerpsController_performMarketDataPreload, _PerpsController_performUserDataPreload, _PerpsController_persistWatchlistToRemote, _PerpsController_syncWatchlistFromRemote;
|
|
13
13
|
import { BaseController } from "@metamask/base-controller";
|
|
14
14
|
import { ORIGIN_METAMASK } from "@metamask/controller-utils";
|
|
15
15
|
import { v4 as uuidv4 } from "uuid";
|
|
16
16
|
import { CandlePeriod } from "./constants/chartConfig.mjs";
|
|
17
17
|
import { PERPS_EVENT_PROPERTY, PERPS_EVENT_VALUE } from "./constants/eventNames.mjs";
|
|
18
|
-
import { USDC_SYMBOL } from "./constants/hyperLiquidConfig.mjs";
|
|
18
|
+
import { canonicalizeHyperLiquidDexes, MAINNET_HIP3_CONFIG, TESTNET_HIP3_CONFIG, USDC_SYMBOL } from "./constants/hyperLiquidConfig.mjs";
|
|
19
19
|
import { PerpsMeasurementName } from "./constants/performanceMetrics.mjs";
|
|
20
|
-
import { PERPS_CONSTANTS, MARKET_SORTING_CONFIG, PROVIDER_CONFIG,
|
|
20
|
+
import { PERPS_CONSTANTS, MARKET_SORTING_CONFIG, PROVIDER_CONFIG, buildProviderCacheKey, MAX_SLIPPAGE_BOUNDS, DEFAULT_PERPS_MODE, DEFAULT_PRO_LAYOUT_PREFERENCES } from "./constants/perpsConfig.mjs";
|
|
21
21
|
import { PERPS_ERROR_CODES } from "./perpsErrorCodes.mjs";
|
|
22
22
|
import { AggregatedPerpsProvider } from "./providers/AggregatedPerpsProvider.mjs";
|
|
23
23
|
import { HyperLiquidProvider } from "./providers/HyperLiquidProvider.mjs";
|
|
@@ -35,9 +35,39 @@ import { WebSocketConnectionState, PerpsAnalyticsEvent, PerpsTraceNames, PerpsTr
|
|
|
35
35
|
import { getSelectedEvmAccountFromMessenger } from "./utils/accountUtils.mjs";
|
|
36
36
|
import { ensureError } from "./utils/errorUtils.mjs";
|
|
37
37
|
import { parseAssetName } from "./utils/hyperLiquidAdapter.mjs";
|
|
38
|
-
import { compileMarketPattern, shouldIncludeMarket } from "./utils/marketUtils.mjs";
|
|
38
|
+
import { clonePerpsMarketData, compileMarketPattern, shouldIncludeMarket } from "./utils/marketUtils.mjs";
|
|
39
39
|
import { hydrateFromDiskSync, persistMarketEntriesToDisk, persistUserEntriesToDisk } from "./utils/perpsDiskPersistence.mjs";
|
|
40
40
|
import { wait } from "./utils/wait.mjs";
|
|
41
|
+
function cloneUserDataSnapshot(snapshot) {
|
|
42
|
+
return {
|
|
43
|
+
positions: snapshot.positions.map((position) => ({
|
|
44
|
+
...position,
|
|
45
|
+
leverage: { ...position.leverage },
|
|
46
|
+
cumulativeFunding: { ...position.cumulativeFunding },
|
|
47
|
+
...(position.takeProfitOrders && {
|
|
48
|
+
takeProfitOrders: position.takeProfitOrders.map((order) => ({
|
|
49
|
+
...order,
|
|
50
|
+
})),
|
|
51
|
+
}),
|
|
52
|
+
...(position.stopLossOrders && {
|
|
53
|
+
stopLossOrders: position.stopLossOrders.map((order) => ({
|
|
54
|
+
...order,
|
|
55
|
+
})),
|
|
56
|
+
}),
|
|
57
|
+
})),
|
|
58
|
+
orders: snapshot.orders.map((order) => ({ ...order })),
|
|
59
|
+
accountState: {
|
|
60
|
+
...snapshot.accountState,
|
|
61
|
+
...(snapshot.accountState.subAccountBreakdown && {
|
|
62
|
+
subAccountBreakdown: Object.fromEntries(Object.entries(snapshot.accountState.subAccountBreakdown).map(([dex, balances]) => [dex, { ...balances }])),
|
|
63
|
+
}),
|
|
64
|
+
},
|
|
65
|
+
identity: {
|
|
66
|
+
...snapshot.identity,
|
|
67
|
+
dexes: [...snapshot.identity.dexes],
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
41
71
|
/**
|
|
42
72
|
* Returns the first non-empty string from the given values.
|
|
43
73
|
* Env vars default to '' (not null/undefined), so ?? wouldn't fall through.
|
|
@@ -373,6 +403,7 @@ const metadata = {
|
|
|
373
403
|
},
|
|
374
404
|
};
|
|
375
405
|
const MESSENGER_EXPOSED_METHODS = [
|
|
406
|
+
'approveSubscriptionBuilderFee',
|
|
376
407
|
'calculateFees',
|
|
377
408
|
'calculateLiquidationPrice',
|
|
378
409
|
'calculateMaintenanceMargin',
|
|
@@ -400,6 +431,7 @@ const MESSENGER_EXPOSED_METHODS = [
|
|
|
400
431
|
'getBlockExplorerUrl',
|
|
401
432
|
'getCachedMarketDataForActiveProvider',
|
|
402
433
|
'getCachedUserDataForActiveProvider',
|
|
434
|
+
'getUserDataSnapshot',
|
|
403
435
|
'getCurrentNetwork',
|
|
404
436
|
'getFunding',
|
|
405
437
|
'getHistoricalPortfolio',
|
|
@@ -421,6 +453,7 @@ const MESSENGER_EXPOSED_METHODS = [
|
|
|
421
453
|
'getWithdrawalProgress',
|
|
422
454
|
'getWithdrawalRoutes',
|
|
423
455
|
'init',
|
|
456
|
+
'invalidateSubscriptionBenefits',
|
|
424
457
|
'isCurrentlyReinitializing',
|
|
425
458
|
'isFirstTimeUserOnCurrentNetwork',
|
|
426
459
|
'isWatchlistMarket',
|
|
@@ -532,6 +565,7 @@ export class PerpsController extends BaseController {
|
|
|
532
565
|
_PerpsController_handlersRegistered.set(this, false);
|
|
533
566
|
_PerpsController_standaloneProviderIsTestnet.set(this, null);
|
|
534
567
|
_PerpsController_standaloneProviderHip3Version.set(this, null);
|
|
568
|
+
_PerpsController_standaloneProviderOperations.set(this, new Map());
|
|
535
569
|
_PerpsController_eligibilityCheckDeferred.set(this, void 0);
|
|
536
570
|
/**
|
|
537
571
|
* Serial promise queue for all AUS watchlist operations (hydration and
|
|
@@ -547,6 +581,7 @@ export class PerpsController extends BaseController {
|
|
|
547
581
|
* a failed operation does not stall subsequent ones.
|
|
548
582
|
*/
|
|
549
583
|
_PerpsController_ausQueue.set(this, Promise.resolve());
|
|
584
|
+
_PerpsController_userDiskWrite.set(this, Promise.resolve());
|
|
550
585
|
// Store options for dependency injection (allows core package to inject platform-specific services)
|
|
551
586
|
_PerpsController_options.set(this, void 0);
|
|
552
587
|
// Service instances (instantiated with platform dependencies)
|
|
@@ -560,7 +595,10 @@ export class PerpsController extends BaseController {
|
|
|
560
595
|
_PerpsController_rewardsIntegrationService.set(this, void 0);
|
|
561
596
|
_PerpsController_preloadTimer.set(this, null);
|
|
562
597
|
_PerpsController_isPreloading.set(this, false);
|
|
598
|
+
_PerpsController_marketPreloadQueued.set(this, false);
|
|
563
599
|
_PerpsController_isPreloadingUserData.set(this, false);
|
|
600
|
+
_PerpsController_userPreloadQueued.set(this, false);
|
|
601
|
+
_PerpsController_userSnapshotRequests.set(this, new Map());
|
|
564
602
|
_PerpsController_preloadStateUnsubscribe.set(this, null);
|
|
565
603
|
_PerpsController_accountChangeUnsubscribe.set(this, null);
|
|
566
604
|
_PerpsController_previousIsTestnet.set(this, null);
|
|
@@ -579,7 +617,9 @@ export class PerpsController extends BaseController {
|
|
|
579
617
|
__classPrivateFieldSet(this, _PerpsController_marketDataService, new MarketDataService({
|
|
580
618
|
...infrastructure,
|
|
581
619
|
terminalMarketService: infrastructure.terminalMarketService ??
|
|
582
|
-
(infrastructure.
|
|
620
|
+
(infrastructure.terminalApi?.marketDataUrl ||
|
|
621
|
+
infrastructure.terminalApiUrl ||
|
|
622
|
+
infrastructure.terminalApi?.globalSnapshotUrl
|
|
583
623
|
? new TerminalMarketService(infrastructure)
|
|
584
624
|
: undefined),
|
|
585
625
|
}), "f");
|
|
@@ -646,24 +686,20 @@ export class PerpsController extends BaseController {
|
|
|
646
686
|
if (activeProvider === 'aggregated') {
|
|
647
687
|
// Assemble from all registered provider entries
|
|
648
688
|
const assembled = [];
|
|
649
|
-
let oldestTimestamp = Infinity;
|
|
650
689
|
for (const providerId of __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getAggregatedCacheProviderIds).call(this, Object.keys(cache))) {
|
|
651
690
|
const key = buildProviderCacheKey(providerId, this.state.isTestnet);
|
|
652
691
|
const entry = cache[key];
|
|
653
692
|
if (!entry || entry.data.length === 0) {
|
|
654
693
|
continue;
|
|
655
694
|
}
|
|
656
|
-
|
|
657
|
-
|
|
695
|
+
if (!__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_isMarketCacheEntryCurrent).call(this, providerId, entry, options)) {
|
|
696
|
+
continue;
|
|
697
|
+
}
|
|
698
|
+
assembled.push(...clonePerpsMarketData(entry.data));
|
|
658
699
|
}
|
|
659
700
|
if (assembled.length === 0) {
|
|
660
701
|
return null;
|
|
661
702
|
}
|
|
662
|
-
// Check TTL against the oldest entry
|
|
663
|
-
if (!options?.skipTTL &&
|
|
664
|
-
Date.now() - oldestTimestamp > __classPrivateFieldGet(_a, _a, "f", _PerpsController_preloadGuardMs) * 10) {
|
|
665
|
-
return null;
|
|
666
|
-
}
|
|
667
703
|
return assembled;
|
|
668
704
|
}
|
|
669
705
|
// Single provider mode
|
|
@@ -672,11 +708,10 @@ export class PerpsController extends BaseController {
|
|
|
672
708
|
if (!entry || entry.data.length === 0) {
|
|
673
709
|
return null;
|
|
674
710
|
}
|
|
675
|
-
if (!options
|
|
676
|
-
Date.now() - entry.timestamp > __classPrivateFieldGet(_a, _a, "f", _PerpsController_preloadGuardMs) * 10) {
|
|
711
|
+
if (!__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_isMarketCacheEntryCurrent).call(this, activeProvider, entry, options)) {
|
|
677
712
|
return null;
|
|
678
713
|
}
|
|
679
|
-
return entry.data;
|
|
714
|
+
return clonePerpsMarketData(entry.data);
|
|
680
715
|
}
|
|
681
716
|
/**
|
|
682
717
|
* Read cached user data for the currently active provider (or aggregated).
|
|
@@ -700,18 +735,21 @@ export class PerpsController extends BaseController {
|
|
|
700
735
|
currentAddress = evmAccount?.address ?? null;
|
|
701
736
|
}
|
|
702
737
|
catch {
|
|
703
|
-
//
|
|
738
|
+
// Account identity is required before account-scoped data can be trusted.
|
|
704
739
|
}
|
|
740
|
+
if (!currentAddress) {
|
|
741
|
+
return null;
|
|
742
|
+
}
|
|
743
|
+
const selectedAddress = currentAddress;
|
|
705
744
|
const skipTTL = options?.skipTTL ?? false;
|
|
706
|
-
const isValidEntry = (entry) => {
|
|
745
|
+
const isValidEntry = (providerId, entry) => {
|
|
707
746
|
if (!entry) {
|
|
708
747
|
return false;
|
|
709
748
|
}
|
|
710
749
|
if (!skipTTL && Date.now() - entry.timestamp >= staleCutoff) {
|
|
711
750
|
return false;
|
|
712
751
|
}
|
|
713
|
-
if (
|
|
714
|
-
entry.address.toLowerCase() !== currentAddress.toLowerCase()) {
|
|
752
|
+
if (!__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_isUserCacheIdentityCurrent).call(this, providerId, entry, selectedAddress)) {
|
|
715
753
|
return false;
|
|
716
754
|
}
|
|
717
755
|
return true;
|
|
@@ -723,9 +761,9 @@ export class PerpsController extends BaseController {
|
|
|
723
761
|
let defaultAccountState = null;
|
|
724
762
|
let hasValidEntry = false;
|
|
725
763
|
for (const providerId of __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getAggregatedCacheProviderIds).call(this, Object.keys(cache))) {
|
|
726
|
-
const
|
|
727
|
-
const entry = cache[
|
|
728
|
-
if (!isValidEntry(entry)) {
|
|
764
|
+
const providerNetworkKey = buildProviderCacheKey(providerId, this.state.isTestnet);
|
|
765
|
+
const entry = cache[providerNetworkKey];
|
|
766
|
+
if (!isValidEntry(providerId, entry)) {
|
|
729
767
|
continue;
|
|
730
768
|
}
|
|
731
769
|
hasValidEntry = true;
|
|
@@ -746,9 +784,9 @@ export class PerpsController extends BaseController {
|
|
|
746
784
|
};
|
|
747
785
|
}
|
|
748
786
|
// Single provider mode
|
|
749
|
-
const
|
|
750
|
-
const entry = cache[
|
|
751
|
-
if (!entry || !isValidEntry(entry)) {
|
|
787
|
+
const providerNetworkKey = buildProviderCacheKey(activeProvider, this.state.isTestnet);
|
|
788
|
+
const entry = cache[providerNetworkKey];
|
|
789
|
+
if (!entry || !isValidEntry(activeProvider, entry)) {
|
|
752
790
|
return null;
|
|
753
791
|
}
|
|
754
792
|
return {
|
|
@@ -757,6 +795,82 @@ export class PerpsController extends BaseController {
|
|
|
757
795
|
accountState: entry.accountState,
|
|
758
796
|
};
|
|
759
797
|
}
|
|
798
|
+
/**
|
|
799
|
+
* Fetch, validate, and atomically cache a complete user-data snapshot.
|
|
800
|
+
* This remains callable after mount so consumers can seed their live channel
|
|
801
|
+
* from one coherent positions/orders/account result.
|
|
802
|
+
*
|
|
803
|
+
* @returns The accepted user-data snapshot.
|
|
804
|
+
*/
|
|
805
|
+
async getUserDataSnapshot() {
|
|
806
|
+
const evmAccount = getSelectedEvmAccountFromMessenger(this.messenger);
|
|
807
|
+
if (!evmAccount?.address) {
|
|
808
|
+
throw new Error('Cannot fetch user data snapshot without an EVM account');
|
|
809
|
+
}
|
|
810
|
+
if (this.state.activeProvider !== 'hyperliquid') {
|
|
811
|
+
throw new Error('User data snapshots require Hyperliquid provider mode');
|
|
812
|
+
}
|
|
813
|
+
const capturedActiveProvider = this.activeProviderInstance;
|
|
814
|
+
const standaloneProvider = capturedActiveProvider
|
|
815
|
+
? null
|
|
816
|
+
: __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getOrCreateStandaloneProvider).call(this);
|
|
817
|
+
const provider = capturedActiveProvider ?? standaloneProvider;
|
|
818
|
+
if (!provider) {
|
|
819
|
+
throw new Error('Cannot create standalone Hyperliquid provider');
|
|
820
|
+
}
|
|
821
|
+
const { address } = evmAccount;
|
|
822
|
+
const { isTestnet, hip3ConfigVersion } = this.state;
|
|
823
|
+
const network = isTestnet ? 'testnet' : 'mainnet';
|
|
824
|
+
const expectedDexes = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getStaticSnapshotDexes).call(this);
|
|
825
|
+
if (!expectedDexes) {
|
|
826
|
+
throw new Error('User data snapshot DEX identity is not static');
|
|
827
|
+
}
|
|
828
|
+
const isCurrent = () => {
|
|
829
|
+
let currentAddress;
|
|
830
|
+
try {
|
|
831
|
+
currentAddress = getSelectedEvmAccountFromMessenger(this.messenger)?.address;
|
|
832
|
+
}
|
|
833
|
+
catch {
|
|
834
|
+
return false;
|
|
835
|
+
}
|
|
836
|
+
return (this.state.activeProvider === 'hyperliquid' &&
|
|
837
|
+
(!capturedActiveProvider ||
|
|
838
|
+
this.activeProviderInstance === capturedActiveProvider) &&
|
|
839
|
+
this.state.isTestnet === isTestnet &&
|
|
840
|
+
this.state.hip3ConfigVersion === hip3ConfigVersion &&
|
|
841
|
+
currentAddress?.toLowerCase() === address.toLowerCase());
|
|
842
|
+
};
|
|
843
|
+
const context = {
|
|
844
|
+
provider,
|
|
845
|
+
standaloneProvider,
|
|
846
|
+
address,
|
|
847
|
+
isTestnet,
|
|
848
|
+
hip3ConfigVersion,
|
|
849
|
+
expectedDexes,
|
|
850
|
+
isCurrent,
|
|
851
|
+
};
|
|
852
|
+
const requestKey = [
|
|
853
|
+
'hyperliquid',
|
|
854
|
+
network,
|
|
855
|
+
address.toLowerCase(),
|
|
856
|
+
hip3ConfigVersion,
|
|
857
|
+
...expectedDexes,
|
|
858
|
+
].join('|');
|
|
859
|
+
const existingRequest = __classPrivateFieldGet(this, _PerpsController_userSnapshotRequests, "f").get(requestKey);
|
|
860
|
+
if (existingRequest?.provider === provider) {
|
|
861
|
+
return existingRequest.promise;
|
|
862
|
+
}
|
|
863
|
+
const request = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_fetchAndCacheUserDataSnapshot).call(this, context);
|
|
864
|
+
__classPrivateFieldGet(this, _PerpsController_userSnapshotRequests, "f").set(requestKey, { provider, promise: request });
|
|
865
|
+
try {
|
|
866
|
+
return await request;
|
|
867
|
+
}
|
|
868
|
+
finally {
|
|
869
|
+
if (__classPrivateFieldGet(this, _PerpsController_userSnapshotRequests, "f").get(requestKey)?.promise === request) {
|
|
870
|
+
__classPrivateFieldGet(this, _PerpsController_userSnapshotRequests, "f").delete(requestKey);
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
}
|
|
760
874
|
/**
|
|
761
875
|
* Test-observable accessor for whether a standalone provider is cached.
|
|
762
876
|
*
|
|
@@ -908,14 +1022,11 @@ export class PerpsController extends BaseController {
|
|
|
908
1022
|
// Check if not initialized
|
|
909
1023
|
if (this.state.initializationState !== InitializationState.Initialized ||
|
|
910
1024
|
!this.isInitialized) {
|
|
911
|
-
const errorMessage = this.state.initializationState === InitializationState.Failed
|
|
912
|
-
? `${PERPS_ERROR_CODES.CLIENT_NOT_INITIALIZED}: ${this.state.initializationError ?? 'Initialization failed'}`
|
|
913
|
-
: PERPS_ERROR_CODES.CLIENT_NOT_INITIALIZED;
|
|
914
1025
|
this.update((state) => {
|
|
915
|
-
state.lastError =
|
|
1026
|
+
state.lastError = PERPS_ERROR_CODES.CLIENT_NOT_INITIALIZED;
|
|
916
1027
|
state.lastUpdateTimestamp = Date.now();
|
|
917
1028
|
});
|
|
918
|
-
throw new Error(
|
|
1029
|
+
throw new Error(PERPS_ERROR_CODES.CLIENT_NOT_INITIALIZED);
|
|
919
1030
|
}
|
|
920
1031
|
// Return the active provider instance (set during initialization based on providerMode)
|
|
921
1032
|
if (!this.activeProviderInstance) {
|
|
@@ -955,7 +1066,7 @@ export class PerpsController extends BaseController {
|
|
|
955
1066
|
* @returns The order result with order ID and status.
|
|
956
1067
|
*/
|
|
957
1068
|
async placeOrder(params) {
|
|
958
|
-
const provider = this.
|
|
1069
|
+
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getActiveProviderWhenReady).call(this);
|
|
959
1070
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_ensureTradingServiceDeps).call(this);
|
|
960
1071
|
return __classPrivateFieldGet(this, _PerpsController_tradingService, "f").placeOrder({
|
|
961
1072
|
provider,
|
|
@@ -974,7 +1085,7 @@ export class PerpsController extends BaseController {
|
|
|
974
1085
|
* @returns The updated order result with order ID and status.
|
|
975
1086
|
*/
|
|
976
1087
|
async editOrder(params) {
|
|
977
|
-
const provider = this.
|
|
1088
|
+
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getActiveProviderWhenReady).call(this);
|
|
978
1089
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_ensureTradingServiceDeps).call(this);
|
|
979
1090
|
return __classPrivateFieldGet(this, _PerpsController_tradingService, "f").editOrder({
|
|
980
1091
|
provider,
|
|
@@ -989,7 +1100,7 @@ export class PerpsController extends BaseController {
|
|
|
989
1100
|
* @returns The cancellation result with status.
|
|
990
1101
|
*/
|
|
991
1102
|
async cancelOrder(params) {
|
|
992
|
-
const provider = this.
|
|
1103
|
+
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getActiveProviderWhenReady).call(this);
|
|
993
1104
|
return __classPrivateFieldGet(this, _PerpsController_tradingService, "f").cancelOrder({
|
|
994
1105
|
provider,
|
|
995
1106
|
params,
|
|
@@ -1004,7 +1115,7 @@ export class PerpsController extends BaseController {
|
|
|
1004
1115
|
* @returns The batch cancellation results for each order.
|
|
1005
1116
|
*/
|
|
1006
1117
|
async cancelOrders(params) {
|
|
1007
|
-
const provider = this.
|
|
1118
|
+
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getActiveProviderWhenReady).call(this);
|
|
1008
1119
|
return __classPrivateFieldGet(this, _PerpsController_tradingService, "f").cancelOrders({
|
|
1009
1120
|
provider,
|
|
1010
1121
|
params,
|
|
@@ -1022,7 +1133,7 @@ export class PerpsController extends BaseController {
|
|
|
1022
1133
|
* @returns The order result from the close position request.
|
|
1023
1134
|
*/
|
|
1024
1135
|
async closePosition(params) {
|
|
1025
|
-
const provider = this.
|
|
1136
|
+
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getActiveProviderWhenReady).call(this);
|
|
1026
1137
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_ensureTradingServiceDeps).call(this);
|
|
1027
1138
|
return __classPrivateFieldGet(this, _PerpsController_tradingService, "f").closePosition({
|
|
1028
1139
|
provider,
|
|
@@ -1041,7 +1152,7 @@ export class PerpsController extends BaseController {
|
|
|
1041
1152
|
* @returns The batch close results for each position.
|
|
1042
1153
|
*/
|
|
1043
1154
|
async closePositions(params) {
|
|
1044
|
-
const provider = this.
|
|
1155
|
+
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getActiveProviderWhenReady).call(this);
|
|
1045
1156
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_ensureTradingServiceDeps).call(this);
|
|
1046
1157
|
return __classPrivateFieldGet(this, _PerpsController_tradingService, "f").closePositions({
|
|
1047
1158
|
provider,
|
|
@@ -1058,7 +1169,7 @@ export class PerpsController extends BaseController {
|
|
|
1058
1169
|
* @returns The order result from the TP/SL update.
|
|
1059
1170
|
*/
|
|
1060
1171
|
async updatePositionTPSL(params) {
|
|
1061
|
-
const provider = this.
|
|
1172
|
+
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getActiveProviderWhenReady).call(this);
|
|
1062
1173
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_ensureTradingServiceDeps).call(this);
|
|
1063
1174
|
return __classPrivateFieldGet(this, _PerpsController_tradingService, "f").updatePositionTPSL({
|
|
1064
1175
|
provider,
|
|
@@ -1073,7 +1184,7 @@ export class PerpsController extends BaseController {
|
|
|
1073
1184
|
* @returns The margin update result.
|
|
1074
1185
|
*/
|
|
1075
1186
|
async updateMargin(params) {
|
|
1076
|
-
const provider = this.
|
|
1187
|
+
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getActiveProviderWhenReady).call(this);
|
|
1077
1188
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_ensureTradingServiceDeps).call(this);
|
|
1078
1189
|
return __classPrivateFieldGet(this, _PerpsController_tradingService, "f").updateMargin({
|
|
1079
1190
|
provider,
|
|
@@ -1089,7 +1200,7 @@ export class PerpsController extends BaseController {
|
|
|
1089
1200
|
* @returns The order result from the position flip.
|
|
1090
1201
|
*/
|
|
1091
1202
|
async flipPosition(params) {
|
|
1092
|
-
const provider = this.
|
|
1203
|
+
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getActiveProviderWhenReady).call(this);
|
|
1093
1204
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_ensureTradingServiceDeps).call(this);
|
|
1094
1205
|
return __classPrivateFieldGet(this, _PerpsController_tradingService, "f").flipPosition({
|
|
1095
1206
|
provider,
|
|
@@ -1111,10 +1222,7 @@ export class PerpsController extends BaseController {
|
|
|
1111
1222
|
const { amount, placeOrder } = params;
|
|
1112
1223
|
let currentDepositId;
|
|
1113
1224
|
try {
|
|
1114
|
-
|
|
1115
|
-
// Don't set depositInProgress yet - wait until user confirms
|
|
1116
|
-
// Prepare deposit transaction using DepositService
|
|
1117
|
-
const provider = this.getActiveProvider();
|
|
1225
|
+
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getActiveProviderWhenReady).call(this);
|
|
1118
1226
|
const { transaction, assetChainId, currentDepositId: depositId, } = await __classPrivateFieldGet(this, _PerpsController_depositService, "f").prepareTransaction({ provider });
|
|
1119
1227
|
currentDepositId = depositId;
|
|
1120
1228
|
// Get current account address via messenger (outside of update() for proper typing)
|
|
@@ -1504,7 +1612,7 @@ export class PerpsController extends BaseController {
|
|
|
1504
1612
|
* @returns WithdrawResult with withdrawal ID and tracking info
|
|
1505
1613
|
*/
|
|
1506
1614
|
async withdraw(params) {
|
|
1507
|
-
const provider = this.
|
|
1615
|
+
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getActiveProviderWhenReady).call(this);
|
|
1508
1616
|
return __classPrivateFieldGet(this, _PerpsController_accountService, "f").withdraw({
|
|
1509
1617
|
provider,
|
|
1510
1618
|
params,
|
|
@@ -1532,7 +1640,10 @@ export class PerpsController extends BaseController {
|
|
|
1532
1640
|
// Fallback to cached standalone provider for pre-initialization discovery
|
|
1533
1641
|
// TODO: When adding new providers (MYX), consider a provider factory pattern
|
|
1534
1642
|
const provider = this.activeProviderInstance ?? __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getOrCreateStandaloneProvider).call(this);
|
|
1535
|
-
|
|
1643
|
+
const operation = provider.getPositions(params);
|
|
1644
|
+
return provider === __classPrivateFieldGet(this, _PerpsController_standaloneProvider, "f")
|
|
1645
|
+
? __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_trackStandaloneProviderOperation).call(this, provider, operation)
|
|
1646
|
+
: operation;
|
|
1536
1647
|
}
|
|
1537
1648
|
const provider = this.getActiveProvider();
|
|
1538
1649
|
return __classPrivateFieldGet(this, _PerpsController_marketDataService, "f").getPositions({
|
|
@@ -1593,7 +1704,10 @@ export class PerpsController extends BaseController {
|
|
|
1593
1704
|
// For standalone mode, access provider directly without initialization check
|
|
1594
1705
|
if (params?.standalone && params.userAddress) {
|
|
1595
1706
|
const provider = this.activeProviderInstance ?? __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getOrCreateStandaloneProvider).call(this);
|
|
1596
|
-
|
|
1707
|
+
const operation = provider.getOpenOrders(params);
|
|
1708
|
+
return provider === __classPrivateFieldGet(this, _PerpsController_standaloneProvider, "f")
|
|
1709
|
+
? __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_trackStandaloneProviderOperation).call(this, provider, operation)
|
|
1710
|
+
: operation;
|
|
1597
1711
|
}
|
|
1598
1712
|
const provider = this.getActiveProvider();
|
|
1599
1713
|
return __classPrivateFieldGet(this, _PerpsController_marketDataService, "f").getOpenOrders({
|
|
@@ -1638,7 +1752,10 @@ export class PerpsController extends BaseController {
|
|
|
1638
1752
|
// Use activeProviderInstance if available (respects provider abstraction)
|
|
1639
1753
|
// Fallback to cached standalone provider for pre-initialization discovery
|
|
1640
1754
|
const provider = this.activeProviderInstance ?? __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getOrCreateStandaloneProvider).call(this);
|
|
1641
|
-
|
|
1755
|
+
const operation = provider.getAccountState(params);
|
|
1756
|
+
return provider === __classPrivateFieldGet(this, _PerpsController_standaloneProvider, "f")
|
|
1757
|
+
? __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_trackStandaloneProviderOperation).call(this, provider, operation)
|
|
1758
|
+
: operation;
|
|
1642
1759
|
}
|
|
1643
1760
|
const provider = this.getActiveProvider();
|
|
1644
1761
|
return __classPrivateFieldGet(this, _PerpsController_marketDataService, "f").getAccountState({
|
|
@@ -1676,12 +1793,15 @@ export class PerpsController extends BaseController {
|
|
|
1676
1793
|
const isMarketAllowed = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_buildMarketAllowedFilter).call(this);
|
|
1677
1794
|
if (params?.standalone) {
|
|
1678
1795
|
const provider = this.activeProviderInstance ?? __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getOrCreateStandaloneProvider).call(this);
|
|
1679
|
-
|
|
1796
|
+
const operation = __classPrivateFieldGet(this, _PerpsController_marketDataService, "f").getMarkets({
|
|
1680
1797
|
provider,
|
|
1681
1798
|
params,
|
|
1682
1799
|
context: __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_createServiceContext).call(this, 'getMarkets'),
|
|
1683
1800
|
isMarketAllowed,
|
|
1684
1801
|
});
|
|
1802
|
+
return provider === __classPrivateFieldGet(this, _PerpsController_standaloneProvider, "f")
|
|
1803
|
+
? __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_trackStandaloneProviderOperation).call(this, provider, operation)
|
|
1804
|
+
: operation;
|
|
1685
1805
|
}
|
|
1686
1806
|
const provider = this.getActiveProvider();
|
|
1687
1807
|
return __classPrivateFieldGet(this, _PerpsController_marketDataService, "f").getMarkets({
|
|
@@ -1707,19 +1827,26 @@ export class PerpsController extends BaseController {
|
|
|
1707
1827
|
* @returns A promise that resolves to the market data.
|
|
1708
1828
|
*/
|
|
1709
1829
|
async getMarketDataWithPrices(params) {
|
|
1830
|
+
const globalSnapshot = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_buildGlobalSnapshotContext).call(this);
|
|
1831
|
+
const context = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_createServiceContext).call(this, 'getMarketDataWithPrices', {
|
|
1832
|
+
...(globalSnapshot && { globalSnapshot }),
|
|
1833
|
+
});
|
|
1710
1834
|
if (params?.standalone) {
|
|
1711
1835
|
const provider = this.activeProviderInstance ?? __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getOrCreateStandaloneProvider).call(this);
|
|
1712
|
-
|
|
1836
|
+
const operation = __classPrivateFieldGet(this, _PerpsController_marketDataService, "f").getMarketDataWithPrices({
|
|
1713
1837
|
provider,
|
|
1714
1838
|
params,
|
|
1715
|
-
context
|
|
1839
|
+
context,
|
|
1716
1840
|
});
|
|
1841
|
+
return provider === __classPrivateFieldGet(this, _PerpsController_standaloneProvider, "f")
|
|
1842
|
+
? __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_trackStandaloneProviderOperation).call(this, provider, operation)
|
|
1843
|
+
: operation;
|
|
1717
1844
|
}
|
|
1718
1845
|
const provider = this.getActiveProvider();
|
|
1719
1846
|
return __classPrivateFieldGet(this, _PerpsController_marketDataService, "f").getMarketDataWithPrices({
|
|
1720
1847
|
provider,
|
|
1721
1848
|
params,
|
|
1722
|
-
context
|
|
1849
|
+
context,
|
|
1723
1850
|
});
|
|
1724
1851
|
}
|
|
1725
1852
|
/**
|
|
@@ -1740,11 +1867,17 @@ export class PerpsController extends BaseController {
|
|
|
1740
1867
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_performMarketDataPreload).call(this).catch(() => {
|
|
1741
1868
|
/* fire-and-forget */
|
|
1742
1869
|
});
|
|
1870
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_performUserDataPreload).call(this).catch(() => {
|
|
1871
|
+
/* fire-and-forget */
|
|
1872
|
+
});
|
|
1743
1873
|
// Periodic refresh
|
|
1744
1874
|
__classPrivateFieldSet(this, _PerpsController_preloadTimer, setInterval(() => {
|
|
1745
1875
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_performMarketDataPreload).call(this).catch(() => {
|
|
1746
1876
|
/* fire-and-forget */
|
|
1747
1877
|
});
|
|
1878
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_performUserDataPreload).call(this).catch(() => {
|
|
1879
|
+
/* fire-and-forget */
|
|
1880
|
+
});
|
|
1748
1881
|
}, __classPrivateFieldGet(_a, _a, "f", _PerpsController_preloadRefreshMs)), "f");
|
|
1749
1882
|
// Watch for isTestnet / hip3ConfigVersion changes
|
|
1750
1883
|
const handler = (_state, patches) => {
|
|
@@ -1773,36 +1906,29 @@ export class PerpsController extends BaseController {
|
|
|
1773
1906
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_performMarketDataPreload).call(this).catch(() => {
|
|
1774
1907
|
/* fire-and-forget */
|
|
1775
1908
|
});
|
|
1909
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_performUserDataPreload).call(this).catch(() => {
|
|
1910
|
+
/* fire-and-forget */
|
|
1911
|
+
});
|
|
1776
1912
|
}
|
|
1777
1913
|
};
|
|
1778
|
-
this.messenger.subscribe('PerpsController:
|
|
1914
|
+
this.messenger.subscribe('PerpsController:stateChanged', handler);
|
|
1779
1915
|
__classPrivateFieldSet(this, _PerpsController_preloadStateUnsubscribe, () => {
|
|
1780
|
-
this.messenger.unsubscribe('PerpsController:
|
|
1916
|
+
this.messenger.unsubscribe('PerpsController:stateChanged', handler);
|
|
1781
1917
|
}, "f");
|
|
1782
1918
|
// Watch for selected account changes and selected account group changes.
|
|
1783
1919
|
const accountChangeHandler = () => {
|
|
1784
1920
|
const evmAccount = getSelectedEvmAccountFromMessenger(this.messenger);
|
|
1785
1921
|
const currentAddress = evmAccount?.address ?? null;
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
// Invalidate disk-cached user data for the old account
|
|
1795
|
-
__classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure.diskCache
|
|
1796
|
-
.removeItem(PERPS_DISK_CACHE_USER_DATA)
|
|
1797
|
-
.catch(() => {
|
|
1922
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: account cache selection', {
|
|
1923
|
+
address: currentAddress?.toLowerCase() ?? null,
|
|
1924
|
+
availableKeys: Object.keys(this.state.cachedUserDataByProvider).sort(),
|
|
1925
|
+
});
|
|
1926
|
+
// The address guard makes the previous entry unreadable immediately;
|
|
1927
|
+
// refresh replaces it under the existing provider/network key.
|
|
1928
|
+
if (currentAddress) {
|
|
1929
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_performUserDataPreload).call(this).catch(() => {
|
|
1798
1930
|
/* fire-and-forget */
|
|
1799
1931
|
});
|
|
1800
|
-
// Only preload if the new account is an EVM account
|
|
1801
|
-
if (currentAddress) {
|
|
1802
|
-
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_performUserDataPreload).call(this).catch(() => {
|
|
1803
|
-
/* fire-and-forget */
|
|
1804
|
-
});
|
|
1805
|
-
}
|
|
1806
1932
|
}
|
|
1807
1933
|
};
|
|
1808
1934
|
this.messenger.subscribe('AccountsController:selectedAccountChange', accountChangeHandler);
|
|
@@ -1831,6 +1957,8 @@ export class PerpsController extends BaseController {
|
|
|
1831
1957
|
}
|
|
1832
1958
|
__classPrivateFieldSet(this, _PerpsController_previousIsTestnet, null, "f");
|
|
1833
1959
|
__classPrivateFieldSet(this, _PerpsController_previousHip3ConfigVersion, null, "f");
|
|
1960
|
+
__classPrivateFieldSet(this, _PerpsController_marketPreloadQueued, false, "f");
|
|
1961
|
+
__classPrivateFieldSet(this, _PerpsController_userPreloadQueued, false, "f");
|
|
1834
1962
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_cleanupStandaloneProvider).call(this).catch(() => {
|
|
1835
1963
|
/* fire-and-forget to preserve sync signature */
|
|
1836
1964
|
});
|
|
@@ -2091,6 +2219,9 @@ export class PerpsController extends BaseController {
|
|
|
2091
2219
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_performMarketDataPreload).call(this).catch(() => {
|
|
2092
2220
|
/* fire-and-forget */
|
|
2093
2221
|
});
|
|
2222
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_performUserDataPreload).call(this).catch(() => {
|
|
2223
|
+
/* fire-and-forget */
|
|
2224
|
+
});
|
|
2094
2225
|
}
|
|
2095
2226
|
}
|
|
2096
2227
|
}
|
|
@@ -2200,6 +2331,9 @@ export class PerpsController extends BaseController {
|
|
|
2200
2331
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_performMarketDataPreload).call(this).catch(() => {
|
|
2201
2332
|
/* fire-and-forget */
|
|
2202
2333
|
});
|
|
2334
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_performUserDataPreload).call(this).catch(() => {
|
|
2335
|
+
/* fire-and-forget */
|
|
2336
|
+
});
|
|
2203
2337
|
}
|
|
2204
2338
|
}
|
|
2205
2339
|
}
|
|
@@ -2535,9 +2669,41 @@ export class PerpsController extends BaseController {
|
|
|
2535
2669
|
*/
|
|
2536
2670
|
async calculateFees(params) {
|
|
2537
2671
|
const provider = this.getActiveProvider();
|
|
2538
|
-
|
|
2672
|
+
// Preview owns subscription hydration. The submit resolver remains a pure
|
|
2673
|
+
// cache read and can therefore never start a benefits request while an
|
|
2674
|
+
// order is being signed.
|
|
2675
|
+
await __classPrivateFieldGet(this, _PerpsController_rewardsIntegrationService, "f").refreshSubscriptionBenefits();
|
|
2676
|
+
const waiverStatus = __classPrivateFieldGet(this, _PerpsController_rewardsIntegrationService, "f").getSubscriptionFeeWaiverStatus();
|
|
2677
|
+
const context = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_createServiceContext).call(this, 'calculateFees', {
|
|
2678
|
+
subscriptionFeeWaiver: waiverStatus.reason === 'no-source' ? undefined : waiverStatus,
|
|
2679
|
+
});
|
|
2539
2680
|
return __classPrivateFieldGet(this, _PerpsController_marketDataService, "f").calculateFees({ provider, params, context });
|
|
2540
2681
|
}
|
|
2682
|
+
/**
|
|
2683
|
+
* Approve the dedicated subscription builder outside order submission.
|
|
2684
|
+
* Until this succeeds, subscription waivers fall back to the ordinary
|
|
2685
|
+
* builder at the standard fee.
|
|
2686
|
+
*
|
|
2687
|
+
* @returns Whether the subscription builder is approved.
|
|
2688
|
+
*/
|
|
2689
|
+
async approveSubscriptionBuilderFee() {
|
|
2690
|
+
const provider = this.getActiveProvider();
|
|
2691
|
+
return provider.approveSubscriptionBuilderFee
|
|
2692
|
+
? provider.approveSubscriptionBuilderFee()
|
|
2693
|
+
: false;
|
|
2694
|
+
}
|
|
2695
|
+
/**
|
|
2696
|
+
* Drop the cached subscription benefits snapshot.
|
|
2697
|
+
*
|
|
2698
|
+
* Call this when the identity behind the benefits changes — sign-out, or a
|
|
2699
|
+
* profile switch. The snapshot carries no profile identity of its own, so
|
|
2700
|
+
* without this it keeps answering for the previous profile until the next
|
|
2701
|
+
* successful refresh. The next fee resolution reports the waiver as
|
|
2702
|
+
* unavailable, so it is withheld until preview or lifecycle hydration.
|
|
2703
|
+
*/
|
|
2704
|
+
invalidateSubscriptionBenefits() {
|
|
2705
|
+
__classPrivateFieldGet(this, _PerpsController_rewardsIntegrationService, "f").invalidateSubscriptionBenefits();
|
|
2706
|
+
}
|
|
2541
2707
|
/**
|
|
2542
2708
|
* Disconnect provider and cleanup subscriptions
|
|
2543
2709
|
* Call this when navigating away from Perps screens to prevent battery drain
|
|
@@ -3262,7 +3428,7 @@ export class PerpsController extends BaseController {
|
|
|
3262
3428
|
return __classPrivateFieldGet(this, _PerpsController_isReinitializing, "f");
|
|
3263
3429
|
}
|
|
3264
3430
|
}
|
|
3265
|
-
_a = PerpsController, _PerpsController_initializationPromise = new WeakMap(), _PerpsController_isReinitializing = new WeakMap(), _PerpsController_myxRegistrationPromise = new WeakMap(), _PerpsController_blockedRegionListVersion = new WeakMap(), _PerpsController_hip3Enabled = new WeakMap(), _PerpsController_hip3AllowlistMarkets = new WeakMap(), _PerpsController_hip3BlocklistMarkets = new WeakMap(), _PerpsController_hip3ConfigSource = new WeakMap(), _PerpsController_priceDeviationLimit = new WeakMap(), _PerpsController_attributionContext = new WeakMap(), _PerpsController_standaloneProvider = new WeakMap(), _PerpsController_handlersRegistered = new WeakMap(), _PerpsController_standaloneProviderIsTestnet = new WeakMap(), _PerpsController_standaloneProviderHip3Version = new WeakMap(), _PerpsController_eligibilityCheckDeferred = new WeakMap(), _PerpsController_ausQueue = new WeakMap(), _PerpsController_options = new WeakMap(), _PerpsController_tradingService = new WeakMap(), _PerpsController_marketDataService = new WeakMap(), _PerpsController_accountService = new WeakMap(), _PerpsController_eligibilityService = new WeakMap(), _PerpsController_dataLakeService = new WeakMap(), _PerpsController_depositService = new WeakMap(), _PerpsController_featureFlagConfigurationService = new WeakMap(), _PerpsController_rewardsIntegrationService = new WeakMap(), _PerpsController_preloadTimer = new WeakMap(), _PerpsController_isPreloading = new WeakMap(), _PerpsController_isPreloadingUserData = new WeakMap(), _PerpsController_preloadStateUnsubscribe = new WeakMap(), _PerpsController_accountChangeUnsubscribe = new WeakMap(), _PerpsController_previousIsTestnet = new WeakMap(), _PerpsController_previousHip3ConfigVersion = new WeakMap(), _PerpsController_instances = new WeakSet(), _PerpsController_isMYXProviderEnabled = function _PerpsController_isMYXProviderEnabled() {
|
|
3431
|
+
_a = PerpsController, _PerpsController_initializationPromise = new WeakMap(), _PerpsController_isReinitializing = new WeakMap(), _PerpsController_myxRegistrationPromise = new WeakMap(), _PerpsController_blockedRegionListVersion = new WeakMap(), _PerpsController_hip3Enabled = new WeakMap(), _PerpsController_hip3AllowlistMarkets = new WeakMap(), _PerpsController_hip3BlocklistMarkets = new WeakMap(), _PerpsController_hip3ConfigSource = new WeakMap(), _PerpsController_priceDeviationLimit = new WeakMap(), _PerpsController_attributionContext = new WeakMap(), _PerpsController_standaloneProvider = new WeakMap(), _PerpsController_handlersRegistered = new WeakMap(), _PerpsController_standaloneProviderIsTestnet = new WeakMap(), _PerpsController_standaloneProviderHip3Version = new WeakMap(), _PerpsController_standaloneProviderOperations = new WeakMap(), _PerpsController_eligibilityCheckDeferred = new WeakMap(), _PerpsController_ausQueue = new WeakMap(), _PerpsController_userDiskWrite = new WeakMap(), _PerpsController_options = new WeakMap(), _PerpsController_tradingService = new WeakMap(), _PerpsController_marketDataService = new WeakMap(), _PerpsController_accountService = new WeakMap(), _PerpsController_eligibilityService = new WeakMap(), _PerpsController_dataLakeService = new WeakMap(), _PerpsController_depositService = new WeakMap(), _PerpsController_featureFlagConfigurationService = new WeakMap(), _PerpsController_rewardsIntegrationService = new WeakMap(), _PerpsController_preloadTimer = new WeakMap(), _PerpsController_isPreloading = new WeakMap(), _PerpsController_marketPreloadQueued = new WeakMap(), _PerpsController_isPreloadingUserData = new WeakMap(), _PerpsController_userPreloadQueued = new WeakMap(), _PerpsController_userSnapshotRequests = new WeakMap(), _PerpsController_preloadStateUnsubscribe = new WeakMap(), _PerpsController_accountChangeUnsubscribe = new WeakMap(), _PerpsController_previousIsTestnet = new WeakMap(), _PerpsController_previousHip3ConfigVersion = new WeakMap(), _PerpsController_instances = new WeakSet(), _PerpsController_isMYXProviderEnabled = function _PerpsController_isMYXProviderEnabled() {
|
|
3266
3432
|
const myx = __classPrivateFieldGet(this, _PerpsController_options, "f").clientConfig?.providerCredentials?.myx;
|
|
3267
3433
|
// Local env-var override (MM_PERPS_MYX_PROVIDER_ENABLED) always wins —
|
|
3268
3434
|
// matches the UI selector (resolvePerpsMyxProviderEnabled) so controller
|
|
@@ -3295,6 +3461,16 @@ _a = PerpsController, _PerpsController_initializationPromise = new WeakMap(), _P
|
|
|
3295
3461
|
__classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure.logger.error(error, options);
|
|
3296
3462
|
}, _PerpsController_debugLog = function _PerpsController_debugLog(...args) {
|
|
3297
3463
|
__classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure.debugLogger.log(...args);
|
|
3464
|
+
}, _PerpsController_awaitInitializationIfInProgress =
|
|
3465
|
+
/**
|
|
3466
|
+
* Awaits the in-flight initialization promise if init is currently running.
|
|
3467
|
+
* Called internally by #getActiveProviderWhenReady().
|
|
3468
|
+
*/
|
|
3469
|
+
async function _PerpsController_awaitInitializationIfInProgress() {
|
|
3470
|
+
if (this.state.initializationState === InitializationState.Initializing &&
|
|
3471
|
+
__classPrivateFieldGet(this, _PerpsController_initializationPromise, "f")) {
|
|
3472
|
+
await __classPrivateFieldGet(this, _PerpsController_initializationPromise, "f");
|
|
3473
|
+
}
|
|
3298
3474
|
}, _PerpsController_getAggregatedCacheProviderIds = function _PerpsController_getAggregatedCacheProviderIds(cacheKeys) {
|
|
3299
3475
|
const providerIds = new Set();
|
|
3300
3476
|
const currentNetwork = this.state.isTestnet ? 'testnet' : 'mainnet';
|
|
@@ -3315,6 +3491,96 @@ _a = PerpsController, _PerpsController_initializationPromise = new WeakMap(), _P
|
|
|
3315
3491
|
}
|
|
3316
3492
|
}
|
|
3317
3493
|
return Array.from(providerIds);
|
|
3494
|
+
}, _PerpsController_isMarketCacheEntryCurrent = function _PerpsController_isMarketCacheEntryCurrent(providerId, entry, options) {
|
|
3495
|
+
if (entry.sourceExpiresAt !== undefined) {
|
|
3496
|
+
const expectedDexes = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getStaticSnapshotDexes).call(this);
|
|
3497
|
+
return (providerId === 'hyperliquid' &&
|
|
3498
|
+
Date.now() < entry.sourceExpiresAt &&
|
|
3499
|
+
entry.hip3ConfigVersion === this.state.hip3ConfigVersion &&
|
|
3500
|
+
expectedDexes !== undefined &&
|
|
3501
|
+
Array.isArray(entry.dexes) &&
|
|
3502
|
+
entry.dexes.length === expectedDexes.length &&
|
|
3503
|
+
entry.dexes.every((dex, index) => dex === expectedDexes[index]));
|
|
3504
|
+
}
|
|
3505
|
+
return (options?.skipTTL === true ||
|
|
3506
|
+
Date.now() - entry.timestamp <= __classPrivateFieldGet(_a, _a, "f", _PerpsController_preloadGuardMs) * 10);
|
|
3507
|
+
}, _PerpsController_isUserCacheIdentityCurrent = function _PerpsController_isUserCacheIdentityCurrent(providerId, entry, address) {
|
|
3508
|
+
if (entry.address.toLowerCase() !== address.toLowerCase()) {
|
|
3509
|
+
return false;
|
|
3510
|
+
}
|
|
3511
|
+
if (providerId !== 'hyperliquid') {
|
|
3512
|
+
return true;
|
|
3513
|
+
}
|
|
3514
|
+
const expectedDexes = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getStaticSnapshotDexes).call(this);
|
|
3515
|
+
return (entry.hip3ConfigVersion === this.state.hip3ConfigVersion &&
|
|
3516
|
+
expectedDexes !== undefined &&
|
|
3517
|
+
Array.isArray(entry.dexes) &&
|
|
3518
|
+
entry.dexes.length === expectedDexes.length &&
|
|
3519
|
+
entry.dexes.every((dex, index) => dex === expectedDexes[index]));
|
|
3520
|
+
}, _PerpsController_fetchAndCacheUserDataSnapshot = async function _PerpsController_fetchAndCacheUserDataSnapshot(context) {
|
|
3521
|
+
const { provider, standaloneProvider, address, isTestnet, hip3ConfigVersion, expectedDexes, isCurrent, } = context;
|
|
3522
|
+
if (!isCurrent()) {
|
|
3523
|
+
throw new Error('User data snapshot context changed');
|
|
3524
|
+
}
|
|
3525
|
+
if (!provider.getUserDataSnapshot) {
|
|
3526
|
+
throw new Error('Provider has no atomic snapshot API');
|
|
3527
|
+
}
|
|
3528
|
+
const identity = {
|
|
3529
|
+
provider: 'hyperliquid',
|
|
3530
|
+
network: isTestnet ? 'testnet' : 'mainnet',
|
|
3531
|
+
hip3ConfigVersion,
|
|
3532
|
+
dexes: expectedDexes,
|
|
3533
|
+
};
|
|
3534
|
+
const snapshotRequest = provider.getUserDataSnapshot({
|
|
3535
|
+
userAddress: address,
|
|
3536
|
+
identity,
|
|
3537
|
+
});
|
|
3538
|
+
const snapshot = standaloneProvider
|
|
3539
|
+
? await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_trackStandaloneProviderOperation).call(this, standaloneProvider, snapshotRequest)
|
|
3540
|
+
: await snapshotRequest;
|
|
3541
|
+
if (!isCurrent()) {
|
|
3542
|
+
throw new Error('User data snapshot context changed');
|
|
3543
|
+
}
|
|
3544
|
+
const snapshotIdentity = snapshot.identity;
|
|
3545
|
+
const hasCompleteBundle = Array.isArray(snapshot.positions) &&
|
|
3546
|
+
Array.isArray(snapshot.orders) &&
|
|
3547
|
+
snapshot.accountState !== null &&
|
|
3548
|
+
typeof snapshot.accountState === 'object';
|
|
3549
|
+
const hasExactIdentity = snapshotIdentity.provider === identity.provider &&
|
|
3550
|
+
snapshotIdentity.network === identity.network &&
|
|
3551
|
+
snapshotIdentity.hip3ConfigVersion === identity.hip3ConfigVersion &&
|
|
3552
|
+
snapshotIdentity.address.toLowerCase() === address.toLowerCase() &&
|
|
3553
|
+
snapshotIdentity.dexes.length === expectedDexes.length &&
|
|
3554
|
+
snapshotIdentity.dexes.every((dex, index) => dex === expectedDexes[index]);
|
|
3555
|
+
if (!hasCompleteBundle || !hasExactIdentity) {
|
|
3556
|
+
throw new Error('User data snapshot is incomplete or mismatched');
|
|
3557
|
+
}
|
|
3558
|
+
if (!isCurrent()) {
|
|
3559
|
+
throw new Error('User data snapshot context changed');
|
|
3560
|
+
}
|
|
3561
|
+
const cachedSnapshot = cloneUserDataSnapshot(snapshot);
|
|
3562
|
+
const result = cloneUserDataSnapshot(snapshot);
|
|
3563
|
+
const timestamp = Date.now();
|
|
3564
|
+
const providerNetworkKey = buildProviderCacheKey('hyperliquid', isTestnet);
|
|
3565
|
+
this.update((state) => {
|
|
3566
|
+
state.cachedUserDataByProvider[providerNetworkKey] = {
|
|
3567
|
+
positions: cachedSnapshot.positions,
|
|
3568
|
+
orders: cachedSnapshot.orders,
|
|
3569
|
+
accountState: cachedSnapshot.accountState,
|
|
3570
|
+
timestamp,
|
|
3571
|
+
address,
|
|
3572
|
+
hip3ConfigVersion,
|
|
3573
|
+
dexes: expectedDexes,
|
|
3574
|
+
};
|
|
3575
|
+
});
|
|
3576
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_persistUserCacheToDisk).call(this);
|
|
3577
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: user cache snapshot written', {
|
|
3578
|
+
writtenKey: providerNetworkKey,
|
|
3579
|
+
availableKeys: Object.keys(this.state.cachedUserDataByProvider).sort(),
|
|
3580
|
+
positionCount: cachedSnapshot.positions.length,
|
|
3581
|
+
orderCount: cachedSnapshot.orders.length,
|
|
3582
|
+
});
|
|
3583
|
+
return result;
|
|
3318
3584
|
}, _PerpsController_getOrCreateStandaloneProvider = function _PerpsController_getOrCreateStandaloneProvider() {
|
|
3319
3585
|
const currentIsTestnet = this.state.isTestnet;
|
|
3320
3586
|
const currentHip3Version = this.state.hip3ConfigVersion ?? 0;
|
|
@@ -3323,10 +3589,13 @@ _a = PerpsController, _PerpsController_initializationPromise = new WeakMap(), _P
|
|
|
3323
3589
|
__classPrivateFieldGet(this, _PerpsController_standaloneProviderHip3Version, "f") === currentHip3Version) {
|
|
3324
3590
|
return __classPrivateFieldGet(this, _PerpsController_standaloneProvider, "f");
|
|
3325
3591
|
}
|
|
3326
|
-
// Stale or missing —
|
|
3592
|
+
// Stale or missing — retire the old provider after active operations finish.
|
|
3327
3593
|
if (__classPrivateFieldGet(this, _PerpsController_standaloneProvider, "f")) {
|
|
3328
3594
|
const old = __classPrivateFieldGet(this, _PerpsController_standaloneProvider, "f");
|
|
3329
|
-
|
|
3595
|
+
__classPrivateFieldSet(this, _PerpsController_standaloneProvider, null, "f");
|
|
3596
|
+
__classPrivateFieldSet(this, _PerpsController_standaloneProviderIsTestnet, null, "f");
|
|
3597
|
+
__classPrivateFieldSet(this, _PerpsController_standaloneProviderHip3Version, null, "f");
|
|
3598
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_retireStandaloneProvider).call(this, old).catch(() => {
|
|
3330
3599
|
/* best-effort */
|
|
3331
3600
|
});
|
|
3332
3601
|
}
|
|
@@ -3342,28 +3611,53 @@ _a = PerpsController, _PerpsController_initializationPromise = new WeakMap(), _P
|
|
|
3342
3611
|
?.builderAddressTestnet,
|
|
3343
3612
|
builderAddressMainnet: __classPrivateFieldGet(this, _PerpsController_options, "f").clientConfig?.providerCredentials?.hyperliquid
|
|
3344
3613
|
?.builderAddressMainnet,
|
|
3614
|
+
subscriptionBuilderAddressTestnet: __classPrivateFieldGet(this, _PerpsController_options, "f").clientConfig?.providerCredentials?.hyperliquid
|
|
3615
|
+
?.subscriptionBuilderAddressTestnet,
|
|
3616
|
+
subscriptionBuilderAddressMainnet: __classPrivateFieldGet(this, _PerpsController_options, "f").clientConfig?.providerCredentials?.hyperliquid
|
|
3617
|
+
?.subscriptionBuilderAddressMainnet,
|
|
3345
3618
|
}), "f");
|
|
3346
3619
|
__classPrivateFieldSet(this, _PerpsController_standaloneProviderIsTestnet, currentIsTestnet, "f");
|
|
3347
3620
|
__classPrivateFieldSet(this, _PerpsController_standaloneProviderHip3Version, currentHip3Version, "f");
|
|
3348
3621
|
return __classPrivateFieldGet(this, _PerpsController_standaloneProvider, "f");
|
|
3622
|
+
}, _PerpsController_trackStandaloneProviderOperation = function _PerpsController_trackStandaloneProviderOperation(provider, operation) {
|
|
3623
|
+
const operations = __classPrivateFieldGet(this, _PerpsController_standaloneProviderOperations, "f").get(provider) ?? new Set();
|
|
3624
|
+
__classPrivateFieldGet(this, _PerpsController_standaloneProviderOperations, "f").set(provider, operations);
|
|
3625
|
+
const trackedOperation = operation.finally(() => {
|
|
3626
|
+
operations.delete(trackedOperation);
|
|
3627
|
+
if (operations.size === 0) {
|
|
3628
|
+
__classPrivateFieldGet(this, _PerpsController_standaloneProviderOperations, "f").delete(provider);
|
|
3629
|
+
}
|
|
3630
|
+
});
|
|
3631
|
+
operations.add(trackedOperation);
|
|
3632
|
+
return trackedOperation;
|
|
3633
|
+
}, _PerpsController_retireStandaloneProvider = async function _PerpsController_retireStandaloneProvider(provider) {
|
|
3634
|
+
const operations = __classPrivateFieldGet(this, _PerpsController_standaloneProviderOperations, "f").get(provider);
|
|
3635
|
+
if (operations?.size) {
|
|
3636
|
+
await Promise.allSettled([...operations]);
|
|
3637
|
+
}
|
|
3638
|
+
try {
|
|
3639
|
+
await provider.disconnect();
|
|
3640
|
+
}
|
|
3641
|
+
catch {
|
|
3642
|
+
/* best-effort */
|
|
3643
|
+
}
|
|
3644
|
+
finally {
|
|
3645
|
+
__classPrivateFieldGet(this, _PerpsController_standaloneProviderOperations, "f").delete(provider);
|
|
3646
|
+
}
|
|
3349
3647
|
}, _PerpsController_cleanupStandaloneProvider =
|
|
3350
3648
|
/**
|
|
3351
3649
|
* Disconnect and discard the cached standalone provider (if any).
|
|
3352
3650
|
* Best-effort — errors are silently caught.
|
|
3353
3651
|
*/
|
|
3354
3652
|
async function _PerpsController_cleanupStandaloneProvider() {
|
|
3355
|
-
|
|
3653
|
+
const provider = __classPrivateFieldGet(this, _PerpsController_standaloneProvider, "f");
|
|
3654
|
+
if (!provider) {
|
|
3356
3655
|
return;
|
|
3357
3656
|
}
|
|
3358
|
-
try {
|
|
3359
|
-
await __classPrivateFieldGet(this, _PerpsController_standaloneProvider, "f").disconnect();
|
|
3360
|
-
}
|
|
3361
|
-
catch {
|
|
3362
|
-
/* best-effort */
|
|
3363
|
-
}
|
|
3364
3657
|
__classPrivateFieldSet(this, _PerpsController_standaloneProvider, null, "f");
|
|
3365
3658
|
__classPrivateFieldSet(this, _PerpsController_standaloneProviderIsTestnet, null, "f");
|
|
3366
3659
|
__classPrivateFieldSet(this, _PerpsController_standaloneProviderHip3Version, null, "f");
|
|
3660
|
+
await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_retireStandaloneProvider).call(this, provider);
|
|
3367
3661
|
}, _PerpsController_getMetrics = function _PerpsController_getMetrics() {
|
|
3368
3662
|
return __classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure.metrics;
|
|
3369
3663
|
}, _PerpsController_findNetworkClientIdForChain = function _PerpsController_findNetworkClientIdForChain(chainId) {
|
|
@@ -3581,6 +3875,10 @@ async function _PerpsController_performInitialization() {
|
|
|
3581
3875
|
?.builderAddressTestnet,
|
|
3582
3876
|
builderAddressMainnet: __classPrivateFieldGet(this, _PerpsController_options, "f").clientConfig?.providerCredentials?.hyperliquid
|
|
3583
3877
|
?.builderAddressMainnet,
|
|
3878
|
+
subscriptionBuilderAddressTestnet: __classPrivateFieldGet(this, _PerpsController_options, "f").clientConfig?.providerCredentials?.hyperliquid
|
|
3879
|
+
?.subscriptionBuilderAddressTestnet,
|
|
3880
|
+
subscriptionBuilderAddressMainnet: __classPrivateFieldGet(this, _PerpsController_options, "f").clientConfig?.providerCredentials?.hyperliquid
|
|
3881
|
+
?.subscriptionBuilderAddressMainnet,
|
|
3584
3882
|
});
|
|
3585
3883
|
this.providers.set('hyperliquid', hyperLiquidProvider);
|
|
3586
3884
|
// Register MYX provider if enabled via feature flag.
|
|
@@ -3697,6 +3995,75 @@ async function _PerpsController_performInitialization() {
|
|
|
3697
3995
|
__classPrivateFieldGet(this, _PerpsController_tradingService, "f").setControllerDependencies({
|
|
3698
3996
|
rewardsIntegrationService: __classPrivateFieldGet(this, _PerpsController_rewardsIntegrationService, "f"),
|
|
3699
3997
|
});
|
|
3998
|
+
}, _PerpsController_getActiveProviderWhenReady =
|
|
3999
|
+
/**
|
|
4000
|
+
* Await in-flight initialization, then return the active provider.
|
|
4001
|
+
* Use for async action methods (trading, deposits, withdrawals) that should
|
|
4002
|
+
* tolerate an in-progress cold-start or reconnection instead of failing
|
|
4003
|
+
* immediately with CLIENT_NOT_INITIALIZED.
|
|
4004
|
+
*
|
|
4005
|
+
* Synchronous callers that need fail-fast behaviour should keep using
|
|
4006
|
+
* getActiveProvider() directly.
|
|
4007
|
+
*
|
|
4008
|
+
* @returns The active provider once initialization completes.
|
|
4009
|
+
*/
|
|
4010
|
+
async function _PerpsController_getActiveProviderWhenReady() {
|
|
4011
|
+
await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_awaitInitializationIfInProgress).call(this);
|
|
4012
|
+
return this.getActiveProvider();
|
|
4013
|
+
}, _PerpsController_buildGlobalSnapshotContext = function _PerpsController_buildGlobalSnapshotContext() {
|
|
4014
|
+
const snapshotConfigured = Boolean(__classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure.terminalApi?.globalSnapshotUrl) ||
|
|
4015
|
+
typeof __classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure.terminalMarketService
|
|
4016
|
+
?.fetchGlobalSnapshot === 'function';
|
|
4017
|
+
if (!snapshotConfigured || this.state.activeProvider !== 'hyperliquid') {
|
|
4018
|
+
return undefined;
|
|
4019
|
+
}
|
|
4020
|
+
const enabledDexes = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getStaticSnapshotDexes).call(this);
|
|
4021
|
+
if (!enabledDexes) {
|
|
4022
|
+
return undefined;
|
|
4023
|
+
}
|
|
4024
|
+
const { isTestnet, hip3ConfigVersion } = this.state;
|
|
4025
|
+
return {
|
|
4026
|
+
request: {
|
|
4027
|
+
provider: 'hyperliquid',
|
|
4028
|
+
network: isTestnet ? 'testnet' : 'mainnet',
|
|
4029
|
+
enabledDexes,
|
|
4030
|
+
},
|
|
4031
|
+
isCurrent: () => this.state.activeProvider === 'hyperliquid' &&
|
|
4032
|
+
this.state.isTestnet === isTestnet &&
|
|
4033
|
+
this.state.hip3ConfigVersion === hip3ConfigVersion,
|
|
4034
|
+
isMarketAllowed: __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_buildMarketAllowedFilter).call(this),
|
|
4035
|
+
};
|
|
4036
|
+
}, _PerpsController_getStaticSnapshotDexes = function _PerpsController_getStaticSnapshotDexes() {
|
|
4037
|
+
if (!__classPrivateFieldGet(this, _PerpsController_hip3Enabled, "f")) {
|
|
4038
|
+
return ['main'];
|
|
4039
|
+
}
|
|
4040
|
+
if (this.state.isTestnet) {
|
|
4041
|
+
return TESTNET_HIP3_CONFIG.AutoDiscoverAll
|
|
4042
|
+
? undefined
|
|
4043
|
+
: canonicalizeHyperLiquidDexes(TESTNET_HIP3_CONFIG.EnabledDexs);
|
|
4044
|
+
}
|
|
4045
|
+
if (MAINNET_HIP3_CONFIG.AutoDiscoverAll) {
|
|
4046
|
+
return undefined;
|
|
4047
|
+
}
|
|
4048
|
+
const dexes = new Set();
|
|
4049
|
+
for (const pattern of __classPrivateFieldGet(this, _PerpsController_hip3AllowlistMarkets, "f")) {
|
|
4050
|
+
const colonIndex = pattern.indexOf(':');
|
|
4051
|
+
if (colonIndex <= 0) {
|
|
4052
|
+
if (/^[a-z][a-z0-9]*$/iu.test(pattern)) {
|
|
4053
|
+
dexes.add(pattern.toLowerCase());
|
|
4054
|
+
continue;
|
|
4055
|
+
}
|
|
4056
|
+
return undefined;
|
|
4057
|
+
}
|
|
4058
|
+
const dex = pattern.slice(0, colonIndex);
|
|
4059
|
+
if (dex && /^[a-z0-9][a-z0-9-]*$/u.test(dex)) {
|
|
4060
|
+
dexes.add(dex);
|
|
4061
|
+
}
|
|
4062
|
+
else {
|
|
4063
|
+
return undefined;
|
|
4064
|
+
}
|
|
4065
|
+
}
|
|
4066
|
+
return canonicalizeHyperLiquidDexes(dexes);
|
|
3700
4067
|
}, _PerpsController_hydrateCacheFromDiskSync = function _PerpsController_hydrateCacheFromDiskSync() {
|
|
3701
4068
|
const { marketUpdates, userUpdates, stats } = hydrateFromDiskSync(__classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure.diskCache, this.state.cachedMarketDataByProvider, this.state.cachedUserDataByProvider, __classPrivateFieldGet(_a, _a, "f", _PerpsController_preloadGuardMs));
|
|
3702
4069
|
const hasMarketUpdates = Object.keys(marketUpdates).length > 0;
|
|
@@ -3717,12 +4084,40 @@ async function _PerpsController_performInitialization() {
|
|
|
3717
4084
|
orders: stats.userOrders,
|
|
3718
4085
|
duration_ms: stats.durationMs,
|
|
3719
4086
|
});
|
|
4087
|
+
}, _PerpsController_persistUserCacheToDisk = function _PerpsController_persistUserCacheToDisk() {
|
|
4088
|
+
const entries = [];
|
|
4089
|
+
for (const [cacheKey, entry] of Object.entries(this.state.cachedUserDataByProvider)) {
|
|
4090
|
+
const [providerId, network] = cacheKey.split(':');
|
|
4091
|
+
if (!providerId ||
|
|
4092
|
+
(network !== 'mainnet' && network !== 'testnet') ||
|
|
4093
|
+
providerId === 'aggregated') {
|
|
4094
|
+
continue;
|
|
4095
|
+
}
|
|
4096
|
+
entries.push({
|
|
4097
|
+
providerNetworkKey: `${providerId}:${network}`,
|
|
4098
|
+
address: entry.address,
|
|
4099
|
+
positions: entry.positions,
|
|
4100
|
+
orders: entry.orders,
|
|
4101
|
+
accountState: entry.accountState,
|
|
4102
|
+
timestamp: entry.timestamp,
|
|
4103
|
+
...(entry.hip3ConfigVersion !== undefined && {
|
|
4104
|
+
hip3ConfigVersion: entry.hip3ConfigVersion,
|
|
4105
|
+
}),
|
|
4106
|
+
...(entry.dexes !== undefined && { dexes: entry.dexes }),
|
|
4107
|
+
});
|
|
4108
|
+
}
|
|
4109
|
+
__classPrivateFieldSet(this, _PerpsController_userDiskWrite, __classPrivateFieldGet(this, _PerpsController_userDiskWrite, "f")
|
|
4110
|
+
.then(() => persistUserEntriesToDisk(__classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure.diskCache, entries))
|
|
4111
|
+
.catch(() => {
|
|
4112
|
+
// Disk persistence is best-effort and must not block live data.
|
|
4113
|
+
}), "f");
|
|
3720
4114
|
}, _PerpsController_performMarketDataPreload =
|
|
3721
4115
|
/**
|
|
3722
4116
|
* Perform a single market data preload (best-effort, no throw).
|
|
3723
4117
|
*/
|
|
3724
4118
|
async function _PerpsController_performMarketDataPreload() {
|
|
3725
4119
|
if (__classPrivateFieldGet(this, _PerpsController_isPreloading, "f")) {
|
|
4120
|
+
__classPrivateFieldSet(this, _PerpsController_marketPreloadQueued, true, "f");
|
|
3726
4121
|
return;
|
|
3727
4122
|
}
|
|
3728
4123
|
// Skip preloading during provider/network reinitialisation.
|
|
@@ -3737,9 +4132,16 @@ async function _PerpsController_performMarketDataPreload() {
|
|
|
3737
4132
|
? this.state.activeProvider // includes 'aggregated'
|
|
3738
4133
|
: 'hyperliquid';
|
|
3739
4134
|
const cacheKey = buildProviderCacheKey(actualProviderId, this.state.isTestnet);
|
|
4135
|
+
const preloadContext = {
|
|
4136
|
+
activeProvider: this.state.activeProvider,
|
|
4137
|
+
isTestnet: this.state.isTestnet,
|
|
4138
|
+
hip3ConfigVersion: this.state.hip3ConfigVersion,
|
|
4139
|
+
};
|
|
4140
|
+
const staticSnapshotDexes = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getStaticSnapshotDexes).call(this);
|
|
3740
4141
|
const now = Date.now();
|
|
3741
4142
|
const existingEntry = this.state.cachedMarketDataByProvider[cacheKey];
|
|
3742
4143
|
if (existingEntry &&
|
|
4144
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_isMarketCacheEntryCurrent).call(this, actualProviderId, existingEntry) &&
|
|
3743
4145
|
now - existingEntry.timestamp < __classPrivateFieldGet(_a, _a, "f", _PerpsController_preloadGuardMs)) {
|
|
3744
4146
|
return;
|
|
3745
4147
|
}
|
|
@@ -3764,8 +4166,32 @@ async function _PerpsController_performMarketDataPreload() {
|
|
|
3764
4166
|
duration_ms: Math.round(performance.now() - preloadStart),
|
|
3765
4167
|
markets: data.length,
|
|
3766
4168
|
});
|
|
4169
|
+
if (this.state.activeProvider !== preloadContext.activeProvider ||
|
|
4170
|
+
this.state.isTestnet !== preloadContext.isTestnet ||
|
|
4171
|
+
this.state.hip3ConfigVersion !== preloadContext.hip3ConfigVersion) {
|
|
4172
|
+
traceData = {
|
|
4173
|
+
success: false,
|
|
4174
|
+
error: 'Global snapshot preload context changed',
|
|
4175
|
+
};
|
|
4176
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: Discarding stale global snapshot preload');
|
|
4177
|
+
return;
|
|
4178
|
+
}
|
|
3767
4179
|
// Store under per-provider key(s)
|
|
3768
4180
|
const ts = Date.now();
|
|
4181
|
+
const sourceExpiries = data.flatMap((market) => market.dataSource === 'terminal-global-snapshot-mark' &&
|
|
4182
|
+
typeof market.sourceExpiresAt === 'number'
|
|
4183
|
+
? [market.sourceExpiresAt]
|
|
4184
|
+
: []);
|
|
4185
|
+
const sourceExpiresAt = data.length > 0 && sourceExpiries.length === data.length
|
|
4186
|
+
? Math.min(...sourceExpiries)
|
|
4187
|
+
: undefined;
|
|
4188
|
+
const snapshotCacheIdentity = sourceExpiresAt !== undefined && staticSnapshotDexes
|
|
4189
|
+
? {
|
|
4190
|
+
sourceExpiresAt,
|
|
4191
|
+
hip3ConfigVersion: preloadContext.hip3ConfigVersion,
|
|
4192
|
+
dexes: staticSnapshotDexes,
|
|
4193
|
+
}
|
|
4194
|
+
: {};
|
|
3769
4195
|
const marketDiskEntries = [];
|
|
3770
4196
|
if (this.state.activeProvider === 'aggregated' &&
|
|
3771
4197
|
this.activeProviderInstance) {
|
|
@@ -3812,6 +4238,7 @@ async function _PerpsController_performMarketDataPreload() {
|
|
|
3812
4238
|
state.cachedMarketDataByProvider[cacheKey] = {
|
|
3813
4239
|
data,
|
|
3814
4240
|
timestamp: ts,
|
|
4241
|
+
...snapshotCacheIdentity,
|
|
3815
4242
|
};
|
|
3816
4243
|
});
|
|
3817
4244
|
}
|
|
@@ -3821,10 +4248,6 @@ async function _PerpsController_performMarketDataPreload() {
|
|
|
3821
4248
|
});
|
|
3822
4249
|
traceData = { success: true, marketCount: data.length };
|
|
3823
4250
|
__classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure.tracer.setMeasurement(PerpsMeasurementName.PerpsMarketDataPreload, performance.now() - preloadStart, 'millisecond');
|
|
3824
|
-
// Also preload user data (fire-and-forget, non-blocking)
|
|
3825
|
-
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_performUserDataPreload).call(this).catch(() => {
|
|
3826
|
-
/* fire-and-forget */
|
|
3827
|
-
});
|
|
3828
4251
|
}
|
|
3829
4252
|
catch (error) {
|
|
3830
4253
|
traceData = {
|
|
@@ -3843,6 +4266,12 @@ async function _PerpsController_performMarketDataPreload() {
|
|
|
3843
4266
|
data: traceData,
|
|
3844
4267
|
});
|
|
3845
4268
|
__classPrivateFieldSet(this, _PerpsController_isPreloading, false, "f");
|
|
4269
|
+
if (__classPrivateFieldGet(this, _PerpsController_marketPreloadQueued, "f") && __classPrivateFieldGet(this, _PerpsController_preloadTimer, "f")) {
|
|
4270
|
+
__classPrivateFieldSet(this, _PerpsController_marketPreloadQueued, false, "f");
|
|
4271
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_performMarketDataPreload).call(this).catch(() => {
|
|
4272
|
+
// Background preload is best-effort.
|
|
4273
|
+
});
|
|
4274
|
+
}
|
|
3846
4275
|
}
|
|
3847
4276
|
}, _PerpsController_performUserDataPreload =
|
|
3848
4277
|
/**
|
|
@@ -3851,6 +4280,10 @@ async function _PerpsController_performMarketDataPreload() {
|
|
|
3851
4280
|
*/
|
|
3852
4281
|
async function _PerpsController_performUserDataPreload() {
|
|
3853
4282
|
if (__classPrivateFieldGet(this, _PerpsController_isPreloadingUserData, "f")) {
|
|
4283
|
+
__classPrivateFieldSet(this, _PerpsController_userPreloadQueued, true, "f");
|
|
4284
|
+
return;
|
|
4285
|
+
}
|
|
4286
|
+
if (__classPrivateFieldGet(this, _PerpsController_isReinitializing, "f")) {
|
|
3854
4287
|
return;
|
|
3855
4288
|
}
|
|
3856
4289
|
// Get current user address
|
|
@@ -3859,21 +4292,54 @@ async function _PerpsController_performUserDataPreload() {
|
|
|
3859
4292
|
return;
|
|
3860
4293
|
}
|
|
3861
4294
|
const userAddress = evmAccount.address;
|
|
4295
|
+
const { activeProvider, isTestnet, hip3ConfigVersion } = this.state;
|
|
4296
|
+
const { activeProviderInstance } = this;
|
|
4297
|
+
const hyperliquidDexes = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getStaticSnapshotDexes).call(this);
|
|
4298
|
+
const isCurrent = () => {
|
|
4299
|
+
let currentAddress;
|
|
4300
|
+
try {
|
|
4301
|
+
currentAddress = getSelectedEvmAccountFromMessenger(this.messenger)?.address;
|
|
4302
|
+
}
|
|
4303
|
+
catch {
|
|
4304
|
+
return false;
|
|
4305
|
+
}
|
|
4306
|
+
return (this.state.activeProvider === activeProvider &&
|
|
4307
|
+
this.activeProviderInstance === activeProviderInstance &&
|
|
4308
|
+
this.state.isTestnet === isTestnet &&
|
|
4309
|
+
this.state.hip3ConfigVersion === hip3ConfigVersion &&
|
|
4310
|
+
currentAddress?.toLowerCase() === userAddress.toLowerCase());
|
|
4311
|
+
};
|
|
3862
4312
|
// Determine actual provider (same logic as market preload)
|
|
3863
|
-
const actualProviderId =
|
|
3864
|
-
?
|
|
4313
|
+
const actualProviderId = activeProviderInstance
|
|
4314
|
+
? activeProvider // includes 'aggregated'
|
|
3865
4315
|
: 'hyperliquid';
|
|
3866
|
-
const
|
|
4316
|
+
const providerNetworkKey = buildProviderCacheKey(actualProviderId, isTestnet);
|
|
3867
4317
|
// Skip if cache is fresh and for same account
|
|
3868
4318
|
const now = Date.now();
|
|
3869
|
-
const existingEntry = this.state.cachedUserDataByProvider[
|
|
3870
|
-
|
|
4319
|
+
const existingEntry = this.state.cachedUserDataByProvider[providerNetworkKey];
|
|
4320
|
+
const hasMatchingCache = existingEntry !== undefined &&
|
|
4321
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_isUserCacheIdentityCurrent).call(this, actualProviderId, existingEntry, userAddress);
|
|
4322
|
+
const cacheAgeMs = existingEntry ? now - existingEntry.timestamp : null;
|
|
4323
|
+
const websocketState = this.getWebSocketConnectionState();
|
|
4324
|
+
let selectedEntryKey = null;
|
|
4325
|
+
if (this.state.cachedUserDataByProvider[providerNetworkKey]) {
|
|
4326
|
+
selectedEntryKey = providerNetworkKey;
|
|
4327
|
+
}
|
|
4328
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: user cache preload decision', {
|
|
4329
|
+
requestedKey: providerNetworkKey,
|
|
4330
|
+
selectedEntryKey,
|
|
4331
|
+
availableKeys: Object.keys(this.state.cachedUserDataByProvider).sort(),
|
|
4332
|
+
hasMatchingCache,
|
|
4333
|
+
cacheAgeMs,
|
|
4334
|
+
websocketState,
|
|
4335
|
+
});
|
|
4336
|
+
if (existingEntry &&
|
|
4337
|
+
hasMatchingCache &&
|
|
3871
4338
|
now - existingEntry.timestamp < __classPrivateFieldGet(_a, _a, "f", _PerpsController_preloadGuardMs)) {
|
|
3872
4339
|
return;
|
|
3873
4340
|
}
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: Skipping user data preload — WebSocket connected');
|
|
4341
|
+
if (hasMatchingCache &&
|
|
4342
|
+
this.getWebSocketConnectionState() === WebSocketConnectionState.Connected) {
|
|
3877
4343
|
return;
|
|
3878
4344
|
}
|
|
3879
4345
|
__classPrivateFieldSet(this, _PerpsController_isPreloadingUserData, true, "f");
|
|
@@ -3886,21 +4352,38 @@ async function _PerpsController_performUserDataPreload() {
|
|
|
3886
4352
|
id: traceId,
|
|
3887
4353
|
op: PerpsTraceOperations.Operation,
|
|
3888
4354
|
tags: {
|
|
3889
|
-
provider:
|
|
3890
|
-
isTestnet
|
|
4355
|
+
provider: activeProvider,
|
|
4356
|
+
isTestnet,
|
|
3891
4357
|
},
|
|
3892
4358
|
data: { userAddress },
|
|
3893
4359
|
});
|
|
3894
4360
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: Fetching user data in background', {
|
|
3895
4361
|
userAddress,
|
|
3896
4362
|
});
|
|
4363
|
+
if (activeProvider === 'hyperliquid') {
|
|
4364
|
+
const snapshot = await this.getUserDataSnapshot();
|
|
4365
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: User data preloaded', {
|
|
4366
|
+
positionCount: snapshot.positions.length,
|
|
4367
|
+
orderCount: snapshot.orders.length,
|
|
4368
|
+
totalBalance: snapshot.accountState.totalBalance,
|
|
4369
|
+
});
|
|
4370
|
+
traceData = {
|
|
4371
|
+
success: true,
|
|
4372
|
+
positionCount: snapshot.positions.length,
|
|
4373
|
+
orderCount: snapshot.orders.length,
|
|
4374
|
+
};
|
|
4375
|
+
__classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure.tracer.setMeasurement(PerpsMeasurementName.PerpsUserDataPreload, performance.now() - preloadStart, 'millisecond');
|
|
4376
|
+
return;
|
|
4377
|
+
}
|
|
3897
4378
|
const [positions, orders, accountState] = await Promise.all([
|
|
3898
4379
|
this.getPositions({ standalone: true, userAddress }),
|
|
3899
4380
|
this.getOpenOrders({ standalone: true, userAddress }),
|
|
3900
4381
|
this.getAccountState({ standalone: true, userAddress }),
|
|
3901
4382
|
]);
|
|
3902
|
-
if (
|
|
3903
|
-
|
|
4383
|
+
if (!isCurrent()) {
|
|
4384
|
+
throw new Error('User data preload context changed');
|
|
4385
|
+
}
|
|
4386
|
+
if (activeProvider === 'aggregated' && activeProviderInstance) {
|
|
3904
4387
|
// Split by providerId and write one cache entry per provider key
|
|
3905
4388
|
// (mirrors the market-data preload pattern at ~line 2976)
|
|
3906
4389
|
const ts = Date.now();
|
|
@@ -3922,26 +4405,22 @@ async function _PerpsController_performUserDataPreload() {
|
|
|
3922
4405
|
}
|
|
3923
4406
|
// AccountState — assign to its provider bucket
|
|
3924
4407
|
ensureBucket(accountState.providerId ?? fallbackProviderId).accountState = accountState;
|
|
3925
|
-
const diskEntries = [];
|
|
3926
4408
|
this.update((state) => {
|
|
3927
4409
|
for (const [pid, data] of byProvider) {
|
|
3928
|
-
const key = buildProviderCacheKey(pid,
|
|
3929
|
-
diskEntries.push({
|
|
3930
|
-
providerNetworkKey: key,
|
|
3931
|
-
address: userAddress,
|
|
3932
|
-
positions: data.positions,
|
|
3933
|
-
orders: data.orders,
|
|
3934
|
-
accountState: data.accountState,
|
|
3935
|
-
timestamp: ts,
|
|
3936
|
-
});
|
|
4410
|
+
const key = buildProviderCacheKey(pid, isTestnet);
|
|
3937
4411
|
state.cachedUserDataByProvider[key] = {
|
|
3938
4412
|
...data,
|
|
3939
4413
|
timestamp: ts,
|
|
3940
4414
|
address: userAddress,
|
|
4415
|
+
...(pid === 'hyperliquid' &&
|
|
4416
|
+
hyperliquidDexes && {
|
|
4417
|
+
hip3ConfigVersion,
|
|
4418
|
+
dexes: hyperliquidDexes,
|
|
4419
|
+
}),
|
|
3941
4420
|
};
|
|
3942
4421
|
}
|
|
3943
4422
|
// Write aggregated sentinel so the staleness guard sees it
|
|
3944
|
-
state.cachedUserDataByProvider[
|
|
4423
|
+
state.cachedUserDataByProvider[providerNetworkKey] = {
|
|
3945
4424
|
positions: [],
|
|
3946
4425
|
orders: [],
|
|
3947
4426
|
accountState: null,
|
|
@@ -3949,30 +4428,26 @@ async function _PerpsController_performUserDataPreload() {
|
|
|
3949
4428
|
address: userAddress,
|
|
3950
4429
|
};
|
|
3951
4430
|
});
|
|
3952
|
-
|
|
4431
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_persistUserCacheToDisk).call(this);
|
|
3953
4432
|
}
|
|
3954
4433
|
else {
|
|
3955
4434
|
// Single provider — store directly under its key
|
|
3956
4435
|
const ts = Date.now();
|
|
3957
4436
|
this.update((state) => {
|
|
3958
|
-
state.cachedUserDataByProvider[
|
|
4437
|
+
state.cachedUserDataByProvider[providerNetworkKey] = {
|
|
3959
4438
|
positions,
|
|
3960
4439
|
orders,
|
|
3961
4440
|
accountState,
|
|
3962
4441
|
timestamp: ts,
|
|
3963
4442
|
address: userAddress,
|
|
4443
|
+
...(actualProviderId === 'hyperliquid' &&
|
|
4444
|
+
hyperliquidDexes && {
|
|
4445
|
+
hip3ConfigVersion,
|
|
4446
|
+
dexes: hyperliquidDexes,
|
|
4447
|
+
}),
|
|
3964
4448
|
};
|
|
3965
4449
|
});
|
|
3966
|
-
|
|
3967
|
-
{
|
|
3968
|
-
providerNetworkKey: userCacheKey,
|
|
3969
|
-
address: userAddress,
|
|
3970
|
-
positions,
|
|
3971
|
-
orders,
|
|
3972
|
-
accountState,
|
|
3973
|
-
timestamp: ts,
|
|
3974
|
-
},
|
|
3975
|
-
]);
|
|
4450
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_persistUserCacheToDisk).call(this);
|
|
3976
4451
|
}
|
|
3977
4452
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: User data preloaded', {
|
|
3978
4453
|
positionCount: positions.length,
|
|
@@ -4003,6 +4478,12 @@ async function _PerpsController_performUserDataPreload() {
|
|
|
4003
4478
|
data: traceData,
|
|
4004
4479
|
});
|
|
4005
4480
|
__classPrivateFieldSet(this, _PerpsController_isPreloadingUserData, false, "f");
|
|
4481
|
+
if (__classPrivateFieldGet(this, _PerpsController_userPreloadQueued, "f") && __classPrivateFieldGet(this, _PerpsController_preloadTimer, "f")) {
|
|
4482
|
+
__classPrivateFieldSet(this, _PerpsController_userPreloadQueued, false, "f");
|
|
4483
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_performUserDataPreload).call(this).catch(() => {
|
|
4484
|
+
// Background preload is best-effort.
|
|
4485
|
+
});
|
|
4486
|
+
}
|
|
4006
4487
|
}
|
|
4007
4488
|
}, _PerpsController_persistWatchlistToRemote =
|
|
4008
4489
|
/**
|