1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-27 21:00:13 +01:00
metamask-extension/ui/app/pages/send/send.component.js
Chi Kei Chan 931aaeb700 Add token selection to the send screen (#6445)
* Move send to pages/

* Fix unit tests

* Finish UI

* Integrate asset dropdown to send actions

* Remove console.log

* Hide asset change during edit

* Enable switch from send token to seand eth

* Enable switching from token to eth when editing

* Fix linter

* Fixing test

* Fix unit tests

* Fix linter

* Fix react warning; remove console.log

* fix flat test

* Add metrics

* Address code review comments

* Consistent spacing between send screen form rows.

* Reduce height of gas buttons on send screen.

* Make send screen gas button height dependent on size of contents.
2019-04-17 16:45:13 -02:30

231 lines
5.7 KiB
JavaScript

import React from 'react'
import PropTypes from 'prop-types'
import PersistentForm from '../../../lib/persistent-form'
import {
getAmountErrorObject,
getGasFeeErrorObject,
getToAddressForGasUpdate,
doesAmountErrorRequireUpdate,
} from './send.utils'
import SendHeader from './send-header'
import SendContent from './send-content'
import SendFooter from './send-footer'
export default class SendTransactionScreen extends PersistentForm {
static propTypes = {
amount: PropTypes.string,
amountConversionRate: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
]),
blockGasLimit: PropTypes.string,
conversionRate: PropTypes.number,
editingTransactionId: PropTypes.string,
from: PropTypes.object,
gasLimit: PropTypes.string,
gasPrice: PropTypes.string,
gasTotal: PropTypes.string,
history: PropTypes.object,
network: PropTypes.string,
primaryCurrency: PropTypes.string,
recentBlocks: PropTypes.array,
selectedAddress: PropTypes.string,
selectedToken: PropTypes.object,
tokenBalance: PropTypes.string,
tokenContract: PropTypes.object,
fetchBasicGasEstimates: PropTypes.func,
updateAndSetGasTotal: PropTypes.func,
updateSendErrors: PropTypes.func,
updateSendTokenBalance: PropTypes.func,
scanQrCode: PropTypes.func,
qrCodeDetected: PropTypes.func,
qrCodeData: PropTypes.object,
}
static contextTypes = {
t: PropTypes.func,
}
componentWillReceiveProps (nextProps) {
if (nextProps.qrCodeData) {
if (nextProps.qrCodeData.type === 'address') {
const scannedAddress = nextProps.qrCodeData.values.address.toLowerCase()
const currentAddress = this.props.to && this.props.to.toLowerCase()
if (currentAddress !== scannedAddress) {
this.props.updateSendTo(scannedAddress)
this.updateGas({ to: scannedAddress })
// Clean up QR code data after handling
this.props.qrCodeDetected(null)
}
}
}
}
updateGas ({ to: updatedToAddress, amount: value, data } = {}) {
const {
amount,
blockGasLimit,
editingTransactionId,
gasLimit,
gasPrice,
recentBlocks,
selectedAddress,
selectedToken = {},
to: currentToAddress,
updateAndSetGasLimit,
} = this.props
updateAndSetGasLimit({
blockGasLimit,
editingTransactionId,
gasLimit,
gasPrice,
recentBlocks,
selectedAddress,
selectedToken,
to: getToAddressForGasUpdate(updatedToAddress, currentToAddress),
value: value || amount,
data,
})
}
componentDidUpdate (prevProps) {
const {
amount,
amountConversionRate,
conversionRate,
from: { address, balance },
gasTotal,
network,
primaryCurrency,
selectedToken,
tokenBalance,
updateSendErrors,
updateSendTokenBalance,
tokenContract,
} = this.props
const {
from: { balance: prevBalance },
gasTotal: prevGasTotal,
tokenBalance: prevTokenBalance,
network: prevNetwork,
selectedToken: prevSelectedToken,
} = prevProps
const uninitialized = [prevBalance, prevGasTotal].every(n => n === null)
const amountErrorRequiresUpdate = doesAmountErrorRequireUpdate({
balance,
gasTotal,
prevBalance,
prevGasTotal,
prevTokenBalance,
selectedToken,
tokenBalance,
})
if (amountErrorRequiresUpdate) {
const amountErrorObject = getAmountErrorObject({
amount,
amountConversionRate,
balance,
conversionRate,
gasTotal,
primaryCurrency,
selectedToken,
tokenBalance,
})
const gasFeeErrorObject = selectedToken
? getGasFeeErrorObject({
amountConversionRate,
balance,
conversionRate,
gasTotal,
primaryCurrency,
selectedToken,
})
: { gasFee: null }
updateSendErrors(Object.assign(amountErrorObject, gasFeeErrorObject))
}
if (!uninitialized) {
if (network !== prevNetwork && network !== 'loading') {
updateSendTokenBalance({
selectedToken,
tokenContract,
address,
})
this.updateGas()
}
}
const prevTokenAddress = prevSelectedToken && prevSelectedToken.address
const selectedTokenAddress = selectedToken && selectedToken.address
if (selectedTokenAddress && prevTokenAddress !== selectedTokenAddress) {
this.updateSendToken()
}
}
componentDidMount () {
this.props.fetchBasicGasEstimates()
.then(() => {
this.updateGas()
})
}
componentWillMount () {
this.updateSendToken()
// Show QR Scanner modal if ?scan=true
if (window.location.search === '?scan=true') {
this.props.scanQrCode()
// Clear the queryString param after showing the modal
const cleanUrl = location.href.split('?')[0]
history.pushState({}, null, `${cleanUrl}`)
window.location.hash = '#send'
}
}
componentWillUnmount () {
this.props.resetSendState()
}
updateSendToken () {
const {
from: { address },
selectedToken,
tokenContract,
updateSendTokenBalance,
} = this.props
updateSendTokenBalance({
selectedToken,
tokenContract,
address,
})
}
render () {
const { history, showHexData } = this.props
return (
<div className="page-container">
<SendHeader history={history}/>
<SendContent
updateGas={(updateData) => this.updateGas(updateData)}
scanQrCode={_ => this.props.scanQrCode()}
showHexData={showHexData}
/>
<SendFooter history={history}/>
</div>
)
}
}