Merge remote-tracking branch 'origin/develop' into Version-v8.0.0

* origin/develop:
  feature/sync imported accounts with mobile (#8631)
  Fix account order on unconnected account alert (#8863)
feature/default_network_editable
Mark Stacey 4 years ago
commit 7ac0014de8
  1. 7
      app/scripts/metamask-controller.js
  2. 4
      ui/app/components/app/alerts/unconnected-account-alert/unconnected-account-alert.js
  3. 20
      ui/app/pages/mobile-sync/mobile-sync.component.js
  4. 5
      ui/app/pages/mobile-sync/mobile-sync.container.js
  5. 10
      ui/app/selectors/permissions.js
  6. 28
      ui/app/store/actions.js

@ -725,10 +725,15 @@ export default class MetamaskController extends EventEmitter {
// Accounts // Accounts
const hdKeyring = this.keyringController.getKeyringsByType('HD Key Tree')[0] const hdKeyring = this.keyringController.getKeyringsByType('HD Key Tree')[0]
const simpleKeyPairKeyrings = this.keyringController.getKeyringsByType('Simple Key Pair')
const hdAccounts = await hdKeyring.getAccounts() const hdAccounts = await hdKeyring.getAccounts()
const simpleKeyPairKeyringAccounts = await Promise.all(
simpleKeyPairKeyrings.map((keyring) => keyring.getAccounts())
)
const simpleKeyPairAccounts = simpleKeyPairKeyringAccounts.reduce((acc, accounts) => [...acc, ...accounts], [])
const accounts = { const accounts = {
hd: hdAccounts.filter((item, pos) => (hdAccounts.indexOf(item) === pos)).map((address) => ethUtil.toChecksumAddress(address)), hd: hdAccounts.filter((item, pos) => (hdAccounts.indexOf(item) === pos)).map((address) => ethUtil.toChecksumAddress(address)),
simpleKeyPair: [], simpleKeyPair: simpleKeyPairAccounts.filter((item, pos) => (simpleKeyPairAccounts.indexOf(item) === pos)).map((address) => ethUtil.toChecksumAddress(address)),
ledger: [], ledger: [],
trezor: [], trezor: [],
} }

@ -11,7 +11,7 @@ import {
} from '../../../../ducks/alerts/unconnected-account' } from '../../../../ducks/alerts/unconnected-account'
import { import {
getOriginOfCurrentTab, getOriginOfCurrentTab,
getPermittedIdentitiesForCurrentTab, getOrderedConnectedAccountsForActiveTab,
getSelectedAddress, getSelectedAddress,
getSelectedIdentity, getSelectedIdentity,
} from '../../../../selectors' } from '../../../../selectors'
@ -32,7 +32,7 @@ const UnconnectedAccountAlert = () => {
const t = useI18nContext() const t = useI18nContext()
const dispatch = useDispatch() const dispatch = useDispatch()
const alertState = useSelector(getAlertState) const alertState = useSelector(getAlertState)
const connectedAccounts = useSelector(getPermittedIdentitiesForCurrentTab) const connectedAccounts = useSelector(getOrderedConnectedAccountsForActiveTab)
const origin = useSelector(getOriginOfCurrentTab) const origin = useSelector(getOriginOfCurrentTab)
const selectedIdentity = useSelector(getSelectedIdentity) const selectedIdentity = useSelector(getSelectedIdentity)
const selectedAddress = useSelector(getSelectedAddress) const selectedAddress = useSelector(getSelectedAddress)

@ -25,6 +25,8 @@ export default class MobileSyncPage extends Component {
fetchInfoToSync: PropTypes.func.isRequired, fetchInfoToSync: PropTypes.func.isRequired,
mostRecentOverviewPage: PropTypes.string.isRequired, mostRecentOverviewPage: PropTypes.string.isRequired,
requestRevealSeedWords: PropTypes.func.isRequired, requestRevealSeedWords: PropTypes.func.isRequired,
exportAccounts: PropTypes.func.isRequired,
keyrings: PropTypes.array,
} }
@ -32,6 +34,7 @@ export default class MobileSyncPage extends Component {
screen: PASSWORD_PROMPT_SCREEN, screen: PASSWORD_PROMPT_SCREEN,
password: '', password: '',
seedWords: null, seedWords: null,
importedAccounts: [],
error: null, error: null,
syncing: false, syncing: false,
completed: false, completed: false,
@ -62,11 +65,25 @@ export default class MobileSyncPage extends Component {
.then((seedWords) => { .then((seedWords) => {
this.startKeysGeneration() this.startKeysGeneration()
this.startIdleTimeout() this.startIdleTimeout()
this.setState({ seedWords, screen: REVEAL_SEED_SCREEN }) this.exportAccounts()
.then((importedAccounts) => {
this.setState({ seedWords, importedAccounts, screen: REVEAL_SEED_SCREEN })
})
}) })
.catch((error) => this.setState({ error: error.message })) .catch((error) => this.setState({ error: error.message }))
} }
async exportAccounts () {
const addresses = []
this.props.keyrings.forEach((keyring) => {
if (keyring.type === 'Simple Key Pair') {
addresses.push(keyring.accounts[0])
}
})
const importedAccounts = await this.props.exportAccounts(this.state.password, addresses)
return importedAccounts
}
startKeysGeneration () { startKeysGeneration () {
this.keysGenerationTimeout && clearTimeout(this.keysGenerationTimeout) this.keysGenerationTimeout && clearTimeout(this.keysGenerationTimeout)
this.disconnectWebsockets() this.disconnectWebsockets()
@ -201,6 +218,7 @@ export default class MobileSyncPage extends Component {
udata: { udata: {
pwd: this.state.password, pwd: this.state.password,
seed: this.state.seedWords, seed: this.state.seedWords,
importedAccounts: this.state.importedAccounts,
}, },
}) })

@ -1,13 +1,15 @@
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { displayWarning, requestRevealSeedWords, fetchInfoToSync } from '../../store/actions' import { displayWarning, requestRevealSeedWords, fetchInfoToSync, exportAccounts } from '../../store/actions'
import MobileSyncPage from './mobile-sync.component' import MobileSyncPage from './mobile-sync.component'
import { getMostRecentOverviewPage } from '../../ducks/history/history' import { getMostRecentOverviewPage } from '../../ducks/history/history'
import { getMetaMaskKeyrings } from '../../selectors'
const mapDispatchToProps = (dispatch) => { const mapDispatchToProps = (dispatch) => {
return { return {
requestRevealSeedWords: (password) => dispatch(requestRevealSeedWords(password)), requestRevealSeedWords: (password) => dispatch(requestRevealSeedWords(password)),
fetchInfoToSync: () => dispatch(fetchInfoToSync()), fetchInfoToSync: () => dispatch(fetchInfoToSync()),
displayWarning: (message) => dispatch(displayWarning(message || null)), displayWarning: (message) => dispatch(displayWarning(message || null)),
exportAccounts: (password, addresses) => dispatch(exportAccounts(password, addresses)),
} }
} }
@ -21,6 +23,7 @@ const mapStateToProps = (state) => {
return { return {
mostRecentOverviewPage: getMostRecentOverviewPage(state), mostRecentOverviewPage: getMostRecentOverviewPage(state),
selectedAddress, selectedAddress,
keyrings: getMetaMaskKeyrings(state),
} }
} }

@ -1,5 +1,5 @@
import { forOwn } from 'lodash' import { forOwn } from 'lodash'
import { getMetaMaskAccountsOrdered, getMetaMaskIdentities, getOriginOfCurrentTab, getSelectedAddress } from '.' import { getMetaMaskAccountsOrdered, getOriginOfCurrentTab, getSelectedAddress } from '.'
import { import {
CAVEAT_NAMES, CAVEAT_NAMES,
} from '../../../app/scripts/controllers/permissions/enums' } from '../../../app/scripts/controllers/permissions/enums'
@ -119,14 +119,6 @@ export function getConnectedDomainsForSelectedAddress (state) {
return connectedDomains return connectedDomains
} }
export function getPermittedIdentitiesForCurrentTab (state) {
const permittedAccounts = getPermittedAccountsForCurrentTab(state)
const identities = getMetaMaskIdentities(state)
return permittedAccounts
.map((address) => identities[address])
.filter((identity) => Boolean(identity))
}
/** /**
* Returns an object mapping addresses to objects mapping origins to connected * Returns an object mapping addresses to objects mapping origins to connected
* domain info. Domain info objects have the following properties: * domain info. Domain info objects have the following properties:

@ -1708,6 +1708,34 @@ export function exportAccount (password, address) {
} }
} }
export function exportAccounts (password, addresses) {
return function (dispatch) {
log.debug(`background.submitPassword`)
return new Promise((resolve, reject) => {
background.submitPassword(password, function (err) {
if (err) {
log.error('Error in submitting password.')
return reject(err)
}
log.debug(`background.exportAccounts`)
const accountPromises = addresses.map((address) =>
new Promise(
(resolve, reject) => background.exportAccount(address, function (err, result) {
if (err) {
log.error(err)
dispatch(displayWarning('Had a problem exporting the account.'))
return reject(err)
}
return resolve(result)
})
)
)
return resolve(Promise.all(accountPromises))
})
})
}
}
export function showPrivateKey (key) { export function showPrivateKey (key) {
return { return {
type: actionConstants.SHOW_PRIVATE_KEY, type: actionConstants.SHOW_PRIVATE_KEY,

Loading…
Cancel
Save