aboutsummaryrefslogblamecommitdiffstats
path: root/ui/app/send.js
blob: de9e64ad1807062480007f283ea4a80ad9933e92 (plain) (tree)
1
2
3
4
5
6
7
8
9
                                         
                                                        

                                              
                                                   


                                                       
                                                       
                                     
                                                      
                                                  
                                          


                                                         

                                                                
                                  
                
                                            


                                          
                                    
                                            
                                                  
                                                    

   

                                                               






                                                                                 
                                               
                                   
                           

 
                                                      

                                              







                          
                   
                    
           

          
 
                                    
              


                                                               
        
 

                                                  
                


                                                     
                                                    
         
          
                                           
                  

                                              
           




                            
           
 




                             
                  
                               
                             
            







                                
            


                                                           
 


                                
                             




                                          
 



                                
                             



                 
 
                             
                  

                                
                             


                

           




                                                                
                  
                             
            









                                                         
 

                                              






















                                                       
 
           
 
                                              






















                                                                         
 

           



                          




                                              







                                                                      










                                  
 
























                                                         
         
 
                                
                                            
 
                               






                                            
 
                               









                                                
      
 


   
                                                                       



                                                 
                                                    



                                                           




                                                                                     

 
                                                        
                                
                                                                                                                            
                                        

                                                                    




                                                                        
                                    
             

                          
                                   

                                                               
 




                                                               
                                                                                
                                             


                                                               
                                                         



                                                               
                                            
 

                                                                    
                  


                                     
 
                                                              
                                    
 

                                               
const inherits = require('util').inherits
const PersistentForm = require('../lib/persistent-form')
const h = require('react-hyperscript')
const connect = require('react-redux').connect
const Identicon = require('./components/identicon')
const actions = require('./actions')
const util = require('./util')
const numericBalance = require('./util').numericBalance
const addressSummary = require('./util').addressSummary
const isHex = require('./util').isHex
const EthBalance = require('./components/eth-balance')
const EnsInput = require('./components/ens-input')
const ethUtil = require('ethereumjs-util')

const ARAGON = '960b236A07cf122663c4303350609A66A7B288C0'

module.exports = connect(mapStateToProps)(SendTransactionScreen)

function mapStateToProps (state) {
  var result = {
    address: state.metamask.selectedAddress,
    accounts: state.metamask.accounts,
    identities: state.metamask.identities,
    warning: state.appState.warning,
    network: state.metamask.network,
    addressBook: state.metamask.addressBook,
    conversionRate: state.metamask.conversionRate,
    currentCurrency: state.metamask.currentCurrency,
  }

  result.error = result.warning && result.warning.split('.')[0]

  result.account = result.accounts[result.address]
  result.identity = result.identities[result.address]
  result.balance = result.account ? numericBalance(result.account.balance) : null

  return result
}

inherits(SendTransactionScreen, PersistentForm)
function SendTransactionScreen () {
  PersistentForm.call(this)
}

SendTransactionScreen.prototype.render = function () {
  this.persistentFormParentId = 'send-tx-form'

  const props = this.props
  const {
    address,
    account,
    identity,
    network,
    identities,
    addressBook,
    conversionRate,
    currentCurrency,
  } = props

  return (

    h('div.flex-column.flex-grow', {
      style: {
        // overflow: 'scroll',
        minWidth: '355px', // TODO: maxWidth TBD, use home.html
      },
    }, [

      // Main Send token Card
      h('div.send-screen.flex-column.flex-grow', {
        style: {
          marginLeft: '3.5%',
          marginRight: '3.5%',
          background: '#FFFFFF', // $background-white
          boxShadow: '0 2px 4px 0 rgba(0,0,0,0.08)',
        }
      }, [
        h('section.flex-center.flex-row', {
          style: {
            zIndex: 15, // $token-icon-z-index
            marginTop: '-35px',
          }
        }, [
          h(Identicon, {
            address: ARAGON,
            diameter: 76,
          }),
        ]),

        //
        // Required Fields
        //

        h('h3.flex-center', {
          style: {
            marginTop: '-18px',
            fontSize: '16px',
          },
        }, [
          'Send Tokens',
        ]),

        h('h3.flex-center', {
          style: {
            textAlign: 'center',
            fontSize: '12px',
          },
        }, [
          'Send Tokens to anyone with an Ethereum account',
        ]),

        h('h3.flex-center', {
          style: {
            textAlign: 'center',
            marginTop: '2px',
            fontSize: '12px',
          },
        }, [
          'Your Aragon Token Balance is:',
        ]),

        h('h3.flex-center', {
          style: {
            textAlign: 'center',
            fontSize: '36px',
            marginTop: '8px',
          },
        }, [
          '2.34',
        ]),

        h('h3.flex-center', {
          style: {
            textAlign: 'center',
            fontSize: '12px',
            marginTop: '4px',
          },
        }, [
          'ANT',
        ]),

        // error message
        props.error && h('span.error.flex-center', props.error),

        // 'to' field
        h('section.flex-row.flex-center', {
          style: {
            fontSize: '12px',
          },
        }, [
          h(EnsInput, {
            name: 'address',
            placeholder: 'Recipient Address',
            onChange: this.recipientDidChange.bind(this),
            network,
            identities,
            addressBook,
          }),
        ]),

        // 'amount' and send button
        h('section.flex-column.flex-center', [
          h('div.flex-row.flex-center', {
            style: {
              fontSize: '12px',
              width: '100%',
              justifyContent: 'space-between',
            }
          },[
            h('span', { style: {} }, ['Amount']),
            h('span', { style: {} }, ['Token <> USD']),
          ]),

          h('input.large-input', {
            name: 'amount',
            placeholder: '0',
            type: 'number',
            style: {
              marginRight: '6px',
              fontSize: '12px',
            },
            dataset: {
              persistentFormId: 'tx-amount',
            },
          }),

        ]),

        h('section.flex-column.flex-center', [
          h('div.flex-row.flex-center', {
            style: {
              fontSize: '12px',
              width: '100%',
              justifyContent: 'space-between',
            }
          },[
            h('span', { style: {} }, ['Gas Fee:']),
            h('span', { style: { fontSize: '8px' } }, ['What\'s this?']),
          ]),

          h('input.large-input', {
            name: 'Gas Fee',
            placeholder: '0',
            type: 'number',
            style: {
              fontSize: '12px',
              marginRight: '6px',
            },
            // dataset: {
            //   persistentFormId: 'tx-amount',
            // },
          }),

        ]),

        //
        // Optional Fields
        //

        h('section.flex-column.flex-center', {
          style: {
            marginBottom: '10px',
          },
        }, [
          h('div.flex-row.flex-center', {
            style: {
              fontSize: '12px',
              width: '100%',
              justifyContent: 'flex-start',
            }
          },[
            h('span', { style: {} }, ['Transaction Memo (optional)']),
          ]),

          h('input.large-input', {
            name: 'memo',
            placeholder: '',
            type: 'string',
            style: {
              marginRight: '6px',
            },
          }),
        ]),

        // h('h3.flex-center.text-transform-uppercase', {
        //   style: {
        //     background: '#EBEBEB',
        //     color: '#AEAEAE',
        //     marginTop: '16px',
        //     marginBottom: '16px',
        //   },
        // }, [
        //   'Transaction Data (optional)',
        // ]),

        // // 'data' field
        // h('section.flex-column.flex-center', [
        //   h('input.large-input', {
        //     name: 'txData',
        //     placeholder: '0x01234',
        //     style: {
        //       width: '100%',
        //       resize: 'none',
        //     },
        //     dataset: {
        //       persistentFormId: 'tx-data',
        //     },
        //   }),
        // ]),
      ]),

      // Buttons underneath card
      h('section.flex-column.flex-center', [

        h('button.btn-light', {
          onClick: this.onSubmit.bind(this),
          style: {
            marginTop: '8px',
            width: '8em',
            background: '#FFFFFF'
          },
        }, 'Next'),

        h('button.btn-light', {
          onClick: this.back.bind(this),
          style: {
            background: '#F7F7F7', // $alabaster
            border: 'none',
            opacity: 1,
            width: '8em',
          },
        }, 'Cancel'),

      ]),
    ])

  )
}

SendTransactionScreen.prototype.navigateToAccounts = function (event) {
  event.stopPropagation()
  this.props.dispatch(actions.showAccountsPage())
}

SendTransactionScreen.prototype.back = function () {
  var address = this.props.address
  this.props.dispatch(actions.backToAccountDetail(address))
}

SendTransactionScreen.prototype.recipientDidChange = function (recipient, nickname) {
  this.setState({
    recipient: recipient,
    nickname: nickname,
  })
}

SendTransactionScreen.prototype.onSubmit = function () {
  const state = this.state || {}
  const recipient = state.recipient || document.querySelector('input[name="address"]').value.replace(/^[.\s]+|[.\s]+$/g, '')
  const nickname = state.nickname || ' '
  const input = document.querySelector('input[name="amount"]').value
  const value = util.normalizeEthStringToWei(input)
  // TODO: check with team on whether txData is removed completely.
  const txData = false;
  // Must replace with memo data.
  // const txData = document.querySelector('input[name="txData"]').value

  const balance = this.props.balance
  let message

  if (value.gt(balance)) {
    message = 'Insufficient funds.'
    return this.props.dispatch(actions.displayWarning(message))
  }

  if (input < 0) {
    message = 'Can not send negative amounts of ETH.'
    return this.props.dispatch(actions.displayWarning(message))
  }

  if ((!util.isValidAddress(recipient) && !txData) || (!recipient && !txData)) {
    message = 'Recipient address is invalid.'
    return this.props.dispatch(actions.displayWarning(message))
  }

  if (txData && !isHex(ethUtil.stripHexPrefix(txData))) {
    message = 'Transaction data must be hex string.'
    return this.props.dispatch(actions.displayWarning(message))
  }

  this.props.dispatch(actions.hideWarning())

  this.props.dispatch(actions.addToAddressBook(recipient, nickname))

  var txParams = {
    from: this.props.address,
    value: '0x' + value.toString(16),
  }

  if (recipient) txParams.to = ethUtil.addHexPrefix(recipient)
  if (txData) txParams.data = txData

  this.props.dispatch(actions.signTx(txParams))
}