diff --git a/react/package.json b/react/package.json index 6218bdce0..ed057b889 100644 --- a/react/package.json +++ b/react/package.json @@ -41,13 +41,13 @@ "qrcode.react": "^0.7.1", "rc-tree": "^1.4.6", "react": "^15.3.1", - "react-cryptocoins": "^1.0.10", "react-dom": "^15.3.1", "react-hot-loader": "^1.3.0", "react-qr-reader": "^1.1.3", "react-redux": "^5.0.3", "react-router": "^3.0.2", "react-router-redux": "^4.0.4", + "react-select": "^1.1.0", "react-table": "~6.5.1", "react-transform-catch-errors": "^1.0.2", "react-transform-hmr": "^1.0.4", diff --git a/react/src/actions/actionCreators.js b/react/src/actions/actionCreators.js index b9db9f538..05753a25a 100644 --- a/react/src/actions/actionCreators.js +++ b/react/src/actions/actionCreators.js @@ -36,14 +36,11 @@ export * from './actions/nativeSyncInfo'; export * from './actions/nativeSend'; export * from './actions/coinList'; export * from './actions/nativeNewAddress'; -// export * from './actions/logout'; export * from './actions/settings'; export * from './actions/addCoin'; -// export * from './actions/walletAuth'; export * from './actions/copyAddress'; export * from './actions/sysInfo'; export * from './actions/dexCoins'; -//export * from './actions/fullTxHistory'; export * from './actions/cli'; export * from './actions/update'; export * from './actions/jumblr'; @@ -52,6 +49,7 @@ export * from './actions/nativeDashboardUpdate'; export * from './actions/getTxDetails'; export * from './actions/electrum'; export * from './actions/mm'; +export * from './actions/nativeNetwork'; export function changeActiveAddress(address) { return { diff --git a/react/src/actions/actions/addCoin.js b/react/src/actions/actions/addCoin.js index 642631db7..de89372cd 100644 --- a/react/src/actions/actions/addCoin.js +++ b/react/src/actions/actions/addCoin.js @@ -12,7 +12,7 @@ import { startAssetChain, startCrypto, checkCoinType, - checkAC + checkAC, } from '../../components/addcoin/payload'; function iguanaActiveHandleState(json) { @@ -240,10 +240,9 @@ export function shepherdHerd(coin, mode, path, startupParams) { addCoinResult(coin, mode) ); } else { - console.warn(acData); dispatch( triggerToaster( - translate('TOASTR.ERROR_STARTING_DAEMON', coin) + ' ' + translate('TOASTR.PORT_IS_TAKEN', acData.rpc), + translate('TOASTR.ERROR_STARTING_DAEMON', coin) + ' ' + translate('TOASTR.PORT_IS_TAKEN', acData), translate('TOASTR.SERVICE_NOTIFICATION'), 'error', false diff --git a/react/src/actions/actions/logout.js b/react/src/actions/actions/logout.js deleted file mode 100644 index 57f4baf95..000000000 --- a/react/src/actions/actions/logout.js +++ /dev/null @@ -1,59 +0,0 @@ -// TODO: use in dex - -import { - LOGIN, - LOGOUT -} from '../storeType'; -import { triggerToaster } from '../actionCreators'; -import Config from '../../config'; - -function logoutState(json) { - sessionStorage.removeItem('IguanaActiveAccount'); - - return { - type: LOGIN, - isLoggedIn: false, - } -} - -function logoutResetAppState() { - return { - type: LOGOUT, - } -} - -export function logout() { - return dispatch => { - dispatch(walletLock()); - } -} - -function walletLock() { - const payload = { - userpass: `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`, - agent: 'bitcoinrpc', - method: 'walletlock', - }; - - return dispatch => { - return fetch(`http://127.0.0.1:${Config.iguanaCorePort}`, { - method: 'POST', - body: JSON.stringify(payload), - }) - .catch((error) => { - console.log(error); - dispatch( - triggerToaster( - 'walletLock', - 'Error', - 'error' - ) - ); - }) - .then(response => response.json()) - .then(json => { - dispatch(logoutState(json)); - dispatch(logoutResetAppState()); - }) - } -} \ No newline at end of file diff --git a/react/src/actions/actions/mm.js b/react/src/actions/actions/mm.js index 6f3da0180..dd3ed54e6 100644 --- a/react/src/actions/actions/mm.js +++ b/react/src/actions/actions/mm.js @@ -10,6 +10,8 @@ import { DEX_UTXO, DEX_CACHE_PRELOAD, DEX_PRICES, + DEX_STATS, + DEX_ACTIVE_SECTION, } from '../storeType'; import { translate } from '../../translate/translate'; import Config from '../../config'; @@ -18,7 +20,7 @@ import { } from '../actionCreators'; import Store from '../../store'; -export function shepherdMMCachePreloadState(isAuth, asks, bids, pair, coins, swaps, rates) { +export function shepherdMMCachePreloadState(isAuth, asks, bids, pair, coins, swaps, rates, coinsHelper, electrumServersList) { return { type: DEX_CACHE_PRELOAD, isAuth, @@ -28,6 +30,8 @@ export function shepherdMMCachePreloadState(isAuth, asks, bids, pair, coins, swa coins, swaps, rates, + coinsHelper, + electrumServersList, } } @@ -88,7 +92,6 @@ export function shepherdMMStop() { } export function shepherdMMRequest(payload) { - console.warn(payload); return dispatch => { return fetch( `http://127.0.0.1:${Config.agamaPort}/shepherd/mm/request`, { @@ -101,7 +104,7 @@ export function shepherdMMRequest(payload) { ) .catch((error) => { console.log(error); - Store.dispatch( + dispatch( triggerToaster( 'shepherdMMRequest', 'Error', @@ -111,21 +114,34 @@ export function shepherdMMRequest(payload) { }) .then(response => response.json()) .then(json => { - dispatch(shepherdMMRequstState(payload.mapToProp, json)); + console.warn(json); + dispatch(shepherdMMRequestState(payload.mapToProp, json)); }); } } -export function shepherdMMRequstState(prop, json) { +export function shepherdMMRequestState(prop, json) { if (prop === 'prices') { return { type: DEX_PRICES, prices: json, } - } else if (prop === 'statsdisp') { + } else if (prop === 'stats') { return { type: DEX_STATS, - prices: json, + stats: json, + } + } else if (prop === 'swaps') { + return { + type: DEX_SWAPS, + swaps: json, } } +} + +export function dexActiveSection(section) { + return { + type: DEX_ACTIVE_SECTION, + section, + } } \ No newline at end of file diff --git a/react/src/actions/actions/nativeNetwork.js b/react/src/actions/actions/nativeNetwork.js new file mode 100644 index 000000000..2141b2e92 --- /dev/null +++ b/react/src/actions/actions/nativeNetwork.js @@ -0,0 +1,97 @@ +import { + DASHBOARD_ACTIVE_COIN_NET_PEERS, + DASHBOARD_ACTIVE_COIN_NET_TOTALS, +} from '../storeType'; +import { translate } from '../../translate/translate'; +import { triggerToaster } from '../actionCreators'; +import Config from '../../config'; + +export function getNativePeers(coin) { + return dispatch => { + const payload = { + mode: null, + chain: coin, + cmd: 'getpeerinfo', + }; + + const _fetchConfig = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ payload: payload }), + }; + + fetch( + `http://127.0.0.1:${Config.agamaPort}/shepherd/cli`, + _fetchConfig + ) + .catch((error) => { + console.log(error); + dispatch( + triggerToaster( + 'getNativePeers', + 'Error', + 'error' + ) + ); + }) + .then(response => response.json()) + .then(json => { + json = json.result; + dispatch(getNativePeersState(json)); + }) + }; +} + +export function getNativeNettotals(coin) { + return dispatch => { + const payload = { + mode: null, + chain: coin, + cmd: 'getnettotals', + }; + + const _fetchConfig = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ payload: payload }), + }; + + fetch( + `http://127.0.0.1:${Config.agamaPort}/shepherd/cli`, + _fetchConfig + ) + .catch((error) => { + console.log(error); + dispatch( + triggerToaster( + 'getNativeNettotals', + 'Error', + 'error' + ) + ); + }) + .then(response => response.json()) + .then(json => { + json = json.result; + dispatch(getNativeNettotalsState(json)); + }) + }; +} + +export function getNativePeersState(json) { + return { + type: DASHBOARD_ACTIVE_COIN_NET_PEERS, + peers: json, + } +} + +export function getNativeNettotalsState(json) { + return { + type: DASHBOARD_ACTIVE_COIN_NET_TOTALS, + totals: json, + } +} \ No newline at end of file diff --git a/react/src/actions/storeType.js b/react/src/actions/storeType.js index 37924bf99..b960965a2 100644 --- a/react/src/actions/storeType.js +++ b/react/src/actions/storeType.js @@ -48,6 +48,9 @@ export const DASHBOARD_ELECTRUM_COINS = 'DASHBOARD_ELECTRUM_COINS'; export const ELECTRUM_SERVER_CHANGED = 'ELECTRUM_SERVER_CHANGED'; export const DISPLAY_ZCASH_PARAMS_FETCH = 'DISPLAY_ZCASH_PARAMS_FETCH'; export const DASHBOARD_REMOVE_COIN = 'DASHBOARD_REMOVE_COIN'; +export const DASHBOARD_ACTIVE_COIN_NET_PEERS = 'DASHBOARD_ACTIVE_COIN_NET_PEERS'; +export const DASHBOARD_ACTIVE_COIN_NET_TOTALS = 'DASHBOARD_ACTIVE_COIN_NET_TOTALS'; + /* dex */ export const DEX_LOGIN = 'DEX_LOGIN'; export const DEX_LOGOUT = 'DEX_LOGOUT'; @@ -61,4 +64,5 @@ export const DEX_UTXO = 'DEX_UTXO'; export const DEX_PRICES = 'DEX_PRICES'; export const DEX_RESET = 'DEX_RESET'; export const DEX_STATS = 'DEX_STATS'; -export const DEX_CACHE_PRELOAD = 'DEX_CACHE_PRELOAD'; \ No newline at end of file +export const DEX_CACHE_PRELOAD = 'DEX_CACHE_PRELOAD'; +export const DEX_ACTIVE_SECTION = 'DEX_ACTIVE_SECTION'; \ No newline at end of file diff --git a/react/src/assets/dex/coins/kmd.svg b/react/src/assets/dex/coins/kmd.svg deleted file mode 100644 index 958e0c9db..000000000 --- a/react/src/assets/dex/coins/kmd.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/react/src/assets/dex/coins/mnz.svg b/react/src/assets/dex/coins/mnz.svg deleted file mode 100644 index d8e50a201..000000000 --- a/react/src/assets/dex/coins/mnz.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/react/src/assets/images/cryptologo/blk.png b/react/src/assets/images/cryptologo/blk.png new file mode 100644 index 000000000..7dc4b2da6 Binary files /dev/null and b/react/src/assets/images/cryptologo/blk.png differ diff --git a/react/src/assets/images/cryptologo/block.png b/react/src/assets/images/cryptologo/block.png new file mode 100644 index 000000000..f109b53b3 Binary files /dev/null and b/react/src/assets/images/cryptologo/block.png differ diff --git a/react/src/assets/images/cryptologo/bsd.png b/react/src/assets/images/cryptologo/bsd.png new file mode 100644 index 000000000..07ae80297 Binary files /dev/null and b/react/src/assets/images/cryptologo/bsd.png differ diff --git a/react/src/assets/images/cryptologo/btcz.png b/react/src/assets/images/cryptologo/btcz.png new file mode 100644 index 000000000..4c6e4778b Binary files /dev/null and b/react/src/assets/images/cryptologo/btcz.png differ diff --git a/react/src/assets/images/cryptologo/chips (copy).png b/react/src/assets/images/cryptologo/chips (copy).png new file mode 100644 index 000000000..53b60b27a Binary files /dev/null and b/react/src/assets/images/cryptologo/chips (copy).png differ diff --git a/react/src/assets/images/cryptologo/chips.png b/react/src/assets/images/cryptologo/chips.png index 53b60b27a..38bafefcd 100644 Binary files a/react/src/assets/images/cryptologo/chips.png and b/react/src/assets/images/cryptologo/chips.png differ diff --git a/react/src/assets/images/cryptologo/hodlc.png b/react/src/assets/images/cryptologo/hodlc.png new file mode 100644 index 000000000..7289d2e02 Binary files /dev/null and b/react/src/assets/images/cryptologo/hodlc.png differ diff --git a/react/src/assets/images/cryptologo/iop.png b/react/src/assets/images/cryptologo/iop.png new file mode 100644 index 000000000..eedd107e7 Binary files /dev/null and b/react/src/assets/images/cryptologo/iop.png differ diff --git a/react/src/assets/images/cryptologo/maga.png b/react/src/assets/images/cryptologo/maga.png new file mode 100644 index 000000000..0dff41cd7 Binary files /dev/null and b/react/src/assets/images/cryptologo/maga.png differ diff --git a/react/src/assets/images/cryptologo/mshark.png b/react/src/assets/images/cryptologo/mshark.png new file mode 100644 index 000000000..f321f3c63 Binary files /dev/null and b/react/src/assets/images/cryptologo/mshark.png differ diff --git a/react/src/assets/images/cryptologo/zen.png b/react/src/assets/images/cryptologo/zen.png new file mode 100644 index 000000000..0dc99d605 Binary files /dev/null and b/react/src/assets/images/cryptologo/zen.png differ diff --git a/react/src/components/addcoin/addcoin.js b/react/src/components/addcoin/addcoin.js index 7610f2f0f..d2d2d6a9e 100644 --- a/react/src/components/addcoin/addcoin.js +++ b/react/src/components/addcoin/addcoin.js @@ -12,6 +12,7 @@ import { } from '../../actions/actionCreators'; import Store from '../../store'; import { zcashParamsCheckErrors } from '../../util/zcashParams'; +import mainWindow from '../../util/mainWindow'; import CoinSelectorsRender from './coin-selectors.render'; import AddCoinRender from './addcoin.render'; @@ -54,14 +55,14 @@ class AddCoin extends React.Component { verifyZcashParamsExist(mode) { return new Promise((resolve, reject) => { if (Number(mode) === -1) { - const _res = window.require('electron').remote.getCurrentWindow().zcashParamsExist; + const _res = mainWindow.zcashParamsExist; const __errors = zcashParamsCheckErrors(_res); if (__errors) { - window.require('electron').remote.getCurrentWindow().zcashParamsExistPromise() + mainWindow.zcashParamsExistPromise() .then((res) => { const _errors = zcashParamsCheckErrors(res); - window.require('electron').remote.getCurrentWindow().zcashParamsExist = res; + mainWindow.zcashParamsExist = res; if (_errors) { Store.dispatch( @@ -147,14 +148,8 @@ class AddCoin extends React.Component { componentWillMount() { this.addNewItem(); - let appConfig; - - try { - appConfig = window.require('electron').remote.getCurrentWindow().appConfig; - } catch (e) {} - this.setState({ - isExperimentalOn: appConfig.experimentalFeatures, + isExperimentalOn: mainWindow.appConfig.experimentalFeatures, }); } @@ -179,32 +174,49 @@ class AddCoin extends React.Component { } } + renderCoinOption(option) { + return ( +
+ { + { option.label } +
+ ); + } + updateSelectedCoin(e, index) { - const coin = e.target.value.split('|'); - const defaultMode = coin[1]; - const modeToValue = { // TODO: move to utils - 'spv': 0, - 'native': -1, - }; - let _coins = this.state.coins; - const _value = e.target.value; + if (e && + e.value && + e.value.indexOf('|')) { + const coin = e.value.split('|'); + const defaultMode = coin[1]; + const modeToValue = { // TODO: move to utils + 'spv': 0, + 'native': -1, + }; + const _value = e.value; + let _coins = this.state.coins; + + _coins[index] = { + selectedCoin: _value, + spvMode: { + disabled: _value.indexOf('spv') > -1 ? false : true, + checked: defaultMode === 'spv' ? true : false, + }, + nativeMode: { + disabled: _value.indexOf('native') > -1 ? false : true, + checked: defaultMode === 'native' ? true : false, + }, + mode: modeToValue[defaultMode] !== undefined ? modeToValue[defaultMode] : -2, + } - _coins[index] = { - [e.target.name]: _value, - spvMode: { - disabled: _value.indexOf('spv') > -1 ? false : true, - checked: defaultMode === 'spv' ? true : false, - }, - nativeMode: { - disabled: _value.indexOf('native') > -1 ? false : true, - checked: defaultMode === 'native' ? true : false, - }, - mode: modeToValue[defaultMode] !== undefined ? modeToValue[defaultMode] : -2, + this.setState(Object.assign({}, this.state, { + coins: _coins, + })); } - - this.setState(Object.assign({}, this.state, { - coins: _coins, - })); } updateSelectedMode(_value, index) { @@ -231,6 +243,7 @@ class AddCoin extends React.Component { } handleKeydown(e) { + console.warn(e); if (e.key === 'Escape') { this.dismiss(); } @@ -336,8 +349,8 @@ class AddCoin extends React.Component { } renderCoinSelectors() { - let items = []; const _coins = this.state.coins; + let items = []; for (let i = 0; i < _coins.length; i++) { const _item = _coins[i]; diff --git a/react/src/components/addcoin/addcoin.render.js b/react/src/components/addcoin/addcoin.render.js index d7070c6e4..ed08b9b8a 100644 --- a/react/src/components/addcoin/addcoin.render.js +++ b/react/src/components/addcoin/addcoin.render.js @@ -7,7 +7,13 @@ const AddCoinRender = function() { return (
this.handleKeydown(event) }>
+
+
+ ); + } +} + +const mapStateToProps = (state) => { + return { + Dex: state.Dex, + }; +}; + +export default connect(mapStateToProps)(DexSwapsTable); \ No newline at end of file diff --git a/react/src/components/dex/table/pagination.js b/react/src/components/dex/table/pagination.js new file mode 100644 index 000000000..ead45b309 --- /dev/null +++ b/react/src/components/dex/table/pagination.js @@ -0,0 +1,50 @@ +import React, { Component } from 'react'; +import PaginationRender from './pagination.render'; + +export default class TablePaginationRenderer extends Component { + constructor(props) { + super(); + this.state = { + page: props.page, + }; + this.getSafePage = this.getSafePage.bind(this); + this.changePage = this.changePage.bind(this); + this.applyPage = this.applyPage.bind(this); + } + + componentWillReceiveProps(nextProps) { + this.setState({ + page: nextProps.page, + }); + } + + getSafePage(page) { + if (isNaN(page)) { + page = this.props.page; + } + + return Math.min(Math.max(page, 0), this.props.pages - 1); + } + + changePage(page) { + page = this.getSafePage(page); + this.setState({ + page, + }); + + if (this.props.page !== page) { + this.props.onPageChange(page); + } + } + + applyPage(e) { + const page = this.state.page; + + e && e.preventDefault(); + this.changePage(page === '' ? this.props.page : page); + } + + render() { + return PaginationRender.call(this); + } +} \ No newline at end of file diff --git a/react/src/components/dex/table/pagination.render.js b/react/src/components/dex/table/pagination.render.js new file mode 100644 index 000000000..c4d1de6dd --- /dev/null +++ b/react/src/components/dex/table/pagination.render.js @@ -0,0 +1,103 @@ +import React from 'react'; +import classnames from 'classnames'; + +const defaultButton = props => + + +const PaginationRender = function() { + const { + // Computed + pages, + // Props + page, + showPageSizeOptions, + pageSizeOptions, + pageSize, + showPageJump, + canPrevious, + canNext, + onPageSizeChange, + className, + PreviousComponent = defaultButton, + NextComponent = defaultButton, + } = this.props; + + return ( +
+
+ { + if (!canPrevious) return; + this.changePage(page - 1) + }} + disabled={!canPrevious}> + {this.props.previousText} + +
+
+ + {this.props.pageText}{' '} + {showPageJump + ? +
+ { + const val = e.target.value; + this.changePage(val - 1); + }} + value={this.state.page === '' ? '' : this.state.page + 1} + onBlur={this.applyPage} + onKeyPress={e => { + if (e.which === 13 || e.keyCode === 13) { + this.applyPage(); + } + }} /> +
+ : + + {page + 1} + }{' '} + {this.props.ofText}{' '} + {pages || 1} +
+ { showPageSizeOptions && + + + + } +
+
+ { + if (!canNext) return; + this.changePage(page + 1); + }} + disabled={!canNext}> + {this.props.nextText} + +
+
+ ) +}; + +export default PaginationRender; \ No newline at end of file diff --git a/react/src/components/dex/table/table.scss b/react/src/components/dex/table/table.scss new file mode 100644 index 000000000..a03e87074 --- /dev/null +++ b/react/src/components/dex/table/table.scss @@ -0,0 +1,92 @@ +.search-box { + float: right; + padding-right: 0; +} +.basilisk-progress-bar { + position: absolute; + width: 100%; +} +.breadcrumb--basilisk, +.breadcrumb--native { + top: 0; +} +.dropdown-menu { + .no--hover { + pointer-events: none; + } +} +.ReactTable { + border: none; + + .pagination-bottom { + margin-top: 35px; + } + .rt-td { + text-align: center; + } + .rt-table { + border: 1px solid rgba(0, 0, 0, 0.1); + } + .rt-thead .rt-th, + .rt-thead .rt-td { + padding: 10px 5px; + } + .rt-tr.-odd div, + .rt-tr.-even div { + padding-top: 10px; + padding-bottom: 10px; + } + .-pagination, + .rt-thead, + .rt-tfoot { + border: none; + } + .rt-tfoot { + border-top: 1px solid rgba(0, 0, 0, 0.1); + } + .rt-thead { + border-bottom: 1px solid rgba(0, 0, 0, 0.1); + } + .colum--direction { + width: 40px !important; + flex: 40 0 auto !important; + padding-right: 10px; + } + .colum--txinfo { + width: 40px !important; + flex: 40 0 auto !important; + } + .colum--type { + width: 40px !important; + flex: 40 0 auto !important; + } + .-pagination { + .-pageJump { + margin-right: 5px; + margin-left: 5px; + } + .-btn { + color: #757575; + background-color: #efefef; + border: 1px solid #e0e0e0; + + &:hover { + color: #fff; + } + } + .-btn[disabled]:hover { + color: #757575; + } + } + .rt-noData { + top: 46px; + width: 100%; + text-align: center; + height: 98px; + padding: 38px; + background: rgba(255, 255, 255, 0.85); + } +} +.table-cell-offset-16 { + padding-left: 16px; +} \ No newline at end of file diff --git a/react/src/components/login/login.js b/react/src/components/login/login.js index 1f991a8a0..4f6285e1e 100644 --- a/react/src/components/login/login.js +++ b/react/src/components/login/login.js @@ -4,7 +4,6 @@ import { toggleAddcoinModal, shepherdElectrumAuth, shepherdElectrumCoins, - //iguanaActiveHandle, startInterval, getDexCoins, triggerToaster, @@ -21,8 +20,9 @@ import { translate } from '../../translate/translate'; import { encryptPassphrase, loadPinList, - loginWithPin + loginWithPin, } from '../../actions/actions/pin'; +import mainWindow from '../../util/mainWindow'; const IGUNA_ACTIVE_HANDLE_TIMEOUT = 3000; const IGUNA_ACTIVE_COINS_TIMEOUT = 10000; @@ -64,7 +64,6 @@ class Login extends React.Component { this.loginSeed = this.loginSeed.bind(this); this.toggleSeedInputVisibility = this.toggleSeedInputVisibility.bind(this); this.handleRegisterWallet = this.handleRegisterWallet.bind(this); - this.openSyncOnlyModal = this.openSyncOnlyModal.bind(this); this.toggleSeedBackupModal = this.toggleSeedBackupModal.bind(this); this.copyPassPhraseToClipboard = this.copyPassPhraseToClipboard.bind(this); this.execWalletCreate = this.execWalletCreate.bind(this); @@ -94,7 +93,7 @@ class Login extends React.Component { toggleCustomWalletSeed() { this.setState({ - customWalletSeed: !this.state.customWalletSeed + customWalletSeed: !this.state.customWalletSeed, }, () => { // if customWalletSeed is set to false, regenerate the seed if (!this.state.customWalletSeed) { @@ -126,50 +125,25 @@ class Login extends React.Component { updateEncryptKey(e) { this.setState({ - encryptKey: e.target.value + encryptKey: e.target.value, }); } updatePubKey(e) { this.setState({ - pubKey: e.target.value + pubKey: e.target.value, }); } updateDecryptKey(e) { this.setState({ - decryptKey: e.target.value - }); - } - - openSyncOnlyModal() { - Store.dispatch(getSyncOnlyForks()); - - const _iguanaActiveHandle = setInterval(() => { - Store.dispatch(getSyncOnlyForks()); - }, IGUNA_ACTIVE_HANDLE_TIMEOUT); - Store.dispatch( - startInterval( - 'syncOnly', - _iguanaActiveHandle - ) - ); - - Store.dispatch(toggleSyncOnlyModal(true)); - this.setState({ - displayLoginSettingsDropdown: false, + decryptKey: e.target.value, }); } componentDidMount() { - let appConfig; - - try { - appConfig = window.require('electron').remote.getCurrentWindow().appConfig; - } catch (e) {} - this.setState({ - isExperimentalOn: appConfig.experimentalFeatures, + isExperimentalOn: mainWindow.experimentalFeatures, }); } @@ -353,7 +327,7 @@ class Login extends React.Component { updateSelectedPin(e) { this.setState({ - selectedPin: e.target.value + selectedPin: e.target.value, }); } diff --git a/react/src/components/main/walletMain.js b/react/src/components/main/walletMain.js index a4b16b531..021147f24 100644 --- a/react/src/components/main/walletMain.js +++ b/react/src/components/main/walletMain.js @@ -5,30 +5,90 @@ import AddCoin from '../addcoin/addcoin'; import Login from '../login/login'; import Dashboard from '../dashboard/main/dashboard'; import DexMain from '../dex/dexMain'; +import mainWindow from '../../util/mainWindow'; +import Store from '../../store'; +import { + toggleDashboardTxInfoModal, + toggleAddcoinModal, + toggleZcparamsFetchModal, + toggleClaimInterestModal, + toggleCoindDownModal, + displayImportKeyModal, +} from '../../actions/actionCreators'; class WalletMain extends React.Component { - render() { - return ( -
- - - { /* - - */ + componentDidMount() { + // handle esc key globally + document.onkeydown = (evt) => { + evt = evt || window.event; + + let isEscape = false; + + if ('key' in evt) { + isEscape = (evt.key === 'Escape' || evt.key === 'Esc'); + } else { + isEscape = (evt.keyCode === 27); + } + + // TODO: qr modal + if (isEscape) { + if (this.props.activeModals.showTransactionInfo) { + Store.dispatch(toggleDashboardTxInfoModal(false)); + } else if (this.props.activeModals.displayZcparamsModal) { + Store.dispatch(toggleZcparamsFetchModal(false)); + } else if (this.props.activeModals.displayClaimInterestModal) { + Store.dispatch(toggleClaimInterestModal(false)); + } else if (this.props.activeModals.displayCoindDownModal) { + Store.dispatch(toggleCoindDownModal(false)); + } else if (this.props.activeModals.displayImportKeyModal) { + Store.dispatch(displayImportKeyModal(false)); + } else if (this.props.activeModals.displayAddCoinModal) { + Store.dispatch(toggleAddcoinModal(false, false)); + } else if (this.props.activeModals.displayLoginSettingsModal) { + Store.dispatch(toggleLoginSettingsModal(false)); } - - - -
- ); + } + }; + } + + render() { + if (mainWindow.argv.indexOf('dexonly') > -1) { + return ( +
+ + +
+ ); + } else { + return ( +
+ + + + + +
+ ); + } } } const mapStateToProps = (state) => { return { toaster: state.toaster, + activeModals: { + showTransactionInfo: state.ActiveCoin.showTransactionInfo, + displayClaimInterestModal: state.Dashboard.displayClaimInterestModal, + displayCoindDownModal: state.Dashboard.displayCoindDownModal, + displayImportKeyModal: state.Dashboard.displayImportKeyModal, + displayZcparamsModal: state.Dashboard.displayZcparamsModal, + displayAddCoinModal: state.AddCoin.display, + displayLoginSettingsModal: state.Main.displayLoginSettingsModal, + }, }; }; diff --git a/react/src/components/overrides.scss b/react/src/components/overrides.scss index 2ec7305dc..7b24f0cf2 100644 --- a/react/src/components/overrides.scss +++ b/react/src/components/overrides.scss @@ -631,4 +631,56 @@ select{ right: 38px; top: 0; transform: scale(0.5); +} + +.Select { + cursor: pointer; + + * { color: #757575 !important; } + + .Select-clear { + display: none; + } + .Select-control { + height: 40px !important; + + .Select-placeholder, + .Select-value { + line-height: 36px !important; + } + } +} +.Select-menu-outer { + max-height: 253px !important; +} +.Select-menu { + max-height: 250px !important; +} +.Select.is-open, +.Select.is-focused { + .Select-control { + border-color: #FF6600 !important; + box-shadow: none !important; + } + .Select-menu-outer { + border-color: #FF6600 !important; + border-top-color: #d9d9d9 !important; + } +} + +.modal-close-overlay { + width: 100%; + height: 100%; + position: absolute; +} + +.navbar-fixed-bottom, +.navbar-fixed-top { + z-index: 100; +} + +#section-iguana-wallet-settings { + > .row { + background: #f3f4f5; + } } \ No newline at end of file diff --git a/react/src/reducers/activeCoin.js b/react/src/reducers/activeCoin.js index c5d0e12b0..c25ff0bf4 100644 --- a/react/src/reducers/activeCoin.js +++ b/react/src/reducers/activeCoin.js @@ -18,6 +18,8 @@ import { DASHBOARD_ELECTRUM_BALANCE, DASHBOARD_ELECTRUM_TRANSACTIONS, DASHBOARD_REMOVE_COIN, + DASHBOARD_ACTIVE_COIN_NET_PEERS, + DASHBOARD_ACTIVE_COIN_NET_TOTALS, } from '../actions/storeType'; // TODO: refactor current coin props copy on change @@ -40,6 +42,10 @@ export function ActiveCoin(state = { progress: null, rescanInProgress: false, getinfoFetchFailures: 0, + net: { + peers: null, + totals: null, + }, }, action) { switch (action.type) { case DASHBOARD_REMOVE_COIN: @@ -61,6 +67,10 @@ export function ActiveCoin(state = { activeSection: 'default', progress: null, rescanInProgress: false, + net: { + peers: null, + totals: null, + }, }; } else { return { @@ -87,6 +97,7 @@ export function ActiveCoin(state = { progress: state.progress, rescanInProgress: state.rescanInProgress, getinfoFetchFailures: state.getinfoFetchFailures, + net: state.net, }; let _coins = state.coins; @@ -114,6 +125,7 @@ export function ActiveCoin(state = { progress: _coinData.progress, rescanInProgress: _coinData.rescanInProgress, getinfoFetchFailures: _coinData.getinfoFetchFailures, + net: _coinData.net, }; } else { if (state.coin) { @@ -134,6 +146,7 @@ export function ActiveCoin(state = { progress: state.progress, rescanInProgress: state.rescanInProgress, getinfoFetchFailures: state.getinfoFetchFailures, + net: state.net, }; let _coins = state.coins; @@ -156,6 +169,10 @@ export function ActiveCoin(state = { activeSection: 'default', progress: null, rescanInProgress: false, + net: { + peers: null, + totals: null, + }, }; } else { return { @@ -172,6 +189,10 @@ export function ActiveCoin(state = { activeSection: 'default', progress: null, rescanInProgress: false, + net: { + peers: null, + totals: null, + }, }; } } @@ -272,6 +293,22 @@ export function ActiveCoin(state = { rescanInProgress: action.rescanInProgress, }; } + case DASHBOARD_ACTIVE_COIN_NET_PEERS: + return { + ...state, + net: { + peers: action.peers, + totals: state.net.totals, + }, + }; + case DASHBOARD_ACTIVE_COIN_NET_TOTALS: + return { + ...state, + net: { + peers: state.net.peers, + totals: action.totals, + }, + }; default: return state; } diff --git a/react/src/reducers/dex.js b/react/src/reducers/dex.js index 338a8e936..b0a669e15 100644 --- a/react/src/reducers/dex.js +++ b/react/src/reducers/dex.js @@ -13,6 +13,7 @@ import { DEX_RESET, DEX_PRICES, DEX_STATS, + DEX_ACTIVE_SECTION, } from '../actions/storeType'; export function Dex(state = { @@ -30,7 +31,10 @@ export function Dex(state = { prices: {}, utxo: {}, inventory: {}, - stats: {} + stats: {}, + coinsHelper: {}, + electrumServersList: {}, + section: 'coins', }, action) { switch (action.type) { case DEX_CACHE_PRELOAD: @@ -41,10 +45,14 @@ export function Dex(state = { pair: action.pair, coins: action.coins, swaps: action.swaps, + stats: action.stats, rates: action.rates, prices: action.prices, utxo: action.utxo, inventory: action.inventory, + coinsHelper: action.coinsHelper, + electrumServersList: action.electrumServersList, + section: state.section, }; case DEX_RESET: return { @@ -62,6 +70,9 @@ export function Dex(state = { prices: {}, utxo: {}, inventory: {}, + coinsHelper: {}, + electrumServersList: {}, + section: state.section, }; case DEX_LOGIN: return { @@ -111,6 +122,11 @@ export function Dex(state = { ...state, stats: action.stats, }; + case DEX_ACTIVE_SECTION: + return { + ...state, + section: action.section, + }; default: return state; } diff --git a/react/src/store.js b/react/src/store.js index 1047d99c2..0e1132ee6 100644 --- a/react/src/store.js +++ b/react/src/store.js @@ -10,9 +10,6 @@ import rootReducer from './reducers/index'; const loggerMiddleware = createLogger(); const defaultState = { - toaster: null, - AddCoin: null, - Main: null, }; // const enhancers = compose(window.devToolsExtension ? window.devToolsExtension() : f => f); diff --git a/react/src/styles/dex/_base.scss b/react/src/styles/dex/_base.scss index 499f633f2..cf664cce4 100644 --- a/react/src/styles/dex/_base.scss +++ b/react/src/styles/dex/_base.scss @@ -109,19 +109,53 @@ text-decoration: underline; } - .crypto-icons-pack { - svg { - position: relative; - top: 9px; - left: 10px; - } - } - .dashboard-wallets-list { .coinList-coin { - width: 32%; + width: calc(33% - 20px); float: left; margin-right: 20px; + margin-bottom: 40px; + + img { + position: relative; + top: 4px; + left: 5px; + max-height: 58px; + max-width: 50px; + opacity: 0.9; + border-radius: 50%; + } + .coinList-coin_balance-name { + text-transform: capitalize; + } + &:hover { + img { + opacity: 1; + } + } + } + .add-new-coin { + i { + width: 30px; + height: 30px; + transform: rotate(0deg); + border-radius: 50%; + background: #fff; + } + } + } + + .prices { + .coin-icon-svg { + img { + width: 24px; + height: 24px; + border-radius: 50%; + } + } + .orders-item-wrapper { + width: 100%; + max-width: 600px; } } } \ No newline at end of file diff --git a/react/src/styles/dex/_helpers.scss b/react/src/styles/dex/_helpers.scss index 33189682e..aebe63f3e 100644 --- a/react/src/styles/dex/_helpers.scss +++ b/react/src/styles/dex/_helpers.scss @@ -43,7 +43,7 @@ .coin-icon-placeholder, .coin-icon-svg { - background: rgba(256,256,256,0.1); + background: rgba(255,255,255,1); box-shadow: $box-shadow-inputs; border-radius: 50% !important; } diff --git a/react/src/styles/dex/components/coinList.scss b/react/src/styles/dex/components/coinList.scss index 567e3b9da..fcc4bfc3f 100644 --- a/react/src/styles/dex/components/coinList.scss +++ b/react/src/styles/dex/components/coinList.scss @@ -60,7 +60,7 @@ } .coinList-coin:hover .coinList-coin_action svg { - fill: #FFF; + /*fill: #FFF;*/ transform: translateX(10px) scale(1.1) } diff --git a/react/src/styles/index.scss b/react/src/styles/index.scss index db36c1089..c9f38b1e9 100644 --- a/react/src/styles/index.scss +++ b/react/src/styles/index.scss @@ -46,6 +46,7 @@ @import '../components/dashboard/spinner/spinner.scss'; @import '../components/toaster/toaster.scss'; @import '~react-table/react-table.css'; +@import '~react-select/dist/react-select.css'; /* dex */ @import 'dex/main.scss'; diff --git a/react/src/translate/en.js b/react/src/translate/en.js index 9e7dc80ba..b16609461 100644 --- a/react/src/translate/en.js +++ b/react/src/translate/en.js @@ -76,7 +76,7 @@ export const _lang = { 'SPV_SERVER_PORT': 'Server Port', 'SPV_SERVER_CON_TYPE': 'Connection type', 'COIND_DOWN_MODAL_ERROR': ' debug.log is empty. Looks like daemon didn\'t start properly. Please retry.', - 'SPV_MODE': 'SPV Mode', + 'SPV_MODE': 'Lite (SPV) Mode', 'PROGRESS_RESCANNING_BLOCKS': '(rescanning blocks)', 'BLOCKS': 'Blocks', 'PLEASE_WAIT_UNTIL_RESCAN_FINISHED': 'Please wait until rescan process is finished', @@ -160,12 +160,11 @@ export const _lang = { 'SELECT': '-Select-', 'NATIVE_MODE': 'Native Mode', 'NATIVE_MODE_DESC1': 'This mode is ONLY available for KOMODO Coin, PAX FIAT Chains, Assetchains, and Geckochains. ' + - 'This mode uses the', - 'NATIVE_MODE_DESC2': 'instead of the', - 'NATIVE_MODE_DESC3': 'to query blockchain data', - 'NATIVE_MODE_DESC4': 'is the only mode which allows you to make', - 'NATIVE_MODE_DESC5': 'Z Transactions', - 'NATIVE_MODE_DESC6': 'Private Transactions', + 'This mode uses', + 'NATIVE_MODE_DESC2': 'to query blockchain data.', + 'NATIVE_MODE_DESC3': 'is the only mode which allows you to make', + 'NATIVE_MODE_DESC4': 'Z Transactions', + 'NATIVE_MODE_DESC5': 'Private Transactions', 'CLOSE': 'Close', 'PLEASE_USE': 'Please use either', 'OR': 'or', @@ -333,6 +332,8 @@ export const _lang = { 'CRYPTO_CURRENCIES': 'Crypto Currencies', 'ASSETCHAINS': 'Assetchains', 'FIAT_CURRENCIES': 'Fiat Currencies', + 'LITE': 'Lite', + 'LITE_MODE_DESC': 'Lite mode doesn\'t require any blockchain to be loaded locally. All data is requested on demand from Electrum servers. Lite mode has higher network latency compared to native mode.', }, 'JUMBLR': { 'TO_SM': 'to', @@ -393,8 +394,6 @@ export const _lang = { 'ACCESS_JUMBLR_FUNDS': 'How to Access your Jumblr Funds', 'ADDRESS_ACCESSIBLE_EASILY': 'Your Jumbler Addresses are accessible easily. For example you logged into your wallet with passphrase', 'TO_ACCESS': 'To access your Jumbler address funds Logout.', - 'CLOSE_IAPP': 'Close Iguana App.', - 'START_IAPP': 'Start Iguana App again.', 'START_KMD': 'Start Komodo in either Full Mode or Basilisk Mode.', 'WORD_JUMBLR': 'Then add word \'jumblr \' before your passphrase.', 'SMALL_LETTERS': '"jumblr" is all in small letters.', @@ -526,7 +525,6 @@ export const _lang = { 'INVALID_QUERY_ALT': 'Invalid query sent. Please try again.', 'VALIDATION_SUCCESS': 'Validation Success on Network', 'KMD_NATIVE_CON_ERROR': 'Connection Error. Is external wallet running?', - 'KMD_IGUANA_CON_ERROR': 'Connection Error. Is iguana connected to external wallet?', 'LOGIN_SUCCESSFULL': 'Login Successfull', 'OPPS': 'Opps... Something went wrong!', 'INVALID_PASSPHRASE': 'Invalid Passphrase. Make sure your passphrase is correct, or create new wallet.', @@ -762,7 +760,6 @@ export const _lang = { 'TRADE_HISTORY_SM': 'trade history', 'ELECTRUM_MODE': 'Electrum mode', 'NATIVE_MODE': 'Native mode', - }, }, }; \ No newline at end of file diff --git a/react/src/util/auth.js b/react/src/util/auth.js deleted file mode 100644 index 46d20f182..000000000 --- a/react/src/util/auth.js +++ /dev/null @@ -1,14 +0,0 @@ -import { PassPhraseGenerator } from './crypto/passphrasegenerator.js'; -import { md5 } from './crypto/md5.js'; - -let appSessionHash; - -try { - appSessionHash = window.require('electron').remote.getCurrentWindow().appSessionHash; -} catch (e) { - appSessionHash = '1234'; -} - -export function iguanaSetRPCAuth() { - sessionStorage.setItem('IguanaRPCAuth', appSessionHash); -} \ No newline at end of file diff --git a/react/src/util/cacheFormat.js b/react/src/util/cacheFormat.js deleted file mode 100644 index 40b4697d8..000000000 --- a/react/src/util/cacheFormat.js +++ /dev/null @@ -1,51 +0,0 @@ -export function edexGetTxIDList(getTxData) { - let getTxidList = []; - - for (let i = 0; i < getTxData.length; i++) { - getTxidList.push(getTxData[i].txid); - } - - return getTxidList; -} - -export function edexRemoveTXID(_obj, address, txidArray) { - let txidToStr = `:${txidArray.join(':')}:`; - - if (_obj, _obj.basilisk) { - if (Object.keys(_obj.basilisk).length === 0) { - console.warn('no coin nodes to parse'); - } else { - for (let key in _obj.basilisk) { - for (let coinAddr in _obj.basilisk[key]) { - if (_obj.basilisk[key][coinAddr] !== 'addresses' && - coinAddr === address) { - if (_obj.basilisk[key][coinAddr].refresh && - _obj.basilisk[key][coinAddr].refresh.data && - _obj.basilisk[key][coinAddr].refresh.data.length > 0) { - for (let i = 0; i < _obj.basilisk[key][coinAddr].refresh.data.length; i++) { - if (txidToStr.indexOf(_obj.basilisk[key][coinAddr].refresh.data[i].txid.toString()) > -1) { - _obj.basilisk[key][coinAddr].refresh.data.splice(i, 1); - _obj.basilisk[key][coinAddr].refresh.timestamp = Date.now(); - } - } - } - if (_obj.basilisk[key][coinAddr].listunspent && - _obj.basilisk[key][coinAddr].listunspent.data && - _obj.basilisk[key][coinAddr].listunspent.data.length > 0) { - for (let i = 0; i < _obj.basilisk[key][coinAddr].listunspent.data.length; i++) { - if (txidToStr.indexOf(_obj.basilisk[key][coinAddr].listunspent.data[i].txid.toString()) > -1) { - _obj.basilisk[key][coinAddr].listunspent.data.splice(i, 1); - _obj.basilisk[key][coinAddr].listunspent.timestamp = Date.now(); - } - } - } - } - } - } - } - } else { - console.warn('basilisk node is missing'); - } - - return _obj; -} \ No newline at end of file diff --git a/react/src/util/formatBytes.js b/react/src/util/formatBytes.js new file mode 100644 index 000000000..566acca1f --- /dev/null +++ b/react/src/util/formatBytes.js @@ -0,0 +1,24 @@ +const formatBytes = (bytes, decimals) => { + if (bytes === 0) { + return '0 Bytes'; + } + + const k = 1000; + const dm = (decimals + 1) || 3; + const sizes = [ + 'Bytes', + 'KB', + 'MB', + 'GB', + 'TB', + 'PB', + 'EB', + 'ZB', + 'YB' + ]; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + + return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`; +} + +export default formatBytes; \ No newline at end of file