From 8c4938d9c6fd2e6692ec1058b0d35d64fb717de8 Mon Sep 17 00:00:00 2001 From: Afri Date: Tue, 18 Apr 2017 12:18:30 +0200 Subject: [PATCH] [beta] registry backports (#5445) * Fixes to the Registry dapp (#4984) * Don't show fee warning when there is none * Hide Warning in Registry onclick * Use the default account in the Registry * Fix Etherscan links in Regsitry * Fix references to api outside of `parity.js` (#4981) --- js/src/api/subscriptions/personal.js | 2 +- js/src/dapps/registry/Accounts/accounts.css | 18 +--- js/src/dapps/registry/Accounts/accounts.js | 83 ++++++------------- js/src/dapps/registry/Accounts/actions.js | 23 +++++ .../registry/Application/application.css | 5 +- .../dapps/registry/Application/application.js | 47 +++++++++-- js/src/dapps/registry/Names/actions.js | 14 ++-- js/src/dapps/registry/Records/actions.js | 8 +- js/src/dapps/registry/Reverse/actions.js | 16 ++-- .../registry/addresses/accounts-reducer.js | 4 +- js/src/dapps/registry/util/etherscan-url.js | 2 +- js/src/dapps/tokenreg/Accounts/actions.js | 2 +- js/src/dapps/tokenreg/Status/actions.js | 3 +- js/src/dapps/tokenreg/Status/status.js | 3 +- js/src/dapps/tokenreg/Tokens/actions.js | 3 +- 15 files changed, 124 insertions(+), 109 deletions(-) diff --git a/js/src/api/subscriptions/personal.js b/js/src/api/subscriptions/personal.js index 15b037b42c2..fa7ae823ca9 100644 --- a/js/src/api/subscriptions/personal.js +++ b/js/src/api/subscriptions/personal.js @@ -42,7 +42,7 @@ export default class Personal { // FIXME: Because of the different API instances, the "wait for valid changes" approach // doesn't work. Since the defaultAccount is critical to operation, we poll in exactly - // same way we do in ../eth (ala same as eth_blockNumber) and update. This should be moved + // same way we do in ../eth (ala eth_blockNumber) and update. This should be moved // to pub-sub as it becomes available _defaultAccount = (timerDisabled = false) => { const nextTimeout = (timeout = 1000) => { diff --git a/js/src/dapps/registry/Accounts/accounts.css b/js/src/dapps/registry/Accounts/accounts.css index d69c25e2b99..d886138f0d0 100644 --- a/js/src/dapps/registry/Accounts/accounts.css +++ b/js/src/dapps/registry/Accounts/accounts.css @@ -15,24 +15,10 @@ /* along with Parity. If not, see . */ -.button { - /* TODO remove !important once material design lite is used */ - padding: 0 !important; -} - .icon { /* TODO remove !important once material design lite is used */ + height: 30px !important; margin: 0 !important; + padding: 0 !important; width: 30px !important; - height: 30px !important; -} - -.menuIcon { - display: inline-block; - vertical-align: middle; -} -.menuText { - display: inline-block; - line-height: 24px; - vertical-align: top; } diff --git a/js/src/dapps/registry/Accounts/accounts.js b/js/src/dapps/registry/Accounts/accounts.js index 0651f6857f2..b17ad63b1bd 100644 --- a/js/src/dapps/registry/Accounts/accounts.js +++ b/js/src/dapps/registry/Accounts/accounts.js @@ -17,83 +17,50 @@ import React, { Component, PropTypes } from 'react'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import IconMenu from 'material-ui/IconMenu'; -import IconButton from 'material-ui/IconButton/IconButton'; import AccountIcon from 'material-ui/svg-icons/action/account-circle'; -import MenuItem from 'material-ui/MenuItem'; +import { init } from './actions'; import IdentityIcon from '../IdentityIcon'; -import Address from '../ui/address'; -import { select } from './actions'; import styles from './accounts.css'; class Accounts extends Component { static propTypes = { - all: PropTypes.object.isRequired, - selected: PropTypes.object, + selected: PropTypes.oneOfType([ + PropTypes.oneOf([ null ]), + PropTypes.string + ]), + onInit: PropTypes.func.isRequired + }; - select: PropTypes.func.isRequired + componentWillMount () { + this.props.onInit(); } render () { - const { all, selected } = this.props; - - const origin = { horizontal: 'right', vertical: 'top' }; + const { selected } = this.props; - const accountsButton = ( - - { selected - ? ( - - ) : ( - - ) - } - ); + if (!selected) { + return ( + + ); + } return ( - - { Object.values(all).map(this.renderAccount) } - + ); } - - renderAccount = (account) => { - const { selected } = this.props; - const isSelected = selected && selected.address === account.address; - - return ( - -
- - ); - }; - - onAccountSelect = (e, address) => { - this.props.select(address); - }; } const mapStateToProps = (state) => state.accounts; -const mapDispatchToProps = (dispatch) => bindActionCreators({ select }, dispatch); +const mapDispatchToProps = (dispatch) => bindActionCreators({ + onInit: init +}, dispatch); export default connect(mapStateToProps, mapDispatchToProps)(Accounts); diff --git a/js/src/dapps/registry/Accounts/actions.js b/js/src/dapps/registry/Accounts/actions.js index bacd85f2e24..7f38de57991 100644 --- a/js/src/dapps/registry/Accounts/actions.js +++ b/js/src/dapps/registry/Accounts/actions.js @@ -14,4 +14,27 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +import { api } from '../parity'; + export const select = (address) => ({ type: 'accounts select', address }); + +export const init = () => (dispatch) => { + api.subscribe('parity_defaultAccount', (error, accountAddress) => { + if (error) { + return console.error(error); + } + + if (accountAddress) { + dispatch(select(accountAddress)); + } + }); + + return api.parity + .defaultAccount() + .then((accountAddress) => { + dispatch(select(accountAddress)); + }) + .catch((error) => { + console.error(error); + }); +}; diff --git a/js/src/dapps/registry/Application/application.css b/js/src/dapps/registry/Application/application.css index e4fc21a2676..b9fac12ae24 100644 --- a/js/src/dapps/registry/Application/application.css +++ b/js/src/dapps/registry/Application/application.css @@ -16,9 +16,11 @@ */ .header { + align-items: center; display: flex; justify-content: space-between; - margin: 0; padding: .3em 1em; + margin: 0; + padding: 0.3em 1em; color: #fff; background-color: #333; } @@ -54,6 +56,7 @@ background: #f80; bottom: 0; color: #fff; + cursor: pointer; left: 0; opacity: 1; padding: 1.5em; diff --git a/js/src/dapps/registry/Application/application.js b/js/src/dapps/registry/Application/application.js index e4f754dd67d..7857b1ad140 100644 --- a/js/src/dapps/registry/Application/application.js +++ b/js/src/dapps/registry/Application/application.js @@ -23,6 +23,7 @@ import CircularProgress from 'material-ui/CircularProgress'; import { Card, CardText } from 'material-ui/Card'; import { nullableProptype } from '~/util/proptypes'; +import { api } from '../parity'; import styles from './application.css'; import Accounts from '../Accounts'; @@ -39,7 +40,7 @@ export default class Application extends Component { }; getChildContext () { - return { muiTheme, api: window.parity.api }; + return { muiTheme, api }; } static propTypes = { @@ -48,8 +49,11 @@ export default class Application extends Component { fee: nullableProptype(PropTypes.object.isRequired) }; + state = { + showWarning: true + }; + render () { - const { api } = window.parity; const { contract, fee } = this.props; let warning = null; @@ -65,9 +69,7 @@ export default class Application extends Component { { this.renderActions() } -
- WARNING: The name registry is experimental. Please ensure that you understand the risks, benefits & consequences of registering a name before doing so. A non-refundable fee of { api.util.fromWei(fee).toFormat(3) }ETH is required for all registrations. -
+ { this.renderWarning() } ) : ( @@ -98,4 +100,39 @@ export default class Application extends Component { ); } + + renderWarning () { + const { showWarning } = this.state; + const { fee } = this.props; + + if (!showWarning) { + return null; + } + + return ( +
+ + WARNING: The name registry is experimental. Please ensure that you understand the risks, + benefits & consequences of registering a name before doing so. + + { + fee && api.util.fromWei(fee).gt(0) + ? ( + +  A non-refundable fee of { api.util.fromWei(fee).toFormat(3) } ETH +  is required for all registrations. + + ) + : null + } +
+ ); + } + + handleHideWarning = () => { + this.setState({ showWarning: false }); + } } diff --git a/js/src/dapps/registry/Names/actions.js b/js/src/dapps/registry/Names/actions.js index 8bc981d0d35..9e5ff4fc6ad 100644 --- a/js/src/dapps/registry/Names/actions.js +++ b/js/src/dapps/registry/Names/actions.js @@ -33,11 +33,11 @@ export const reserveFail = (name, error) => ({ type: 'names reserve fail', name, export const reserve = (name) => (dispatch, getState) => { const state = getState(); - const account = state.accounts.selected; + const accountAddress = state.accounts.selected; const contract = state.contract; const fee = state.fee; - if (!contract || !account) { + if (!contract || !accountAddress) { return; } @@ -58,7 +58,7 @@ export const reserve = (name) => (dispatch, getState) => { const { reserve } = contract.instance; const options = { - from: account.address, + from: accountAddress, value: fee }; const values = [ @@ -88,10 +88,10 @@ export const dropFail = (name, error) => ({ type: 'names drop fail', name, error export const drop = (name) => (dispatch, getState) => { const state = getState(); - const account = state.accounts.selected; + const accountAddress = state.accounts.selected; const contract = state.contract; - if (!contract || !account) { + if (!contract || !accountAddress) { return; } @@ -105,14 +105,14 @@ export const drop = (name) => (dispatch, getState) => { return getOwner(contract, name) .then((owner) => { - if (owner.toLowerCase() !== account.address.toLowerCase()) { + if (owner.toLowerCase() !== accountAddress.toLowerCase()) { throw new Error(`you are not the owner of "${name}"`); } const { drop } = contract.instance; const options = { - from: account.address + from: accountAddress }; const values = [ diff --git a/js/src/dapps/registry/Records/actions.js b/js/src/dapps/registry/Records/actions.js index 9f0d1beff83..4b7ef51d1fb 100644 --- a/js/src/dapps/registry/Records/actions.js +++ b/js/src/dapps/registry/Records/actions.js @@ -30,10 +30,10 @@ export const fail = (error) => ({ type: 'records update fail', error }); export const update = (name, key, value) => (dispatch, getState) => { const state = getState(); - const account = state.accounts.selected; + const accountAddress = state.accounts.selected; const contract = state.contract; - if (!contract || !account) { + if (!contract || !accountAddress) { return; } @@ -42,7 +42,7 @@ export const update = (name, key, value) => (dispatch, getState) => { return getOwner(contract, name) .then((owner) => { - if (owner.toLowerCase() !== account.address.toLowerCase()) { + if (owner.toLowerCase() !== accountAddress.toLowerCase()) { throw new Error(`you are not the owner of "${name}"`); } @@ -51,7 +51,7 @@ export const update = (name, key, value) => (dispatch, getState) => { : contract.instance.setData || contract.instance.set; const options = { - from: account.address + from: accountAddress }; const values = [ diff --git a/js/src/dapps/registry/Reverse/actions.js b/js/src/dapps/registry/Reverse/actions.js index 6effa9f10cb..f78ff3434c9 100644 --- a/js/src/dapps/registry/Reverse/actions.js +++ b/js/src/dapps/registry/Reverse/actions.js @@ -30,10 +30,10 @@ export const fail = (action, error) => ({ type: `reverse ${action} fail`, error export const propose = (name, address) => (dispatch, getState) => { const state = getState(); - const account = state.accounts.selected; + const accountAddress = state.accounts.selected; const contract = state.contract; - if (!contract || !account) { + if (!contract || !accountAddress) { return; } @@ -42,14 +42,14 @@ export const propose = (name, address) => (dispatch, getState) => { return getOwner(contract, name) .then((owner) => { - if (owner.toLowerCase() !== account.address.toLowerCase()) { + if (owner.toLowerCase() !== accountAddress.toLowerCase()) { throw new Error(`you are not the owner of "${name}"`); } const { proposeReverse } = contract.instance; const options = { - from: account.address + from: accountAddress }; const values = [ @@ -74,10 +74,10 @@ export const propose = (name, address) => (dispatch, getState) => { export const confirm = (name) => (dispatch, getState) => { const state = getState(); - const account = state.accounts.selected; + const accountAddress = state.accounts.selected; const contract = state.contract; - if (!contract || !account) { + if (!contract || !accountAddress) { return; } @@ -86,14 +86,14 @@ export const confirm = (name) => (dispatch, getState) => { return getOwner(contract, name) .then((owner) => { - if (owner.toLowerCase() !== account.address.toLowerCase()) { + if (owner.toLowerCase() !== accountAddress.toLowerCase()) { throw new Error(`you are not the owner of "${name}"`); } const { confirmReverse } = contract.instance; const options = { - from: account.address + from: accountAddress }; const values = [ diff --git a/js/src/dapps/registry/addresses/accounts-reducer.js b/js/src/dapps/registry/addresses/accounts-reducer.js index 5be0421ec74..2ff11ae27a5 100644 --- a/js/src/dapps/registry/addresses/accounts-reducer.js +++ b/js/src/dapps/registry/addresses/accounts-reducer.js @@ -31,8 +31,8 @@ export default (state = initialState, action) => { return { ...state, all: accounts }; } - if (action.type === 'accounts select' && state.all[action.address]) { - return { ...state, selected: state.all[action.address] }; + if (action.type === 'accounts select') { + return { ...state, selected: action.address }; } return state; diff --git a/js/src/dapps/registry/util/etherscan-url.js b/js/src/dapps/registry/util/etherscan-url.js index bb4e2fe9878..68e765c17ed 100644 --- a/js/src/dapps/registry/util/etherscan-url.js +++ b/js/src/dapps/registry/util/etherscan-url.js @@ -22,7 +22,7 @@ const etherscanUrl = (hash, isTestnet, netVersion) => { hash = hash.toLowerCase().replace(leading0x, ''); const type = hash.length === 40 ? 'address' : 'tx'; - return `https://${externalUrl(isTestnet, netVersion)}/${type}/0x${hash}`; + return `${externalUrl(isTestnet, netVersion)}/${type}/0x${hash}`; }; export default etherscanUrl; diff --git a/js/src/dapps/tokenreg/Accounts/actions.js b/js/src/dapps/tokenreg/Accounts/actions.js index e561334c9cb..538f1a831c1 100644 --- a/js/src/dapps/tokenreg/Accounts/actions.js +++ b/js/src/dapps/tokenreg/Accounts/actions.js @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -const { api } = window.parity; +import { api } from '../parity'; export const SET_ACCOUNTS = 'SET_ACCOUNTS'; export const setAccounts = (accounts) => ({ diff --git a/js/src/dapps/tokenreg/Status/actions.js b/js/src/dapps/tokenreg/Status/actions.js index 9d789ca3467..deb473d9b0a 100644 --- a/js/src/dapps/tokenreg/Status/actions.js +++ b/js/src/dapps/tokenreg/Status/actions.js @@ -17,8 +17,7 @@ import Contracts from '~/contracts'; import { loadToken, setTokenPending, deleteToken, setTokenData } from '../Tokens/actions'; - -const { api } = window.parity; +import { api } from '../parity'; export const SET_LOADING = 'SET_LOADING'; export const setLoading = (isLoading) => ({ diff --git a/js/src/dapps/tokenreg/Status/status.js b/js/src/dapps/tokenreg/Status/status.js index db007318f1d..6f77f386b9a 100644 --- a/js/src/dapps/tokenreg/Status/status.js +++ b/js/src/dapps/tokenreg/Status/status.js @@ -16,12 +16,11 @@ import React, { Component, PropTypes } from 'react'; +import { api } from '../parity'; import Chip from '../Chip'; import styles from './status.css'; -const { api } = window.parity; - export default class Status extends Component { static propTypes = { address: PropTypes.string.isRequired, diff --git a/js/src/dapps/tokenreg/Tokens/actions.js b/js/src/dapps/tokenreg/Tokens/actions.js index b32b8690541..8a5204673ee 100644 --- a/js/src/dapps/tokenreg/Tokens/actions.js +++ b/js/src/dapps/tokenreg/Tokens/actions.js @@ -15,8 +15,9 @@ // along with Parity. If not, see . import { getTokenTotalSupply } from '../utils'; +import { api } from '../parity'; -const { bytesToHex } = window.parity.api.util; +const { bytesToHex } = api.util; export const SET_TOKENS_LOADING = 'SET_TOKENS_LOADING'; export const setTokensLoading = (isLoading) => ({