@@ -142,7 +142,6 @@ import {
142142import { Interface } from '@ethersproject/abi' ;
143143import { abiERC1155 , abiERC721 } from '@metamask/metamask-eth-abis' ;
144144import { isEvmAccountType } from '@metamask/keyring-api' ;
145- import { normalize } from '@metamask/eth-sig-util' ;
146145import {
147146 methodsRequiringNetworkSwitch ,
148147 methodsWithConfirmation ,
@@ -4046,10 +4045,7 @@ export default class MetamaskController extends EventEmitter {
40464045 // keyring's iframe and have the setting initialized properly
40474046 // Optimistically called to not block MetaMask login due to
40484047 // Ledger Keyring GitHub downtime
4049- this . withKeyringForDevice (
4050- { name : HardwareDeviceNames . ledger } ,
4051- async ( keyring ) => this . setLedgerTransportPreference ( keyring ) ,
4052- ) ;
4048+ this . setLedgerTransportPreference ( ) ;
40534049 }
40544050 } finally {
40554051 releaseLock ( ) ;
@@ -4179,10 +4175,7 @@ export default class MetamaskController extends EventEmitter {
41794175 // Optimistically called to not block MetaMask login due to
41804176 // Ledger Keyring GitHub downtime
41814177 if ( completedOnboarding ) {
4182- this . withKeyringForDevice (
4183- { name : HardwareDeviceNames . ledger } ,
4184- async ( keyring ) => this . setLedgerTransportPreference ( keyring ) ,
4185- ) ;
4178+ this . setLedgerTransportPreference ( ) ;
41864179 }
41874180 }
41884181
@@ -4286,74 +4279,50 @@ export default class MetamaskController extends EventEmitter {
42864279 // Hardware
42874280 //
42884281
4289- /**
4290- * Select a hardware wallet device and execute a
4291- * callback with the keyring for that device.
4292- *
4293- * Note that KeyringController state is not updated before
4294- * the end of the callback execution, and calls to KeyringController
4295- * methods within the callback can lead to deadlocks.
4296- *
4297- * @param {object } options - The options for the device
4298- * @param {string } options.name - The device name to select
4299- * @param {string } options.hdPath - An optional hd path to be set on the device
4300- * keyring
4301- * @param {* } callback - The callback to execute with the keyring
4302- * @returns {* } The result of the callback
4303- */
4304- async withKeyringForDevice ( options , callback ) {
4282+ async getKeyringForDevice ( deviceName , hdPath = null ) {
43054283 const keyringOverrides = this . opts . overrides ?. keyrings ;
4306- let keyringType = null ;
4307- switch ( options . name ) {
4284+ let keyringName = null ;
4285+ switch ( deviceName ) {
43084286 case HardwareDeviceNames . trezor :
4309- keyringType = keyringOverrides ?. trezor ?. type || TrezorKeyring . type ;
4287+ keyringName = keyringOverrides ?. trezor ?. type || TrezorKeyring . type ;
43104288 break ;
43114289 case HardwareDeviceNames . ledger :
4312- keyringType = keyringOverrides ?. ledger ?. type || LedgerKeyring . type ;
4290+ keyringName = keyringOverrides ?. ledger ?. type || LedgerKeyring . type ;
43134291 break ;
43144292 case HardwareDeviceNames . qr :
4315- keyringType = QRHardwareKeyring . type ;
4293+ keyringName = QRHardwareKeyring . type ;
43164294 break ;
43174295 case HardwareDeviceNames . lattice :
4318- keyringType = keyringOverrides ?. lattice ?. type || LatticeKeyring . type ;
4296+ keyringName = keyringOverrides ?. lattice ?. type || LatticeKeyring . type ;
43194297 break ;
43204298 default :
43214299 throw new Error (
4322- 'MetamaskController:withKeyringForDevice - Unknown device' ,
4300+ 'MetamaskController:getKeyringForDevice - Unknown device' ,
43234301 ) ;
43244302 }
4303+ let [ keyring ] = await this . keyringController . getKeyringsByType ( keyringName ) ;
4304+ if ( ! keyring ) {
4305+ keyring = await this . keyringController . addNewKeyring ( keyringName ) ;
4306+ }
4307+ if ( hdPath && keyring . setHdPath ) {
4308+ keyring . setHdPath ( hdPath ) ;
4309+ }
4310+ if ( deviceName === HardwareDeviceNames . lattice ) {
4311+ keyring . appName = 'MetaMask' ;
4312+ }
4313+ if ( deviceName === HardwareDeviceNames . trezor ) {
4314+ const model = keyring . getModel ( ) ;
4315+ this . appStateController . setTrezorModel ( model ) ;
4316+ }
43254317
4326- return this . keyringController . withKeyring (
4327- { type : keyringType } ,
4328- async ( keyring ) => {
4329- if ( options . hdPath && keyring . setHdPath ) {
4330- keyring . setHdPath ( options . hdPath ) ;
4331- }
4332-
4333- if ( options . name === HardwareDeviceNames . lattice ) {
4334- keyring . appName = 'MetaMask' ;
4335- }
4336-
4337- if ( options . name === HardwareDeviceNames . trezor ) {
4338- const model = keyring . getModel ( ) ;
4339- this . appStateController . setTrezorModel ( model ) ;
4340- }
4341-
4342- keyring . network = this . networkController . state . providerConfig . type ;
4318+ keyring . network = this . networkController . state . providerConfig . type ;
43434319
4344- return await callback ( keyring ) ;
4345- } ,
4346- {
4347- createIfMissing : true ,
4348- } ,
4349- ) ;
4320+ return keyring ;
43504321 }
43514322
43524323 async attemptLedgerTransportCreation ( ) {
4353- return await this . withKeyringForDevice (
4354- HardwareDeviceNames . ledger ,
4355- async ( keyring ) => keyring . attemptMakeApp ( ) ,
4356- ) ;
4324+ const keyring = await this . getKeyringForDevice ( HardwareDeviceNames . ledger ) ;
4325+ return await keyring . attemptMakeApp ( ) ;
43574326 }
43584327
43594328 /**
@@ -4365,38 +4334,35 @@ export default class MetamaskController extends EventEmitter {
43654334 * @returns [] accounts
43664335 */
43674336 async connectHardware ( deviceName , page , hdPath ) {
4368- return this . withKeyringForDevice (
4369- { name : deviceName , hdPath } ,
4370- async ( keyring ) => {
4371- if ( deviceName === HardwareDeviceNames . ledger ) {
4372- await this . setLedgerTransportPreference ( keyring ) ;
4373- }
4337+ const keyring = await this . getKeyringForDevice ( deviceName , hdPath ) ;
43744338
4375- let accounts = [ ] ;
4376- switch ( page ) {
4377- case - 1 :
4378- accounts = await keyring . getPreviousPage ( ) ;
4379- break ;
4380- case 1 :
4381- accounts = await keyring . getNextPage ( ) ;
4382- break ;
4383- default :
4384- accounts = await keyring . getFirstPage ( ) ;
4385- }
4339+ if ( deviceName === HardwareDeviceNames . ledger ) {
4340+ await this . setLedgerTransportPreference ( keyring ) ;
4341+ }
43864342
4387- // Merge with existing accounts
4388- // and make sure addresses are not repeated
4389- const oldAccounts = await this . keyringController . getAccounts ( ) ;
4343+ let accounts = [ ] ;
4344+ switch ( page ) {
4345+ case - 1 :
4346+ accounts = await keyring . getPreviousPage ( ) ;
4347+ break ;
4348+ case 1 :
4349+ accounts = await keyring . getNextPage ( ) ;
4350+ break ;
4351+ default :
4352+ accounts = await keyring . getFirstPage ( ) ;
4353+ }
43904354
4391- const accountsToTrack = [
4392- ...new Set (
4393- oldAccounts . concat ( accounts . map ( ( a ) => a . address . toLowerCase ( ) ) ) ,
4394- ) ,
4395- ] ;
4396- this . accountTracker . syncWithAddresses ( accountsToTrack ) ;
4397- return accounts ;
4398- } ,
4399- ) ;
4355+ // Merge with existing accounts
4356+ // and make sure addresses are not repeated
4357+ const oldAccounts = await this . keyringController . getAccounts ( ) ;
4358+
4359+ const accountsToTrack = [
4360+ ...new Set (
4361+ oldAccounts . concat ( accounts . map ( ( a ) => a . address . toLowerCase ( ) ) ) ,
4362+ ) ,
4363+ ] ;
4364+ this . accountTracker . syncWithAddresses ( accountsToTrack ) ;
4365+ return accounts ;
44004366 }
44014367
44024368 /**
@@ -4407,12 +4373,8 @@ export default class MetamaskController extends EventEmitter {
44074373 * @returns {Promise<boolean> }
44084374 */
44094375 async checkHardwareStatus ( deviceName , hdPath ) {
4410- return this . withKeyringForDevice (
4411- { name : deviceName , hdPath } ,
4412- async ( keyring ) => {
4413- return keyring . isUnlocked ( ) ;
4414- } ,
4415- ) ;
4376+ const keyring = await this . getKeyringForDevice ( deviceName , hdPath ) ;
4377+ return keyring . isUnlocked ( ) ;
44164378 }
44174379
44184380 /**
@@ -4422,15 +4384,14 @@ export default class MetamaskController extends EventEmitter {
44224384 * @returns {Promise<boolean> }
44234385 */
44244386 async forgetDevice ( deviceName ) {
4425- return this . withKeyringForDevice ( { name : deviceName } , async ( keyring ) => {
4426- for ( const address of keyring . accounts ) {
4427- await this . _onAccountRemoved ( address ) ;
4428- }
4387+ const keyring = await this . getKeyringForDevice ( deviceName ) ;
44294388
4430- keyring . forgetDevice ( ) ;
4389+ for ( const address of keyring . accounts ) {
4390+ await this . removeAccount ( address ) ;
4391+ }
44314392
4432- return true ;
4433- } ) ;
4393+ keyring . forgetDevice ( ) ;
4394+ return true ;
44344395 }
44354396
44364397 /**
@@ -4468,22 +4429,21 @@ export default class MetamaskController extends EventEmitter {
44684429 * @returns {'ledger' | 'lattice' | string | undefined }
44694430 */
44704431 async getDeviceModel ( address ) {
4471- return this . keyringController . withKeyring ( { address } , async ( keyring ) => {
4472- switch ( keyring . type ) {
4473- case KeyringType . trezor :
4474- return keyring . getModel ( ) ;
4475- case KeyringType . qr :
4476- return keyring . getName ( ) ;
4477- case KeyringType . ledger :
4478- // TODO: get model after ledger keyring exposes method
4479- return HardwareDeviceNames . ledger ;
4480- case KeyringType . lattice :
4481- // TODO: get model after lattice keyring exposes method
4482- return HardwareDeviceNames . lattice ;
4483- default :
4484- return undefined ;
4485- }
4486- } ) ;
4432+ const keyring = await this . keyringController . getKeyringForAccount ( address ) ;
4433+ switch ( keyring . type ) {
4434+ case KeyringType . trezor :
4435+ return keyring . getModel ( ) ;
4436+ case KeyringType . qr :
4437+ return keyring . getName ( ) ;
4438+ case KeyringType . ledger :
4439+ // TODO: get model after ledger keyring exposes method
4440+ return HardwareDeviceNames . ledger ;
4441+ case KeyringType . lattice :
4442+ // TODO: get model after lattice keyring exposes method
4443+ return HardwareDeviceNames . lattice ;
4444+ default :
4445+ return undefined ;
4446+ }
44874447 }
44884448
44894449 /**
@@ -4513,24 +4473,16 @@ export default class MetamaskController extends EventEmitter {
45134473 hdPath ,
45144474 hdPathDescription ,
45154475 ) {
4516- const { address : unlockedAccount , label } = await this . withKeyringForDevice (
4517- { name : deviceName , hdPath } ,
4518- async ( keyring ) => {
4519- keyring . setAccountToUnlock ( index ) ;
4520- const [ address ] = await keyring . addAccounts ( 1 ) ;
4521- return {
4522- address : normalize ( address ) ,
4523- label : this . getAccountLabel (
4524- deviceName === HardwareDeviceNames . qr
4525- ? keyring . getName ( )
4526- : deviceName ,
4527- index ,
4528- hdPathDescription ,
4529- ) ,
4530- } ;
4531- } ,
4476+ const keyring = await this . getKeyringForDevice ( deviceName , hdPath ) ;
4477+
4478+ keyring . setAccountToUnlock ( index ) ;
4479+ const unlockedAccount =
4480+ await this . keyringController . addNewAccountForKeyring ( keyring ) ;
4481+ const label = this . getAccountLabel (
4482+ deviceName === HardwareDeviceNames . qr ? keyring . getName ( ) : deviceName ,
4483+ index ,
4484+ hdPathDescription ,
45324485 ) ;
4533-
45344486 // Set the account label to Trezor 1 / Ledger 1 / QR Hardware 1, etc
45354487 this . preferencesController . setAccountLabel ( unlockedAccount , label ) ;
45364488 // Select the account
@@ -4706,8 +4658,20 @@ export default class MetamaskController extends EventEmitter {
47064658 * @param {string[] } address - A hex address
47074659 */
47084660 async removeAccount ( address ) {
4709- await this . _onAccountRemoved ( address ) ;
4661+ // Remove all associated permissions
4662+ this . removeAllAccountPermissions ( address ) ;
4663+
4664+ ///: BEGIN:ONLY_INCLUDE_IF(build-mmi)
4665+ this . custodyController . removeAccount ( address ) ;
4666+ ///: END:ONLY_INCLUDE_IF(build-mmi)
4667+
4668+ const keyring = await this . keyringController . getKeyringForAccount ( address ) ;
4669+ // Remove account from the keyring
47104670 await this . keyringController . removeAccount ( address ) ;
4671+ const updatedKeyringAccounts = keyring ? await keyring . getAccounts ( ) : { } ;
4672+ if ( updatedKeyringAccounts ?. length === 0 ) {
4673+ keyring . destroy ?. ( ) ;
4674+ }
47114675
47124676 return address ;
47134677 }
@@ -5920,21 +5884,6 @@ export default class MetamaskController extends EventEmitter {
59205884 this . _notifyChainChange ( ) ;
59215885 }
59225886
5923- /**
5924- * Execute side effects of a removed account.
5925- *
5926- * @param {string } address - The address of the account to remove.
5927- * @returns {Promise<void> }
5928- */
5929- async _onAccountRemoved ( address ) {
5930- // Remove all associated permissions
5931- this . removeAllAccountPermissions ( address ) ;
5932-
5933- ///: BEGIN:ONLY_INCLUDE_IF(build-mmi)
5934- this . custodyController . removeAccount ( address ) ;
5935- ///: END:ONLY_INCLUDE_IF(build-mmi)
5936- }
5937-
59385887 // misc
59395888
59405889 /**
@@ -6209,15 +6158,16 @@ export default class MetamaskController extends EventEmitter {
62096158 /**
62106159 * Sets the Ledger Live preference to use for Ledger hardware wallet support
62116160 *
6212- * @param keyring
6161+ * @param _keyring
62136162 * @deprecated This method is deprecated and will be removed in the future.
62146163 * Only webhid connections are supported in chrome and u2f in firefox.
62156164 */
6216- async setLedgerTransportPreference ( keyring ) {
6165+ async setLedgerTransportPreference ( _keyring ) {
62176166 const transportType = window . navigator . hid
62186167 ? LedgerTransportTypes . webhid
62196168 : LedgerTransportTypes . u2f ;
6220-
6169+ const keyring =
6170+ _keyring || ( await this . getKeyringForDevice ( HardwareDeviceNames . ledger ) ) ;
62216171 if ( keyring ?. updateTransportMethod ) {
62226172 return keyring . updateTransportMethod ( transportType ) . catch ( ( e ) => {
62236173 throw e ;
0 commit comments