From c77029ea90560b4210f9204e99314d30f9b59989 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 26 Sep 2017 19:21:04 -0700 Subject: Implement Confirm Deploy Contract screen --- .../pending-tx/confirm-deploy-contract.js | 344 +++++++++++++++++++++ 1 file changed, 344 insertions(+) create mode 100644 ui/app/components/pending-tx/confirm-deploy-contract.js (limited to 'ui/app/components/pending-tx/confirm-deploy-contract.js') diff --git a/ui/app/components/pending-tx/confirm-deploy-contract.js b/ui/app/components/pending-tx/confirm-deploy-contract.js new file mode 100644 index 000000000..89a0389d7 --- /dev/null +++ b/ui/app/components/pending-tx/confirm-deploy-contract.js @@ -0,0 +1,344 @@ +const Component = require('react').Component +const { connect } = require('react-redux') +const h = require('react-hyperscript') +const inherits = require('util').inherits +const actions = require('../../actions') +const clone = require('clone') +const Identicon = require('../identicon') +const ethUtil = require('ethereumjs-util') +const BN = ethUtil.BN +const hexToBn = require('../../../../app/scripts/lib/hex-to-bn') +const { conversionUtil } = require('../../conversion-util') + +const MIN_GAS_PRICE_GWEI_BN = new BN(1) +const GWEI_FACTOR = new BN(1e9) +const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR) + + +module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmDeployContract) + +function mapStateToProps (state) { + const { + 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(actions.setCurrentCurrency('USD')), + backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)), + cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), + } +} + + +inherits(ConfirmDeployContract, Component) +function ConfirmDeployContract () { + Component.call(this) + this.state = {} + this.onSubmit = this.onSubmit.bind(this) +} + +ConfirmDeployContract.prototype.onSubmit = function (event) { + event.preventDefault() + const txMeta = this.gatherTxMeta() + const valid = this.checkValidity() + this.setState({ valid, submitting: true }) + + if (valid && this.verifyGasParams()) { + this.props.sendTransaction(txMeta, event) + } else { + this.props.dispatch(actions.displayWarning('Invalid Gas Parameters')) + this.setState({ submitting: false }) + } +} + +ConfirmDeployContract.prototype.cancel = function (event, txMeta) { + event.preventDefault() + this.props.cancelTransaction(txMeta) +} + +ConfirmDeployContract.prototype.checkValidity = function () { + const form = this.getFormEl() + const valid = form.checkValidity() + return valid +} + +ConfirmDeployContract.prototype.getFormEl = function () { + const form = document.querySelector('form#pending-tx-form') + // Stub out form for unit tests: + if (!form) { + return { checkValidity () { return true } } + } + return form +} + +// After a customizable state value has been updated, +ConfirmDeployContract.prototype.gatherTxMeta = function () { + const props = this.props + const state = this.state + const txData = clone(state.txData) || clone(props.txData) + + // log.debug(`UI has defaulted to tx meta ${JSON.stringify(txData)}`) + return txData +} + +ConfirmDeployContract.prototype.verifyGasParams = function () { + // We call this in case the gas has not been modified at all + if (!this.state) { return true } + return ( + this._notZeroOrEmptyString(this.state.gas) && + this._notZeroOrEmptyString(this.state.gasPrice) + ) +} + +ConfirmDeployContract.prototype._notZeroOrEmptyString = function (obj) { + return obj !== '' && obj !== '0x0' +} + +ConfirmDeployContract.prototype.bnMultiplyByFraction = function (targetBN, numerator, denominator) { + const numBN = new BN(numerator) + const denomBN = new BN(denominator) + return targetBN.mul(numBN).div(denomBN) +} + +ConfirmDeployContract.prototype.getData = function () { + const { identities } = this.props + const txMeta = this.gatherTxMeta() + const txParams = txMeta.txParams || {} + + return { + from: { + address: txParams.from, + name: identities[txParams.from].name, + }, + memo: txParams.memo || '', + } +} + +ConfirmDeployContract.prototype.getAmount = function () { + const { conversionRate } = this.props + const txMeta = this.gatherTxMeta() + const txParams = txMeta.txParams || {} + + const USD = conversionUtil(txParams.value, { + fromNumericBase: 'hex', + toNumericBase: 'dec', + fromCurrency: 'ETH', + toCurrency: 'USD', + numberOfDecimals: 2, + fromDenomination: 'WEI', + conversionRate, + }) + const ETH = conversionUtil(txParams.value, { + fromNumericBase: 'hex', + toNumericBase: 'dec', + fromCurrency: 'ETH', + toCurrency: 'ETH', + fromDenomination: 'WEI', + conversionRate, + numberOfDecimals: 6, + }) + + return { + fiat: Number(USD), + token: Number(ETH), + } + +} + +ConfirmDeployContract.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 USD = conversionUtil(txFeeBn, { + fromNumericBase: 'BN', + toNumericBase: 'dec', + fromDenomination: 'WEI', + fromCurrency: 'ETH', + toCurrency: 'USD', + numberOfDecimals: 2, + conversionRate, + }) + const ETH = conversionUtil(txFeeBn, { + fromNumericBase: 'BN', + toNumericBase: 'dec', + fromDenomination: 'WEI', + fromCurrency: 'ETH', + toCurrency: 'ETH', + numberOfDecimals: 6, + conversionRate, + }) + + return { + fiat: Number(USD), + eth: Number(ETH), + } +} +ConfirmDeployContract.prototype.renderGasFee = function () { + const { fiat: fiatGas, eth: ethGas } = this.getGasFee() + + return ( + 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', `$${fiatGas} USD`), + + h( + 'div.confirm-screen-row-detail', + `${ethGas} ETH` + ), + ]), + ]) + ) +} + +ConfirmDeployContract.prototype.renderHeroAmount = function () { + const { fiat: fiatAmount } = this.getAmount() + const txMeta = this.gatherTxMeta() + const txParams = txMeta.txParams || {} + const { memo = '' } = txParams + + return ( + h('div.confirm-send-token__hero-amount-wrapper', [ + h('h3.flex-center.confirm-screen-send-amount', `$${fiatAmount}`), + h('h3.flex-center.confirm-screen-send-amount-currency', 'USD'), + h('div.flex-center.confirm-memo-wrapper', [ + h('h3.confirm-screen-send-memo', memo), + ]), + ]) + ) +} + +ConfirmDeployContract.prototype.renderTotalPlusGas = function () { + const { fiat: fiatAmount, token: tokenAmount } = this.getAmount() + const { fiat: fiatGas, eth: ethGas } = this.getGasFee() + + return ( + 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.confirm-screen-section-column', [ + h('div.confirm-screen-row-info', `$${fiatAmount + fiatGas} USD`), + h('div.confirm-screen-row-detail', `${tokenAmount + ethGas} ETH`), + ]), + ]) + ) +} + +ConfirmDeployContract.prototype.render = function () { + const { backToAccountDetail, selectedAddress } = this.props + const txMeta = this.gatherTxMeta() + + const { + from: { + address: fromAddress, + name: fromName, + }, + } = this.getData() + + this.inputs = [] + + return ( + h('div.flex-column.flex-grow.confirm-screen-container', { + 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', { + 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( + Identicon, + { + address: fromAddress, + diameter: 100, + }, + ), + 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('i.fa.fa-file-text-o'), + h('span.confirm-screen-account-name', 'New Contract'), + h('span.confirm-screen-account-number', ' '), + ]), + ]), + + h('h3.flex-center.confirm-screen-sending-to-message', { + style: { + textAlign: 'center', + fontSize: '16px', + }, + }, [ + `You're deploying a new contract.`, + ]), + + this.renderHeroAmount(), + + 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('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', 'New Contract'), + ]), + ]), + + this.renderGasFee(), + + this.renderTotalPlusGas(), + + ]), + ]), + + h('form#pending-tx-form.flex-column.flex-center', { + onSubmit: this.onSubmit, + }, [ + + // Accept Button + h('button.confirm-screen-confirm-button', ['CONFIRM']), + + // Cancel Button + h('div.cancel.btn-light.confirm-screen-cancel-button', { + onClick: (event) => this.cancel(event, txMeta), + }, 'CANCEL'), + ]), + ]) + ) +} -- cgit From 06292107d756f0b25805f819cd276e4b6303ccb0 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Thu, 28 Sep 2017 16:13:53 -0700 Subject: Always set currency to USD on app mount --- ui/app/components/pending-tx/confirm-deploy-contract.js | 1 - 1 file changed, 1 deletion(-) (limited to 'ui/app/components/pending-tx/confirm-deploy-contract.js') diff --git a/ui/app/components/pending-tx/confirm-deploy-contract.js b/ui/app/components/pending-tx/confirm-deploy-contract.js index 89a0389d7..386e14afe 100644 --- a/ui/app/components/pending-tx/confirm-deploy-contract.js +++ b/ui/app/components/pending-tx/confirm-deploy-contract.js @@ -33,7 +33,6 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { - setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('USD')), backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)), cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), } -- cgit From c221f5ce79a1e24df4672e16bda8e85c434e11ba Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Tue, 10 Oct 2017 14:30:20 -0700 Subject: Confirm Token and Confirm Contract v2 --- .../pending-tx/confirm-deploy-contract.js | 33 +++++++++++----------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'ui/app/components/pending-tx/confirm-deploy-contract.js') diff --git a/ui/app/components/pending-tx/confirm-deploy-contract.js b/ui/app/components/pending-tx/confirm-deploy-contract.js index 386e14afe..ea4aa1dde 100644 --- a/ui/app/components/pending-tx/confirm-deploy-contract.js +++ b/ui/app/components/pending-tx/confirm-deploy-contract.js @@ -270,7 +270,8 @@ ConfirmDeployContract.prototype.render = function () { h('button.confirm-screen-back-button', { onClick: () => backToAccountDetail(selectedAddress), }, 'BACK'), - h('div.confirm-screen-title', 'Confirm Transaction'), + h('div.confirm-screen-title', 'Confirm Contract'), + h('div.confirm-screen-header-tip'), ]), h('div.flex-row.flex-center.confirm-screen-identicons', [ h('div.confirm-screen-account-wrapper', [ @@ -278,11 +279,11 @@ ConfirmDeployContract.prototype.render = function () { Identicon, { address: fromAddress, - diameter: 100, + diameter: 60, }, ), h('span.confirm-screen-account-name', fromName), - h('span.confirm-screen-account-number', fromAddress.slice(fromAddress.length - 4)), + // 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', [ @@ -292,14 +293,14 @@ ConfirmDeployContract.prototype.render = function () { ]), ]), - h('h3.flex-center.confirm-screen-sending-to-message', { - style: { - textAlign: 'center', - fontSize: '16px', - }, - }, [ - `You're deploying a new contract.`, - ]), + // h('h3.flex-center.confirm-screen-sending-to-message', { + // style: { + // textAlign: 'center', + // fontSize: '16px', + // }, + // }, [ + // `You're deploying a new contract.`, + // ]), this.renderHeroAmount(), @@ -326,17 +327,17 @@ ConfirmDeployContract.prototype.render = function () { ]), ]), - h('form#pending-tx-form.flex-column.flex-center', { + h('form#pending-tx-form', { onSubmit: this.onSubmit, }, [ - - // Accept Button - h('button.confirm-screen-confirm-button', ['CONFIRM']), - // Cancel Button h('div.cancel.btn-light.confirm-screen-cancel-button', { onClick: (event) => this.cancel(event, txMeta), }, 'CANCEL'), + + // Accept Button + h('button.confirm-screen-confirm-button', ['CONFIRM']), + ]), ]) ) -- cgit From 332c7441b656ec82ebfba863e3feb4dbf365d67b Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 18 Oct 2017 23:39:26 -0230 Subject: Get currency from state in account details, send and confirm screens. --- .../pending-tx/confirm-deploy-contract.js | 28 ++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'ui/app/components/pending-tx/confirm-deploy-contract.js') diff --git a/ui/app/components/pending-tx/confirm-deploy-contract.js b/ui/app/components/pending-tx/confirm-deploy-contract.js index ea4aa1dde..d19cec755 100644 --- a/ui/app/components/pending-tx/confirm-deploy-contract.js +++ b/ui/app/components/pending-tx/confirm-deploy-contract.js @@ -21,10 +21,12 @@ function mapStateToProps (state) { const { conversionRate, identities, + currentCurrency, } = state.metamask const accounts = state.metamask.accounts const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] return { + currentCurrency, conversionRate, identities, selectedAddress, @@ -124,15 +126,15 @@ ConfirmDeployContract.prototype.getData = function () { } ConfirmDeployContract.prototype.getAmount = function () { - const { conversionRate } = this.props + const { conversionRate, currentCurrency } = this.props const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} - const USD = conversionUtil(txParams.value, { + const FIAT = conversionUtil(txParams.value, { fromNumericBase: 'hex', toNumericBase: 'dec', fromCurrency: 'ETH', - toCurrency: 'USD', + toCurrency: currentCurrency, numberOfDecimals: 2, fromDenomination: 'WEI', conversionRate, @@ -148,14 +150,14 @@ ConfirmDeployContract.prototype.getAmount = function () { }) return { - fiat: Number(USD), + fiat: Number(FIAT), token: Number(ETH), } } ConfirmDeployContract.prototype.getGasFee = function () { - const { conversionRate } = this.props + const { conversionRate, currentCurrency } = this.props const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} @@ -169,12 +171,12 @@ ConfirmDeployContract.prototype.getGasFee = function () { const txFeeBn = gasBn.mul(gasPriceBn) - const USD = conversionUtil(txFeeBn, { + const FIAT = conversionUtil(txFeeBn, { fromNumericBase: 'BN', toNumericBase: 'dec', fromDenomination: 'WEI', fromCurrency: 'ETH', - toCurrency: 'USD', + toCurrency: currentCurrency, numberOfDecimals: 2, conversionRate, }) @@ -189,7 +191,7 @@ ConfirmDeployContract.prototype.getGasFee = function () { }) return { - fiat: Number(USD), + fiat: Number(FIAT), eth: Number(ETH), } } @@ -200,7 +202,7 @@ ConfirmDeployContract.prototype.renderGasFee = function () { 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', `$${fiatGas} USD`), + h('div.confirm-screen-row-info', `${fiatGas} FIAT`), h( 'div.confirm-screen-row-detail', @@ -212,6 +214,7 @@ ConfirmDeployContract.prototype.renderGasFee = function () { } ConfirmDeployContract.prototype.renderHeroAmount = function () { + const { currentCurrency } = this.props const { fiat: fiatAmount } = this.getAmount() const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} @@ -219,8 +222,8 @@ ConfirmDeployContract.prototype.renderHeroAmount = function () { return ( h('div.confirm-send-token__hero-amount-wrapper', [ - h('h3.flex-center.confirm-screen-send-amount', `$${fiatAmount}`), - h('h3.flex-center.confirm-screen-send-amount-currency', 'USD'), + h('h3.flex-center.confirm-screen-send-amount', `${fiatAmount}`), + h('h3.flex-center.confirm-screen-send-amount-currency', currentCurrency.toUpperCase()), h('div.flex-center.confirm-memo-wrapper', [ h('h3.confirm-screen-send-memo', memo), ]), @@ -229,6 +232,7 @@ ConfirmDeployContract.prototype.renderHeroAmount = function () { } ConfirmDeployContract.prototype.renderTotalPlusGas = function () { + const { currentCurrency } = this.props const { fiat: fiatAmount, token: tokenAmount } = this.getAmount() const { fiat: fiatGas, eth: ethGas } = this.getGasFee() @@ -240,7 +244,7 @@ ConfirmDeployContract.prototype.renderTotalPlusGas = function () { ]), h('div.confirm-screen-section-column', [ - h('div.confirm-screen-row-info', `$${fiatAmount + fiatGas} USD`), + h('div.confirm-screen-row-info', `${fiatAmount + fiatGas} ${currentCurrency.toUpperCase()}`), h('div.confirm-screen-row-detail', `${tokenAmount + ethGas} ETH`), ]), ]) -- cgit From 8f3b762461ada222f82089e686a61183dd167428 Mon Sep 17 00:00:00 2001 From: Chi Kei Chan Date: Fri, 20 Oct 2017 18:26:18 -0700 Subject: Fix Conversions bugs; Fiat value bugs --- ui/app/components/pending-tx/confirm-deploy-contract.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'ui/app/components/pending-tx/confirm-deploy-contract.js') diff --git a/ui/app/components/pending-tx/confirm-deploy-contract.js b/ui/app/components/pending-tx/confirm-deploy-contract.js index d19cec755..a0ba94045 100644 --- a/ui/app/components/pending-tx/confirm-deploy-contract.js +++ b/ui/app/components/pending-tx/confirm-deploy-contract.js @@ -195,14 +195,16 @@ ConfirmDeployContract.prototype.getGasFee = function () { eth: Number(ETH), } } + ConfirmDeployContract.prototype.renderGasFee = function () { + const { currentCurrency } = this.props const { fiat: fiatGas, eth: ethGas } = this.getGasFee() return ( 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', `${fiatGas} FIAT`), + h('div.confirm-screen-row-info', `${fiatGas} ${currentCurrency.toUpperCase()}`), h( 'div.confirm-screen-row-detail', -- cgit From 220da24f9ab4a57a10bc1fc3e249c511a98ecb46 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 26 Oct 2017 13:36:34 -0230 Subject: Change min gas price to 0.1 GWEI --- ui/app/components/pending-tx/confirm-deploy-contract.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'ui/app/components/pending-tx/confirm-deploy-contract.js') diff --git a/ui/app/components/pending-tx/confirm-deploy-contract.js b/ui/app/components/pending-tx/confirm-deploy-contract.js index a0ba94045..ae6c6ef7b 100644 --- a/ui/app/components/pending-tx/confirm-deploy-contract.js +++ b/ui/app/components/pending-tx/confirm-deploy-contract.js @@ -10,9 +10,7 @@ const BN = ethUtil.BN const hexToBn = require('../../../../app/scripts/lib/hex-to-bn') const { conversionUtil } = require('../../conversion-util') -const MIN_GAS_PRICE_GWEI_BN = new BN(1) -const GWEI_FACTOR = new BN(1e9) -const MIN_GAS_PRICE_BN = MIN_GAS_PRICE_GWEI_BN.mul(GWEI_FACTOR) +const { MIN_GAS_PRICE_HEX } = require('../send/send-constants') module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmDeployContract) @@ -166,7 +164,7 @@ ConfirmDeployContract.prototype.getGasFee = function () { const gasBn = hexToBn(gas) // Gas Price - const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_BN.toString(16) + const gasPrice = txParams.gasPrice || MIN_GAS_PRICE_HEX const gasPriceBn = hexToBn(gasPrice) const txFeeBn = gasBn.mul(gasPriceBn) -- cgit