mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Fix Connected Sites data selector (#8310)
This change replaces `getRenderablePermissionsDomains` with a new selector `getConnectedDomainsForSelectedAddress` that works better. The data returned from this selector is used to populated the _Connected Sites_ modal, which (as of #8262) didn't use most of the data returned from the old selector. The old selector only looked at the first address that was exposed, making it not work for anything other than the first account connected to a particular origin.
This commit is contained in:
parent
f1c9f1ab68
commit
d131014b5e
@ -2,10 +2,10 @@ import { connect } from 'react-redux'
|
||||
import ConnectedSites from './connected-sites.component'
|
||||
import { getOpenMetamaskTabsIds, legacyExposeAccounts, removePermissionsFor } from '../../store/actions'
|
||||
import {
|
||||
getConnectedDomainsForSelectedAddress,
|
||||
getCurrentAccountWithSendEtherInfo,
|
||||
getPermissionsDomains,
|
||||
getPermittedAccountsForCurrentTab,
|
||||
getRenderablePermissionsDomains,
|
||||
getSelectedAddress,
|
||||
} from '../../selectors/selectors'
|
||||
import { getOriginFromUrl } from '../../helpers/utils/util'
|
||||
@ -14,7 +14,7 @@ const mapStateToProps = (state) => {
|
||||
const { openMetaMaskTabs } = state.appState
|
||||
const { title, url, id } = state.activeTab
|
||||
const permittedAccounts = getPermittedAccountsForCurrentTab(state)
|
||||
const connectedDomains = getRenderablePermissionsDomains(state)
|
||||
const connectedDomains = getConnectedDomainsForSelectedAddress(state)
|
||||
|
||||
let tabToConnect
|
||||
if (url && permittedAccounts.length === 0 && !openMetaMaskTabs[id]) {
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { flatten, forOwn } from 'lodash'
|
||||
import { NETWORK_TYPES } from '../helpers/constants/common'
|
||||
import { stripHexPrefix, addHexPrefix } from 'ethereumjs-util'
|
||||
import { createSelector } from 'reselect'
|
||||
@ -7,7 +8,6 @@ import { multiplyCurrencies } from '../helpers/utils/conversion-util'
|
||||
import {
|
||||
addressSlicer,
|
||||
checksumAddress,
|
||||
formatDate,
|
||||
getOriginFromUrl,
|
||||
getAccountByAddress,
|
||||
} from '../helpers/utils/util'
|
||||
@ -465,59 +465,6 @@ export function getPermittedAccountsForCurrentTab (state) {
|
||||
return permittedAccountsMap[originOfCurrentTab] || []
|
||||
}
|
||||
|
||||
export function getRenderablePermissionsDomains (state) {
|
||||
const {
|
||||
domains = {},
|
||||
domainMetadata,
|
||||
permissionsHistory,
|
||||
permissionsDescriptions,
|
||||
selectedAddress,
|
||||
} = state.metamask
|
||||
|
||||
const renderableDomains = Object.keys(domains).reduce((acc, domainKey) => {
|
||||
const { permissions } = domains[domainKey]
|
||||
const permissionsWithCaveatsForSelectedAddress = permissions.filter((perm) => {
|
||||
const caveats = perm.caveats || []
|
||||
const exposedAccountCaveat = caveats.find((caveat) => caveat.name === 'exposedAccounts')
|
||||
const exposedAccountCaveatValue = exposedAccountCaveat && exposedAccountCaveat.value && exposedAccountCaveat.value.length
|
||||
? exposedAccountCaveat.value[0]
|
||||
: {}
|
||||
return exposedAccountCaveatValue === selectedAddress
|
||||
})
|
||||
|
||||
if (permissionsWithCaveatsForSelectedAddress.length) {
|
||||
const permissionKeys = permissions.map((permission) => permission.parentCapability)
|
||||
const {
|
||||
name,
|
||||
icon,
|
||||
extensionId,
|
||||
} = domainMetadata[domainKey] || {}
|
||||
const permissionsHistoryForDomain = permissionsHistory[domainKey] || {}
|
||||
const ethAccountsPermissionsForDomain = permissionsHistoryForDomain['eth_accounts'] || {}
|
||||
const accountsLastConnectedTime = ethAccountsPermissionsForDomain.accounts || {}
|
||||
const selectedAddressLastConnectedTime = accountsLastConnectedTime[selectedAddress]
|
||||
|
||||
const lastConnectedTime = selectedAddressLastConnectedTime
|
||||
? formatDate(selectedAddressLastConnectedTime, 'yyyy-MM-dd')
|
||||
: ''
|
||||
|
||||
return [ ...acc, {
|
||||
name: name || domainKey,
|
||||
secondaryName: name ? domainKey : '',
|
||||
icon,
|
||||
key: domainKey,
|
||||
lastConnectedTime,
|
||||
permissionDescriptions: permissionKeys.map((permissionKey) => permissionsDescriptions[permissionKey]),
|
||||
extensionId,
|
||||
}]
|
||||
} else {
|
||||
return acc
|
||||
}
|
||||
}, [])
|
||||
|
||||
return renderableDomains
|
||||
}
|
||||
|
||||
export function getOriginOfCurrentTab (state) {
|
||||
const { activeTab } = state
|
||||
return activeTab && activeTab.url && getOriginFromUrl(activeTab.url)
|
||||
@ -538,3 +485,37 @@ export function getLastConnectedInfo (state) {
|
||||
export function getIpfsGateway (state) {
|
||||
return state.metamask.ipfsGateway
|
||||
}
|
||||
|
||||
export function getConnectedDomainsForSelectedAddress (state) {
|
||||
const {
|
||||
domains = {},
|
||||
domainMetadata,
|
||||
selectedAddress,
|
||||
} = state.metamask
|
||||
|
||||
const connectedDomains = []
|
||||
|
||||
forOwn(domains, (value, domain) => {
|
||||
const exposedAccounts = flatten(value.permissions.map(
|
||||
(p) => p.caveats?.find(({ name }) => name === 'exposedAccounts').value || []
|
||||
))
|
||||
if (!exposedAccounts.includes(selectedAddress)) {
|
||||
return
|
||||
}
|
||||
|
||||
const {
|
||||
extensionId,
|
||||
name,
|
||||
icon,
|
||||
} = domainMetadata[domain] || {}
|
||||
|
||||
connectedDomains.push({
|
||||
extensionId,
|
||||
key: domain,
|
||||
name,
|
||||
icon,
|
||||
})
|
||||
})
|
||||
|
||||
return connectedDomains
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import assert from 'assert'
|
||||
import { getAddressBook } from '../selectors.js'
|
||||
import { getAddressBook, getConnectedDomainsForSelectedAddress } from '../selectors.js'
|
||||
import mockState from './selectors-test-data'
|
||||
|
||||
describe('selectors', function () {
|
||||
@ -21,4 +21,154 @@ describe('selectors', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('getConnectedDomainsForSelectedAddress', function () {
|
||||
it('should return the list of connected domains when there is 1 connected account', function () {
|
||||
const mockState = {
|
||||
metamask: {
|
||||
selectedAddress: '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5',
|
||||
domainMetadata: {
|
||||
'peepeth.com': {
|
||||
'icon': 'https://peepeth.com/favicon-32x32.png',
|
||||
'name': 'Peepeth',
|
||||
},
|
||||
'remix.ethereum.org': {
|
||||
'icon': 'https://remix.ethereum.org/icon.png',
|
||||
'name': 'Remix - Ethereum IDE',
|
||||
},
|
||||
},
|
||||
domains: {
|
||||
'peepeth.com': {
|
||||
'permissions': [
|
||||
{
|
||||
'@context': [
|
||||
'https://github.com/MetaMask/rpc-cap',
|
||||
],
|
||||
'caveats': [
|
||||
{
|
||||
'name': 'exposedAccounts',
|
||||
'type': 'filterResponse',
|
||||
'value': [
|
||||
'0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5',
|
||||
],
|
||||
},
|
||||
],
|
||||
'date': 1585676177970,
|
||||
'id': '840d72a0-925f-449f-830a-1aa1dd5ce151',
|
||||
'invoker': 'peepeth.com',
|
||||
'parentCapability': 'eth_accounts',
|
||||
},
|
||||
],
|
||||
},
|
||||
'remix.ethereum.org': {
|
||||
'permissions': [
|
||||
{
|
||||
'@context': [
|
||||
'https://github.com/MetaMask/rpc-cap',
|
||||
],
|
||||
'caveats': [
|
||||
{
|
||||
'type': 'filterResponse',
|
||||
'value': [
|
||||
'0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5',
|
||||
],
|
||||
'name': 'exposedAccounts',
|
||||
},
|
||||
],
|
||||
'date': 1585685128948,
|
||||
'id': '6b9615cc-64e4-4317-afab-3c4f8ee0244a',
|
||||
'invoker': 'remix.ethereum.org',
|
||||
'parentCapability': 'eth_accounts',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
const extensionId = undefined
|
||||
assert.deepEqual(getConnectedDomainsForSelectedAddress(mockState), [{
|
||||
extensionId,
|
||||
icon: 'https://peepeth.com/favicon-32x32.png',
|
||||
key: 'peepeth.com',
|
||||
name: 'Peepeth',
|
||||
}, {
|
||||
extensionId,
|
||||
name: 'Remix - Ethereum IDE',
|
||||
icon: 'https://remix.ethereum.org/icon.png',
|
||||
key: 'remix.ethereum.org',
|
||||
}])
|
||||
})
|
||||
|
||||
it('should return the list of connected domains when there are 2 connected accounts', function () {
|
||||
const mockState = {
|
||||
metamask: {
|
||||
selectedAddress: '0x7250739de134d33ec7ab1ee592711e15098c9d2d',
|
||||
domainMetadata: {
|
||||
'peepeth.com': {
|
||||
'icon': 'https://peepeth.com/favicon-32x32.png',
|
||||
'name': 'Peepeth',
|
||||
},
|
||||
'remix.ethereum.org': {
|
||||
'icon': 'https://remix.ethereum.org/icon.png',
|
||||
'name': 'Remix - Ethereum IDE',
|
||||
},
|
||||
},
|
||||
domains: {
|
||||
'peepeth.com': {
|
||||
'permissions': [
|
||||
{
|
||||
'@context': [
|
||||
'https://github.com/MetaMask/rpc-cap',
|
||||
],
|
||||
'caveats': [
|
||||
{
|
||||
'name': 'exposedAccounts',
|
||||
'type': 'filterResponse',
|
||||
'value': [
|
||||
'0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5',
|
||||
],
|
||||
},
|
||||
],
|
||||
'date': 1585676177970,
|
||||
'id': '840d72a0-925f-449f-830a-1aa1dd5ce151',
|
||||
'invoker': 'peepeth.com',
|
||||
'parentCapability': 'eth_accounts',
|
||||
},
|
||||
],
|
||||
},
|
||||
'remix.ethereum.org': {
|
||||
'permissions': [
|
||||
{
|
||||
'@context': [
|
||||
'https://github.com/MetaMask/rpc-cap',
|
||||
],
|
||||
'caveats': [
|
||||
{
|
||||
'type': 'filterResponse',
|
||||
'value': [
|
||||
'0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5',
|
||||
'0x7250739de134d33ec7ab1ee592711e15098c9d2d',
|
||||
],
|
||||
'name': 'exposedAccounts',
|
||||
},
|
||||
],
|
||||
'date': 1585685128948,
|
||||
'id': '6b9615cc-64e4-4317-afab-3c4f8ee0244a',
|
||||
'invoker': 'remix.ethereum.org',
|
||||
'parentCapability': 'eth_accounts',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
const extensionId = undefined
|
||||
assert.deepEqual(getConnectedDomainsForSelectedAddress(mockState), [{
|
||||
extensionId,
|
||||
name: 'Remix - Ethereum IDE',
|
||||
icon: 'https://remix.ethereum.org/icon.png',
|
||||
key: 'remix.ethereum.org',
|
||||
}])
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user