Browse Source

Merge pull request #149 from SuperNETorg/update

Update
all-modes
pbca26 8 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. 46
      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. 16
      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. 9
      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. 43
      react/src/components/dashboard/main/dashboard.scss
  30. 1
      react/src/components/dashboard/notifications/notifications.js
  31. 28
      react/src/components/dashboard/receiveCoin/receiveCoin.js
  32. 2
      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. 33
      react/src/components/dashboard/settings/settings.js
  36. 77
      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. 13
      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. 13
      react/src/components/dashboard/walletsProgress/walletsProgress.js
  46. 15
      react/src/components/dashboard/walletsProgress/walletsProgress.render.js
  47. 3
      react/src/components/dashboard/walletsTxInfo/walletsTxInfo.js
  48. 6
      react/src/components/dashboard/walletsTxInfo/walletsTxInfo.render.js
  49. 55
      react/src/components/login/login.js
  50. 43
      react/src/components/login/login.render.js
  51. 22
      react/src/components/login/login.scss
  52. 2
      react/src/components/overrides.scss
  53. 2
      react/src/reducers/addcoin.js
  54. 5
      react/src/reducers/toaster.js
  55. 80
      react/src/translate/en.js
  56. 7
      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 v0.2.0.2a-beta
-------------- --------------
front: UI:
- fixed native t to t bug that led to interest loss - fixed native t to t bug that led to interest loss
- added pending request(s) spinner - added pending request(s) spinner
- added missing native z_balance api call for z-addresses - 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 && if (json &&
json.error) { json.error) {
if (json.error === 'bitcoinrpc needs coin that is active') { 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 = { const modeToValue = {
'1': 'full', '1': 'full',
'0': 'basilisk', '0': 'basilisk',
'-1': 'native' '-1': 'native',
}; };
return dispatch => { return dispatch => {
@ -161,7 +161,7 @@ export function shepherdHerd(coin, mode, path, startupParams) {
'-daemon=0', '-daemon=0',
'-server', '-server',
`-ac_name=${coin}`, `-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_name': 'zcashd',
'ac_options': [ 'ac_options': [
'-daemon=0', '-daemon=0',
'-server=1' '-server=1',
] ]
}; };
} }
@ -180,7 +180,7 @@ export function shepherdHerd(coin, mode, path, startupParams) {
'ac_name': 'komodod', 'ac_name': 'komodod',
'ac_options': [ 'ac_options': [
'-daemon=0', '-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); console.log(error);
dispatch( dispatch(
triggerToaster( triggerToaster(
'Failed to get mode config', '_shepherdGetConfig',
'Error', 'Error',
'error' 'error'
) )
@ -334,7 +334,7 @@ export function iguanaActiveHandleBypass() {
console.log(error); console.log(error);
dispatch( dispatch(
triggerToaster( triggerToaster(
'Failed to iguanaActiveHandleBypass', 'iguanaActiveHandleBypass',
'Error', 'Error',
'error' 'error'
) )
@ -364,7 +364,7 @@ export function shepherdGetConfig(coin, mode, startupParams) {
console.log(error); console.log(error);
dispatch( dispatch(
triggerToaster( triggerToaster(
'Failed to get KMD config', 'shepherdGetConfig',
'Error', 'Error',
'error' 'error'
) )
@ -395,7 +395,7 @@ export function shepherdGetConfig(coin, mode, startupParams) {
console.log(error); console.log(error);
dispatch( dispatch(
triggerToaster( triggerToaster(
'Failed to get mode config', 'shepherdGetConfig',
'Error', 'Error',
'error' 'error'
) )

46
react/src/actions/actions/addressBalance.js

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

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

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

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

@ -8,6 +8,8 @@ import {
guiLogState guiLogState
} from './log'; } from './log';
// TODO: rewrite cache API to use POST
export function deleteCacheFile(_payload) { export function deleteCacheFile(_payload) {
return dispatch => { return dispatch => {
return fetch(`http://127.0.0.1:${Config.agamaPort}/shepherd/groom`, { 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 => { return dispatch => {
dispatch( dispatch(
triggerToaster( triggerToaster(
'Address already registered', translate('API.ADDRESS_ALREADY_REG'),
translate('TOASTR.WALLET_NOTIFICATION'), translate('TOASTR.WALLET_NOTIFICATION'),
'warning' 'warning'
) )

16
react/src/actions/actions/copyAddress.js

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

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

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

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

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

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

@ -16,11 +16,11 @@ export function sendNativeTx(coin, _payload) {
let payload; let payload;
let _apiMethod; let _apiMethod;
if (_payload.addressType === 'public' && if (_payload.addressType === 'public' && // transparent
_payload.sendTo.length !== 95) { _payload.sendTo.length !== 95) {
_apiMethod = 'sendtoaddress'; _apiMethod = 'sendtoaddress';
ajaxDataToHex = `["${_payload.sendTo}", ${Number(_payload.amount) - Number(_payload.fee)}]`; ajaxDataToHex = `["${_payload.sendTo}", ${Number(_payload.amount) - Number(_payload.fee)}]`;
} else { } else { // private
_apiMethod = 'z_sendmany'; _apiMethod = 'z_sendmany';
ajaxDataToHex = `["${_payload.sendFrom}", [{"address": "${_payload.sendTo}", "amount": ${Number(_payload.amount) - Number(_payload.fee)}}]]`; 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) { 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( dispatch(
triggerToaster( triggerToaster(
@ -138,7 +141,7 @@ export function sendNativeTx(coin, _payload) {
triggerToaster( triggerToaster(
true, true,
translate('TOASTR.WALLET_NOTIFICATION'), translate('TOASTR.WALLET_NOTIFICATION'),
'Your wallet.dat is not matching the blockchain. Please resync from the scratch.', translate('API.WALLETDAT_MISMATCH'),
'info', 'info',
false 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; }); const _response = response.text().then(function(text) { return text; });
return _response; return _response;
}) })
//.then(response => response.json())
.then(json => { .then(json => {
if (!json && if (!json &&
Config.cli.default) { Config.cli.default) {

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

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

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

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

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

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

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

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

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

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

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

@ -15,3 +15,13 @@
.float-none { .float-none {
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 { class AddCoinOptionsAC extends React.Component {
render() { render() {
return ( return (
<optgroup label="Assetchains"> <optgroup label={ translate('ADD_COIN.ASSETCHAINS') }>
<option value="BET|basilisk|native">BET (BET)</option> <option value="BET|basilisk|native">BET (BET)</option>
<option value="BOTS|basilisk|native">BOTS (BOTS)</option> <option value="BOTS|basilisk|native">BOTS (BOTS)</option>
<option value="CEAL|basilisk|native">CEAL NET (CEAL)</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 { class AddCoinOptionsACFiat extends React.Component {
render() { render() {
return ( return (
<optgroup label="Fiat Currencies"> <optgroup label={ translate('ADD_COIN.FIAT_CURRENCIES') }>
<option value="AUD|basilisk|native">Australian Dollar (AUD)</option> <option value="AUD|basilisk|native">Australian Dollar (AUD)</option>
<option value="BRL|basilisk|native">Brazilian Real (BRL)</option> <option value="BRL|basilisk|native">Brazilian Real (BRL)</option>
<option value="GBP|basilisk|native">British Pound (GBP)</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() { 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="ANC|full">AnonCoin (ANC)</option>
//<option value="MZC|full">MazaCoin (MZC)</option> //<option value="MZC|full">MazaCoin (MZC)</option>
//<option value="SYS|full">SysCoin (SYS)</option> //<option value="SYS|full">SysCoin (SYS)</option>
return ( return (
<optgroup label="Crypto Currencies"> <optgroup label={ translate('ADD_COIN.CRYPTO_CURRENCIES') }>
<option value="BTCD|full" className={ this.state.nativeOnly ? 'hide' : '' }>BitcoinDark (BTCD)</option> <option
<option value="BTC|full|basilisk" className={ this.state.nativeOnly ? 'hide' : '' }>Bitcoin (BTC)</option> value="BTCD|full"
<option value="BTM|full" className={ this.state.nativeOnly ? 'hide' : '' }>Bitmark (BTM)</option> className={ this.state.nativeOnly || isWindows ? 'hide' : '' }>BitcoinDark (BTCD)</option>
<option value="CARB|full" className={ this.state.nativeOnly ? 'hide' : '' }>Carboncoin (CARB)</option> <option
<option value="DGB|full" className={ this.state.nativeOnly ? 'hide' : '' }>Digibyte (DGB)</option> value="BTC|full"
<option value="DOGE|full" className={ this.state.nativeOnly ? 'hide' : '' }>Dogecoin (DOGE)</option> className={ this.state.nativeOnly || isWindows ? 'hide' : '' }>Bitcoin (BTC)</option>
<option value="FRK|full" className={ this.state.nativeOnly ? 'hide' : '' }>Franko (FRK)</option> <option
<option value="GAME|full" className={ this.state.nativeOnly ? 'hide' : '' }>Gamecredits (GAME)</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="KMD|basilisk|native">Komodo (KMD)</option>
<option value="LTC|full" className={ this.state.nativeOnly ? 'hide' : '' }>Litecoin (LTC)</option> <option
<option value="UNO|full" className={ this.state.nativeOnly ? 'hide' : '' }>Unobtanium (UNO)</option> value="LTC|full"
<option value="ZEC|full" className={ this.state.nativeOnly ? 'hide' : '' }>Zcash (ZEC)</option> className={ this.state.nativeOnly || isWindows ? 'hide' : '' }>Litecoin (LTC)</option>
<option value="ZET|full" className={ this.state.nativeOnly ? 'hide' : '' }>Zetacoin (ZET)</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> </optgroup>
); );
} }

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

@ -5,6 +5,8 @@ import AddCoinOptionsAC from '../addcoin/addcoinOptionsAC';
import AddCoinOptionsACFiat from '../addcoin/addcoinOptionsACFiat'; import AddCoinOptionsACFiat from '../addcoin/addcoinOptionsACFiat';
const CoinSelectorsRender = function(item, coin, i) { 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 ( return (
<div <div
className={ this.hasMoreThanOneCoin() ? 'multi' : 'single' } className={ this.hasMoreThanOneCoin() ? 'multi' : 'single' }
@ -18,9 +20,9 @@ const CoinSelectorsRender = function(item, coin, i) {
onChange={ (event) => this.updateSelectedCoin(event, i) } onChange={ (event) => this.updateSelectedCoin(event, i) }
autoFocus> autoFocus>
<option>{ translate('INDEX.SELECT') }</option> <option>{ translate('INDEX.SELECT') }</option>
<AddCoinOptionsCrypto /> <AddCoinOptionsCrypto appSettings={ this.props.Settings } />
<AddCoinOptionsAC /> <AddCoinOptionsAC appSettings={ this.props.Settings } />
<AddCoinOptionsACFiat /> <AddCoinOptionsACFiat appSettings={ this.props.Settings } />
</select> </select>
</div> </div>
</div> </div>
@ -33,8 +35,8 @@ const CoinSelectorsRender = function(item, coin, i) {
{ translate('INDEX.ACTIVATE_COIN') } { translate('INDEX.ACTIVATE_COIN') }
</button> </button>
</div> </div>
<div className="col-sm-12 text-center"> <div className="col-sm-11 text-center add-coin-modes">
<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={ 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 <input
type="radio" type="radio"
className="to-labelauty labelauty" className="to-labelauty labelauty"
@ -94,7 +96,9 @@ const CoinSelectorsRender = function(item, coin, i) {
</span> </span>
</label> </label>
</div> </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 <input
type="radio" type="radio"
className="to-labelauty labelauty" className="to-labelauty labelauty"

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

@ -1,53 +1,54 @@
// TODO: merge check functions
export function checkAC(coinVal) { export function checkAC(coinVal) {
if (coinVal == 'SUPERNET' || if (coinVal === 'SUPERNET' ||
coinVal == 'REVS' || coinVal === 'REVS' ||
coinVal == 'WLC' || coinVal === 'WLC' ||
coinVal == 'DEX' || coinVal === 'DEX' ||
coinVal == 'PANGEA' || coinVal === 'PANGEA' ||
coinVal == 'JUMBLR' || coinVal === 'JUMBLR' ||
coinVal == 'BET' || coinVal === 'BET' ||
coinVal == 'CRYPTO' || coinVal === 'CRYPTO' ||
coinVal == 'HODL' || coinVal === 'HODL' ||
coinVal == 'SHARK' || coinVal === 'SHARK' ||
coinVal == 'BOTS' || coinVal === 'BOTS' ||
coinVal == 'MGW' || coinVal === 'MGW' ||
coinVal == 'MVP' || coinVal === 'MVP' ||
coinVal == 'KV' || coinVal === 'KV' ||
coinVal == 'CEAL' || coinVal === 'CEAL' ||
coinVal == 'MESH' || coinVal === 'MESH' ||
coinVal == 'BTC' || coinVal === 'USD' ||
coinVal == 'USD' || coinVal === 'RON' ||
coinVal == 'RON' || coinVal === 'EUR' ||
coinVal == 'EUR' || coinVal === 'JPY' ||
coinVal == 'JPY' || coinVal === 'GBP' ||
coinVal == 'GBP' || coinVal === 'AUD' ||
coinVal == 'AUD' || coinVal === 'CAD' ||
coinVal == 'CAD' || coinVal === 'CHF' ||
coinVal == 'CHF' || coinVal === 'NZD' ||
coinVal == 'NZD' || coinVal === 'CNY' ||
coinVal == 'CNY' || coinVal === 'RUB' ||
coinVal == 'RUB' || coinVal === 'MXN' ||
coinVal == 'MXN' || coinVal === 'BRL' ||
coinVal == 'BRL' || coinVal === 'INR' ||
coinVal == 'INR' || coinVal === 'HKD' ||
coinVal == 'HKD' || coinVal === 'TRY' ||
coinVal == 'TRY' || coinVal === 'ZAR' ||
coinVal == 'ZAR' || coinVal === 'PLN' ||
coinVal == 'PLN' || coinVal === 'NOK' ||
coinVal == 'NOK' || coinVal === 'SEK' ||
coinVal == 'SEK' || coinVal === 'DKK' ||
coinVal == 'DKK' || coinVal === 'CZK' ||
coinVal == 'CZK' || coinVal === 'HUF' ||
coinVal == 'HUF' || coinVal === 'ILS' ||
coinVal == 'ILS' || coinVal === 'KRW' ||
coinVal == 'KRW' || coinVal === 'MYR' ||
coinVal == 'MYR' || coinVal === 'PHP' ||
coinVal == 'PHP' || coinVal === 'SGD' ||
coinVal == 'SGD' || coinVal === 'THB' ||
coinVal == 'THB' || coinVal === 'BGN' ||
coinVal == 'BGN' || coinVal === 'IDR' ||
coinVal == 'IDR' || coinVal === 'HRK') {
coinVal == 'HRK') {
return true; return true;
} else { } else {
return false; return false;
@ -130,7 +131,7 @@ export function checkCoinType(coin) {
} }
export function startCrypto(confpath, coin, mode) { export function startCrypto(confpath, coin, mode) {
var tmpinternval = 0, let tmpinternval = 0,
AddCoinData = {}, AddCoinData = {},
tmpPendValue = 1, // TODO: hook up to shepherd sysinfo tmpPendValue = 1, // TODO: hook up to shepherd sysinfo
tmpIguanaRPCAuth = `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`; tmpIguanaRPCAuth = `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`;
@ -141,7 +142,8 @@ export function startCrypto(confpath, coin, mode) {
tmpPendValue = parseInt(tmpPendValue) * 4; 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.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.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"}; 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) { export function startCurrencyAssetChain(confpath, coin, mode) {
var AddCoinDataPayload = {}, let AddCoinDataPayload = {},
tmpPendValue = 1, tmpPendValue = 1,
tmpIguanaRPCAuth = `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`; tmpIguanaRPCAuth = `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`;
@ -184,7 +186,7 @@ export function startCurrencyAssetChain(confpath, coin, mode) {
tmpPendValue = parseInt(tmpPendValue) * 4; tmpPendValue = parseInt(tmpPendValue) * 4;
} }
var _payloadVar = { let _payloadVar = {
'userpass': tmpIguanaRPCAuth, 'userpass': tmpIguanaRPCAuth,
'unitval': '20', 'unitval': '20',
'zcash': 1, 'zcash': 1,
@ -221,7 +223,7 @@ export function startCurrencyAssetChain(confpath, coin, mode) {
}; };
if (mode === '-1') { if (mode === '-1') {
var _payloadVarRegular = Object.assign({}, _payloadVar); let _payloadVarRegular = Object.assign({}, _payloadVar);
delete _payloadVarRegular.userpass; delete _payloadVarRegular.userpass;
_payloadVarRegular.RELAY = -1; _payloadVarRegular.RELAY = -1;
_payloadVarRegular.VALIDATE = 1; _payloadVarRegular.VALIDATE = 1;
@ -639,8 +641,8 @@ export function startCurrencyAssetChain(confpath, coin, mode) {
} }
export function startAssetChain(confpath, coin, mode, getSuppyOnly) { export function startAssetChain(confpath, coin, mode, getSuppyOnly) {
var tmpIguanaRPCAuth = `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`; let tmpIguanaRPCAuth = `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`;
var tmpPendValue; let tmpPendValue;
if (coin !== 'BTC' && if (coin !== 'BTC' &&
coin !== 'LTC' && coin !== 'LTC' &&

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

@ -11,30 +11,35 @@ class About extends React.Component {
<ul> <ul>
<li> <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. transaction performance.
</li> </li>
<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. while. Good transaction performance.
</li> </li>
<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. Mode' but provides advanced functionality.
</li> </li>
</ul> </ul>
Agama includes the following capabilities:
Agama includes the following capabilities:
<ul> <ul>
<li> <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. shapeshift-like service.
<a href="https://supernet.org/en/technology/whitepapers/easydex-a-practical-native-dex" target="_blank"> <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> </a>
</li> </li>
<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 have query information from a centralized
server. server.
</li> </li>
@ -47,7 +52,7 @@ class About extends React.Component {
<br/> <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>. 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. Then, report any bugs you encounter to our developers on the #testing-agama Slack channel.
Your help is greatly appreciated! Your help is greatly appreciated!
@ -59,7 +64,7 @@ class About extends React.Component {
and lower fees. and lower fees.
</li> </li>
<li> <li>
<span className="font-weight-600">NativeDEX</span> <span className="font-weight-600">BarterDEX</span>
</li> </li>
</ul> </ul>
</p> </p>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -49,7 +49,7 @@ export const AddressItemRender = function(address, type) {
return ( return (
<tr key={ address.address }> <tr key={ address.address }>
{ this.renderAddressActions(address.address, type) } { 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> <td>{ address.amount }</td>
{!this.isNativeMode() && {!this.isNativeMode() &&
<td>{ address.interest ? address.interest : 'N/A' }</td> <td>{ address.interest ? address.interest : 'N/A' }</td>

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

@ -103,7 +103,6 @@ class SendCoin extends React.Component {
} }
updateSocketsData(data) { updateSocketsData(data) {
console.log('sockets', data);
if (data && if (data &&
data.message && data.message &&
data.message.shepherd.iguanaAPI && data.message.shepherd.iguanaAPI &&
@ -149,20 +148,23 @@ class SendCoin extends React.Component {
timestamp, timestamp,
isReadyToUpdate, isReadyToUpdate,
waitUntilCallIsFinished = this.state.currentStackLength > 1 ? true : false; 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 || if (_cache[_coin][_sendFrom].refresh ||
this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].listunspent) { _cache[_coin][_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; refreshCacheData = _cache[_coin][_sendFrom].refresh || _cache[_coin][_sendFrom].listunspent;
timestamp = checkTimestamp(refreshCacheData.timestamp); timestamp = checkTimestamp(refreshCacheData.timestamp);
isReadyToUpdate = timestamp > 600 ? true : false; isReadyToUpdate = timestamp > 600 ? true : false;
} else { } else {
isReadyToUpdate = true; isReadyToUpdate = true;
} }
if (this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].refresh && if (_cache[_coin][_sendFrom].refresh &&
this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].refresh.data && _cache[_coin][_sendFrom].refresh.data &&
this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].refresh.data.error && _cache[_coin][_sendFrom].refresh.data.error &&
this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].refresh.data.error === 'request failed') { _cache[_coin][_sendFrom].refresh.data.error === 'request failed') {
timestamp = null; timestamp = null;
} }
@ -179,13 +181,15 @@ class SendCoin extends React.Component {
} }
renderAddressAmount(address) { renderAddressAmount(address) {
if (this.props.ActiveCoin.addresses && const _addresses = this.props.ActiveCoin.addresses;
this.props.ActiveCoin.addresses.public &&
this.props.ActiveCoin.addresses.public.length) { if (_addresses &&
for (let i = 0; i < this.props.ActiveCoin.addresses.public.length; i++) { _addresses.public &&
if (this.props.ActiveCoin.addresses.public[i].address === address) { _addresses.public.length) {
if (this.props.ActiveCoin.addresses.public[i].amount !== 'N/A') { for (let i = 0; i < _addresses.public.length; i++) {
return this.props.ActiveCoin.addresses.public[i].amount; 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) { renderAddressByType(type) {
if (this.props.ActiveCoin.addresses && const _addresses = this.props.ActiveCoin.addresses;
this.props.ActiveCoin.addresses[type] &&
this.props.ActiveCoin.addresses[type].length) { if (_addresses &&
_addresses[type] &&
_addresses[type].length) {
if (this.state.sendApiType) { if (this.state.sendApiType) {
const mainAddress = this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin]; const mainAddress = this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin];
const mainAddressAmount = this.renderAddressAmount(mainAddress); const mainAddressAmount = this.renderAddressAmount(mainAddress);
@ -206,27 +212,41 @@ class SendCoin extends React.Component {
<li <li
key={ mainAddress } key={ mainAddress }
className={ mainAddressAmount <= 0 ? 'hide' : '' }> 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> </li>
); );
} else { } else {
let items = []; 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++) { for (let i = 0; i < _addresses[type].length; i++) {
const address = this.props.ActiveCoin.addresses[type][i]; const address = _addresses[type][i].address;
let _amount = address.amount; let _amount = address.amount;
if (this.props.ActiveCoin.mode === 'basilisk' && if (this.props.ActiveCoin.mode === 'basilisk' &&
this.props.ActiveCoin.cache) { _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'; _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') { if (_amount !== 'N/A') {
items.push( items.push(
<li <li
key={ address.address } key={ address }
className={ _amount <= 0 ? 'hide' : '' }> 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> </li>
); );
} }
@ -242,18 +262,22 @@ class SendCoin extends React.Component {
renderSelectorCurrentLabel() { renderSelectorCurrentLabel() {
if (this.state.sendFrom) { if (this.state.sendFrom) {
let _amount; let _amount;
const _cache = this.props.ActiveCoin.cache;
const _coin = this.props.ActiveCoin.coin;
const _sendFrom = this.state.sendFrom;
if (this.state.sendFromAmount === 0 && if (this.state.sendFromAmount === 0 &&
this.props.ActiveCoin.mode === 'basilisk' && this.props.ActiveCoin.mode === 'basilisk' &&
this.props.ActiveCoin.cache) { _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'; _amount = _cache[_coin][_sendFrom].getbalance.data && _cache[_coin][_sendFrom].getbalance.data.balance ? _cache[_coin][_sendFrom].getbalance.data.balance : 'N/A';
} else { } else {
_amount = this.state.sendFromAmount; _amount = this.state.sendFromAmount;
} }
return ( return (
<span> <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> </span>
); );
} else if (this.state.sendApiType) { } else if (this.state.sendApiType) {
@ -262,7 +286,8 @@ class SendCoin extends React.Component {
return ( return (
<span> <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> </span>
); );
} else { } else {
@ -278,7 +303,7 @@ class SendCoin extends React.Component {
<button <button
type="button" type="button"
className="btn dropdown-toggle btn-info" 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 }> onClick={ this.openDropMenu }>
<span className="filter-option pull-left"> <span className="filter-option pull-left">
{ this.renderSelectorCurrentLabel() }&nbsp;&nbsp; { this.renderSelectorCurrentLabel() }&nbsp;&nbsp;
@ -290,7 +315,10 @@ class SendCoin extends React.Component {
<div className="dropdown-menu open"> <div className="dropdown-menu open">
<ul className="dropdown-menu inner"> <ul className="dropdown-menu inner">
<li className="selected"> <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> </li>
{ this.renderAddressByType('public') } { this.renderAddressByType('public') }
</ul> </ul>
@ -307,10 +335,12 @@ class SendCoin extends React.Component {
updateAddressSelection(address, type, amount) { updateAddressSelection(address, type, amount) {
let _sendFromAmount = amount ? amount : this.props.ActiveCoin.addresses[type][address].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' && if (this.props.ActiveCoin.mode === 'basilisk' &&
this.props.ActiveCoin.cache) { 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, { this.setState(Object.assign({}, this.state, {
@ -403,6 +433,7 @@ class SendCoin extends React.Component {
'utxos': utxoSet 'utxos': utxoSet
}; };
// TODO: es arrows
iguanaUTXORawTX(sendData, Store.dispatch) iguanaUTXORawTX(sendData, Store.dispatch)
.then(function(json) { .then(function(json) {
if (json.result === 'success' && if (json.result === 'success' &&
@ -559,7 +590,7 @@ class SendCoin extends React.Component {
Store.dispatch(sendToAddressStateAlt(json)); Store.dispatch(sendToAddressStateAlt(json));
Store.dispatch( Store.dispatch(
triggerToaster( triggerToaster(
translate('TOASTR.SIGNED_TX_GENERATED_FAIL') + '.', `${translate('TOASTR.SIGNED_TX_GENERATED_FAIL')}.`,
translate('TOASTR.WALLET_NOTIFICATION'), translate('TOASTR.WALLET_NOTIFICATION'),
'error' 'error'
) )
@ -602,17 +633,19 @@ class SendCoin extends React.Component {
} else if (key === 'rawtx') { } else if (key === 'rawtx') {
return this.renderSignedTx(true); return this.renderSignedTx(true);
} else if (key === 'complete' || key === 'completed' || key === 'result') { } else if (key === 'complete' || key === 'completed' || key === 'result') {
if (this.props.ActiveCoin.lastSendToResponse[key] === true || const _lastSendToResponse = this.props.ActiveCoin.lastSendToResponse;
this.props.ActiveCoin.lastSendToResponse[key] === 'success') {
if (_lastSendToResponse[key] === true ||
_lastSendToResponse[key] === 'success') {
return ( 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 { } else {
if (key === 'result' && if (key === 'result' &&
this.props.ActiveCoin.lastSendToResponse.result && _lastSendToResponse.result &&
typeof this.props.ActiveCoin.lastSendToResponse.result !== 'object') { typeof _lastSendToResponse.result !== 'object') {
return ( return (
<span>{ this.props.ActiveCoin.lastSendToResponse.result }</span> <span>{ _lastSendToResponse.result }</span>
); );
} else { } else {
return ( return (
@ -621,17 +654,19 @@ class SendCoin extends React.Component {
} }
} }
} else if (key === 'error') { } 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 ( return (
<span>{ JSON.stringify(this.props.ActiveCoin.lastSendToResponse[key], null, '\t') }</span> <span>{ JSON.stringify(_lastSendToResponse[key], null, '\t') }</span>
); );
} else { } else {
return ( return (
<span className="label label-danger">{ this.props.ActiveCoin.lastSendToResponse[key] }</span> <span className="label label-danger">{ _lastSendToResponse[key] }</span>
); );
} }
} else if (key === 'sendrawtransaction') { } else if (key === 'sendrawtransaction') {
if (this.props.ActiveCoin.lastSendToResponse[key] === 'success') { if (_lastSendToResponse[key] === 'success') {
return ( return (
<span className="label label-success">true</span> <span className="label label-success">true</span>
); );
@ -642,7 +677,7 @@ class SendCoin extends React.Component {
} }
} else if (key === 'txid' || key === 'sent') { } else if (key === 'txid' || key === 'sent') {
return ( return (
<span>{ this.props.ActiveCoin.lastSendToResponse[key] }</span> <span>{ _lastSendToResponse[key] }</span>
); );
} else if (key === 'tag') { } else if (key === 'tag') {
return null; return null;
@ -653,6 +688,7 @@ class SendCoin extends React.Component {
return SendCoinResponseRender.call(this); return SendCoinResponseRender.call(this);
} }
// experimental, ask @kolo for details if required
getOAdress() { getOAdress() {
resolveOpenAliasAddress(this.state.sendToOA) resolveOpenAliasAddress(this.state.sendToOA)
.then(function(json) { .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 /> { refreshCacheData ? refreshCacheData.data && refreshCacheData.data.length : translate('SEND.PRESS_UPDATE_BTN') }<br />
<div className={ !timestamp ? 'hide' : '' }> <div className={ !timestamp ? 'hide' : '' }>
{ translate('SEND.LAST_UPDATED') } @ { 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>
<div className={ isReadyToUpdate ? 'hide' : '' }> <div className={ isReadyToUpdate ? 'hide' : '' }>
{ translate('SEND.NEXT_UPDATE_IN') } { secondsElapsedToString(600 - timestamp) }s { 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={ '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 <div
className="progress-bar progress-bar-striped active progress-bar-indicating progress-bar-success font-size-80-percent" 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 } { translate('SEND.PROCESSING_REQ') }: { this.state.currentStackLength } / { this.state.totalStackLength }
</div> </div>
</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') } className={ 'margin-top-10 ' + (isReadyToUpdate ? 'btn btn-primary waves-effect waves-light' : 'hide') }
onClick={ this._fetchNewUTXOData } onClick={ this._fetchNewUTXOData }
disabled={ waitUntilCallIsFinished }> disabled={ waitUntilCallIsFinished }>
{ waitUntilCallIsFinished ? translate('SEND.LOCKED_PLEASE_WAIT') + '...' : translate('SEND.UPDATE') } { waitUntilCallIsFinished ? `${translate('SEND.LOCKED_PLEASE_WAIT')}...` : translate('SEND.UPDATE') }
</button> </button>
</div> </div>
); );
@ -257,7 +259,11 @@ export const SendCoinRender = function () {
onChange={ this.updateInput } /> onChange={ this.updateInput } />
</div> </div>
<div className="col-lg-12"> <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>
<div className={ this.state.sendApiType ? 'hide' : 'col-lg-10 margin-top-30' }> <div className={ this.state.sendApiType ? 'hide' : 'col-lg-10 margin-top-30' }>
<span className="pointer"> <span className="pointer">
@ -283,7 +289,8 @@ export const SendCoinRender = function () {
className="btn btn-primary waves-effect waves-light pull-right" className="btn btn-primary waves-effect waves-light pull-right"
onClick={ () => this.changeSendCoinStep(1) } onClick={ () => this.changeSendCoinStep(1) }
disabled={ !this.state.sendFrom || !this.state.sendTo || !this.state.amount }> 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> </button>
</div> </div>
</div> </div>
@ -365,7 +372,7 @@ export const SendCoinRender = function () {
className="btn btn-primary" className="btn btn-primary"
onClick={ () => this.changeSendCoinStep(0) } onClick={ () => this.changeSendCoinStep(0) }
disabled={ this.state.utxoMethodInProgress }> 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> </button>
</div> </div>
</div> </div>

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

@ -59,6 +59,8 @@ class Settings extends React.Component {
updateBins: null, updateBins: null,
updateLog: [], updateLog: [],
updateProgressPatch: null, updateProgressPatch: null,
wifkeysPassphrase: '',
trimPassphraseTimer: null,
}; };
this.exportWifKeys = this.exportWifKeys.bind(this); this.exportWifKeys = this.exportWifKeys.bind(this);
this.updateInput = this.updateInput.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) { updateSocketsData(data) {
if (data && if (data &&
data.msg && data.msg &&
@ -404,10 +416,31 @@ class Settings extends React.Component {
} }
updateInput(e) { updateInput(e) {
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({ this.setState({
[e.target.name]: e.target.value, [e.target.name]: e.target.value,
}); });
} }
}
renderDebugLogData() { renderDebugLogData() {
if (this.props.Settings.debugLog) { if (this.props.Settings.debugLog) {

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

@ -12,38 +12,38 @@ export const AppUpdateTabRender = function() {
onClick={ () => this.openTab('AppUpdate', 10) }> onClick={ () => this.openTab('AppUpdate', 10) }>
<div className="panel-heading"> <div className="panel-heading">
<a className={ this.state.activeTab === 10 ? 'panel-title' : 'panel-title collapsed' }> <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> </a>
</div> </div>
<div <div
className={ this.state.activeTab === 10 ? 'panel-collapse collapse in' : 'panel-collapse collapse' } 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="panel-body">
<div className="col-sm-4 padding-top-15"> <div className="col-sm-4 padding-top-15">
<h5>UI update</h5> <h5>{ translate('INDEX.UI_UPDATE') }</h5>
<div className="padding-top-15"> <div className="padding-top-15">
<button <button
type="button" type="button"
className="btn btn-primary waves-effect waves-light" 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 <button
type="button" type="button"
className="btn btn-primary waves-effect waves-light margin-left-20" className="btn btn-primary waves-effect waves-light margin-left-20"
onClick={ this._updateUIPromise } onClick={ this._updateUIPromise }
disabled={ !this.state.updatePatch }>Update UI now</button> disabled={ !this.state.updatePatch }>{ translate('INDEX.UPDATE_UI_NOW') }</button>
</div> </div>
</div> </div>
<div className="col-sm-4 padding-top-15 hide"> <div className="col-sm-4 padding-top-15 hide">
<h5>Binaries update</h5> <h5>{ translate('INDEX.BINS_UPDATE') }</h5>
<div className="padding-top-15"> <div className="padding-top-15">
<button <button
type="button" type="button"
className="btn btn-primary waves-effect waves-light" 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 <button
type="button" type="button"
className="btn btn-primary waves-effect waves-light margin-left-20" 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> </div>
<div className="col-sm-12 padding-top-15"> <div className="col-sm-12 padding-top-15">
@ -68,7 +68,7 @@ export const AppInfoTabRender = function() {
</div> </div>
<div <div
className={ this.state.activeTab === 8 ? 'panel-collapse collapse in' : 'panel-collapse collapse' } 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="panel-body">
<div className="col-sm-12 padding-top-15"> <div className="col-sm-12 padding-top-15">
<div className="row"> <div className="row">
@ -159,7 +159,7 @@ export const SettingsRender = function() {
<div <div
id="WalletInfo" id="WalletInfo"
onClick={ () => this.openTab('WalletInfo', 0) } onClick={ () => this.openTab('WalletInfo', 0) }
className={ this.state.nativeOnly ? 'hide' : 'panel' }> className={ this.state.nativeOnly ? 'panel hide' : 'panel' }>
<div className="panel-heading"> <div className="panel-heading">
<a className={ this.state.activeTab === 0 ? 'panel-title' : 'panel-title collapsed' }> <a className={ this.state.activeTab === 0 ? 'panel-title' : 'panel-title collapsed' }>
<i className="icon md-balance-wallet"></i>{ translate('INDEX.WALLET_INFO') } <i className="icon md-balance-wallet"></i>{ translate('INDEX.WALLET_INFO') }
@ -167,7 +167,7 @@ export const SettingsRender = function() {
</div> </div>
<div <div
className={ this.state.activeTab === 0 ? 'panel-collapse collapse in' : 'panel-collapse collapse' } 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"> <div className="panel-body">
<table className="table"> <table className="table">
<thead> <thead>
@ -210,7 +210,7 @@ export const SettingsRender = function() {
<div <div
id="AddNodeforCoin" id="AddNodeforCoin"
onClick={ () => this.openTab('AddNodeforCoin', 1) } onClick={ () => this.openTab('AddNodeforCoin', 1) }
className={ this.state.nativeOnly ? 'hide' : 'panel' }> className={ this.state.nativeOnly ? 'panel hide' : 'panel' }>
<div className="panel-heading"> <div className="panel-heading">
<a className={ this.state.activeTab === 1 ? 'panel-title' : 'panel-title collapsed' }> <a className={ this.state.activeTab === 1 ? 'panel-title' : 'panel-title collapsed' }>
<i className="icon md-plus-square"></i>{ translate('INDEX.ADD_NODE') } <i className="icon md-plus-square"></i>{ translate('INDEX.ADD_NODE') }
@ -218,7 +218,7 @@ export const SettingsRender = function() {
</div> </div>
<div <div
className={ this.state.activeTab === 1 ? 'panel-collapse collapse in' : 'panel-collapse collapse' } 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="panel-body">
<div className="row"> <div className="row">
<div className="col-sm-6"> <div className="col-sm-6">
@ -296,7 +296,7 @@ export const SettingsRender = function() {
<div <div
id="DumpWallet" id="DumpWallet"
onClick={ () => this.openTab('DumpWallet', 2) } onClick={ () => this.openTab('DumpWallet', 2) }
className={ this.state.nativeOnly ? 'hide' : 'panel' }> className={ this.state.nativeOnly ? 'panel hide' : 'panel' }>
<div className="panel-heading"> <div className="panel-heading">
<a className={ this.state.activeTab === 2 ? 'panel-title' : 'panel-title collapsed' }> <a className={ this.state.activeTab === 2 ? 'panel-title' : 'panel-title collapsed' }>
<i className="icon wb-briefcase"></i>{ translate('INDEX.WALLET_BACKUP') } <i className="icon wb-briefcase"></i>{ translate('INDEX.WALLET_BACKUP') }
@ -304,7 +304,7 @@ export const SettingsRender = function() {
</div> </div>
<div <div
className={ this.state.activeTab === 2 ? 'panel-collapse collapse in' : 'panel-collapse collapse' } 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 className="panel-body">Wallet Backup section to be updated soon.</div>
</div> </div>
</div> </div>
@ -312,7 +312,7 @@ export const SettingsRender = function() {
<div <div
id="FiatCurrencySettings" id="FiatCurrencySettings"
onClick={ () => this.openTab('FiatCurrencySettings', 3) } onClick={ () => this.openTab('FiatCurrencySettings', 3) }
className={ this.state.nativeOnly ? 'hide' : 'panel' }> className={ this.state.nativeOnly ? 'panel hide' : 'panel' }>
<div className="panel-heading"> <div className="panel-heading">
<a className={ this.state.activeTab === 3 ? 'panel-title' : 'panel-title collapsed' }> <a className={ this.state.activeTab === 3 ? 'panel-title' : 'panel-title collapsed' }>
<i className="icon fa-money"></i>{ translate('INDEX.FIAT_CURRENCY') } <i className="icon fa-money"></i>{ translate('INDEX.FIAT_CURRENCY') }
@ -320,7 +320,7 @@ export const SettingsRender = function() {
</div> </div>
<div <div
className={ this.state.activeTab === 3 ? 'panel-collapse collapse in' : 'panel-collapse collapse' } 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 className="panel-body">Fiat currency settings section to be updated soon.</div>
</div> </div>
</div> </div>
@ -328,7 +328,7 @@ export const SettingsRender = function() {
<div <div
id="ExportKeys" id="ExportKeys"
onClick={ () => this.openTab('ExportKeys', 4) } onClick={ () => this.openTab('ExportKeys', 4) }
className={ this.state.nativeOnly ? 'hide' : 'panel' }> className={ this.state.nativeOnly ? 'panel hide' : 'panel' }>
<div className="panel-heading"> <div className="panel-heading">
<a className={ this.state.activeTab === 4 ? 'panel-title' : 'panel-title collapsed' }> <a className={ this.state.activeTab === 4 ? 'panel-title' : 'panel-title collapsed' }>
<i className="icon md-key"></i>{ translate('INDEX.EXPORT_KEYS') } <i className="icon md-key"></i>{ translate('INDEX.EXPORT_KEYS') }
@ -336,7 +336,7 @@ export const SettingsRender = function() {
</div> </div>
<div <div
className={ this.state.activeTab === 4 ? 'panel-collapse collapse in' : 'panel-collapse collapse' } 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"> <div className="panel-body">
<p> <p>
<div className="padding-bottom-20">{ this.renderLB('INDEX.ONLY_ACTIVE_WIF_KEYS') }</div> <div className="padding-bottom-20">{ this.renderLB('INDEX.ONLY_ACTIVE_WIF_KEYS') }</div>
@ -355,11 +355,18 @@ export const SettingsRender = function() {
autoComplete="off"> autoComplete="off">
<div className="form-group form-material floating"> <div className="form-group form-material floating">
<input <input
type={ this.state.seedInputVisibility ? 'text' : 'password' } type="password"
className="form-control" className={ !this.state.seedInputVisibility ? 'form-control' : 'hide' }
name="wifkeysPassphrase" name="wifkeysPassphrase"
id="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 <i
className={ !this.state.seedInputVisibility ? 'seed-toggle fa fa-eye-slash' : 'seed-toggle fa fa-eye' } className={ !this.state.seedInputVisibility ? 'seed-toggle fa fa-eye-slash' : 'seed-toggle fa fa-eye' }
onClick={ this.toggleSeedInputVisibility }></i> onClick={ this.toggleSeedInputVisibility }></i>
@ -398,7 +405,7 @@ export const SettingsRender = function() {
<div <div
id="ImportKeys" id="ImportKeys"
onClick={ () => this.openTab('ImportKeys', 5) } onClick={ () => this.openTab('ImportKeys', 5) }
className={ this.state.nativeOnly ? 'hide' : 'panel' }> className={ this.state.nativeOnly ? 'panel hide' : 'panel' }>
<div className="panel-heading"> <div className="panel-heading">
<a className={ this.state.activeTab === 5 ? 'panel-title' : 'panel-title collapsed' }> <a className={ this.state.activeTab === 5 ? 'panel-title' : 'panel-title collapsed' }>
<i className="icon md-key"></i>{ translate('INDEX.IMPORT_KEYS') } <i className="icon md-key"></i>{ translate('INDEX.IMPORT_KEYS') }
@ -406,16 +413,16 @@ export const SettingsRender = function() {
</div> </div>
<div <div
className={ this.state.activeTab === 5 ? 'panel-collapse collapse in' : 'panel-collapse collapse' } 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"> <div className="panel-body">
<p>
<div>{ translate('INDEX.IMPORT_KEYS_DESC_P1') }</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_P2') }</div><br/>
<div>{ translate('INDEX.IMPORT_KEYS_DESC_P3') }</div><br/> <div>{ translate('INDEX.IMPORT_KEYS_DESC_P3') }</div><br/>
<div>
<strong> <strong>
<i>{ translate('INDEX.PLEASE_KEEP_KEYS_SAFE') }</i> <i>{ translate('INDEX.PLEASE_KEEP_KEYS_SAFE') }</i>
</strong> </strong>
</p> </div>
<div className="col-sm-12"></div> <div className="col-sm-12"></div>
<form <form
className="wifkeys-import-form" className="wifkeys-import-form"
@ -455,7 +462,7 @@ export const SettingsRender = function() {
</div> </div>
<div <div
className={ this.state.activeTab === 6 ? 'panel-collapse collapse in' : 'panel-collapse collapse' } 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"> <div className="panel-body">
<p>{ translate('INDEX.DEBUG_LOG_DESC') }</p> <p>{ translate('INDEX.DEBUG_LOG_DESC') }</p>
<div className="col-sm-12"></div> <div className="col-sm-12"></div>
@ -514,7 +521,7 @@ export const SettingsRender = function() {
</div> </div>
<div <div
className={ this.state.activeTab === 7 ? 'panel-collapse collapse in' : 'panel-collapse collapse' } 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"> <div className="panel-body">
<p> <p>
<strong>{ translate('SETTINGS.CONFIG_RESTART_REQUIRED') }</strong> <strong>{ translate('SETTINGS.CONFIG_RESTART_REQUIRED') }</strong>
@ -540,7 +547,7 @@ export const SettingsRender = function() {
<div <div
id="Cli" id="Cli"
onClick={ () => this.openTab('Cli', 9) } 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"> <div className="panel-heading">
<a className={ this.state.activeTab === 9 ? 'panel-title' : 'panel-title collapsed' }> <a className={ this.state.activeTab === 9 ? 'panel-title' : 'panel-title collapsed' }>
<i className="icon fa-code"></i> CLI <i className="icon fa-code"></i> CLI
@ -548,9 +555,9 @@ export const SettingsRender = function() {
</div> </div>
<div <div
className={ this.state.activeTab === 9 ? 'panel-collapse collapse in' : 'panel-collapse collapse' } 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"> <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> <div className="col-sm-12"></div>
<form <form
className="execute-cli-cmd-form" className="execute-cli-cmd-form"
@ -563,12 +570,12 @@ export const SettingsRender = function() {
name="cliCoin" name="cliCoin"
id="settingsCliOptions" id="settingsCliOptions"
onChange={ this.updateInput }> onChange={ this.updateInput }>
<option value="">Select coin</option> <option value="">{ translate('INDEX.CLI_SELECT_A_COIN') }</option>
{ this.renderActiveCoinsList('native') } { this.renderActiveCoinsList('native') }
</select> </select>
<label <label
className="floating-label" className="floating-label"
htmlFor="settingsDelectDebugLogOptions">Coin</label> htmlFor="settingsDelectDebugLogOptions">{ translate('INDEX.COIN') }</label>
</div> </div>
<div className="form-group form-material floating"> <div className="form-group form-material floating">
<textarea <textarea
@ -580,14 +587,14 @@ export const SettingsRender = function() {
onChange={ this.updateInput }></textarea> onChange={ this.updateInput }></textarea>
<label <label
className="floating-label" className="floating-label"
htmlFor="readDebugLogLines">Type in CLI compatible cmd</label> htmlFor="readDebugLogLines">{ translate('INDEX.TYPE_CLI_CMD') }</label>
</div> </div>
<div className="col-sm-12 col-xs-12 text-align-center"> <div className="col-sm-12 col-xs-12 text-align-center">
<button <button
type="button" type="button"
className="btn btn-primary waves-effect waves-light" className="btn btn-primary waves-effect waves-light"
disabled={ !this.state.cliCoin || !this.state.cliCmd } disabled={ !this.state.cliCoin || !this.state.cliCmd }
onClick={ () => this.execCliCmd() }>Execute</button> onClick={ () => this.execCliCmd() }>{ translate('INDEX.EXECUTE') }</button>
</div> </div>
<div className="col-sm-12 col-xs-12 text-align-left"> <div className="col-sm-12 col-xs-12 text-align-left">
<div className="padding-top-40 padding-bottom-20 horizontal-padding-0"> <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 React from 'react';
import { getCoinTitle } from '../../../util/coinHelper'; import { getCoinTitle } from '../../../util/coinHelper';
import { translate } from '../../../translate/translate';
import { import {
stopInterval, stopInterval,
addCoin, addCoin,
@ -19,7 +20,7 @@ class SyncOnly extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
autoRestartedForks: {} autoRestartedForks: {},
}; };
this.closeSyncOnlyModal = this.closeSyncOnlyModal.bind(this); this.closeSyncOnlyModal = this.closeSyncOnlyModal.bind(this);
} }
@ -141,7 +142,7 @@ class SyncOnly extends React.Component {
return items; return items;
} else { } else {
return ( 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>
<div <div
className={ 'font-size-80-percent ' + (this.isFullySynced(fork) ? 'hide' : 'progress-bar progress-bar-info progress-bar-striped active') } 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 }% { translate('INDEX.BUNDLES') } { fork.bundles }%
</div> </div>
</div> </div>
@ -23,21 +23,21 @@ export const ProgressRender = function (fork) {
<div className="progress progress-sm"> <div className="progress progress-sm">
<div <div
className="progress-bar progress-bar-warning progress-bar-striped active font-size-80-percent" 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 }% utxo { fork.utxo }%
</div> </div>
</div> </div>
<div className="progress progress-sm"> <div className="progress progress-sm">
<div <div
className="progress-bar progress-bar-danger progress-bar-striped active font-size-80-percent" 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 }% { translate('INDEX.BALANCES') } { fork.balances }%
</div> </div>
</div> </div>
<div className="progress progress-sm"> <div className="progress progress-sm">
<div <div
className="progress-bar progress-bar-success progress-bar-striped active font-size-80-percent" 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 }% { translate('INDEX.VALIDATED') } { fork.validated }%
</div> </div>
</div> </div>
@ -57,7 +57,9 @@ export const ForkItemRender = function (forkInfo, port) {
src={ `assets/images/cryptologo/${this.renderCoinName(forkInfo.registry.coin).logo}.png` } src={ `assets/images/cryptologo/${this.renderCoinName(forkInfo.registry.coin).logo}.png` }
alt={ forkInfo.registry.coin }/> alt={ forkInfo.registry.coin }/>
<span className="badge up badge-success margin-bottom-5">Full</span> <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"> <div className="margin-top-10">
<span <span
className="btn btn-primary" className="btn btn-primary"

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

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

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

@ -7,23 +7,13 @@ const WalletsBalanceRender = function() {
<div className="col-xs-12"> <div className="col-xs-12">
<div className={ this.isFullMode() && !this.isFullySynced() ? 'col-xs-12' : 'col-xs-12 hide' }> <div className={ this.isFullMode() && !this.isFullySynced() ? 'col-xs-12' : 'col-xs-12 hide' }>
<div className="alert alert-info alert-dismissible"> <div className="alert alert-info alert-dismissible">
<button
className="close"
type="button">
<span>×</span>
</button>
<h4>{ translate('INDEX.ACTIVATING_WALLET_RT') }</h4> <h4>{ translate('INDEX.ACTIVATING_WALLET_RT') }</h4>
<p>{ translate('INDEX.IGUANA_FULL_MODE_SYNC_P1') }</p> <p>{ translate('INDEX.IGUANA_FULL_MODE_SYNC_P1') }</p>
<p>{ translate('INDEX.IGUANA_FULL_MODE_SYNC_P2') }</p> <p>{ translate('INDEX.IGUANA_FULL_MODE_SYNC_P2') }</p>
<p className="font-weight-600">{ this.renderLB('INDEX.IGUANA_FULL_MODE_SYNC_P3') }</p> <p className="font-weight-600">{ this.renderLB('INDEX.IGUANA_FULL_MODE_SYNC_P3') }</p>
</div> </div>
<div className="alert alert-info alert-dismissible"> <div className="alert alert-info alert-dismissible hide">
<button
className="close"
type="button">
<span>×</span>
</button>
<h4>{ translate('INDEX.FETCHING_COIN_DATA') }</h4> <h4>{ translate('INDEX.FETCHING_COIN_DATA') }</h4>
<p>{ translate('INDEX.IGUANA_FULL_MODE_SYNC_P1') }</p> <p>{ translate('INDEX.IGUANA_FULL_MODE_SYNC_P1') }</p>
<p>{ translate('INDEX.IGUANA_FULL_MODE_SYNC_P2') }</p> <p>{ translate('INDEX.IGUANA_FULL_MODE_SYNC_P2') }</p>
@ -32,7 +22,6 @@ const WalletsBalanceRender = function() {
</div> </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={ 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 widget-shadow">
<div className="widget-content"> <div className="widget-content">
<div className="padding-20 padding-top-10"> <div className="padding-20 padding-top-10">

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

@ -32,7 +32,7 @@ import {
import { SocketProvider } from 'socket.io-react'; import { SocketProvider } from 'socket.io-react';
import io from 'socket.io-client'; 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 { class WalletsData extends React.Component {
constructor(props) { constructor(props) {
@ -401,22 +401,30 @@ class WalletsData extends React.Component {
} }
renderAddressByType(type) { renderAddressByType(type) {
if (this.props.ActiveCoin.addresses && const _addresses = this.props.ActiveCoin.addresses;
this.props.ActiveCoin.addresses[type] &&
this.props.ActiveCoin.addresses[type].length) { if (_addresses &&
_addresses[type] &&
_addresses[type].length) {
let items = []; 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++) { for (let i = 0; i < _addresses[type].length; i++) {
const address = this.props.ActiveCoin.addresses[type][i]; const address = _addresses[type][i].address;
let _amount = address.amount; let _amount = address.amount;
if (this.props.ActiveCoin.mode === 'basilisk') { 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( items.push(
<li key={address.address}> <li key={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> <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> </li>
); );
} }
@ -435,14 +443,19 @@ class WalletsData extends React.Component {
renderAddressAmount() { renderAddressAmount() {
if (this.hasPublicAdresses()) { if (this.hasPublicAdresses()) {
for (let i = 0; i < this.props.ActiveCoin.addresses.public.length; i++) { const _addresses = this.props.ActiveCoin.addresses;
if (this.props.ActiveCoin.addresses.public[i].address === this.state.currentAddress) { const _cache = this.props.ActiveCoin.cache;
if (this.props.ActiveCoin.addresses.public[i].amount && const _coin = this.props.ActiveCoin.coin;
this.props.ActiveCoin.addresses.public[i].amount !== 'N/A') {
return this.props.ActiveCoin.addresses.public[i].amount; 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 { } else {
const address = this.props.ActiveCoin.addresses.public[i].address; const address = _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 _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; return _amount;
} }
} }
@ -456,7 +469,8 @@ class WalletsData extends React.Component {
if (this.state.currentAddress) { if (this.state.currentAddress) {
return ( return (
<span> <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> </span>
); );
} else { } 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 WalletsCacheData from '../walletsCacheData/walletsCacheData';
import { secondsToString } from '../../../util/time'; import { secondsToString } from '../../../util/time';
// TODO: clean basilisk dropdown menu
export const PaginationItemRender = function(i) { export const PaginationItemRender = function(i) {
return ( return (
<li <li
@ -81,7 +83,7 @@ export const TxHistoryListRender = function(tx, index) {
<button <button
type="button" type="button"
className="btn btn-xs white btn-info waves-effect waves-light btn-kmdtxid" 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> <i className="icon fa-search"></i>
</button> </button>
</td> </td>

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

@ -4,11 +4,6 @@ import { translate } from '../../../translate/translate';
const WalletsNativeAlertRender = function() { const WalletsNativeAlertRender = function() {
return ( return (
<div className="alert alert-danger alert-dismissible"> <div className="alert alert-danger alert-dismissible">
<button
className="close"
type="button">
<span>×</span>
</button>
<h4>{ translate('INDEX.OOPS_ERROR') }</h4> <h4>{ translate('INDEX.OOPS_ERROR') }</h4>
<p> <p>
<span>{ translate('INDEX.OOPS_ERROR_DESC') }</span> <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 <div
className="progress-bar progress-bar-info progress-bar-striped active font-size-80-percent" className="progress-bar progress-bar-info progress-bar-striped active font-size-80-percent"
style={{ width: '100%' }}> 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> </div>
); );
} }
@ -48,7 +48,6 @@ class WalletsNativeSyncProgress extends React.Component {
renderActivatingBestChainProgress() { renderActivatingBestChainProgress() {
if (this.props.Settings && if (this.props.Settings &&
this.props.Settings.debugLog) { this.props.Settings.debugLog) {
console.log('debugLog');
if (this.props.Settings.debugLog.indexOf('UpdateTip') > -1 && if (this.props.Settings.debugLog.indexOf('UpdateTip') > -1 &&
!this.props.Dashboard.progress && !this.props.Dashboard.progress &&
!this.props.Dashboard.progress.blocks) { !this.props.Dashboard.progress.blocks) {
@ -75,7 +74,7 @@ class WalletsNativeSyncProgress extends React.Component {
if (this.props.Dashboard.progress.remoteKMDNode && if (this.props.Dashboard.progress.remoteKMDNode &&
this.props.Dashboard.progress.remoteKMDNode.blocks) { this.props.Dashboard.progress.remoteKMDNode.blocks) {
return( 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 ( return (
`: ${currentProgress}% (rescanning blocks)` `: ${currentProgress}% (${ translate('INDEX.RESCAN_SM') })`
); );
} else if ( } else if (
this.props.Settings.debugLog.indexOf('LoadExternalBlockFile:') > -1 || this.props.Settings.debugLog.indexOf('LoadExternalBlockFile:') > -1 ||
this.props.Settings.debugLog.indexOf('Reindexing block file') > -1 this.props.Settings.debugLog.indexOf('Reindexing block file') > -1
) { ) {
return ( return (
`: (reindexing blocks from disk)` `: (${ translate('INDEX.REINDEX') })`
); );
} else { } else {
return ( return (
<span> (downloading blocks!)</span> <span> ({ translate('INDEX.DL_BLOCKS') })</span>
); );
} }
} }

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

@ -53,7 +53,8 @@ class WalletsProgress extends React.Component {
return SyncErrorLongestChainRender.call(this); 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); return SyncErrorBlocksRender.call(this);
} }
@ -94,13 +95,13 @@ class WalletsProgress extends React.Component {
if (this.props.Dashboard.progress.remoteKMDNode && if (this.props.Dashboard.progress.remoteKMDNode &&
!this.props.Dashboard.progress.remoteKMDNode.blocks) { !this.props.Dashboard.progress.remoteKMDNode.blocks) {
return ( return (
`: ${currentProgress}% (activating)` `: ${currentProgress}% (${ translate('INDEX.ACTIVATING_SM') })`
); );
} else { } else {
if (this.props.Dashboard.progress.remoteKMDNode && if (this.props.Dashboard.progress.remoteKMDNode &&
this.props.Dashboard.progress.remoteKMDNode.blocks) { this.props.Dashboard.progress.remoteKMDNode.blocks) {
return( 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 ( return (
`: ${currentProgress}% (rescanning blocks)` `: ${currentProgress}% (${ translate('INDEX.RESCAN_SM') })`
); );
} else if ( } else if (
this.props.Settings.debugLog.indexOf('LoadExternalBlockFile:') > -1 || this.props.Settings.debugLog.indexOf('LoadExternalBlockFile:') > -1 ||
this.props.Settings.debugLog.indexOf('Reindexing block file') > -1 this.props.Settings.debugLog.indexOf('Reindexing block file') > -1
) { ) {
return ( return (
`: (reindexing blocks from disk)` `: ({ translate('INDEX.REINDEX') })`
); );
} else { } else {
return ( return (
<span> (downloading blocks)</span> <span> ({ translate('INDEX.DL_BLOCKS') })</span>
); );
} }
} }

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

@ -32,13 +32,14 @@ export const LoadingBlocksRender = function() {
<div <div
className="progress-bar progress-bar-info progress-bar-striped active font-size-80-percent" className="progress-bar progress-bar-info progress-bar-striped active font-size-80-percent"
style={{ width: '100%' }}> 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> </div>
); );
}; };
export const TranslationComponentsRender = function(translationID) { export const TranslationComponentsRender = function(translationID) {
const translationComponents = translate(translationID).split('<br>'); const translationComponents = translate(translationID).split('<br>');
return translationComponents.map((translation, idx) => return translationComponents.map((translation, idx) =>
<span key={idx}> <span key={idx}>
{ translation } { translation }
@ -77,19 +78,21 @@ export const WalletsProgressRender = function () {
className="margin-bottom-20"> className="margin-bottom-20">
{ !this.isNativeMode() && { !this.isNativeMode() &&
this.props.Dashboard.progress &&
<div className="row no-space"> <div className="row no-space">
<div id="currency-progressbars"> <div id="currency-progressbars">
<div className="progress progress-sm"> <div className="progress progress-sm">
<div className={ 'full-width font-size-80-percent ' <div className={ 'full-width font-size-80-percent '
+ (this.isFullySynced() ? 'progress-bar progress-bar-striped active progress-bar-indicating progress-bar-success' : 'hide') }> + (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 } { 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; / { this.props.Dashboard.progress.blocks } ) ==&gt;&gt;
RT{ this.props.Dashboard.progress.RTheight }</span> RT{ this.props.Dashboard.progress.RTheight }</span>
</div> </div>
<div <div
className={ 'font-size-80-percent ' className={ 'font-size-80-percent '
+ (this.isFullySynced() ? 'hide' : 'progress-bar progress-bar-info progress-bar-striped active') } + (this.isFullySynced() ? 'hide' : 'progress-bar progress-bar-info progress-bar-striped active') }
style={{width: this.props.Dashboard.progress.bundles + '%'}}> style={{ width: `${this.props.Dashboard.progress.bundles}%` }}>
{ translate('INDEX.BUNDLES') } { this.props.Dashboard.progress.bundles }% { translate('INDEX.BUNDLES') } { this.props.Dashboard.progress.bundles }%
</div> </div>
</div> </div>
@ -98,21 +101,21 @@ export const WalletsProgressRender = function () {
<div className="progress progress-sm"> <div className="progress progress-sm">
<div <div
className="progress-bar progress-bar-warning progress-bar-striped active font-size-80-percent" className="progress-bar progress-bar-warning progress-bar-striped active font-size-80-percent"
style={{width: this.props.Dashboard.progress.utxo + '%'}}> style={{ width: `${this.props.Dashboard.progress.utxo}%` }}>
utxo { this.props.Dashboard.progress.utxo }% utxo { this.props.Dashboard.progress.utxo }%
</div> </div>
</div> </div>
<div className="progress progress-sm"> <div className="progress progress-sm">
<div <div
className="progress-bar progress-bar-danger progress-bar-striped active font-size-80-percent" className="progress-bar progress-bar-danger progress-bar-striped active font-size-80-percent"
style={{width: this.props.Dashboard.progress.balances + '%'}}> style={{ width: `${this.props.Dashboard.progress.balances}%` }}>
{ translate('INDEX.BALANCES') } { this.props.Dashboard.progress.balances }% { translate('INDEX.BALANCES') } { this.props.Dashboard.progress.balances }%
</div> </div>
</div> </div>
<div className="progress progress-sm"> <div className="progress progress-sm">
<div <div
className="progress-bar progress-bar-success progress-bar-striped active font-size-80-percent" className="progress-bar progress-bar-success progress-bar-striped active font-size-80-percent"
style={{width: this.props.Dashboard.progress.validated + '%'}}> style={{ width: `${this.props.Dashboard.progress.validated}%` }}>
{ translate('INDEX.VALIDATED') } { this.props.Dashboard.progress.validated }% { translate('INDEX.VALIDATED') } { this.props.Dashboard.progress.validated }%
</div> </div>
</div> </div>

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

@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import { sortByDate } from '../../../util/sort';
import { toggleDashboardTxInfoModal } from '../../../actions/actionCreators'; import { toggleDashboardTxInfoModal } from '../../../actions/actionCreators';
import Store from '../../../store'; import Store from '../../../store';
import WalletsTxInfoRender from './walletsTxInfo.render'; import WalletsTxInfoRender from './walletsTxInfo.render';
@ -39,7 +40,7 @@ class WalletsTxInfo extends React.Component {
// into the rest of the components // into the rest of the components
(!this.isNativeMode() || (!this.isNativeMode() ||
(this.isNativeMode() && this.props.ActiveCoin.nativeActiveSection === 'default'))) { (this.isNativeMode() && this.props.ActiveCoin.nativeActiveSection === 'default'))) {
const txInfo = this.props.ActiveCoin.txhistory[this.props.ActiveCoin.showTransactionInfoTxIndex]; const txInfo = sortByDate(this.props.ActiveCoin.txhistory)[this.props.ActiveCoin.showTransactionInfoTxIndex];
return WalletsTxInfoRender.call(this, txInfo); return WalletsTxInfoRender.call(this, txInfo);
} }

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

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

55
react/src/components/login/login.js

@ -26,7 +26,7 @@ class Login extends React.Component {
this.state = { this.state = {
display: false, display: false,
activeLoginSection: 'activateCoin', activeLoginSection: 'activateCoin',
loginPassphrase: null, loginPassphrase: '',
seedInputVisibility: false, seedInputVisibility: false,
loginPassPhraseSeedType: null, loginPassPhraseSeedType: null,
bitsOption: 256, bitsOption: 256,
@ -38,6 +38,7 @@ class Login extends React.Component {
customWalletSeed: false, customWalletSeed: false,
isCustomSeedWeak: false, isCustomSeedWeak: false,
nativeOnly: Config.iguanaLessMode, nativeOnly: Config.iguanaLessMode,
trimPassphraseTimer: null,
}; };
this.toggleActivateCoinForm = this.toggleActivateCoinForm.bind(this); this.toggleActivateCoinForm = this.toggleActivateCoinForm.bind(this);
this.updateRegisterConfirmPassPhraseInput = this.updateRegisterConfirmPassPhraseInput.bind(this); this.updateRegisterConfirmPassPhraseInput = this.updateRegisterConfirmPassPhraseInput.bind(this);
@ -49,6 +50,7 @@ class Login extends React.Component {
this.toggleSeedBackupModal = this.toggleSeedBackupModal.bind(this); this.toggleSeedBackupModal = this.toggleSeedBackupModal.bind(this);
this.copyPassPhraseToClipboard = this.copyPassPhraseToClipboard.bind(this); this.copyPassPhraseToClipboard = this.copyPassPhraseToClipboard.bind(this);
this.execWalletCreate = this.execWalletCreate.bind(this); this.execWalletCreate = this.execWalletCreate.bind(this);
this.resizeLoginTextarea = this.resizeLoginTextarea.bind(this);
} }
isCustomWalletSeed() { isCustomWalletSeed() {
@ -64,13 +66,13 @@ class Login extends React.Component {
this.setState({ this.setState({
randomSeed: PassPhraseGenerator.generatePassPhrase(this.state.bitsOption), randomSeed: PassPhraseGenerator.generatePassPhrase(this.state.bitsOption),
isSeedConfirmError: false, isSeedConfirmError: false,
isSeedBlank: false isSeedBlank: false,
}); });
} else { } else {
// if customWalletSeed is set to true, reset to seed to an empty string // if customWalletSeed is set to true, reset to seed to an empty string
this.setState({ this.setState({
randomSeed: '', randomSeed: '',
randomSeedConfirm: '' randomSeedConfirm: '',
}); });
} }
}); });
@ -100,13 +102,15 @@ class Login extends React.Component {
this.setState({ this.setState({
seedInputVisibility: !this.state.seedInputVisibility, seedInputVisibility: !this.state.seedInputVisibility,
}); });
this.resizeLoginTextarea();
} }
generateNewSeed(bits) { generateNewSeed(bits) {
this.setState(Object.assign({}, this.state, { this.setState(Object.assign({}, this.state, {
randomSeed: PassPhraseGenerator.generatePassPhrase(bits), randomSeed: PassPhraseGenerator.generatePassPhrase(bits),
bitsOption: bits, bitsOption: bits,
isSeedBlank: false isSeedBlank: false,
})); }));
} }
@ -155,13 +159,35 @@ class Login extends React.Component {
Store.dispatch(toggleAddcoinModal(true, false)); 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) { updateLoginPassPhraseInput(e) {
// remove any empty chars from the start/end of the string // 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({ this.setState({
trimPassphraseTimer: _trimPassphraseTimer,
[e.target.name]: newValue, [e.target.name]: newValue,
loginPassPhraseSeedType: this.getLoginPassPhraseSeedType(newValue) loginPassPhraseSeedType: this.getLoginPassPhraseSeedType(newValue),
}); });
} }
@ -169,7 +195,7 @@ class Login extends React.Component {
this.setState({ this.setState({
[e.target.name]: e.target.value, [e.target.name]: e.target.value,
isSeedConfirmError: false, 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({ this.setState({
randomSeed: e.target.value, randomSeed: e.target.value,
isSeedConfirmError: false, 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(' '); const passPhraseWords = passPhrase.split(' ');
if (!PassPhraseGenerator.arePassPhraseWordsValid(passPhraseWords)) if (!PassPhraseGenerator.arePassPhraseWordsValid(passPhraseWords)) {
return null; return null;
}
if (PassPhraseGenerator.isPassPhraseValid(passPhraseWords, 256)) { if (PassPhraseGenerator.isPassPhraseValid(passPhraseWords, 256)) {
return translate('LOGIN.IGUANA_SEED'); return translate('LOGIN.IGUANA_SEED');
@ -250,9 +277,7 @@ class Login extends React.Component {
}); });
} }
// TODO: // TODO: disable register btn if seed or seed conf is incorrect
// 1) disable register btn if seed or seed conf is incorrect
// 2) display explicit custom seed validation message
handleRegisterWallet() { handleRegisterWallet() {
const enteredSeedsMatch = this.state.randomSeed === this.state.randomSeedConfirm; const enteredSeedsMatch = this.state.randomSeed === this.state.randomSeedConfirm;
const isSeedBlank = this.isBlank(this.state.randomSeed); const isSeedBlank = this.isBlank(this.state.randomSeed);
@ -281,6 +306,8 @@ class Login extends React.Component {
} }
handleKeydown(e) { handleKeydown(e) {
this.updateLoginPassPhraseInput(e);
if (e.key === 'Enter') { if (e.key === 'Enter') {
this.loginSeed(); this.loginSeed();
} }
@ -295,6 +322,7 @@ class Login extends React.Component {
copyPassPhraseToClipboard() { copyPassPhraseToClipboard() {
const passPhrase = this.state.randomSeed; const passPhrase = this.state.randomSeed;
const textField = document.createElement('textarea'); const textField = document.createElement('textarea');
textField.innerText = passPhrase; textField.innerText = passPhrase;
document.body.appendChild(textField); document.body.appendChild(textField);
textField.select(); textField.select();
@ -319,7 +347,8 @@ class Login extends React.Component {
} }
render() { render() {
if ((this.state && this.state.display) || !this.props.Main) { if ((this.state && this.state.display) ||
!this.props.Main) {
return LoginRender.call(this); return LoginRender.call(this);
} }

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

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

22
react/src/components/login/login.scss

@ -56,8 +56,28 @@ textarea {
} }
} }
.seed-type-block {
position: absolute;
left: 100%;
min-width: 50px;
.placeholder-label { .placeholder-label {
color: #808080; 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 { .seed-tooltip {

2
react/src/components/overrides.scss

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

2
react/src/reducers/addcoin.js

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

5
react/src/reducers/toaster.js

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

80
react/src/translate/en.js

@ -1,6 +1,45 @@
export const _lang = { export const _lang = {
'EN': { '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': { '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', 'IMPORT': 'Import',
'CHECK': 'Check', 'CHECK': 'Check',
'VALIDATE': 'Validate', 'VALIDATE': 'Validate',
@ -180,7 +219,7 @@ export const _lang = {
'ERRORS': 'Errors', 'ERRORS': 'Errors',
'ADD_NODE': 'Add Node', '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:', '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', 'CHECK_NODES': 'Check Nodes',
'USE_THIS_SECTION_PEER': 'Use this section to add a peer IP to a selected coin:', 'USE_THIS_SECTION_PEER': 'Use this section to add a peer IP to a selected coin:',
'WALLET_BACKUP': 'Wallet Backup', 'WALLET_BACKUP': 'Wallet Backup',
@ -225,7 +264,10 @@ export const _lang = {
'ALREADY_ADDED': 'is already added', 'ALREADY_ADDED': 'is already added',
'COIN_ALREADY_ADDED': 'Coin already added', 'COIN_ALREADY_ADDED': 'Coin already added',
'IN': 'in', 'IN': 'in',
'MODE': 'mode' 'MODE': 'mode',
'CRYPTO_CURRENCIES': 'Crypto Currencies',
'ASSETCHAINS': 'Assetchains',
'FIAT_CURRENCIES': 'Fiat Currencies'
}, },
'JUMBLR': { 'JUMBLR': {
'NOTICE': 'EXPERIMENTAL TEST VERSION ONLY', 'NOTICE': 'EXPERIMENTAL TEST VERSION ONLY',
@ -470,6 +512,40 @@ export const _lang = {
'ENTER_AN_ADDRESS': 'Enter an address', 'ENTER_AN_ADDRESS': 'Enter an address',
'YOU_PICKED_OPT': 'You picked option', 'YOU_PICKED_OPT': 'You picked option',
'PLEASE_WAIT': 'Please wait' '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)'
} }
} }
}; };

7
react/src/util/sort.js

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