diff --git a/package.json b/package.json index 1155a2534..1d931a0cd 100644 --- a/package.json +++ b/package.json @@ -46,11 +46,13 @@ "dependencies": { "bignumber.js": "4.0.0", "classnames": "^2.1.2", + "copy-to-clipboard": "^3.0.6", "eslint-plugin-react": "^6.10.3", "ethereumjs-abi": "0.6.4", "ethereumjs-util": "5.1.1", "fbjs": "0.8.9", "flexboxgrid": "^6.3.0", + "follow-redirects": "1.2.3", "font-awesome": "4.7.0", "i18next": "^8.3.0", "i18next-browser-languagedetector": "^1.0.1", @@ -59,6 +61,7 @@ "i18next-xhr-backend": "^1.4.1", "immutable": "3.8.1", "isomorphic-fetch": "^2.2.1", + "kbpgp": "2.0.72", "lib": "^2.2.5", "loglevel": "1.4.0", "material-ui": "^0.16.6", @@ -83,9 +86,7 @@ "redux-thunk": "2.2.0", "roboto-fontface": "0.7.0", "store": "^2.0.4", - "unzip2": "0.2.5", - "follow-redirects": "1.2.3", - "kbpgp": "2.0.72" + "unzip2": "0.2.5" }, "devDependencies": { "@elastic/webpack-directory-name-as-main": "2.0.2", diff --git a/src/components/accounts/account.js b/src/components/accounts/account.js index 57322d4ae..7a4a1f6f6 100644 --- a/src/components/accounts/account.js +++ b/src/components/accounts/account.js @@ -5,24 +5,30 @@ import { TableRow, TableRowColumn } from 'material-ui/Table'; import { gotoScreen } from 'store/screenActions'; import log from 'loglevel'; import { link, tables } from 'lib/styles'; +import AccountPopup from './popup'; const Render = ({ account, openAccount }) => ( - - - + + + {account.get('name')} - - + + {account.get('id')} - + {account.get('balance') ? account.get('balance').getEther() : '?'} Ether + + + + + ); diff --git a/src/components/accounts/add/add.js b/src/components/accounts/add/add.js index 7bbe051c1..e9be247d6 100644 --- a/src/components/accounts/add/add.js +++ b/src/components/accounts/add/add.js @@ -41,7 +41,8 @@ const Render = translate("accounts")(({ t, handleSubmit, submitting, generate, i }/> + icon={} + secondary={true} /> )); diff --git a/src/components/accounts/add/generate.js b/src/components/accounts/add/generate.js index cd9a60a6e..8ff911c48 100644 --- a/src/components/accounts/add/generate.js +++ b/src/components/accounts/add/generate.js @@ -67,7 +67,8 @@ const Render = translate("accounts")(({ t, account, submitSucceeded, handleSubmi }/> + icon={} + secondary={true} /> )); diff --git a/src/components/accounts/list.js b/src/components/accounts/list.js index 450122a02..9eb267420 100644 --- a/src/components/accounts/list.js +++ b/src/components/accounts/list.js @@ -6,7 +6,7 @@ import { Card, CardActions, CardHeader, CardText } from 'material-ui/Card'; import FlatButton from 'material-ui/FlatButton'; import FontIcon from 'material-ui/FontIcon'; import Avatar from 'material-ui/Avatar'; -import { cardSpace, tables } from 'lib/styles'; +import { cardSpace } from 'lib/styles'; import Immutable from 'immutable'; import { translate } from 'react-i18next'; import { gotoScreen } from 'store/screenActions'; @@ -16,9 +16,10 @@ const Render = translate('accounts')(({ t, accounts, createAccount }) => { const table = - Account - Address - Balance + Account + Address + Balance + Add Ether diff --git a/src/components/accounts/popup.js b/src/components/accounts/popup.js new file mode 100644 index 000000000..062dfd692 --- /dev/null +++ b/src/components/accounts/popup.js @@ -0,0 +1,175 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Immutable from 'immutable'; +import { connect } from 'react-redux'; +import { translate } from 'react-i18next'; +import log from 'loglevel'; +import QRCode from 'qrcode.react'; +import Dialog from 'material-ui/Dialog'; +import FlatButton from 'material-ui/FlatButton'; +import FontIcon from 'material-ui/FontIcon'; +import copy from 'copy-to-clipboard'; +import { Row, Col } from 'react-flexbox-grid/lib/index'; +import { DescriptionList, DescriptionTitle, DescriptionData } from 'elements/dl'; +import { link, align, cardSpace } from 'lib/styles'; +import { Wei } from 'lib/types'; + +/** + * Dialog with action buttons. The actions are passed in as an array of React objects, + * in this example [FlatButtons](/#/components/flat-button). + * + * You can also close this dialog by clicking outside the dialog, or with the 'Esc' key. + */ +class AccountPopupRender extends React.Component { + constructor(props) { + super(props); + this.state = { + open: false, + } + + } + + handleOpen = () => { + this.setState({open: true}); + }; + + handleClose = () => { + this.setState({open: false}); + }; + + render() { + const { account, rates, gasPrice } = this.props; + const styles = { + container: { + display: 'inline', + }, + closeButton: { + float: 'right', + color: 'green', + }, + openButton: { + display: 'inline', + backgroundColor: 'dimgray', + color: 'white', + }, + qr: { + marginLeft: 'auto', + marginRight: 'auto', + maxWidth: '90%', + }, + usageText: { + color: 'gray', + }, + usageWarning: { + color: 'crimson', + fontSize: '0.9rem', + }, + accountId: { + overflow: 'scroll', + backgroundColor: 'whitesmoke', + padding: '0.1rem 0.3rem', + display: 'inline', + fontSize: '0.8rem', /* to better ensure fit for all screen sizes */ + }, + copyIcon: { + display: 'inline', + fontSize: '0.9rem', + color: 'darkgray', + marginLeft: '0.3rem', + }, + }; + + function copyAccountToClipBoard() { + copy(account.get('id')); + } + + return ( +
+ } + onTouchTap={this.handleOpen} + style={styles.openButton} /> + + +
+

Add ETC

+ + + } + primary={true} + onTouchTap={this.handleClose} + style={styles.closeButton} + /> + + + + +

Top up your wallet with BTC

+ + {account.get('description') &&
+ - {account.get('description')} + -
} + + + + {account.get('id')} + + + + +
+ +

Exchange Rate

+ + 1 ETC ~ {rates.get('btc')} BTC + + +

+ Share your wallet address and use it to top up your wallet with BTC from any +  other service. All BTC will be converted to ETC. + It may take some time for your coins be deposited. +

+ +

Minimal amount

+

{gasPrice.getEther(10)} ~ {gasPrice.getFiat(rates.get('btc'), 10)} BTC

+ +

+ Please note that if an amount is less than the minimum, it is mostly non-refundable. +

+ + + + + + + + ); + } +} + +AccountPopupRender.propTypes = { + account: PropTypes.object.isRequired, +}; + +const AccountPopup = connect( + (state, ownProps) => { + const accounts = state.accounts.get('accounts'); + const pos = accounts.findKey((acc) => acc.get('id') === ownProps.account.get('id')); + const rates = state.accounts.get('rates'); + const gasPrice = new Wei(21338000000); // Rough estimate tx gasprice; 21000 * 10^6 + return { + account: (accounts.get(pos) || Immutable.Map({})), + rates, + gasPrice, + }; + }, + (dispatch, ownProps) => ({}) +)(AccountPopupRender); + +export default AccountPopup; diff --git a/src/components/accounts/show.js b/src/components/accounts/show.js index c96507c60..6326641a2 100644 --- a/src/components/accounts/show.js +++ b/src/components/accounts/show.js @@ -14,6 +14,7 @@ import { cardSpace } from 'lib/styles'; import { gotoScreen } from 'store/screenActions'; import { updateAccount } from 'store/accountActions'; import AccountEdit from './edit'; +import AccountPopup from './popup'; const TokenRow = ({ token }) => { const balance = token.get('balance') ? token.get('balance').getDecimalized() : '0'; @@ -51,19 +52,16 @@ class AccountRender extends React.Component { this.setState({ edit: false }); } - showModal = () => { - this.setState({ showModal: true }); - } - - closeModal = () => { - this.setState({ showModal: false }); - } - render() { const { account, rates, createTx, goBack } = this.props; const value = account.get('balance') ? account.get('balance').getEther() : '?'; const pending = account.get('balancePending') ? `(${account.get('balancePending').getEther()} pending)` : null; + const styles = { + sendButton: { + color: 'green', + }, + }; return ( @@ -88,7 +86,7 @@ class AccountRender extends React.Component { primary={account.get('name')} onClick={this.handleEdit} />} - {this.state.edit && - }/> + }/> + icon={} + style={styles.sendButton} /> - {/* - TODO: Replace with @whilei's ADD ETHER modal - */} - ); } diff --git a/src/components/addressbook/form.js b/src/components/addressbook/form.js index 0bdc681c6..be02c7774 100644 --- a/src/components/addressbook/form.js +++ b/src/components/addressbook/form.js @@ -27,6 +27,7 @@ const Render = ({ handleSubmit, blockAddress, invalid, pristine, submitting, can diff --git a/src/components/main.js b/src/components/main.js index 041c2b9a5..7d4715eb4 100644 --- a/src/components/main.js +++ b/src/components/main.js @@ -12,8 +12,9 @@ import { gotoScreen } from 'store/screenActions'; import './main.scss'; import Screen from './screen'; import Header from './layout/header'; +import AccountPopup from './accounts/popup'; -const Render = translate("common")(({t, ...props}) => ( +const Render = translate('common')(({t, ...props}) => ( diff --git a/src/components/tx/create.js b/src/components/tx/create.js index 478c79e0e..f83aebd70 100644 --- a/src/components/tx/create.js +++ b/src/components/tx/create.js @@ -25,7 +25,7 @@ const traceValidate = (data, dispatch) => { const resolveValidate = (response, resolve) => { let errors = null; dataObj.data = (((response.trace || [])[0] || {}).action || {}).input; - let gasEst; + let gasEst; if (response.gas) gasEst = response.gas; else { gasEst = estimateGasFromTrace(dataObj, response); @@ -147,7 +147,7 @@ const CreateTx = connect( dispatch(change('createTx', 'to', item.props.value)); }, cancel: () => { - dispatch(gotoScreen('home')); + dispatch(gotoScreen('account', ownProps.account)); }, }) )(CreateTxForm); diff --git a/src/components/tx/createTxForm.js b/src/components/tx/createTxForm.js index b95d217fa..6aad74601 100644 --- a/src/components/tx/createTxForm.js +++ b/src/components/tx/createTxForm.js @@ -26,6 +26,12 @@ const Render = (props) => { return ( + + }/> + { - }/> }/> + icon={} + secondary={true} /> + } + /> ); diff --git a/src/images/ETC_LOGO_One_Color_Black.png b/src/images/ETC_LOGO_One_Color_Black.png new file mode 100644 index 000000000..c8213c59b Binary files /dev/null and b/src/images/ETC_LOGO_One_Color_Black.png differ diff --git a/src/lib/styles.js b/src/lib/styles.js index c3d98bde9..bdbc2e8e6 100644 --- a/src/lib/styles.js +++ b/src/lib/styles.js @@ -8,8 +8,8 @@ export const link = { }; export const tables = { - shortStyle: { width: 12 }, - wideStyle: { width: 120 }, + shortStyle: { }, + wideStyle: { }, }; export const code = { @@ -28,4 +28,4 @@ export const align = { left: { textAlign: 'left' }, center: { textAlign: 'center'}, right: { textAlign: 'right'} -}; \ No newline at end of file +}; diff --git a/src/lib/types.js b/src/lib/types.js index 94885eae2..cb4a09cca 100644 --- a/src/lib/types.js +++ b/src/lib/types.js @@ -54,8 +54,11 @@ export class Wei extends Immutable.Record({ val: ZERO }) { }); } } - getEther() { - return this.val.dividedBy(ETHER).toFixed(5); + getEther(decimals) { + if (typeof decimals === 'undefined' || decimals === null) { + decimals = 5; + } + return this.val.dividedBy(ETHER).toFixed(decimals); } getMwei() { return this.val.dividedBy(MWEI).toFixed(5); @@ -63,12 +66,15 @@ export class Wei extends Immutable.Record({ val: ZERO }) { plus(another) { return new Wei(this.val.plus(another.val)); } - getFiat(r) { + getFiat(r, decimals) { if (typeof (r) === 'undefined' || r === null) { r = 0; } + if (typeof decimals === 'undefined' || decimals === null) { + decimals = 2; + } const rate = new BigNumber(r.toString()); - return this.val.dividedBy(ETHER).mul(rate).toFixed(5); + return this.val.dividedBy(ETHER).mul(rate).toFixed(decimals); } sub(another) { return new Wei(this.val.sub(another.val)); diff --git a/src/store/accountActions.js b/src/store/accountActions.js index f1da0de26..f39a8d5dc 100644 --- a/src/store/accountActions.js +++ b/src/store/accountActions.js @@ -2,7 +2,6 @@ import { rpc } from 'lib/rpc'; import { getRates } from 'lib/marketApi'; import { address } from 'lib/validators'; import { loadTokenBalanceOf } from './tokenActions'; -import { addAddress } from './addressActions'; export function loadAccountBalance(accountId) { return (dispatch, getState) => { @@ -79,7 +78,7 @@ export function updateAccount(address, name, description) { rpc.call('emerald_updateAccounts', [{ name, description, - address + address, }]).then((result) => { dispatch({ type: 'ACCOUNT/UPDATE_ACCOUNT', diff --git a/src/store/accountReducers.js b/src/store/accountReducers.js index 10ef7d158..74f47eb1a 100644 --- a/src/store/accountReducers.js +++ b/src/store/accountReducers.js @@ -149,7 +149,7 @@ function createTx(data) { } if (typeof data.gas === 'string' || typeof data.gas === 'number') { tx = tx.set('gas', toNumber(data.gas)); - } + } return tx; }