diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index d2a5c793173e..cad80de0b3c7 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -131,6 +131,7 @@ import { } from '@metamask/seedless-onboarding-controller'; import { PRODUCT_TYPES } from '@metamask/subscription-controller'; import { isSnapId } from '@metamask/snaps-utils'; +import { address } from '@solana/addresses'; import { findAtomicBatchSupportForChain, checkEip7702Support, @@ -1638,8 +1639,9 @@ export default class MetamaskController extends EventEmitter { setupControllerEventSubscriptions() { let lastSelectedAddress; let lastSelectedSolanaAccountAddress; + let lastSelectedTronAccountAddress; - // this throws if there is no solana account... perhaps we should handle this better at the controller level + // this throws if there is no solana or Tron account... perhaps we should handle this better at the controller level try { lastSelectedSolanaAccountAddress = this.accountsController.getSelectedMultichainAccount( @@ -1648,6 +1650,14 @@ export default class MetamaskController extends EventEmitter { } catch { // noop } + try { + lastSelectedTronAccountAddress = + this.accountsController.getSelectedMultichainAccount( + MultichainNetworks.TRON, + )?.address; + } catch { + // noop + } this.controllerMessenger.subscribe( 'PreferencesController:stateChange', @@ -1943,6 +1953,194 @@ export default class MetamaskController extends EventEmitter { }, ); + // wallet_notify for tron accountChanged when permission changes + this.controllerMessenger.subscribe( + `${this.permissionController.name}:stateChange`, + async (currentValue, previousValue) => { + const origins = uniq([...previousValue.keys(), ...currentValue.keys()]); + origins.forEach((origin) => { + const previousCaveatValue = previousValue.get(origin); + const currentCaveatValue = currentValue.get(origin); + + const previousTronAccountChangedNotificationsEnabled = Boolean( + previousCaveatValue?.sessionProperties?.[ + KnownSessionProperties.TronAccountChangedNotifications + ], + ); + const currentTronAccountChangedNotificationsEnabled = Boolean( + currentCaveatValue?.sessionProperties?.[ + KnownSessionProperties.TronAccountChangedNotifications + ], + ); + + if ( + !previousTronAccountChangedNotificationsEnabled && + !currentTronAccountChangedNotificationsEnabled + ) { + return; + } + + const previousTronCaipAccountIds = previousCaveatValue + ? getPermittedAccountsForScopes(previousCaveatValue, [ + MultichainNetworks.TRON, + MultichainNetworks.TRON_SHASTA, + MultichainNetworks.TRON_NILE, + ]) + : []; + const previousNonUniqueTronHexAccountAddresses = + previousTronCaipAccountIds.map((caipAccountId) => { + const { address } = parseCaipAccountId(caipAccountId); + return address; + }); + const previousTronHexAccountAddresses = uniq( + previousNonUniqueTronHexAccountAddresses, + ); + const [previousSelectedTronAccountAddress] = + this.sortMultichainAccountsByLastSelected( + previousTronHexAccountAddresses, + ); + + const currentTronCaipAccountIds = currentCaveatValue + ? getPermittedAccountsForScopes(currentCaveatValue, [ + MultichainNetworks.TRON, + MultichainNetworks.TRON_SHASTA, + MultichainNetworks.TRON_NILE, + ]) + : []; + const currentNonUniqueTronHexAccountAddresses = + currentTronCaipAccountIds.map((caipAccountId) => { + const { address } = parseCaipAccountId(caipAccountId); + return address; + }); + const currentTronHexAccountAddresses = uniq( + currentNonUniqueTronHexAccountAddresses, + ); + const [currentSelectedTronAccountAddress] = + this.sortMultichainAccountsByLastSelected( + currentTronHexAccountAddresses, + ); + + if ( + previousSelectedTronAccountAddress !== + currentSelectedTronAccountAddress + ) { + this._notifyTronAccountChange( + origin, + currentSelectedTronAccountAddress + ? [currentSelectedTronAccountAddress] + : [], + ); + } + }); + }, + getAuthorizedScopesByOrigin, + ); + + // TODO: To be removed when state 2 is fully transitioned. + // wallet_notify for tron accountChanged when selected account changes + this.controllerMessenger.subscribe( + `${this.accountsController.name}:selectedAccountChange`, + async (account) => { + if ( + account.type === TrxAccountType.Eoa && + account.address !== lastSelectedTronAccountAddress + ) { + lastSelectedTronAccountAddress = account.address; + + const originsWithTronAccountChangedNotifications = + getOriginsWithSessionProperty( + this.permissionController.state, + KnownSessionProperties.TronAccountChangedNotifications, + ); + + // returns a map of origins to permitted tron accounts + const tronAccounts = getPermittedAccountsForScopesByOrigin( + this.permissionController.state, + [ + MultichainNetworks.TRON, + MultichainNetworks.TRON_SHASTA, + MultichainNetworks.TRON_NILE, + ], + ); + + if (tronAccounts.size > 0) { + for (const [origin, accounts] of tronAccounts.entries()) { + const parsedTronAddresses = accounts.map((caipAccountId) => { + const { address } = parseCaipAccountId(caipAccountId); + return address; + }); + + if ( + parsedTronAddresses.includes(account.address) && + originsWithTronAccountChangedNotifications[origin] + ) { + this._notifyTronAccountChange(origin, [account.address]); + } + } + } + } + }, + ); + + // wallet_notify for tron accountChanged when selected account group changes + this.controllerMessenger.subscribe( + `${this.accountTreeController.name}:selectedAccountGroupChange`, + (groupId) => { + // TODO: Move this logic to the SnapKeyring directly. + // Forward selected accounts to the Snap keyring, so each Snaps can fetch those accounts. + // eslint-disable-next-line no-void + void this.forwardSelectedAccountGroupToSnapKeyring( + this.getSnapKeyringIfAvailable(), + groupId, + ); + + const [account] = + this.accountTreeController.getAccountsFromSelectedAccountGroup({ + scopes: [TrxScope.Mainnet], + }); + if ( + account && + account.type === TrxAccountType.Eoa && + account.address !== lastSelectedTronAccountAddress + ) { + lastSelectedTronAccountAddress = account.address; + + const originsWithTronAccountChangedNotifications = + getOriginsWithSessionProperty( + this.permissionController.state, + KnownSessionProperties.TronAccountChangedNotifications, + ); + + // returns a map of origins to permitted tron accounts + const tronAccounts = getPermittedAccountsForScopesByOrigin( + this.permissionController.state, + [ + MultichainNetworks.TRON, + MultichainNetworks.TRON_SHASTA, + MultichainNetworks.TRON_NILE, + ], + ); + + if (tronAccounts.size > 0) { + for (const [origin, accounts] of tronAccounts.entries()) { + const parsedTronAddresses = accounts.map((caipAccountId) => { + const { address } = parseCaipAccountId(caipAccountId); + return address; + }); + + if ( + parsedTronAddresses.includes(account.address) && + originsWithTronAccountChangedNotifications[origin] + // originsWithTronAccountChangedNotifications[origin] + ) { + this._notifyTronAccountChange(origin, [account.address]); + } + } + } + } + }, + ); + // TODO: Move this logic to the SnapKeyring directly. // Forward selected accounts to the Snap keyring, so each Snaps can fetch those accounts. this.controllerMessenger.subscribe( @@ -6259,13 +6457,13 @@ export default class MetamaskController extends EventEmitter { } /** - * For origins with a solana scope permitted, sends a wallet_notify -> metamask_accountChanged - * event to fire for the solana scope with the currently selected solana account if any are + * For origins with a solana or tron scope permitted, sends a wallet_notify -> metamask_accountChanged + * event to fire for the scope with the currently selected account if any are * permitted or empty array otherwise. * - * @param {string} origin - The origin to notify with the current solana account + * @param {string} origin - The origin to notify with the current account */ - notifySolanaAccountChangedForCurrentAccount(origin) { + notifyNonEVMAccountChangedForCurrentAccount(origin) { let caip25Caveat; try { caip25Caveat = this.permissionController.getCaveat( @@ -6292,10 +6490,16 @@ export default class MetamaskController extends EventEmitter { KnownSessionProperties.SolanaAccountChangedNotifications ]; + const tronAccountsChangedNotifications = + caip25Caveat.value.sessionProperties?.[ + KnownSessionProperties.TronAccountChangedNotifications + ]; + const sessionScopes = getSessionScopes(caip25Caveat.value, { getNonEvmSupportedMethods: this.getNonEvmSupportedMethods.bind(this), }); + // Handle Solana account notifications const solanaScope = sessionScopes[MultichainNetworks.SOLANA] || sessionScopes[MultichainNetworks.SOLANA_DEVNET] || @@ -6316,9 +6520,29 @@ export default class MetamaskController extends EventEmitter { this._notifySolanaAccountChange(origin, [accountAddressToEmit]); } } - } - // --------------------------------------------------------------------------- + // Handle Tron account notifications + const tronScope = + sessionScopes[MultichainNetworks.TRON] || + sessionScopes[MultichainNetworks.TRON_DEVNET] || + sessionScopes[MultichainNetworks.TRON_TESTNET]; + + if (tronAccountsChangedNotifications && tronScope) { + const { accounts } = tronScope; + const parsedPermittedTronAddresses = accounts.map((caipAccountId) => { + const { address } = parseCaipAccountId(caipAccountId); + return address; + }); + + const [accountAddressToEmit] = this.sortMultichainAccountsByLastSelected( + parsedPermittedTronAddresses, + ); + + if (accountAddressToEmit) { + this._notifyTronAccountChange(origin, [accountAddressToEmit]); + } + } + } // --------------------------------------------------------------------------- // Identity Management (signature operations) getAddTransactionRequest({ @@ -6932,13 +7156,13 @@ export default class MetamaskController extends EventEmitter { engine, }); - // solana account changed notifications + // solana and Tron account changed notifications // This delay is needed because it's possible for a dapp to not have listeners // setup in time right after a connection is established. // This can be resolved if we amend the caip standards to include a liveliness // handshake as part of the initial connection. setTimeout( - () => this.notifySolanaAccountChangedForCurrentAccount(origin), + () => this.notifyNonEVMAccountChangedForCurrentAccount(origin), 500, ); @@ -8677,6 +8901,23 @@ export default class MetamaskController extends EventEmitter { ); } + async _notifyTronAccountChange(origin, accountAddressArray) { + this.notifyConnections( + origin, + { + method: MultichainApiNotifications.walletNotify, + params: { + scope: MultichainNetworks.TRON, + notification: { + method: NOTIFICATION_NAMES.accountsChanged, + params: accountAddressArray, + }, + }, + }, + API_TYPE.CAIP_MULTICHAIN, + ); + } + async _notifyChainChange() { this.notifyAllConnections( async (origin) => ({ diff --git a/app/scripts/metamask-controller.test.js b/app/scripts/metamask-controller.test.js index f6949815ca7b..91763f19bf7e 100644 --- a/app/scripts/metamask-controller.test.js +++ b/app/scripts/metamask-controller.test.js @@ -21,6 +21,7 @@ import { EthAccountType, SolAccountType, SolScope, + TrxAccountType, } from '@metamask/keyring-api'; import { MOCK_ANY_NAMESPACE, Messenger } from '@metamask/messenger'; import { LoggingController, LogType } from '@metamask/logging-controller'; @@ -283,7 +284,7 @@ jest.mock('../../shared/modules/mv3.utils', () => ({ jest.mock('./controllers/permissions', () => ({ ...jest.requireActual('./controllers/permissions'), getOriginsWithSessionProperty: jest.fn(), - getPermittedAccountsForScopesByOrigin: jest.fn(), + getPermittedAccountsForScopesByOrigin: jest.fn(() => new Map()), })); jest.mock('@metamask/utils', () => ({ @@ -5621,7 +5622,7 @@ describe('MetaMaskController', () => { }); }); - describe('selectedAccountGroupChange subscription', () => { + describe('selectedAccountGroupChange subscription for Solana', () => { let metamaskController; const mockOrigin = 'https://test-dapp.com'; @@ -5771,4 +5772,156 @@ describe('MetaMaskController', () => { ).not.toHaveBeenCalled(); }); }); + + describe('selectedAccountGroupChange subscription for Tron', () => { + let metamaskController; + + const mockOrigin = 'https://test-dapp.com'; + const mockTronAddress = 'TYThGuS6a4KmX2rMFhqeCPHrRmmYEF7Xoi'; + const mockTronAccount = createMockInternalAccount({ + type: TrxAccountType.Eoa, + address: mockTronAddress, + name: 'Tron Account 1', + }); + const mockEvmAccount = createMockInternalAccount({ + type: EthAccountType.Eoa, + address: '0x742d35Cc6634C0532925a3b8D69b5b7f6Bb5b0bF', + name: 'EVM Account 1', + }); + + const setupMocks = ({ + account = mockTronAccount, + hasNotifications = true, + hasPermittedAccounts = true, + } = {}) => { + jest + .spyOn( + metamaskController.accountTreeController, + 'getAccountsFromSelectedAccountGroup', + ) + .mockReturnValue([account]); + + jest + .mocked(getOriginsWithSessionProperty) + .mockReturnValue(hasNotifications ? { [mockOrigin]: true } : {}); + + const mockTronAccounts = hasPermittedAccounts + ? new Map([ + [mockOrigin, [`${MultichainNetworks.TRON}:${mockTronAddress}`]], + ]) + : new Map(); + + jest + .mocked(getPermittedAccountsForScopesByOrigin) + .mockReturnValue(mockTronAccounts); + + jest.mocked(parseCaipAccountId).mockReturnValue({ + address: mockTronAddress, + }); + + const mockPermissionState = new Map(); + if (hasNotifications) { + mockPermissionState.set(mockOrigin, { + sessionProperties: { + [KnownSessionProperties.TronAccountChangedNotifications]: true, + }, + }); + } + jest + .spyOn(metamaskController.permissionController, 'state', 'get') + .mockReturnValue(mockPermissionState); + }; + + const triggerSubscription = () => { + metamaskController.controllerMessenger.publish( + 'AccountTreeController:selectedAccountGroupChange', + ); + }; + + beforeEach(async () => { + metamaskController = new MetaMaskController({ + showUserConfirmation: noop, + encryptor: mockEncryptor, + initState: cloneDeep(firstTimeState), + initLangCode: 'en_US', + platform: { + showTransactionNotification: () => undefined, + getVersion: () => 'foo', + switchToAnotherURL: jest.fn(), + }, + browser: browserPolyfillMock, + infuraProjectId: 'foo', + isFirstMetaMaskControllerSetup: true, + cronjobControllerStorageManager: + createMockCronjobControllerStorageManager(), + controllerMessenger: new Messenger({ + namespace: MOCK_ANY_NAMESPACE, + }), + }); + + jest + .spyOn(metamaskController, '_notifyTronAccountChange') + .mockImplementation(() => undefined); + }); + + it('notifies Tron account change when selected account group changes', async () => { + setupMocks(); + triggerSubscription(); + + expect(metamaskController._notifyTronAccountChange).toHaveBeenCalledWith( + mockOrigin, + [mockTronAddress], + ); + }); + + it('does not notify when account is not a Tron DataAccount', async () => { + setupMocks({ account: mockEvmAccount }); + triggerSubscription(); + + expect( + metamaskController._notifyTronAccountChange, + ).not.toHaveBeenCalled(); + }); + + it('should not notify when account address has not changed', async () => { + setupMocks(); + + // First call to set the lastSelectedTronAccountAddress + triggerSubscription(); + + // Reset the mock to check the second call + jest.clearAllMocks(); + + // Second call with same address should not trigger notification + triggerSubscription(); + + expect( + metamaskController._notifyTronAccountChange, + ).not.toHaveBeenCalled(); + }); + + it('does not notify when no origins have Tron account change notifications enabled', async () => { + setupMocks({ hasNotifications: false, hasPermittedAccounts: false }); + triggerSubscription(); + + expect( + metamaskController._notifyTronAccountChange, + ).not.toHaveBeenCalled(); + }); + + it('does not notify when no account is returned from selected account group', async () => { + jest + .spyOn( + metamaskController.accountTreeController, + 'getAccountsFromSelectedAccountGroup', + ) + .mockReturnValue([]); + + triggerSubscription(); + + expect( + metamaskController._notifyTronAccountChange, + ).not.toHaveBeenCalled(); + }); + }); }); diff --git a/package.json b/package.json index 4abbafb5b7e8..87f3922a8055 100644 --- a/package.json +++ b/package.json @@ -280,7 +280,7 @@ "@metamask/bridge-controller": "^64.0.0", "@metamask/bridge-status-controller": "^64.0.1", "@metamask/browser-passworder": "^6.0.0", - "@metamask/chain-agnostic-permission": "^1.2.2", + "@metamask/chain-agnostic-permission": "^1.3.0", "@metamask/claims-controller": "^0.2.0", "@metamask/contract-metadata": "^2.5.0", "@metamask/controller-utils": "^11.16.0", @@ -331,7 +331,7 @@ "@metamask/metamask-eth-abis": "^3.1.1", "@metamask/multichain-account-service": "^3.0.0", "@metamask/multichain-api-client": "^0.7.0", - "@metamask/multichain-api-middleware": "^1.2.4", + "@metamask/multichain-api-middleware": "^1.2.5", "@metamask/multichain-network-controller": "^2.0.0", "@metamask/multichain-transactions-controller": "^6.0.0", "@metamask/name-controller": "^9.0.0", diff --git a/test/jest/mocks.ts b/test/jest/mocks.ts index c6fd69d743f0..73a2a8000503 100644 --- a/test/jest/mocks.ts +++ b/test/jest/mocks.ts @@ -5,10 +5,10 @@ import { BtcAccountType, isEvmAccountType, EthScope, - BtcScope, SolAccountType, - SolScope, SolMethod, + TrxAccountType, + TrxMethod, } from '@metamask/keyring-api'; import { InternalAccount } from '@metamask/keyring-internal-api'; import { KeyringTypes } from '@metamask/keyring-controller'; @@ -23,6 +23,7 @@ import { import { MetaMaskReduxState } from '../../ui/store/store'; import mockState from '../data/mock-state.json'; import { isBtcMainnetAddress } from '../../shared/lib/multichain/accounts'; +import { MultichainNetworks } from '../../shared/constants/multichain/networks'; export type MockState = typeof mockState; @@ -241,14 +242,30 @@ export function createMockInternalAccount({ // If no address is given, we fallback to testnet const isMainnet = Boolean(address) && isBtcMainnetAddress(address); - scopes = [isMainnet ? BtcScope.Mainnet : BtcScope.Testnet]; + scopes = [ + isMainnet + ? MultichainNetworks.BITCOIN + : MultichainNetworks.BITCOIN_TESTNET, + ]; methods = Object.values(BtcMethod); break; } case SolAccountType.DataAccount: - scopes = [SolScope.Mainnet, SolScope.Testnet, SolScope.Devnet]; + scopes = [ + MultichainNetworks.SOLANA, + MultichainNetworks.SOLANA_TESTNET, + MultichainNetworks.SOLANA_DEVNET, + ]; methods = [SolMethod.SendAndConfirmTransaction]; break; + case TrxAccountType.Eoa: + scopes = [ + MultichainNetworks.TRON, + MultichainNetworks.TRON_SHASTA, + MultichainNetworks.TRON_NILE, + ]; + methods = [TrxMethod.SignMessage, TrxMethod.SignTransaction]; + break; default: throw new Error(`Unknown account type: ${type}`); } diff --git a/ui/pages/multichain-accounts/multichain-accounts-connect-page/multichain-accounts-connect-page.test.tsx b/ui/pages/multichain-accounts/multichain-accounts-connect-page/multichain-accounts-connect-page.test.tsx index f7b660fa8c02..b8682bf7bff0 100644 --- a/ui/pages/multichain-accounts/multichain-accounts-connect-page/multichain-accounts-connect-page.test.tsx +++ b/ui/pages/multichain-accounts/multichain-accounts-connect-page/multichain-accounts-connect-page.test.tsx @@ -22,10 +22,12 @@ import { } from '../../../../shared/modules/selectors/networks'; import { getMultichainNetwork } from '../../../selectors/multichain'; +import { MultichainNetworks } from '../../../../shared/constants/multichain/networks'; import { MultichainAccountsConnectPage, MultichainConnectPageProps, } from './multichain-accounts-connect-page'; +import { MultichainNetworks } from '../../../../shared/constants/multichain/networks'; const mockGetAllNetworkConfigurationsByCaipChainId = getAllNetworkConfigurationsByCaipChainId as jest.MockedFunction< @@ -872,6 +874,82 @@ describe('MultichainConnectPage', () => { ); }); + it('returns all default networks for Tron Wallet Adapter requests', () => { + const TRON_CAIP_CHAIN_ID = MultichainNetworks.TRON; + + mockGetCaip25CaveatValueFromPermissions.mockReturnValue({ + requiredScopes: {}, + optionalScopes: { + [TRON_CAIP_CHAIN_ID]: { + accounts: [], + }, + }, + sessionProperties: { + [KnownSessionProperties.TronAccountChangedNotifications]: true, + }, + isMultichainOrigin: true, + }); + + mockGetAllScopesFromCaip25CaveatValue.mockReturnValue([ + TRON_CAIP_CHAIN_ID, + ]); + + mockGetAllNetworkConfigurationsByCaipChainId.mockReturnValue({ + 'eip155:1': { + chainId: 'eip155:1', + name: 'Ethereum Mainnet', + nativeCurrency: 'ETH', + } as unknown as EvmAndMultichainNetworkConfigurationsWithCaipChainId, + [TRON_CAIP_CHAIN_ID]: { + chainId: TRON_CAIP_CHAIN_ID, + name: 'Tron Mainnet', + nativeCurrency: 'TRX', + } as unknown as EvmAndMultichainNetworkConfigurationsWithCaipChainId, + }); + + render({ + props: { + request: { + permissions: { + 'endowment:caip25': { + caveats: [ + { + type: 'restrictNetworkSwitching', + value: { + requiredScopes: {}, + optionalScopes: { + [TRON_CAIP_CHAIN_ID]: { + accounts: [], + }, + }, + sessionProperties: { + [KnownSessionProperties.TronAccountChangedNotifications]: true, // Tron Wallet Adapter indicator + }, + isMultichainOrigin: true, + }, + }, + ], + }, + }, + metadata: { + id: '1', + origin: mockTargetSubjectMetadata.origin, + }, + }, + }, + }); + + // For Tron Wallet Adapter requests, should return all default networks (EVM + Tron) + // even though only Tron was explicitly requested + const { calls } = mockUseAccountGroupsForPermissions.mock; + expect(calls.length).toBeGreaterThan(0); + const actualChainIds = calls[0]?.[2] as string[] | undefined; + expect(actualChainIds).toBeDefined(); + // Should include both EVM and Tron networks by default + expect(actualChainIds).toContain('eip155:1'); + expect(actualChainIds).toContain(TRON_CAIP_CHAIN_ID); + }); + it('returns all default networks when EIP-1193 request with no specific chain IDs requested', () => { mockGetCaip25CaveatValueFromPermissions.mockReturnValue({ requiredScopes: {}, diff --git a/ui/pages/multichain-accounts/multichain-accounts-connect-page/multichain-accounts-connect-page.tsx b/ui/pages/multichain-accounts/multichain-accounts-connect-page/multichain-accounts-connect-page.tsx index e34dad8a4384..fab8aab252e7 100644 --- a/ui/pages/multichain-accounts/multichain-accounts-connect-page/multichain-accounts-connect-page.tsx +++ b/ui/pages/multichain-accounts/multichain-accounts-connect-page/multichain-accounts-connect-page.tsx @@ -90,6 +90,7 @@ import { AccountGroupWithInternalAccounts } from '../../../selectors/multichain- import { getMultichainNetwork } from '../../../selectors/multichain'; import { TrustSignalDisplayState } from '../../../hooks/useTrustSignals'; import { useOriginTrustSignals } from '../../../hooks/useOriginTrustSignals'; +import { MultichainNetworks } from '../../../../shared/constants/multichain/networks'; export type MultichainAccountsConnectPageRequest = { permissions?: PermissionsRequest; @@ -164,16 +165,20 @@ export const MultichainAccountsConnectPage: React.FC< requestedCaip25CaveatValue, ); - const SOLANA_MAINNET_CAIP_CHAIN_ID = - 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp'; - const isSolanaWalletStandardRequest = requestedScopes.length === 1 && - requestedScopes[0] === SOLANA_MAINNET_CAIP_CHAIN_ID && + requestedScopes[0] === MultichainNetworks.SOLANA && requestedCaip25CaveatValue.sessionProperties[ KnownSessionProperties.SolanaAccountChangedNotifications ]; + const isTronWalletAdapterRequest = + requestedScopes.length === 1 && + requestedScopes[0] === MultichainNetworks.TRON && + requestedCaip25CaveatValue.sessionProperties[ + KnownSessionProperties.TronAccountChangedNotifications + ]; + const requestedCaip25CaveatValueWithExistingPermissions = useMemo( () => existingCaip25CaveatValue @@ -267,10 +272,11 @@ export const MultichainAccountsConnectPage: React.FC< ) : nonTestNetworkConfigurations.map(({ caipChainId }) => caipChainId); - // If the request is an EIP-1193 request (with no specific chains requested) or a Solana wallet standard request , return the default selected network list + // If the request is an EIP-1193 request (with no specific chains requested), a Solana wallet standard or a tronWallet library request , return the default selected network list if ( (requestedCaipChainIds.length === 0 && isEip1193Request) || - isSolanaWalletStandardRequest + isSolanaWalletStandardRequest || + isTronWalletAdapterRequest ) { return defaultSelectedNetworkList; } diff --git a/yarn.lock b/yarn.lock index 225283bf6d45..89bfda357860 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6189,18 +6189,18 @@ __metadata: languageName: node linkType: hard -"@metamask/chain-agnostic-permission@npm:^1.2.2": - version: 1.2.2 - resolution: "@metamask/chain-agnostic-permission@npm:1.2.2" +"@metamask/chain-agnostic-permission@npm:^1.3.0": + version: 1.3.0 + resolution: "@metamask/chain-agnostic-permission@npm:1.3.0" dependencies: "@metamask/api-specs": "npm:^0.14.0" - "@metamask/controller-utils": "npm:^11.14.1" - "@metamask/network-controller": "npm:^25.0.0" - "@metamask/permission-controller": "npm:^12.0.0" + "@metamask/controller-utils": "npm:^11.16.0" + "@metamask/network-controller": "npm:^27.0.0" + "@metamask/permission-controller": "npm:^12.1.1" "@metamask/rpc-errors": "npm:^7.0.2" "@metamask/utils": "npm:^11.8.1" lodash: "npm:^4.17.21" - checksum: 10/cf647bd5e3d38de912439c52a75a9fde91cf2f47f5cbda49258d8c0a0b16e0cb503be430462d7fb96b76cc7fb52402eb2b2b9f1262c75bf028793963709a402c + checksum: 10/0a5cd61a32af9e605b0378697744a6ae964a8ca0ff599b207fa6184176b09b122f4af303c2a70abc909606a10c3eabaf06a87dc9f205f9e74626a7061e6f33d3 languageName: node linkType: hard @@ -6583,18 +6583,6 @@ __metadata: languageName: node linkType: hard -"@metamask/eth-block-tracker@npm:^14.0.0": - version: 14.0.0 - resolution: "@metamask/eth-block-tracker@npm:14.0.0" - dependencies: - "@metamask/eth-json-rpc-provider": "npm:^5.0.1" - "@metamask/safe-event-emitter": "npm:^3.0.0" - "@metamask/utils": "npm:^11.8.1" - json-rpc-random-id: "npm:^1.0.1" - checksum: 10/63515bcc5fad22dba78d824f1fafd989e9a6770b318b91f46ba4a68326fafbeb9929146a82713f92e4920d489dc3a9bb81b5f457946053e8cf89bc4062788b36 - languageName: node - linkType: hard - "@metamask/eth-block-tracker@npm:^15.0.0": version: 15.0.0 resolution: "@metamask/eth-block-tracker@npm:15.0.0" @@ -6647,24 +6635,6 @@ __metadata: languageName: node linkType: hard -"@metamask/eth-json-rpc-middleware@npm:^21.0.0": - version: 21.0.0 - resolution: "@metamask/eth-json-rpc-middleware@npm:21.0.0" - dependencies: - "@metamask/eth-block-tracker": "npm:^14.0.0" - "@metamask/eth-json-rpc-provider": "npm:^5.0.1" - "@metamask/eth-sig-util": "npm:^8.2.0" - "@metamask/json-rpc-engine": "npm:^10.1.1" - "@metamask/rpc-errors": "npm:^7.0.2" - "@metamask/superstruct": "npm:^3.1.0" - "@metamask/utils": "npm:^11.8.1" - klona: "npm:^2.0.6" - pify: "npm:^5.0.0" - safe-stable-stringify: "npm:^2.4.3" - checksum: 10/3859035c7647202160fa73a8b2837153454b0097713bf822b4c22a14e971176895546c548e5899f0e600d1adbc3b79071ad468a8a1df3f06247ff5bd8b867353 - languageName: node - linkType: hard - "@metamask/eth-json-rpc-middleware@npm:^22.0.0": version: 22.0.0 resolution: "@metamask/eth-json-rpc-middleware@npm:22.0.0" @@ -6697,7 +6667,7 @@ __metadata: languageName: node linkType: hard -"@metamask/eth-json-rpc-provider@npm:^5.0.0, @metamask/eth-json-rpc-provider@npm:^5.0.1": +"@metamask/eth-json-rpc-provider@npm:^5.0.0": version: 5.0.1 resolution: "@metamask/eth-json-rpc-provider@npm:5.0.1" dependencies: @@ -7662,22 +7632,22 @@ __metadata: languageName: node linkType: hard -"@metamask/multichain-api-middleware@npm:^1.2.4": - version: 1.2.4 - resolution: "@metamask/multichain-api-middleware@npm:1.2.4" +"@metamask/multichain-api-middleware@npm:^1.2.5": + version: 1.2.5 + resolution: "@metamask/multichain-api-middleware@npm:1.2.5" dependencies: "@metamask/api-specs": "npm:^0.14.0" - "@metamask/chain-agnostic-permission": "npm:^1.2.2" - "@metamask/controller-utils": "npm:^11.14.1" - "@metamask/json-rpc-engine": "npm:^10.1.1" - "@metamask/network-controller": "npm:^25.0.0" - "@metamask/permission-controller": "npm:^12.1.0" + "@metamask/chain-agnostic-permission": "npm:^1.3.0" + "@metamask/controller-utils": "npm:^11.16.0" + "@metamask/json-rpc-engine": "npm:^10.2.0" + "@metamask/network-controller": "npm:^27.0.0" + "@metamask/permission-controller": "npm:^12.1.1" "@metamask/rpc-errors": "npm:^7.0.2" "@metamask/utils": "npm:^11.8.1" "@open-rpc/meta-schema": "npm:^1.14.6" "@open-rpc/schema-utils-js": "npm:^2.0.5" jsonschema: "npm:^1.4.1" - checksum: 10/0572858dec7bb47a75d4da531e3d030fe0ba67aee46dfd72daab7fe8669da0216d344fa17cee1cd8d0c428c4c1b975e1a2085fd7064114a8ebb5e4ce01b32782 + checksum: 10/57c90313fbb04c0d8ff2a79ab863930dc4fb0f678c219d3beb3aed55782cf419f9b4042479e0c9a2eb54ab0d0d11a4ec5ae1cd5d00e2882527c820a8b0f83104 languageName: node linkType: hard @@ -7766,35 +7736,6 @@ __metadata: languageName: node linkType: hard -"@metamask/network-controller@npm:^25.0.0": - version: 25.0.0 - resolution: "@metamask/network-controller@npm:25.0.0" - dependencies: - "@metamask/base-controller": "npm:^9.0.0" - "@metamask/controller-utils": "npm:^11.14.1" - "@metamask/eth-block-tracker": "npm:^14.0.0" - "@metamask/eth-json-rpc-infura": "npm:^10.3.0" - "@metamask/eth-json-rpc-middleware": "npm:^21.0.0" - "@metamask/eth-json-rpc-provider": "npm:^5.0.1" - "@metamask/eth-query": "npm:^4.0.0" - "@metamask/json-rpc-engine": "npm:^10.1.1" - "@metamask/messenger": "npm:^0.3.0" - "@metamask/rpc-errors": "npm:^7.0.2" - "@metamask/swappable-obj-proxy": "npm:^2.3.0" - "@metamask/utils": "npm:^11.8.1" - async-mutex: "npm:^0.5.0" - fast-deep-equal: "npm:^3.1.3" - immer: "npm:^9.0.6" - loglevel: "npm:^1.8.1" - reselect: "npm:^5.1.1" - uri-js: "npm:^4.4.1" - uuid: "npm:^8.3.2" - peerDependencies: - "@metamask/error-reporting-service": ^3.0.0 - checksum: 10/1fcad4f22f4b090b7de64134fdc6e4085f5bb4bb1dea53d7d25122c708f18d90a61caa5e6098a483ecbbb8cd93cdd2a145484cb129c7e8def4a9b726e9b4ee4c - languageName: node - linkType: hard - "@metamask/network-controller@npm:^26.0.0": version: 26.0.0 resolution: "@metamask/network-controller@npm:26.0.0" @@ -33458,7 +33399,7 @@ __metadata: "@metamask/bridge-status-controller": "npm:^64.0.1" "@metamask/browser-passworder": "npm:^6.0.0" "@metamask/build-utils": "npm:^3.0.0" - "@metamask/chain-agnostic-permission": "npm:^1.2.2" + "@metamask/chain-agnostic-permission": "npm:^1.3.0" "@metamask/claims-controller": "npm:^0.2.0" "@metamask/contract-metadata": "npm:^2.5.0" "@metamask/controller-utils": "npm:^11.16.0" @@ -33518,7 +33459,7 @@ __metadata: "@metamask/metamask-eth-abis": "npm:^3.1.1" "@metamask/multichain-account-service": "npm:^3.0.0" "@metamask/multichain-api-client": "npm:^0.7.0" - "@metamask/multichain-api-middleware": "npm:^1.2.4" + "@metamask/multichain-api-middleware": "npm:^1.2.5" "@metamask/multichain-network-controller": "npm:^2.0.0" "@metamask/multichain-transactions-controller": "npm:^6.0.0" "@metamask/name-controller": "npm:^9.0.0"