@metamask-previews/perps-controller 1.3.0-preview-2d89a26 → 1.3.0-preview-afe010990
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 +9 -0
- package/dist/PerpsController-method-action-types.cjs +3 -0
- package/dist/PerpsController-method-action-types.cjs.map +1 -0
- package/dist/PerpsController-method-action-types.d.cts +147 -0
- package/dist/PerpsController-method-action-types.d.cts.map +1 -0
- package/dist/PerpsController-method-action-types.d.mts +147 -0
- package/dist/PerpsController-method-action-types.d.mts.map +1 -0
- package/dist/PerpsController-method-action-types.mjs +2 -0
- package/dist/PerpsController-method-action-types.mjs.map +1 -0
- package/dist/PerpsController.cjs +488 -183
- package/dist/PerpsController.cjs.map +1 -1
- package/dist/PerpsController.d.cts +91 -131
- package/dist/PerpsController.d.cts.map +1 -1
- package/dist/PerpsController.d.mts +91 -131
- package/dist/PerpsController.d.mts.map +1 -1
- package/dist/PerpsController.mjs +485 -182
- package/dist/PerpsController.mjs.map +1 -1
- package/dist/constants/eventNames.cjs +26 -0
- package/dist/constants/eventNames.cjs.map +1 -1
- package/dist/constants/eventNames.d.cts +19 -0
- package/dist/constants/eventNames.d.cts.map +1 -1
- package/dist/constants/eventNames.d.mts +19 -0
- package/dist/constants/eventNames.d.mts.map +1 -1
- package/dist/constants/eventNames.mjs +26 -0
- package/dist/constants/eventNames.mjs.map +1 -1
- package/dist/constants/hyperLiquidConfig.cjs +24 -4
- package/dist/constants/hyperLiquidConfig.cjs.map +1 -1
- package/dist/constants/hyperLiquidConfig.d.cts +8 -3
- package/dist/constants/hyperLiquidConfig.d.cts.map +1 -1
- package/dist/constants/hyperLiquidConfig.d.mts +8 -3
- package/dist/constants/hyperLiquidConfig.d.mts.map +1 -1
- package/dist/constants/hyperLiquidConfig.mjs +23 -3
- package/dist/constants/hyperLiquidConfig.mjs.map +1 -1
- package/dist/constants/myxConfig.cjs +75 -51
- package/dist/constants/myxConfig.cjs.map +1 -1
- package/dist/constants/myxConfig.d.cts +58 -19
- package/dist/constants/myxConfig.d.cts.map +1 -1
- package/dist/constants/myxConfig.d.mts +58 -19
- package/dist/constants/myxConfig.d.mts.map +1 -1
- package/dist/constants/myxConfig.mjs +74 -50
- package/dist/constants/myxConfig.mjs.map +1 -1
- package/dist/constants/perpsConfig.cjs +6 -2
- package/dist/constants/perpsConfig.cjs.map +1 -1
- package/dist/constants/perpsConfig.d.cts +5 -1
- package/dist/constants/perpsConfig.d.cts.map +1 -1
- package/dist/constants/perpsConfig.d.mts +5 -1
- package/dist/constants/perpsConfig.d.mts.map +1 -1
- package/dist/constants/perpsConfig.mjs +5 -1
- package/dist/constants/perpsConfig.mjs.map +1 -1
- package/dist/index.cjs +243 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -5
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +48 -5
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +36 -10
- package/dist/index.mjs.map +1 -1
- package/dist/providers/AggregatedPerpsProvider.cjs +24 -0
- package/dist/providers/AggregatedPerpsProvider.cjs.map +1 -1
- package/dist/providers/AggregatedPerpsProvider.d.cts +4 -0
- package/dist/providers/AggregatedPerpsProvider.d.cts.map +1 -1
- package/dist/providers/AggregatedPerpsProvider.d.mts +4 -0
- package/dist/providers/AggregatedPerpsProvider.d.mts.map +1 -1
- package/dist/providers/AggregatedPerpsProvider.mjs +24 -0
- package/dist/providers/AggregatedPerpsProvider.mjs.map +1 -1
- package/dist/providers/HyperLiquidProvider.cjs +470 -154
- package/dist/providers/HyperLiquidProvider.cjs.map +1 -1
- package/dist/providers/HyperLiquidProvider.d.cts +11 -2
- package/dist/providers/HyperLiquidProvider.d.cts.map +1 -1
- package/dist/providers/HyperLiquidProvider.d.mts +11 -2
- package/dist/providers/HyperLiquidProvider.d.mts.map +1 -1
- package/dist/providers/HyperLiquidProvider.mjs +471 -155
- package/dist/providers/HyperLiquidProvider.mjs.map +1 -1
- package/dist/selectors.cjs +1 -1
- package/dist/selectors.cjs.map +1 -1
- package/dist/selectors.mjs +1 -1
- package/dist/selectors.mjs.map +1 -1
- package/dist/services/AccountService.cjs +1 -1
- package/dist/services/AccountService.cjs.map +1 -1
- package/dist/services/AccountService.d.cts.map +1 -1
- package/dist/services/AccountService.d.mts.map +1 -1
- package/dist/services/AccountService.mjs +2 -2
- package/dist/services/AccountService.mjs.map +1 -1
- package/dist/services/DepositService.cjs +2 -1
- package/dist/services/DepositService.cjs.map +1 -1
- package/dist/services/DepositService.d.cts.map +1 -1
- package/dist/services/DepositService.d.mts.map +1 -1
- package/dist/services/DepositService.mjs +2 -1
- package/dist/services/DepositService.mjs.map +1 -1
- package/dist/services/EligibilityService.cjs +8 -103
- package/dist/services/EligibilityService.cjs.map +1 -1
- package/dist/services/EligibilityService.d.cts +4 -15
- package/dist/services/EligibilityService.d.cts.map +1 -1
- package/dist/services/EligibilityService.d.mts +4 -15
- package/dist/services/EligibilityService.d.mts.map +1 -1
- package/dist/services/EligibilityService.mjs +8 -103
- package/dist/services/EligibilityService.mjs.map +1 -1
- package/dist/services/HyperLiquidSubscriptionService.cjs +252 -46
- package/dist/services/HyperLiquidSubscriptionService.cjs.map +1 -1
- package/dist/services/HyperLiquidSubscriptionService.d.cts +1 -0
- package/dist/services/HyperLiquidSubscriptionService.d.cts.map +1 -1
- package/dist/services/HyperLiquidSubscriptionService.d.mts +1 -0
- package/dist/services/HyperLiquidSubscriptionService.d.mts.map +1 -1
- package/dist/services/HyperLiquidSubscriptionService.mjs +252 -46
- package/dist/services/HyperLiquidSubscriptionService.mjs.map +1 -1
- package/dist/services/MarketDataService.cjs +2 -4
- package/dist/services/MarketDataService.cjs.map +1 -1
- package/dist/services/MarketDataService.d.cts.map +1 -1
- package/dist/services/MarketDataService.d.mts.map +1 -1
- package/dist/services/MarketDataService.mjs +2 -4
- package/dist/services/MarketDataService.mjs.map +1 -1
- package/dist/services/TradingService.cjs +72 -6
- 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 +72 -6
- package/dist/services/TradingService.mjs.map +1 -1
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.d.cts +51 -3
- package/dist/types/index.d.cts.map +1 -1
- package/dist/types/index.d.mts +51 -3
- package/dist/types/index.d.mts.map +1 -1
- package/dist/types/index.mjs.map +1 -1
- package/dist/types/messenger.cjs.map +1 -1
- package/dist/types/messenger.d.cts +2 -1
- package/dist/types/messenger.d.cts.map +1 -1
- package/dist/types/messenger.d.mts +2 -1
- package/dist/types/messenger.d.mts.map +1 -1
- package/dist/types/messenger.mjs.map +1 -1
- package/dist/types/myx-types.cjs +19 -3
- package/dist/types/myx-types.cjs.map +1 -1
- package/dist/types/myx-types.d.cts +33 -2
- package/dist/types/myx-types.d.cts.map +1 -1
- package/dist/types/myx-types.d.mts +33 -2
- package/dist/types/myx-types.d.mts.map +1 -1
- package/dist/types/myx-types.mjs +6 -2
- package/dist/types/myx-types.mjs.map +1 -1
- package/dist/types/perps-types.cjs +3 -0
- package/dist/types/perps-types.cjs.map +1 -1
- package/dist/types/perps-types.d.cts +3 -3
- package/dist/types/perps-types.d.cts.map +1 -1
- package/dist/types/perps-types.d.mts +3 -3
- package/dist/types/perps-types.d.mts.map +1 -1
- package/dist/types/perps-types.mjs +3 -0
- package/dist/types/perps-types.mjs.map +1 -1
- package/dist/utils/accountUtils.cjs.map +1 -1
- package/dist/utils/accountUtils.d.cts.map +1 -1
- package/dist/utils/accountUtils.d.mts.map +1 -1
- package/dist/utils/accountUtils.mjs.map +1 -1
- package/dist/utils/myxAdapter.cjs +360 -15
- package/dist/utils/myxAdapter.cjs.map +1 -1
- package/dist/utils/myxAdapter.d.cts +94 -7
- package/dist/utils/myxAdapter.d.cts.map +1 -1
- package/dist/utils/myxAdapter.d.mts +94 -7
- package/dist/utils/myxAdapter.d.mts.map +1 -1
- package/dist/utils/myxAdapter.mjs +351 -16
- package/dist/utils/myxAdapter.mjs.map +1 -1
- package/package.json +4 -2
package/dist/PerpsController.cjs
CHANGED
|
@@ -10,9 +10,9 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
|
10
10
|
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");
|
|
11
11
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
12
12
|
};
|
|
13
|
-
var _PerpsController_instances, _a, _PerpsController_initializationPromise, _PerpsController_isReinitializing, _PerpsController_blockedRegionListVersion, _PerpsController_hip3Enabled, _PerpsController_hip3AllowlistMarkets, _PerpsController_hip3BlocklistMarkets, _PerpsController_hip3ConfigSource, _PerpsController_isMYXProviderEnabled, _PerpsController_standaloneProvider, _PerpsController_standaloneProviderIsTestnet, _PerpsController_standaloneProviderHip3Version, _PerpsController_eligibilityCheckDeferred, _PerpsController_options, _PerpsController_tradingService, _PerpsController_marketDataService, _PerpsController_accountService, _PerpsController_eligibilityService, _PerpsController_dataLakeService, _PerpsController_depositService, _PerpsController_featureFlagConfigurationService, _PerpsController_rewardsIntegrationService, _PerpsController_logError, _PerpsController_debugLog, _PerpsController_getOrCreateStandaloneProvider, _PerpsController_cleanupStandaloneProvider, _PerpsController_getMetrics, _PerpsController_findNetworkClientIdForChain, _PerpsController_submitTransaction, _PerpsController_migrateRequestsIfNeeded, _PerpsController_withStreamPause, _PerpsController_performInitialization, _PerpsController_getErrorContext, _PerpsController_getControllerState, _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_performMarketDataPreload, _PerpsController_performUserDataPreload;
|
|
13
|
+
var _PerpsController_instances, _a, _PerpsController_initializationPromise, _PerpsController_isReinitializing, _PerpsController_myxRegistrationPromise, _PerpsController_blockedRegionListVersion, _PerpsController_hip3Enabled, _PerpsController_hip3AllowlistMarkets, _PerpsController_hip3BlocklistMarkets, _PerpsController_hip3ConfigSource, _PerpsController_isMYXProviderEnabled, _PerpsController_standaloneProvider, _PerpsController_handlersRegistered, _PerpsController_standaloneProviderIsTestnet, _PerpsController_standaloneProviderHip3Version, _PerpsController_eligibilityCheckDeferred, _PerpsController_options, _PerpsController_tradingService, _PerpsController_marketDataService, _PerpsController_accountService, _PerpsController_eligibilityService, _PerpsController_dataLakeService, _PerpsController_depositService, _PerpsController_featureFlagConfigurationService, _PerpsController_rewardsIntegrationService, _PerpsController_logError, _PerpsController_debugLog, _PerpsController_marketCacheKey, _PerpsController_providerIsTestnet, _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_createServiceContext, _PerpsController_ensureTradingServiceDeps, _PerpsController_preloadWatchedPaths, _PerpsController_preloadTimer, _PerpsController_isPreloading, _PerpsController_isPreloadingUserData, _PerpsController_preloadStateUnsubscribe, _PerpsController_accountChangeUnsubscribe, _PerpsController_previousIsTestnet, _PerpsController_previousHip3ConfigVersion, _PerpsController_preloadRefreshMs, _PerpsController_preloadGuardMs, _PerpsController_performMarketDataPreload, _PerpsController_performUserDataPreload;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.PerpsController = exports.getDefaultPerpsControllerState = exports.InitializationState = exports.PERPS_ERROR_CODES = void 0;
|
|
15
|
+
exports.PerpsController = exports.getDefaultPerpsControllerState = exports.InitializationState = exports.PERPS_ERROR_CODES = exports.resolveMyxAuthConfig = exports.firstNonEmpty = void 0;
|
|
16
16
|
const base_controller_1 = require("@metamask/base-controller");
|
|
17
17
|
const controller_utils_1 = require("@metamask/controller-utils");
|
|
18
18
|
const uuid_1 = require("uuid");
|
|
@@ -37,6 +37,39 @@ const types_1 = require("./types/index.cjs");
|
|
|
37
37
|
const accountUtils_1 = require("./utils/accountUtils.cjs");
|
|
38
38
|
const errorUtils_1 = require("./utils/errorUtils.cjs");
|
|
39
39
|
const wait_1 = require("./utils/wait.cjs");
|
|
40
|
+
/**
|
|
41
|
+
* Returns the first non-empty string from the given values.
|
|
42
|
+
* Env vars default to '' (not null/undefined), so ?? wouldn't fall through.
|
|
43
|
+
*
|
|
44
|
+
* @param vals - String values to check in order.
|
|
45
|
+
* @returns The first non-empty string, or '' if all are empty/undefined.
|
|
46
|
+
*/
|
|
47
|
+
function firstNonEmpty(...vals) {
|
|
48
|
+
return (vals.find((val) => val !== null && val !== undefined && val !== '') ?? '');
|
|
49
|
+
}
|
|
50
|
+
exports.firstNonEmpty = firstNonEmpty;
|
|
51
|
+
/**
|
|
52
|
+
* Resolves MYX auth config from provider credentials, handling
|
|
53
|
+
* testnet/mainnet fallback logic.
|
|
54
|
+
*
|
|
55
|
+
* @param myx - MYX provider credentials.
|
|
56
|
+
* @param isTestnet - Whether the controller is in testnet mode.
|
|
57
|
+
* @returns Resolved appId, apiSecret, and brokerAddress.
|
|
58
|
+
*/
|
|
59
|
+
function resolveMyxAuthConfig(myx, isTestnet) {
|
|
60
|
+
return {
|
|
61
|
+
appId: isTestnet
|
|
62
|
+
? (myx.appIdTestnet ?? '')
|
|
63
|
+
: firstNonEmpty(myx.appIdMainnet, myx.appIdTestnet),
|
|
64
|
+
apiSecret: isTestnet
|
|
65
|
+
? (myx.apiSecretTestnet ?? '')
|
|
66
|
+
: firstNonEmpty(myx.apiSecretMainnet, myx.apiSecretTestnet),
|
|
67
|
+
brokerAddress: isTestnet
|
|
68
|
+
? (myx.brokerAddressTestnet ?? '')
|
|
69
|
+
: firstNonEmpty(myx.brokerAddressMainnet, myx.brokerAddressTestnet),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
exports.resolveMyxAuthConfig = resolveMyxAuthConfig;
|
|
40
73
|
// Re-export error codes from separate file to avoid circular dependencies
|
|
41
74
|
var perpsErrorCodes_2 = require("./perpsErrorCodes.cjs");
|
|
42
75
|
Object.defineProperty(exports, "PERPS_ERROR_CODES", { enumerable: true, get: function () { return perpsErrorCodes_2.PERPS_ERROR_CODES; } });
|
|
@@ -105,13 +138,8 @@ const getDefaultPerpsControllerState = () => ({
|
|
|
105
138
|
},
|
|
106
139
|
hip3ConfigVersion: 0,
|
|
107
140
|
selectedPaymentToken: null,
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
cachedPositions: null,
|
|
111
|
-
cachedOrders: null,
|
|
112
|
-
cachedAccountState: null,
|
|
113
|
-
cachedUserDataTimestamp: 0,
|
|
114
|
-
cachedUserDataAddress: null,
|
|
141
|
+
cachedMarketDataByProvider: {},
|
|
142
|
+
cachedUserDataByProvider: {},
|
|
115
143
|
});
|
|
116
144
|
exports.getDefaultPerpsControllerState = getDefaultPerpsControllerState;
|
|
117
145
|
/**
|
|
@@ -268,48 +296,18 @@ const metadata = {
|
|
|
268
296
|
includeInDebugSnapshot: false,
|
|
269
297
|
usedInUi: true,
|
|
270
298
|
},
|
|
271
|
-
|
|
299
|
+
cachedMarketDataByProvider: {
|
|
272
300
|
includeInStateLogs: false,
|
|
273
301
|
persist: false,
|
|
274
302
|
includeInDebugSnapshot: false,
|
|
275
303
|
usedInUi: true,
|
|
276
304
|
},
|
|
277
|
-
|
|
278
|
-
includeInStateLogs: false,
|
|
279
|
-
persist: false,
|
|
280
|
-
includeInDebugSnapshot: false,
|
|
281
|
-
usedInUi: false,
|
|
282
|
-
},
|
|
283
|
-
cachedPositions: {
|
|
305
|
+
cachedUserDataByProvider: {
|
|
284
306
|
includeInStateLogs: false,
|
|
285
307
|
persist: false,
|
|
286
308
|
includeInDebugSnapshot: false,
|
|
287
309
|
usedInUi: true,
|
|
288
310
|
},
|
|
289
|
-
cachedOrders: {
|
|
290
|
-
includeInStateLogs: false,
|
|
291
|
-
persist: false,
|
|
292
|
-
includeInDebugSnapshot: false,
|
|
293
|
-
usedInUi: true,
|
|
294
|
-
},
|
|
295
|
-
cachedAccountState: {
|
|
296
|
-
includeInStateLogs: false,
|
|
297
|
-
persist: false,
|
|
298
|
-
includeInDebugSnapshot: false,
|
|
299
|
-
usedInUi: true,
|
|
300
|
-
},
|
|
301
|
-
cachedUserDataTimestamp: {
|
|
302
|
-
includeInStateLogs: false,
|
|
303
|
-
persist: false,
|
|
304
|
-
includeInDebugSnapshot: false,
|
|
305
|
-
usedInUi: false,
|
|
306
|
-
},
|
|
307
|
-
cachedUserDataAddress: {
|
|
308
|
-
includeInStateLogs: false,
|
|
309
|
-
persist: false,
|
|
310
|
-
includeInDebugSnapshot: false,
|
|
311
|
-
usedInUi: false,
|
|
312
|
-
},
|
|
313
311
|
};
|
|
314
312
|
const MESSENGER_EXPOSED_METHODS = [
|
|
315
313
|
'placeOrder',
|
|
@@ -369,6 +367,8 @@ class PerpsController extends base_controller_1.BaseController {
|
|
|
369
367
|
this.isInitialized = false;
|
|
370
368
|
_PerpsController_initializationPromise.set(this, null);
|
|
371
369
|
_PerpsController_isReinitializing.set(this, false);
|
|
370
|
+
/** Tracks the async MYX dynamic import so performInitialization can await it. */
|
|
371
|
+
_PerpsController_myxRegistrationPromise.set(this, null);
|
|
372
372
|
this.blockedRegionList = {
|
|
373
373
|
list: [],
|
|
374
374
|
source: 'fallback',
|
|
@@ -397,6 +397,7 @@ class PerpsController extends base_controller_1.BaseController {
|
|
|
397
397
|
* connections) on every standalone call from the preload cycle.
|
|
398
398
|
*/
|
|
399
399
|
_PerpsController_standaloneProvider.set(this, null);
|
|
400
|
+
_PerpsController_handlersRegistered.set(this, false);
|
|
400
401
|
_PerpsController_standaloneProviderIsTestnet.set(this, null);
|
|
401
402
|
_PerpsController_standaloneProviderHip3Version.set(this, null);
|
|
402
403
|
_PerpsController_eligibilityCheckDeferred.set(this, void 0);
|
|
@@ -472,7 +473,122 @@ class PerpsController extends base_controller_1.BaseController {
|
|
|
472
473
|
this.providers = new Map();
|
|
473
474
|
// Migrate old persisted data without accountAddress
|
|
474
475
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_migrateRequestsIfNeeded).call(this);
|
|
475
|
-
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Read cached market data for the currently active provider (or aggregated).
|
|
479
|
+
* Returns null when no valid cache exists or when cache has expired.
|
|
480
|
+
*
|
|
481
|
+
* @returns The cached market data array, or null if no valid cache.
|
|
482
|
+
*/
|
|
483
|
+
getCachedMarketDataForActiveProvider() {
|
|
484
|
+
const { activeProvider } = this.state;
|
|
485
|
+
const cache = this.state.cachedMarketDataByProvider;
|
|
486
|
+
if (activeProvider === 'aggregated') {
|
|
487
|
+
// Assemble from all registered provider entries
|
|
488
|
+
const assembled = [];
|
|
489
|
+
let oldestTimestamp = Infinity;
|
|
490
|
+
for (const [providerId] of this.providers) {
|
|
491
|
+
const key = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_marketCacheKey).call(this, providerId, __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_providerIsTestnet).call(this, providerId));
|
|
492
|
+
const entry = cache[key];
|
|
493
|
+
if (!entry || entry.data.length === 0) {
|
|
494
|
+
continue;
|
|
495
|
+
}
|
|
496
|
+
oldestTimestamp = Math.min(oldestTimestamp, entry.timestamp);
|
|
497
|
+
assembled.push(...entry.data);
|
|
498
|
+
}
|
|
499
|
+
if (assembled.length === 0) {
|
|
500
|
+
return null;
|
|
501
|
+
}
|
|
502
|
+
// Check TTL against the oldest entry
|
|
503
|
+
if (Date.now() - oldestTimestamp > __classPrivateFieldGet(_a, _a, "f", _PerpsController_preloadGuardMs) * 10) {
|
|
504
|
+
return null;
|
|
505
|
+
}
|
|
506
|
+
return assembled;
|
|
507
|
+
}
|
|
508
|
+
// Single provider mode
|
|
509
|
+
const key = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_marketCacheKey).call(this, activeProvider, __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_providerIsTestnet).call(this, activeProvider));
|
|
510
|
+
const entry = cache[key];
|
|
511
|
+
if (!entry || entry.data.length === 0) {
|
|
512
|
+
return null;
|
|
513
|
+
}
|
|
514
|
+
if (Date.now() - entry.timestamp > __classPrivateFieldGet(_a, _a, "f", _PerpsController_preloadGuardMs) * 10) {
|
|
515
|
+
return null;
|
|
516
|
+
}
|
|
517
|
+
return entry.data;
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Read cached user data for the currently active provider (or aggregated).
|
|
521
|
+
* Returns null when no valid cache exists, cache has expired, or address
|
|
522
|
+
* does not match the currently selected EVM account.
|
|
523
|
+
*
|
|
524
|
+
* @returns The cached user data, or null if no valid cache.
|
|
525
|
+
*/
|
|
526
|
+
getCachedUserDataForActiveProvider() {
|
|
527
|
+
const { activeProvider } = this.state;
|
|
528
|
+
const cache = this.state.cachedUserDataByProvider;
|
|
529
|
+
const staleCutoff = __classPrivateFieldGet(_a, _a, "f", _PerpsController_preloadGuardMs) * 2; // 60s
|
|
530
|
+
// Get current user address for validation
|
|
531
|
+
let currentAddress = null;
|
|
532
|
+
try {
|
|
533
|
+
const evmAccount = (0, accountUtils_1.getSelectedEvmAccount)(this.messenger.call('AccountTreeController:getAccountsFromSelectedAccountGroup'));
|
|
534
|
+
currentAddress = evmAccount?.address ?? null;
|
|
535
|
+
}
|
|
536
|
+
catch {
|
|
537
|
+
// Can't determine current account — trust the cache
|
|
538
|
+
}
|
|
539
|
+
const isValidEntry = (entry) => {
|
|
540
|
+
if (!entry) {
|
|
541
|
+
return false;
|
|
542
|
+
}
|
|
543
|
+
if (Date.now() - entry.timestamp >= staleCutoff) {
|
|
544
|
+
return false;
|
|
545
|
+
}
|
|
546
|
+
if (currentAddress &&
|
|
547
|
+
entry.address.toLowerCase() !== currentAddress.toLowerCase()) {
|
|
548
|
+
return false;
|
|
549
|
+
}
|
|
550
|
+
return true;
|
|
551
|
+
};
|
|
552
|
+
if (activeProvider === 'aggregated') {
|
|
553
|
+
// Assemble from all registered provider entries
|
|
554
|
+
const allPositions = [];
|
|
555
|
+
const allOrders = [];
|
|
556
|
+
let defaultAccountState = null;
|
|
557
|
+
let hasValidEntry = false;
|
|
558
|
+
for (const [providerId] of this.providers) {
|
|
559
|
+
const key = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_marketCacheKey).call(this, providerId, __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_providerIsTestnet).call(this, providerId));
|
|
560
|
+
const entry = cache[key];
|
|
561
|
+
if (!isValidEntry(entry)) {
|
|
562
|
+
continue;
|
|
563
|
+
}
|
|
564
|
+
hasValidEntry = true;
|
|
565
|
+
allPositions.push(...entry.positions);
|
|
566
|
+
allOrders.push(...entry.orders);
|
|
567
|
+
// AccountState from default provider (hyperliquid)
|
|
568
|
+
if (providerId === 'hyperliquid') {
|
|
569
|
+
defaultAccountState = entry.accountState;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
if (!hasValidEntry) {
|
|
573
|
+
return null;
|
|
574
|
+
}
|
|
575
|
+
return {
|
|
576
|
+
positions: allPositions,
|
|
577
|
+
orders: allOrders,
|
|
578
|
+
accountState: defaultAccountState,
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
// Single provider mode
|
|
582
|
+
const key = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_marketCacheKey).call(this, activeProvider, __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_providerIsTestnet).call(this, activeProvider));
|
|
583
|
+
const entry = cache[key];
|
|
584
|
+
if (!entry || !isValidEntry(entry)) {
|
|
585
|
+
return null;
|
|
586
|
+
}
|
|
587
|
+
return {
|
|
588
|
+
positions: entry.positions,
|
|
589
|
+
orders: entry.orders,
|
|
590
|
+
accountState: entry.accountState,
|
|
591
|
+
};
|
|
476
592
|
}
|
|
477
593
|
/**
|
|
478
594
|
* Test-observable accessor for whether a standalone provider is cached.
|
|
@@ -552,6 +668,10 @@ class PerpsController extends base_controller_1.BaseController {
|
|
|
552
668
|
* @returns A promise that resolves when the operation completes.
|
|
553
669
|
*/
|
|
554
670
|
async init() {
|
|
671
|
+
if (!__classPrivateFieldGet(this, _PerpsController_handlersRegistered, "f")) {
|
|
672
|
+
this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
|
|
673
|
+
__classPrivateFieldSet(this, _PerpsController_handlersRegistered, true, "f");
|
|
674
|
+
}
|
|
555
675
|
if (this.isInitialized) {
|
|
556
676
|
return undefined;
|
|
557
677
|
}
|
|
@@ -561,6 +681,46 @@ class PerpsController extends base_controller_1.BaseController {
|
|
|
561
681
|
__classPrivateFieldSet(this, _PerpsController_initializationPromise, __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_performInitialization).call(this), "f");
|
|
562
682
|
return __classPrivateFieldGet(this, _PerpsController_initializationPromise, "f");
|
|
563
683
|
}
|
|
684
|
+
/**
|
|
685
|
+
* Registers the MYX provider after dynamic import resolves.
|
|
686
|
+
*
|
|
687
|
+
* Extracted from the import().then() callback so it can be tested directly
|
|
688
|
+
* (Jest cannot resolve dynamic imports without --experimental-vm-modules).
|
|
689
|
+
*
|
|
690
|
+
* @param MYXProvider - Constructor class for the MYX provider.
|
|
691
|
+
*/
|
|
692
|
+
registerMYXProvider(MYXProvider) {
|
|
693
|
+
const myxIsTestnet = perpsConfig_1.PROVIDER_CONFIG.MYX_TESTNET_ONLY || this.state.isTestnet;
|
|
694
|
+
const myx = __classPrivateFieldGet(this, _PerpsController_options, "f").clientConfig?.providerCredentials?.myx ?? {};
|
|
695
|
+
const myxAuthConfig = resolveMyxAuthConfig(myx, myxIsTestnet);
|
|
696
|
+
const myxProvider = new MYXProvider({
|
|
697
|
+
isTestnet: myxIsTestnet,
|
|
698
|
+
platformDependencies: __classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure,
|
|
699
|
+
messenger: this.messenger,
|
|
700
|
+
myxAuthConfig,
|
|
701
|
+
});
|
|
702
|
+
this.providers.set('myx', myxProvider);
|
|
703
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: MYX provider registered', {
|
|
704
|
+
isTestnet: myxIsTestnet,
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* Handles errors from the MYX dynamic import.
|
|
709
|
+
*
|
|
710
|
+
* Module-not-found errors are expected (extension doesn't ship MYX) → debug log.
|
|
711
|
+
* Other errors indicate constructor/config problems → Sentry via logError.
|
|
712
|
+
*
|
|
713
|
+
* @param error - The caught error from the dynamic import or constructor.
|
|
714
|
+
*/
|
|
715
|
+
handleMYXImportError(error) {
|
|
716
|
+
const isModuleError = error?.code === 'MODULE_NOT_FOUND';
|
|
717
|
+
if (isModuleError) {
|
|
718
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: MYX provider module not available, skipping registration');
|
|
719
|
+
}
|
|
720
|
+
else {
|
|
721
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_logError).call(this, error instanceof Error ? error : new Error(String(error)), __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getErrorContext).call(this, 'createProviders.myx'));
|
|
722
|
+
}
|
|
723
|
+
}
|
|
564
724
|
/**
|
|
565
725
|
* Get the currently active provider.
|
|
566
726
|
* In aggregated mode, returns AggregatedPerpsProvider which routes to underlying providers.
|
|
@@ -821,6 +981,14 @@ class PerpsController extends base_controller_1.BaseController {
|
|
|
821
981
|
origin: controller_utils_1.ORIGIN_METAMASK,
|
|
822
982
|
skipInitialGasEstimate: true,
|
|
823
983
|
};
|
|
984
|
+
__classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure.tracer.addBreadcrumb({
|
|
985
|
+
category: 'perps',
|
|
986
|
+
message: 'Deposit action started',
|
|
987
|
+
level: 'info',
|
|
988
|
+
data: {
|
|
989
|
+
place_order_after_deposit: placeOrder === true,
|
|
990
|
+
},
|
|
991
|
+
});
|
|
824
992
|
if (placeOrder) {
|
|
825
993
|
// Use addTransaction to create transaction without navigating to confirmation screen
|
|
826
994
|
const addResult = await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_submitTransaction).call(this, transaction, {
|
|
@@ -956,8 +1124,8 @@ class PerpsController extends base_controller_1.BaseController {
|
|
|
956
1124
|
const errorMessage = (0, errorUtils_1.ensureError)(error, 'PerpsController.depositWithOrder').message;
|
|
957
1125
|
const isCancellation = errorMessage.includes('User denied') ||
|
|
958
1126
|
errorMessage.includes('User rejected') ||
|
|
959
|
-
errorMessage.includes('cancelled') ||
|
|
960
|
-
errorMessage.includes('canceled');
|
|
1127
|
+
errorMessage.includes('User cancelled') ||
|
|
1128
|
+
errorMessage.includes('User canceled');
|
|
961
1129
|
this.update((state) => {
|
|
962
1130
|
const requestToUpdate = state.depositRequests.find((req) => req.id === currentDepositId);
|
|
963
1131
|
if (requestToUpdate) {
|
|
@@ -1321,7 +1489,7 @@ class PerpsController extends base_controller_1.BaseController {
|
|
|
1321
1489
|
/* fire-and-forget */
|
|
1322
1490
|
});
|
|
1323
1491
|
}, __classPrivateFieldGet(_a, _a, "f", _PerpsController_preloadRefreshMs)), "f");
|
|
1324
|
-
// Watch for isTestnet / hip3ConfigVersion
|
|
1492
|
+
// Watch for isTestnet / hip3ConfigVersion changes
|
|
1325
1493
|
const handler = (_state, patches) => {
|
|
1326
1494
|
// Early-return when no watched field changed (skips ~46 unrelated updates)
|
|
1327
1495
|
const hasRelevantChange = patches.some((patch) => typeof patch.path[0] === 'string' &&
|
|
@@ -1342,16 +1510,9 @@ class PerpsController extends base_controller_1.BaseController {
|
|
|
1342
1510
|
});
|
|
1343
1511
|
__classPrivateFieldSet(this, _PerpsController_previousIsTestnet, currentIsTestnet, "f");
|
|
1344
1512
|
__classPrivateFieldSet(this, _PerpsController_previousHip3ConfigVersion, currentHip3Version, "f");
|
|
1345
|
-
//
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
state.cachedMarketDataTimestamp = 0;
|
|
1349
|
-
state.cachedPositions = null;
|
|
1350
|
-
state.cachedOrders = null;
|
|
1351
|
-
state.cachedAccountState = null;
|
|
1352
|
-
state.cachedUserDataTimestamp = 0;
|
|
1353
|
-
state.cachedUserDataAddress = null;
|
|
1354
|
-
});
|
|
1513
|
+
// No need to clear user data cache — per-provider keys include the
|
|
1514
|
+
// network, so different networks don't collide. Re-preload will
|
|
1515
|
+
// populate the new key.
|
|
1355
1516
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_performMarketDataPreload).call(this).catch(() => {
|
|
1356
1517
|
/* fire-and-forget */
|
|
1357
1518
|
});
|
|
@@ -1365,16 +1526,13 @@ class PerpsController extends base_controller_1.BaseController {
|
|
|
1365
1526
|
const accountChangeHandler = () => {
|
|
1366
1527
|
const evmAccount = (0, accountUtils_1.getSelectedEvmAccount)(this.messenger.call('AccountTreeController:getAccountsFromSelectedAccountGroup'));
|
|
1367
1528
|
const currentAddress = evmAccount?.address ?? null;
|
|
1368
|
-
// If
|
|
1369
|
-
|
|
1370
|
-
|
|
1529
|
+
// If any cached entry belongs to a different account, clear all entries.
|
|
1530
|
+
// Max 4 entries (2 providers × 2 networks) — clearing all is simple and safe.
|
|
1531
|
+
const hasStaleEntries = Object.values(this.state.cachedUserDataByProvider).some((entry) => entry.address.toLowerCase() !== currentAddress?.toLowerCase());
|
|
1532
|
+
if (hasStaleEntries) {
|
|
1371
1533
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: Account changed, clearing user data cache');
|
|
1372
1534
|
this.update((state) => {
|
|
1373
|
-
state.
|
|
1374
|
-
state.cachedOrders = null;
|
|
1375
|
-
state.cachedAccountState = null;
|
|
1376
|
-
state.cachedUserDataTimestamp = 0;
|
|
1377
|
-
state.cachedUserDataAddress = null;
|
|
1535
|
+
state.cachedUserDataByProvider = {};
|
|
1378
1536
|
});
|
|
1379
1537
|
// Only preload if the new account is an EVM account
|
|
1380
1538
|
if (currentAddress) {
|
|
@@ -1607,6 +1765,15 @@ class PerpsController extends base_controller_1.BaseController {
|
|
|
1607
1765
|
}
|
|
1608
1766
|
finally {
|
|
1609
1767
|
__classPrivateFieldSet(this, _PerpsController_isReinitializing, false, "f");
|
|
1768
|
+
// Re-trigger preload now that reinit is complete and the
|
|
1769
|
+
// activeProviderInstance points to the correct network.
|
|
1770
|
+
// The state-change listener may have already fired during reinit
|
|
1771
|
+
// but was skipped due to the #isReinitializing guard.
|
|
1772
|
+
if (__classPrivateFieldGet(this, _PerpsController_preloadTimer, "f")) {
|
|
1773
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_performMarketDataPreload).call(this).catch(() => {
|
|
1774
|
+
/* fire-and-forget */
|
|
1775
|
+
});
|
|
1776
|
+
}
|
|
1610
1777
|
}
|
|
1611
1778
|
}
|
|
1612
1779
|
/**
|
|
@@ -1653,7 +1820,7 @@ class PerpsController extends base_controller_1.BaseController {
|
|
|
1653
1820
|
// Provider disconnect is handled by performInitialization() during
|
|
1654
1821
|
// reinitialization. The disconnect() method skips provider teardown
|
|
1655
1822
|
// when isReinitializing is true to prevent double-disconnect.
|
|
1656
|
-
// Update state with new provider
|
|
1823
|
+
// Update state with new provider (market data cache preserved per-provider)
|
|
1657
1824
|
this.update((state) => {
|
|
1658
1825
|
state.activeProvider = providerId;
|
|
1659
1826
|
state.accountState = null;
|
|
@@ -1710,6 +1877,12 @@ class PerpsController extends base_controller_1.BaseController {
|
|
|
1710
1877
|
}
|
|
1711
1878
|
finally {
|
|
1712
1879
|
__classPrivateFieldSet(this, _PerpsController_isReinitializing, false, "f");
|
|
1880
|
+
// Re-trigger preload now that reinit is complete.
|
|
1881
|
+
if (__classPrivateFieldGet(this, _PerpsController_preloadTimer, "f")) {
|
|
1882
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_performMarketDataPreload).call(this).catch(() => {
|
|
1883
|
+
/* fire-and-forget */
|
|
1884
|
+
});
|
|
1885
|
+
}
|
|
1713
1886
|
}
|
|
1714
1887
|
}
|
|
1715
1888
|
/**
|
|
@@ -2087,14 +2260,18 @@ class PerpsController extends base_controller_1.BaseController {
|
|
|
2087
2260
|
* Eligibility (Geo-Blocking)
|
|
2088
2261
|
*/
|
|
2089
2262
|
/**
|
|
2090
|
-
*
|
|
2091
|
-
* Call this after onboarding is complete when the controller was constructed
|
|
2092
|
-
* with `deferEligibilityCheck: true`.
|
|
2263
|
+
* Fetch geo location
|
|
2093
2264
|
*
|
|
2094
|
-
*
|
|
2095
|
-
*
|
|
2096
|
-
|
|
2097
|
-
|
|
2265
|
+
* Returned in Country or Country-Region format
|
|
2266
|
+
* Example: FR, DE, US-MI, CA-ON
|
|
2267
|
+
*/
|
|
2268
|
+
/**
|
|
2269
|
+
* Refresh eligibility status
|
|
2270
|
+
*/
|
|
2271
|
+
/**
|
|
2272
|
+
* Resume eligibility monitoring after onboarding completes.
|
|
2273
|
+
* Clears the deferred flag and triggers an immediate eligibility check
|
|
2274
|
+
* using the current remote feature flag state.
|
|
2098
2275
|
*/
|
|
2099
2276
|
startEligibilityMonitoring() {
|
|
2100
2277
|
__classPrivateFieldSet(this, _PerpsController_eligibilityCheckDeferred, false, "f");
|
|
@@ -2117,9 +2294,6 @@ class PerpsController extends base_controller_1.BaseController {
|
|
|
2117
2294
|
stopEligibilityMonitoring() {
|
|
2118
2295
|
__classPrivateFieldSet(this, _PerpsController_eligibilityCheckDeferred, true, "f");
|
|
2119
2296
|
}
|
|
2120
|
-
/**
|
|
2121
|
-
* Refresh eligibility status
|
|
2122
|
-
*/
|
|
2123
2297
|
async refreshEligibility() {
|
|
2124
2298
|
if (__classPrivateFieldGet(this, _PerpsController_eligibilityCheckDeferred, "f")) {
|
|
2125
2299
|
return;
|
|
@@ -2130,9 +2304,10 @@ class PerpsController extends base_controller_1.BaseController {
|
|
|
2130
2304
|
// (started with remote config after it was fetched).
|
|
2131
2305
|
const versionAtStart = __classPrivateFieldGet(this, _PerpsController_blockedRegionListVersion, "f");
|
|
2132
2306
|
try {
|
|
2133
|
-
|
|
2307
|
+
const geoLocation = await this.messenger.call('GeolocationController:getGeolocation');
|
|
2134
2308
|
const isEligible = await __classPrivateFieldGet(this, _PerpsController_eligibilityService, "f").checkEligibility({
|
|
2135
2309
|
blockedRegions: this.blockedRegionList.list,
|
|
2310
|
+
geoLocation,
|
|
2136
2311
|
});
|
|
2137
2312
|
// Only update state if the blocked region list hasn't changed while we were awaiting.
|
|
2138
2313
|
// This prevents stale fallback-based eligibility checks from overwriting
|
|
@@ -2616,27 +2791,46 @@ class PerpsController extends base_controller_1.BaseController {
|
|
|
2616
2791
|
}
|
|
2617
2792
|
}
|
|
2618
2793
|
exports.PerpsController = PerpsController;
|
|
2619
|
-
_a = PerpsController, _PerpsController_initializationPromise = new WeakMap(), _PerpsController_isReinitializing = new WeakMap(), _PerpsController_blockedRegionListVersion = new WeakMap(), _PerpsController_hip3Enabled = new WeakMap(), _PerpsController_hip3AllowlistMarkets = new WeakMap(), _PerpsController_hip3BlocklistMarkets = new WeakMap(), _PerpsController_hip3ConfigSource = new WeakMap(), _PerpsController_standaloneProvider = new WeakMap(), _PerpsController_standaloneProviderIsTestnet = new WeakMap(), _PerpsController_standaloneProviderHip3Version = new WeakMap(), _PerpsController_eligibilityCheckDeferred = 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() {
|
|
2620
|
-
const
|
|
2621
|
-
|
|
2794
|
+
_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_standaloneProvider = new WeakMap(), _PerpsController_handlersRegistered = new WeakMap(), _PerpsController_standaloneProviderIsTestnet = new WeakMap(), _PerpsController_standaloneProviderHip3Version = new WeakMap(), _PerpsController_eligibilityCheckDeferred = 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() {
|
|
2795
|
+
const myx = __classPrivateFieldGet(this, _PerpsController_options, "f").clientConfig?.providerCredentials?.myx;
|
|
2796
|
+
// Local env-var override (MM_PERPS_MYX_PROVIDER_ENABLED) always wins —
|
|
2797
|
+
// matches the UI selector (resolvePerpsMyxProviderEnabled) so controller
|
|
2798
|
+
// and UI agree on whether MYX is available.
|
|
2799
|
+
if (myx?.enabled) {
|
|
2800
|
+
return true;
|
|
2801
|
+
}
|
|
2802
|
+
// Credentials present → MYX is enabled regardless of remote flag.
|
|
2803
|
+
// Use || so empty-string env vars (default '') fall through.
|
|
2804
|
+
const hasCredentials = Boolean(
|
|
2805
|
+
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
2806
|
+
myx?.appIdTestnet || myx?.appIdMainnet);
|
|
2807
|
+
if (hasCredentials) {
|
|
2808
|
+
return true;
|
|
2809
|
+
}
|
|
2810
|
+
// No local override or credentials — check remote flag as fallback
|
|
2622
2811
|
try {
|
|
2623
|
-
const localFlag = getLocalFlag();
|
|
2624
2812
|
const remoteState = this.messenger.call('RemoteFeatureFlagController:getState');
|
|
2625
2813
|
const remoteFlag = remoteState.remoteFeatureFlags?.perpsMyxProviderEnabled;
|
|
2626
2814
|
if ((0, types_1.isVersionGatedFeatureFlag)(remoteFlag)) {
|
|
2627
2815
|
const validated = __classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure.featureFlags.validateVersionGated(remoteFlag);
|
|
2628
|
-
return validated ??
|
|
2816
|
+
return validated ?? false;
|
|
2629
2817
|
}
|
|
2630
|
-
return
|
|
2818
|
+
return false;
|
|
2631
2819
|
}
|
|
2632
2820
|
catch {
|
|
2633
|
-
|
|
2634
|
-
return getLocalFlag();
|
|
2821
|
+
return false;
|
|
2635
2822
|
}
|
|
2636
2823
|
}, _PerpsController_logError = function _PerpsController_logError(error, options) {
|
|
2637
2824
|
__classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure.logger.error(error, options);
|
|
2638
2825
|
}, _PerpsController_debugLog = function _PerpsController_debugLog(...args) {
|
|
2639
2826
|
__classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure.debugLogger.log(...args);
|
|
2827
|
+
}, _PerpsController_marketCacheKey = function _PerpsController_marketCacheKey(providerId, isTestnet) {
|
|
2828
|
+
return `${providerId}:${isTestnet ? 'testnet' : 'mainnet'}`;
|
|
2829
|
+
}, _PerpsController_providerIsTestnet = function _PerpsController_providerIsTestnet(providerId) {
|
|
2830
|
+
if (providerId === 'myx') {
|
|
2831
|
+
return perpsConfig_1.PROVIDER_CONFIG.MYX_TESTNET_ONLY || this.state.isTestnet;
|
|
2832
|
+
}
|
|
2833
|
+
return this.state.isTestnet;
|
|
2640
2834
|
}, _PerpsController_getOrCreateStandaloneProvider = function _PerpsController_getOrCreateStandaloneProvider() {
|
|
2641
2835
|
const currentIsTestnet = this.state.isTestnet;
|
|
2642
2836
|
const currentHip3Version = this.state.hip3ConfigVersion ?? 0;
|
|
@@ -2659,6 +2853,10 @@ _a = PerpsController, _PerpsController_initializationPromise = new WeakMap(), _P
|
|
|
2659
2853
|
blocklistMarkets: __classPrivateFieldGet(this, _PerpsController_hip3BlocklistMarkets, "f"),
|
|
2660
2854
|
platformDependencies: __classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure,
|
|
2661
2855
|
messenger: this.messenger,
|
|
2856
|
+
builderAddressTestnet: __classPrivateFieldGet(this, _PerpsController_options, "f").clientConfig?.providerCredentials?.hyperliquid
|
|
2857
|
+
?.builderAddressTestnet,
|
|
2858
|
+
builderAddressMainnet: __classPrivateFieldGet(this, _PerpsController_options, "f").clientConfig?.providerCredentials?.hyperliquid
|
|
2859
|
+
?.builderAddressMainnet,
|
|
2662
2860
|
}), "f");
|
|
2663
2861
|
__classPrivateFieldSet(this, _PerpsController_standaloneProviderIsTestnet, currentIsTestnet, "f");
|
|
2664
2862
|
__classPrivateFieldSet(this, _PerpsController_standaloneProviderHip3Version, currentHip3Version, "f");
|
|
@@ -2816,89 +3014,16 @@ async function _PerpsController_performInitialization() {
|
|
|
2816
3014
|
}
|
|
2817
3015
|
this.providers.clear();
|
|
2818
3016
|
await __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_cleanupStandaloneProvider).call(this);
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
const hyperLiquidProvider = new HyperLiquidProvider_1.HyperLiquidProvider({
|
|
2830
|
-
isTestnet: this.state.isTestnet,
|
|
2831
|
-
hip3Enabled: __classPrivateFieldGet(this, _PerpsController_hip3Enabled, "f"),
|
|
2832
|
-
allowlistMarkets: __classPrivateFieldGet(this, _PerpsController_hip3AllowlistMarkets, "f"),
|
|
2833
|
-
blocklistMarkets: __classPrivateFieldGet(this, _PerpsController_hip3BlocklistMarkets, "f"),
|
|
2834
|
-
platformDependencies: __classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure,
|
|
2835
|
-
messenger: this.messenger,
|
|
2836
|
-
});
|
|
2837
|
-
this.providers.set('hyperliquid', hyperLiquidProvider);
|
|
2838
|
-
// Register MYX provider if enabled via feature flag.
|
|
2839
|
-
// Uses dynamic import so @myx-trade/sdk is excluded from the bundle
|
|
2840
|
-
// unless MM_PERPS_MYX_PROVIDER_ENABLED=true is set at build time.
|
|
2841
|
-
// Wrapped in try/catch so a missing module (stripped at build time)
|
|
2842
|
-
// only skips MYX registration instead of aborting initialization.
|
|
2843
|
-
const isMYXEnabled = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_isMYXProviderEnabled).call(this);
|
|
2844
|
-
if (isMYXEnabled) {
|
|
2845
|
-
try {
|
|
2846
|
-
const { MYXProvider } = await import("./providers/MYXProvider.cjs");
|
|
2847
|
-
const myxProvider = new MYXProvider({
|
|
2848
|
-
isTestnet: perpsConfig_1.PROVIDER_CONFIG.MYX_TESTNET_ONLY || this.state.isTestnet,
|
|
2849
|
-
platformDependencies: __classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure,
|
|
2850
|
-
});
|
|
2851
|
-
this.providers.set('myx', myxProvider);
|
|
2852
|
-
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: MYX provider registered', {
|
|
2853
|
-
isTestnet: perpsConfig_1.PROVIDER_CONFIG.MYX_TESTNET_ONLY || this.state.isTestnet,
|
|
2854
|
-
});
|
|
2855
|
-
}
|
|
2856
|
-
catch {
|
|
2857
|
-
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: MYX provider module not available (stripped from build), skipping registration');
|
|
2858
|
-
}
|
|
2859
|
-
}
|
|
2860
|
-
// Set up active provider based on activeProvider value in state
|
|
2861
|
-
// 'aggregated' is treated as just another provider that wraps others
|
|
2862
|
-
if (activeProvider === 'aggregated') {
|
|
2863
|
-
// Aggregated mode: wrap in AggregatedPerpsProvider for multi-provider support
|
|
2864
|
-
this.activeProviderInstance = new AggregatedPerpsProvider_1.AggregatedPerpsProvider({
|
|
2865
|
-
providers: this.providers,
|
|
2866
|
-
defaultProvider: 'hyperliquid',
|
|
2867
|
-
infrastructure: __classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure,
|
|
2868
|
-
});
|
|
2869
|
-
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: Using aggregated provider (multi-provider)', { registeredProviders: Array.from(this.providers.keys()) });
|
|
2870
|
-
}
|
|
2871
|
-
else if (activeProvider === 'hyperliquid') {
|
|
2872
|
-
// Direct provider mode: use HyperLiquid provider directly
|
|
2873
|
-
this.activeProviderInstance = hyperLiquidProvider;
|
|
2874
|
-
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, `PerpsController: Using direct provider (${activeProvider})`);
|
|
2875
|
-
}
|
|
2876
|
-
else if (activeProvider === 'myx') {
|
|
2877
|
-
// MYX provider mode
|
|
2878
|
-
const myxProvider = this.providers.get('myx');
|
|
2879
|
-
if (myxProvider) {
|
|
2880
|
-
this.activeProviderInstance = myxProvider;
|
|
2881
|
-
}
|
|
2882
|
-
else {
|
|
2883
|
-
// MYX feature flag is disabled — fall back to HyperLiquid
|
|
2884
|
-
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: MYX provider not available (feature flag disabled), falling back to hyperliquid');
|
|
2885
|
-
this.activeProviderInstance = hyperLiquidProvider;
|
|
2886
|
-
this.update((state) => {
|
|
2887
|
-
state.activeProvider = 'hyperliquid';
|
|
2888
|
-
});
|
|
2889
|
-
}
|
|
2890
|
-
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, `PerpsController: Using direct provider (${this.activeProviderInstance === hyperLiquidProvider ? 'hyperliquid' : activeProvider})`);
|
|
2891
|
-
}
|
|
2892
|
-
else {
|
|
2893
|
-
// Unsupported provider - throw error to prevent silent misconfiguration
|
|
2894
|
-
throw new Error(`Unsupported provider: ${String(activeProvider)}. Currently only 'hyperliquid', 'myx', and 'aggregated' are supported.`);
|
|
2895
|
-
}
|
|
2896
|
-
// Future providers can be added here with their own authentication patterns:
|
|
2897
|
-
// - Some might use API keys: new BinanceProvider({ apiKey, apiSecret })
|
|
2898
|
-
// - Some might use different wallet patterns: new GMXProvider({ signer })
|
|
2899
|
-
// - Some might not need auth at all: new DydxProvider()
|
|
2900
|
-
// Wait for WebSocket transport to be ready before marking as initialized
|
|
2901
|
-
await (0, wait_1.wait)(perpsConfig_1.PERPS_CONSTANTS.ReconnectionCleanupDelayMs);
|
|
3017
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_createProviders).call(this);
|
|
3018
|
+
// Await MYX dynamic import (if started) so MYX is in the providers
|
|
3019
|
+
// map before we assign the active provider. Runs concurrently with
|
|
3020
|
+
// the WebSocket readiness delay for zero additional latency.
|
|
3021
|
+
await Promise.all([
|
|
3022
|
+
(0, wait_1.wait)(perpsConfig_1.PERPS_CONSTANTS.ReconnectionCleanupDelayMs),
|
|
3023
|
+
__classPrivateFieldGet(this, _PerpsController_myxRegistrationPromise, "f"),
|
|
3024
|
+
]);
|
|
3025
|
+
__classPrivateFieldSet(this, _PerpsController_myxRegistrationPromise, null, "f");
|
|
3026
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_assignActiveProvider).call(this);
|
|
2902
3027
|
this.isInitialized = true;
|
|
2903
3028
|
this.update((state) => {
|
|
2904
3029
|
state.initializationState = InitializationState.Initialized;
|
|
@@ -2906,7 +3031,7 @@ async function _PerpsController_performInitialization() {
|
|
|
2906
3031
|
});
|
|
2907
3032
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: Providers initialized successfully', {
|
|
2908
3033
|
providerCount: this.providers.size,
|
|
2909
|
-
activeProvider,
|
|
3034
|
+
activeProvider: this.state.activeProvider,
|
|
2910
3035
|
timestamp: new Date().toISOString(),
|
|
2911
3036
|
attempts: attempt,
|
|
2912
3037
|
});
|
|
@@ -2941,6 +3066,84 @@ async function _PerpsController_performInitialization() {
|
|
|
2941
3066
|
attempts: maxAttempts,
|
|
2942
3067
|
timestamp: new Date().toISOString(),
|
|
2943
3068
|
});
|
|
3069
|
+
}, _PerpsController_createProviders = function _PerpsController_createProviders() {
|
|
3070
|
+
const { activeProvider } = this.state;
|
|
3071
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: Creating provider with HIP-3 configuration', {
|
|
3072
|
+
hip3Enabled: __classPrivateFieldGet(this, _PerpsController_hip3Enabled, "f"),
|
|
3073
|
+
hip3AllowlistMarkets: __classPrivateFieldGet(this, _PerpsController_hip3AllowlistMarkets, "f"),
|
|
3074
|
+
hip3BlocklistMarkets: __classPrivateFieldGet(this, _PerpsController_hip3BlocklistMarkets, "f"),
|
|
3075
|
+
hip3ConfigSource: __classPrivateFieldGet(this, _PerpsController_hip3ConfigSource, "f"),
|
|
3076
|
+
isTestnet: this.state.isTestnet,
|
|
3077
|
+
activeProvider,
|
|
3078
|
+
});
|
|
3079
|
+
// Always create HyperLiquid provider as the base provider
|
|
3080
|
+
const hyperLiquidProvider = new HyperLiquidProvider_1.HyperLiquidProvider({
|
|
3081
|
+
isTestnet: this.state.isTestnet,
|
|
3082
|
+
hip3Enabled: __classPrivateFieldGet(this, _PerpsController_hip3Enabled, "f"),
|
|
3083
|
+
allowlistMarkets: __classPrivateFieldGet(this, _PerpsController_hip3AllowlistMarkets, "f"),
|
|
3084
|
+
blocklistMarkets: __classPrivateFieldGet(this, _PerpsController_hip3BlocklistMarkets, "f"),
|
|
3085
|
+
platformDependencies: __classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure,
|
|
3086
|
+
messenger: this.messenger,
|
|
3087
|
+
builderAddressTestnet: __classPrivateFieldGet(this, _PerpsController_options, "f").clientConfig?.providerCredentials?.hyperliquid
|
|
3088
|
+
?.builderAddressTestnet,
|
|
3089
|
+
builderAddressMainnet: __classPrivateFieldGet(this, _PerpsController_options, "f").clientConfig?.providerCredentials?.hyperliquid
|
|
3090
|
+
?.builderAddressMainnet,
|
|
3091
|
+
});
|
|
3092
|
+
this.providers.set('hyperliquid', hyperLiquidProvider);
|
|
3093
|
+
// Register MYX provider if enabled via feature flag.
|
|
3094
|
+
// Dynamic import because the MYX package pulls in heavy dependencies we
|
|
3095
|
+
// don't want bundled in extension. Until MYX fixes their package, extension
|
|
3096
|
+
// doesn't ship it — the catch branch silently skips registration.
|
|
3097
|
+
// Uses .then()/.catch() instead of await because #createProviders is not async;
|
|
3098
|
+
// MYX registration completing asynchronously is fine since it's only used when
|
|
3099
|
+
// explicitly enabled and selected.
|
|
3100
|
+
const isMYXEnabled = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_isMYXProviderEnabled).call(this);
|
|
3101
|
+
if (isMYXEnabled) {
|
|
3102
|
+
// IMPORTANT: Must use import() — NOT require() — for core/extension tree-shaking.
|
|
3103
|
+
// require() is synchronous and bundlers include it in the main bundle.
|
|
3104
|
+
// import() enables true code splitting so MYX is excluded when not enabled.
|
|
3105
|
+
__classPrivateFieldSet(this, _PerpsController_myxRegistrationPromise, import("./providers/MYXProvider.cjs")
|
|
3106
|
+
.then(({ MYXProvider }) => {
|
|
3107
|
+
this.registerMYXProvider(MYXProvider);
|
|
3108
|
+
return undefined;
|
|
3109
|
+
})
|
|
3110
|
+
.catch((error) => this.handleMYXImportError(error)), "f");
|
|
3111
|
+
}
|
|
3112
|
+
}, _PerpsController_assignActiveProvider = function _PerpsController_assignActiveProvider() {
|
|
3113
|
+
const { activeProvider } = this.state;
|
|
3114
|
+
const hyperLiquidProvider = this.providers.get('hyperliquid');
|
|
3115
|
+
if (!hyperLiquidProvider) {
|
|
3116
|
+
throw new Error('HyperLiquid provider not registered — cannot assign active provider');
|
|
3117
|
+
}
|
|
3118
|
+
if (activeProvider === 'aggregated') {
|
|
3119
|
+
this.activeProviderInstance = new AggregatedPerpsProvider_1.AggregatedPerpsProvider({
|
|
3120
|
+
providers: this.providers,
|
|
3121
|
+
defaultProvider: 'hyperliquid',
|
|
3122
|
+
infrastructure: __classPrivateFieldGet(this, _PerpsController_options, "f").infrastructure,
|
|
3123
|
+
});
|
|
3124
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: Using aggregated provider (multi-provider)', { registeredProviders: Array.from(this.providers.keys()) });
|
|
3125
|
+
}
|
|
3126
|
+
else if (activeProvider === 'hyperliquid') {
|
|
3127
|
+
this.activeProviderInstance = hyperLiquidProvider;
|
|
3128
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, `PerpsController: Using direct provider (${activeProvider})`);
|
|
3129
|
+
}
|
|
3130
|
+
else if (activeProvider === 'myx') {
|
|
3131
|
+
const myxProvider = this.providers.get('myx');
|
|
3132
|
+
if (myxProvider) {
|
|
3133
|
+
this.activeProviderInstance = myxProvider;
|
|
3134
|
+
}
|
|
3135
|
+
else {
|
|
3136
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: MYX provider not available, falling back to hyperliquid');
|
|
3137
|
+
this.activeProviderInstance = hyperLiquidProvider;
|
|
3138
|
+
this.update((state) => {
|
|
3139
|
+
state.activeProvider = 'hyperliquid';
|
|
3140
|
+
});
|
|
3141
|
+
}
|
|
3142
|
+
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, `PerpsController: Using direct provider (${this.activeProviderInstance === hyperLiquidProvider ? 'hyperliquid' : activeProvider})`);
|
|
3143
|
+
}
|
|
3144
|
+
else {
|
|
3145
|
+
throw new Error(`Unsupported provider: ${String(activeProvider)}. Currently only 'hyperliquid', 'myx', and 'aggregated' are supported.`);
|
|
3146
|
+
}
|
|
2944
3147
|
}, _PerpsController_getErrorContext = function _PerpsController_getErrorContext(method, extra) {
|
|
2945
3148
|
return {
|
|
2946
3149
|
tags: {
|
|
@@ -2970,7 +3173,7 @@ async function _PerpsController_performInitialization() {
|
|
|
2970
3173
|
},
|
|
2971
3174
|
stateManager: {
|
|
2972
3175
|
update: (updater) =>
|
|
2973
|
-
// @ts-expect-error TS2589 - excessively deep instantiation
|
|
3176
|
+
// @ts-expect-error TS2589 - excessively deep instantiation from BaseController generic
|
|
2974
3177
|
this.update(updater),
|
|
2975
3178
|
getState: () => __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_getControllerState).call(this),
|
|
2976
3179
|
},
|
|
@@ -2988,9 +3191,22 @@ async function _PerpsController_performMarketDataPreload() {
|
|
|
2988
3191
|
if (__classPrivateFieldGet(this, _PerpsController_isPreloading, "f")) {
|
|
2989
3192
|
return;
|
|
2990
3193
|
}
|
|
3194
|
+
// Skip preloading during provider/network reinitialisation.
|
|
3195
|
+
// The activeProviderInstance still points to the OLD network's provider
|
|
3196
|
+
// until init() completes, so fetching now would store stale data under
|
|
3197
|
+
// the NEW network's cache key.
|
|
3198
|
+
if (__classPrivateFieldGet(this, _PerpsController_isReinitializing, "f")) {
|
|
3199
|
+
return;
|
|
3200
|
+
}
|
|
3201
|
+
// Determine actual provider and cache key for debounce
|
|
3202
|
+
const actualProviderId = this.activeProviderInstance
|
|
3203
|
+
? this.state.activeProvider // includes 'aggregated'
|
|
3204
|
+
: 'hyperliquid';
|
|
3205
|
+
const cacheKey = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_marketCacheKey).call(this, actualProviderId, __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_providerIsTestnet).call(this, actualProviderId));
|
|
2991
3206
|
const now = Date.now();
|
|
2992
|
-
|
|
2993
|
-
|
|
3207
|
+
const existingEntry = this.state.cachedMarketDataByProvider[cacheKey];
|
|
3208
|
+
if (existingEntry &&
|
|
3209
|
+
now - existingEntry.timestamp < __classPrivateFieldGet(_a, _a, "f", _PerpsController_preloadGuardMs)) {
|
|
2994
3210
|
return;
|
|
2995
3211
|
}
|
|
2996
3212
|
__classPrivateFieldSet(this, _PerpsController_isPreloading, true, "f");
|
|
@@ -3009,10 +3225,46 @@ async function _PerpsController_performMarketDataPreload() {
|
|
|
3009
3225
|
});
|
|
3010
3226
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: Fetching market data in background');
|
|
3011
3227
|
const data = await this.getMarketDataWithPrices({ standalone: true });
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3228
|
+
// Store under per-provider key(s)
|
|
3229
|
+
const ts = Date.now();
|
|
3230
|
+
if (this.state.activeProvider === 'aggregated' &&
|
|
3231
|
+
this.activeProviderInstance) {
|
|
3232
|
+
// Split returned data by providerId and store each slice
|
|
3233
|
+
const fallbackProviderId = 'hyperliquid'; // default for items missing providerId
|
|
3234
|
+
const byProvider = new Map();
|
|
3235
|
+
for (const item of data) {
|
|
3236
|
+
const pid = item.providerId ?? fallbackProviderId;
|
|
3237
|
+
const existing = byProvider.get(pid);
|
|
3238
|
+
if (existing) {
|
|
3239
|
+
existing.push(item);
|
|
3240
|
+
}
|
|
3241
|
+
else {
|
|
3242
|
+
byProvider.set(pid, [item]);
|
|
3243
|
+
}
|
|
3244
|
+
}
|
|
3245
|
+
this.update((state) => {
|
|
3246
|
+
for (const [pid, slice] of byProvider) {
|
|
3247
|
+
const key = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_marketCacheKey).call(this, pid, __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_providerIsTestnet).call(this, pid));
|
|
3248
|
+
state.cachedMarketDataByProvider[key] = {
|
|
3249
|
+
data: slice,
|
|
3250
|
+
timestamp: ts,
|
|
3251
|
+
};
|
|
3252
|
+
}
|
|
3253
|
+
// Write aggregated sentinel so the staleness guard sees it
|
|
3254
|
+
state.cachedMarketDataByProvider[cacheKey] = {
|
|
3255
|
+
data: [], // sentinel — real data is in per-provider keys
|
|
3256
|
+
timestamp: ts,
|
|
3257
|
+
};
|
|
3258
|
+
});
|
|
3259
|
+
}
|
|
3260
|
+
else {
|
|
3261
|
+
this.update((state) => {
|
|
3262
|
+
state.cachedMarketDataByProvider[cacheKey] = {
|
|
3263
|
+
data,
|
|
3264
|
+
timestamp: ts,
|
|
3265
|
+
};
|
|
3266
|
+
});
|
|
3267
|
+
}
|
|
3016
3268
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: Market data preloaded', {
|
|
3017
3269
|
marketCount: data.length,
|
|
3018
3270
|
});
|
|
@@ -3056,10 +3308,16 @@ async function _PerpsController_performUserDataPreload() {
|
|
|
3056
3308
|
return;
|
|
3057
3309
|
}
|
|
3058
3310
|
const userAddress = evmAccount.address;
|
|
3311
|
+
// Determine actual provider (same logic as market preload)
|
|
3312
|
+
const actualProviderId = this.activeProviderInstance
|
|
3313
|
+
? this.state.activeProvider // includes 'aggregated'
|
|
3314
|
+
: 'hyperliquid';
|
|
3315
|
+
const userCacheKey = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_marketCacheKey).call(this, actualProviderId, __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_providerIsTestnet).call(this, actualProviderId));
|
|
3059
3316
|
// Skip if cache is fresh and for same account
|
|
3060
3317
|
const now = Date.now();
|
|
3061
|
-
|
|
3062
|
-
|
|
3318
|
+
const existingEntry = this.state.cachedUserDataByProvider[userCacheKey];
|
|
3319
|
+
if (existingEntry?.address === userAddress &&
|
|
3320
|
+
now - existingEntry.timestamp < __classPrivateFieldGet(_a, _a, "f", _PerpsController_preloadGuardMs)) {
|
|
3063
3321
|
return;
|
|
3064
3322
|
}
|
|
3065
3323
|
// Skip standalone REST polling when WebSocket is connected — live data is streaming
|
|
@@ -3090,13 +3348,60 @@ async function _PerpsController_performUserDataPreload() {
|
|
|
3090
3348
|
this.getOpenOrders({ standalone: true, userAddress }),
|
|
3091
3349
|
this.getAccountState({ standalone: true, userAddress }),
|
|
3092
3350
|
]);
|
|
3093
|
-
this.
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3351
|
+
if (this.state.activeProvider === 'aggregated' &&
|
|
3352
|
+
this.activeProviderInstance) {
|
|
3353
|
+
// Split by providerId and write one cache entry per provider key
|
|
3354
|
+
// (mirrors the market-data preload pattern at ~line 2976)
|
|
3355
|
+
const ts = Date.now();
|
|
3356
|
+
const fallbackProviderId = 'hyperliquid'; // default for items missing providerId
|
|
3357
|
+
const byProvider = new Map();
|
|
3358
|
+
const ensureBucket = (pid) => {
|
|
3359
|
+
let bucket = byProvider.get(pid);
|
|
3360
|
+
if (!bucket) {
|
|
3361
|
+
bucket = { positions: [], orders: [], accountState: null };
|
|
3362
|
+
byProvider.set(pid, bucket);
|
|
3363
|
+
}
|
|
3364
|
+
return bucket;
|
|
3365
|
+
};
|
|
3366
|
+
for (const pos of positions) {
|
|
3367
|
+
ensureBucket(pos.providerId ?? fallbackProviderId).positions.push(pos);
|
|
3368
|
+
}
|
|
3369
|
+
for (const order of orders) {
|
|
3370
|
+
ensureBucket(order.providerId ?? fallbackProviderId).orders.push(order);
|
|
3371
|
+
}
|
|
3372
|
+
// AccountState — assign to its provider bucket
|
|
3373
|
+
ensureBucket(accountState.providerId ?? fallbackProviderId).accountState = accountState;
|
|
3374
|
+
this.update((state) => {
|
|
3375
|
+
for (const [pid, data] of byProvider) {
|
|
3376
|
+
const key = __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_marketCacheKey).call(this, pid, __classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_providerIsTestnet).call(this, pid));
|
|
3377
|
+
state.cachedUserDataByProvider[key] = {
|
|
3378
|
+
...data,
|
|
3379
|
+
timestamp: ts,
|
|
3380
|
+
address: userAddress,
|
|
3381
|
+
};
|
|
3382
|
+
}
|
|
3383
|
+
// Write aggregated sentinel so the staleness guard sees it
|
|
3384
|
+
state.cachedUserDataByProvider[userCacheKey] = {
|
|
3385
|
+
positions: [],
|
|
3386
|
+
orders: [],
|
|
3387
|
+
accountState: null,
|
|
3388
|
+
timestamp: ts,
|
|
3389
|
+
address: userAddress,
|
|
3390
|
+
};
|
|
3391
|
+
});
|
|
3392
|
+
}
|
|
3393
|
+
else {
|
|
3394
|
+
// Single provider — store directly under its key
|
|
3395
|
+
this.update((state) => {
|
|
3396
|
+
state.cachedUserDataByProvider[userCacheKey] = {
|
|
3397
|
+
positions,
|
|
3398
|
+
orders,
|
|
3399
|
+
accountState,
|
|
3400
|
+
timestamp: Date.now(),
|
|
3401
|
+
address: userAddress,
|
|
3402
|
+
};
|
|
3403
|
+
});
|
|
3404
|
+
}
|
|
3100
3405
|
__classPrivateFieldGet(this, _PerpsController_instances, "m", _PerpsController_debugLog).call(this, 'PerpsController: User data preloaded', {
|
|
3101
3406
|
positionCount: positions.length,
|
|
3102
3407
|
orderCount: orders.length,
|