@metamask-previews/perps-controller 6.2.0-preview-e43dfcb → 6.2.0-preview-c7c3c44
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 +12 -0
- package/dist/PerpsController-method-action-types.cjs.map +1 -1
- package/dist/PerpsController-method-action-types.d.cts +19 -1
- package/dist/PerpsController-method-action-types.d.cts.map +1 -1
- package/dist/PerpsController-method-action-types.d.mts +19 -1
- package/dist/PerpsController-method-action-types.d.mts.map +1 -1
- package/dist/PerpsController-method-action-types.mjs.map +1 -1
- package/dist/PerpsController.cjs +43 -5
- package/dist/PerpsController.cjs.map +1 -1
- package/dist/PerpsController.d.cts +13 -0
- package/dist/PerpsController.d.cts.map +1 -1
- package/dist/PerpsController.d.mts +13 -0
- package/dist/PerpsController.d.mts.map +1 -1
- package/dist/PerpsController.mjs +45 -7
- package/dist/PerpsController.mjs.map +1 -1
- package/dist/constants/eventNames.cjs +22 -0
- package/dist/constants/eventNames.cjs.map +1 -1
- package/dist/constants/eventNames.d.cts +15 -0
- package/dist/constants/eventNames.d.cts.map +1 -1
- package/dist/constants/eventNames.d.mts +15 -0
- package/dist/constants/eventNames.d.mts.map +1 -1
- package/dist/constants/eventNames.mjs +22 -0
- package/dist/constants/eventNames.mjs.map +1 -1
- package/dist/constants/perpsConfig.cjs +22 -1
- package/dist/constants/perpsConfig.cjs.map +1 -1
- package/dist/constants/perpsConfig.d.cts +11 -0
- package/dist/constants/perpsConfig.d.cts.map +1 -1
- package/dist/constants/perpsConfig.d.mts +11 -0
- package/dist/constants/perpsConfig.d.mts.map +1 -1
- package/dist/constants/perpsConfig.mjs +21 -0
- package/dist/constants/perpsConfig.mjs.map +1 -1
- package/dist/index.cjs +4 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/providers/HyperLiquidProvider.cjs +178 -40
- package/dist/providers/HyperLiquidProvider.cjs.map +1 -1
- package/dist/providers/HyperLiquidProvider.d.cts.map +1 -1
- package/dist/providers/HyperLiquidProvider.d.mts.map +1 -1
- package/dist/providers/HyperLiquidProvider.mjs +179 -41
- package/dist/providers/HyperLiquidProvider.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/DataLakeService.cjs +1 -1
- package/dist/services/DataLakeService.cjs.map +1 -1
- package/dist/services/DataLakeService.d.cts.map +1 -1
- package/dist/services/DataLakeService.d.mts.map +1 -1
- package/dist/services/DataLakeService.mjs +2 -2
- package/dist/services/DataLakeService.mjs.map +1 -1
- package/dist/services/DepositService.cjs +2 -2
- 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 +3 -3
- package/dist/services/DepositService.mjs.map +1 -1
- package/dist/services/HyperLiquidWalletService.cjs +5 -5
- package/dist/services/HyperLiquidWalletService.cjs.map +1 -1
- package/dist/services/HyperLiquidWalletService.d.cts.map +1 -1
- package/dist/services/HyperLiquidWalletService.d.mts.map +1 -1
- package/dist/services/HyperLiquidWalletService.mjs +6 -6
- package/dist/services/HyperLiquidWalletService.mjs.map +1 -1
- package/dist/services/RewardsIntegrationService.cjs +1 -1
- package/dist/services/RewardsIntegrationService.cjs.map +1 -1
- package/dist/services/RewardsIntegrationService.d.cts.map +1 -1
- package/dist/services/RewardsIntegrationService.d.mts.map +1 -1
- package/dist/services/RewardsIntegrationService.mjs +2 -2
- package/dist/services/RewardsIntegrationService.mjs.map +1 -1
- package/dist/services/TradingReadinessCache.cjs +42 -2
- package/dist/services/TradingReadinessCache.cjs.map +1 -1
- package/dist/services/TradingReadinessCache.d.cts +29 -0
- package/dist/services/TradingReadinessCache.d.cts.map +1 -1
- package/dist/services/TradingReadinessCache.d.mts +29 -0
- package/dist/services/TradingReadinessCache.d.mts.map +1 -1
- package/dist/services/TradingReadinessCache.mjs +42 -2
- package/dist/services/TradingReadinessCache.mjs.map +1 -1
- package/dist/services/TradingService.cjs +27 -1
- package/dist/services/TradingService.cjs.map +1 -1
- package/dist/services/TradingService.d.cts +3 -1
- package/dist/services/TradingService.d.cts.map +1 -1
- package/dist/services/TradingService.d.mts +3 -1
- package/dist/services/TradingService.d.mts.map +1 -1
- package/dist/services/TradingService.mjs +27 -1
- package/dist/services/TradingService.mjs.map +1 -1
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.d.cts +10 -1
- package/dist/types/index.d.cts.map +1 -1
- package/dist/types/index.d.mts +10 -1
- 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 +3 -2
- package/dist/types/messenger.d.cts.map +1 -1
- package/dist/types/messenger.d.mts +3 -2
- package/dist/types/messenger.d.mts.map +1 -1
- package/dist/types/messenger.mjs.map +1 -1
- package/dist/utils/accountUtils.cjs +38 -1
- package/dist/utils/accountUtils.cjs.map +1 -1
- package/dist/utils/accountUtils.d.cts +8 -0
- package/dist/utils/accountUtils.d.cts.map +1 -1
- package/dist/utils/accountUtils.d.mts +8 -0
- package/dist/utils/accountUtils.d.mts.map +1 -1
- package/dist/utils/accountUtils.mjs +35 -0
- package/dist/utils/accountUtils.mjs.map +1 -1
- package/dist/utils/errorUtils.cjs +15 -1
- package/dist/utils/errorUtils.cjs.map +1 -1
- package/dist/utils/errorUtils.d.cts +10 -0
- package/dist/utils/errorUtils.d.cts.map +1 -1
- package/dist/utils/errorUtils.d.mts +10 -0
- package/dist/utils/errorUtils.d.mts.map +1 -1
- package/dist/utils/errorUtils.mjs +13 -0
- package/dist/utils/errorUtils.mjs.map +1 -1
- package/dist/utils/orderCalculations.cjs +7 -3
- package/dist/utils/orderCalculations.cjs.map +1 -1
- package/dist/utils/orderCalculations.d.cts +1 -1
- package/dist/utils/orderCalculations.d.cts.map +1 -1
- package/dist/utils/orderCalculations.d.mts +1 -1
- package/dist/utils/orderCalculations.d.mts.map +1 -1
- package/dist/utils/orderCalculations.mjs +7 -3
- package/dist/utils/orderCalculations.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -25,16 +25,23 @@
|
|
|
25
25
|
type SigningOperationState = {
|
|
26
26
|
attempted: boolean;
|
|
27
27
|
success: boolean;
|
|
28
|
+
reason?: 'no_hl_account' | 'user_rejected' | 'transient';
|
|
29
|
+
};
|
|
30
|
+
type WalletRegistrationState = {
|
|
31
|
+
known: boolean;
|
|
32
|
+
registered: boolean;
|
|
28
33
|
};
|
|
29
34
|
type PerpsSigningCacheEntry = {
|
|
30
35
|
unifiedAccount: SigningOperationState;
|
|
31
36
|
builderFee: SigningOperationState;
|
|
32
37
|
referral: SigningOperationState;
|
|
38
|
+
walletRegistered: WalletRegistrationState;
|
|
33
39
|
timestamp: number;
|
|
34
40
|
};
|
|
35
41
|
type TradingReadinessCacheEntry = {
|
|
36
42
|
attempted: boolean;
|
|
37
43
|
enabled: boolean;
|
|
44
|
+
reason?: 'no_hl_account' | 'user_rejected' | 'transient';
|
|
38
45
|
timestamp: number;
|
|
39
46
|
};
|
|
40
47
|
declare class PerpsSigningCacheManager {
|
|
@@ -76,10 +83,12 @@ declare class PerpsSigningCacheManager {
|
|
|
76
83
|
* @param data - The transaction data payload.
|
|
77
84
|
* @param data.attempted - Whether the operation was attempted.
|
|
78
85
|
* @param data.enabled - Whether the feature is enabled.
|
|
86
|
+
* @param data.reason - Optional discriminator explaining a non-success outcome.
|
|
79
87
|
*/
|
|
80
88
|
set(network: 'mainnet' | 'testnet', userAddress: string, data: {
|
|
81
89
|
attempted: boolean;
|
|
82
90
|
enabled: boolean;
|
|
91
|
+
reason?: 'no_hl_account' | 'user_rejected' | 'transient';
|
|
83
92
|
}): void;
|
|
84
93
|
/**
|
|
85
94
|
* Check if builder fee approval was attempted
|
|
@@ -121,6 +130,26 @@ declare class PerpsSigningCacheManager {
|
|
|
121
130
|
* @param userAddress - The user's wallet address.
|
|
122
131
|
*/
|
|
123
132
|
clearUnifiedAccount(network: 'mainnet' | 'testnet', userAddress: string): void;
|
|
133
|
+
/**
|
|
134
|
+
* Read the wallet's Hyperliquid registration signal.
|
|
135
|
+
*
|
|
136
|
+
* @param network - The network environment.
|
|
137
|
+
* @param userAddress - The user's wallet address.
|
|
138
|
+
* @returns The current signal, or undefined if no entry exists.
|
|
139
|
+
*/
|
|
140
|
+
getWalletRegistered(network: 'mainnet' | 'testnet', userAddress: string): WalletRegistrationState | undefined;
|
|
141
|
+
/**
|
|
142
|
+
* Record whether the wallet has been observed on Hyperliquid. Once
|
|
143
|
+
* `registered=true` is set, it stays true for the session — the goal
|
|
144
|
+
* is to skip doomed exchange writes for unfunded wallets, not to
|
|
145
|
+
* gate them after they fund.
|
|
146
|
+
*
|
|
147
|
+
* @param network - The network environment.
|
|
148
|
+
* @param userAddress - The user's wallet address.
|
|
149
|
+
* @param registered - True once any evidence (clearinghouseState balance,
|
|
150
|
+
* userFills, successful deposit, ...) confirms the wallet exists on HL.
|
|
151
|
+
*/
|
|
152
|
+
setWalletRegistered(network: 'mainnet' | 'testnet', userAddress: string, registered: boolean): void;
|
|
124
153
|
/**
|
|
125
154
|
* Clear only builder fee state for a specific network and user address
|
|
126
155
|
* This preserves unified account and referral states
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TradingReadinessCache.d.cts","sourceRoot":"","sources":["../../src/services/TradingReadinessCache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,KAAK,qBAAqB,GAAG;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"TradingReadinessCache.d.cts","sourceRoot":"","sources":["../../src/services/TradingReadinessCache.ts"],"names":[],"mappings":"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"}
|
|
@@ -25,16 +25,23 @@
|
|
|
25
25
|
type SigningOperationState = {
|
|
26
26
|
attempted: boolean;
|
|
27
27
|
success: boolean;
|
|
28
|
+
reason?: 'no_hl_account' | 'user_rejected' | 'transient';
|
|
29
|
+
};
|
|
30
|
+
type WalletRegistrationState = {
|
|
31
|
+
known: boolean;
|
|
32
|
+
registered: boolean;
|
|
28
33
|
};
|
|
29
34
|
type PerpsSigningCacheEntry = {
|
|
30
35
|
unifiedAccount: SigningOperationState;
|
|
31
36
|
builderFee: SigningOperationState;
|
|
32
37
|
referral: SigningOperationState;
|
|
38
|
+
walletRegistered: WalletRegistrationState;
|
|
33
39
|
timestamp: number;
|
|
34
40
|
};
|
|
35
41
|
type TradingReadinessCacheEntry = {
|
|
36
42
|
attempted: boolean;
|
|
37
43
|
enabled: boolean;
|
|
44
|
+
reason?: 'no_hl_account' | 'user_rejected' | 'transient';
|
|
38
45
|
timestamp: number;
|
|
39
46
|
};
|
|
40
47
|
declare class PerpsSigningCacheManager {
|
|
@@ -76,10 +83,12 @@ declare class PerpsSigningCacheManager {
|
|
|
76
83
|
* @param data - The transaction data payload.
|
|
77
84
|
* @param data.attempted - Whether the operation was attempted.
|
|
78
85
|
* @param data.enabled - Whether the feature is enabled.
|
|
86
|
+
* @param data.reason - Optional discriminator explaining a non-success outcome.
|
|
79
87
|
*/
|
|
80
88
|
set(network: 'mainnet' | 'testnet', userAddress: string, data: {
|
|
81
89
|
attempted: boolean;
|
|
82
90
|
enabled: boolean;
|
|
91
|
+
reason?: 'no_hl_account' | 'user_rejected' | 'transient';
|
|
83
92
|
}): void;
|
|
84
93
|
/**
|
|
85
94
|
* Check if builder fee approval was attempted
|
|
@@ -121,6 +130,26 @@ declare class PerpsSigningCacheManager {
|
|
|
121
130
|
* @param userAddress - The user's wallet address.
|
|
122
131
|
*/
|
|
123
132
|
clearUnifiedAccount(network: 'mainnet' | 'testnet', userAddress: string): void;
|
|
133
|
+
/**
|
|
134
|
+
* Read the wallet's Hyperliquid registration signal.
|
|
135
|
+
*
|
|
136
|
+
* @param network - The network environment.
|
|
137
|
+
* @param userAddress - The user's wallet address.
|
|
138
|
+
* @returns The current signal, or undefined if no entry exists.
|
|
139
|
+
*/
|
|
140
|
+
getWalletRegistered(network: 'mainnet' | 'testnet', userAddress: string): WalletRegistrationState | undefined;
|
|
141
|
+
/**
|
|
142
|
+
* Record whether the wallet has been observed on Hyperliquid. Once
|
|
143
|
+
* `registered=true` is set, it stays true for the session — the goal
|
|
144
|
+
* is to skip doomed exchange writes for unfunded wallets, not to
|
|
145
|
+
* gate them after they fund.
|
|
146
|
+
*
|
|
147
|
+
* @param network - The network environment.
|
|
148
|
+
* @param userAddress - The user's wallet address.
|
|
149
|
+
* @param registered - True once any evidence (clearinghouseState balance,
|
|
150
|
+
* userFills, successful deposit, ...) confirms the wallet exists on HL.
|
|
151
|
+
*/
|
|
152
|
+
setWalletRegistered(network: 'mainnet' | 'testnet', userAddress: string, registered: boolean): void;
|
|
124
153
|
/**
|
|
125
154
|
* Clear only builder fee state for a specific network and user address
|
|
126
155
|
* This preserves unified account and referral states
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TradingReadinessCache.d.mts","sourceRoot":"","sources":["../../src/services/TradingReadinessCache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,KAAK,qBAAqB,GAAG;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"TradingReadinessCache.d.mts","sourceRoot":"","sources":["../../src/services/TradingReadinessCache.ts"],"names":[],"mappings":"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"}
|
|
@@ -100,6 +100,7 @@ class PerpsSigningCacheManager {
|
|
|
100
100
|
return {
|
|
101
101
|
attempted: entry.unifiedAccount.attempted,
|
|
102
102
|
enabled: entry.unifiedAccount.success,
|
|
103
|
+
reason: entry.unifiedAccount.reason,
|
|
103
104
|
timestamp: entry.timestamp,
|
|
104
105
|
};
|
|
105
106
|
}
|
|
@@ -111,10 +112,15 @@ class PerpsSigningCacheManager {
|
|
|
111
112
|
* @param data - The transaction data payload.
|
|
112
113
|
* @param data.attempted - Whether the operation was attempted.
|
|
113
114
|
* @param data.enabled - Whether the feature is enabled.
|
|
115
|
+
* @param data.reason - Optional discriminator explaining a non-success outcome.
|
|
114
116
|
*/
|
|
115
117
|
set(network, userAddress, data) {
|
|
116
118
|
const entry = __classPrivateFieldGet(this, _PerpsSigningCacheManager_instances, "m", _PerpsSigningCacheManager_getOrCreateEntry).call(this, network, userAddress);
|
|
117
|
-
entry.unifiedAccount = {
|
|
119
|
+
entry.unifiedAccount = {
|
|
120
|
+
attempted: data.attempted,
|
|
121
|
+
success: data.enabled,
|
|
122
|
+
reason: data.reason,
|
|
123
|
+
};
|
|
118
124
|
entry.timestamp = Date.now();
|
|
119
125
|
}
|
|
120
126
|
// ===== Builder Fee Methods =====
|
|
@@ -183,6 +189,38 @@ class PerpsSigningCacheManager {
|
|
|
183
189
|
entry.timestamp = Date.now();
|
|
184
190
|
}
|
|
185
191
|
}
|
|
192
|
+
// ===== Wallet Registration Methods =====
|
|
193
|
+
/**
|
|
194
|
+
* Read the wallet's Hyperliquid registration signal.
|
|
195
|
+
*
|
|
196
|
+
* @param network - The network environment.
|
|
197
|
+
* @param userAddress - The user's wallet address.
|
|
198
|
+
* @returns The current signal, or undefined if no entry exists.
|
|
199
|
+
*/
|
|
200
|
+
getWalletRegistered(network, userAddress) {
|
|
201
|
+
const key = __classPrivateFieldGet(this, _PerpsSigningCacheManager_instances, "m", _PerpsSigningCacheManager_getCacheKey).call(this, network, userAddress);
|
|
202
|
+
return __classPrivateFieldGet(this, _PerpsSigningCacheManager_cache, "f").get(key)?.walletRegistered;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Record whether the wallet has been observed on Hyperliquid. Once
|
|
206
|
+
* `registered=true` is set, it stays true for the session — the goal
|
|
207
|
+
* is to skip doomed exchange writes for unfunded wallets, not to
|
|
208
|
+
* gate them after they fund.
|
|
209
|
+
*
|
|
210
|
+
* @param network - The network environment.
|
|
211
|
+
* @param userAddress - The user's wallet address.
|
|
212
|
+
* @param registered - True once any evidence (clearinghouseState balance,
|
|
213
|
+
* userFills, successful deposit, ...) confirms the wallet exists on HL.
|
|
214
|
+
*/
|
|
215
|
+
setWalletRegistered(network, userAddress, registered) {
|
|
216
|
+
const entry = __classPrivateFieldGet(this, _PerpsSigningCacheManager_instances, "m", _PerpsSigningCacheManager_getOrCreateEntry).call(this, network, userAddress);
|
|
217
|
+
if (entry.walletRegistered.registered && !registered) {
|
|
218
|
+
// Monotonic: once registered, never demote.
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
entry.walletRegistered = { known: true, registered };
|
|
222
|
+
entry.timestamp = Date.now();
|
|
223
|
+
}
|
|
186
224
|
/**
|
|
187
225
|
* Clear only builder fee state for a specific network and user address
|
|
188
226
|
* This preserves unified account and referral states
|
|
@@ -257,7 +295,8 @@ class PerpsSigningCacheManager {
|
|
|
257
295
|
__classPrivateFieldGet(this, _PerpsSigningCacheManager_cache, "f").forEach((entry, key) => {
|
|
258
296
|
entries.push(`${key}: unified=${entry.unifiedAccount.attempted}/${entry.unifiedAccount.success}, ` +
|
|
259
297
|
`builder=${entry.builderFee.attempted}/${entry.builderFee.success}, ` +
|
|
260
|
-
`referral=${entry.referral.attempted}/${entry.referral.success}`
|
|
298
|
+
`referral=${entry.referral.attempted}/${entry.referral.success}, ` +
|
|
299
|
+
`walletRegistered=${entry.walletRegistered.known}/${entry.walletRegistered.registered}`);
|
|
261
300
|
});
|
|
262
301
|
return entries.join('\n') || '(empty)';
|
|
263
302
|
}
|
|
@@ -272,6 +311,7 @@ _a = PerpsSigningCacheManager, _PerpsSigningCacheManager_cache = new WeakMap(),
|
|
|
272
311
|
unifiedAccount: { attempted: false, success: false },
|
|
273
312
|
builderFee: { attempted: false, success: false },
|
|
274
313
|
referral: { attempted: false, success: false },
|
|
314
|
+
walletRegistered: { known: false, registered: false },
|
|
275
315
|
timestamp: Date.now(),
|
|
276
316
|
};
|
|
277
317
|
__classPrivateFieldGet(this, _PerpsSigningCacheManager_cache, "f").set(key, entry);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TradingReadinessCache.mjs","sourceRoot":"","sources":["../../src/services/TradingReadinessCache.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Global singleton cache for Perps signing operations\n *\n * This cache persists across provider reconnections to prevent repeated\n * signing requests for hardware wallets. Critical for preventing repeated\n * hardware wallet signing prompts.\n *\n * Cache is intentionally kept separate from provider instances because providers\n * are recreated on account/network changes, which would reset instance-level caches.\n *\n * Tracks three signing operations:\n * 1. Unified Account enablement (one-time, replaces deprecated DEX abstraction)\n * 2. Builder Fee approval (required for trading)\n * 3. Referral code setup (one-time per account)\n *\n * Cache Structure:\n * - Key: `network:userAddress` (e.g., \"mainnet:0x123...\")\n * - Value: { unifiedAccount, builderFee, referral, timestamp }\n *\n * Lifecycle:\n * - Cache persists throughout app session\n * - Individual entries can be cleared per user/network\n * - Full cache can be cleared on app restart or explicit user action\n */\n\ntype SigningOperationState = {\n attempted: boolean; // Whether we've attempted this operation\n success: boolean; // Whether it succeeded (only valid if attempted=true)\n};\n\ntype PerpsSigningCacheEntry = {\n unifiedAccount: SigningOperationState;\n builderFee: SigningOperationState;\n referral: SigningOperationState;\n timestamp: number; // When this entry was last updated\n};\n\n// Legacy interface for backward compatibility\ntype TradingReadinessCacheEntry = {\n attempted: boolean;\n enabled: boolean;\n timestamp: number;\n};\n\nclass PerpsSigningCacheManager {\n static #instance: PerpsSigningCacheManager;\n\n readonly #cache: Map<string, PerpsSigningCacheEntry> = new Map();\n\n // Global in-flight locks to prevent concurrent signing attempts across providers\n // Key: operationType:network:userAddress, Value: Promise that resolves when operation completes\n readonly #inFlightOperations: Map<string, Promise<void>> = new Map();\n\n // Singleton: use getInstance() instead of new\n protected constructor() {\n // Protected constructor for singleton\n }\n\n public static getInstance(): PerpsSigningCacheManager {\n PerpsSigningCacheManager.#instance ??= new PerpsSigningCacheManager();\n return PerpsSigningCacheManager.#instance;\n }\n\n // ===== In-Flight Lock Methods =====\n\n /**\n * Check if an operation is currently in-flight for this user/network\n *\n * @param operationType - The type of operation being performed.\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n * @returns The resulting string value.\n */\n public isInFlight(\n operationType: 'unifiedAccount' | 'builderFee' | 'referral',\n network: 'mainnet' | 'testnet',\n userAddress: string,\n ): Promise<void> | undefined {\n const key = `${operationType}:${network}:${userAddress.toLowerCase()}`;\n return this.#inFlightOperations.get(key);\n }\n\n /**\n * Set an operation as in-flight\n * Returns a function to call when operation completes\n *\n * @param operationType - The type of operation being performed.\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n * @returns The resulting string value.\n */\n public setInFlight(\n operationType: 'unifiedAccount' | 'builderFee' | 'referral',\n network: 'mainnet' | 'testnet',\n userAddress: string,\n ): () => void {\n const key = `${operationType}:${network}:${userAddress.toLowerCase()}`;\n let resolvePromise: () => void;\n const promise = new Promise<void>((resolve) => {\n resolvePromise = resolve;\n });\n this.#inFlightOperations.set(key, promise);\n return () => {\n this.#inFlightOperations.delete(key);\n resolvePromise();\n };\n }\n\n #getCacheKey(network: 'mainnet' | 'testnet', userAddress: string): string {\n return `${network}:${userAddress.toLowerCase()}`;\n }\n\n #getOrCreateEntry(\n network: 'mainnet' | 'testnet',\n userAddress: string,\n ): PerpsSigningCacheEntry {\n const key = this.#getCacheKey(network, userAddress);\n let entry = this.#cache.get(key);\n if (!entry) {\n entry = {\n unifiedAccount: { attempted: false, success: false },\n builderFee: { attempted: false, success: false },\n referral: { attempted: false, success: false },\n timestamp: Date.now(),\n };\n this.#cache.set(key, entry);\n }\n return entry;\n }\n\n // ===== Unified Account Methods =====\n\n /**\n * Get unified account cache entry (legacy compatibility)\n *\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n * @returns The resulting string value.\n */\n public get(\n network: 'mainnet' | 'testnet',\n userAddress: string,\n ): TradingReadinessCacheEntry | undefined {\n const key = this.#getCacheKey(network, userAddress);\n const entry = this.#cache.get(key);\n if (!entry) {\n return undefined;\n }\n return {\n attempted: entry.unifiedAccount.attempted,\n enabled: entry.unifiedAccount.success,\n timestamp: entry.timestamp,\n };\n }\n\n /**\n * Set unified account cache entry (legacy compatibility)\n *\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n * @param data - The transaction data payload.\n * @param data.attempted - Whether the operation was attempted.\n * @param data.enabled - Whether the feature is enabled.\n */\n public set(\n network: 'mainnet' | 'testnet',\n userAddress: string,\n data: { attempted: boolean; enabled: boolean },\n ): void {\n const entry = this.#getOrCreateEntry(network, userAddress);\n entry.unifiedAccount = { attempted: data.attempted, success: data.enabled };\n entry.timestamp = Date.now();\n }\n\n // ===== Builder Fee Methods =====\n\n /**\n * Check if builder fee approval was attempted\n *\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n * @returns The resulting string value.\n */\n public getBuilderFee(\n network: 'mainnet' | 'testnet',\n userAddress: string,\n ): SigningOperationState | undefined {\n const key = this.#getCacheKey(network, userAddress);\n const entry = this.#cache.get(key);\n return entry?.builderFee;\n }\n\n /**\n * Set builder fee approval state\n *\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n * @param state - The current state.\n */\n public setBuilderFee(\n network: 'mainnet' | 'testnet',\n userAddress: string,\n state: SigningOperationState,\n ): void {\n const entry = this.#getOrCreateEntry(network, userAddress);\n entry.builderFee = state;\n entry.timestamp = Date.now();\n }\n\n // ===== Referral Methods =====\n\n /**\n * Check if referral setup was attempted\n *\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n * @returns The resulting string value.\n */\n public getReferral(\n network: 'mainnet' | 'testnet',\n userAddress: string,\n ): SigningOperationState | undefined {\n const key = this.#getCacheKey(network, userAddress);\n const entry = this.#cache.get(key);\n return entry?.referral;\n }\n\n /**\n * Set referral setup state\n *\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n * @param state - The current state.\n */\n public setReferral(\n network: 'mainnet' | 'testnet',\n userAddress: string,\n state: SigningOperationState,\n ): void {\n const entry = this.#getOrCreateEntry(network, userAddress);\n entry.referral = state;\n entry.timestamp = Date.now();\n }\n\n // ===== General Methods =====\n\n /**\n * Clear only unified account state for a specific network and user address\n * This preserves builder fee and referral states\n *\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n */\n public clearUnifiedAccount(\n network: 'mainnet' | 'testnet',\n userAddress: string,\n ): void {\n const key = this.#getCacheKey(network, userAddress);\n const entry = this.#cache.get(key);\n if (entry) {\n entry.unifiedAccount = { attempted: false, success: false };\n entry.timestamp = Date.now();\n }\n }\n\n /**\n * Clear only builder fee state for a specific network and user address\n * This preserves unified account and referral states\n *\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n */\n public clearBuilderFee(\n network: 'mainnet' | 'testnet',\n userAddress: string,\n ): void {\n const key = this.#getCacheKey(network, userAddress);\n const entry = this.#cache.get(key);\n if (entry) {\n entry.builderFee = { attempted: false, success: false };\n entry.timestamp = Date.now();\n }\n }\n\n /**\n * Clear only referral state for a specific network and user address\n * This preserves unified account and builder fee states\n *\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n */\n public clearReferral(\n network: 'mainnet' | 'testnet',\n userAddress: string,\n ): void {\n const key = this.#getCacheKey(network, userAddress);\n const entry = this.#cache.get(key);\n if (entry) {\n entry.referral = { attempted: false, success: false };\n entry.timestamp = Date.now();\n }\n }\n\n /**\n * Clear entire cache entry for a specific network and user address\n * WARNING: This clears ALL signing operation states (unifiedAccount, builderFee, referral)\n *\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n */\n public clear(network: 'mainnet' | 'testnet', userAddress: string): void {\n const key = this.#getCacheKey(network, userAddress);\n this.#cache.delete(key);\n }\n\n /**\n * Clear all cache entries\n * WARNING: This clears ALL signing operation states for ALL users\n */\n public clearAll(): void {\n this.#cache.clear();\n }\n\n /**\n * Get all cache entries (for debugging)\n *\n * @returns The result of the operation.\n */\n public getAll(): Map<string, PerpsSigningCacheEntry> {\n return new Map(this.#cache);\n }\n\n /**\n * Get cache size (for debugging)\n *\n * @returns The resulting numeric value.\n */\n public size(): number {\n return this.#cache.size;\n }\n\n /**\n * Get full cache state for debugging\n *\n * @returns The resulting string value.\n */\n public debugState(): string {\n const entries: string[] = [];\n this.#cache.forEach((entry, key) => {\n entries.push(\n `${key}: unified=${entry.unifiedAccount.attempted}/${entry.unifiedAccount.success}, ` +\n `builder=${entry.builderFee.attempted}/${entry.builderFee.success}, ` +\n `referral=${entry.referral.attempted}/${entry.referral.success}`,\n );\n });\n return entries.join('\\n') || '(empty)';\n }\n}\n\n// Export singleton instance with backward-compatible name\nexport const TradingReadinessCache = PerpsSigningCacheManager.getInstance();\n\n// Export with new name for clarity\nexport const PerpsSigningCache = PerpsSigningCacheManager.getInstance();\n"]}
|
|
1
|
+
{"version":3,"file":"TradingReadinessCache.mjs","sourceRoot":"","sources":["../../src/services/TradingReadinessCache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;;;;;;;;;;;;;AAmCH,MAAM,wBAAwB;IAS5B,8CAA8C;IAC9C;;QAPS,0CAA8C,IAAI,GAAG,EAAE,EAAC;QAEjE,iFAAiF;QACjF,gGAAgG;QACvF,uDAAkD,IAAI,GAAG,EAAE,EAAC;QAInE,sCAAsC;IACxC,CAAC;IAEM,MAAM,CAAC,WAAW;;QACvB,+GAAuC,IAAI,EAAwB,EAAE,0CAAA,CAAC;QACtE,OAAO,uBAAA,EAAwB,8CAAU,CAAC;IAC5C,CAAC;IAED,qCAAqC;IAErC;;;;;;;OAOG;IACI,UAAU,CACf,aAA2D,EAC3D,OAA8B,EAC9B,WAAmB;QAEnB,MAAM,GAAG,GAAG,GAAG,aAAa,IAAI,OAAO,IAAI,WAAW,CAAC,WAAW,EAAE,EAAE,CAAC;QACvE,OAAO,uBAAA,IAAI,oDAAoB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;;;OAQG;IACI,WAAW,CAChB,aAA2D,EAC3D,OAA8B,EAC9B,WAAmB;QAEnB,MAAM,GAAG,GAAG,GAAG,aAAa,IAAI,OAAO,IAAI,WAAW,CAAC,WAAW,EAAE,EAAE,CAAC;QACvE,IAAI,cAA0B,CAAC;QAC/B,MAAM,OAAO,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAC5C,cAAc,GAAG,OAAO,CAAC;QAC3B,CAAC,CAAC,CAAC;QACH,uBAAA,IAAI,oDAAoB,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAC3C,OAAO,GAAG,EAAE;YACV,uBAAA,IAAI,oDAAoB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACrC,cAAc,EAAE,CAAC;QACnB,CAAC,CAAC;IACJ,CAAC;IAyBD,sCAAsC;IAEtC;;;;;;OAMG;IACI,GAAG,CACR,OAA8B,EAC9B,WAAmB;QAEnB,MAAM,GAAG,GAAG,uBAAA,IAAI,kFAAa,MAAjB,IAAI,EAAc,OAAO,EAAE,WAAW,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,uBAAA,IAAI,uCAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO;YACL,SAAS,EAAE,KAAK,CAAC,cAAc,CAAC,SAAS;YACzC,OAAO,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO;YACrC,MAAM,EAAE,KAAK,CAAC,cAAc,CAAC,MAAM;YACnC,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B,CAAC;IACJ,CAAC;IAED;;;;;;;;;OASG;IACI,GAAG,CACR,OAA8B,EAC9B,WAAmB,EACnB,IAIC;QAED,MAAM,KAAK,GAAG,uBAAA,IAAI,uFAAkB,MAAtB,IAAI,EAAmB,OAAO,EAAE,WAAW,CAAC,CAAC;QAC3D,KAAK,CAAC,cAAc,GAAG;YACrB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC;QACF,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC/B,CAAC;IAED,kCAAkC;IAElC;;;;;;OAMG;IACI,aAAa,CAClB,OAA8B,EAC9B,WAAmB;QAEnB,MAAM,GAAG,GAAG,uBAAA,IAAI,kFAAa,MAAjB,IAAI,EAAc,OAAO,EAAE,WAAW,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,uBAAA,IAAI,uCAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnC,OAAO,KAAK,EAAE,UAAU,CAAC;IAC3B,CAAC;IAED;;;;;;OAMG;IACI,aAAa,CAClB,OAA8B,EAC9B,WAAmB,EACnB,KAA4B;QAE5B,MAAM,KAAK,GAAG,uBAAA,IAAI,uFAAkB,MAAtB,IAAI,EAAmB,OAAO,EAAE,WAAW,CAAC,CAAC;QAC3D,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC;QACzB,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC/B,CAAC;IAED,+BAA+B;IAE/B;;;;;;OAMG;IACI,WAAW,CAChB,OAA8B,EAC9B,WAAmB;QAEnB,MAAM,GAAG,GAAG,uBAAA,IAAI,kFAAa,MAAjB,IAAI,EAAc,OAAO,EAAE,WAAW,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,uBAAA,IAAI,uCAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnC,OAAO,KAAK,EAAE,QAAQ,CAAC;IACzB,CAAC;IAED;;;;;;OAMG;IACI,WAAW,CAChB,OAA8B,EAC9B,WAAmB,EACnB,KAA4B;QAE5B,MAAM,KAAK,GAAG,uBAAA,IAAI,uFAAkB,MAAtB,IAAI,EAAmB,OAAO,EAAE,WAAW,CAAC,CAAC;QAC3D,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC;QACvB,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC/B,CAAC;IAED,8BAA8B;IAE9B;;;;;;OAMG;IACI,mBAAmB,CACxB,OAA8B,EAC9B,WAAmB;QAEnB,MAAM,GAAG,GAAG,uBAAA,IAAI,kFAAa,MAAjB,IAAI,EAAc,OAAO,EAAE,WAAW,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,uBAAA,IAAI,uCAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,CAAC,cAAc,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YAC5D,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,0CAA0C;IAE1C;;;;;;OAMG;IACI,mBAAmB,CACxB,OAA8B,EAC9B,WAAmB;QAEnB,MAAM,GAAG,GAAG,uBAAA,IAAI,kFAAa,MAAjB,IAAI,EAAc,OAAO,EAAE,WAAW,CAAC,CAAC;QACpD,OAAO,uBAAA,IAAI,uCAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,gBAAgB,CAAC;IAChD,CAAC;IAED;;;;;;;;;;OAUG;IACI,mBAAmB,CACxB,OAA8B,EAC9B,WAAmB,EACnB,UAAmB;QAEnB,MAAM,KAAK,GAAG,uBAAA,IAAI,uFAAkB,MAAtB,IAAI,EAAmB,OAAO,EAAE,WAAW,CAAC,CAAC;QAC3D,IAAI,KAAK,CAAC,gBAAgB,CAAC,UAAU,IAAI,CAAC,UAAU,EAAE,CAAC;YACrD,4CAA4C;YAC5C,OAAO;QACT,CAAC;QACD,KAAK,CAAC,gBAAgB,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;QACrD,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC/B,CAAC;IAED;;;;;;OAMG;IACI,eAAe,CACpB,OAA8B,EAC9B,WAAmB;QAEnB,MAAM,GAAG,GAAG,uBAAA,IAAI,kFAAa,MAAjB,IAAI,EAAc,OAAO,EAAE,WAAW,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,uBAAA,IAAI,uCAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,CAAC,UAAU,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YACxD,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC/B,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACI,aAAa,CAClB,OAA8B,EAC9B,WAAmB;QAEnB,MAAM,GAAG,GAAG,uBAAA,IAAI,kFAAa,MAAjB,IAAI,EAAc,OAAO,EAAE,WAAW,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,uBAAA,IAAI,uCAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,CAAC,QAAQ,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YACtD,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC/B,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,OAA8B,EAAE,WAAmB;QAC9D,MAAM,GAAG,GAAG,uBAAA,IAAI,kFAAa,MAAjB,IAAI,EAAc,OAAO,EAAE,WAAW,CAAC,CAAC;QACpD,uBAAA,IAAI,uCAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED;;;OAGG;IACI,QAAQ;QACb,uBAAA,IAAI,uCAAO,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC;IAED;;;;OAIG;IACI,MAAM;QACX,OAAO,IAAI,GAAG,CAAC,uBAAA,IAAI,uCAAO,CAAC,CAAC;IAC9B,CAAC;IAED;;;;OAIG;IACI,IAAI;QACT,OAAO,uBAAA,IAAI,uCAAO,CAAC,IAAI,CAAC;IAC1B,CAAC;IAED;;;;OAIG;IACI,UAAU;QACf,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,uBAAA,IAAI,uCAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;YACjC,OAAO,CAAC,IAAI,CACV,GAAG,GAAG,aAAa,KAAK,CAAC,cAAc,CAAC,SAAS,IAAI,KAAK,CAAC,cAAc,CAAC,OAAO,IAAI;gBACnF,WAAW,KAAK,CAAC,UAAU,CAAC,SAAS,IAAI,KAAK,CAAC,UAAU,CAAC,OAAO,IAAI;gBACrE,YAAY,KAAK,CAAC,QAAQ,CAAC,SAAS,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,IAAI;gBAClE,oBAAoB,KAAK,CAAC,gBAAgB,CAAC,KAAK,IAAI,KAAK,CAAC,gBAAgB,CAAC,UAAU,EAAE,CAC1F,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC;IACzC,CAAC;CACF;0RA/Sc,OAA8B,EAAE,WAAmB;IAC9D,OAAO,GAAG,OAAO,IAAI,WAAW,CAAC,WAAW,EAAE,EAAE,CAAC;AACnD,CAAC,mGAGC,OAA8B,EAC9B,WAAmB;IAEnB,MAAM,GAAG,GAAG,uBAAA,IAAI,kFAAa,MAAjB,IAAI,EAAc,OAAO,EAAE,WAAW,CAAC,CAAC;IACpD,IAAI,KAAK,GAAG,uBAAA,IAAI,uCAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG;YACN,cAAc,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE;YACpD,UAAU,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE;YAChD,QAAQ,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE;YAC9C,gBAAgB,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE;YACrD,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC;QACF,uBAAA,IAAI,uCAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AApFM,sDAAS,CAA2B;AAgX7C,0DAA0D;AAC1D,MAAM,CAAC,MAAM,qBAAqB,GAAG,wBAAwB,CAAC,WAAW,EAAE,CAAC;AAE5E,mCAAmC;AACnC,MAAM,CAAC,MAAM,iBAAiB,GAAG,wBAAwB,CAAC,WAAW,EAAE,CAAC","sourcesContent":["/**\n * Global singleton cache for Perps signing operations\n *\n * This cache persists across provider reconnections to prevent repeated\n * signing requests for hardware wallets. Critical for preventing repeated\n * hardware wallet signing prompts.\n *\n * Cache is intentionally kept separate from provider instances because providers\n * are recreated on account/network changes, which would reset instance-level caches.\n *\n * Tracks three signing operations:\n * 1. Unified Account enablement (one-time, replaces deprecated DEX abstraction)\n * 2. Builder Fee approval (required for trading)\n * 3. Referral code setup (one-time per account)\n *\n * Cache Structure:\n * - Key: `network:userAddress` (e.g., \"mainnet:0x123...\")\n * - Value: { unifiedAccount, builderFee, referral, timestamp }\n *\n * Lifecycle:\n * - Cache persists throughout app session\n * - Individual entries can be cleared per user/network\n * - Full cache can be cleared on app restart or explicit user action\n */\n\ntype SigningOperationState = {\n attempted: boolean; // Whether we've attempted this operation\n success: boolean; // Whether it succeeded (only valid if attempted=true)\n reason?: 'no_hl_account' | 'user_rejected' | 'transient'; // optional discriminator\n};\n\n// Tracks whether the wallet has ever been observed on Hyperliquid.\n// Hyperliquid accounts only come into existence on first USDC deposit.\n// Before then, user-scoped exchange writes (agentSetAbstraction,\n// userSetAbstraction, setReferrer, ...) reject with\n// \"User or API Wallet 0x... does not exist.\"\n// Used to skip those writes proactively rather than catching the rejection.\ntype WalletRegistrationState = {\n known: boolean; // Whether we have signal at all\n registered: boolean; // True once observed on Hyperliquid (monotonic)\n};\n\ntype PerpsSigningCacheEntry = {\n unifiedAccount: SigningOperationState;\n builderFee: SigningOperationState;\n referral: SigningOperationState;\n walletRegistered: WalletRegistrationState;\n timestamp: number; // When this entry was last updated\n};\n\n// Legacy interface for backward compatibility\ntype TradingReadinessCacheEntry = {\n attempted: boolean;\n enabled: boolean;\n reason?: 'no_hl_account' | 'user_rejected' | 'transient';\n timestamp: number;\n};\n\nclass PerpsSigningCacheManager {\n static #instance: PerpsSigningCacheManager;\n\n readonly #cache: Map<string, PerpsSigningCacheEntry> = new Map();\n\n // Global in-flight locks to prevent concurrent signing attempts across providers\n // Key: operationType:network:userAddress, Value: Promise that resolves when operation completes\n readonly #inFlightOperations: Map<string, Promise<void>> = new Map();\n\n // Singleton: use getInstance() instead of new\n protected constructor() {\n // Protected constructor for singleton\n }\n\n public static getInstance(): PerpsSigningCacheManager {\n PerpsSigningCacheManager.#instance ??= new PerpsSigningCacheManager();\n return PerpsSigningCacheManager.#instance;\n }\n\n // ===== In-Flight Lock Methods =====\n\n /**\n * Check if an operation is currently in-flight for this user/network\n *\n * @param operationType - The type of operation being performed.\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n * @returns The resulting string value.\n */\n public isInFlight(\n operationType: 'unifiedAccount' | 'builderFee' | 'referral',\n network: 'mainnet' | 'testnet',\n userAddress: string,\n ): Promise<void> | undefined {\n const key = `${operationType}:${network}:${userAddress.toLowerCase()}`;\n return this.#inFlightOperations.get(key);\n }\n\n /**\n * Set an operation as in-flight\n * Returns a function to call when operation completes\n *\n * @param operationType - The type of operation being performed.\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n * @returns The resulting string value.\n */\n public setInFlight(\n operationType: 'unifiedAccount' | 'builderFee' | 'referral',\n network: 'mainnet' | 'testnet',\n userAddress: string,\n ): () => void {\n const key = `${operationType}:${network}:${userAddress.toLowerCase()}`;\n let resolvePromise: () => void;\n const promise = new Promise<void>((resolve) => {\n resolvePromise = resolve;\n });\n this.#inFlightOperations.set(key, promise);\n return () => {\n this.#inFlightOperations.delete(key);\n resolvePromise();\n };\n }\n\n #getCacheKey(network: 'mainnet' | 'testnet', userAddress: string): string {\n return `${network}:${userAddress.toLowerCase()}`;\n }\n\n #getOrCreateEntry(\n network: 'mainnet' | 'testnet',\n userAddress: string,\n ): PerpsSigningCacheEntry {\n const key = this.#getCacheKey(network, userAddress);\n let entry = this.#cache.get(key);\n if (!entry) {\n entry = {\n unifiedAccount: { attempted: false, success: false },\n builderFee: { attempted: false, success: false },\n referral: { attempted: false, success: false },\n walletRegistered: { known: false, registered: false },\n timestamp: Date.now(),\n };\n this.#cache.set(key, entry);\n }\n return entry;\n }\n\n // ===== Unified Account Methods =====\n\n /**\n * Get unified account cache entry (legacy compatibility)\n *\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n * @returns The resulting string value.\n */\n public get(\n network: 'mainnet' | 'testnet',\n userAddress: string,\n ): TradingReadinessCacheEntry | undefined {\n const key = this.#getCacheKey(network, userAddress);\n const entry = this.#cache.get(key);\n if (!entry) {\n return undefined;\n }\n return {\n attempted: entry.unifiedAccount.attempted,\n enabled: entry.unifiedAccount.success,\n reason: entry.unifiedAccount.reason,\n timestamp: entry.timestamp,\n };\n }\n\n /**\n * Set unified account cache entry (legacy compatibility)\n *\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n * @param data - The transaction data payload.\n * @param data.attempted - Whether the operation was attempted.\n * @param data.enabled - Whether the feature is enabled.\n * @param data.reason - Optional discriminator explaining a non-success outcome.\n */\n public set(\n network: 'mainnet' | 'testnet',\n userAddress: string,\n data: {\n attempted: boolean;\n enabled: boolean;\n reason?: 'no_hl_account' | 'user_rejected' | 'transient';\n },\n ): void {\n const entry = this.#getOrCreateEntry(network, userAddress);\n entry.unifiedAccount = {\n attempted: data.attempted,\n success: data.enabled,\n reason: data.reason,\n };\n entry.timestamp = Date.now();\n }\n\n // ===== Builder Fee Methods =====\n\n /**\n * Check if builder fee approval was attempted\n *\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n * @returns The resulting string value.\n */\n public getBuilderFee(\n network: 'mainnet' | 'testnet',\n userAddress: string,\n ): SigningOperationState | undefined {\n const key = this.#getCacheKey(network, userAddress);\n const entry = this.#cache.get(key);\n return entry?.builderFee;\n }\n\n /**\n * Set builder fee approval state\n *\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n * @param state - The current state.\n */\n public setBuilderFee(\n network: 'mainnet' | 'testnet',\n userAddress: string,\n state: SigningOperationState,\n ): void {\n const entry = this.#getOrCreateEntry(network, userAddress);\n entry.builderFee = state;\n entry.timestamp = Date.now();\n }\n\n // ===== Referral Methods =====\n\n /**\n * Check if referral setup was attempted\n *\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n * @returns The resulting string value.\n */\n public getReferral(\n network: 'mainnet' | 'testnet',\n userAddress: string,\n ): SigningOperationState | undefined {\n const key = this.#getCacheKey(network, userAddress);\n const entry = this.#cache.get(key);\n return entry?.referral;\n }\n\n /**\n * Set referral setup state\n *\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n * @param state - The current state.\n */\n public setReferral(\n network: 'mainnet' | 'testnet',\n userAddress: string,\n state: SigningOperationState,\n ): void {\n const entry = this.#getOrCreateEntry(network, userAddress);\n entry.referral = state;\n entry.timestamp = Date.now();\n }\n\n // ===== General Methods =====\n\n /**\n * Clear only unified account state for a specific network and user address\n * This preserves builder fee and referral states\n *\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n */\n public clearUnifiedAccount(\n network: 'mainnet' | 'testnet',\n userAddress: string,\n ): void {\n const key = this.#getCacheKey(network, userAddress);\n const entry = this.#cache.get(key);\n if (entry) {\n entry.unifiedAccount = { attempted: false, success: false };\n entry.timestamp = Date.now();\n }\n }\n\n // ===== Wallet Registration Methods =====\n\n /**\n * Read the wallet's Hyperliquid registration signal.\n *\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n * @returns The current signal, or undefined if no entry exists.\n */\n public getWalletRegistered(\n network: 'mainnet' | 'testnet',\n userAddress: string,\n ): WalletRegistrationState | undefined {\n const key = this.#getCacheKey(network, userAddress);\n return this.#cache.get(key)?.walletRegistered;\n }\n\n /**\n * Record whether the wallet has been observed on Hyperliquid. Once\n * `registered=true` is set, it stays true for the session — the goal\n * is to skip doomed exchange writes for unfunded wallets, not to\n * gate them after they fund.\n *\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n * @param registered - True once any evidence (clearinghouseState balance,\n * userFills, successful deposit, ...) confirms the wallet exists on HL.\n */\n public setWalletRegistered(\n network: 'mainnet' | 'testnet',\n userAddress: string,\n registered: boolean,\n ): void {\n const entry = this.#getOrCreateEntry(network, userAddress);\n if (entry.walletRegistered.registered && !registered) {\n // Monotonic: once registered, never demote.\n return;\n }\n entry.walletRegistered = { known: true, registered };\n entry.timestamp = Date.now();\n }\n\n /**\n * Clear only builder fee state for a specific network and user address\n * This preserves unified account and referral states\n *\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n */\n public clearBuilderFee(\n network: 'mainnet' | 'testnet',\n userAddress: string,\n ): void {\n const key = this.#getCacheKey(network, userAddress);\n const entry = this.#cache.get(key);\n if (entry) {\n entry.builderFee = { attempted: false, success: false };\n entry.timestamp = Date.now();\n }\n }\n\n /**\n * Clear only referral state for a specific network and user address\n * This preserves unified account and builder fee states\n *\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n */\n public clearReferral(\n network: 'mainnet' | 'testnet',\n userAddress: string,\n ): void {\n const key = this.#getCacheKey(network, userAddress);\n const entry = this.#cache.get(key);\n if (entry) {\n entry.referral = { attempted: false, success: false };\n entry.timestamp = Date.now();\n }\n }\n\n /**\n * Clear entire cache entry for a specific network and user address\n * WARNING: This clears ALL signing operation states (unifiedAccount, builderFee, referral)\n *\n * @param network - The network environment.\n * @param userAddress - The user's wallet address.\n */\n public clear(network: 'mainnet' | 'testnet', userAddress: string): void {\n const key = this.#getCacheKey(network, userAddress);\n this.#cache.delete(key);\n }\n\n /**\n * Clear all cache entries\n * WARNING: This clears ALL signing operation states for ALL users\n */\n public clearAll(): void {\n this.#cache.clear();\n }\n\n /**\n * Get all cache entries (for debugging)\n *\n * @returns The result of the operation.\n */\n public getAll(): Map<string, PerpsSigningCacheEntry> {\n return new Map(this.#cache);\n }\n\n /**\n * Get cache size (for debugging)\n *\n * @returns The resulting numeric value.\n */\n public size(): number {\n return this.#cache.size;\n }\n\n /**\n * Get full cache state for debugging\n *\n * @returns The resulting string value.\n */\n public debugState(): string {\n const entries: string[] = [];\n this.#cache.forEach((entry, key) => {\n entries.push(\n `${key}: unified=${entry.unifiedAccount.attempted}/${entry.unifiedAccount.success}, ` +\n `builder=${entry.builderFee.attempted}/${entry.builderFee.success}, ` +\n `referral=${entry.referral.attempted}/${entry.referral.success}, ` +\n `walletRegistered=${entry.walletRegistered.known}/${entry.walletRegistered.registered}`,\n );\n });\n return entries.join('\\n') || '(empty)';\n }\n}\n\n// Export singleton instance with backward-compatible name\nexport const TradingReadinessCache = PerpsSigningCacheManager.getInstance();\n\n// Export with new name for clarity\nexport const PerpsSigningCache = PerpsSigningCacheManager.getInstance();\n"]}
|
|
@@ -1052,11 +1052,12 @@ class TradingService {
|
|
|
1052
1052
|
* @param options - The configuration options.
|
|
1053
1053
|
* @param options.provider - The perps provider instance.
|
|
1054
1054
|
* @param options.position - The position data.
|
|
1055
|
+
* @param options.trackingData - Optional tracking data for analytics events.
|
|
1055
1056
|
* @param options.context - The service context for dependencies.
|
|
1056
1057
|
* @returns The result of the operation.
|
|
1057
1058
|
*/
|
|
1058
1059
|
async flipPosition(options) {
|
|
1059
|
-
const { provider, position, context } = options;
|
|
1060
|
+
const { provider, position, trackingData, context } = options;
|
|
1060
1061
|
const traceId = (0, uuid_1.v4)();
|
|
1061
1062
|
const startTime = __classPrivateFieldGet(this, _TradingService_deps, "f").performance.now();
|
|
1062
1063
|
try {
|
|
@@ -1113,6 +1114,12 @@ class TradingService {
|
|
|
1113
1114
|
[eventNames_1.PERPS_EVENT_PROPERTY.COMPLETION_DURATION]: completionDuration,
|
|
1114
1115
|
[eventNames_1.PERPS_EVENT_PROPERTY.ACTION]: flipAction,
|
|
1115
1116
|
[eventNames_1.PERPS_EVENT_PROPERTY.ORDER_VALUE]: positionSize * executedPrice,
|
|
1117
|
+
...(trackingData?.vipTier !== undefined && {
|
|
1118
|
+
[eventNames_1.PERPS_EVENT_PROPERTY.VIP_TIER]: trackingData.vipTier,
|
|
1119
|
+
}),
|
|
1120
|
+
...(trackingData?.vipDiscount !== undefined && {
|
|
1121
|
+
[eventNames_1.PERPS_EVENT_PROPERTY.VIP_DISCOUNT]: trackingData.vipDiscount,
|
|
1122
|
+
}),
|
|
1116
1123
|
});
|
|
1117
1124
|
// Invalidate standalone caches so external hooks refresh
|
|
1118
1125
|
__classPrivateFieldGet(this, _TradingService_deps, "f").cacheInvalidator.invalidate({ cacheType: 'positions' });
|
|
@@ -1140,6 +1147,12 @@ class TradingService {
|
|
|
1140
1147
|
[eventNames_1.PERPS_EVENT_PROPERTY.ACTION]: failFlipAction,
|
|
1141
1148
|
[eventNames_1.PERPS_EVENT_PROPERTY.COMPLETION_DURATION]: completionDuration,
|
|
1142
1149
|
[eventNames_1.PERPS_EVENT_PROPERTY.ERROR_MESSAGE]: errorMessage,
|
|
1150
|
+
...(trackingData?.vipTier !== undefined && {
|
|
1151
|
+
[eventNames_1.PERPS_EVENT_PROPERTY.VIP_TIER]: trackingData.vipTier,
|
|
1152
|
+
}),
|
|
1153
|
+
...(trackingData?.vipDiscount !== undefined && {
|
|
1154
|
+
[eventNames_1.PERPS_EVENT_PROPERTY.VIP_DISCOUNT]: trackingData.vipDiscount,
|
|
1155
|
+
}),
|
|
1143
1156
|
});
|
|
1144
1157
|
__classPrivateFieldGet(this, _TradingService_deps, "f").tracer.endTrace({
|
|
1145
1158
|
name: types_1.PerpsTraceNames.FlipPosition,
|
|
@@ -1251,6 +1264,13 @@ _TradingService_deps = new WeakMap(), _TradingService_controllerDeps = new WeakM
|
|
|
1251
1264
|
properties[eventNames_1.PERPS_EVENT_PROPERTY.ERROR_MESSAGE] =
|
|
1252
1265
|
error?.message ?? result?.error ?? 'Unknown error';
|
|
1253
1266
|
}
|
|
1267
|
+
if (params.trackingData?.vipTier !== undefined) {
|
|
1268
|
+
properties[eventNames_1.PERPS_EVENT_PROPERTY.VIP_TIER] = params.trackingData.vipTier;
|
|
1269
|
+
}
|
|
1270
|
+
if (params.trackingData?.vipDiscount !== undefined) {
|
|
1271
|
+
properties[eventNames_1.PERPS_EVENT_PROPERTY.VIP_DISCOUNT] =
|
|
1272
|
+
params.trackingData.vipDiscount;
|
|
1273
|
+
}
|
|
1254
1274
|
if (params.trackingData?.abTests &&
|
|
1255
1275
|
Object.keys(params.trackingData.abTests).length > 0) {
|
|
1256
1276
|
properties[eventNames_1.PERPS_EVENT_PROPERTY.AB_TESTS] = params.trackingData.abTests;
|
|
@@ -1429,6 +1449,12 @@ async function _TradingService_loadPositionData(options) {
|
|
|
1429
1449
|
...(params.trackingData?.source && {
|
|
1430
1450
|
[eventNames_1.PERPS_EVENT_PROPERTY.SOURCE]: params.trackingData.source,
|
|
1431
1451
|
}),
|
|
1452
|
+
...(params.trackingData?.vipTier !== undefined && {
|
|
1453
|
+
[eventNames_1.PERPS_EVENT_PROPERTY.VIP_TIER]: params.trackingData.vipTier,
|
|
1454
|
+
}),
|
|
1455
|
+
...(params.trackingData?.vipDiscount !== undefined && {
|
|
1456
|
+
[eventNames_1.PERPS_EVENT_PROPERTY.VIP_DISCOUNT]: params.trackingData.vipDiscount,
|
|
1457
|
+
}),
|
|
1432
1458
|
};
|
|
1433
1459
|
// Calculate and add order value in USD (size * price)
|
|
1434
1460
|
const closeAssetPrice = result?.averagePrice
|