Improve styling in Confirmation Screen; Show decoded send token data

feature/default_network_editable
Chi Kei Chan 7 years ago
parent b64471833f
commit 8b5f2a95df
  1. 1
      app/scripts/popup-core.js
  2. 2
      package.json
  3. 1
      ui/app/actions.js
  4. 339
      ui/app/components/pending-tx.js
  5. 104
      ui/app/css/itcss/components/confirm.scss

@ -49,7 +49,6 @@ function setupControllerConnection (connectionStream, cb) {
})
connectionStream.pipe(accountManagerDnode).pipe(connectionStream)
accountManagerDnode.once('remote', function (accountManager) {
console.log({ accountManager })
// setup push events
accountManager.on = eventEmitter.on.bind(eventEmitter)
cb(null, accountManager)

@ -49,6 +49,7 @@
]
},
"dependencies": {
"abi-decoder": "^1.0.8",
"async": "^2.5.0",
"await-semaphore": "^0.1.1",
"babel-runtime": "^6.23.0",
@ -92,6 +93,7 @@
"gulp-eslint": "^4.0.0",
"gulp-sass": "^3.1.0",
"hat": "0.0.3",
"human-standard-token-abi": "^1.0.2",
"idb-global": "^2.1.0",
"identicon.js": "^2.3.1",
"iframe": "^1.0.0",

@ -194,7 +194,6 @@ module.exports = actions
var background = null
function _setBackgroundConnection (backgroundConnection) {
background = backgroundConnection
console.log({ background })
}
function goHome () {

@ -1,12 +1,14 @@
const Component = require('react').Component
const { connect } = require('react-redux')
const h = require('react-hyperscript')
const abi = require('human-standard-token-abi')
const abiDecoder = require('abi-decoder')
abiDecoder.addABI(abi)
const inherits = require('util').inherits
const actions = require('../actions')
const clone = require('clone')
const FiatValue = require('./fiat-value')
const Identicon = require('./identicon')
const { setCurrentCurrency } = require('../actions')
const ethUtil = require('ethereumjs-util')
const BN = ethUtil.BN
@ -33,16 +35,19 @@ function mapStateToProps (state) {
conversionRate,
identities,
} = state.metamask
const accounts = state.metamask.accounts
const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0]
return {
conversionRate,
identities,
selectedAddress,
}
}
function mapDispatchToProps (dispatch) {
return {
setCurrentCurrencyToUSD: () => dispatch(setCurrentCurrency('USD'))
setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('USD')),
backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)),
}
}
@ -54,258 +59,242 @@ function PendingTx () {
txData: null,
submitting: false,
}
this.onSubmit = this.onSubmit.bind(this)
}
PendingTx.prototype.componentWillMount = function () {
this.props.setCurrentCurrencyToUSD()
}
PendingTx.prototype.render = function () {
const props = this.props
const { blockGasLimit, conversionRate, identities } = props
PendingTx.prototype.getTotal = function () {
const { conversionRate } = this.props
const txMeta = this.gatherTxMeta()
const txParams = txMeta.txParams || {}
const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data)
const { params = [] } = decodedData || {}
const { name, value } = params[1] || {}
const amountBn = name === '_value'
? new BN(value)
: hexToBn(txParams.value)
const USD = conversionUtil(amountBn, {
fromFormat: 'BN',
toCurrency: 'USD',
conversionRate,
})
const ETH = conversionUtil(amountBn, {
fromFormat: 'BN',
toCurrency: 'ETH',
conversionRate,
})
// Account Details
const address = txParams.from || props.selectedAddress
const account = props.accounts[address]
const balance = account ? account.balance : '0x0'
return {
USD,
ETH,
}
}
// recipient check
const isValidAddress = !txParams.to || util.isValidAddress(txParams.to)
PendingTx.prototype.getGasFee = function () {
const { conversionRate } = this.props
const txMeta = this.gatherTxMeta()
const txParams = txMeta.txParams || {}
// Gas
const gas = txParams.gas
const gasBn = hexToBn(gas)
// Gas Price
const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16)
const gasPriceBn = hexToBn(gasPrice)
const txFeeBn = gasBn.mul(gasPriceBn)
const amountBn = hexToBn(txParams.value)
// TODO: insufficient balance should be handled on send screen
// const maxCost = txFeeBn.add(amountBn)
// const balanceBn = hexToBn(balance)
// const insufficientBalance = balanceBn.lt(maxCost)
const fromName = identities[txParams.from].name
const to = identities[txParams.to]
const toName = to ? to.name : ' '
const endOfFromAddress = txParams.from.slice(txParams.from.length - 4)
const endOfToAddress = txParams.to.slice(txParams.to.length - 4)
const gasFeeInUSD = conversionUtil(txFeeBn, {
const USD = conversionUtil(txFeeBn, {
fromFormat: 'BN',
fromCurrency: 'GWEI',
toCurrency: 'USD',
conversionRate,
})
const gasFeeInETH = conversionUtil(txFeeBn, {
const ETH = conversionUtil(txFeeBn, {
fromFormat: 'BN',
fromCurrency: 'GWEI',
toCurrency: 'ETH',
conversionRate,
})
const totalInUSD = conversionUtil(amountBn, {
fromFormat: 'BN',
toCurrency: 'USD',
conversionRate,
})
const totalInETH = conversionUtil(amountBn, {
fromFormat: 'BN',
toCurrency: 'ETH',
conversionRate,
})
return {
USD,
ETH,
}
}
PendingTx.prototype.getData = function () {
const { identities } = this.props
const txMeta = this.gatherTxMeta()
const txParams = txMeta.txParams || {}
const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data)
const { name, params = [] } = decodedData || {}
const { type, value } = params[0] || {}
const { USD: gasFeeInUSD, ETH: gasFeeInETH } = this.getGasFee()
const { USD: totalInUSD, ETH: totalInETH } = this.getTotal()
if (name === 'transfer' && type === 'address') {
return {
from: {
address: txParams.from,
name: identities[txParams.from].name,
},
to: {
address: value,
name: identities[value] ? identities[value].name : 'New Recipient',
},
memo: txParams.memo || '',
gasFeeInUSD,
gasFeeInETH,
totalInUSD,
totalInETH,
}
} else {
return {
from: {
address: txParams.from,
name: identities[txParams.from].name,
},
to: {
address: txParams.to,
name: identities[txParams.to] ? identities[txParams.to].name : 'New Recipient',
},
memo: txParams.memo || '',
gasFeeInUSD,
gasFeeInETH,
totalInUSD,
totalInETH,
}
}
}
PendingTx.prototype.render = function () {
const { backToAccountDetail, selectedAddress } = this.props
const txMeta = this.gatherTxMeta()
const txParams = txMeta.txParams || {}
// recipient check
// const isValidAddress = !txParams.to || util.isValidAddress(txParams.to)
const {
from: {
address: fromAddress,
name: fromName,
},
to: {
address: toAddress,
name: toName,
},
memo,
gasFeeInUSD,
gasFeeInETH,
totalInUSD,
totalInETH,
} = this.getData()
this.inputs = []
return (
h('div.flex-column.flex-grow.confirm-screen-container', {
style: {
// overflow: 'scroll',
minWidth: '355px', // TODO: maxWidth TBD, use home.html
},
style: { minWidth: '355px' },
}, [
// Main Send token Card
h('div.confirm-screen-wrapper.flex-column.flex-grow', {}, [
h('h3.flex-center.confirm-screen-header', {}, [
h('button.confirm-screen-back-button', {}, 'BACK'),
h('div.confirm-screen-title', {}, 'Confirm Transaction'),
h('div.confirm-screen-wrapper.flex-column.flex-grow', [
h('h3.flex-center.confirm-screen-header', [
h('button.confirm-screen-back-button', {
onClick: () => backToAccountDetail(selectedAddress),
}, 'BACK'),
h('div.confirm-screen-title', 'Confirm Transaction'),
]),
h('div.flex-row.flex-center.confirm-screen-identicons', {}, [
h('div.confirm-screen-account-wrapper', {}, [
h('div.flex-row.flex-center.confirm-screen-identicons', [
h('div.confirm-screen-account-wrapper', [
h(
Identicon,
{
address: txParams.from,
diameter: 64,
style: {},
address: fromAddress,
diameter: 100,
},
),
h('span.confirm-screen-account-name', {}, fromName),
h('span.confirm-screen-account-number', {}, endOfFromAddress),
h('span.confirm-screen-account-name', fromName),
h('span.confirm-screen-account-number', fromAddress.slice(fromAddress.length - 4)),
]),
h('i.fa.fa-arrow-right.fa-lg'),
h('div.confirm-screen-account-wrapper', {}, [
h('div.confirm-screen-account-wrapper', [
h(
Identicon,
{
address: txParams.to,
diameter: 64,
style: {},
diameter: 100,
},
),
h('span.confirm-screen-account-name', {}, toName),
h('span.confirm-screen-account-number', {}, endOfToAddress),
])
h('span.confirm-screen-account-name', toName),
h('span.confirm-screen-account-number', toAddress.slice(toAddress.length - 4)),
]),
]),
h('h3.flex-center.confirm-screen-sending-to-message', {
style: {
textAlign: 'center',
fontSize: '16px',
}
},
}, [
`You're sending to Recipient ...${endOfToAddress}`
`You're sending to Recipient ...${toAddress.slice(toAddress.length - 4)}`,
]),
h('h3.flex-center.confirm-screen-send-amount', {}, [`$${totalInUSD}`]),
h('h3.flex-center.confirm-screen-send-amount-currency', {}, [
'USD',
h('h3.flex-center.confirm-screen-send-amount', [`$${totalInUSD}`]),
h('h3.flex-center.confirm-screen-send-amount-currency', [ 'USD' ]),
h('div.flex-center.confirm-memo-wrapper', [
h('h3.confirm-screen-send-memo', [ memo ]),
]),
h('div.flex-center.confirm-memo-wrapper', {}, h(
'h3.confirm-screen-send-memo', {}, txParams.memo || 'Fake memo'
)),
// TODO: put this error message in the right place
// props.error && h('span.error.flex-center', props.error),
h('section.flex-row.flex-center.confirm-screen-row', {
}, [
h('div', {
style: {
width: '50%',
},
}, [
h('span.confirm-screen-label', {}, [
'From',
h('div.confirm-screen-rows', [
h('section.flex-row.flex-center.confirm-screen-row', [
h('span.confirm-screen-label.confirm-screen-section-column', [ 'From' ]),
h('div.confirm-screen-section-column', [
h('div.confirm-screen-row-info', fromName),
h('div.confirm-screen-row-detail', `...${fromAddress.slice(fromAddress.length - 4)}`),
]),
]),
h('div', {
style: {
width: '50%',
},
}, [
h('div.confirm-screen-row-info', {}, fromName),
h('div.confirm-screen-row-detail', {}, `...${endOfFromAddress}`),
]),
]),
h('section.flex-row.flex-center.confirm-screen-row', {
}, [
h('div', {
style: {
width: '50%',
},
}, [
h('span.confirm-screen-label', {}, [
'To',
h('section.flex-row.flex-center.confirm-screen-row', [
h('span.confirm-screen-label.confirm-screen-section-column', [ 'To' ]),
h('div.confirm-screen-section-column', [
h('div.confirm-screen-row-info', toName),
h('div.confirm-screen-row-detail', `...${toAddress.slice(toAddress.length - 4)}`),
]),
]),
h('div', {
style: {
width: '50%',
},
}, [
h('div.confirm-screen-row-info', {}, toName),
h('section.flex-row.flex-center.confirm-screen-row', [
h('span.confirm-screen-label.confirm-screen-section-column', [ 'Gas Fee' ]),
h('div.confirm-screen-section-column', [
h('div.confirm-screen-row-info', `$${gasFeeInUSD} USD`),
h('div.confirm-screen-row-detail', {}, `...${endOfToAddress}`),
]),
]),
h('section.flex-row.flex-center.confirm-screen-row', {
}, [
h('div', {
style: {
width: '50%',
},
}, [
h('span.confirm-screen-label', {}, [
'Gas Fee',
h('div.confirm-screen-row-detail', `${gasFeeInETH} ETH`),
]),
]),
h('div', {
style: {
width: '50%',
},
}, [
h('div.confirm-screen-row-info', {}, `$${gasFeeInUSD} USD`),
h('div.confirm-screen-row-detail', {}, `${gasFeeInETH} ETH`),
]),
]),
h('section.flex-row.flex-center.confirm-screen-total-box ', {}, [
h('div', {
style: {
width: '50%',
},
}, [
h('span.confirm-screen-label', {}, [
'Total ',
h('section.flex-row.flex-center.confirm-screen-total-box ', [
h('div.confirm-screen-section-column', [
h('span.confirm-screen-label', [ 'Total ' ]),
h('div.confirm-screen-total-box__subtitle', [ 'Amount + Gas' ]),
]),
h('div', {
style: {
textAlign: 'left',
fontSize: '8px',
},
}, [
'Amount + Gas',
h('div.confirm-screen-section-column', [
h('div.confirm-screen-row-info', `$${totalInUSD} USD`),
h('div.confirm-screen-row-detail', `${totalInETH} ETH`),
]),
]),
h('div', {
style: {
width: '50%',
},
}, [
h('div.confirm-screen-row-info', {}, `$${totalInUSD} USD`),
h('div.confirm-screen-row-detail', {}, `${totalInETH} ETH`),
]),
]),
]),
]), // end of container
]),
h('form#pending-tx-form.flex-column.flex-center', {
onSubmit: this.onSubmit.bind(this),
onSubmit: this.onSubmit,
}, [
// Reset Button
// h('button', {
@ -325,7 +314,7 @@ PendingTx.prototype.render = function () {
// Cancel Button
h('button.cancel.btn-light.confirm-screen-cancel-button', {}, 'CANCEL'),
]),
]) // end of minwidth wrapper
])
)
}

@ -4,6 +4,7 @@
@media screen and (max-width: 575px) {
margin-top: 35px;
width: 100%;
}
@media screen and (min-width: 576px) {
@ -14,30 +15,21 @@
.confirm-screen-wrapper {
display: flex;
flex-direction: column;
min-width: 320px;
min-height: 753px;
align-items: center;
z-index: 100;
top: 5%;
font-family: 'DIN NEXT';
margin-left: 3.5%;
margin-right: 3.5%;
background: $white;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .08);
padding-top: 20px;
padding-bottom: 31px;
// padding: 20px 24px 32px;
color: $scorpion;
width: 100%;
@media screen and (min-width: $break-large) {
width: 498px;
}
}
.confirm-screen-wrapper > h3,
.confirm-screen-wrapper > div,
.confirm-screen-wrapper > section {
margin-left: 23px;
margin-right: 23px;
}
.confirm-screen-wrapper > .confirm-screen-total-box {
margin-left: 10px;
margin-right: 10px;
@ -48,6 +40,7 @@
}
.confirm-screen-wrapper > .confirm-screen-header {
@media screen and (max-width: $break-small) {
margin-left: 8px;
}
@ -56,23 +49,30 @@
.confirm-screen-header {
font-size: 26px;
position: relative;
display: flex;
flex-flow: row nowrap;
align-items: center;
width: 100%;
padding: 20px 24px 0;
@media screen and (max-width: $break-small) {
font-size: 22px;
font-size: 22px;
}
}
.confirm-screen-title {
line-height: 27px;
@media screen and (max-width: $break-small) {
margin-left: 22px;
margin-right: 8px;
margin-left: 22px;
margin-right: 8px;
}
}
.confirm-screen-back-button {
background: $white;
border: 1px solid $dusty-gray;
left: 0;
left: 24px;
position: absolute;
text-align: center;
color: $black;
@ -82,7 +82,7 @@
width: 54px;
@media screen and (max-width: $break-small) {
margin-right: 12px;
margin-right: 12px;
}
}
@ -91,7 +91,12 @@
flex-direction: column;
}
.confirm-screen-account-name, .confirm-screen-row-info {
.confirm-screen-account-name {
margin-top: 12px;
}
.confirm-screen-account-name,
.confirm-screen-row-info {
font-size: 16px;
line-height: 24px;
color: $scorpion;
@ -106,11 +111,11 @@
}
.confirm-screen-identicons {
margin-top: 48px;
margin-top: 24px;
i {
align-self: start;
margin: 20px 14px 0 14px;
margin: 42px 14px 0;
}
}
@ -118,13 +123,14 @@
text-align: center;
font-size: 16px;
margin-top: 30px;
font-family: 'DIN NEXT Light';
}
.confirm-screen-send-amount {
font-size: 64px;
color: $scorpion;
margin-top: 12px;
line-height: 60px;
line-height: 60px;
text-align: center;
font-family: 'DIN NEXT Light';
}
@ -136,8 +142,9 @@
}
.confirm-memo-wrapper {
min-height: 24px;
width: 100%;
border-bottom: 1px solid $gallery;
border-bottom: 1px solid $alto;
}
.confirm-screen-send-memo {
@ -147,11 +154,12 @@
text-align: center;
margin-top: 21px;
margin-bottom: 18px;
font-family: 'DIN NEXT Light';
}
.confirm-screen-label {
font-size: 18px;
line-height: 25px;
font-size: 18px;
line-height: 40px;
color: $scorpion;
text-align: left;
}
@ -163,32 +171,60 @@ section .confirm-screen-account-number,
text-align: left;
}
.confirm-screen-rows {
display: flex;
flex-flow: column nowrap;
width: 100%;
padding: 0 24px 32px;
}
.confirm-screen-section-column {
flex: .5;
}
.confirm-screen-row {
margin-top: 15px;
margin-bottom: 11.5px;
display: flex;
flex-flow: row nowrap;
border-bottom: 1px solid $alto;
width: calc(100% - 24px);
align-items: center;
padding: 12px 0;
margin: 0 12px;
}
.confirm-screen-row-detail {
font-size: 12px;
line-height: 16px;
color: $dusty-gray;
font-family: 'DIN NEXT Light';
}
.confirm-screen-total-box {
background-color: $wild-sand;
border-radius: 8px;
margin-left: 10px;
margin-right: 10px;
padding: 22px 14px 22px;
margin-bottom: 10px;
padding: 22px 14px;
margin-top: 13px;
.confirm-screen-label {
line-height: 18px;
}
.confirm-screen-row-detail {
color: $scorpion;
}
&__subtitle {
font-size: 14px;
line-height: 20px;
font-family: 'DIN NEXT Light';
}
}
.confirm-screen-confirm-button {
height: 62px;
width: 216.88px;
border-radius: 2px;
background-color: #02C9B1;
background-color: #02c9b1;
font-size: 16px;
color: $white;
text-align: center;
@ -218,7 +254,3 @@ section .confirm-screen-account-number,
#pending-tx-form {
flex: 1 0 auto;
}
.confirm-screen-row + .confirm-screen-row {
border-top: 1px solid $gallery;
}

Loading…
Cancel
Save