@@ -24,6 +24,85 @@ const INTERNAL_ORIGINS = [process.env.MM_FOX_CODE, TransactionTypes.MMM];
2424// eslint-disable-next-line @typescript-eslint/no-explicit-any
2525const Engine = ImportedEngine as any ;
2626
27+ /**
28+ * Checks that all accounts referenced have a matching InternalAccount. Sends
29+ * an error to sentry for any accounts that were expected but are missing from the wallet.
30+ *
31+ * @param [internalAccounts] - The list of evm accounts the wallet knows about.
32+ * @param [accounts] - The list of evm accounts addresses that should exist.
33+ */
34+ const captureKeyringTypesWithMissingIdentities = (
35+ internalAccounts : InternalAccount [ ] = [ ] ,
36+ accounts : Hex [ ] = [ ] ,
37+ ) => {
38+ const accountsMissingIdentities = accounts . filter (
39+ ( address ) =>
40+ ! internalAccounts . some (
41+ ( account ) => account . address . toLowerCase ( ) === address . toLowerCase ( ) ,
42+ ) ,
43+ ) ;
44+ const keyringTypesWithMissingIdentities = accountsMissingIdentities . map (
45+ ( address ) =>
46+ Engine . context . KeyringController . getAccountKeyringType ( address ) ,
47+ ) ;
48+
49+ const internalAccountCount = internalAccounts . length ;
50+
51+ const accountTrackerCount = Object . keys (
52+ Engine . context . AccountTrackerController . state . accounts || { } ,
53+ ) . length ;
54+
55+ captureException (
56+ new Error (
57+ `Attempt to get permission specifications failed because there were ${ accounts . length } accounts, but ${ internalAccountCount } identities, and the ${ keyringTypesWithMissingIdentities } keyrings included accounts with missing identities. Meanwhile, there are ${ accountTrackerCount } accounts in the account tracker.` ,
58+ ) ,
59+ ) ;
60+ } ;
61+
62+ /**
63+ * Sorts a list of evm account addresses by most recently selected by using
64+ * the lastSelected value for the matching InternalAccount object stored in state.
65+ *
66+ * @param accounts - The list of evm accounts addresses to sort.
67+ * @returns The sorted evm accounts addresses.
68+ */
69+ export const sortAccountsByLastSelected = ( accounts : Hex [ ] ) => {
70+ const internalAccounts : InternalAccount [ ] =
71+ Engine . context . AccountsController . listAccounts ( ) ;
72+
73+ return accounts . sort ( ( firstAddress , secondAddress ) => {
74+ const firstAccount = internalAccounts . find (
75+ ( internalAccount ) =>
76+ internalAccount . address . toLowerCase ( ) === firstAddress . toLowerCase ( ) ,
77+ ) ;
78+
79+ const secondAccount = internalAccounts . find (
80+ ( internalAccount ) =>
81+ internalAccount . address . toLowerCase ( ) === secondAddress . toLowerCase ( ) ,
82+ ) ;
83+
84+ if ( ! firstAccount ) {
85+ captureKeyringTypesWithMissingIdentities ( internalAccounts , accounts ) ;
86+ throw new Error ( `Missing identity for address: "${ firstAddress } ".` ) ;
87+ } else if ( ! secondAccount ) {
88+ captureKeyringTypesWithMissingIdentities ( internalAccounts , accounts ) ;
89+ throw new Error ( `Missing identity for address: "${ secondAddress } ".` ) ;
90+ } else if (
91+ firstAccount . metadata . lastSelected === secondAccount . metadata . lastSelected
92+ ) {
93+ return 0 ;
94+ } else if ( firstAccount . metadata . lastSelected === undefined ) {
95+ return 1 ;
96+ } else if ( secondAccount . metadata . lastSelected === undefined ) {
97+ return - 1 ;
98+ }
99+
100+ return (
101+ secondAccount . metadata . lastSelected - firstAccount . metadata . lastSelected
102+ ) ;
103+ } ) ;
104+ } ;
105+
27106// TODO: Replace "any" with type
28107// eslint-disable-next-line @typescript-eslint/no-explicit-any
29108function getAccountsFromSubject ( subject : any ) {
@@ -228,85 +307,6 @@ export const addPermittedChains = (origin: string, chainIds: Hex[]) => {
228307 ) ;
229308} ;
230309
231- /**
232- * Checks that all accounts referenced have a matching InternalAccount. Sends
233- * an error to sentry for any accounts that were expected but are missing from the wallet.
234- *
235- * @param [internalAccounts] - The list of evm accounts the wallet knows about.
236- * @param [accounts] - The list of evm accounts addresses that should exist.
237- */
238- const captureKeyringTypesWithMissingIdentities = (
239- internalAccounts : InternalAccount [ ] = [ ] ,
240- accounts : Hex [ ] = [ ] ,
241- ) => {
242- const accountsMissingIdentities = accounts . filter (
243- ( address ) =>
244- ! internalAccounts . some (
245- ( account ) => account . address . toLowerCase ( ) === address . toLowerCase ( ) ,
246- ) ,
247- ) ;
248- const keyringTypesWithMissingIdentities = accountsMissingIdentities . map (
249- ( address ) =>
250- Engine . context . KeyringController . getAccountKeyringType ( address ) ,
251- ) ;
252-
253- const internalAccountCount = internalAccounts . length ;
254-
255- const accountTrackerCount = Object . keys (
256- Engine . context . AccountTrackerController . state . accounts || { } ,
257- ) . length ;
258-
259- captureException (
260- new Error (
261- `Attempt to get permission specifications failed because there were ${ accounts . length } accounts, but ${ internalAccountCount } identities, and the ${ keyringTypesWithMissingIdentities } keyrings included accounts with missing identities. Meanwhile, there are ${ accountTrackerCount } accounts in the account tracker.` ,
262- ) ,
263- ) ;
264- } ;
265-
266- /**
267- * Sorts a list of evm account addresses by most recently selected by using
268- * the lastSelected value for the matching InternalAccount object stored in state.
269- *
270- * @param accounts - The list of evm accounts addresses to sort.
271- * @returns The sorted evm accounts addresses.
272- */
273- export const sortAccountsByLastSelected = ( accounts : Hex [ ] ) => {
274- const internalAccounts : InternalAccount [ ] =
275- Engine . context . AccountsController . listAccounts ( ) ;
276-
277- return accounts . sort ( ( firstAddress , secondAddress ) => {
278- const firstAccount = internalAccounts . find (
279- ( internalAccount ) =>
280- internalAccount . address . toLowerCase ( ) === firstAddress . toLowerCase ( ) ,
281- ) ;
282-
283- const secondAccount = internalAccounts . find (
284- ( internalAccount ) =>
285- internalAccount . address . toLowerCase ( ) === secondAddress . toLowerCase ( ) ,
286- ) ;
287-
288- if ( ! firstAccount ) {
289- captureKeyringTypesWithMissingIdentities ( internalAccounts , accounts ) ;
290- throw new Error ( `Missing identity for address: "${ firstAddress } ".` ) ;
291- } else if ( ! secondAccount ) {
292- captureKeyringTypesWithMissingIdentities ( internalAccounts , accounts ) ;
293- throw new Error ( `Missing identity for address: "${ secondAddress } ".` ) ;
294- } else if (
295- firstAccount . metadata . lastSelected === secondAccount . metadata . lastSelected
296- ) {
297- return 0 ;
298- } else if ( firstAccount . metadata . lastSelected === undefined ) {
299- return 1 ;
300- } else if ( secondAccount . metadata . lastSelected === undefined ) {
301- return - 1 ;
302- }
303-
304- return (
305- secondAccount . metadata . lastSelected - firstAccount . metadata . lastSelected
306- ) ;
307- } ) ;
308- } ;
309-
310310/**
311311 * Gets the sorted permitted accounts for the specified origin. Returns an empty
312312 * array if no accounts are permitted or the wallet is locked. Returns any permitted
0 commit comments