aboutsummaryrefslogblamecommitdiffstats
path: root/ui/app/components/account-menu/index.js
blob: bcada41e3887a065843cca8b95f8da675b5048ab (plain) (tree)
1
2
3
4
5
6
7
8

                                            
                                              

                                                  
                                       

                                        


                                                                                  

                                                                               
                                     

 




                       
                         

                           
 



                                              
 



                            





                                                    



                                                        


   


                                                                   

                                                  
                                     



                                           
                                     
                                     


                                           
                                        
                                     

                                           

                                      
                                     

                                           

                                                                                      
      
   


                                            


                      
                 
            

                

                                                                               

                                        
        
                                   
                                               



                                     
                                   

               
                                                           

               



                                       
                                                                                   
                                            

             



                                          
                                                                                   
                                            
       


                           




                                                                                  

                                                                                 
                                                    
       

               



                                
                                                         
                                       

             



                                    
                                                                             
                                       



       
                                                    


               
                    


                      
 
                                                                                            

                                                                                 
                                        
                                                           
 
                                                                           








                                                                                  

                                                             

                                           
                                                                     
           
 








                                             
                                                           


                                                           
                                        
                                                    




        
                                                                          
                                                                     
                           
                                            





                                             
                                                          



               

 
                                                              

                     
                                                           
                                              


                                                              

                                                


                             
                             










                                                                   

                        
const inherits = require('util').inherits
const Component = require('react').Component
const connect = require('react-redux').connect
const { compose } = require('recompose')
const { withRouter } = require('react-router-dom')
const PropTypes = require('prop-types')
const h = require('react-hyperscript')
const actions = require('../../actions')
const { Menu, Item, Divider, CloseArea } = require('../dropdowns/components/menu')
const Identicon = require('../identicon')
const { formatBalance } = require('../../util')
const { ENVIRONMENT_TYPE_POPUP } = require('../../../../app/scripts/lib/enums')
const { getEnvironmentType } = require('../../../../app/scripts/lib/util')
const Tooltip = require('../tooltip')


const {
  SETTINGS_ROUTE,
  INFO_ROUTE,
  NEW_ACCOUNT_ROUTE,
  IMPORT_ACCOUNT_ROUTE,
  CONNECT_HARDWARE_ROUTE,
  DEFAULT_ROUTE,
} = require('../../routes')

module.exports = compose(
  withRouter,
  connect(mapStateToProps, mapDispatchToProps)
)(AccountMenu)

AccountMenu.contextTypes = {
  t: PropTypes.func,
}

inherits(AccountMenu, Component)
function AccountMenu () { Component.call(this) }

function mapStateToProps (state) {
  return {
    selectedAddress: state.metamask.selectedAddress,
    isAccountMenuOpen: state.metamask.isAccountMenuOpen,
    keyrings: state.metamask.keyrings,
    identities: state.metamask.identities,
    accounts: state.metamask.accounts,
  }
}

function mapDispatchToProps (dispatch) {
  return {
    toggleAccountMenu: () => dispatch(actions.toggleAccountMenu()),
    showAccountDetail: address => {
      dispatch(actions.showAccountDetail(address))
      dispatch(actions.hideSidebar())
      dispatch(actions.toggleAccountMenu())
    },
    lockMetamask: () => {
      dispatch(actions.lockMetamask())
      dispatch(actions.hideWarning())
      dispatch(actions.hideSidebar())
      dispatch(actions.toggleAccountMenu())
    },
    showConfigPage: () => {
      dispatch(actions.showConfigPage())
      dispatch(actions.hideSidebar())
      dispatch(actions.toggleAccountMenu())
    },
    showInfoPage: () => {
      dispatch(actions.showInfoPage())
      dispatch(actions.hideSidebar())
      dispatch(actions.toggleAccountMenu())
    },
    showRemoveAccountConfirmationModal: (identity) => {
      return dispatch(actions.showModal({ name: 'CONFIRM_REMOVE_ACCOUNT', identity }))
    },
  }
}

AccountMenu.prototype.render = function () {
  const {
    isAccountMenuOpen,
    toggleAccountMenu,
    lockMetamask,
    history,
  } = this.props

  return h(Menu, { className: 'account-menu', isShowing: isAccountMenuOpen }, [
    h(CloseArea, { onClick: toggleAccountMenu }),
    h(Item, {
      className: 'account-menu__header',
    }, [
      this.context.t('myAccounts'),
      h('button.account-menu__logout-button', {
        onClick: () => {
          lockMetamask()
          history.push(DEFAULT_ROUTE)
        },
      }, this.context.t('logout')),
    ]),
    h(Divider),
    h('div.account-menu__accounts', this.renderAccounts()),
    h(Divider),
    h(Item, {
      onClick: () => {
        toggleAccountMenu()
        history.push(NEW_ACCOUNT_ROUTE)
      },
      icon: h('img.account-menu__item-icon', { src: 'images/plus-btn-white.svg' }),
      text: this.context.t('createAccount'),
    }),
    h(Item, {
      onClick: () => {
        toggleAccountMenu()
        history.push(IMPORT_ACCOUNT_ROUTE)
      },
      icon: h('img.account-menu__item-icon', { src: 'images/import-account.svg' }),
      text: this.context.t('importAccount'),
    }),
    h(Item, {
      onClick: () => {
        toggleAccountMenu()
        if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP) {
          global.platform.openExtensionInBrowser(CONNECT_HARDWARE_ROUTE)
        } else {
          history.push(CONNECT_HARDWARE_ROUTE)
        }
      },
      icon: h('img.account-menu__item-icon', { src: 'images/connect-icon.svg' }),
      text: this.context.t('connectHardwareWallet'),
    }),
    h(Divider),
    h(Item, {
      onClick: () => {
        toggleAccountMenu()
        history.push(INFO_ROUTE)
      },
      icon: h('img', { src: 'images/mm-info-icon.svg' }),
      text: this.context.t('infoHelp'),
    }),
    h(Item, {
      onClick: () => {
        toggleAccountMenu()
        history.push(SETTINGS_ROUTE)
      },
      icon: h('img.account-menu__item-icon', { src: 'images/settings.svg' }),
      text: this.context.t('settings'),
    }),
  ])
}

AccountMenu.prototype.renderAccounts = function () {
  const {
    identities,
    accounts,
    selectedAddress,
    keyrings,
    showAccountDetail,
  } = this.props

  const accountOrder = keyrings.reduce((list, keyring) => list.concat(keyring.accounts), [])
  return accountOrder.filter(address => !!identities[address]).map((address) => {

    const identity = identities[address]
    const isSelected = identity.address === selectedAddress

    const balanceValue = accounts[address] ? accounts[address].balance : ''
    const formattedBalance = balanceValue ? formatBalance(balanceValue, 6) : '...'
    const simpleAddress = identity.address.substring(2).toLowerCase()

    const keyring = keyrings.find((kr) => {
      return kr.accounts.includes(simpleAddress) ||
        kr.accounts.includes(identity.address)
    })

    return h(
      'div.account-menu__account.menu__item--clickable',
      { onClick: () => showAccountDetail(identity.address) },
      [
        h('div.account-menu__check-mark', [
          isSelected ? h('div.account-menu__check-mark-icon') : null,
        ]),

        h(
          Identicon,
          {
            address: identity.address,
            diameter: 24,
          },
        ),

        h('div.account-menu__account-info', [
          h('div.account-menu__name', identity.name || ''),
          h('div.account-menu__balance', formattedBalance),
        ]),

        this.renderKeyringType(keyring),
        this.renderRemoveAccount(keyring, identity),
      ],
    )
  })
}

AccountMenu.prototype.renderRemoveAccount = function (keyring, identity) {
  // Any account that's not from the HD wallet Keyring can be removed
  const type = keyring.type
  const isRemovable = type !== 'HD Key Tree'
  if (isRemovable) {
    return h(Tooltip, {
      title: this.context.t('removeAccount'),
      position: 'bottom',
    }, [
        h('a.remove-account-icon', {
          onClick: (e) => this.removeAccount(e, identity),
        }, ''),
      ])
  }
  return null
}

AccountMenu.prototype.removeAccount = function (e, identity) {
  e.preventDefault()
  e.stopPropagation()
  const { showRemoveAccountConfirmationModal } = this.props
  showRemoveAccountConfirmationModal(identity)
}

AccountMenu.prototype.renderKeyringType = function (keyring) {
  try { // Sometimes keyrings aren't loaded yet:
    const type = keyring.type
    let label
    switch (type) {
      case 'Trezor Hardware':
      case 'Ledger Hardware':
        label = this.context.t('hardware')
      break
      case 'Simple Key Pair':
        label = this.context.t('imported')
      break
      default:
        label = ''
    }

    return label !== '' ? h('.keyring-label.allcaps', label) : null

  } catch (e) { return }
}