@metamask-previews/perps-controller 12.2.0-preview-e68ab1498 → 13.0.0-preview-4b37525
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 +15 -6
- package/dist/PerpsController-method-action-types.cjs.map +1 -1
- package/dist/PerpsController-method-action-types.d.cts +26 -3
- package/dist/PerpsController-method-action-types.d.cts.map +1 -1
- package/dist/PerpsController-method-action-types.d.mts +26 -3
- 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 +392 -102
- package/dist/PerpsController.cjs.map +1 -1
- package/dist/PerpsController.d.cts +26 -7
- package/dist/PerpsController.d.cts.map +1 -1
- package/dist/PerpsController.d.mts +26 -7
- package/dist/PerpsController.d.mts.map +1 -1
- package/dist/PerpsController.mjs +392 -102
- package/dist/PerpsController.mjs.map +1 -1
- package/dist/constants/eventNames.cjs +1 -1
- package/dist/constants/eventNames.cjs.map +1 -1
- package/dist/constants/eventNames.d.cts +1 -1
- package/dist/constants/eventNames.d.mts +1 -1
- package/dist/constants/eventNames.mjs +1 -1
- 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 +10 -0
- package/dist/constants/hyperLiquidConfig.d.cts.map +1 -1
- package/dist/constants/hyperLiquidConfig.d.mts +10 -0
- package/dist/constants/hyperLiquidConfig.d.mts.map +1 -1
- package/dist/constants/hyperLiquidConfig.mjs +12 -0
- package/dist/constants/hyperLiquidConfig.mjs.map +1 -1
- package/dist/constants/perpsConfig.cjs +3 -4
- package/dist/constants/perpsConfig.cjs.map +1 -1
- package/dist/constants/perpsConfig.d.cts +2 -4
- package/dist/constants/perpsConfig.d.cts.map +1 -1
- package/dist/constants/perpsConfig.d.mts +2 -4
- package/dist/constants/perpsConfig.d.mts.map +1 -1
- package/dist/constants/perpsConfig.mjs +3 -4
- package/dist/constants/perpsConfig.mjs.map +1 -1
- package/dist/index.cjs +8 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +4 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -0
- package/dist/index.mjs.map +1 -1
- package/dist/perpsErrorCodes.cjs +5 -1
- package/dist/perpsErrorCodes.cjs.map +1 -1
- package/dist/perpsErrorCodes.d.cts +4 -0
- package/dist/perpsErrorCodes.d.cts.map +1 -1
- package/dist/perpsErrorCodes.d.mts +4 -0
- package/dist/perpsErrorCodes.d.mts.map +1 -1
- package/dist/perpsErrorCodes.mjs +5 -1
- package/dist/perpsErrorCodes.mjs.map +1 -1
- package/dist/providers/AggregatedPerpsProvider.cjs +104 -14
- package/dist/providers/AggregatedPerpsProvider.cjs.map +1 -1
- package/dist/providers/AggregatedPerpsProvider.d.cts +34 -2
- package/dist/providers/AggregatedPerpsProvider.d.cts.map +1 -1
- package/dist/providers/AggregatedPerpsProvider.d.mts +34 -2
- package/dist/providers/AggregatedPerpsProvider.d.mts.map +1 -1
- package/dist/providers/AggregatedPerpsProvider.mjs +102 -13
- package/dist/providers/AggregatedPerpsProvider.mjs.map +1 -1
- package/dist/providers/HyperLiquidProvider.cjs +2141 -637
- package/dist/providers/HyperLiquidProvider.cjs.map +1 -1
- package/dist/providers/HyperLiquidProvider.d.cts +37 -17
- package/dist/providers/HyperLiquidProvider.d.cts.map +1 -1
- package/dist/providers/HyperLiquidProvider.d.mts +37 -17
- package/dist/providers/HyperLiquidProvider.d.mts.map +1 -1
- package/dist/providers/HyperLiquidProvider.mjs +2146 -642
- package/dist/providers/HyperLiquidProvider.mjs.map +1 -1
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.d.cts +96 -3
- package/dist/types/index.d.cts.map +1 -1
- package/dist/types/index.d.mts +96 -3
- package/dist/types/index.d.mts.map +1 -1
- package/dist/types/index.mjs.map +1 -1
- package/dist/utils/capabilitySymbols.cjs +25 -0
- package/dist/utils/capabilitySymbols.cjs.map +1 -0
- package/dist/utils/capabilitySymbols.d.cts +15 -0
- package/dist/utils/capabilitySymbols.d.cts.map +1 -0
- package/dist/utils/capabilitySymbols.d.mts +15 -0
- package/dist/utils/capabilitySymbols.d.mts.map +1 -0
- package/dist/utils/capabilitySymbols.mjs +21 -0
- package/dist/utils/capabilitySymbols.mjs.map +1 -0
- package/dist/utils/hyperLiquidAdapter.cjs +20 -1
- package/dist/utils/hyperLiquidAdapter.cjs.map +1 -1
- package/dist/utils/hyperLiquidAdapter.d.cts +1 -0
- package/dist/utils/hyperLiquidAdapter.d.cts.map +1 -1
- package/dist/utils/hyperLiquidAdapter.d.mts +1 -0
- package/dist/utils/hyperLiquidAdapter.d.mts.map +1 -1
- package/dist/utils/hyperLiquidAdapter.mjs +19 -0
- package/dist/utils/hyperLiquidAdapter.mjs.map +1 -1
- package/dist/utils/hyperLiquidValidation.cjs +1 -1
- package/dist/utils/hyperLiquidValidation.cjs.map +1 -1
- package/dist/utils/hyperLiquidValidation.d.cts +1 -1
- package/dist/utils/hyperLiquidValidation.d.mts +1 -1
- package/dist/utils/hyperLiquidValidation.mjs +1 -1
- package/dist/utils/hyperLiquidValidation.mjs.map +1 -1
- package/dist/utils/stringParseUtils.cjs +17 -1
- package/dist/utils/stringParseUtils.cjs.map +1 -1
- package/dist/utils/stringParseUtils.d.cts +8 -0
- package/dist/utils/stringParseUtils.d.cts.map +1 -1
- package/dist/utils/stringParseUtils.d.mts +8 -0
- package/dist/utils/stringParseUtils.d.mts.map +1 -1
- package/dist/utils/stringParseUtils.mjs +15 -0
- package/dist/utils/stringParseUtils.mjs.map +1 -1
- package/package.json +1 -1
package/dist/PerpsController.mjs
CHANGED
|
@@ -9,7 +9,7 @@ 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_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,
|
|
12
|
+
var _PerpsController_instances, _a, _PerpsController_initializationPromise, _PerpsController_isReinitializing, _PerpsController_reinitializationOperationPromise, _PerpsController_disconnectOperationPromise, _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_publishChaseOrderMaxDistanceReached, _PerpsController_logError, _PerpsController_debugLog, _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_initWithoutDisconnectWait, _PerpsController_beginReinitialization, _PerpsController_performInitialization, _PerpsController_createProviders, _PerpsController_assignActiveProvider, _PerpsController_getErrorContext, _PerpsController_getControllerState, _PerpsController_buildMarketAllowedFilter, _PerpsController_compilePatternsSafely, _PerpsController_createServiceContext, _PerpsController_ensureTradingServiceDeps, _PerpsController_getActiveProviderWhenReady, _PerpsController_getUnavailableOrderCapabilities, _PerpsController_getDirectProviderId, _PerpsController_hasConflictingProviderRoute, _PerpsController_resolveRoutedOrderProvider, _PerpsController_buildGlobalSnapshotContext, _PerpsController_getStaticSnapshotDexes, _PerpsController_preloadWatchedPaths, _PerpsController_preloadTimer, _PerpsController_preloadStartRequested, _PerpsController_isPreloading, _PerpsController_marketPreloadQueued, _PerpsController_isPreloadingUserData, _PerpsController_userPreloadQueued, _PerpsController_lifecycleGeneration, _PerpsController_userSnapshotRequests, _PerpsController_preloadStateUnsubscribe, _PerpsController_accountChangeUnsubscribe, _PerpsController_previousIsTestnet, _PerpsController_previousHip3ConfigVersion, _PerpsController_preloadRefreshMs, _PerpsController_preloadGuardMs, _PerpsController_hydrateCacheFromDiskSync, _PerpsController_persistUserCacheToDisk, _PerpsController_performMarketDataPreload, _PerpsController_performUserDataPreload, _PerpsController_performDisconnect, _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";
|
|
@@ -36,6 +36,7 @@ import { getSelectedEvmAccountFromMessenger } from "./utils/accountUtils.mjs";
|
|
|
36
36
|
import { ensureError } from "./utils/errorUtils.mjs";
|
|
37
37
|
import { parseAssetName } from "./utils/hyperLiquidAdapter.mjs";
|
|
38
38
|
import { clonePerpsMarketData, compileMarketPattern, shouldIncludeMarket } from "./utils/marketUtils.mjs";
|
|
39
|
+
import { isStrategyOrderType } from "./utils/orderTypes.mjs";
|
|
39
40
|
import { hydrateFromDiskSync, persistMarketEntriesToDisk, persistUserEntriesToDisk } from "./utils/perpsDiskPersistence.mjs";
|
|
40
41
|
import { wait } from "./utils/wait.mjs";
|
|
41
42
|
function cloneUserDataSnapshot(snapshot) {
|
|
@@ -453,6 +454,7 @@ const MESSENGER_EXPOSED_METHODS = [
|
|
|
453
454
|
'getCachedMarketDataForActiveProvider',
|
|
454
455
|
'getCachedUserDataForActiveProvider',
|
|
455
456
|
'getChaseOrders',
|
|
457
|
+
'getTwapOrders',
|
|
456
458
|
'getUserDataSnapshot',
|
|
457
459
|
'getCurrentNetwork',
|
|
458
460
|
'getFunding',
|
|
@@ -465,6 +467,7 @@ const MESSENGER_EXPOSED_METHODS = [
|
|
|
465
467
|
'getOpenOrders',
|
|
466
468
|
'getOrderBookGrouping',
|
|
467
469
|
'getOrderBookPreferences',
|
|
470
|
+
'getOrderCapabilities',
|
|
468
471
|
'getOrderFills',
|
|
469
472
|
'getOrders',
|
|
470
473
|
'getPendingTradeConfiguration',
|
|
@@ -551,6 +554,8 @@ export class PerpsController extends BaseController {
|
|
|
551
554
|
this.isInitialized = false;
|
|
552
555
|
_PerpsController_initializationPromise.set(this, null);
|
|
553
556
|
_PerpsController_isReinitializing.set(this, false);
|
|
557
|
+
_PerpsController_reinitializationOperationPromise.set(this, null);
|
|
558
|
+
_PerpsController_disconnectOperationPromise.set(this, null);
|
|
554
559
|
/** Tracks the async MYX dynamic import so performInitialization can await it. */
|
|
555
560
|
_PerpsController_myxRegistrationPromise.set(this, null);
|
|
556
561
|
this.blockedRegionList = {
|
|
@@ -622,11 +627,16 @@ export class PerpsController extends BaseController {
|
|
|
622
627
|
_PerpsController_depositService.set(this, void 0);
|
|
623
628
|
_PerpsController_featureFlagConfigurationService.set(this, void 0);
|
|
624
629
|
_PerpsController_rewardsIntegrationService.set(this, void 0);
|
|
630
|
+
_PerpsController_publishChaseOrderMaxDistanceReached.set(this, (event) => {
|
|
631
|
+
this.messenger.publish('PerpsController:chaseOrderMaxDistanceReached', event);
|
|
632
|
+
});
|
|
625
633
|
_PerpsController_preloadTimer.set(this, null);
|
|
634
|
+
_PerpsController_preloadStartRequested.set(this, false);
|
|
626
635
|
_PerpsController_isPreloading.set(this, false);
|
|
627
636
|
_PerpsController_marketPreloadQueued.set(this, false);
|
|
628
637
|
_PerpsController_isPreloadingUserData.set(this, false);
|
|
629
638
|
_PerpsController_userPreloadQueued.set(this, false);
|
|
639
|
+
_PerpsController_lifecycleGeneration.set(this, 0);
|
|
630
640
|
_PerpsController_userSnapshotRequests.set(this, new Map());
|
|
631
641
|
_PerpsController_preloadStateUnsubscribe.set(this, null);
|
|
632
642
|
_PerpsController_accountChangeUnsubscribe.set(this, null);
|
|
@@ -850,6 +860,7 @@ export class PerpsController extends BaseController {
|
|
|
850
860
|
}
|
|
851
861
|
const { address } = evmAccount;
|
|
852
862
|
const { isTestnet, hip3ConfigVersion } = this.state;
|
|
863
|
+
const lifecycleGeneration = __classPrivateFieldGet(this, _PerpsController_lifecycleGeneration, "f");
|
|
853
864
|
const network = isTestnet ? 'testnet' : 'mainnet';
|
|
854
865
|
const expectedDexes = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getStaticSnapshotDexes).call(this);
|
|
855
866
|
if (!expectedDexes) {
|
|
@@ -863,7 +874,8 @@ export class PerpsController extends BaseController {
|
|
|
863
874
|
catch {
|
|
864
875
|
return false;
|
|
865
876
|
}
|
|
866
|
-
return (this
|
|
877
|
+
return (__classPrivateFieldGet(this, _PerpsController_lifecycleGeneration, "f") === lifecycleGeneration &&
|
|
878
|
+
this.state.activeProvider === 'hyperliquid' &&
|
|
867
879
|
(!capturedActiveProvider ||
|
|
868
880
|
this.activeProviderInstance === capturedActiveProvider) &&
|
|
869
881
|
this.state.isTestnet === isTestnet &&
|
|
@@ -979,18 +991,19 @@ export class PerpsController extends BaseController {
|
|
|
979
991
|
* @returns A promise that resolves when the operation completes.
|
|
980
992
|
*/
|
|
981
993
|
async init() {
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
994
|
+
while (true) {
|
|
995
|
+
const pendingDisconnect = __classPrivateFieldGet(this, _PerpsController_disconnectOperationPromise, "f");
|
|
996
|
+
if (pendingDisconnect) {
|
|
997
|
+
await pendingDisconnect;
|
|
998
|
+
continue;
|
|
999
|
+
}
|
|
1000
|
+
const pendingReinitialization = __classPrivateFieldGet(this, _PerpsController_reinitializationOperationPromise, "f");
|
|
1001
|
+
if (pendingReinitialization) {
|
|
1002
|
+
await pendingReinitialization;
|
|
1003
|
+
continue;
|
|
1004
|
+
}
|
|
1005
|
+
return __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_initWithoutDisconnectWait).call(this);
|
|
991
1006
|
}
|
|
992
|
-
__classPrivateFieldSet(this, _PerpsController_initializationPromise, __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_performInitialization).call(this), "f");
|
|
993
|
-
return __classPrivateFieldGet(this, _PerpsController_initializationPromise, "f");
|
|
994
1007
|
}
|
|
995
1008
|
/**
|
|
996
1009
|
* Registers the MYX provider after dynamic import resolves.
|
|
@@ -1092,6 +1105,50 @@ export class PerpsController extends BaseController {
|
|
|
1092
1105
|
// Return the active provider instance or null if not found
|
|
1093
1106
|
return this.activeProviderInstance ?? null;
|
|
1094
1107
|
}
|
|
1108
|
+
/**
|
|
1109
|
+
* Get strategy capabilities through the active provider route used by order
|
|
1110
|
+
* placement. The query waits for in-flight initialization and reports an
|
|
1111
|
+
* explicit unavailable status when no provider route can answer reliably.
|
|
1112
|
+
*
|
|
1113
|
+
* @param params - Market and optional provider route.
|
|
1114
|
+
* @returns Provider-owned order capabilities.
|
|
1115
|
+
*/
|
|
1116
|
+
async getOrderCapabilities(params) {
|
|
1117
|
+
let activeProvider;
|
|
1118
|
+
try {
|
|
1119
|
+
activeProvider = await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getActiveProviderWhenReady).call(this);
|
|
1120
|
+
}
|
|
1121
|
+
catch (error) {
|
|
1122
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: Order capabilities unavailable', {
|
|
1123
|
+
error: ensureError(error, 'PerpsController.getOrderCapabilities')
|
|
1124
|
+
.message,
|
|
1125
|
+
});
|
|
1126
|
+
return __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getUnavailableOrderCapabilities).call(this, 'provider_unavailable', params.providerId);
|
|
1127
|
+
}
|
|
1128
|
+
const resolvedProviderId = params.providerId ?? __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getDirectProviderId).call(this, activeProvider);
|
|
1129
|
+
if (__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_hasConflictingProviderRoute).call(this, params.providerId, activeProvider)) {
|
|
1130
|
+
return __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getUnavailableOrderCapabilities).call(this, 'provider_not_routable', resolvedProviderId);
|
|
1131
|
+
}
|
|
1132
|
+
if (!activeProvider.getOrderCapabilities) {
|
|
1133
|
+
return __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getUnavailableOrderCapabilities).call(this, 'not_implemented', resolvedProviderId);
|
|
1134
|
+
}
|
|
1135
|
+
try {
|
|
1136
|
+
const capabilities = await activeProvider.getOrderCapabilities(params);
|
|
1137
|
+
if (capabilities.status === 'unavailable' &&
|
|
1138
|
+
capabilities.providerId === undefined &&
|
|
1139
|
+
resolvedProviderId !== undefined) {
|
|
1140
|
+
return { ...capabilities, providerId: resolvedProviderId };
|
|
1141
|
+
}
|
|
1142
|
+
return capabilities;
|
|
1143
|
+
}
|
|
1144
|
+
catch (error) {
|
|
1145
|
+
const safeError = ensureError(error, 'PerpsController.getOrderCapabilities');
|
|
1146
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: Order capabilities unavailable', {
|
|
1147
|
+
error: safeError.message,
|
|
1148
|
+
});
|
|
1149
|
+
return __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getUnavailableOrderCapabilities).call(this, 'provider_unavailable', resolvedProviderId);
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1095
1152
|
/**
|
|
1096
1153
|
* Place a new order
|
|
1097
1154
|
* Thin delegation to TradingService
|
|
@@ -1100,7 +1157,10 @@ export class PerpsController extends BaseController {
|
|
|
1100
1157
|
* @returns The order result with order ID and status.
|
|
1101
1158
|
*/
|
|
1102
1159
|
async placeOrder(params) {
|
|
1103
|
-
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m",
|
|
1160
|
+
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_resolveRoutedOrderProvider).call(this, {
|
|
1161
|
+
orderType: params.orderType,
|
|
1162
|
+
providerId: params.providerId,
|
|
1163
|
+
});
|
|
1104
1164
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_ensureTradingServiceDeps).call(this);
|
|
1105
1165
|
const result = await __classPrivateFieldGet(this, _PerpsController_tradingService, "f").placeOrder({
|
|
1106
1166
|
provider,
|
|
@@ -1123,7 +1183,16 @@ export class PerpsController extends BaseController {
|
|
|
1123
1183
|
* @returns The updated order result with order ID and status.
|
|
1124
1184
|
*/
|
|
1125
1185
|
async editOrder(params) {
|
|
1126
|
-
|
|
1186
|
+
if (isStrategyOrderType(params.newOrder.orderType)) {
|
|
1187
|
+
return {
|
|
1188
|
+
success: false,
|
|
1189
|
+
error: PERPS_ERROR_CODES.ORDER_EDIT_STRATEGY_UNSUPPORTED,
|
|
1190
|
+
};
|
|
1191
|
+
}
|
|
1192
|
+
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_resolveRoutedOrderProvider).call(this, {
|
|
1193
|
+
orderType: params.newOrder.orderType,
|
|
1194
|
+
providerId: params.newOrder.providerId,
|
|
1195
|
+
});
|
|
1127
1196
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_ensureTradingServiceDeps).call(this);
|
|
1128
1197
|
return __classPrivateFieldGet(this, _PerpsController_tradingService, "f").editOrder({
|
|
1129
1198
|
provider,
|
|
@@ -1138,13 +1207,26 @@ export class PerpsController extends BaseController {
|
|
|
1138
1207
|
* @returns The cancellation result with status.
|
|
1139
1208
|
*/
|
|
1140
1209
|
async cancelOrder(params) {
|
|
1141
|
-
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m",
|
|
1210
|
+
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_resolveRoutedOrderProvider).call(this, {
|
|
1211
|
+
orderType: params.orderType,
|
|
1212
|
+
providerId: params.providerId,
|
|
1213
|
+
});
|
|
1142
1214
|
return __classPrivateFieldGet(this, _PerpsController_tradingService, "f").cancelOrder({
|
|
1143
1215
|
provider,
|
|
1144
1216
|
params,
|
|
1145
1217
|
context: __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_createServiceContext).call(this, 'cancelOrder'),
|
|
1146
1218
|
});
|
|
1147
1219
|
}
|
|
1220
|
+
/**
|
|
1221
|
+
* Read venue-backed TWAP lifecycle records through the active provider.
|
|
1222
|
+
* Providers without native TWAP history return an empty list.
|
|
1223
|
+
*
|
|
1224
|
+
* @returns Current and terminal TWAP schedules with slice fills.
|
|
1225
|
+
*/
|
|
1226
|
+
async getTwapOrders() {
|
|
1227
|
+
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getActiveProviderWhenReady).call(this);
|
|
1228
|
+
return provider.getTwapOrders ? await provider.getTwapOrders() : [];
|
|
1229
|
+
}
|
|
1148
1230
|
/**
|
|
1149
1231
|
* Read the active provider's retained Chase lifecycle snapshots.
|
|
1150
1232
|
* Providers without an emulated Chase implementation return an empty list.
|
|
@@ -1195,7 +1277,10 @@ export class PerpsController extends BaseController {
|
|
|
1195
1277
|
* @returns The order result from the close position request.
|
|
1196
1278
|
*/
|
|
1197
1279
|
async closePosition(params) {
|
|
1198
|
-
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m",
|
|
1280
|
+
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_resolveRoutedOrderProvider).call(this, {
|
|
1281
|
+
orderType: params.orderType,
|
|
1282
|
+
providerId: params.providerId,
|
|
1283
|
+
});
|
|
1199
1284
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_ensureTradingServiceDeps).call(this);
|
|
1200
1285
|
return __classPrivateFieldGet(this, _PerpsController_tradingService, "f").closePosition({
|
|
1201
1286
|
provider,
|
|
@@ -1231,7 +1316,10 @@ export class PerpsController extends BaseController {
|
|
|
1231
1316
|
* @returns The order result from the TP/SL update.
|
|
1232
1317
|
*/
|
|
1233
1318
|
async updatePositionTPSL(params) {
|
|
1234
|
-
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m",
|
|
1319
|
+
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_resolveRoutedOrderProvider).call(this, {
|
|
1320
|
+
orderType: undefined,
|
|
1321
|
+
providerId: params.providerId,
|
|
1322
|
+
});
|
|
1235
1323
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_ensureTradingServiceDeps).call(this);
|
|
1236
1324
|
return __classPrivateFieldGet(this, _PerpsController_tradingService, "f").updatePositionTPSL({
|
|
1237
1325
|
provider,
|
|
@@ -1917,6 +2005,11 @@ export class PerpsController extends BaseController {
|
|
|
1917
2005
|
* Watches for isTestnet and hip3ConfigVersion changes to re-preload.
|
|
1918
2006
|
*/
|
|
1919
2007
|
startMarketDataPreload() {
|
|
2008
|
+
__classPrivateFieldSet(this, _PerpsController_preloadStartRequested, true, "f");
|
|
2009
|
+
if (__classPrivateFieldGet(this, _PerpsController_disconnectOperationPromise, "f")) {
|
|
2010
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: Disconnect in progress, deferring market data preload');
|
|
2011
|
+
return;
|
|
2012
|
+
}
|
|
1920
2013
|
if (__classPrivateFieldGet(this, _PerpsController_preloadTimer, "f")) {
|
|
1921
2014
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: Preload already started, skipping');
|
|
1922
2015
|
return;
|
|
@@ -2005,6 +2098,7 @@ export class PerpsController extends BaseController {
|
|
|
2005
2098
|
*/
|
|
2006
2099
|
stopMarketDataPreload() {
|
|
2007
2100
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: Stopping market data preload');
|
|
2101
|
+
__classPrivateFieldSet(this, _PerpsController_preloadStartRequested, false, "f");
|
|
2008
2102
|
if (__classPrivateFieldGet(this, _PerpsController_preloadTimer, "f")) {
|
|
2009
2103
|
clearInterval(__classPrivateFieldGet(this, _PerpsController_preloadTimer, "f"));
|
|
2010
2104
|
__classPrivateFieldSet(this, _PerpsController_preloadTimer, null, "f");
|
|
@@ -2113,7 +2207,10 @@ export class PerpsController extends BaseController {
|
|
|
2113
2207
|
* @returns True if the condition is met.
|
|
2114
2208
|
*/
|
|
2115
2209
|
async validateOrder(params) {
|
|
2116
|
-
const provider = this.
|
|
2210
|
+
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_resolveRoutedOrderProvider).call(this, {
|
|
2211
|
+
orderType: params.orderType,
|
|
2212
|
+
providerId: params.providerId,
|
|
2213
|
+
});
|
|
2117
2214
|
const context = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_createServiceContext).call(this, 'validateOrder');
|
|
2118
2215
|
return __classPrivateFieldGet(this, _PerpsController_marketDataService, "f").validateOrder({ provider, params, context });
|
|
2119
2216
|
}
|
|
@@ -2124,7 +2221,10 @@ export class PerpsController extends BaseController {
|
|
|
2124
2221
|
* @returns A promise that resolves to the result.
|
|
2125
2222
|
*/
|
|
2126
2223
|
async validateClosePosition(params) {
|
|
2127
|
-
const provider = this.
|
|
2224
|
+
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_resolveRoutedOrderProvider).call(this, {
|
|
2225
|
+
orderType: params.orderType,
|
|
2226
|
+
providerId: params.providerId,
|
|
2227
|
+
});
|
|
2128
2228
|
const context = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_createServiceContext).call(this, 'validateClosePosition');
|
|
2129
2229
|
return __classPrivateFieldGet(this, _PerpsController_marketDataService, "f").validateClosePosition({
|
|
2130
2230
|
provider,
|
|
@@ -2217,6 +2317,9 @@ export class PerpsController extends BaseController {
|
|
|
2217
2317
|
* @returns The toggle result with success status and current network mode.
|
|
2218
2318
|
*/
|
|
2219
2319
|
async toggleTestnet() {
|
|
2320
|
+
while (__classPrivateFieldGet(this, _PerpsController_disconnectOperationPromise, "f")) {
|
|
2321
|
+
await __classPrivateFieldGet(this, _PerpsController_disconnectOperationPromise, "f");
|
|
2322
|
+
}
|
|
2220
2323
|
// Prevent concurrent reinitializations
|
|
2221
2324
|
if (this.isCurrentlyReinitializing()) {
|
|
2222
2325
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: Already reinitializing, skipping toggle', {
|
|
@@ -2228,10 +2331,13 @@ export class PerpsController extends BaseController {
|
|
|
2228
2331
|
error: PERPS_ERROR_CODES.CLIENT_REINITIALIZING,
|
|
2229
2332
|
};
|
|
2230
2333
|
}
|
|
2231
|
-
|
|
2232
|
-
// Store previous isTestnet for rollback on failure
|
|
2334
|
+
const completeReinitialization = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_beginReinitialization).call(this);
|
|
2233
2335
|
const previousIsTestnet = this.state.isTestnet;
|
|
2234
2336
|
try {
|
|
2337
|
+
const pendingInitialization = __classPrivateFieldGet(this, _PerpsController_initializationPromise, "f");
|
|
2338
|
+
if (pendingInitialization) {
|
|
2339
|
+
await pendingInitialization;
|
|
2340
|
+
}
|
|
2235
2341
|
await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_cleanupStandaloneProvider).call(this);
|
|
2236
2342
|
const previousNetwork = previousIsTestnet ? 'testnet' : 'mainnet';
|
|
2237
2343
|
this.update((state) => {
|
|
@@ -2246,7 +2352,7 @@ export class PerpsController extends BaseController {
|
|
|
2246
2352
|
// Reset initialization state and reinitialize provider with new testnet setting
|
|
2247
2353
|
this.isInitialized = false;
|
|
2248
2354
|
__classPrivateFieldSet(this, _PerpsController_initializationPromise, null, "f");
|
|
2249
|
-
await this.
|
|
2355
|
+
await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_initWithoutDisconnectWait).call(this);
|
|
2250
2356
|
// Check if initialization actually succeeded — performInitialization()
|
|
2251
2357
|
// does not throw on failure, it sets state to Failed and resolves.
|
|
2252
2358
|
if (this.state.initializationState === InitializationState.Failed) {
|
|
@@ -2272,7 +2378,7 @@ export class PerpsController extends BaseController {
|
|
|
2272
2378
|
};
|
|
2273
2379
|
}
|
|
2274
2380
|
finally {
|
|
2275
|
-
|
|
2381
|
+
completeReinitialization();
|
|
2276
2382
|
// Re-trigger preload now that reinit is complete and the
|
|
2277
2383
|
// activeProviderInstance points to the correct network.
|
|
2278
2384
|
// The state-change listener may have already fired during reinit
|
|
@@ -2296,19 +2402,8 @@ export class PerpsController extends BaseController {
|
|
|
2296
2402
|
* @returns The switch result with success status and active provider.
|
|
2297
2403
|
*/
|
|
2298
2404
|
async switchProvider(providerId) {
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
return { success: true, providerId };
|
|
2302
|
-
}
|
|
2303
|
-
// Validate provider is available
|
|
2304
|
-
// 'aggregated' is always valid, individual providers must exist in the map
|
|
2305
|
-
const isValidProvider = providerId === 'aggregated' || this.providers.has(providerId);
|
|
2306
|
-
if (!isValidProvider) {
|
|
2307
|
-
return {
|
|
2308
|
-
success: false,
|
|
2309
|
-
providerId: this.state.activeProvider,
|
|
2310
|
-
error: `Provider ${providerId} not available`,
|
|
2311
|
-
};
|
|
2405
|
+
while (__classPrivateFieldGet(this, _PerpsController_disconnectOperationPromise, "f")) {
|
|
2406
|
+
await __classPrivateFieldGet(this, _PerpsController_disconnectOperationPromise, "f");
|
|
2312
2407
|
}
|
|
2313
2408
|
// Prevent concurrent switches
|
|
2314
2409
|
if (this.isCurrentlyReinitializing()) {
|
|
@@ -2318,10 +2413,44 @@ export class PerpsController extends BaseController {
|
|
|
2318
2413
|
error: PERPS_ERROR_CODES.CLIENT_REINITIALIZING,
|
|
2319
2414
|
};
|
|
2320
2415
|
}
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
const previousProvider = this.state.activeProvider;
|
|
2416
|
+
const completeReinitialization = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_beginReinitialization).call(this);
|
|
2417
|
+
let previousProvider = this.state.activeProvider;
|
|
2324
2418
|
try {
|
|
2419
|
+
const pendingInitialization = __classPrivateFieldGet(this, _PerpsController_initializationPromise, "f");
|
|
2420
|
+
if (pendingInitialization) {
|
|
2421
|
+
await pendingInitialization;
|
|
2422
|
+
}
|
|
2423
|
+
// A completed disconnect leaves no initialization promise to await. Rebuild
|
|
2424
|
+
// the provider registry before same-provider detection or route validation
|
|
2425
|
+
// so a successful switch always leaves a usable active provider.
|
|
2426
|
+
const needsInitialization = !this.isInitialized ||
|
|
2427
|
+
this.state.initializationState !== InitializationState.Initialized;
|
|
2428
|
+
if (needsInitialization) {
|
|
2429
|
+
await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_initWithoutDisconnectWait).call(this);
|
|
2430
|
+
const initializationFailed = !this.isInitialized ||
|
|
2431
|
+
this.state.initializationState !== InitializationState.Initialized;
|
|
2432
|
+
if (initializationFailed) {
|
|
2433
|
+
throw new Error(this.state.initializationError ?? 'Provider initialization failed');
|
|
2434
|
+
}
|
|
2435
|
+
}
|
|
2436
|
+
// Initialization may select a fallback provider. Read the effective
|
|
2437
|
+
// provider only after it settles so no-op detection and rollback both
|
|
2438
|
+
// use the state this switch is actually replacing.
|
|
2439
|
+
previousProvider = this.state.activeProvider;
|
|
2440
|
+
if (previousProvider === providerId) {
|
|
2441
|
+
return { success: true, providerId };
|
|
2442
|
+
}
|
|
2443
|
+
// Validate provider only after a pending initialization has rebuilt the
|
|
2444
|
+
// registry. Otherwise a switch queued behind disconnect can observe the
|
|
2445
|
+
// intentionally empty teardown state.
|
|
2446
|
+
const isValidProvider = providerId === 'aggregated' || this.providers.has(providerId);
|
|
2447
|
+
if (!isValidProvider) {
|
|
2448
|
+
return {
|
|
2449
|
+
success: false,
|
|
2450
|
+
providerId: this.state.activeProvider,
|
|
2451
|
+
error: `Provider ${providerId} not available`,
|
|
2452
|
+
};
|
|
2453
|
+
}
|
|
2325
2454
|
await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_cleanupStandaloneProvider).call(this);
|
|
2326
2455
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: Provider switch initiated', {
|
|
2327
2456
|
from: previousProvider,
|
|
@@ -2329,8 +2458,7 @@ export class PerpsController extends BaseController {
|
|
|
2329
2458
|
timestamp: new Date().toISOString(),
|
|
2330
2459
|
});
|
|
2331
2460
|
// Provider disconnect is handled by performInitialization() during
|
|
2332
|
-
// reinitialization.
|
|
2333
|
-
// when isReinitializing is true to prevent double-disconnect.
|
|
2461
|
+
// reinitialization.
|
|
2334
2462
|
// Update state with new provider (market data cache preserved per-provider)
|
|
2335
2463
|
this.update((state) => {
|
|
2336
2464
|
state.activeProvider = providerId;
|
|
@@ -2340,7 +2468,7 @@ export class PerpsController extends BaseController {
|
|
|
2340
2468
|
// Reset initialization state and reinitialize
|
|
2341
2469
|
this.isInitialized = false;
|
|
2342
2470
|
__classPrivateFieldSet(this, _PerpsController_initializationPromise, null, "f");
|
|
2343
|
-
await this.
|
|
2471
|
+
await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_initWithoutDisconnectWait).call(this);
|
|
2344
2472
|
// Check if initialization actually succeeded — performInitialization()
|
|
2345
2473
|
// does not throw on failure, it sets state to Failed and resolves.
|
|
2346
2474
|
if (this.state.initializationState === InitializationState.Failed) {
|
|
@@ -2363,7 +2491,7 @@ export class PerpsController extends BaseController {
|
|
|
2363
2491
|
try {
|
|
2364
2492
|
this.isInitialized = false;
|
|
2365
2493
|
__classPrivateFieldSet(this, _PerpsController_initializationPromise, null, "f");
|
|
2366
|
-
await this.
|
|
2494
|
+
await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_initWithoutDisconnectWait).call(this);
|
|
2367
2495
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: Rollback to previous provider succeeded', {
|
|
2368
2496
|
previousProvider,
|
|
2369
2497
|
timestamp: new Date().toISOString(),
|
|
@@ -2387,7 +2515,7 @@ export class PerpsController extends BaseController {
|
|
|
2387
2515
|
};
|
|
2388
2516
|
}
|
|
2389
2517
|
finally {
|
|
2390
|
-
|
|
2518
|
+
completeReinitialization();
|
|
2391
2519
|
// Re-trigger preload now that reinit is complete.
|
|
2392
2520
|
if (__classPrivateFieldGet(this, _PerpsController_preloadTimer, "f")) {
|
|
2393
2521
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_performMarketDataPreload).call(this).catch(() => {
|
|
@@ -2723,14 +2851,18 @@ export class PerpsController extends BaseController {
|
|
|
2723
2851
|
}
|
|
2724
2852
|
}
|
|
2725
2853
|
/**
|
|
2726
|
-
* Calculate trading fees
|
|
2727
|
-
* Each provider
|
|
2854
|
+
* Calculate trading fees through the active provider route.
|
|
2855
|
+
* Each provider owns its fee policy. An explicit provider route overrides
|
|
2856
|
+
* the active/default provider used by placement.
|
|
2728
2857
|
*
|
|
2729
2858
|
* @param params - The operation parameters.
|
|
2730
2859
|
* @returns The fee calculation result for the trade.
|
|
2731
2860
|
*/
|
|
2732
2861
|
async calculateFees(params) {
|
|
2733
|
-
const provider = this.
|
|
2862
|
+
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_resolveRoutedOrderProvider).call(this, {
|
|
2863
|
+
orderType: params.orderType,
|
|
2864
|
+
providerId: params.providerId,
|
|
2865
|
+
});
|
|
2734
2866
|
// Preview owns subscription hydration. The submit resolver remains a pure
|
|
2735
2867
|
// cache read and can therefore never start a benefits request while an
|
|
2736
2868
|
// order is being signed.
|
|
@@ -2771,46 +2903,33 @@ export class PerpsController extends BaseController {
|
|
|
2771
2903
|
* Call this when navigating away from Perps screens to prevent battery drain
|
|
2772
2904
|
*/
|
|
2773
2905
|
async disconnect() {
|
|
2774
|
-
__classPrivateFieldGet(this,
|
|
2775
|
-
|
|
2906
|
+
while (__classPrivateFieldGet(this, _PerpsController_disconnectOperationPromise, "f")) {
|
|
2907
|
+
// Each explicit disconnect claims a teardown after the operation already
|
|
2908
|
+
// in flight. This lets a later disconnect close providers created by an
|
|
2909
|
+
// init call that was queued behind the same earlier teardown.
|
|
2910
|
+
__classPrivateFieldSet(this, _PerpsController_preloadStartRequested, false, "f");
|
|
2911
|
+
await __classPrivateFieldGet(this, _PerpsController_disconnectOperationPromise, "f");
|
|
2912
|
+
}
|
|
2913
|
+
// A disconnect stops the current preload session. A later start call made
|
|
2914
|
+
// while teardown is in flight sets this back to true and is resumed below.
|
|
2915
|
+
__classPrivateFieldSet(this, _PerpsController_preloadStartRequested, false, "f");
|
|
2916
|
+
let resolveOperation = () => undefined;
|
|
2917
|
+
const operation = new Promise((resolve) => {
|
|
2918
|
+
resolveOperation = resolve;
|
|
2776
2919
|
});
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
clearInterval(__classPrivateFieldGet(this, _PerpsController_preloadTimer, "f"));
|
|
2781
|
-
__classPrivateFieldSet(this, _PerpsController_preloadTimer, null, "f");
|
|
2782
|
-
}
|
|
2783
|
-
if (__classPrivateFieldGet(this, _PerpsController_preloadStateUnsubscribe, "f")) {
|
|
2784
|
-
__classPrivateFieldGet(this, _PerpsController_preloadStateUnsubscribe, "f").call(this);
|
|
2785
|
-
__classPrivateFieldSet(this, _PerpsController_preloadStateUnsubscribe, null, "f");
|
|
2786
|
-
}
|
|
2787
|
-
if (__classPrivateFieldGet(this, _PerpsController_accountChangeUnsubscribe, "f")) {
|
|
2788
|
-
__classPrivateFieldGet(this, _PerpsController_accountChangeUnsubscribe, "f").call(this);
|
|
2789
|
-
__classPrivateFieldSet(this, _PerpsController_accountChangeUnsubscribe, null, "f");
|
|
2920
|
+
__classPrivateFieldSet(this, _PerpsController_disconnectOperationPromise, operation, "f");
|
|
2921
|
+
try {
|
|
2922
|
+
await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_performDisconnect).call(this);
|
|
2790
2923
|
}
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
try {
|
|
2796
|
-
const provider = this.getActiveProvider();
|
|
2797
|
-
await provider.disconnect();
|
|
2924
|
+
finally {
|
|
2925
|
+
resolveOperation();
|
|
2926
|
+
if (__classPrivateFieldGet(this, _PerpsController_disconnectOperationPromise, "f") === operation) {
|
|
2927
|
+
__classPrivateFieldSet(this, _PerpsController_disconnectOperationPromise, null, "f");
|
|
2798
2928
|
}
|
|
2799
|
-
|
|
2800
|
-
|
|
2929
|
+
if (__classPrivateFieldGet(this, _PerpsController_preloadStartRequested, "f")) {
|
|
2930
|
+
this.startMarketDataPreload();
|
|
2801
2931
|
}
|
|
2802
2932
|
}
|
|
2803
|
-
// Clear stale reference so standalone reads don't route through old provider
|
|
2804
|
-
this.activeProviderInstance = null;
|
|
2805
|
-
// Cleanup cached standalone provider (if any) — awaited to prevent races
|
|
2806
|
-
await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_cleanupStandaloneProvider).call(this);
|
|
2807
|
-
// Note: Feature-flag subscription is NOT cleaned up here.
|
|
2808
|
-
// It is a controller-lifetime concern (set once in the constructor),
|
|
2809
|
-
// not a session-lifetime concern. Unsubscribing here would break
|
|
2810
|
-
// geo-blocking / HIP-3 flag propagation after disconnect → reconnect.
|
|
2811
|
-
// Reset initialization state to ensure proper reconnection
|
|
2812
|
-
this.isInitialized = false;
|
|
2813
|
-
__classPrivateFieldSet(this, _PerpsController_initializationPromise, null, "f");
|
|
2814
2933
|
}
|
|
2815
2934
|
/**
|
|
2816
2935
|
* Eligibility (Geo-Blocking)
|
|
@@ -3558,7 +3677,7 @@ export class PerpsController extends BaseController {
|
|
|
3558
3677
|
return __classPrivateFieldGet(this, _PerpsController_isReinitializing, "f");
|
|
3559
3678
|
}
|
|
3560
3679
|
}
|
|
3561
|
-
_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() {
|
|
3680
|
+
_a = PerpsController, _PerpsController_initializationPromise = new WeakMap(), _PerpsController_isReinitializing = new WeakMap(), _PerpsController_reinitializationOperationPromise = new WeakMap(), _PerpsController_disconnectOperationPromise = 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_publishChaseOrderMaxDistanceReached = new WeakMap(), _PerpsController_preloadTimer = new WeakMap(), _PerpsController_preloadStartRequested = new WeakMap(), _PerpsController_isPreloading = new WeakMap(), _PerpsController_marketPreloadQueued = new WeakMap(), _PerpsController_isPreloadingUserData = new WeakMap(), _PerpsController_userPreloadQueued = new WeakMap(), _PerpsController_lifecycleGeneration = 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() {
|
|
3562
3681
|
const myx = __classPrivateFieldGet(this, _PerpsController_options, "f").clientConfig?.providerCredentials?.myx;
|
|
3563
3682
|
// Local env-var override (MM_PERPS_MYX_PROVIDER_ENABLED) always wins —
|
|
3564
3683
|
// matches the UI selector (resolvePerpsMyxProviderEnabled) so controller
|
|
@@ -3591,16 +3710,6 @@ _a = PerpsController, _PerpsController_initializationPromise = new WeakMap(), _P
|
|
|
3591
3710
|
__classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure.logger.error(error, options);
|
|
3592
3711
|
}, _PerpsController_debugLog = function _PerpsController_debugLog(...args) {
|
|
3593
3712
|
__classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure.debugLogger.log(...args);
|
|
3594
|
-
}, _PerpsController_awaitInitializationIfInProgress =
|
|
3595
|
-
/**
|
|
3596
|
-
* Awaits the in-flight initialization promise if init is currently running.
|
|
3597
|
-
* Called internally by #getActiveProviderWhenReady().
|
|
3598
|
-
*/
|
|
3599
|
-
async function _PerpsController_awaitInitializationIfInProgress() {
|
|
3600
|
-
if (this.state.initializationState === InitializationState.Initializing &&
|
|
3601
|
-
__classPrivateFieldGet(this, _PerpsController_initializationPromise, "f")) {
|
|
3602
|
-
await __classPrivateFieldGet(this, _PerpsController_initializationPromise, "f");
|
|
3603
|
-
}
|
|
3604
3713
|
}, _PerpsController_getAggregatedCacheProviderIds = function _PerpsController_getAggregatedCacheProviderIds(cacheKeys) {
|
|
3605
3714
|
const providerIds = new Set();
|
|
3606
3715
|
const currentNetwork = this.state.isTestnet ? 'testnet' : 'mainnet';
|
|
@@ -3745,6 +3854,7 @@ async function _PerpsController_awaitInitializationIfInProgress() {
|
|
|
3745
3854
|
?.subscriptionBuilderAddressTestnet,
|
|
3746
3855
|
subscriptionBuilderAddressMainnet: __classPrivateFieldGet(this, _PerpsController_options, "f").clientConfig?.providerCredentials?.hyperliquid
|
|
3747
3856
|
?.subscriptionBuilderAddressMainnet,
|
|
3857
|
+
onChaseOrderMaxDistanceReached: __classPrivateFieldGet(this, _PerpsController_publishChaseOrderMaxDistanceReached, "f"),
|
|
3748
3858
|
}), "f");
|
|
3749
3859
|
__classPrivateFieldSet(this, _PerpsController_standaloneProviderIsTestnet, currentIsTestnet, "f");
|
|
3750
3860
|
__classPrivateFieldSet(this, _PerpsController_standaloneProviderHip3Version, currentHip3Version, "f");
|
|
@@ -3889,6 +3999,40 @@ async function _PerpsController_withStreamPause(operation, channels) {
|
|
|
3889
3999
|
}
|
|
3890
4000
|
}
|
|
3891
4001
|
}
|
|
4002
|
+
}, _PerpsController_initWithoutDisconnectWait =
|
|
4003
|
+
/**
|
|
4004
|
+
* Initialize without waiting for disconnect. Reinitialization operations use
|
|
4005
|
+
* this after they have claimed the controller lifecycle.
|
|
4006
|
+
*
|
|
4007
|
+
* @returns A promise that resolves when initialization finishes.
|
|
4008
|
+
*/
|
|
4009
|
+
async function _PerpsController_initWithoutDisconnectWait() {
|
|
4010
|
+
if (!__classPrivateFieldGet(this, _PerpsController_handlersRegistered, "f")) {
|
|
4011
|
+
this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
|
|
4012
|
+
__classPrivateFieldSet(this, _PerpsController_handlersRegistered, true, "f");
|
|
4013
|
+
}
|
|
4014
|
+
if (this.isInitialized) {
|
|
4015
|
+
return undefined;
|
|
4016
|
+
}
|
|
4017
|
+
if (__classPrivateFieldGet(this, _PerpsController_initializationPromise, "f")) {
|
|
4018
|
+
return __classPrivateFieldGet(this, _PerpsController_initializationPromise, "f");
|
|
4019
|
+
}
|
|
4020
|
+
__classPrivateFieldSet(this, _PerpsController_initializationPromise, __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_performInitialization).call(this), "f");
|
|
4021
|
+
return __classPrivateFieldGet(this, _PerpsController_initializationPromise, "f");
|
|
4022
|
+
}, _PerpsController_beginReinitialization = function _PerpsController_beginReinitialization() {
|
|
4023
|
+
__classPrivateFieldSet(this, _PerpsController_isReinitializing, true, "f");
|
|
4024
|
+
let resolveOperation = () => undefined;
|
|
4025
|
+
const operation = new Promise((resolve) => {
|
|
4026
|
+
resolveOperation = resolve;
|
|
4027
|
+
});
|
|
4028
|
+
__classPrivateFieldSet(this, _PerpsController_reinitializationOperationPromise, operation, "f");
|
|
4029
|
+
return () => {
|
|
4030
|
+
__classPrivateFieldSet(this, _PerpsController_isReinitializing, false, "f");
|
|
4031
|
+
resolveOperation();
|
|
4032
|
+
if (__classPrivateFieldGet(this, _PerpsController_reinitializationOperationPromise, "f") === operation) {
|
|
4033
|
+
__classPrivateFieldSet(this, _PerpsController_reinitializationOperationPromise, null, "f");
|
|
4034
|
+
}
|
|
4035
|
+
};
|
|
3892
4036
|
}, _PerpsController_performInitialization =
|
|
3893
4037
|
/**
|
|
3894
4038
|
* Actual initialization implementation with retry logic
|
|
@@ -4009,6 +4153,7 @@ async function _PerpsController_performInitialization() {
|
|
|
4009
4153
|
?.subscriptionBuilderAddressTestnet,
|
|
4010
4154
|
subscriptionBuilderAddressMainnet: __classPrivateFieldGet(this, _PerpsController_options, "f").clientConfig?.providerCredentials?.hyperliquid
|
|
4011
4155
|
?.subscriptionBuilderAddressMainnet,
|
|
4156
|
+
onChaseOrderMaxDistanceReached: __classPrivateFieldGet(this, _PerpsController_publishChaseOrderMaxDistanceReached, "f"),
|
|
4012
4157
|
});
|
|
4013
4158
|
this.providers.set('hyperliquid', hyperLiquidProvider);
|
|
4014
4159
|
// Register MYX provider if enabled via feature flag.
|
|
@@ -4138,8 +4283,56 @@ async function _PerpsController_performInitialization() {
|
|
|
4138
4283
|
* @returns The active provider once initialization completes.
|
|
4139
4284
|
*/
|
|
4140
4285
|
async function _PerpsController_getActiveProviderWhenReady() {
|
|
4141
|
-
|
|
4142
|
-
|
|
4286
|
+
while (true) {
|
|
4287
|
+
const pendingDisconnect = __classPrivateFieldGet(this, _PerpsController_disconnectOperationPromise, "f");
|
|
4288
|
+
if (pendingDisconnect) {
|
|
4289
|
+
await pendingDisconnect;
|
|
4290
|
+
continue;
|
|
4291
|
+
}
|
|
4292
|
+
const pendingReinitialization = __classPrivateFieldGet(this, _PerpsController_reinitializationOperationPromise, "f");
|
|
4293
|
+
if (pendingReinitialization) {
|
|
4294
|
+
await pendingReinitialization;
|
|
4295
|
+
continue;
|
|
4296
|
+
}
|
|
4297
|
+
const pendingInitialization = __classPrivateFieldGet(this, _PerpsController_initializationPromise, "f");
|
|
4298
|
+
if (this.state.initializationState === InitializationState.Initializing &&
|
|
4299
|
+
pendingInitialization) {
|
|
4300
|
+
await pendingInitialization;
|
|
4301
|
+
continue;
|
|
4302
|
+
}
|
|
4303
|
+
return this.getActiveProvider();
|
|
4304
|
+
}
|
|
4305
|
+
}, _PerpsController_getUnavailableOrderCapabilities = function _PerpsController_getUnavailableOrderCapabilities(reason, providerId) {
|
|
4306
|
+
return providerId
|
|
4307
|
+
? { status: 'unavailable', providerId, reason }
|
|
4308
|
+
: { status: 'unavailable', reason };
|
|
4309
|
+
}, _PerpsController_getDirectProviderId = function _PerpsController_getDirectProviderId(provider) {
|
|
4310
|
+
if (provider.routesOrdersByProviderId) {
|
|
4311
|
+
return undefined;
|
|
4312
|
+
}
|
|
4313
|
+
return Array.from(this.providers.entries()).find(([, candidate]) => candidate === provider)?.[0];
|
|
4314
|
+
}, _PerpsController_hasConflictingProviderRoute = function _PerpsController_hasConflictingProviderRoute(providerId, provider) {
|
|
4315
|
+
return (providerId !== undefined &&
|
|
4316
|
+
!provider.routesOrdersByProviderId &&
|
|
4317
|
+
providerId !== provider.protocolId);
|
|
4318
|
+
}, _PerpsController_resolveRoutedOrderProvider =
|
|
4319
|
+
/**
|
|
4320
|
+
* Resolve one routed order operation after any in-flight initialization.
|
|
4321
|
+
*
|
|
4322
|
+
* @param params - Routed operation context.
|
|
4323
|
+
* @param params.orderType - Order type, when the operation carries one.
|
|
4324
|
+
* @param params.providerId - Explicit provider route, when supplied.
|
|
4325
|
+
* @returns The initialized provider that owns the operation.
|
|
4326
|
+
*/
|
|
4327
|
+
async function _PerpsController_resolveRoutedOrderProvider(params) {
|
|
4328
|
+
const { orderType, providerId } = params;
|
|
4329
|
+
const provider = await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getActiveProviderWhenReady).call(this);
|
|
4330
|
+
if (__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_hasConflictingProviderRoute).call(this, providerId, provider)) {
|
|
4331
|
+
throw new Error(orderType !== undefined && isStrategyOrderType(orderType)
|
|
4332
|
+
? PERPS_ERROR_CODES.ORDER_STRATEGY_ROUTE_UNAVAILABLE
|
|
4333
|
+
: PERPS_ERROR_CODES.PROVIDER_NOT_FOUND);
|
|
4334
|
+
}
|
|
4335
|
+
return provider;
|
|
4143
4336
|
}, _PerpsController_buildGlobalSnapshotContext = function _PerpsController_buildGlobalSnapshotContext() {
|
|
4144
4337
|
const snapshotConfigured = Boolean(__classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure.terminalApi?.globalSnapshotUrl) ||
|
|
4145
4338
|
typeof __classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure.terminalMarketService
|
|
@@ -4266,7 +4459,12 @@ async function _PerpsController_performMarketDataPreload() {
|
|
|
4266
4459
|
activeProvider: this.state.activeProvider,
|
|
4267
4460
|
isTestnet: this.state.isTestnet,
|
|
4268
4461
|
hip3ConfigVersion: this.state.hip3ConfigVersion,
|
|
4462
|
+
lifecycleGeneration: __classPrivateFieldGet(this, _PerpsController_lifecycleGeneration, "f"),
|
|
4269
4463
|
};
|
|
4464
|
+
const isCurrent = () => __classPrivateFieldGet(this, _PerpsController_lifecycleGeneration, "f") === preloadContext.lifecycleGeneration &&
|
|
4465
|
+
this.state.activeProvider === preloadContext.activeProvider &&
|
|
4466
|
+
this.state.isTestnet === preloadContext.isTestnet &&
|
|
4467
|
+
this.state.hip3ConfigVersion === preloadContext.hip3ConfigVersion;
|
|
4270
4468
|
const staticSnapshotDexes = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getStaticSnapshotDexes).call(this);
|
|
4271
4469
|
const now = Date.now();
|
|
4272
4470
|
const existingEntry = this.state.cachedMarketDataByProvider[cacheKey];
|
|
@@ -4296,9 +4494,7 @@ async function _PerpsController_performMarketDataPreload() {
|
|
|
4296
4494
|
duration_ms: Math.round(performance.now() - preloadStart),
|
|
4297
4495
|
markets: data.length,
|
|
4298
4496
|
});
|
|
4299
|
-
if (
|
|
4300
|
-
this.state.isTestnet !== preloadContext.isTestnet ||
|
|
4301
|
-
this.state.hip3ConfigVersion !== preloadContext.hip3ConfigVersion) {
|
|
4497
|
+
if (!isCurrent()) {
|
|
4302
4498
|
traceData = {
|
|
4303
4499
|
success: false,
|
|
4304
4500
|
error: 'Global snapshot preload context changed',
|
|
@@ -4323,6 +4519,13 @@ async function _PerpsController_performMarketDataPreload() {
|
|
|
4323
4519
|
}
|
|
4324
4520
|
: {};
|
|
4325
4521
|
const marketDiskEntries = [];
|
|
4522
|
+
if (!isCurrent()) {
|
|
4523
|
+
traceData = {
|
|
4524
|
+
success: false,
|
|
4525
|
+
error: 'Global snapshot preload context changed',
|
|
4526
|
+
};
|
|
4527
|
+
return;
|
|
4528
|
+
}
|
|
4326
4529
|
if (this.state.activeProvider === 'aggregated' &&
|
|
4327
4530
|
this.activeProviderInstance) {
|
|
4328
4531
|
// Split returned data by providerId and store each slice
|
|
@@ -4423,6 +4626,7 @@ async function _PerpsController_performUserDataPreload() {
|
|
|
4423
4626
|
}
|
|
4424
4627
|
const userAddress = evmAccount.address;
|
|
4425
4628
|
const { activeProvider, isTestnet, hip3ConfigVersion } = this.state;
|
|
4629
|
+
const lifecycleGeneration = __classPrivateFieldGet(this, _PerpsController_lifecycleGeneration, "f");
|
|
4426
4630
|
const { activeProviderInstance } = this;
|
|
4427
4631
|
const hyperliquidDexes = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getStaticSnapshotDexes).call(this);
|
|
4428
4632
|
const isCurrent = () => {
|
|
@@ -4433,7 +4637,8 @@ async function _PerpsController_performUserDataPreload() {
|
|
|
4433
4637
|
catch {
|
|
4434
4638
|
return false;
|
|
4435
4639
|
}
|
|
4436
|
-
return (this
|
|
4640
|
+
return (__classPrivateFieldGet(this, _PerpsController_lifecycleGeneration, "f") === lifecycleGeneration &&
|
|
4641
|
+
this.state.activeProvider === activeProvider &&
|
|
4437
4642
|
this.activeProviderInstance === activeProviderInstance &&
|
|
4438
4643
|
this.state.isTestnet === isTestnet &&
|
|
4439
4644
|
this.state.hip3ConfigVersion === hip3ConfigVersion &&
|
|
@@ -4476,6 +4681,15 @@ async function _PerpsController_performUserDataPreload() {
|
|
|
4476
4681
|
const traceId = uuidv4();
|
|
4477
4682
|
const preloadStart = performance.now();
|
|
4478
4683
|
let traceData;
|
|
4684
|
+
const staleContextError = 'User data preload context changed';
|
|
4685
|
+
const discardStalePreload = () => {
|
|
4686
|
+
if (isCurrent()) {
|
|
4687
|
+
return false;
|
|
4688
|
+
}
|
|
4689
|
+
traceData = { success: false, error: staleContextError };
|
|
4690
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: Discarding stale user data preload');
|
|
4691
|
+
return true;
|
|
4692
|
+
};
|
|
4479
4693
|
try {
|
|
4480
4694
|
__classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure.tracer.trace({
|
|
4481
4695
|
name: PerpsTraceNames.UserDataPreload,
|
|
@@ -4489,6 +4703,9 @@ async function _PerpsController_performUserDataPreload() {
|
|
|
4489
4703
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: Fetching user data in background');
|
|
4490
4704
|
if (activeProvider === 'hyperliquid') {
|
|
4491
4705
|
const snapshot = await this.getUserDataSnapshot();
|
|
4706
|
+
if (discardStalePreload()) {
|
|
4707
|
+
return;
|
|
4708
|
+
}
|
|
4492
4709
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: User data preloaded', {
|
|
4493
4710
|
positionCount: snapshot.positions.length,
|
|
4494
4711
|
orderCount: snapshot.orders.length,
|
|
@@ -4507,8 +4724,8 @@ async function _PerpsController_performUserDataPreload() {
|
|
|
4507
4724
|
this.getOpenOrders({ standalone: true, userAddress }),
|
|
4508
4725
|
this.getAccountState({ standalone: true, userAddress }),
|
|
4509
4726
|
]);
|
|
4510
|
-
if (
|
|
4511
|
-
|
|
4727
|
+
if (discardStalePreload()) {
|
|
4728
|
+
return;
|
|
4512
4729
|
}
|
|
4513
4730
|
if (activeProvider === 'aggregated' && activeProviderInstance) {
|
|
4514
4731
|
// Split by providerId and write one cache entry per provider key
|
|
@@ -4532,6 +4749,9 @@ async function _PerpsController_performUserDataPreload() {
|
|
|
4532
4749
|
}
|
|
4533
4750
|
// AccountState — assign to its provider bucket
|
|
4534
4751
|
ensureBucket(accountState.providerId ?? fallbackProviderId).accountState = accountState;
|
|
4752
|
+
if (discardStalePreload()) {
|
|
4753
|
+
return;
|
|
4754
|
+
}
|
|
4535
4755
|
this.update((state) => {
|
|
4536
4756
|
for (const [pid, data] of byProvider) {
|
|
4537
4757
|
const key = buildProviderCacheKey(pid, isTestnet);
|
|
@@ -4560,6 +4780,9 @@ async function _PerpsController_performUserDataPreload() {
|
|
|
4560
4780
|
else {
|
|
4561
4781
|
// Single provider — store directly under its key
|
|
4562
4782
|
const ts = Date.now();
|
|
4783
|
+
if (discardStalePreload()) {
|
|
4784
|
+
return;
|
|
4785
|
+
}
|
|
4563
4786
|
this.update((state) => {
|
|
4564
4787
|
state.cachedUserDataByProvider[providerNetworkKey] = {
|
|
4565
4788
|
positions,
|
|
@@ -4589,6 +4812,9 @@ async function _PerpsController_performUserDataPreload() {
|
|
|
4589
4812
|
__classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure.tracer.setMeasurement(PerpsMeasurementName.PerpsUserDataPreload, performance.now() - preloadStart, 'millisecond', traceId);
|
|
4590
4813
|
}
|
|
4591
4814
|
catch (error) {
|
|
4815
|
+
if (discardStalePreload()) {
|
|
4816
|
+
return;
|
|
4817
|
+
}
|
|
4592
4818
|
traceData = {
|
|
4593
4819
|
success: false,
|
|
4594
4820
|
error: ensureError(error, 'PerpsController.performUserDataPreload')
|
|
@@ -4612,6 +4838,70 @@ async function _PerpsController_performUserDataPreload() {
|
|
|
4612
4838
|
});
|
|
4613
4839
|
}
|
|
4614
4840
|
}
|
|
4841
|
+
}, _PerpsController_performDisconnect =
|
|
4842
|
+
/**
|
|
4843
|
+
* Disconnect after this call has claimed the controller lifecycle.
|
|
4844
|
+
*
|
|
4845
|
+
* @returns A promise that resolves when teardown finishes.
|
|
4846
|
+
*/
|
|
4847
|
+
async function _PerpsController_performDisconnect() {
|
|
4848
|
+
__classPrivateFieldSet(this, _PerpsController_lifecycleGeneration, __classPrivateFieldGet(this, _PerpsController_lifecycleGeneration, "f") + 1, "f");
|
|
4849
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: Disconnecting provider to cleanup subscriptions', {
|
|
4850
|
+
timestamp: new Date().toISOString(),
|
|
4851
|
+
});
|
|
4852
|
+
// Stop preload interval and messenger subscriptions first,
|
|
4853
|
+
// so no background work fires while we tear down providers.
|
|
4854
|
+
if (__classPrivateFieldGet(this, _PerpsController_preloadTimer, "f")) {
|
|
4855
|
+
clearInterval(__classPrivateFieldGet(this, _PerpsController_preloadTimer, "f"));
|
|
4856
|
+
__classPrivateFieldSet(this, _PerpsController_preloadTimer, null, "f");
|
|
4857
|
+
}
|
|
4858
|
+
if (__classPrivateFieldGet(this, _PerpsController_preloadStateUnsubscribe, "f")) {
|
|
4859
|
+
__classPrivateFieldGet(this, _PerpsController_preloadStateUnsubscribe, "f").call(this);
|
|
4860
|
+
__classPrivateFieldSet(this, _PerpsController_preloadStateUnsubscribe, null, "f");
|
|
4861
|
+
}
|
|
4862
|
+
if (__classPrivateFieldGet(this, _PerpsController_accountChangeUnsubscribe, "f")) {
|
|
4863
|
+
__classPrivateFieldGet(this, _PerpsController_accountChangeUnsubscribe, "f").call(this);
|
|
4864
|
+
__classPrivateFieldSet(this, _PerpsController_accountChangeUnsubscribe, null, "f");
|
|
4865
|
+
}
|
|
4866
|
+
__classPrivateFieldSet(this, _PerpsController_previousIsTestnet, null, "f");
|
|
4867
|
+
__classPrivateFieldSet(this, _PerpsController_previousHip3ConfigVersion, null, "f");
|
|
4868
|
+
const pendingReinitialization = __classPrivateFieldGet(this, _PerpsController_reinitializationOperationPromise, "f");
|
|
4869
|
+
if (pendingReinitialization) {
|
|
4870
|
+
await pendingReinitialization;
|
|
4871
|
+
}
|
|
4872
|
+
// Initialization owns provider creation. Let it finish before teardown so
|
|
4873
|
+
// it cannot repopulate providers after this method clears the references.
|
|
4874
|
+
const pendingInitialization = __classPrivateFieldGet(this, _PerpsController_initializationPromise, "f");
|
|
4875
|
+
if (pendingInitialization) {
|
|
4876
|
+
try {
|
|
4877
|
+
await pendingInitialization;
|
|
4878
|
+
}
|
|
4879
|
+
catch (error) {
|
|
4880
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_logError).call(this, ensureError(error, 'PerpsController.disconnect.initialization'), __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getErrorContext).call(this, 'disconnect', {
|
|
4881
|
+
operation: 'awaitInitialization',
|
|
4882
|
+
}));
|
|
4883
|
+
}
|
|
4884
|
+
}
|
|
4885
|
+
const provider = this.activeProviderInstance;
|
|
4886
|
+
if (provider) {
|
|
4887
|
+
try {
|
|
4888
|
+
await provider.disconnect();
|
|
4889
|
+
}
|
|
4890
|
+
catch (error) {
|
|
4891
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_logError).call(this, ensureError(error, 'PerpsController.disconnect'), __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getErrorContext).call(this, 'disconnect'));
|
|
4892
|
+
}
|
|
4893
|
+
}
|
|
4894
|
+
// Clear stale reference so standalone reads don't route through old provider
|
|
4895
|
+
this.activeProviderInstance = null;
|
|
4896
|
+
// Cleanup cached standalone provider (if any) — awaited to prevent races
|
|
4897
|
+
await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_cleanupStandaloneProvider).call(this);
|
|
4898
|
+
// Note: Feature-flag subscription is NOT cleaned up here.
|
|
4899
|
+
// It is a controller-lifetime concern (set once in the constructor),
|
|
4900
|
+
// not a session-lifetime concern. Unsubscribing here would break
|
|
4901
|
+
// geo-blocking / HIP-3 flag propagation after disconnect → reconnect.
|
|
4902
|
+
// Reset initialization state to ensure proper reconnection
|
|
4903
|
+
this.isInitialized = false;
|
|
4904
|
+
__classPrivateFieldSet(this, _PerpsController_initializationPromise, null, "f");
|
|
4615
4905
|
}, _PerpsController_persistWatchlistToRemote =
|
|
4616
4906
|
/**
|
|
4617
4907
|
* Writes the current local watchlist to AuthenticatedUserStorageService
|