Browse Source

Merge pull request #149 from SuperNETorg/update

Update
all-modes
pbca26 7 years ago
committed by GitHub
parent
commit
d7dbe39834
  1. 10
      react/change.log
  2. 2
      react/src/actions/actionCreators.js
  3. 16
      react/src/actions/actions/addCoin.js
  4. 56
      react/src/actions/actions/addressBalance.js
  5. 4
      react/src/actions/actions/atomic.js
  6. 2
      react/src/actions/actions/basiliskCache.js
  7. 2
      react/src/actions/actions/basiliskProcessAddress.js
  8. 28
      react/src/actions/actions/copyAddress.js
  9. 2
      react/src/actions/actions/createWallet.js
  10. 18
      react/src/actions/actions/nativeNewAddress.js
  11. 11
      react/src/actions/actions/nativeSend.js
  12. 1
      react/src/actions/actions/nativeSyncInfo.js
  13. 12
      react/src/actions/actions/settings.js
  14. 2
      react/src/actions/actions/syncOnly.js
  15. 2
      react/src/actions/actions/sysInfo.js
  16. 42
      react/src/components/addcoin/addcoin.js
  17. 11
      react/src/components/addcoin/addcoin.render.js
  18. 10
      react/src/components/addcoin/addcoin.scss
  19. 2
      react/src/components/addcoin/addcoinOptionsAC.js
  20. 2
      react/src/components/addcoin/addcoinOptionsACFiat.js
  21. 52
      react/src/components/addcoin/addcoinOptionsCrypto.js
  22. 16
      react/src/components/addcoin/coin-selectors.render.js
  23. 114
      react/src/components/addcoin/payload.js
  24. 23
      react/src/components/dashboard/about/about.js
  25. 130
      react/src/components/dashboard/atomic/atomic.js
  26. 24
      react/src/components/dashboard/coinTile/coinTileItem.js
  27. 2
      react/src/components/dashboard/coinTile/coinTileItem.render.js
  28. 1
      react/src/components/dashboard/main/dashboard.js
  29. 53
      react/src/components/dashboard/main/dashboard.scss
  30. 1
      react/src/components/dashboard/notifications/notifications.js
  31. 32
      react/src/components/dashboard/receiveCoin/receiveCoin.js
  32. 6
      react/src/components/dashboard/receiveCoin/receiveCoin.render.js
  33. 124
      react/src/components/dashboard/sendCoin/sendCoin.js
  34. 19
      react/src/components/dashboard/sendCoin/sendCoin.render.js
  35. 39
      react/src/components/dashboard/settings/settings.js
  36. 83
      react/src/components/dashboard/settings/settings.render.js
  37. 5
      react/src/components/dashboard/syncOnly/syncOnly.js
  38. 12
      react/src/components/dashboard/syncOnly/syncOnly.render.js
  39. 59
      react/src/components/dashboard/walletsBalance/walletsBalance.js
  40. 35
      react/src/components/dashboard/walletsBalance/walletsBalance.render.js
  41. 48
      react/src/components/dashboard/walletsData/walletsData.js
  42. 4
      react/src/components/dashboard/walletsData/walletsData.render.js
  43. 5
      react/src/components/dashboard/walletsNativeAlert/walletsNativeAlert.render.js
  44. 11
      react/src/components/dashboard/walletsNativeSyncProgress/walletsNativeSyncProgress.js
  45. 36
      react/src/components/dashboard/walletsNativeTxHistory/walletsNativeTxHistory.render.js
  46. 25
      react/src/components/dashboard/walletsProgress/walletsProgress.js
  47. 87
      react/src/components/dashboard/walletsProgress/walletsProgress.render.js
  48. 5
      react/src/components/dashboard/walletsTxInfo/walletsTxInfo.js
  49. 42
      react/src/components/dashboard/walletsTxInfo/walletsTxInfo.render.js
  50. 65
      react/src/components/login/login.js
  51. 47
      react/src/components/login/login.render.js
  52. 24
      react/src/components/login/login.scss
  53. 2
      react/src/components/overrides.scss
  54. 2
      react/src/reducers/addcoin.js
  55. 5
      react/src/reducers/toaster.js
  56. 80
      react/src/translate/en.js
  57. 9
      react/src/util/sort.js

10
react/change.log

@ -1,6 +1,14 @@
v0.2.0.21a-beta
--------------
UI:
- fixed transaction info modal bug
- full mode is disabled on windows
- fixed BTC add coin bug
- updated login form
v0.2.0.2a-beta
--------------
front:
UI:
- fixed native t to t bug that led to interest loss
- added pending request(s) spinner
- added missing native z_balance api call for z-addresses

2
react/src/actions/actionCreators.js

@ -295,7 +295,7 @@ export function rpcErrorHandler(json, dispatch) {
if (json &&
json.error) {
if (json.error === 'bitcoinrpc needs coin that is active') {
dispatch(triggerToaster('No active coin', translate('TOASTR.SERVICE_NOTIFICATION'), 'error'));
dispatch(triggerToaster(translate('API.NO_ACTIVE_COIN'), translate('TOASTR.SERVICE_NOTIFICATION'), 'error'));
}
}
}

16
react/src/actions/actions/addCoin.js

@ -47,7 +47,7 @@ export function addCoin(coin, mode, syncOnly, port, startupParams) {
const modeToValue = {
'1': 'full',
'0': 'basilisk',
'-1': 'native'
'-1': 'native',
};
return dispatch => {
@ -161,7 +161,7 @@ export function shepherdHerd(coin, mode, path, startupParams) {
'-daemon=0',
'-server',
`-ac_name=${coin}`,
'-addnode=78.47.196.146'
'-addnode=78.47.196.146',
]
};
@ -170,7 +170,7 @@ export function shepherdHerd(coin, mode, path, startupParams) {
'ac_name': 'zcashd',
'ac_options': [
'-daemon=0',
'-server=1'
'-server=1',
]
};
}
@ -180,7 +180,7 @@ export function shepherdHerd(coin, mode, path, startupParams) {
'ac_name': 'komodod',
'ac_options': [
'-daemon=0',
'-addnode=78.47.196.146'
'-addnode=78.47.196.146',
]
};
}
@ -302,7 +302,7 @@ export function _shepherdGetConfig(coin, mode, startupParams) {
console.log(error);
dispatch(
triggerToaster(
'Failed to get mode config',
'_shepherdGetConfig',
'Error',
'error'
)
@ -334,7 +334,7 @@ export function iguanaActiveHandleBypass() {
console.log(error);
dispatch(
triggerToaster(
'Failed to iguanaActiveHandleBypass',
'iguanaActiveHandleBypass',
'Error',
'error'
)
@ -364,7 +364,7 @@ export function shepherdGetConfig(coin, mode, startupParams) {
console.log(error);
dispatch(
triggerToaster(
'Failed to get KMD config',
'shepherdGetConfig',
'Error',
'error'
)
@ -395,7 +395,7 @@ export function shepherdGetConfig(coin, mode, startupParams) {
console.log(error);
dispatch(
triggerToaster(
'Failed to get mode config',
'shepherdGetConfig',
'Error',
'error'
)

56
react/src/actions/actions/addressBalance.js

@ -33,20 +33,11 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
return dispatch => {
Promise.all(type.map((_type, index) => {
return new Promise((resolve, reject) => {
let payload,
ajaxFunctionInput = '',
tmplistaddrHexInput = '',
passthruAgent = getPassthruAgent(coin),
tmpIguanaRPCAuth = `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`;
if (_type === 'public') {
ajaxFunctionInput = 'getaddressesbyaccount';
tmplistaddrHexInput = '222200';
}
if (_type === 'private') {
ajaxFunctionInput = 'z_listaddresses';
tmplistaddrHexInput = '';
}
let payload;
let ajaxFunctionInput = _type === 'public' ? 'getaddressesbyaccount' : 'z_listaddresses';
let tmplistaddrHexInput = _type === 'public' ? '222200' : '';
let passthruAgent = getPassthruAgent(coin);
let tmpIguanaRPCAuth = `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`;
if (passthruAgent === 'iguana') {
payload = {
@ -112,7 +103,7 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
mode: null,
chain: coin,
cmd: payload.function,
params: [""]
params: [''],
};
}
@ -175,27 +166,18 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
}))
.then(result => {
// TODO: split into 2 functions
const passthruAgent = getPassthruAgent(coin),
tmpIguanaRPCAuth = `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`;
let payload;
const passthruAgent = getPassthruAgent(coin);
const tmpIguanaRPCAuth = `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`;
let payload = {
'userpass': `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`,
'agent': passthruAgent,
'method': 'passthru',
'function': 'listunspent',
'hex': '',
};
if (passthruAgent === 'iguana') {
payload = {
'userpass': `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`,
'agent': passthruAgent,
'method': 'passthru',
'asset': coin,
'function': 'listunspent',
'hex': '',
};
} else {
payload = {
'userpass': `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`,
'agent': passthruAgent,
'method': 'passthru',
'function': 'listunspent',
'hex': '',
};
payload.asset = coin;
}
if (mode === 'full') {
@ -341,7 +323,7 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
cmd: 'z_getbalance',
params: [
_address
]
],
};
_fetchConfig = {
@ -375,7 +357,7 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
.then(response => response.json())
.then(function(json) {
if (json &&
json.error) {
json.error) {
resolve(0);
dispatch(logGuiHttp({
'timestamp': _timestamp,
@ -525,7 +507,7 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
mode: null,
chain: coin,
cmd: payload.function,
params: payload.params
params: payload.params,
};
_fetchConfig = {

4
react/src/actions/actions/atomic.js

@ -34,8 +34,8 @@ export function atomic(payload) {
dispatch(
triggerToaster(
payload.method,
'Atomic Explorer error',
'error'
translate('API.ATOMIC_EXPLORER_ERR'),
translate('API.ERROR_SM')
)
);
})

2
react/src/actions/actions/basiliskCache.js

@ -8,6 +8,8 @@ import {
guiLogState
} from './log';
// TODO: rewrite cache API to use POST
export function deleteCacheFile(_payload) {
return dispatch => {
return fetch(`http://127.0.0.1:${Config.agamaPort}/shepherd/groom`, {

2
react/src/actions/actions/basiliskProcessAddress.js

@ -79,7 +79,7 @@ function checkAddressBasiliskHandle(json) {
return dispatch => {
dispatch(
triggerToaster(
'Address already registered',
translate('API.ADDRESS_ALREADY_REG'),
translate('TOASTR.WALLET_NOTIFICATION'),
'warning'
)

28
react/src/actions/actions/copyAddress.js

@ -5,25 +5,13 @@ import { triggerToaster } from '../actionCreators';
export function copyCoinAddress(address) {
const _result = copyToClipboard(address);
if (_result) {
return dispatch => {
dispatch(
triggerToaster(
translate('DASHBOARD.ADDR_COPIED'),
translate('TOASTR.COIN_NOTIFICATION'),
'success'
)
);
}
} else {
return dispatch => {
dispatch(
triggerToaster(
'Couldn\'t copy address to clipboard',
translate('TOASTR.COIN_NOTIFICATION'),
'error'
)
);
}
return dispatch => {
dispatch(
triggerToaster(
translate(_result ? 'DASHBOARD.ADDR_COPIED' : 'API.COULDNT_COPY_ADDRESS'),
translate('TOASTR.COIN_NOTIFICATION'),
_result ? 'success' : 'error'
)
);
}
}

2
react/src/actions/actions/createWallet.js

@ -25,7 +25,7 @@ function createNewWalletState(json) {
return dispatch => {
dispatch(
triggerToaster(
'Couldn\'t create new wallet seed',
translate('API.COULDNT_CREATE_SEED'),
translate('TOASTR.ACCOUNT_NOTIFICATION'),
'error'
)

18
react/src/actions/actions/nativeNewAddress.js

@ -11,13 +11,6 @@ import {
} from './log';
function handleGetNewKMDAddresses(pubpriv, coin, dispatch, json) {
/*dispatch(
triggerToaster(
translate('KMD_NATIVE.NEW_ADDR_GENERATED'),
translate('TOASTR.WALLET_NOTIFICATION'),
'success'
)
);*/
dispatch(
triggerToaster(
json.result ? json.result : json,
@ -32,15 +25,8 @@ function handleGetNewKMDAddresses(pubpriv, coin, dispatch, json) {
}
export function getNewKMDAddresses(coin, pubpriv) {
let payload,
ajaxFunctionInput = '';
if (pubpriv === 'public') {
ajaxFunctionInput = 'getnewaddress';
}
if (pubpriv === 'private') {
ajaxFunctionInput = 'z_getnewaddress';
}
let payload;
let ajaxFunctionInput = pubpriv === 'public' ? 'getnewaddress' : 'z_getnewaddress';
if (getPassthruAgent(coin) === 'iguana') {
payload = {

11
react/src/actions/actions/nativeSend.js

@ -16,11 +16,11 @@ export function sendNativeTx(coin, _payload) {
let payload;
let _apiMethod;
if (_payload.addressType === 'public' &&
if (_payload.addressType === 'public' && // transparent
_payload.sendTo.length !== 95) {
_apiMethod = 'sendtoaddress';
ajaxDataToHex = `["${_payload.sendTo}", ${Number(_payload.amount) - Number(_payload.fee)}]`;
} else {
} else { // private
_apiMethod = 'z_sendmany';
ajaxDataToHex = `["${_payload.sendFrom}", [{"address": "${_payload.sendTo}", "amount": ${Number(_payload.amount) - Number(_payload.fee)}}]]`;
}
@ -122,7 +122,10 @@ export function sendNativeTx(coin, _payload) {
}));
if (json.indexOf('"code":') > -1) {
const _message = json.substring(json.indexOf('"message":"') + 11, json.indexOf('"},"id":"jl777"'));
const _message = json.substring(
`${json.indexOf('"message":"')}11`,
json.indexOf('"},"id":"jl777"')
);
dispatch(
triggerToaster(
@ -138,7 +141,7 @@ export function sendNativeTx(coin, _payload) {
triggerToaster(
true,
translate('TOASTR.WALLET_NOTIFICATION'),
'Your wallet.dat is not matching the blockchain. Please resync from the scratch.',
translate('API.WALLETDAT_MISMATCH'),
'info',
false
)

1
react/src/actions/actions/nativeSyncInfo.js

@ -148,7 +148,6 @@ export function getSyncInfoNative(coin, skipDebug) {
const _response = response.text().then(function(text) { return text; });
return _response;
})
//.then(response => response.json())
.then(json => {
if (!json &&
Config.cli.default) {

12
react/src/actions/actions/settings.js

@ -58,7 +58,7 @@ function parseImportPrivKeyResponse(json, dispatch) {
return dispatch => {
dispatch(
triggerToaster(
'Illegal privkey',
transalte('API.ILLEGAL_PRIVKEY'),
translate('TOASTR.SETTINGS_NOTIFICATION'),
'error'
)
@ -69,7 +69,7 @@ function parseImportPrivKeyResponse(json, dispatch) {
return dispatch => {
dispatch(
triggerToaster(
'Privkey already in wallet',
transalte('API.PRIVKEY_IN_WALLET'),
translate('TOASTR.SETTINGS_NOTIFICATION'),
'warning'
)
@ -265,7 +265,7 @@ function addPeerNodeState(json, dispatch) {
return dispatch => {
dispatch(
triggerToaster(
'Addnode needs active coin',
translate('API.ADDNODE_NEEDS_COIN'),
translate('TOASTR.SETTINGS_NOTIFICATION'),
'error'
)
@ -276,7 +276,7 @@ function addPeerNodeState(json, dispatch) {
return dispatch => {
dispatch(
triggerToaster(
'Peer was already connected',
translate('API.PEER_ALREADY_CONN'),
translate('TOASTR.SETTINGS_NOTIFICATION'),
'warning'
)
@ -287,7 +287,7 @@ function addPeerNodeState(json, dispatch) {
return dispatch => {
dispatch(
triggerToaster(
'Addnode connection was already pending',
translate('API.ADDNODE_ALREADY_PENDING'),
translate('TOASTR.SETTINGS_NOTIFICATION'),
'warning'
)
@ -298,7 +298,7 @@ function addPeerNodeState(json, dispatch) {
return dispatch => {
dispatch(
triggerToaster(
'Peer is added',
translate('API.PEER_ADDED'),
translate('TOASTR.SETTINGS_NOTIFICATION'),
'success'
)

2
react/src/actions/actions/syncOnly.js

@ -71,7 +71,7 @@ export function stopIguanaFork(pmid) {
.then(
json => dispatch(
triggerToaster(
'Iguana instance is stopped',
translate('API.IGUANA_INSTANCE_STOP'),
translate('TOASTR.SERVICE_NOTIFICATION'),
'success'
)

2
react/src/actions/actions/sysInfo.js

@ -19,7 +19,7 @@ export function shepherdGetSysInfo() {
console.log(error);
dispatch(
triggerToaster(
'Failed to get sys info',
'shepherdGetSysInfo',
'Error',
'error'
)

42
react/src/components/addcoin/addcoin.js

@ -10,6 +10,8 @@ import {
} from '../../actions/actionCreators';
import Store from '../../store';
// TODO: refactor coin selector options renders
import CoinSelectorsRender from './coin-selectors.render';
import AddCoinRender from './addcoin.render';
@ -136,25 +138,26 @@ class AddCoin extends React.Component {
updateSelectedCoin(e, index) {
const coin = e.target.value.split('|');
const defaultMode = Config.iguanaLessMode ? 'native' : coin[1];
const modeToValue = {
const modeToValue = { // TODO: move to utils
'full': 1,
'basilisk': 0,
'native': -1,
};
let _coins = this.state.coins;
const _value = e.target.value;
_coins[index] = {
[e.target.name]: e.target.value,
[e.target.name]: _value,
fullMode: {
disabled: e.target.value.indexOf('full') > -1 ? false : true,
disabled: _value.indexOf('full') > -1 ? false : true,
checked: defaultMode === 'full' ? true : false,
},
basiliskMode: {
disabled: e.target.value.indexOf('basilisk') > -1 ? false : true,
disabled: _value.indexOf('basilisk') > -1 ? false : true,
checked: defaultMode === 'basilisk' ? true : false,
},
nativeMode: {
disabled: e.target.value.indexOf('native') > -1 ? false : true,
disabled: _value.indexOf('native') > -1 ? false : true,
checked: defaultMode === 'native' ? true : false,
},
mode: modeToValue[defaultMode] !== undefined ? modeToValue[defaultMode] : -2,
@ -168,23 +171,24 @@ class AddCoin extends React.Component {
updateSelectedMode(_value, index) {
let _coins = this.state.coins;
const _selectedCoin = _coins[index].selectedCoin;
_coins[index] = {
selectedCoin: _coins[index].selectedCoin,
selectedCoin: _selectedCoin,
fullMode: {
disabled: _coins[index].selectedCoin.indexOf('full') > -1 ? false : true,
disabled: _selectedCoin.indexOf('full') > -1 ? false : true,
checked: _value === '1' ? true : false,
},
basiliskMode: {
disabled: _coins[index].selectedCoin.indexOf('basilisk') > -1 ? false : true,
disabled: _selectedCoin.indexOf('basilisk') > -1 ? false : true,
checked: _value === '0' ? true : false,
},
nativeMode: {
disabled: _coins[index].selectedCoin.indexOf('native') > -1 ? false : true,
disabled: _selectedCoin.indexOf('native') > -1 ? false : true,
checked: _value === '-1' ? true : false,
},
mode: _value,
syncOnly: this.state.coins[index].syncOnly,
syncOnly: _coins[index].syncOnly,
};
this.setState(Object.assign({}, this.state, {
@ -200,25 +204,26 @@ class AddCoin extends React.Component {
activateCoin() {
const coin = this.state.coins[0].selectedCoin.split('|')[0];
const _coin = this.state.coins[0];
if (this.isCoinAlreadyAdded(coin)) {
this.dismiss();
return;
}
if (!this.state.coins[0].daemonParam) {
if (!_coin.daemonParam) {
Store.dispatch(addCoin(
coin,
this.state.coins[0].mode,
this.state.coins[0].syncOnly,
_coin.mode,
_coin.syncOnly,
));
} else {
Store.dispatch(addCoin(
coin,
this.state.coins[0].mode,
this.state.coins[0].syncOnly,
_coin.mode,
_coin.syncOnly,
null,
{ type: this.state.coins[0].daemonParam }
{ type: _coin.daemonParam } // TODO: custom param value
));
}
@ -298,9 +303,10 @@ class AddCoin extends React.Component {
renderCoinSelectors() {
let items = [];
const _coins = this.state.coins;
for (let i = 0; i < this.state.coins.length; i++) {
const _item = this.state.coins[i];
for (let i = 0; i < _coins.length; i++) {
const _item = _coins[i];
const _coin = _item.selectedCoin || '';
items.push(

11
react/src/components/addcoin/addcoin.render.js

@ -1,6 +1,8 @@
import React from 'react';
import { translate } from '../../translate/translate';
// TODO: add modal close on modal overlay click evt
const AddCoinRender = function() {
return (
<div onKeyDown={ (event) => this.handleKeydown(event) }>
@ -25,7 +27,7 @@ const AddCoinRender = function() {
<button
className="btn btn-outline-primary btn-add-coin-item-options"
onClick={ this.toggleActionsMenu }>
<i className={ this.state.actionsMenu ? 'fa-chevron-up' : 'fa-chevron-down' }></i>
<i className={ 'fa-chevron-' + (this.state.actionsMenu ? 'up' : 'down') }></i>
</button>
<span className={ !this.state.actionsMenu ? 'hide' : '' }>
<button
@ -61,12 +63,7 @@ const AddCoinRender = function() {
<i>Iguana Daemon</i> { translate('INDEX.NATIVE_MODE_DESC3') }.
</p>
<div className="alert alert-icon alert-primary">
<button
type="button"
className="close">
<span>×</span>
</button>
<i className="icon md-info-outline"></i>
<i className="icon md-info-outline"></i>
<strong>{ translate('INDEX.NATIVE_MODE') }</strong> { translate('INDEX.NATIVE_MODE_DESC4') }&nbsp;
<strong>{ translate('INDEX.NATIVE_MODE_DESC5') }</strong>,&nbsp;
<i>{ translate('INDEX.NATIVE_MODE_DESC5') }</i>.

10
react/src/components/addcoin/addcoin.scss

@ -14,4 +14,14 @@
.float-none {
float: none;
}
.add-coin-modes {
> div {
padding: 0;
label {
margin: 0;
}
}
}

2
react/src/components/addcoin/addcoinOptionsAC.js

@ -4,7 +4,7 @@ import { translate } from '../../translate/translate';
class AddCoinOptionsAC extends React.Component {
render() {
return (
<optgroup label="Assetchains">
<optgroup label={ translate('ADD_COIN.ASSETCHAINS') }>
<option value="BET|basilisk|native">BET (BET)</option>
<option value="BOTS|basilisk|native">BOTS (BOTS)</option>
<option value="CEAL|basilisk|native">CEAL NET (CEAL)</option>

2
react/src/components/addcoin/addcoinOptionsACFiat.js

@ -4,7 +4,7 @@ import { translate } from '../../translate/translate';
class AddCoinOptionsACFiat extends React.Component {
render() {
return (
<optgroup label="Fiat Currencies">
<optgroup label={ translate('ADD_COIN.FIAT_CURRENCIES') }>
<option value="AUD|basilisk|native">Australian Dollar (AUD)</option>
<option value="BRL|basilisk|native">Brazilian Real (BRL)</option>
<option value="GBP|basilisk|native">British Pound (GBP)</option>

52
react/src/components/addcoin/addcoinOptionsCrypto.js

@ -11,24 +11,50 @@ class AddCoinOptionsCrypto extends React.Component {
}
render() {
const isWindows = this.props.appSettings && this.props.appSettings.appInfo && this.props.appSettings.appInfo.sysInfo && this.props.appSettings.appInfo.sysInfo.platform === 'win32';
//<option value="ANC|full">AnonCoin (ANC)</option>
//<option value="MZC|full">MazaCoin (MZC)</option>
//<option value="SYS|full">SysCoin (SYS)</option>
return (
<optgroup label="Crypto Currencies">
<option value="BTCD|full" className={ this.state.nativeOnly ? 'hide' : '' }>BitcoinDark (BTCD)</option>
<option value="BTC|full|basilisk" className={ this.state.nativeOnly ? 'hide' : '' }>Bitcoin (BTC)</option>
<option value="BTM|full" className={ this.state.nativeOnly ? 'hide' : '' }>Bitmark (BTM)</option>
<option value="CARB|full" className={ this.state.nativeOnly ? 'hide' : '' }>Carboncoin (CARB)</option>
<option value="DGB|full" className={ this.state.nativeOnly ? 'hide' : '' }>Digibyte (DGB)</option>
<option value="DOGE|full" className={ this.state.nativeOnly ? 'hide' : '' }>Dogecoin (DOGE)</option>
<option value="FRK|full" className={ this.state.nativeOnly ? 'hide' : '' }>Franko (FRK)</option>
<option value="GAME|full" className={ this.state.nativeOnly ? 'hide' : '' }>Gamecredits (GAME)</option>
<optgroup label={ translate('ADD_COIN.CRYPTO_CURRENCIES') }>
<option
value="BTCD|full"
className={ this.state.nativeOnly || isWindows ? 'hide' : '' }>BitcoinDark (BTCD)</option>
<option
value="BTC|full"
className={ this.state.nativeOnly || isWindows ? 'hide' : '' }>Bitcoin (BTC)</option>
<option
value="BTM|full"
className={ this.state.nativeOnly || isWindows ? 'hide' : '' }>Bitmark (BTM)</option>
<option
value="CARB|full"
className={ this.state.nativeOnly || isWindows ? 'hide' : '' }>Carboncoin (CARB)</option>
<option
value="DGB|full"
className={ this.state.nativeOnly || isWindows ? 'hide' : '' }>Digibyte (DGB)</option>
<option
value="DOGE|full"
className={ this.state.nativeOnly || isWindows ? 'hide' : '' }>Dogecoin (DOGE)</option>
<option
value="FRK|full"
className={ this.state.nativeOnly || isWindows ? 'hide' : '' }>Franko (FRK)</option>
<option
value="GAME|full"
className={ this.state.nativeOnly || isWindows ? 'hide' : '' }>Gamecredits (GAME)</option>
<option value="KMD|basilisk|native">Komodo (KMD)</option>
<option value="LTC|full" className={ this.state.nativeOnly ? 'hide' : '' }>Litecoin (LTC)</option>
<option value="UNO|full" className={ this.state.nativeOnly ? 'hide' : '' }>Unobtanium (UNO)</option>
<option value="ZEC|full" className={ this.state.nativeOnly ? 'hide' : '' }>Zcash (ZEC)</option>
<option value="ZET|full" className={ this.state.nativeOnly ? 'hide' : '' }>Zetacoin (ZET)</option>
<option
value="LTC|full"
className={ this.state.nativeOnly || isWindows ? 'hide' : '' }>Litecoin (LTC)</option>
<option
value="UNO|full"
className={ this.state.nativeOnly || isWindows ? 'hide' : '' }>Unobtanium (UNO)</option>
<option
value="ZEC|full"
className={ this.state.nativeOnly || isWindows ? 'hide' : '' }>Zcash (ZEC)</option>
<option
value="ZET|full"
className={ this.state.nativeOnly || isWindows ? 'hide' : '' }>Zetacoin (ZET)</option>
</optgroup>
);
}

16
react/src/components/addcoin/coin-selectors.render.js

@ -5,6 +5,8 @@ import AddCoinOptionsAC from '../addcoin/addcoinOptionsAC';
import AddCoinOptionsACFiat from '../addcoin/addcoinOptionsACFiat';
const CoinSelectorsRender = function(item, coin, i) {
const isWindows = this.props.Settings && this.props.Settings.appInfo && this.props.Settings.appInfo.sysInfo && this.props.Settings.appInfo.sysInfo.platform === 'win32';
return (
<div
className={ this.hasMoreThanOneCoin() ? 'multi' : 'single' }
@ -18,9 +20,9 @@ const CoinSelectorsRender = function(item, coin, i) {
onChange={ (event) => this.updateSelectedCoin(event, i) }
autoFocus>
<option>{ translate('INDEX.SELECT') }</option>
<AddCoinOptionsCrypto />
<AddCoinOptionsAC />
<AddCoinOptionsACFiat />
<AddCoinOptionsCrypto appSettings={ this.props.Settings } />
<AddCoinOptionsAC appSettings={ this.props.Settings } />
<AddCoinOptionsACFiat appSettings={ this.props.Settings } />
</select>
</div>
</div>
@ -33,8 +35,8 @@ const CoinSelectorsRender = function(item, coin, i) {
{ translate('INDEX.ACTIVATE_COIN') }
</button>
</div>
<div className="col-sm-12 text-center">
<div className={ this.state.nativeOnly ? 'hide' : 'form-group col-lg-4 col-md-4 col-sm-6 col-xs-6 style-addcoin-lbl-mdl-login' }>
<div className="col-sm-11 text-center add-coin-modes">
<div className={ this.state.nativeOnly || isWindows ? 'hide' : 'form-group col-lg-4 col-md-4 col-sm-6 col-xs-6 style-addcoin-lbl-mdl-login' }>
<input
type="radio"
className="to-labelauty labelauty"
@ -94,7 +96,9 @@ const CoinSelectorsRender = function(item, coin, i) {
</span>
</label>
</div>
<div className="form-group col-lg-4 col-md-4 col-sm-6 col-xs-6" style={{ paddingLeft: this.state.nativeOnly ? '0' : 'inherit' }}>
<div
className="form-group col-lg-4 col-md-4 col-sm-6 col-xs-6"
style={{ paddingLeft: this.state.nativeOnly ? '0' : 'inherit' }}>
<input
type="radio"
className="to-labelauty labelauty"

114
react/src/components/addcoin/payload.js

@ -1,53 +1,54 @@
// TODO: merge check functions
export function checkAC(coinVal) {
if (coinVal == 'SUPERNET' ||
coinVal == 'REVS' ||
coinVal == 'WLC' ||
coinVal == 'DEX' ||
coinVal == 'PANGEA' ||
coinVal == 'JUMBLR' ||
coinVal == 'BET' ||
coinVal == 'CRYPTO' ||
coinVal == 'HODL' ||
coinVal == 'SHARK' ||
coinVal == 'BOTS' ||
coinVal == 'MGW' ||
coinVal == 'MVP' ||
coinVal == 'KV' ||
coinVal == 'CEAL' ||
coinVal == 'MESH' ||
coinVal == 'BTC' ||
coinVal == 'USD' ||
coinVal == 'RON' ||
coinVal == 'EUR' ||
coinVal == 'JPY' ||
coinVal == 'GBP' ||
coinVal == 'AUD' ||
coinVal == 'CAD' ||
coinVal == 'CHF' ||
coinVal == 'NZD' ||
coinVal == 'CNY' ||
coinVal == 'RUB' ||
coinVal == 'MXN' ||
coinVal == 'BRL' ||
coinVal == 'INR' ||
coinVal == 'HKD' ||
coinVal == 'TRY' ||
coinVal == 'ZAR' ||
coinVal == 'PLN' ||
coinVal == 'NOK' ||
coinVal == 'SEK' ||
coinVal == 'DKK' ||
coinVal == 'CZK' ||
coinVal == 'HUF' ||
coinVal == 'ILS' ||
coinVal == 'KRW' ||
coinVal == 'MYR' ||
coinVal == 'PHP' ||
coinVal == 'SGD' ||
coinVal == 'THB' ||
coinVal == 'BGN' ||
coinVal == 'IDR' ||
coinVal == 'HRK') {
if (coinVal === 'SUPERNET' ||
coinVal === 'REVS' ||
coinVal === 'WLC' ||
coinVal === 'DEX' ||
coinVal === 'PANGEA' ||
coinVal === 'JUMBLR' ||
coinVal === 'BET' ||
coinVal === 'CRYPTO' ||
coinVal === 'HODL' ||
coinVal === 'SHARK' ||
coinVal === 'BOTS' ||
coinVal === 'MGW' ||
coinVal === 'MVP' ||
coinVal === 'KV' ||
coinVal === 'CEAL' ||
coinVal === 'MESH' ||
coinVal === 'USD' ||
coinVal === 'RON' ||
coinVal === 'EUR' ||
coinVal === 'JPY' ||
coinVal === 'GBP' ||
coinVal === 'AUD' ||
coinVal === 'CAD' ||
coinVal === 'CHF' ||
coinVal === 'NZD' ||
coinVal === 'CNY' ||
coinVal === 'RUB' ||
coinVal === 'MXN' ||
coinVal === 'BRL' ||
coinVal === 'INR' ||
coinVal === 'HKD' ||
coinVal === 'TRY' ||
coinVal === 'ZAR' ||
coinVal === 'PLN' ||
coinVal === 'NOK' ||
coinVal === 'SEK' ||
coinVal === 'DKK' ||
coinVal === 'CZK' ||
coinVal === 'HUF' ||
coinVal === 'ILS' ||
coinVal === 'KRW' ||
coinVal === 'MYR' ||
coinVal === 'PHP' ||
coinVal === 'SGD' ||
coinVal === 'THB' ||
coinVal === 'BGN' ||
coinVal === 'IDR' ||
coinVal === 'HRK') {
return true;
} else {
return false;
@ -130,7 +131,7 @@ export function checkCoinType(coin) {
}
export function startCrypto(confpath, coin, mode) {
var tmpinternval = 0,
let tmpinternval = 0,
AddCoinData = {},
tmpPendValue = 1, // TODO: hook up to shepherd sysinfo
tmpIguanaRPCAuth = `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`;
@ -141,7 +142,8 @@ export function startCrypto(confpath, coin, mode) {
tmpPendValue = parseInt(tmpPendValue) * 4;
}
AddCoinData.BTCD = {'userpass':tmpIguanaRPCAuth,"RELAY":mode,"VALIDATE":mode,"prefetchlag":-1,"poll":50,"active":1,"agent":"iguana","method":"addcoin","newcoin":"BTCD","startpend":tmpPendValue,"endpend":tmpPendValue,"services":129,"maxpeers":64,"portp2p":14631,"rpc":14632}
AddCoinData.BTC = {'userpass':tmpIguanaRPCAuth,"RELAY":mode,"VALIDATE":mode,"startpend":tmpPendValue,"endpend":tmpPendValue,"prefetchlag":5,"poll":1,"active":1,"agent":"iguana","method":"addcoin","newcoin":"BTC","services":128,"maxpeers":512,"portp2p":8333};
AddCoinData.BTCD = {'userpass':tmpIguanaRPCAuth,"RELAY":mode,"VALIDATE":mode,"prefetchlag":-1,"poll":50,"active":1,"agent":"iguana","method":"addcoin","newcoin":"BTCD","startpend":tmpPendValue,"endpend":tmpPendValue,"services":129,"maxpeers":64,"portp2p":14631,"rpc":14632};
AddCoinData.LTC = {'userpass':tmpIguanaRPCAuth,"RELAY":mode,"VALIDATE":mode,"prefetchlag":-1,"poll":10,"active":1,"agent":"iguana","method":"addcoin","startpend":tmpPendValue,"endpend":tmpPendValue,"services":129,"maxpeers":256,"newcoin":"LTC","name":"Litecoin","hasheaders":1,"useaddmultisig":0,"netmagic":"fbc0b6db","p2p":9333,"rpc":9332,"pubval":48,"p2shval":5,"wifval":176,"txfee_satoshis":"100000","isPoS":0,"minoutput":10000,"minconfirms":2,"genesishash":"12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2","genesis":{"hashalgo":"scrypt","version":1,"timestamp":1317972665,"nBits":"1e0ffff0","nonce":2084524493,"merkle_root":"97ddfbbae6be97fd6cdf3e7ca13232a3afff2353e29badfab7f73011edd4ced9"},"alertpubkey":"040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9","protover":70002};
AddCoinData.DOGE = {'userpass':tmpIguanaRPCAuth,"RELAY":mode,"VALIDATE":mode,"startpend":tmpPendValue,"endpend":tmpPendValue,"services":129,"auxpow":1,"prefetchlag":-1,"poll":10,"active":1,"agent":"iguana","method":"addcoin","maxpeers":256,"newcoin":"DOGE","name":"Dogecoin","netmagic":"C0C0C0C0","p2p":22556,"rpc":22555,"pubval":30,"p2shval":5,"wifval":128,"txfee_satoshis":"100000000","minconfirms":2,"genesishash":"1a91e3dace36e2be3bf030a65679fe821aa1d6ef92e7c9902eb318182c355691","genesis":{"hashalgo": "scrypt","version":1,"timestamp":1386325540,"nBits":"1e0ffff0","nonce":99943,"merkle_root":"5b2a3f53f605d62c53e62932dac6925e3d74afa5a4b459745c36d42d0ed26a69"},"alertpubkey":"04d4da7a5dae4db797d9b0644d57a5cd50e05a70f36091cd62e2fc41c98ded06340be5a43a35e185690cd9cde5d72da8f6d065b499b06f51dcfba14aad859f443a"};
AddCoinData.DGB = {'userpass':tmpIguanaRPCAuth,"RELAY":mode,"VALIDATE":mode,"startpend":tmpPendValue,"endpend":tmpPendValue,"services":129,"prefetchlag":-1,"poll":10,"active":1,"agent":"iguana","method":"addcoin","maxpeers":256,"newcoin":"DGB","name":"Digibyte","netmagic":"FAC3B6DA","p2p":12024,"rpc":14022,"pubval":30,"p2shval":5,"wifval":128,"txfee_satoshis":"10000","minconfirms":2,"genesishash":"7497ea1b465eb39f1c8f507bc877078fe016d6fcb6dfad3a64c98dcc6e1e8496","genesis":{"version":1,"timestamp":1389388394,"nBits":"1e0ffff0","nonce":2447652,"merkle_root":"72ddd9496b004221ed0557358846d9248ecd4c440ebd28ed901efc18757d0fad"},"alertpubkey":"04F04441C4757F356290A37C313C3772C5BC5003E898EB2E0CF365795543A7BF690C8BBBFA32EE3A3325477CE2000B7D0453EFBB203329D0F9DF34D5927D022BC9"};
@ -174,7 +176,7 @@ export function startCrypto(confpath, coin, mode) {
}
export function startCurrencyAssetChain(confpath, coin, mode) {
var AddCoinDataPayload = {},
let AddCoinDataPayload = {},
tmpPendValue = 1,
tmpIguanaRPCAuth = `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`;
@ -184,7 +186,7 @@ export function startCurrencyAssetChain(confpath, coin, mode) {
tmpPendValue = parseInt(tmpPendValue) * 4;
}
var _payloadVar = {
let _payloadVar = {
'userpass': tmpIguanaRPCAuth,
'unitval': '20',
'zcash': 1,
@ -221,7 +223,7 @@ export function startCurrencyAssetChain(confpath, coin, mode) {
};
if (mode === '-1') {
var _payloadVarRegular = Object.assign({}, _payloadVar);
let _payloadVarRegular = Object.assign({}, _payloadVar);
delete _payloadVarRegular.userpass;
_payloadVarRegular.RELAY = -1;
_payloadVarRegular.VALIDATE = 1;
@ -639,8 +641,8 @@ export function startCurrencyAssetChain(confpath, coin, mode) {
}
export function startAssetChain(confpath, coin, mode, getSuppyOnly) {
var tmpIguanaRPCAuth = `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`;
var tmpPendValue;
let tmpIguanaRPCAuth = `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`;
let tmpPendValue;
if (coin !== 'BTC' &&
coin !== 'LTC' &&

23
react/src/components/dashboard/about/about.js

@ -11,30 +11,35 @@ class About extends React.Component {
<ul>
<li>
<span className="font-weight-600">Basilisk Mode</span>: Doesn't download the blockchain. Slightly slower
<span className="font-weight-600">Basilisk Mode</span>:&nbsp;
Doesn't download the blockchain. Slightly slower
transaction performance.
</li>
<li>
<span className="font-weight-600">Full Mode</span>: Downloads the full blockchain, which can take a
<span className="font-weight-600">Full Mode</span>:&nbsp;
Downloads the full blockchain, which can take a
while. Good transaction performance.
</li>
<li>
<span className="font-weight-600">Native Mode</span>: Only available for a few currencies. Like 'Full
<span className="font-weight-600">Native Mode</span>:&nbsp;
Only available for a few currencies. Like 'Full
Mode' but provides advanced functionality.
</li>
</ul>
Agama includes the following capabilities:
Agama includes the following capabilities:
<ul>
<li>
<span className="font-weight-600">InstantDEX</span>: Easily exchange cryptocurrencies via a
<span className="font-weight-600">BarterDEX</span>:&nbsp;
Easily exchange cryptocurrencies via a
shapeshift-like service.
<a href="https://supernet.org/en/technology/whitepapers/easydex-a-practical-native-dex" target="_blank">
(EasyDEX A Practical Native DEX)
(BarterDEX A Practical Native DEX)
</a>
</li>
<li>
<span className="font-weight-600">Atomic Exporer</span>: A universal local explorer ensures you don't
<span className="font-weight-600">Atomic Exporer</span>:&nbsp;
A universal local explorer ensures you don't
have query information from a centralized
server.
</li>
@ -47,7 +52,7 @@ class About extends React.Component {
<br/>
<span className="font-weight-600">Testers</span>:
<span className="font-weight-600">Testers</span>:&nbsp;
You can help us test Agama. Just <a target="_blank" href="https://supernet.org/en/products/agama-wallet">download and install the latest release</a>.
Then, report any bugs you encounter to our developers on the #testing-agama Slack channel.
Your help is greatly appreciated!
@ -59,7 +64,7 @@ class About extends React.Component {
and lower fees.
</li>
<li>
<span className="font-weight-600">NativeDEX</span>
<span className="font-weight-600">BarterDEX</span>
</li>
</ul>
</p>

130
react/src/components/dashboard/atomic/atomic.js

@ -6,7 +6,8 @@ import AtomicRender from './atomic.render';
/*
TODO:
pre-select active coin
1) pre-select active coin
2) validation
*/
class Atomic extends React.Component {
constructor(props) {
@ -44,6 +45,8 @@ class Atomic extends React.Component {
getAtomicData() {
const tmpIguanaRPCAuth = `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`;
let ExplorerInputData;
const _coin = this.state.coin;
const _input = this.state.input;
switch (this.state.api) {
case 'history':
@ -53,70 +56,70 @@ class Atomic extends React.Component {
'agent': 'basilisk',
'method': 'history',
'vals': {
'coin': this.state.coin,
'addresses': [ this.state.input ]
'coin': _coin,
'addresses': [ _input ],
}
};
break;
case 'getbalance':
ExplorerInputData = {
'userpass': tmpIguanaRPCAuth,
'coin': this.state.coin,
'coin': _coin,
'method': 'getbalance',
'params': [ this.state.input ]
'params': [ _input ],
};
break;
case 'listunspent':
ExplorerInputData = {
'userpass': tmpIguanaRPCAuth,
'coin': this.state.coin,
'coin': _coin,
'method': 'listunspent',
'params': [
1,
9999999,
[ this.state.input ]
[ _input ],
]
};
break;
case 'txid':
ExplorerInputData = {
'userpass': tmpIguanaRPCAuth,
'coin': this.state.coin,
'coin': _coin,
'method': 'getrawtransaction',
'params': [ this.state.input ]
'params': [ _input ],
};
break;
case 'blockash':
ExplorerInputData = {
'userpass': tmpIguanaRPCAuth,
'coin': this.state.coin,
'coin': _coin,
'agent': 'bitcoinrpc',
'method': 'getblockhash',
'height': this.state.input
'height': _input,
};
break;
case 'chaintip':
ExplorerInputData = {
'userpass': tmpIguanaRPCAuth,
'coin': this.state.coin,
'coin': _coin,
'agent': 'bitcoinrpc',
'method': 'getbestblockhash'
'method': 'getbestblockhash',
};
break;
case 'activehandle':
ExplorerInputData = {
'userpass': tmpIguanaRPCAuth,
'agent': 'SuperNET',
'method': 'activehandle'
'method': 'activehandle',
};
break;
case 'gettransaction':
ExplorerInputData = {
'userpass': tmpIguanaRPCAuth,
'coin': this.state.coin,
'coin': _coin,
'agent': 'bitcoinrpc',
'method': 'gettransaction',
'txid': this.state.input
'txid': _input,
};
break;
case 'dex_getinfo':
@ -124,7 +127,7 @@ class Atomic extends React.Component {
'userpass': tmpIguanaRPCAuth,
'agent': 'dex',
'method': 'getinfo',
'symbol': this.state.coin
'symbol': _coin,
};
break;
case 'dex_getnotaries':
@ -132,7 +135,7 @@ class Atomic extends React.Component {
'userpass': tmpIguanaRPCAuth,
'agent': 'dex',
'method': 'getnotaries',
'symbol': this.state.coin
'symbol': _coin,
};
break;
case 'dex_alladdresses':
@ -140,7 +143,7 @@ class Atomic extends React.Component {
'userpass': tmpIguanaRPCAuth,
'agent': 'dex',
'method': 'alladdresses',
'symbol': this.state.coin
'symbol': _coin,
};
break;
case 'dex_importaddress':
@ -148,8 +151,8 @@ class Atomic extends React.Component {
'userpass': tmpIguanaRPCAuth,
'agent': 'dex',
'method': 'importaddress',
'address': this.state.input,
'symbol': this.state.coin
'address': _input,
'symbol': _coin,
};
break;
case 'dex_checkaddress':
@ -157,8 +160,8 @@ class Atomic extends React.Component {
'userpass': tmpIguanaRPCAuth,
'agent': 'dex',
'method': 'checkaddress',
'ddress': this.state.input,
'symbol': this.state.coin
'ddress': _input,
'symbol': _coin,
};
break;
case 'dex_validateaddress':
@ -166,8 +169,8 @@ class Atomic extends React.Component {
'userpass': tmpIguanaRPCAuth,
'agent': 'dex',
'method': 'validateaddress',
'address': this.state.input,
'symbol': this.state.coin
'address': _input,
'symbol': _coin,
};
break;
case 'dex_getbestblockhash':
@ -175,7 +178,7 @@ class Atomic extends React.Component {
'userpass': tmpIguanaRPCAuth,
'agent': 'dex',
'method': 'getbestblockhash',
'symbol': this.state.coin
'symbol': _coin,
};
break;
case 'dex_listtransactions':
@ -183,10 +186,10 @@ class Atomic extends React.Component {
'userpass': tmpIguanaRPCAuth,
'agent': 'dex',
'method': 'listtransactions',
'address': this.state.input,
'address': _input,
'count': 100,
'skip': 0,
'symbol': this.state.coin
'symbol': _coin,
};
break;
case 'dex_listtransactions2':
@ -194,10 +197,10 @@ class Atomic extends React.Component {
'userpass': tmpIguanaRPCAuth,
'agent': 'dex',
'method': 'listtransactions2',
'address': this.state.input,
'address': _input,
'count': 100,
'skip': 0,
'symbol': this.state.coin
'symbol': _coin,
};
break;
case 'dex_listunspent':
@ -205,8 +208,8 @@ class Atomic extends React.Component {
'userpass': tmpIguanaRPCAuth,
'agent': 'dex',
'method': 'listunspent',
'address': this.state.input,
'symbol': this.state.coin
'address': _input,
'symbol': _coin,
};
break;
case 'dex_listspent':
@ -214,8 +217,8 @@ class Atomic extends React.Component {
'userpass': tmpIguanaRPCAuth,
'agent': 'dex',
'method': 'listspent',
'address': this.state.input,
'symbol': this.state.coin
'address': _input,
'symbol': _coin,
};
break;
case 'dex_listunspent2':
@ -223,8 +226,8 @@ class Atomic extends React.Component {
'userpass': tmpIguanaRPCAuth,
'agent': 'dex',
'method': 'listunspent2',
'address': this.state.input,
'symbol': this.state.coin
'address': _input,
'symbol': _coin,
};
break;
case 'dex_getblockhash':
@ -233,7 +236,7 @@ class Atomic extends React.Component {
'agent': 'dex',
'method': 'getblockhash',
'height': 100,
'symbol': this.state.coin
'symbol': _coin,
};
break;
case 'dex_getblock':
@ -241,8 +244,8 @@ class Atomic extends React.Component {
'userpass': tmpIguanaRPCAuth,
'agent': 'dex',
'method': 'getblock',
'hash': this.state.input,
'symbol': this.state.coin
'hash': _input,
'symbol': _coin,
};
break;
case 'dex_gettxin':
@ -251,8 +254,8 @@ class Atomic extends React.Component {
'agent': 'dex',
'method': 'gettxin',
'vout': 0,
'txid': this.state.input,
'symbol': this.state.coin
'txid': _input,
'symbol': _coin,
};
break;
case 'dex_gettxout':
@ -261,8 +264,8 @@ class Atomic extends React.Component {
'agent': 'dex',
'method': 'gettxout',
'vout': 0,
'txid': this.state.input,
'symbol': this.state.coin
'txid': _input,
'symbol': _coin,
};
break;
case 'dex_gettransaction':
@ -270,8 +273,8 @@ class Atomic extends React.Component {
'userpass': tmpIguanaRPCAuth,
'agent': 'dex',
'method': 'gettransaction',
'txid': this.state.input,
'symbol': this.state.coin
'txid': _input,
'symbol': _coin,
};
break;
case 'dex_getbalance':
@ -279,8 +282,8 @@ class Atomic extends React.Component {
'userpass': tmpIguanaRPCAuth,
'agent': 'dex',
'method': 'getbalance',
'address': this.state.input,
'symbol': this.state.coin
'address': _input,
'symbol': _coin,
};
break;
case 'dex_getsupply':
@ -289,8 +292,8 @@ class Atomic extends React.Component {
'agent': 'dex',
'method': 'getbalance',
'address': '*',
'symbol': this.state.coin,
'timeout': 600000
'symbol': _coin,
'timeout': 600000,
};
break;
case 'dex_sendrawtransaction':
@ -298,8 +301,8 @@ class Atomic extends React.Component {
'userpass': tmpIguanaRPCAuth,
'agent': 'dex',
'method': 'sendrawtransaction',
'signedtx': this.state.input,
'symbol': this.state.coin
'signedtx': _input,
'symbol': _coin,
};
break;
case 'basilisk_refresh':
@ -307,16 +310,16 @@ class Atomic extends React.Component {
'userpass': tmpIguanaRPCAuth,
'agent': 'basilisk',
'method': 'refresh',
'address': this.state.input,
'symbol': this.state.coin,
'timeout': 600000
'address': _input,
'symbol': _coin,
'timeout': 600000,
};
break;
case 'jumblr_status':
ExplorerInputData = {
'userpass': tmpIguanaRPCAuth,
'agent': 'jumblr',
'method': 'status'
'method': 'status',
};
break;
}
@ -326,20 +329,23 @@ class Atomic extends React.Component {
componentWillReceiveProps(props) {
if (props && props.Atomic.response) {
if (this.state.api === 'txid' ||
this.state.api === 'dex_getbestblockhash' ||
this.state.api === 'dex_sendrawtransaction' ||
this.state.api === 'dex_getblockhash') {
const _api = this.state.api;
const _propsAtomicRes = props.Atomic.response;
if (_api === 'txid' ||
_api === 'dex_getbestblockhash' ||
_api === 'dex_sendrawtransaction' ||
_api === 'dex_getblockhash') {
this.setState(Object.assign({}, this.state, {
'output': props.Atomic.response,
'output': _propsAtomicRes,
}));
} else {
this.setState(Object.assign({}, this.state, {
'output': JSON.stringify(props.Atomic.response, null, '\t'),
'output': JSON.stringify(_propsAtomicRes, null, '\t'),
}));
}
if (props.Atomic.response.error === 'less than required responses') {
if (_propsAtomicRes.error === 'less than required responses') {
Store.dispatch(
triggerToaster(
'Basilisk connection error',

24
react/src/components/dashboard/coinTile/coinTileItem.js

@ -43,14 +43,15 @@ class CoinTileItem extends React.Component {
dispatchCoinActions(coin, mode) {
if (mode === 'native') {
Store.dispatch(iguanaActiveHandle(true));
const syncPercentage = this.props.Dashboard && this.props.Dashboard.progress && (parseFloat(parseInt(this.props.Dashboard.progress.blocks, 10) * 100 / parseInt(this.props.Dashboard.progress.longestchain, 10)).toFixed(2)).replace('NaN', 0);
const _propsDashboard = this.props.Dashboard;
const syncPercentage = _propsDashboard && _propsDashboard.progress && (parseFloat(parseInt(_propsDashboard.progress.blocks, 10) * 100 / parseInt(this.props.Dashboard.progress.longestchain, 10)).toFixed(2)).replace('NaN', 0);
if (syncPercentage < 100) {
Store.dispatch(getDebugLog('komodo', 10));
}
if (this.props.Dashboard.progress &&
this.props.Dashboard.progress.blocks &&
this.props.Dashboard.progress.longestchain &&
if (_propsDashboard.progress &&
_propsDashboard.progress.blocks &&
_propsDashboard.progress.longestchain &&
syncPercentage &&
(Config.iguanaLessMode || syncPercentage >= NATIVE_MIN_SYNC_PERCENTAGE_THRESHOLD)) {
Store.dispatch(getSyncInfoNative(coin, true));
@ -73,6 +74,7 @@ class CoinTileItem extends React.Component {
const useAddress = this.props.ActiveCoin.mainBasiliskAddress ? this.props.ActiveCoin.mainBasiliskAddress : this.props.Dashboard.activeHandle[coin];
Store.dispatch(iguanaActiveHandle(true));
Store.dispatch(
getKMDAddressesNative(
coin,
@ -80,6 +82,7 @@ class CoinTileItem extends React.Component {
useAddress
)
);
Store.dispatch(
getShepherdCache(
JSON.parse(sessionStorage.getItem('IguanaActiveAccount')).pubkey,
@ -108,12 +111,14 @@ class CoinTileItem extends React.Component {
this.props.Interval.interval
)
);
Store.dispatch(
stopInterval(
'basilisk',
this.props.Interval.interval
)
);
Store.dispatch(dashboardChangeActiveCoin(coin, mode));
this.dispatchCoinActions(coin, mode);
@ -122,6 +127,7 @@ class CoinTileItem extends React.Component {
const _iguanaActiveHandle = setInterval(() => {
this.dispatchCoinActions(coin, mode);
}, IGUNA_ACTIVE_HANDLE_TIMEOUT);
Store.dispatch(
startInterval(
'sync',
@ -133,15 +139,17 @@ class CoinTileItem extends React.Component {
const _iguanaActiveHandle = setInterval(() => {
this.dispatchCoinActions(coin, mode);
}, coin === 'KMD' ? IGUNA_ACTIVE_HANDLE_TIMEOUT_KMD_NATIVE : IGUNA_ACTIVE_HANDLE_TIMEOUT);
Store.dispatch(startInterval('sync', _iguanaActiveHandle));
}
if (mode === 'basilisk') {
const _basiliskMainAddress = this.props.Dashboard.activeHandle[coin] || JSON.parse(sessionStorage.getItem('IguanaActiveAccount'))[coin];
const _activeHandle = this.props.Dashboard.activeHandle;
const _basiliskMainAddress = _activeHandle[coin] || JSON.parse(sessionStorage.getItem('IguanaActiveAccount'))[coin];
Store.dispatch(changeActiveAddress(_basiliskMainAddress));
if (_basiliskMainAddress) {
Store.dispatch(fetchNewCacheData({
'pubkey': this.props.Dashboard.activeHandle.pubkey,
'pubkey': _activeHandle.pubkey,
'allcoins': false,
'coin': coin,
'calls': 'listtransactions:getbalance',
@ -154,19 +162,21 @@ class CoinTileItem extends React.Component {
const _basiliskCache = setInterval(() => {
Store.dispatch(fetchNewCacheData({
'pubkey': this.props.Dashboard.activeHandle.pubkey,
'pubkey': _activeHandle.pubkey,
'allcoins': false,
'coin': this.props.ActiveCoin.coin,
'calls': 'listtransactions:getbalance',
'address': _basiliskMainAddress,
}));
}, BASILISK_CACHE_UPDATE_TIMEOUT);
Store.dispatch(
startInterval(
'sync',
_iguanaActiveHandle
)
);
Store.dispatch(
startInterval(
'basilisk',

2
react/src/components/dashboard/coinTile/coinTileItem.render.js

@ -5,7 +5,7 @@ const CoinTileItemRender = function() {
return (
<div className="list-group-item col-xlg-6 col-lg-12 wallet-widgets-info pointer">
<div className={ this.props.ActiveCoin.coin === item.coin ? 'widget widget-shadow active' : 'widget widget-shadow' }>
<div className={ 'widget widget-shadow' + (this.props.ActiveCoin.coin === item.coin ? ' active' : '') }>
<div
className="widget-content text-center bg-white padding-20"
onClick={ () => this.dashboardChangeActiveCoin(item.coin, item.mode) }>

1
react/src/components/dashboard/main/dashboard.js

@ -1,5 +1,4 @@
import React from 'react';
import DashboardRender from './dashboard.render';
class Dashboard extends React.Component {

53
react/src/components/dashboard/main/dashboard.scss

@ -2,8 +2,13 @@
height: 100%;
}
.text-align-center {
text-align: center;
.text {
&-align-center {
text-align: center;
}
&-align-left {
text-align: left;
}
}
.margin-top-30 {
@ -22,8 +27,14 @@
}
// navbar.js
.navbar-toolbar > li > a.padding-top-16 {
padding-top: 16px;
.navbar-toolbar {
> li {
> a {
&.padding-top-16 {
padding-top: 16px;
}
}
}
}
// notifications.js
@ -60,17 +71,17 @@
width: 5%;
}
.text-align-left {
text-align: left;
}
// walletsBalance.js
.font-weight-600 {
font-weight: 600;
}
.font-size-22 {
font-size: 22px;
.font {
&-weight-600 {
font-weight: 600;
}
&-size-22 {
font-size: 22px;
}
&-size-80-percent {
font-size: 80%;
}
}
// walletBasiliskConnection.js
@ -86,15 +97,16 @@
padding: 0 !important;
}
.font-size-80-percent {
font-size: 80%;
}
// walletsData.js
.z-index-10 {
z-index: 10;
}
// walletsHeader.js
.z-index-1 {
z-index: 1;
}
.full-width {
width: 100%;
}
@ -103,11 +115,6 @@
padding: 20px 0 10px 0;
}
// walletsHeader.js
.z-index-1 {
z-index: 1;
}
// walletsNative.js
.background-color-white {
background-color: #fff;

1
react/src/components/dashboard/notifications/notifications.js

@ -42,7 +42,6 @@ class Notifications extends React.Component {
success: 0,
pending: 0,
}
let guiLogToArray = [];
for (let timestamp in _guiLog) {

32
react/src/components/dashboard/receiveCoin/receiveCoin.js

@ -13,7 +13,7 @@ import {
ReceiveCoinRender
} from './receiveCoin.render';
// TODO: implement sorting
// TODO: implement balance/interest sorting
// TODO: fallback to localstorage/stores data in case iguana is taking too long to respond
class ReceiveCoin extends React.Component {
@ -109,25 +109,29 @@ class ReceiveCoin extends React.Component {
}
renderAddressList(type) {
if (this.props.addresses &&
this.props.addresses[type] &&
this.props.addresses[type].length) {
const _addresses = this.props.addresses;
const _cache = this.props.cache;
const _coin = this.props.coin;
if (_addresses &&
_addresses[type] &&
_addresses[type].length) {
let items = [];
for (let i = 0; i < this.props.addresses[type].length; i++) {
let address = this.props.addresses[type][i];
for (let i = 0; i < _addresses[type].length; i++) {
let address = _addresses[type][i];
if (this.isBasiliskMode() &&
this.hasNoAmount(address)) {
address.amount = this.props.cache && this.props.cache[this.props.coin][address.address]
&& this.props.cache[this.props.coin][address.address].getbalance.data
&& this.props.cache[this.props.coin][address.address].getbalance.data.balance ? this.props.cache[this.props.coin][address.address].getbalance.data.balance : 'N/A';
this.hasNoAmount(address)) {
address.amount = _cache && _cache[_coin][address.address]
&& _cache[_coin][address.address].getbalance.data
&& _cache[_coin][address.address].getbalance.data.balance ? _cache[_coin][address.address].getbalance.data.balance : 'N/A';
}
if (this.isBasiliskMode() &&
this.hasNoInterest(address)) {
address.interest = this.props.cache && this.props.cache[this.props.coin][address.address]
&& this.props.cache[this.props.coin][address.address].getbalance.data
&& this.props.cache[this.props.coin][address.address].getbalance.data.interest ? this.props.cache[this.props.coin][address.address].getbalance.data.interest : 'N/A';
this.hasNoInterest(address)) {
address.interest = _cache && _cache[_coin][address.address]
&& _cache[_coin][address.address].getbalance.data
&& _cache[_coin][address.address].getbalance.data.interest ? _cache[_coin][address.address].getbalance.data.interest : 'N/A';
}
items.push(

6
react/src/components/dashboard/receiveCoin/receiveCoin.render.js

@ -49,7 +49,7 @@ export const AddressItemRender = function(address, type) {
return (
<tr key={ address.address }>
{ this.renderAddressActions(address.address, type) }
<td>{ type === 'public' ? address.address : address.address.substring(0, 34) + '...' }</td>
<td>{ type === 'public' ? address.address : `${address.address.substring(0, 34)}...` }</td>
<td>{ address.amount }</td>
{!this.isNativeMode() &&
<td>{ address.interest ? address.interest : 'N/A' }</td>
@ -112,8 +112,8 @@ export const ReceiveCoinRender = function() {
}
</thead>
<tbody>
{ this.renderAddressList('public') }
{ this.isNativeMode() && this.renderAddressList('private') }
{ this.renderAddressList('public') }
{ this.isNativeMode() && this.renderAddressList('private') }
</tbody>
<tfoot>
{ this.isNativeMode() ?

124
react/src/components/dashboard/sendCoin/sendCoin.js

@ -103,7 +103,6 @@ class SendCoin extends React.Component {
}
updateSocketsData(data) {
console.log('sockets', data);
if (data &&
data.message &&
data.message.shepherd.iguanaAPI &&
@ -149,20 +148,23 @@ class SendCoin extends React.Component {
timestamp,
isReadyToUpdate,
waitUntilCallIsFinished = this.state.currentStackLength > 1 ? true : false;
const _cache = this.props.ActiveCoin.cache;
const _coin = this.props.ActiveCoin.coin;
const _sendFrom = this.state.sendFrom;
if (this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].refresh ||
this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].listunspent) {
refreshCacheData = this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].refresh || this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].listunspent;
if (_cache[_coin][_sendFrom].refresh ||
_cache[_coin][_sendFrom].listunspent) {
refreshCacheData = _cache[_coin][_sendFrom].refresh || _cache[_coin][_sendFrom].listunspent;
timestamp = checkTimestamp(refreshCacheData.timestamp);
isReadyToUpdate = timestamp > 600 ? true : false;
} else {
isReadyToUpdate = true;
}
if (this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].refresh &&
this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].refresh.data &&
this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].refresh.data.error &&
this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].refresh.data.error === 'request failed') {
if (_cache[_coin][_sendFrom].refresh &&
_cache[_coin][_sendFrom].refresh.data &&
_cache[_coin][_sendFrom].refresh.data.error &&
_cache[_coin][_sendFrom].refresh.data.error === 'request failed') {
timestamp = null;
}
@ -179,13 +181,15 @@ class SendCoin extends React.Component {
}
renderAddressAmount(address) {
if (this.props.ActiveCoin.addresses &&
this.props.ActiveCoin.addresses.public &&
this.props.ActiveCoin.addresses.public.length) {
for (let i = 0; i < this.props.ActiveCoin.addresses.public.length; i++) {
if (this.props.ActiveCoin.addresses.public[i].address === address) {
if (this.props.ActiveCoin.addresses.public[i].amount !== 'N/A') {
return this.props.ActiveCoin.addresses.public[i].amount;
const _addresses = this.props.ActiveCoin.addresses;
if (_addresses &&
_addresses.public &&
_addresses.public.length) {
for (let i = 0; i < _addresses.public.length; i++) {
if (_addresses.public[i].address === address) {
if (_addresses.public[i].amount !== 'N/A') {
return _addresses.public[i].amount;
}
}
}
@ -195,9 +199,11 @@ class SendCoin extends React.Component {
}
renderAddressByType(type) {
if (this.props.ActiveCoin.addresses &&
this.props.ActiveCoin.addresses[type] &&
this.props.ActiveCoin.addresses[type].length) {
const _addresses = this.props.ActiveCoin.addresses;
if (_addresses &&
_addresses[type] &&
_addresses[type].length) {
if (this.state.sendApiType) {
const mainAddress = this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin];
const mainAddressAmount = this.renderAddressAmount(mainAddress);
@ -206,27 +212,41 @@ class SendCoin extends React.Component {
<li
key={ mainAddress }
className={ mainAddressAmount <= 0 ? 'hide' : '' }>
<a onClick={ () => this.updateAddressSelection(mainAddress, type, mainAddressAmount) }><i className={ type === 'public' ? 'icon fa-eye' : 'icon fa-eye-slash' }></i> <span className="text">[ { mainAddressAmount } { this.props.ActiveCoin.coin } ] { mainAddress }</span><span className="glyphicon glyphicon-ok check-mark"></span></a>
<a onClick={ () => this.updateAddressSelection(mainAddress, type, mainAddressAmount) }>
<i className={ type === 'public' ? 'icon fa-eye' : 'icon fa-eye-slash' }></i>&nbsp;&nbsp;
<span className="text">
[ { mainAddressAmount } { this.props.ActiveCoin.coin } ]&nbsp;&nbsp;
{ mainAddress }
</span>
<span className="glyphicon glyphicon-ok check-mark"></span>
</a>
</li>
);
} else {
let items = [];
const _addresses = this.props.ActiveCoin.addresses;
const _cache = this.props.ActiveCoin.cache;
const _coin = this.props.ActiveCoin.coin;
for (let i = 0; i < this.props.ActiveCoin.addresses[type].length; i++) {
const address = this.props.ActiveCoin.addresses[type][i];
for (let i = 0; i < _addresses[type].length; i++) {
const address = _addresses[type][i].address;
let _amount = address.amount;
if (this.props.ActiveCoin.mode === 'basilisk' &&
this.props.ActiveCoin.cache) {
_amount = this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][address.address] && this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][address.address].getbalance.data && this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][address.address].getbalance.data.balance ? this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][address.address].getbalance.data.balance : 'N/A';
_cache) {
_amount = _cache[_coin][address] && _cache[_coin][address].getbalance.data && _cache[_coin][address].getbalance.data.balance ? _cache[_coin][address].getbalance.data.balance : 'N/A';
}
if (_amount !== 'N/A') {
items.push(
<li
key={ address.address }
key={ address }
className={ _amount <= 0 ? 'hide' : '' }>
<a onClick={ () => this.updateAddressSelection(address.address, type, _amount) }><i className={ type === 'public' ? 'icon fa-eye' : 'icon fa-eye-slash' }></i> <span className="text">[ { _amount } { this.props.ActiveCoin.coin } ] { address.address }</span><span className="glyphicon glyphicon-ok check-mark"></span></a>
<a onClick={ () => this.updateAddressSelection(address, type, _amount) }>
<i className={ type === 'public' ? 'icon fa-eye' : 'icon fa-eye-slash' }></i>&nbsp;&nbsp;
<span className="text">[ { _amount } { _coin } ]{ address }</span>
<span className="glyphicon glyphicon-ok check-mark"></span>
</a>
</li>
);
}
@ -242,18 +262,22 @@ class SendCoin extends React.Component {
renderSelectorCurrentLabel() {
if (this.state.sendFrom) {
let _amount;
const _cache = this.props.ActiveCoin.cache;
const _coin = this.props.ActiveCoin.coin;
const _sendFrom = this.state.sendFrom;
if (this.state.sendFromAmount === 0 &&
this.props.ActiveCoin.mode === 'basilisk' &&
this.props.ActiveCoin.cache) {
_amount = this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].getbalance.data && this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].getbalance.data.balance ? this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].getbalance.data.balance : 'N/A';
_cache) {
_amount = _cache[_coin][_sendFrom].getbalance.data && _cache[_coin][_sendFrom].getbalance.data.balance ? _cache[_coin][_sendFrom].getbalance.data.balance : 'N/A';
} else {
_amount = this.state.sendFromAmount;
}
return (
<span>
<i className={ this.state.addressType === 'public' ? 'icon fa-eye' : 'icon fa-eye-slash' }></i> <span className="text">[ { _amount } { this.props.ActiveCoin.coin } ] { this.state.sendFrom }</span>
<i className={ this.state.addressType === 'public' ? 'icon fa-eye' : 'icon fa-eye-slash' }></i>&nbsp;&nbsp;
<span className="text">[ { _amount } { _coin } ]{ _sendFrom }</span>
</span>
);
} else if (this.state.sendApiType) {
@ -262,7 +286,8 @@ class SendCoin extends React.Component {
return (
<span>
<i className={ this.state.addressType === 'public' ? 'icon fa-eye' : 'icon fa-eye-slash' }></i> <span className="text">[ { mainAddressAmount } { this.props.ActiveCoin.coin } ] { mainAddress }</span>
<i className={ this.state.addressType === 'public' ? 'icon fa-eye' : 'icon fa-eye-slash' }></i>&nbsp;&nbsp;
<span className="text">[ { mainAddressAmount } { this.props.ActiveCoin.coin } ]{ mainAddress }</span>
</span>
);
} else {
@ -278,7 +303,7 @@ class SendCoin extends React.Component {
<button
type="button"
className="btn dropdown-toggle btn-info"
title={ '-' + translate('SEND.SELECT_T_OR_Z_ADDR') + '-' }
title={ `-${translate('SEND.SELECT_T_OR_Z_ADDR')}-` }
onClick={ this.openDropMenu }>
<span className="filter-option pull-left">
{ this.renderSelectorCurrentLabel() }&nbsp;&nbsp;
@ -290,7 +315,10 @@ class SendCoin extends React.Component {
<div className="dropdown-menu open">
<ul className="dropdown-menu inner">
<li className="selected">
<a><span className="text"> - { translate('SEND.SELECT_T_OR_Z_ADDR') } - </span><span className="glyphicon glyphicon-ok check-mark"></span></a>
<a>
<span className="text"> - { translate('SEND.SELECT_T_OR_Z_ADDR') } - </span>
<span className="glyphicon glyphicon-ok check-mark"></span>
</a>
</li>
{ this.renderAddressByType('public') }
</ul>
@ -307,10 +335,12 @@ class SendCoin extends React.Component {
updateAddressSelection(address, type, amount) {
let _sendFromAmount = amount ? amount : this.props.ActiveCoin.addresses[type][address].amount;
const _cache = this.props.ActiveCoin.cache;
const _coin = this.props.ActiveCoin.coin;
if (this.props.ActiveCoin.mode === 'basilisk' &&
this.props.ActiveCoin.cache) {
_sendFromAmount = this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][address].getbalance.data && this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][address].getbalance.data.balance ? this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][address].getbalance.data.balance : 'N/A';
_sendFromAmount = _cache[_coin][address].getbalance.data && _cache[_coin][address].getbalance.data.balance ? _cache[_coin][address].getbalance.data.balance : 'N/A';
}
this.setState(Object.assign({}, this.state, {
@ -403,6 +433,7 @@ class SendCoin extends React.Component {
'utxos': utxoSet
};
// TODO: es arrows
iguanaUTXORawTX(sendData, Store.dispatch)
.then(function(json) {
if (json.result === 'success' &&
@ -559,7 +590,7 @@ class SendCoin extends React.Component {
Store.dispatch(sendToAddressStateAlt(json));
Store.dispatch(
triggerToaster(
translate('TOASTR.SIGNED_TX_GENERATED_FAIL') + '.',
`${translate('TOASTR.SIGNED_TX_GENERATED_FAIL')}.`,
translate('TOASTR.WALLET_NOTIFICATION'),
'error'
)
@ -602,17 +633,19 @@ class SendCoin extends React.Component {
} else if (key === 'rawtx') {
return this.renderSignedTx(true);
} else if (key === 'complete' || key === 'completed' || key === 'result') {
if (this.props.ActiveCoin.lastSendToResponse[key] === true ||
this.props.ActiveCoin.lastSendToResponse[key] === 'success') {
const _lastSendToResponse = this.props.ActiveCoin.lastSendToResponse;
if (_lastSendToResponse[key] === true ||
_lastSendToResponse[key] === 'success') {
return (
<span className="label label-success">{ this.props.ActiveCoin.lastSendToResponse[key] === true ? 'true' : 'success' }</span>
<span className="label label-success">{ _lastSendToResponse[key] === true ? 'true' : 'success' }</span>
);
} else {
if (key === 'result' &&
this.props.ActiveCoin.lastSendToResponse.result &&
typeof this.props.ActiveCoin.lastSendToResponse.result !== 'object') {
_lastSendToResponse.result &&
typeof _lastSendToResponse.result !== 'object') {
return (
<span>{ this.props.ActiveCoin.lastSendToResponse.result }</span>
<span>{ _lastSendToResponse.result }</span>
);
} else {
return (
@ -621,17 +654,19 @@ class SendCoin extends React.Component {
}
}
} else if (key === 'error') {
if (Object.keys(this.props.ActiveCoin.lastSendToResponse[key]).length) {
const _lastSendToResponse = this.props.ActiveCoin.lastSendToResponse;
if (Object.keys(_lastSendToResponse[key]).length) {
return (
<span>{ JSON.stringify(this.props.ActiveCoin.lastSendToResponse[key], null, '\t') }</span>
<span>{ JSON.stringify(_lastSendToResponse[key], null, '\t') }</span>
);
} else {
return (
<span className="label label-danger">{ this.props.ActiveCoin.lastSendToResponse[key] }</span>
<span className="label label-danger">{ _lastSendToResponse[key] }</span>
);
}
} else if (key === 'sendrawtransaction') {
if (this.props.ActiveCoin.lastSendToResponse[key] === 'success') {
if (_lastSendToResponse[key] === 'success') {
return (
<span className="label label-success">true</span>
);
@ -642,7 +677,7 @@ class SendCoin extends React.Component {
}
} else if (key === 'txid' || key === 'sent') {
return (
<span>{ this.props.ActiveCoin.lastSendToResponse[key] }</span>
<span>{ _lastSendToResponse[key] }</span>
);
} else if (key === 'tag') {
return null;
@ -653,6 +688,7 @@ class SendCoin extends React.Component {
return SendCoinResponseRender.call(this);
}
// experimental, ask @kolo for details if required
getOAdress() {
resolveOpenAliasAddress(this.state.sendToOA)
.then(function(json) {

19
react/src/components/dashboard/sendCoin/sendCoin.render.js

@ -13,7 +13,9 @@ export const UTXOCacheInfoRender = function(refreshCacheData, isReadyToUpdate, w
{ refreshCacheData ? refreshCacheData.data && refreshCacheData.data.length : translate('SEND.PRESS_UPDATE_BTN') }<br />
<div className={ !timestamp ? 'hide' : '' }>
{ translate('SEND.LAST_UPDATED') } @
{ secondsToString(refreshCacheData ? refreshCacheData.timestamp : 0, true) } | { secondsElapsedToString(timestamp || 0) } { translate('SEND.AGO') }<br />
{ secondsToString(refreshCacheData ? refreshCacheData.timestamp : 0, true) }&nbsp;|&nbsp;
{ secondsElapsedToString(timestamp || 0) }&nbps;
{ translate('SEND.AGO') }<br />
</div>
<div className={ isReadyToUpdate ? 'hide' : '' }>
{ translate('SEND.NEXT_UPDATE_IN') } { secondsElapsedToString(600 - timestamp) }s
@ -21,7 +23,7 @@ export const UTXOCacheInfoRender = function(refreshCacheData, isReadyToUpdate, w
<div className={ 'full-width margin-bottom-10 margin-top-10 ' + (this.state.currentStackLength === 1 || (this.state.currentStackLength === 0 && this.state.totalStackLength === 0) ? 'hide' : 'progress progress-sm') }>
<div
className="progress-bar progress-bar-striped active progress-bar-indicating progress-bar-success font-size-80-percent"
style={{ width: 100 - (this.state.currentStackLength * 100 / this.state.totalStackLength) + '%' }}>
style={{ width: 100 - `${(this.state.currentStackLength * 100 / this.state.totalStackLength)}%` }}>
{ translate('SEND.PROCESSING_REQ') }: { this.state.currentStackLength } / { this.state.totalStackLength }
</div>
</div>
@ -30,7 +32,7 @@ export const UTXOCacheInfoRender = function(refreshCacheData, isReadyToUpdate, w
className={ 'margin-top-10 ' + (isReadyToUpdate ? 'btn btn-primary waves-effect waves-light' : 'hide') }
onClick={ this._fetchNewUTXOData }
disabled={ waitUntilCallIsFinished }>
{ waitUntilCallIsFinished ? translate('SEND.LOCKED_PLEASE_WAIT') + '...' : translate('SEND.UPDATE') }
{ waitUntilCallIsFinished ? `${translate('SEND.LOCKED_PLEASE_WAIT')}...` : translate('SEND.UPDATE') }
</button>
</div>
);
@ -257,7 +259,11 @@ export const SendCoinRender = function () {
onChange={ this.updateInput } />
</div>
<div className="col-lg-12">
<strong>{ translate('INDEX.TOTAL') } ({ translate('INDEX.AMOUNT_SM') } - txfee):</strong> { Number(this.state.amount) - Number(this.state.fee) } { this.props.ActiveCoin.coin }
<strong>
{ translate('INDEX.TOTAL') }&nbsp;
({ translate('INDEX.AMOUNT_SM') } - txfee):
</strong>&nbsp;
{ Number(this.state.amount) - Number(this.state.fee) } { this.props.ActiveCoin.coin }
</div>
<div className={ this.state.sendApiType ? 'hide' : 'col-lg-10 margin-top-30' }>
<span className="pointer">
@ -283,7 +289,8 @@ export const SendCoinRender = function () {
className="btn btn-primary waves-effect waves-light pull-right"
onClick={ () => this.changeSendCoinStep(1) }
disabled={ !this.state.sendFrom || !this.state.sendTo || !this.state.amount }>
{ translate('INDEX.SEND') } { Number(this.state.amount) - Number(this.state.fee) } { this.props.ActiveCoin.coin }
{ translate('INDEX.SEND') }&nbsp;
{ Number(this.state.amount) - Number(this.state.fee) } { this.props.ActiveCoin.coin }
</button>
</div>
</div>
@ -365,7 +372,7 @@ export const SendCoinRender = function () {
className="btn btn-primary"
onClick={ () => this.changeSendCoinStep(0) }
disabled={ this.state.utxoMethodInProgress }>
{ !this.state.utxoMethodInProgress ? translate('INDEX.MAKE_ANOTHER_TX') : translate('SEND.PLEASE_WAIT') + '...' }
{ !this.state.utxoMethodInProgress ? translate('INDEX.MAKE_ANOTHER_TX') : `${translate('SEND.PLEASE_WAIT')}...` }
</button>
</div>
</div>

39
react/src/components/dashboard/settings/settings.js

@ -59,6 +59,8 @@ class Settings extends React.Component {
updateBins: null,
updateLog: [],
updateProgressPatch: null,
wifkeysPassphrase: '',
trimPassphraseTimer: null,
};
this.exportWifKeys = this.exportWifKeys.bind(this);
this.updateInput = this.updateInput.bind(this);
@ -95,6 +97,16 @@ class Settings extends React.Component {
}
}
resizeLoginTextarea() {
// auto-size textarea
setTimeout(() => {
if (this.state.seedInputVisibility) {
document.querySelector('#wifkeysPassphraseTextarea').style.height = '1px';
document.querySelector('#wifkeysPassphraseTextarea').style.height = `${(15 + document.querySelector('#wifkeysPassphraseTextarea').scrollHeight)}px`;
}
}, 100);
}
updateSocketsData(data) {
if (data &&
data.msg &&
@ -404,9 +416,30 @@ class Settings extends React.Component {
}
updateInput(e) {
this.setState({
[e.target.name]: e.target.value,
});
console.log(e.target.name);
if (e.target.name === 'wifkeysPassphrase') {
// remove any empty chars from the start/end of the string
const newValue = e.target.value;
clearTimeout(this.state.trimPassphraseTimer);
const _trimPassphraseTimer = setTimeout(() => {
this.setState({
wifkeysPassphrase: newValue ? newValue.trim() : '', // hardcoded field name
});
}, 2000);
this.resizeLoginTextarea();
this.setState({
trimPassphraseTimer: _trimPassphraseTimer,
[e.target.name]: newValue,
});
} else {
this.setState({
[e.target.name]: e.target.value,
});
}
}
renderDebugLogData() {

83
react/src/components/dashboard/settings/settings.render.js

@ -12,38 +12,38 @@ export const AppUpdateTabRender = function() {
onClick={ () => this.openTab('AppUpdate', 10) }>
<div className="panel-heading">
<a className={ this.state.activeTab === 10 ? 'panel-title' : 'panel-title collapsed' }>
<i className="icon fa fa-life-ring"></i> Update
<i className="icon fa fa-life-ring"></i> { translate('INDEX.UPDATE') }
</a>
</div>
<div
className={ this.state.activeTab === 10 ? 'panel-collapse collapse in' : 'panel-collapse collapse' }
style={{ height: this.state.activeTab === 10 ? this.state.activeTabHeight + 'px' : '0' }}>
style={{ height: this.state.activeTab === 10 ? `${this.state.activeTabHeight}px` : '0' }}>
<div className="panel-body">
<div className="col-sm-4 padding-top-15">
<h5>UI update</h5>
<h5>{ translate('INDEX.UI_UPDATE') }</h5>
<div className="padding-top-15">
<button
type="button"
className="btn btn-primary waves-effect waves-light"
onClick={ this._checkForUpdateUIPromise }>Check for update</button>
onClick={ this._checkForUpdateUIPromise }>{ translate('INDEX.CHECK_FOR_UPDATE') }</button>
<button
type="button"
className="btn btn-primary waves-effect waves-light margin-left-20"
onClick={ this._updateUIPromise }
disabled={ !this.state.updatePatch }>Update UI now</button>
disabled={ !this.state.updatePatch }>{ translate('INDEX.UPDATE_UI_NOW') }</button>
</div>
</div>
<div className="col-sm-4 padding-top-15 hide">
<h5>Binaries update</h5>
<h5>{ translate('INDEX.BINS_UPDATE') }</h5>
<div className="padding-top-15">
<button
type="button"
className="btn btn-primary waves-effect waves-light"
onClick={ this._checkForUpdateUIPromise }>Check for updates</button>
onClick={ this._checkForUpdateUIPromise }>{ translate('INDEX.CHECK_FOR_UPDATE') }</button>
<button
type="button"
className="btn btn-primary waves-effect waves-light margin-left-20"
onClick={ this.checkNodes }>Update bins now</button>
onClick={ this.checkNodes }>{ translate('INDEX.UPDATE_BINS_NOW') }</button>
</div>
</div>
<div className="col-sm-12 padding-top-15">
@ -68,7 +68,7 @@ export const AppInfoTabRender = function() {
</div>
<div
className={ this.state.activeTab === 8 ? 'panel-collapse collapse in' : 'panel-collapse collapse' }
style={{ height: this.state.activeTab === 8 ? this.state.activeTabHeight + 'px' : '0' }}>
style={{ height: this.state.activeTab === 8 ? `${this.state.activeTabHeight}px` : '0' }}>
<div className="panel-body">
<div className="col-sm-12 padding-top-15">
<div className="row">
@ -159,7 +159,7 @@ export const SettingsRender = function() {
<div
id="WalletInfo"
onClick={ () => this.openTab('WalletInfo', 0) }
className={ this.state.nativeOnly ? 'hide' : 'panel' }>
className={ this.state.nativeOnly ? 'panel hide' : 'panel' }>
<div className="panel-heading">
<a className={ this.state.activeTab === 0 ? 'panel-title' : 'panel-title collapsed' }>
<i className="icon md-balance-wallet"></i>{ translate('INDEX.WALLET_INFO') }
@ -167,7 +167,7 @@ export const SettingsRender = function() {
</div>
<div
className={ this.state.activeTab === 0 ? 'panel-collapse collapse in' : 'panel-collapse collapse' }
style={{ height: this.state.activeTab === 0 ? this.state.activeTabHeight + 'px' : '0' }}>
style={{ height: this.state.activeTab === 0 ? `${this.state.activeTabHeight}px` : '0' }}>
<div className="panel-body">
<table className="table">
<thead>
@ -210,7 +210,7 @@ export const SettingsRender = function() {
<div
id="AddNodeforCoin"
onClick={ () => this.openTab('AddNodeforCoin', 1) }
className={ this.state.nativeOnly ? 'hide' : 'panel' }>
className={ this.state.nativeOnly ? 'panel hide' : 'panel' }>
<div className="panel-heading">
<a className={ this.state.activeTab === 1 ? 'panel-title' : 'panel-title collapsed' }>
<i className="icon md-plus-square"></i>{ translate('INDEX.ADD_NODE') }
@ -218,7 +218,7 @@ export const SettingsRender = function() {
</div>
<div
className={ this.state.activeTab === 1 ? 'panel-collapse collapse in' : 'panel-collapse collapse' }
style={{ height: this.state.activeTab === 1 ? this.state.activeTabHeight + 'px' : '0' }}>
style={{ height: this.state.activeTab === 1 ? `${this.state.activeTabHeight}px` : '0' }}>
<div className="panel-body">
<div className="row">
<div className="col-sm-6">
@ -296,7 +296,7 @@ export const SettingsRender = function() {
<div
id="DumpWallet"
onClick={ () => this.openTab('DumpWallet', 2) }
className={ this.state.nativeOnly ? 'hide' : 'panel' }>
className={ this.state.nativeOnly ? 'panel hide' : 'panel' }>
<div className="panel-heading">
<a className={ this.state.activeTab === 2 ? 'panel-title' : 'panel-title collapsed' }>
<i className="icon wb-briefcase"></i>{ translate('INDEX.WALLET_BACKUP') }
@ -304,7 +304,7 @@ export const SettingsRender = function() {
</div>
<div
className={ this.state.activeTab === 2 ? 'panel-collapse collapse in' : 'panel-collapse collapse' }
style={{ height: this.state.activeTab === 2 ? this.state.activeTabHeight + 'px' : '0' }}>
style={{ height: this.state.activeTab === 2 ? `${this.state.activeTabHeight}px` : '0' }}>
<div className="panel-body">Wallet Backup section to be updated soon.</div>
</div>
</div>
@ -312,7 +312,7 @@ export const SettingsRender = function() {
<div
id="FiatCurrencySettings"
onClick={ () => this.openTab('FiatCurrencySettings', 3) }
className={ this.state.nativeOnly ? 'hide' : 'panel' }>
className={ this.state.nativeOnly ? 'panel hide' : 'panel' }>
<div className="panel-heading">
<a className={ this.state.activeTab === 3 ? 'panel-title' : 'panel-title collapsed' }>
<i className="icon fa-money"></i>{ translate('INDEX.FIAT_CURRENCY') }
@ -320,7 +320,7 @@ export const SettingsRender = function() {
</div>
<div
className={ this.state.activeTab === 3 ? 'panel-collapse collapse in' : 'panel-collapse collapse' }
style={{ height: this.state.activeTab === 3 ? this.state.activeTabHeight + 'px' : '0' }}>
style={{ height: this.state.activeTab === 3 ? `${this.state.activeTabHeight}px` : '0' }}>
<div className="panel-body">Fiat currency settings section to be updated soon.</div>
</div>
</div>
@ -328,7 +328,7 @@ export const SettingsRender = function() {
<div
id="ExportKeys"
onClick={ () => this.openTab('ExportKeys', 4) }
className={ this.state.nativeOnly ? 'hide' : 'panel' }>
className={ this.state.nativeOnly ? 'panel hide' : 'panel' }>
<div className="panel-heading">
<a className={ this.state.activeTab === 4 ? 'panel-title' : 'panel-title collapsed' }>
<i className="icon md-key"></i>{ translate('INDEX.EXPORT_KEYS') }
@ -336,7 +336,7 @@ export const SettingsRender = function() {
</div>
<div
className={ this.state.activeTab === 4 ? 'panel-collapse collapse in' : 'panel-collapse collapse' }
style={{ height: this.state.activeTab === 4 ? this.state.activeTabHeight + 'px' : '0' }}>
style={{ height: this.state.activeTab === 4 ? `${this.state.activeTabHeight}px` : '0' }}>
<div className="panel-body">
<p>
<div className="padding-bottom-20">{ this.renderLB('INDEX.ONLY_ACTIVE_WIF_KEYS') }</div>
@ -355,11 +355,18 @@ export const SettingsRender = function() {
autoComplete="off">
<div className="form-group form-material floating">
<input
type={ this.state.seedInputVisibility ? 'text' : 'password' }
className="form-control"
type="password"
className={ !this.state.seedInputVisibility ? 'form-control' : 'hide' }
name="wifkeysPassphrase"
id="wifkeysPassphrase"
onChange={ this.updateInput } />
onChange={ this.updateInput }
value={ this.state.wifkeysPassphrase } />
<textarea
className={ this.state.seedInputVisibility ? 'form-control' : 'hide' }
id="wifkeysPassphraseTextarea"
name="wifkeysPassphrase"
onChange={ this.updateInput }
value={ this.state.wifkeysPassphrase }></textarea>
<i
className={ !this.state.seedInputVisibility ? 'seed-toggle fa fa-eye-slash' : 'seed-toggle fa fa-eye' }
onClick={ this.toggleSeedInputVisibility }></i>
@ -398,7 +405,7 @@ export const SettingsRender = function() {
<div
id="ImportKeys"
onClick={ () => this.openTab('ImportKeys', 5) }
className={ this.state.nativeOnly ? 'hide' : 'panel' }>
className={ this.state.nativeOnly ? 'panel hide' : 'panel' }>
<div className="panel-heading">
<a className={ this.state.activeTab === 5 ? 'panel-title' : 'panel-title collapsed' }>
<i className="icon md-key"></i>{ translate('INDEX.IMPORT_KEYS') }
@ -406,16 +413,16 @@ export const SettingsRender = function() {
</div>
<div
className={ this.state.activeTab === 5 ? 'panel-collapse collapse in' : 'panel-collapse collapse' }
style={{ height: this.state.activeTab === 5 ? this.state.activeTabHeight + 'px' : '0' }}>
style={{ height: this.state.activeTab === 5 ? `${this.state.activeTabHeight}px` : '0' }}>
<div className="panel-body">
<p>
<div>{ translate('INDEX.IMPORT_KEYS_DESC_P1') }</div><br/>
<div>{ translate('INDEX.IMPORT_KEYS_DESC_P2') }</div><br/>
<div>{ translate('INDEX.IMPORT_KEYS_DESC_P3') }</div><br/>
<div>{ translate('INDEX.IMPORT_KEYS_DESC_P1') }</div><br/>
<div>{ translate('INDEX.IMPORT_KEYS_DESC_P2') }</div><br/>
<div>{ translate('INDEX.IMPORT_KEYS_DESC_P3') }</div><br/>
<div>
<strong>
<i>{ translate('INDEX.PLEASE_KEEP_KEYS_SAFE') }</i>
</strong>
</p>
</div>
<div className="col-sm-12"></div>
<form
className="wifkeys-import-form"
@ -455,7 +462,7 @@ export const SettingsRender = function() {
</div>
<div
className={ this.state.activeTab === 6 ? 'panel-collapse collapse in' : 'panel-collapse collapse' }
style={{ height: this.state.activeTab === 6 ? this.state.activeTabHeight + 'px' : '0' }}>
style={{ height: this.state.activeTab === 6 ? `${this.state.activeTabHeight}px` : '0' }}>
<div className="panel-body">
<p>{ translate('INDEX.DEBUG_LOG_DESC') }</p>
<div className="col-sm-12"></div>
@ -514,7 +521,7 @@ export const SettingsRender = function() {
</div>
<div
className={ this.state.activeTab === 7 ? 'panel-collapse collapse in' : 'panel-collapse collapse' }
style={{ height: this.state.activeTab === 7 ? this.state.activeTabHeight + 'px' : '0' }}>
style={{ height: this.state.activeTab === 7 ? `${this.state.activeTabHeight}px` : '0' }}>
<div className="panel-body">
<p>
<strong>{ translate('SETTINGS.CONFIG_RESTART_REQUIRED') }</strong>
@ -540,7 +547,7 @@ export const SettingsRender = function() {
<div
id="Cli"
onClick={ () => this.openTab('Cli', 9) }
className={ !this.props.Main.coins.native.length ? 'hide' : 'panel' }>
className={ !this.props.Main.coins.native.length ? 'panel hide' : 'panel' }>
<div className="panel-heading">
<a className={ this.state.activeTab === 9 ? 'panel-title' : 'panel-title collapsed' }>
<i className="icon fa-code"></i> CLI
@ -548,9 +555,9 @@ export const SettingsRender = function() {
</div>
<div
className={ this.state.activeTab === 9 ? 'panel-collapse collapse in' : 'panel-collapse collapse' }
style={{ height: this.state.activeTab === 9 ? this.state.activeTabHeight + 'px' : '0' }}>
style={{ height: this.state.activeTab === 9 ? `${this.state.activeTabHeight}px` : '0' }}>
<div className="panel-body">
<p>Select a coin and type in CLI compatible command</p>
<p>{ translate('INDEX.CLI_SELECT_A_COIN') }</p>
<div className="col-sm-12"></div>
<form
className="execute-cli-cmd-form"
@ -563,12 +570,12 @@ export const SettingsRender = function() {
name="cliCoin"
id="settingsCliOptions"
onChange={ this.updateInput }>
<option value="">Select coin</option>
<option value="">{ translate('INDEX.CLI_SELECT_A_COIN') }</option>
{ this.renderActiveCoinsList('native') }
</select>
<label
className="floating-label"
htmlFor="settingsDelectDebugLogOptions">Coin</label>
htmlFor="settingsDelectDebugLogOptions">{ translate('INDEX.COIN') }</label>
</div>
<div className="form-group form-material floating">
<textarea
@ -580,14 +587,14 @@ export const SettingsRender = function() {
onChange={ this.updateInput }></textarea>
<label
className="floating-label"
htmlFor="readDebugLogLines">Type in CLI compatible cmd</label>
htmlFor="readDebugLogLines">{ translate('INDEX.TYPE_CLI_CMD') }</label>
</div>
<div className="col-sm-12 col-xs-12 text-align-center">
<button
type="button"
className="btn btn-primary waves-effect waves-light"
disabled={ !this.state.cliCoin || !this.state.cliCmd }
onClick={ () => this.execCliCmd() }>Execute</button>
onClick={ () => this.execCliCmd() }>{ translate('INDEX.EXECUTE') }</button>
</div>
<div className="col-sm-12 col-xs-12 text-align-left">
<div className="padding-top-40 padding-bottom-20 horizontal-padding-0">

5
react/src/components/dashboard/syncOnly/syncOnly.js

@ -1,5 +1,6 @@
import React from 'react';
import { getCoinTitle } from '../../../util/coinHelper';
import { translate } from '../../../translate/translate';
import {
stopInterval,
addCoin,
@ -19,7 +20,7 @@ class SyncOnly extends React.Component {
constructor(props) {
super(props);
this.state = {
autoRestartedForks: {}
autoRestartedForks: {},
};
this.closeSyncOnlyModal = this.closeSyncOnlyModal.bind(this);
}
@ -141,7 +142,7 @@ class SyncOnly extends React.Component {
return items;
} else {
return (
<div>Loading...</div>
<div>{ translate('INDEX.LOADING') }...</div>
);
}
}

12
react/src/components/dashboard/syncOnly/syncOnly.render.js

@ -12,7 +12,7 @@ export const ProgressRender = function (fork) {
</div>
<div
className={ 'font-size-80-percent ' + (this.isFullySynced(fork) ? 'hide' : 'progress-bar progress-bar-info progress-bar-striped active') }
style={{ width: fork.bundles + '%' }}>
style={{ width: `${fork.bundles}%` }}>
{ translate('INDEX.BUNDLES') } { fork.bundles }%
</div>
</div>
@ -23,21 +23,21 @@ export const ProgressRender = function (fork) {
<div className="progress progress-sm">
<div
className="progress-bar progress-bar-warning progress-bar-striped active font-size-80-percent"
style={{ width: fork.utxo + '%' }}>
style={{ width: `${fork.utxo}%` }}>
utxo { fork.utxo }%
</div>
</div>
<div className="progress progress-sm">
<div
className="progress-bar progress-bar-danger progress-bar-striped active font-size-80-percent"
style={{ width: fork.balances + '%' }}>
style={{ width: `${fork.balances}%` }}>
{ translate('INDEX.BALANCES') } { fork.balances }%
</div>
</div>
<div className="progress progress-sm">
<div
className="progress-bar progress-bar-success progress-bar-striped active font-size-80-percent"
style={{ width: fork.validated + '%' }}>
style={{ width: `${fork.validated}%` }}>
{ translate('INDEX.VALIDATED') } { fork.validated }%
</div>
</div>
@ -57,7 +57,9 @@ export const ForkItemRender = function (forkInfo, port) {
src={ `assets/images/cryptologo/${this.renderCoinName(forkInfo.registry.coin).logo}.png` }
alt={ forkInfo.registry.coin }/>
<span className="badge up badge-success margin-bottom-5">Full</span>
<div className="coin-name">{ this.renderCoinName(forkInfo.registry.coin).name } ({ forkInfo.registry.coin.toUpperCase() })</div>
<div className="coin-name">
{ this.renderCoinName(forkInfo.registry.coin).name } ({ forkInfo.registry.coin.toUpperCase() })
</div>
<div className="margin-top-10">
<span
className="btn btn-primary"

59
react/src/components/dashboard/walletsBalance/walletsBalance.js

@ -23,44 +23,49 @@ class WalletsBalance extends React.Component {
renderBalance(type) {
let _balance = '0';
const _mode = this.props.ActiveCoin.mode;
if (this.props.ActiveCoin.mode === 'full') {
if (_mode === 'full') {
_balance = this.props.ActiveCoin.balance || 0;
} else {
if (this.props.ActiveCoin.cache) {
const _cache = this.props.ActiveCoin.cache;
const _coin = this.props.ActiveCoin.coin;
const _address = this.props.ActiveCoin.activeAddress;
if (type === 'main' &&
this.props.ActiveCoin.mode === 'basilisk' &&
this.props.ActiveCoin.activeAddress &&
this.props.ActiveCoin.cache[this.props.ActiveCoin.coin] &&
this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress] &&
this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance &&
this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data &&
this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data.balance) {
_balance = this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data.balance;
_mode === 'basilisk' &&
_address &&
_cache[_coin] &&
_cache[_coin][_address] &&
_cache[_coin][_address].getbalance &&
_cache[_coin][_address].getbalance.data &&
_cache[_coin][_address].getbalance.data.balance) {
_balance = _cache[_coin][_address].getbalance.data.balance;
}
if (type === 'interest' &&
this.props.ActiveCoin.mode === 'basilisk' &&
this.props.ActiveCoin.activeAddress &&
this.props.ActiveCoin.cache[this.props.ActiveCoin.coin] &&
this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress] &&
this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance &&
this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data &&
this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data.interest) {
_balance = this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data.interest;
_mode === 'basilisk' &&
_address &&
_cache[_coin] &&
_cache[_coin][_address] &&
_cache[_coin][_address].getbalance &&
_cache[_coin][_address].getbalance.data &&
_cache[_coin][_address].getbalance.data.interest) {
_balance = _cache[_coin][_address].getbalance.data.interest;
}
if (type === 'total' &&
this.props.ActiveCoin.mode === 'basilisk' &&
this.props.ActiveCoin.activeAddress &&
this.props.ActiveCoin.cache[this.props.ActiveCoin.coin] &&
this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress] &&
this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance &&
this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data &&
(this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data.balance ||
this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data.interest)) {
const _regBalance = this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data.balance ? this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data.balance : 0;
const _regInterest = this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data.interest ? this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data.interest : 0;
_mode === 'basilisk' &&
_address &&
_cache[_coin] &&
_cache[_coin][_address] &&
_cache[_coin][_address].getbalance &&
_cache[_coin][_address].getbalance.data &&
(_cache[_coin][_address].getbalance.data.balance ||
_cache[_coin][_address].getbalance.data.interest)) {
const _regBalance = _cache[_coin][_address].getbalance.data.balance ? _cache[_coin][_address].getbalance.data.balance : 0;
const _regInterest = _cache[_coin][_address].getbalance.data.interest ? _cache[_coin][_address].getbalance.data.interest : 0;
_balance = _regBalance + _regInterest;
}

35
react/src/components/dashboard/walletsBalance/walletsBalance.render.js

@ -7,23 +7,13 @@ const WalletsBalanceRender = function() {
<div className="col-xs-12">
<div className={ this.isFullMode() && !this.isFullySynced() ? 'col-xs-12' : 'col-xs-12 hide' }>
<div className="alert alert-info alert-dismissible">
<button
className="close"
type="button">
<span>×</span>
</button>
<h4>{ translate('INDEX.ACTIVATING_WALLET_RT') }</h4>
<p>{ translate('INDEX.IGUANA_FULL_MODE_SYNC_P1') }</p>
<p>{ translate('INDEX.IGUANA_FULL_MODE_SYNC_P2') }</p>
<p className="font-weight-600">{ this.renderLB('INDEX.IGUANA_FULL_MODE_SYNC_P3') }</p>
</div>
<div className="alert alert-info alert-dismissible">
<button
className="close"
type="button">
<span>×</span>
</button>
<div className="alert alert-info alert-dismissible hide">
<h4>{ translate('INDEX.FETCHING_COIN_DATA') }</h4>
<p>{ translate('INDEX.IGUANA_FULL_MODE_SYNC_P1') }</p>
<p>{ translate('INDEX.IGUANA_FULL_MODE_SYNC_P2') }</p>
@ -32,7 +22,6 @@ const WalletsBalanceRender = function() {
</div>
<div className={ this.isNativeMode() ? 'col-lg-3 col-xs-12' : this.isBasiliskMode() ? 'col-lg-4 col-xs-12' : 'col-lg-12 col-xs-12'}>
<div className="widget widget-shadow">
<div className="widget-content">
<div className="padding-20 padding-top-10">
@ -57,21 +46,21 @@ const WalletsBalanceRender = function() {
</div>
{ this.isNativeMode() &&
<div className="col-lg-3 col-xs-12">
<div className="widget widget-shadow">
<div className="padding-20 padding-top-10">
<div className="clearfix">
<div className="pull-left padding-vertical-10">
<i className="icon fa-eye-slash font-size-24 vertical-align-bottom margin-right-5"></i>
{ translate('INDEX.Z_BALANCE') }
<div className="col-lg-3 col-xs-12">
<div className="widget widget-shadow">
<div className="padding-20 padding-top-10">
<div className="clearfix">
<div className="pull-left padding-vertical-10">
<i className="icon fa-eye-slash font-size-24 vertical-align-bottom margin-right-5"></i>
{ translate('INDEX.Z_BALANCE') }
</div>
<span className="pull-right padding-top-10 font-size-22">
{ this.props.ActiveCoin.balance.private ? this.props.ActiveCoin.balance.private : '-' }
</span>
</div>
<span className="pull-right padding-top-10 font-size-22">
{ this.props.ActiveCoin.balance.private ? this.props.ActiveCoin.balance.private : '-' }
</span>
</div>
</div>
</div>
</div>
}
<div className={ this.isNativeMode() ? 'col-lg-3 col-xs-12' :

48
react/src/components/dashboard/walletsData/walletsData.js

@ -32,7 +32,7 @@ import {
import { SocketProvider } from 'socket.io-react';
import io from 'socket.io-client';
const socket = io.connect('http://127.0.0.1:' + Config.agamaPort);
const socket = io.connect(`http://127.0.0.1:${Config.agamaPort}`);
class WalletsData extends React.Component {
constructor(props) {
@ -401,22 +401,30 @@ class WalletsData extends React.Component {
}
renderAddressByType(type) {
if (this.props.ActiveCoin.addresses &&
this.props.ActiveCoin.addresses[type] &&
this.props.ActiveCoin.addresses[type].length) {
const _addresses = this.props.ActiveCoin.addresses;
if (_addresses &&
_addresses[type] &&
_addresses[type].length) {
let items = [];
const _cache = this.props.ActiveCoin.cache;
const _coin = this.props.ActiveCoin.coin;
for (let i = 0; i < this.props.ActiveCoin.addresses[type].length; i++) {
const address = this.props.ActiveCoin.addresses[type][i];
for (let i = 0; i < _addresses[type].length; i++) {
const address = _addresses[type][i].address;
let _amount = address.amount;
if (this.props.ActiveCoin.mode === 'basilisk') {
_amount = this.props.ActiveCoin.cache && this.props.ActiveCoin.cache[this.props.ActiveCoin.coin] && this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][address.address] && this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][address.address].getbalance.data && this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][address.address].getbalance.data.balance ? this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][address.address].getbalance.data.balance : 'N/A';
_amount = _cache && _cache[_coin] && _cache[_coin][address] && _cache[_coin][address].getbalance.data && _cache[_coin][address].getbalance.data.balance ? _cache[_coin][address].getbalance.data.balance : 'N/A';
}
items.push(
<li key={address.address}>
<a onClick={ () => this.updateAddressSelection(address.address, type, _amount) }><i className={ type === 'public' ? 'icon fa-eye' : 'icon fa-eye-slash' }></i> <span className="text">[ { _amount } { this.props.ActiveCoin.coin } ] { address.address }</span><span className="glyphicon glyphicon-ok check-mark"></span></a>
<li key={address}>
<a onClick={ () => this.updateAddressSelection(address, type, _amount) }>
<i className={ type === 'public' ? 'icon fa-eye' : 'icon fa-eye-slash' }></i>&nbsp;&nbsp;
<span className="text">[ { _amount } { _coin } ]{ address }</span>
<span className="glyphicon glyphicon-ok check-mark"></span>
</a>
</li>
);
}
@ -435,14 +443,19 @@ class WalletsData extends React.Component {
renderAddressAmount() {
if (this.hasPublicAdresses()) {
for (let i = 0; i < this.props.ActiveCoin.addresses.public.length; i++) {
if (this.props.ActiveCoin.addresses.public[i].address === this.state.currentAddress) {
if (this.props.ActiveCoin.addresses.public[i].amount &&
this.props.ActiveCoin.addresses.public[i].amount !== 'N/A') {
return this.props.ActiveCoin.addresses.public[i].amount;
const _addresses = this.props.ActiveCoin.addresses;
const _cache = this.props.ActiveCoin.cache;
const _coin = this.props.ActiveCoin.coin;
for (let i = 0; i < _addresses.public.length; i++) {
if (_addresses.public[i].address === this.state.currentAddress) {
if (_addresses.public[i].amount &&
_addresses.public[i].amount !== 'N/A') {
return _addresses.public[i].amount;
} else {
const address = this.props.ActiveCoin.addresses.public[i].address;
const _amount = this.props.ActiveCoin.cache[this.props.ActiveCoin.coin] && this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][address] && this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][address].getbalance.data && this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][address].getbalance.data.balance ? this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][address].getbalance.data.balance : 'N/A';
const address = _addresses.public[i].address;
const _amount = _cache[_coin] && _cache[_coin][address] && _cache[_coin][address].getbalance.data && _cache[_coin][address].getbalance.data.balance ? _cache[_coin][address].getbalance.data.balance : 'N/A';
return _amount;
}
}
@ -456,7 +469,8 @@ class WalletsData extends React.Component {
if (this.state.currentAddress) {
return (
<span>
<i className={ this.state.addressType === 'public' ? 'icon fa-eye' : 'icon fa-eye-slash' }></i> <span className="text">[ { this.renderAddressAmount() } { this.props.ActiveCoin.coin } ] { this.state.currentAddress }</span>
<i className={ 'icon fa-eye' + (this.state.addressType === 'public' ? '' : '-slash') }></i>&nbsp;&nbsp;
<span className="text">[ { this.renderAddressAmount() } { this.props.ActiveCoin.coin } ]{ this.state.currentAddress }</span>
</span>
);
} else {

4
react/src/components/dashboard/walletsData/walletsData.render.js

@ -6,6 +6,8 @@ import WalletsNotariesList from '../walletsNotariesList/walletsNotariesList';
import WalletsCacheData from '../walletsCacheData/walletsCacheData';
import { secondsToString } from '../../../util/time';
// TODO: clean basilisk dropdown menu
export const PaginationItemRender = function(i) {
return (
<li
@ -81,7 +83,7 @@ export const TxHistoryListRender = function(tx, index) {
<button
type="button"
className="btn btn-xs white btn-info waves-effect waves-light btn-kmdtxid"
onClick={ () => this.toggleTxInfoModal(!this.props.ActiveCoin.showTransactionInfo, index) }>
onClick={ () => this.toggleTxInfoModal(!this.props.ActiveCoin.showTransactionInfo, ((this.state.activePage - 1) * this.state.itemsPerPage) + index) }>
<i className="icon fa-search"></i>
</button>
</td>

5
react/src/components/dashboard/walletsNativeAlert/walletsNativeAlert.render.js

@ -4,11 +4,6 @@ import { translate } from '../../../translate/translate';
const WalletsNativeAlertRender = function() {
return (
<div className="alert alert-danger alert-dismissible">
<button
className="close"
type="button">
<span>×</span>
</button>
<h4>{ translate('INDEX.OOPS_ERROR') }</h4>
<p>
<span>{ translate('INDEX.OOPS_ERROR_DESC') }</span>

11
react/src/components/dashboard/walletsNativeSyncProgress/walletsNativeSyncProgress.js

@ -38,7 +38,7 @@ class WalletsNativeSyncProgress extends React.Component {
<div
className="progress-bar progress-bar-info progress-bar-striped active font-size-80-percent"
style={{ width: '100%' }}>
<span style={{ width: '100%' }}>Loading blocks...it can take up to 15 min to load blocks</span>
<span style={{ width: '100%' }}>{ translate('INDEX.LOADING_BLOCKS') }</span>
</div>
);
}
@ -48,7 +48,6 @@ class WalletsNativeSyncProgress extends React.Component {
renderActivatingBestChainProgress() {
if (this.props.Settings &&
this.props.Settings.debugLog) {
console.log('debugLog');
if (this.props.Settings.debugLog.indexOf('UpdateTip') > -1 &&
!this.props.Dashboard.progress &&
!this.props.Dashboard.progress.blocks) {
@ -75,7 +74,7 @@ class WalletsNativeSyncProgress extends React.Component {
if (this.props.Dashboard.progress.remoteKMDNode &&
this.props.Dashboard.progress.remoteKMDNode.blocks) {
return(
`: ${Math.floor(currentBestChain * 100 / this.props.Dashboard.progress.remoteKMDNode.blocks)}% (blocks ${currentBestChain} / ${this.props.Dashboard.progress.remoteKMDNode.blocks})`
`: ${Math.floor(currentBestChain * 100 / this.props.Dashboard.progress.remoteKMDNode.blocks)}% (${ translate('INDEX.BLOCKS_SM') } ${currentBestChain} / ${this.props.Dashboard.progress.remoteKMDNode.blocks})`
);
}
}
@ -94,18 +93,18 @@ class WalletsNativeSyncProgress extends React.Component {
}
return (
`: ${currentProgress}% (rescanning blocks)`
`: ${currentProgress}% (${ translate('INDEX.RESCAN_SM') })`
);
} else if (
this.props.Settings.debugLog.indexOf('LoadExternalBlockFile:') > -1 ||
this.props.Settings.debugLog.indexOf('Reindexing block file') > -1
) {
return (
`: (reindexing blocks from disk)`
`: (${ translate('INDEX.REINDEX') })`
);
} else {
return (
<span> (downloading blocks!)</span>
<span> ({ translate('INDEX.DL_BLOCKS') })</span>
);
}
}

36
react/src/components/dashboard/walletsNativeTxHistory/walletsNativeTxHistory.render.js

@ -113,29 +113,29 @@ export const WalletsNativeTxHistoryRender = function() {
className="table table-hover dataTable table-striped"
width="100%">
<thead>
<tr>
<th>{ translate('INDEX.TYPE') }</th>
<th>{ translate('INDEX.DIRECTION') }</th>
<th>{ translate('INDEX.CONFIRMATIONS') }</th>
<th>{ translate('INDEX.AMOUNT') }</th>
<th>{ translate('INDEX.TIME') }</th>
<th>{ translate('INDEX.DEST_ADDRESS') }</th>
<th>{ translate('INDEX.TX_DETAIL') }</th>
</tr>
<tr>
<th>{ translate('INDEX.TYPE') }</th>
<th>{ translate('INDEX.DIRECTION') }</th>
<th>{ translate('INDEX.CONFIRMATIONS') }</th>
<th>{ translate('INDEX.AMOUNT') }</th>
<th>{ translate('INDEX.TIME') }</th>
<th>{ translate('INDEX.DEST_ADDRESS') }</th>
<th>{ translate('INDEX.TX_DETAIL') }</th>
</tr>
</thead>
<tbody>
{ this.renderTxHistoryList() }
</tbody>
<tfoot>
<tr>
<th>{ translate('INDEX.TYPE') }</th>
<th>{ translate('INDEX.DIRECTION') }</th>
<th>{ translate('INDEX.CONFIRMATIONS') }</th>
<th>{ translate('INDEX.AMOUNT') }</th>
<th>{ translate('INDEX.TIME') }</th>
<th>{ translate('INDEX.DEST_ADDRESS') }</th>
<th>{ translate('INDEX.TX_DETAIL') }</th>
</tr>
<tr>
<th>{ translate('INDEX.TYPE') }</th>
<th>{ translate('INDEX.DIRECTION') }</th>
<th>{ translate('INDEX.CONFIRMATIONS') }</th>
<th>{ translate('INDEX.AMOUNT') }</th>
<th>{ translate('INDEX.TIME') }</th>
<th>{ translate('INDEX.DEST_ADDRESS') }</th>
<th>{ translate('INDEX.TX_DETAIL') }</th>
</tr>
</tfoot>
</table>
</div>

25
react/src/components/dashboard/walletsProgress/walletsProgress.js

@ -38,7 +38,7 @@ class WalletsProgress extends React.Component {
renderChainActivationNotification() {
if (this.props.Dashboard.progress) {
if ((!this.props.Dashboard.progress.blocks && !this.props.Dashboard.progress.longestchain) ||
(this.props.Dashboard.progress.blocks < this.props.Dashboard.progress.longestchain)) {
(this.props.Dashboard.progress.blocks < this.props.Dashboard.progress.longestchain)) {
return ChainActivationNotificationRender.call(this);
}
} else {
@ -48,17 +48,18 @@ class WalletsProgress extends React.Component {
renderSyncPercentagePlaceholder() {
if (this.props.Dashboard.progress &&
this.props.Dashboard.progress.blocks > 0 &&
this.props.Dashboard.progress.longestchain === 0) {
this.props.Dashboard.progress.blocks > 0 &&
this.props.Dashboard.progress.longestchain === 0) {
return SyncErrorLongestChainRender.call(this);
}
if (this.props.Dashboard.progress && this.props.Dashboard.progress.blocks === 0) {
if (this.props.Dashboard.progress &&
this.props.Dashboard.progress.blocks === 0) {
return SyncErrorBlocksRender.call(this);
}
if (this.props.Dashboard.progress &&
this.props.Dashboard.progress.blocks) {
this.props.Dashboard.progress.blocks) {
const syncPercentage = (parseFloat(parseInt(this.props.Dashboard.progress.blocks, 10) * 100
/ parseInt(this.props.Dashboard.progress.longestchain, 10)).toFixed(2) + '%').replace('NaN', 0);
return SyncPercentageRender.call(this, syncPercentage);
@ -75,8 +76,8 @@ class WalletsProgress extends React.Component {
if (this.props.Settings &&
this.props.Settings.debugLog) {
if (this.props.Settings.debugLog.indexOf('UpdateTip') > -1 &&
!this.props.Dashboard.progress &&
!this.props.Dashboard.progress.blocks) {
!this.props.Dashboard.progress &&
!this.props.Dashboard.progress.blocks) {
const temp = this.props.Settings.debugLog.split(' ');
let currentBestChain;
let currentProgress;
@ -94,13 +95,13 @@ class WalletsProgress extends React.Component {
if (this.props.Dashboard.progress.remoteKMDNode &&
!this.props.Dashboard.progress.remoteKMDNode.blocks) {
return (
`: ${currentProgress}% (activating)`
`: ${currentProgress}% (${ translate('INDEX.ACTIVATING_SM') })`
);
} else {
if (this.props.Dashboard.progress.remoteKMDNode &&
this.props.Dashboard.progress.remoteKMDNode.blocks) {
return(
`: ${Math.floor(currentBestChain * 100 / this.props.Dashboard.progress.remoteKMDNode.blocks)}% (blocks ${currentBestChain} / ${this.props.Dashboard.progress.remoteKMDNode.blocks})`
`: ${Math.floor(currentBestChain * 100 / this.props.Dashboard.progress.remoteKMDNode.blocks)}% (${ translate('INDEX.BLOCKS_SM') } ${currentBestChain} / ${this.props.Dashboard.progress.remoteKMDNode.blocks})`
);
}
}
@ -119,18 +120,18 @@ class WalletsProgress extends React.Component {
}
return (
`: ${currentProgress}% (rescanning blocks)`
`: ${currentProgress}% (${ translate('INDEX.RESCAN_SM') })`
);
} else if (
this.props.Settings.debugLog.indexOf('LoadExternalBlockFile:') > -1 ||
this.props.Settings.debugLog.indexOf('Reindexing block file') > -1
) {
return (
`: (reindexing blocks from disk)`
`: ({ translate('INDEX.REINDEX') })`
);
} else {
return (
<span> (downloading blocks)</span>
<span> ({ translate('INDEX.DL_BLOCKS') })</span>
);
}
}

87
react/src/components/dashboard/walletsProgress/walletsProgress.render.js

@ -32,13 +32,14 @@ export const LoadingBlocksRender = function() {
<div
className="progress-bar progress-bar-info progress-bar-striped active font-size-80-percent"
style={{ width: '100%' }}>
<span style={{ width: '100%' }}>Loading blocks...it can take up to 15 min to load blocks</span>
<span style={{ width: '100%' }}>{ translate('INDEX.LOADING_BLOCKS') }</span>
</div>
);
};
export const TranslationComponentsRender = function(translationID) {
const translationComponents = translate(translationID).split('<br>');
return translationComponents.map((translation, idx) =>
<span key={idx}>
{ translation }
@ -77,60 +78,62 @@ export const WalletsProgressRender = function () {
className="margin-bottom-20">
{ !this.isNativeMode() &&
<div className="row no-space">
<div id="currency-progressbars">
<div className="progress progress-sm">
<div className={ 'full-width font-size-80-percent '
+ (this.isFullySynced() ? 'progress-bar progress-bar-striped active progress-bar-indicating progress-bar-success' : 'hide') }>
{ translate('INDEX.BUNDLES') } <span id="currency-bundles-percent">({ this.props.ActiveCoin.coin }) 100.00% - ( { this.props.Dashboard.progress.blocks }
/ { this.props.Dashboard.progress.blocks } ) ==&gt;&gt;
RT{ this.props.Dashboard.progress.RTheight }</span>
</div>
<div
className={ 'font-size-80-percent '
+ (this.isFullySynced() ? 'hide' : 'progress-bar progress-bar-info progress-bar-striped active') }
style={{width: this.props.Dashboard.progress.bundles + '%'}}>
{ translate('INDEX.BUNDLES') } { this.props.Dashboard.progress.bundles }%
this.props.Dashboard.progress &&
<div className="row no-space">
<div id="currency-progressbars">
<div className="progress progress-sm">
<div className={ 'full-width font-size-80-percent '
+ (this.isFullySynced() ? 'progress-bar progress-bar-striped active progress-bar-indicating progress-bar-success' : 'hide') }>
{ translate('INDEX.BUNDLES') }&nbsp;
<span id="currency-bundles-percent">({ this.props.ActiveCoin.coin }) 100.00% - ( { this.props.Dashboard.progress.blocks }
/ { this.props.Dashboard.progress.blocks } ) ==&gt;&gt;
RT{ this.props.Dashboard.progress.RTheight }</span>
</div>
<div
className={ 'font-size-80-percent '
+ (this.isFullySynced() ? 'hide' : 'progress-bar progress-bar-info progress-bar-striped active') }
style={{ width: `${this.props.Dashboard.progress.bundles}%` }}>
{ translate('INDEX.BUNDLES') } { this.props.Dashboard.progress.bundles }%
</div>
</div>
</div>
</div>
<div className={ this.isFullySynced() ? 'hide' : '' }>
<div className="progress progress-sm">
<div
className="progress-bar progress-bar-warning progress-bar-striped active font-size-80-percent"
style={{width: this.props.Dashboard.progress.utxo + '%'}}>
utxo { this.props.Dashboard.progress.utxo }%
<div className={ this.isFullySynced() ? 'hide' : '' }>
<div className="progress progress-sm">
<div
className="progress-bar progress-bar-warning progress-bar-striped active font-size-80-percent"
style={{ width: `${this.props.Dashboard.progress.utxo}%` }}>
utxo { this.props.Dashboard.progress.utxo }%
</div>
</div>
</div>
<div className="progress progress-sm">
<div
className="progress-bar progress-bar-danger progress-bar-striped active font-size-80-percent"
style={{width: this.props.Dashboard.progress.balances + '%'}}>
{ translate('INDEX.BALANCES') } { this.props.Dashboard.progress.balances }%
<div className="progress progress-sm">
<div
className="progress-bar progress-bar-danger progress-bar-striped active font-size-80-percent"
style={{ width: `${this.props.Dashboard.progress.balances}%` }}>
{ translate('INDEX.BALANCES') } { this.props.Dashboard.progress.balances }%
</div>
</div>
</div>
<div className="progress progress-sm">
<div
className="progress-bar progress-bar-success progress-bar-striped active font-size-80-percent"
style={{width: this.props.Dashboard.progress.validated + '%'}}>
{ translate('INDEX.VALIDATED') } { this.props.Dashboard.progress.validated }%
<div className="progress progress-sm">
<div
className="progress-bar progress-bar-success progress-bar-striped active font-size-80-percent"
style={{ width: `${this.props.Dashboard.progress.validated}%` }}>
{ translate('INDEX.VALIDATED') } { this.props.Dashboard.progress.validated }%
</div>
</div>
</div>
</div>
</div>
}
{ this.isNativeMode() &&
<div>
{ this.renderChainActivationNotification() }
<div className="row sync-progress-container">
<div className="col-xs-12">
<div className="progress">
{ this.renderSyncPercentagePlaceholder() }
<div>
{ this.renderChainActivationNotification() }
<div className="row sync-progress-container">
<div className="col-xs-12">
<div className="progress">
{ this.renderSyncPercentagePlaceholder() }
</div>
</div>
</div>
</div>
</div>
}
</div>
);

5
react/src/components/dashboard/walletsTxInfo/walletsTxInfo.js

@ -1,4 +1,5 @@
import React from 'react';
import { sortByDate } from '../../../util/sort';
import { toggleDashboardTxInfoModal } from '../../../actions/actionCreators';
import Store from '../../../store';
import WalletsTxInfoRender from './walletsTxInfo.render';
@ -38,8 +39,8 @@ class WalletsTxInfo extends React.Component {
// TODO the conditions below should be merged once the native mode components are fully merged
// into the rest of the components
(!this.isNativeMode() ||
(this.isNativeMode() && this.props.ActiveCoin.nativeActiveSection === 'default'))) {
const txInfo = this.props.ActiveCoin.txhistory[this.props.ActiveCoin.showTransactionInfoTxIndex];
(this.isNativeMode() && this.props.ActiveCoin.nativeActiveSection === 'default'))) {
const txInfo = sortByDate(this.props.ActiveCoin.txhistory)[this.props.ActiveCoin.showTransactionInfoTxIndex];
return WalletsTxInfoRender.call(this, txInfo);
}

42
react/src/components/dashboard/walletsTxInfo/walletsTxInfo.render.js

@ -90,30 +90,30 @@ const WalletsTxInfoRender = function(txInfo) {
</tr>
{ this.isNativeMode() &&
<tr>
<td>walletconflicts</td>
<td>
{ txInfo.walletconflicts.length }
</td>
</tr>
<tr>
<td>walletconflicts</td>
<td>
{ txInfo.walletconflicts.length }
</td>
</tr>
}
{ this.isNativeMode() &&
<tr>
<td>time</td>
<td>
{ secondsToString(txInfo.time) }
</td>
</tr>
<tr>
<td>time</td>
<td>
{ secondsToString(txInfo.time) }
</td>
</tr>
}
{ this.isNativeMode() &&
<tr>
<td>timereceived</td>
<td>
{ secondsToString(txInfo.timereceived) }
</td>
</tr>
<tr>
<td>timereceived</td>
<td>
{ secondsToString(txInfo.timereceived) }
</td>
</tr>
}
</tbody>
</table>
@ -142,7 +142,8 @@ const WalletsTxInfoRender = function(txInfo) {
className="full-width height-170"
rows="10"
cols="80"
defaultValue={ txInfo.hex } disabled></textarea>
defaultValue={ txInfo.hex }
disabled></textarea>
</div>
<div className={ this.state.activeTab === 3 ? 'tab-pane active' : 'tab-pane' }>
@ -150,7 +151,8 @@ const WalletsTxInfoRender = function(txInfo) {
className="full-width height-400"
rows="40"
cols="80"
defaultValue={ JSON.stringify(txInfo, null, '\t') } disabled></textarea>
defaultValue={ JSON.stringify(txInfo, null, '\t') }
disabled></textarea>
</div>
</div>
</div>

65
react/src/components/login/login.js

@ -12,10 +12,10 @@ import {
triggerToaster
} from '../../actions/actionCreators';
import Store from '../../store';
import {PassPhraseGenerator} from '../../util/crypto/passphrasegenerator';
import { PassPhraseGenerator } from '../../util/crypto/passphrasegenerator';
import SwallModalRender from './swall-modal.render';
import LoginRender from './login.render';
import {translate} from '../../translate/translate';
import { translate } from '../../translate/translate';
const IGUNA_ACTIVE_HANDLE_TIMEOUT = 3000;
const IGUNA_ACTIVE_COINS_TIMEOUT = 10000;
@ -26,7 +26,7 @@ class Login extends React.Component {
this.state = {
display: false,
activeLoginSection: 'activateCoin',
loginPassphrase: null,
loginPassphrase: '',
seedInputVisibility: false,
loginPassPhraseSeedType: null,
bitsOption: 256,
@ -38,6 +38,7 @@ class Login extends React.Component {
customWalletSeed: false,
isCustomSeedWeak: false,
nativeOnly: Config.iguanaLessMode,
trimPassphraseTimer: null,
};
this.toggleActivateCoinForm = this.toggleActivateCoinForm.bind(this);
this.updateRegisterConfirmPassPhraseInput = this.updateRegisterConfirmPassPhraseInput.bind(this);
@ -49,6 +50,7 @@ class Login extends React.Component {
this.toggleSeedBackupModal = this.toggleSeedBackupModal.bind(this);
this.copyPassPhraseToClipboard = this.copyPassPhraseToClipboard.bind(this);
this.execWalletCreate = this.execWalletCreate.bind(this);
this.resizeLoginTextarea = this.resizeLoginTextarea.bind(this);
}
isCustomWalletSeed() {
@ -64,13 +66,13 @@ class Login extends React.Component {
this.setState({
randomSeed: PassPhraseGenerator.generatePassPhrase(this.state.bitsOption),
isSeedConfirmError: false,
isSeedBlank: false
isSeedBlank: false,
});
} else {
// if customWalletSeed is set to true, reset to seed to an empty string
this.setState({
randomSeed: '',
randomSeedConfirm: ''
randomSeedConfirm: '',
});
}
});
@ -100,13 +102,15 @@ class Login extends React.Component {
this.setState({
seedInputVisibility: !this.state.seedInputVisibility,
});
this.resizeLoginTextarea();
}
generateNewSeed(bits) {
this.setState(Object.assign({}, this.state, {
randomSeed: PassPhraseGenerator.generatePassPhrase(bits),
bitsOption: bits,
isSeedBlank: false
isSeedBlank: false,
}));
}
@ -138,8 +142,8 @@ class Login extends React.Component {
if (this.state.activeLoginSection !== 'signup') {
if (props &&
props.Main &&
props.Main.activeCoins) {
props.Main &&
props.Main.activeCoins) {
this.setState({
activeLoginSection: 'login',
});
@ -155,21 +159,43 @@ class Login extends React.Component {
Store.dispatch(toggleAddcoinModal(true, false));
}
resizeLoginTextarea() {
// auto-size textarea
setTimeout(() => {
if (this.state.seedInputVisibility) {
document.querySelector('#loginPassphrase').style.height = '1px';
document.querySelector('#loginPassphrase').style.height = `${(15 + document.querySelector('#loginPassphrase').scrollHeight)}px`;
}
}, 100);
}
updateLoginPassPhraseInput(e) {
// remove any empty chars from the start/end of the string
const newValue = e.target.value ? e.target.value.trim() : null;
const newValue = e.target.value;
clearTimeout(this.state.trimPassphraseTimer);
const _trimPassphraseTimer = setTimeout(() => {
this.setState({
loginPassphrase: newValue ? newValue.trim() : '', // hardcoded field name
loginPassPhraseSeedType: this.getLoginPassPhraseSeedType(newValue),
});
}, 2000);
this.resizeLoginTextarea();
this.setState({
trimPassphraseTimer: _trimPassphraseTimer,
[e.target.name]: newValue,
loginPassPhraseSeedType: this.getLoginPassPhraseSeedType(newValue)
});
loginPassPhraseSeedType: this.getLoginPassPhraseSeedType(newValue),
});
}
updateRegisterConfirmPassPhraseInput(e) {
this.setState({
[e.target.name]: e.target.value,
isSeedConfirmError: false,
isSeedBlank: this.isBlank(e.target.value)
isSeedBlank: this.isBlank(e.target.value),
});
}
@ -177,7 +203,7 @@ class Login extends React.Component {
this.setState({
randomSeed: e.target.value,
isSeedConfirmError: false,
isSeedBlank: this.isBlank(e.target.value)
isSeedBlank: this.isBlank(e.target.value),
});
}
@ -199,8 +225,9 @@ class Login extends React.Component {
}
const passPhraseWords = passPhrase.split(' ');
if (!PassPhraseGenerator.arePassPhraseWordsValid(passPhraseWords))
if (!PassPhraseGenerator.arePassPhraseWordsValid(passPhraseWords)) {
return null;
}
if (PassPhraseGenerator.isPassPhraseValid(passPhraseWords, 256)) {
return translate('LOGIN.IGUANA_SEED');
@ -250,9 +277,7 @@ class Login extends React.Component {
});
}
// TODO:
// 1) disable register btn if seed or seed conf is incorrect
// 2) display explicit custom seed validation message
// TODO: disable register btn if seed or seed conf is incorrect
handleRegisterWallet() {
const enteredSeedsMatch = this.state.randomSeed === this.state.randomSeedConfirm;
const isSeedBlank = this.isBlank(this.state.randomSeed);
@ -281,6 +306,8 @@ class Login extends React.Component {
}
handleKeydown(e) {
this.updateLoginPassPhraseInput(e);
if (e.key === 'Enter') {
this.loginSeed();
}
@ -295,6 +322,7 @@ class Login extends React.Component {
copyPassPhraseToClipboard() {
const passPhrase = this.state.randomSeed;
const textField = document.createElement('textarea');
textField.innerText = passPhrase;
document.body.appendChild(textField);
textField.select();
@ -319,7 +347,8 @@ class Login extends React.Component {
}
render() {
if ((this.state && this.state.display) || !this.props.Main) {
if ((this.state && this.state.display) ||
!this.props.Main) {
return LoginRender.call(this);
}

47
react/src/components/login/login.render.js

@ -56,15 +56,23 @@ const LoginRender = function () {
<div className={ this.state.activeLoginSection === 'login' && !this.state.nativeOnly ? 'show' : 'hide' }>
<h4 className="color-white">
{translate('INDEX.WELCOME_LOGIN')}
{ translate('INDEX.WELCOME_LOGIN') }
</h4>
<div className="form-group form-material floating col-sm-9 horizontal-padding-0">
<div className="form-group form-material floating col-sm-12 horizontal-padding-0">
<input
type={ this.state.seedInputVisibility ? 'text' : 'password' }
className="form-control"
type="password"
className={ !this.state.seedInputVisibility ? 'form-control' : 'hide' }
name="loginPassphrase"
onChange={ this.updateLoginPassPhraseInput }
onKeyDown={ (event) => this.handleKeydown(event) }/>
onKeyDown={ (event) => this.handleKeydown(event) }
value={ this.state.loginPassphrase } />
<textarea
className={ this.state.seedInputVisibility ? 'form-control' : 'hide' }
id="loginPassphrase"
name="loginPassphrase"
onChange={ this.updateLoginPassPhraseInput }
onKeyDown={ (event) => this.handleKeydown(event) }
value={ this.state.loginPassphrase }></textarea>
<i
className={ !this.state.seedInputVisibility ? 'seed-toggle fa fa-eye-slash' : 'seed-toggle fa fa-eye' }
onClick={ this.toggleSeedInputVisibility }></i>
@ -72,14 +80,13 @@ const LoginRender = function () {
className="floating-label"
htmlFor="inputPassword">{ translate('INDEX.WALLET_SEED') }</label>
</div>
<div className="form-group form-material floating col-sm-3 horizontal-padding-0 margin-top-20">
{ this.state.loginPassPhraseSeedType
?
this.state.loginPassPhraseSeedType
:
<div className="placeholder-label">Seed Type</div>
}
</div>
{ this.state.loginPassPhraseSeedType &&
<div
className="form-group form-material floating horizontal-padding-0 margin-top-20 seed-type-block"
style={{ width: `${this.state.loginPassPhraseSeedType.length * 8}px` }}>
<div className="placeholder-label">{ this.state.loginPassPhraseSeedType }</div>
</div>
}
<button
type="button"
className="btn btn-primary btn-block"
@ -200,14 +207,14 @@ const LoginRender = function () {
></textarea>
<button className="copy-floating-label"
htmlFor="walletseed"
onClick={ () => this.copyPassPhraseToClipboard() }>Copy</button>
onClick={ () => this.copyPassPhraseToClipboard() }>{ translate('INDEX.COPY') }</button>
<span className={ this.state.isCustomSeedWeak ? 'tooltiptext' : 'hide' }>
<strong>Weak seed!</strong><br /><br />
Your seed must contain:<br />
- at least 1 upper case letter<br />
- at least 1 digit<br />
- at least 1 special character<br />
- minimum 10 characters long
<strong>{ translate('INDEX.WEAK_SEED') }</strong><br /><br />
{ translate('INDEX.YOUR_SEED_MUST_CONTAIN') }<br />
{ translate('INDEX.YOUR_SEED_MUST_CONTAIN1') }<br />
{ translate('INDEX.YOUR_SEED_MUST_CONTAIN2') }<br />
{ translate('INDEX.YOUR_SEED_MUST_CONTAIN3') }<br />
{ translate('INDEX.YOUR_SEED_MUST_CONTAIN4') }
</span>
<label
className="floating-label"

24
react/src/components/login/login.scss

@ -56,8 +56,28 @@ textarea {
}
}
.placeholder-label {
color: #808080;
.seed-type-block {
position: absolute;
left: 100%;
min-width: 50px;
.placeholder-label {
border-radius: 4px;
padding: 3px;
background: #61BD4F;
color: #fff;
}
}
#loginPassphrase,
#wifkeysPassphraseTextarea,
input[type="password"] {
width: calc(100% - 35px);
}
#wifkeysPassphraseTextarea,
#loginPassphrase {
overflow: hidden;
margin-top: 5px;
}
.seed-tooltip {

2
react/src/components/overrides.scss

@ -74,7 +74,7 @@ body {
.seed-toggle {
position: absolute;
right: 0;
top: 0px;
top: 6px;
cursor: pointer;
cursor: hand;
}

2
react/src/reducers/addcoin.js

@ -10,7 +10,7 @@ export function AddCoin(state = {
case DISPLAY_ADDCOIN_MODAL:
return Object.assign({}, state, {
display: action.display,
isLogin: action.isLogin
isLogin: action.isLogin,
});
default:
return state;

5
react/src/reducers/toaster.js

@ -7,6 +7,7 @@ export function toaster(state = {
toasts: [],
}, action) {
if (state === null) state = { toasts: [] };
switch (action.type) {
case ADD_TOASTER_MESSAGE:
return {
@ -14,13 +15,13 @@ export function toaster(state = {
toasts: [
...state.toasts,
action
]
],
};
case REMOVE_TOASTER_MESSAGE:
// filter out the toastId that should be removed
return {
...state,
toasts: state.toasts.filter(t => t.toastId !== action.toastId)
toasts: state.toasts.filter(t => t.toastId !== action.toastId),
};
default:
return state;

80
react/src/translate/en.js

@ -1,6 +1,45 @@
export const _lang = {
'EN': {
'API': {
'ERROR_SM': 'error',
'ATOMIC_EXPLORER_ERR': 'Atomic Explorer error',
'ADDRESS_ALREADY_REG': 'Address already registered',
'COULDNT_COPY_ADDRESS': 'Couldn\'t copy address to clipboard',
'COULDNT_CREATE_SEED': 'Couldn\'t create new wallet seed',
'WALLETDAT_MISMATCH': 'Your wallet.dat is not matching the blockchain. Please resync from the scratch.',
'PEER_ADDED': 'Peer is added',
'ADDNODE_ALREADY_PENDING': 'Addnode connection was already pending',
'PEER_ALREADY_CONN': 'Peer was already connected',
'ADDNODE_NEEDS_COIN': 'Addnode needs active coin',
'PRIVKEY_IN_WALLET': 'Privkey already in wallet',
'ILLEGAL_PRIVKEY': 'Illegal privkey',
'IGUANA_INSTANCE_STOP': 'Iguana instance is stopped',
'NO_ACTIVE_COIN': 'No active coin',
},
'INDEX': {
'LOADING': 'Loading',
'ACTIVATING_SM': 'activating',
'DL_BLOCKS': 'downloading blocks',
'RESCAN_SM': 'rescanning blocks',
'REINDEX': 'reindexing blocks from disk',
'BLOCKS_SM': 'blocks',
'LOADING_BLOCKS': 'Loading blocks...it can take up to 15 min to load blocks',
'WEAK_SEED': 'Weak seed!',
'YOUR_SEED_MUST_CONTAIN': 'Your seed must contain:',
'YOUR_SEED_MUST_CONTAIN1': '- at least 1 upper case letter',
'YOUR_SEED_MUST_CONTAIN2': '- at least 1 digit',
'YOUR_SEED_MUST_CONTAIN3': '- at least 1 special character',
'YOUR_SEED_MUST_CONTAIN4': '- minimum 10 characters long',
'EXECUTE': 'Execute',
'TYPE_CLI_CMD': 'Type in CLI compatible cmd',
'COIN': 'Coin',
'UPDATE': 'Update',
'UI_UPDATE': 'UI update',
'CHECK_FOR_UPDATE': 'Check for update',
'UPDATE_UI_NOW': 'Update UI now',
'BINS_UPDATE': 'Binaries update',
'UPDATE_BINS_NOW': 'Update binaries now',
'CLI_SELECT_A_COIN': 'Select a coin and type in CLI compatible command',
'IMPORT': 'Import',
'CHECK': 'Check',
'VALIDATE': 'Validate',
@ -180,7 +219,7 @@ export const _lang = {
'ERRORS': 'Errors',
'ADD_NODE': 'Add Node',
'USE_THIS_SECTION': 'Use this section to check if the node IP you wish to add is allready active as peer of your coin:',
'SELECT_COIN': '-Select Coin-',
'SELECT_COIN': 'Select Coin',
'CHECK_NODES': 'Check Nodes',
'USE_THIS_SECTION_PEER': 'Use this section to add a peer IP to a selected coin:',
'WALLET_BACKUP': 'Wallet Backup',
@ -225,7 +264,10 @@ export const _lang = {
'ALREADY_ADDED': 'is already added',
'COIN_ALREADY_ADDED': 'Coin already added',
'IN': 'in',
'MODE': 'mode'
'MODE': 'mode',
'CRYPTO_CURRENCIES': 'Crypto Currencies',
'ASSETCHAINS': 'Assetchains',
'FIAT_CURRENCIES': 'Fiat Currencies'
},
'JUMBLR': {
'NOTICE': 'EXPERIMENTAL TEST VERSION ONLY',
@ -470,6 +512,40 @@ export const _lang = {
'ENTER_AN_ADDRESS': 'Enter an address',
'YOU_PICKED_OPT': 'You picked option',
'PLEASE_WAIT': 'Please wait'
},
'FIAT_CURRENCIES': {
'AUD': 'Australian Dollar (AUD)',
'BRL': 'Brazilian Real (BRL)',
'GBP': 'British Pound (GBP)',
'BGN': 'Bulgarian Lev (BGN)',
'CAD': 'Canadian Dollar (CAD)',
'HRK': 'Croatian Kuna (HRK)',
'CZK': 'Czech Koruna (CZK)',
'CNY': 'Chinese Yuan (CNY)',
'DKK': 'Danish Krone (DKK)',
'EUR': 'Euro (EUR)',
'HKD': 'Hong Kong Dollar (HKD)',
'HUF': 'Hungarian Forint (HUF)',
'INR': 'Indian Rupee (INR)',
'IDR': 'Indonesian Rupiah (IDR)',
'ILS': 'Israeli Shekel (ILS)',
'JPY': 'Japanese Yen (JPY)',
'KRW': 'Korean Won (KRW)',
'MYR': 'Malaysian Ringgit (MYR)',
'MXN': 'Mexican peso (MXN)',
'NZD': 'New Zealand Dollar (NZD)',
'NOK': 'Norwegian Krone (NOK)',
'PHP': 'Philippine Peso (PHP)',
'PLN': 'Polish Zloty (PLN)',
'RON': 'Romanian Leu (RON)',
'RUB': 'Russian Ruble (RUB)',
'SGD': 'Singapore Dollar (SGD)',
'ZAR': 'South African Rand (ZAR)',
'SEK': 'Swedish Krona (SEK)',
'CHF': 'Swiss Franc (CHF)',
'THB': 'Thai Baht (THB)',
'TRY': 'Turkish Lira (TRY)',
'USD': 'US Dollar (USD)'
}
}
};

9
react/src/util/sort.js

@ -1,5 +1,10 @@
export function sortByDate(data) {
return data.sort(function(a, b){
return new Date(b.blocktime || b.timestamp) - new Date(a.blocktime || a.timestamp);
return data.sort(function(a, b) {
if (a.timestamp &&
b.timestamp) {
return b.timestamp - a.timestamp;
} else {
return b.blocktime - a.blocktime;
}
});
}
Loading…
Cancel
Save