Browse Source

Merge branch 'redux' into merge-wallets-progress

# Conflicts:
#	react/src/components/dashboard/main/dashboard.render.js
#	react/src/components/dashboard/walletsNativeSyncProgress/walletsNativeSyncProgress.js
#	react/src/components/dashboard/walletsNativeSyncProgress/walletsNativeSyncProgress.render.js
all-modes
petitPapillon 7 years ago
parent
commit
d5a6be43f8
  1. 9
      react/change.log
  2. 116
      react/src/actions/actions/addressBalance.js
  3. 75
      react/src/actions/actions/iguanaHelpers.js
  4. 31
      react/src/actions/actions/nativeBalance.js
  5. 47
      react/src/actions/actions/nativeNewAddress.js
  6. 93
      react/src/actions/actions/nativeSend.js
  7. 69
      react/src/actions/actions/nativeSyncInfo.js
  8. 27
      react/src/actions/actions/nativeTxHistory.js
  9. 4
      react/src/components/dashboard/main/dashboard.render.js
  10. 82
      react/src/components/dashboard/receiveCoin/receiveCoin.js
  11. 68
      react/src/components/dashboard/receiveCoin/receiveCoin.render.js
  12. 2
      react/src/components/dashboard/sendCoin/sendCoin.render.js
  13. 2
      react/src/components/dashboard/settings/settings.js
  14. 2
      react/src/components/dashboard/settings/settings.render.js
  15. 26
      react/src/components/dashboard/walletsBalance/walletsBalance.js
  16. 56
      react/src/components/dashboard/walletsBalance/walletsBalance.render.js
  17. 2
      react/src/components/dashboard/walletsCacheData/walletsCacheData.render.js
  18. 6
      react/src/components/dashboard/walletsNative/walletsNative.render.js
  19. 15
      react/src/components/dashboard/walletsNativeBalance/walletsNativeBalance.js
  20. 82
      react/src/components/dashboard/walletsNativeBalance/walletsNativeBalance.render.js
  21. 94
      react/src/components/dashboard/walletsNativeReceive/walletsNativeReceive.js
  22. 90
      react/src/components/dashboard/walletsNativeReceive/walletsNativeReceive.render.js
  23. 4
      react/src/components/dashboard/walletsNativeSend/walletsNativeSend.js
  24. 44
      react/src/components/dashboard/walletsNativeSend/walletsNativeSend.render.js
  25. 139
      react/src/components/dashboard/walletsNativeSyncProgress/walletsNativeSyncProgress.js
  26. 34
      react/src/components/dashboard/walletsNativeSyncProgress/walletsNativeSyncProgress.render.js
  27. 26
      react/src/components/dashboard/walletsNotariesList/walletsNotariesList.render.js
  28. 149
      react/src/components/login/login.js
  29. 213
      react/src/components/login/login.render.js
  30. 40
      react/src/components/login/login.scss
  31. 4
      react/src/config.js
  32. 9
      react/src/translate/en.js
  33. 24
      react/src/util/crypto/passphrasegenerator.js
  34. 2
      react/www/index.html

9
react/change.log

@ -12,6 +12,13 @@ front:
- sort http stack history desc
- swapped gettotalbalance interest with getinfo interest
- extended settings / export keys ui
- added error message if coin is already running in another mode
- added explicit "new address generated" message
- added cli / rpc passphru
- seed type check
- seed extra space(s) check
- custom seed option
back:
- added cli route
- added cli route
- rpc passphru

116
react/src/actions/actions/addressBalance.js

@ -106,20 +106,46 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
}
})
} else {
if (Config.cli.default &&
mode === 'native') {
payload = {
mode: null,
chain: coin,
cmd: payload.function,
params: [""]
};
}
const _timestamp = Date.now();
dispatch(logGuiHttp({
'timestamp': _timestamp,
'function': 'getKMDAddressesNative',
'type': 'post',
'url': `http://127.0.0.1:${Config.iguanaCorePort}`,
'url': Config.cli.default ? `http://127.0.0.1:${Config.agamaPort}/shepherd/cli` : `http://127.0.0.1:${Config.iguanaCorePort}`,
'payload': payload,
'status': 'pending',
}));
fetch(`http://127.0.0.1:${Config.iguanaCorePort}`, {
let _fetchConfig = {
method: 'POST',
body: JSON.stringify(payload),
})
};
if (Config.cli.default &&
mode === 'native') {
_fetchConfig = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ 'payload': payload }),
};
}
fetch(
Config.cli.default && mode === 'native' ? `http://127.0.0.1:${Config.agamaPort}/shepherd/cli` : `http://127.0.0.1:${Config.iguanaCorePort}`,
_fetchConfig
)
.catch(function(error) {
console.log(error);
dispatch(logGuiHttp({
@ -142,7 +168,7 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
'status': 'success',
'response': json,
}));
resolve(json);
resolve(Config.cli.default && mode === 'native' ? json.result : json);
})
}
});
@ -227,8 +253,19 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
}
}
let newAddressArray = [];
// remove addr duplicates
if (result[0]) {
result[0] = result[0].filter(function(elem, pos) {
return result[0].indexOf(elem) === pos;
});
}
if (result[1]) {
result[1] = result[1].filter(function(elem, pos) {
return result[1].indexOf(elem) === pos;
});
}
let newAddressArray = [];
for (let a = 0; a < result.length; a++) {
newAddressArray[a] = [];
@ -260,7 +297,7 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
Promise.all(result[1].map((_address, index) => {
return new Promise((resolve, reject) => {
const _timestamp = Date.now();
let ajaxDataToHex = `["${_address}"]`;
let ajaxDataToHex = `[\"${_address}\"]`;
iguanaHashHex(ajaxDataToHex, dispatch)
.then((hashHexJson) => {
@ -286,16 +323,40 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
'timestamp': _timestamp,
'function': 'getKMDAddressesNative+ZBalance',
'type': 'post',
'url': `http://127.0.0.1:${Config.iguanaCorePort}`,
'url': Config.cli.default ? `http://127.0.0.1:${Config.agamaPort}/shepherd/cli` : `http://127.0.0.1:${Config.iguanaCorePort}`,
'payload': payload,
'status': 'pending',
}));
fetch(`http://127.0.0.1:${Config.iguanaCorePort}`,
{
let _fetchConfig = {
method: 'POST',
body: JSON.stringify(payload),
})
};
if (Config.cli.default &&
mode === 'native') {
payload = {
mode: null,
chain: coin,
cmd: 'z_getbalance',
params: [
_address
]
};
_fetchConfig = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ 'payload': payload }),
};
}
fetch(
Config.cli.default && mode === 'native' ? `http://127.0.0.1:${Config.agamaPort}/shepherd/cli` : `http://127.0.0.1:${Config.iguanaCorePort}`,
_fetchConfig
)
.catch(function(error) {
console.log(error);
dispatch(logGuiHttp({
@ -329,6 +390,10 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
)
);
} else {
if (Config.cli.default &&
mode === 'native') {
json = json.result;
}
resolve(json);
newAddressArray[1][index] = {
address: _address,
@ -449,10 +514,33 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
'status': 'pending',
}));
fetch(`http://127.0.0.1:${(Config.useBasiliskInstance && mode === 'basilisk' ? Config.iguanaCorePort + 1 : Config.iguanaCorePort)}`, {
let _fetchConfig = {
method: 'POST',
body: JSON.stringify(payload),
})
};
if (Config.cli.default &&
mode === 'native') {
payload = {
mode: null,
chain: coin,
cmd: payload.function,
params: payload.params
};
_fetchConfig = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ 'payload': payload }),
};
}
fetch(
Config.cli.default && mode === 'native' ? `http://127.0.0.1:${Config.agamaPort}/shepherd/cli` : `http://127.0.0.1:${(Config.useBasiliskInstance && mode === 'basilisk' ? Config.iguanaCorePort + 1 : Config.iguanaCorePort)}`,
_fetchConfig
)
.catch(function(error) {
console.log(error);
dispatch(logGuiHttp({
@ -470,6 +558,10 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
})
.then(response => response.json())
.then(function(json) {
if (Config.cli.default &&
mode === 'native') {
json = json.result;
}
dispatch(logGuiHttp({
'timestamp': _timestamp,
'status': 'success',

75
react/src/actions/actions/iguanaHelpers.js

@ -28,44 +28,49 @@ export function iguanaHashHex(data, dispatch) {
};
return new Promise((resolve, reject) => {
const _timestamp = Date.now();
dispatch(logGuiHttp({
'timestamp': _timestamp,
'function': 'iguanaHashHex',
'type': 'post',
'url': `http://127.0.0.1:${Config.iguanaCorePort}`,
'payload': payload,
'status': 'pending',
}));
fetch(`http://127.0.0.1:${Config.iguanaCorePort}`, {
method: 'POST',
body: JSON.stringify(payload),
})
.catch(function(error) {
console.log(error);
// skip iguana hashing in cli mode
if (Config.cli.default) {
resolve(true);
} else {
const _timestamp = Date.now();
dispatch(logGuiHttp({
'timestamp': _timestamp,
'status': 'error',
'response': error,
'function': 'iguanaHashHex',
'type': 'post',
'url': `http://127.0.0.1:${Config.iguanaCorePort}`,
'payload': payload,
'status': 'pending',
}));
dispatch(
triggerToaster(
'iguanaHashHex',
'Error',
'error'
)
);
})
.then(response => response.json())
.then(json => {
dispatch(logGuiHttp({
'timestamp': _timestamp,
'status': 'success',
'response': json,
}));
resolve(json.hex);
})
fetch(`http://127.0.0.1:${Config.iguanaCorePort}`, {
method: 'POST',
body: JSON.stringify(payload),
})
.catch(function(error) {
console.log(error);
dispatch(logGuiHttp({
'timestamp': _timestamp,
'status': 'error',
'response': error,
}));
dispatch(
triggerToaster(
'iguanaHashHex',
'Error',
'error'
)
);
})
.then(response => response.json())
.then(json => {
dispatch(logGuiHttp({
'timestamp': _timestamp,
'status': 'success',
'response': json,
}));
resolve(json.hex);
})
}
})
}

31
react/src/actions/actions/nativeBalance.js

@ -32,21 +32,44 @@ export function getKMDBalanceTotal(coin) {
};
}
if (Config.cli.default) {
payload = {
mode: null,
chain: coin,
cmd: 'z_gettotalbalance'
};
}
return dispatch => {
const _timestamp = Date.now();
dispatch(logGuiHttp({
'timestamp': _timestamp,
'function': 'getKMDBalanceTotal',
'type': 'post',
'url': `http://127.0.0.1:${Config.iguanaCorePort}`,
'url': Config.cli.default ? `http://127.0.0.1:${Config.agamaPort}/shepherd/cli` : `http://127.0.0.1:${Config.iguanaCorePort}`,
'payload': payload,
'status': 'pending',
}));
return fetch(`http://127.0.0.1:${Config.iguanaCorePort}`, {
let _fetchConfig = {
method: 'POST',
body: JSON.stringify(payload),
})
};
if (Config.cli.default) {
_fetchConfig = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ 'payload': payload }),
};
}
return fetch(
Config.cli.default ? `http://127.0.0.1:${Config.agamaPort}/shepherd/cli` : `http://127.0.0.1:${Config.iguanaCorePort}`,
_fetchConfig
)
.catch(function(error) {
console.log(error);
dispatch(logGuiHttp({
@ -80,6 +103,6 @@ export function getKMDBalanceTotal(coin) {
export function getNativeBalancesState(json) {
return {
type: DASHBOARD_ACTIVE_COIN_NATIVE_BALANCE,
balance: json && !json.error ? json : 0,
balance: json && !json.error ? (Config.cli.default ? json.result : json) : 0,
}
}

47
react/src/actions/actions/nativeNewAddress.js

@ -10,13 +10,21 @@ import {
guiLogState
} from './log';
function handleGetNewKMDAddresses(pubpriv, coin, dispatch) {
dispatch(
function handleGetNewKMDAddresses(pubpriv, coin, dispatch, json) {
/*dispatch(
triggerToaster(
translate('KMD_NATIVE.NEW_ADDR_GENERATED'),
translate('TOASTR.WALLET_NOTIFICATION'),
'success'
)
);*/
dispatch(
triggerToaster(
json.result ? json.result : json,
translate('KMD_NATIVE.NEW_ADDR_GENERATED'),
'info',
false
)
);
dispatch(getKMDAddressesNative(coin));
@ -45,7 +53,7 @@ export function getNewKMDAddresses(coin, pubpriv) {
};
} else {
payload = {
'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
'userpass': `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`,
'agent': coin,
'method': 'passthru',
'function': ajaxFunctionInput,
@ -59,15 +67,36 @@ export function getNewKMDAddresses(coin, pubpriv) {
'timestamp': _timestamp,
'function': 'getNewKMDAddresses',
'type': 'post',
'url': `http://127.0.0.1:${Config.iguanaCorePort}`,
'url': Config.cli.default ? `http://127.0.0.1:${Config.agamaPort}/shepherd/cli` : `http://127.0.0.1:${Config.iguanaCorePort}`,
'payload': payload,
'status': 'pending',
}));
return fetch(`http://127.0.0.1:${Config.iguanaCorePort}`, {
let _fetchConfig = {
method: 'POST',
body: JSON.stringify(payload),
})
};
if (Config.cli.default) {
payload = {
mode: null,
chain: coin,
cmd: payload.function
};
_fetchConfig = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ 'payload': payload }),
};
}
return fetch(
Config.cli.default ? `http://127.0.0.1:${Config.agamaPort}/shepherd/cli` : `http://127.0.0.1:${Config.iguanaCorePort}`,
_fetchConfig
)
.catch(function(error) {
console.log(error);
dispatch(logGuiHttp({
@ -85,6 +114,9 @@ export function getNewKMDAddresses(coin, pubpriv) {
})
.then(response => response.json())
.then(json => {
if (Config.cli.default) {
json = json.result;
}
dispatch(logGuiHttp({
'timestamp': _timestamp,
'status': 'success',
@ -94,7 +126,8 @@ export function getNewKMDAddresses(coin, pubpriv) {
handleGetNewKMDAddresses(
pubpriv,
coin,
dispatch
dispatch,
json
)
);
})

93
react/src/actions/actions/nativeSend.js

@ -51,15 +51,50 @@ export function sendNativeTx(coin, _payload) {
'timestamp': _timestamp,
'function': 'sendNativeTx',
'type': 'post',
'url': `http://127.0.0.1:${Config.iguanaCorePort}`,
'url': Config.cli.default ? `http://127.0.0.1:${Config.agamaPort}/shepherd/cli` : `http://127.0.0.1:${Config.iguanaCorePort}`,
'payload': payload,
'status': 'pending',
}));
fetch(`http://127.0.0.1:${Config.iguanaCorePort}`, {
let _fetchConfig = {
method: 'POST',
body: JSON.stringify(payload),
})
};
if (Config.cli.default) {
payload = {
mode: null,
chain: coin,
cmd: payload.function,
params:
_payload.addressType === 'public' && _payload.sendTo.length !== 95 ?
[
_payload.sendTo,
_payload.amount
]
:
[
_payload.sendFrom,
[{
address: _payload.sendTo,
amount: _payload.amount
}]
]
};
_fetchConfig = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ 'payload': payload }),
};
}
fetch(
Config.cli.default ? `http://127.0.0.1:${Config.agamaPort}/shepherd/cli` : `http://127.0.0.1:${Config.iguanaCorePort}`,
_fetchConfig
)
.catch(function(error) {
console.log(error);
dispatch(logGuiHttp({
@ -77,7 +112,7 @@ export function sendNativeTx(coin, _payload) {
})
.then(function(response) {
const _response = response.text().then(function(text) { return text; });
return response.json();
return _response;
})
.then(function(json) {
dispatch(logGuiHttp({
@ -86,15 +121,29 @@ export function sendNativeTx(coin, _payload) {
'response': json,
}));
if (json.error &&
json.error.toString().indexOf('code:') > -1) {
if (json.indexOf('"code":') > -1) {
const _message = json.substring(json.indexOf('"message":"') + 11, json.indexOf('"},"id":"jl777"'));
dispatch(
triggerToaster(
'Send failed',
true,
_message,
translate('TOASTR.WALLET_NOTIFICATION'),
'error'
)
);
if (json.indexOf('"code":-4') > -1) {
dispatch(
triggerToaster(
true,
translate('TOASTR.WALLET_NOTIFICATION'),
'Your wallet.dat is not matching the blockchain. Please resync from the scratch.',
'info',
false
)
);
}
} else {
dispatch(
triggerToaster(
@ -160,15 +209,36 @@ export function getKMDOPID(opid, coin) {
'timestamp': _timestamp,
'function': 'getKMDOPID',
'type': 'post',
'url': `http://127.0.0.1:${Config.iguanaCorePort}`,
'url': Config.cli.default ? `http://127.0.0.1:${Config.agamaPort}/shepherd/cli` : `http://127.0.0.1:${Config.iguanaCorePort}`,
'payload': payload,
'status': 'pending',
}));
fetch(`http://127.0.0.1:${Config.iguanaCorePort}`, {
let _fetchConfig = {
method: 'POST',
body: JSON.stringify(payload),
})
};
if (Config.cli.default) {
payload = {
mode: null,
chain: coin,
cmd: 'z_getoperationstatus'
};
_fetchConfig = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ 'payload': payload }),
};
}
fetch(
Config.cli.default ? `http://127.0.0.1:${Config.agamaPort}/shepherd/cli` : `http://127.0.0.1:${Config.iguanaCorePort}`,
_fetchConfig
)
.catch(function(error) {
console.log(error);
dispatch(logGuiHttp({
@ -186,6 +256,9 @@ export function getKMDOPID(opid, coin) {
})
.then(response => response.json())
.then(json => {
if (Config.cli.default) {
json = json.result;
}
dispatch(logGuiHttp({
'timestamp': _timestamp,
'status': 'success',

69
react/src/actions/actions/nativeSyncInfo.js

@ -60,20 +60,31 @@ export function getSyncInfoNativeKMD(skipDebug) {
}
function getSyncInfoNativeState(json, coin, skipDebug) {
console.log('getSyncInfoNativeState', json);
if (coin === 'KMD' &&
json &&
json.error) {
return getSyncInfoNativeKMD(skipDebug);
} else {
return {
type: SYNCING_NATIVE_MODE,
progress: json,
if (json &&
json.error &&
Config.cli.default) {
console.log('getSyncInfoNativeState', 'error');
return {
type: SYNCING_NATIVE_MODE,
progress: Config.cli.default ? json.error : json,
}
} else {
return {
type: SYNCING_NATIVE_MODE,
progress: Config.cli.default ? json.result : json,
}
}
}
}
export function getSyncInfoNative(coin, skipDebug) {
const payload = {
let payload = {
'userpass': `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`,
'agent': getPassthruAgent(coin),
'method': 'passthru',
@ -82,21 +93,43 @@ export function getSyncInfoNative(coin, skipDebug) {
'hex': '',
};
if (Config.cli.default) {
payload = {
mode: null,
chain: coin,
cmd: 'getinfo'
};
}
return dispatch => {
const _timestamp = Date.now();
dispatch(logGuiHttp({
'timestamp': _timestamp,
'function': 'getSyncInfo',
'type': 'post',
'url': `http://127.0.0.1:${Config.iguanaCorePort}`,
'url': Config.cli.default ? `http://127.0.0.1:${Config.agamaPort}/shepherd/cli` : `http://127.0.0.1:${Config.iguanaCorePort}`,
'payload': payload,
'status': 'pending',
}));
return fetch(`http://127.0.0.1:${Config.iguanaCorePort}`, {
let _fetchConfig = {
method: 'POST',
body: JSON.stringify(payload),
})
};
if (Config.cli.default) {
_fetchConfig = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ 'payload': payload }),
};
}
return fetch(
Config.cli.default ? `http://127.0.0.1:${Config.agamaPort}/shepherd/cli` : `http://127.0.0.1:${Config.iguanaCorePort}`,
_fetchConfig
)
.catch(function(error) {
console.log(error);
dispatch(logGuiHttp({
@ -112,8 +145,26 @@ export function getSyncInfoNative(coin, skipDebug) {
)
);
})
.then(response => response.json())
.then(function(response) {
const _response = response.text().then(function(text) { return text; });
return _response;
})
//.then(response => response.json())
.then(json => {
if (!json &&
Config.cli.default) {
dispatch(
triggerToaster(
'Komodod is down',
'Critical Error',
'error',
false
)
);
} else {
json = JSON.parse(json);
}
dispatch(logGuiHttp({
'timestamp': _timestamp,
'status': 'success',

27
react/src/actions/actions/nativeTxHistory.js

@ -37,15 +37,36 @@ export function getNativeTxHistory(coin) {
'timestamp': _timestamp,
'function': 'getNativeTxHistory',
'type': 'post',
'url': `http://127.0.0.1:${Config.iguanaCorePort}`,
'url': Config.cli.default ? `http://127.0.0.1:${Config.agamaPort}/shepherd/cli` : `http://127.0.0.1:${Config.iguanaCorePort}`,
'payload': payload,
'status': 'pending',
}));
return fetch(`http://127.0.0.1:${Config.iguanaCorePort}`, {
let _fetchConfig = {
method: 'POST',
body: JSON.stringify(payload),
})
};
if (Config.cli.default) {
payload = {
mode: null,
chain: coin,
cmd: 'listtransactions'
};
_fetchConfig = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ 'payload': payload }),
};
}
return fetch(
Config.cli.default ? `http://127.0.0.1:${Config.agamaPort}/shepherd/cli` : `http://127.0.0.1:${Config.iguanaCorePort}`,
_fetchConfig
)
.catch(function(error) {
console.log(error);
dispatch(logGuiHttp({

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

@ -28,12 +28,12 @@ const DashboardRender = function() {
<CoinTile {...this.props} />
<WalletsNav {...this.props} />
{ !this.isNativeMode() && <WalletsProgress {...this.props} /> }
<WalletsBalance {...this.props} />
{ !this.isNativeMode() && <WalletsBalance {...this.props} />}
<SendCoin {...this.props} />
<ReceiveCoin {...this.props.ActiveCoin} />
<WalletsData {...this.props} />
<WalletsTxInfo {...this.props} />
<WalletsNative {...this.props} />
<ReceiveCoin {...this.props.ActiveCoin} />
<WalletsNativeTxInfo {...this.props} />
</div>
<div className={ this.isSectionActive('edex') ? 'show' : 'hide' }>

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

@ -2,10 +2,10 @@ import React from 'react';
import {
copyCoinAddress,
checkAddressBasilisk,
validateAddressBasilisk
validateAddressBasilisk,
getNewKMDAddresses
} from '../../../actions/actionCreators';
import Store from '../../../store';
import {
AddressActionsBasiliskModeRender,
AddressActionsNonBasiliskModeRender,
@ -19,6 +19,43 @@ import {
class ReceiveCoin extends React.Component {
constructor(props) {
super(props);
this.state = {
openDropMenu: false,
};
this.openDropMenu = this.openDropMenu.bind(this);
this.handleClickOutside = this.handleClickOutside.bind(this);
}
componentWillMount() {
document.addEventListener(
'click',
this.handleClickOutside,
false
);
}
componentWillUnmount() {
document.removeEventListener(
'click',
this.handleClickOutside,
false
);
}
handleClickOutside(e) {
if (e.srcElement.className.indexOf('dropdown') === -1 &&
(e.srcElement.offsetParent && e.srcElement.offsetParent.className.indexOf('dropdown') === -1)) {
this.setState({
openDropMenu: false,
});
}
}
openDropMenu() {
this.setState(Object.assign({}, this.state, {
openDropMenu: !this.state.openDropMenu,
}));
}
_checkAddressBasilisk(address) {
@ -47,12 +84,16 @@ class ReceiveCoin extends React.Component {
return this.props.mode === 'basilisk';
}
renderAddressActions(address) {
isNativeMode() {
return this.props.mode == 'native';
}
renderAddressActions(address, type) {
if (this.isBasiliskMode()) {
return AddressActionsBasiliskModeRender.call(this, address);
}
return AddressActionsNonBasiliskModeRender.call(this, address);
return AddressActionsNonBasiliskModeRender.call(this, address, type);
}
hasNoAmount(address) {
@ -63,26 +104,34 @@ class ReceiveCoin extends React.Component {
return address.interest === 'N/A' || address.interest === 0 || !address.interest;
}
renderAddressList() {
getNewAddress(type) {
Store.dispatch(getNewKMDAddresses(this.props.coin, type));
}
renderAddressList(type) {
if (this.props.addresses &&
this.props.addresses.public &&
this.props.addresses.public.length) {
this.props.addresses[type] &&
this.props.addresses[type].length) {
let items = [];
for (let i = 0; i < this.props.addresses.public.length; i++) {
let address = this.props.addresses.public[i];
for (let i = 0; i < this.props.addresses[type].length; i++) {
let address = this.props.addresses[type][i];
if (this.isBasiliskMode() &&
this.hasNoAmount(address)) {
address.amount = this.props.cache && this.props.cache[this.props.coin][address.address] && this.props.cache[this.props.coin][address.address].getbalance.data && this.props.cache[this.props.coin][address.address].getbalance.data.balance ? this.props.cache[this.props.coin][address.address].getbalance.data.balance : 'N/A';
this.hasNoAmount(address)) {
address.amount = this.props.cache && this.props.cache[this.props.coin][address.address]
&& this.props.cache[this.props.coin][address.address].getbalance.data
&& this.props.cache[this.props.coin][address.address].getbalance.data.balance ? this.props.cache[this.props.coin][address.address].getbalance.data.balance : 'N/A';
}
if (this.isBasiliskMode() &&
this.hasNoInterest(address)) {
address.interest = this.props.cache && this.props.cache[this.props.coin][address.address] && this.props.cache[this.props.coin][address.address].getbalance.data && this.props.cache[this.props.coin][address.address].getbalance.data.interest ? this.props.cache[this.props.coin][address.address].getbalance.data.interest : 'N/A';
this.hasNoInterest(address)) {
address.interest = this.props.cache && this.props.cache[this.props.coin][address.address]
&& this.props.cache[this.props.coin][address.address].getbalance.data
&& this.props.cache[this.props.coin][address.address].getbalance.data.interest ? this.props.cache[this.props.coin][address.address].getbalance.data.interest : 'N/A';
}
items.push(
AddressItemRender.call(this, address)
AddressItemRender.call(this, address, type)
);
}
@ -93,9 +142,10 @@ class ReceiveCoin extends React.Component {
}
render() {
// TODO nativeActiveSection === 'receive' should be removed when native mode is fully merged
// into the rest of the components
if (this.props &&
this.props.receive &&
this.props.mode !== 'native') {
(this.props.receive || (this.isNativeMode() && this.props.nativeActiveSection === 'receive'))) {
return ReceiveCoinRender.call(this);
}

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

@ -29,11 +29,12 @@ export const AddressActionsBasiliskModeRender = function(address) {
);
};
export const AddressActionsNonBasiliskModeRender = function(address) {
export const AddressActionsNonBasiliskModeRender = function(address, type) {
return (
<td>
<span className="label label-default">
<i className="icon fa-eye"></i> { translate('IAPI.PUBLIC_SM') }
<span className={ type === 'public' ? 'label label-default' : 'label label-dark' }>
<i className={ type === 'public' ? 'icon fa-eye' : 'icon fa-eye-slash' }></i>
{ type === 'public' ? translate('IAPI.PUBLIC_SM') : translate('KMD_NATIVE.PRIVATE') }
</span>
<button
className="btn btn-default btn-xs clipboard-edexaddr margin-left-10"
@ -44,13 +45,15 @@ export const AddressActionsNonBasiliskModeRender = function(address) {
);
};
export const AddressItemRender = function(address) {
export const AddressItemRender = function(address, type) {
return (
<tr key={ address.address }>
{ this.renderAddressActions(address.address) }
<td>{ address.address }</td>
{ this.renderAddressActions(address.address, type) }
<td>{ type === 'public' ? address.address : address.address.substring(0, 34) + '...' }</td>
<td>{ address.amount }</td>
<td>{ address.interest ? address.interest : 'N/A' }</td>
{!this.isNativeMode() &&
<td>{ address.interest ? address.interest : 'N/A' }</td>
}
</tr>
);
};
@ -64,31 +67,70 @@ export const ReceiveCoinRender = function() {
<div className="col-xlg-12 col-lg-12 col-sm-12 col-xs-12">
<div className="panel">
<header className="panel-heading">
<div className="panel-actions"></div>
<h4 className="panel-title">
{ translate('INDEX.RECEIVING_ADDRESS') }
</h4>
{this.isNativeMode() &&
<div className="panel-actions">
<div className={ 'dropdown' + (this.state.openDropMenu ? ' open' : '') }
onClick={ this.openDropMenu }>
<a className="dropdown-toggle white btn btn-warning">
<i className="icon md-arrows margin-right-10"></i> { translate('INDEX.GET_NEW_ADDRESS') }
<span
className="caret"></span>
</a>
<ul
className="dropdown-menu dropdown-menu-right">
<li>
<a onClick={ () => this.getNewAddress('public') }>
<i className="icon fa-eye"></i> { translate('INDEX.TRANSPARENT_ADDRESS') }
</a>
</li>
<li>
<a onClick={ () => this.getNewAddress('private') }>
<i className="icon fa-eye-slash"></i> { translate('INDEX.PRIVATE_Z_ADDRESS') }
</a>
</li>
</ul>
</div>
</div>
}
<h4 className="panel-title">{ translate('INDEX.RECEIVING_ADDRESS') }</h4>
</header>
<div className="panel-body">
<table className="table table-hover dataTable table-striped">
<thead>
{this.isNativeMode() ?
<tr>
<th>{ translate('INDEX.TYPE') }</th>
<th>{ translate('INDEX.ADDRESS') }</th>
<th>{ translate('INDEX.AMOUNT') }</th>
</tr>
:
<tr>
<th>{ translate('INDEX.TYPE') }</th>
<th>{ translate('INDEX.ADDRESS') }</th>
<th>{ translate('INDEX.BALANCE') }</th>
<th>{ translate('INDEX.INTEREST') }</th>
<th> {translate('INDEX.INTEREST') }</th>
</tr>
}
</thead>
<tbody>
{ this.renderAddressList() }
{this.renderAddressList('public')}
{this.isNativeMode() && this.renderAddressList('private')}
</tbody>
<tfoot>
{this.isNativeMode() ?
<tr>
<th>{ translate('INDEX.TYPE') }</th>
<th>{ translate('INDEX.ADDRESS') }</th>
<th>{ translate('INDEX.AMOUNT') }</th>
</tr>
:
<tr>
<th>{ translate('INDEX.TYPE') }</th>
<th>{ translate('INDEX.ADDRESS') }</th>
<th>{ translate('INDEX.BALANCE') }</th>
<th>{ translate('INDEX.INTEREST') }</th>
</tr>
}
</tfoot>
</table>
</div>

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

@ -235,6 +235,8 @@ export const SendCoinRender = function () {
name="amount"
placeholder="0.000"
autoComplete="off"
defaultValue={ this.state.amount }
value={ this.state.amount }
onChange={ this.updateInput } />
</div>
<div className="col-lg-6 form-group form-material">

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

@ -315,7 +315,7 @@ class Settings extends React.Component {
let _cliResponseParsed;
try {
_cliResponseParsed = JSON.parse(_cliResponse.result)
_cliResponseParsed = JSON.parse(_cliResponse.result);
} catch(e) {
_cliResponseParsed = _cliResponse.result;
}

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

@ -310,7 +310,7 @@ export const SettingsRender = function() {
id="wifkeysPassphrase"
onChange={ this.updateInput } />
<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>
<label
className="floating-label"

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

@ -74,8 +74,16 @@ class WalletsBalance extends React.Component {
return this.props.ActiveCoin.mode === coinMode;
}
isNativeOrBasiliskCoinMode() {
return this.isActiveCoinMode('native') || this.isActiveCoinMode('basilisk');
isBasiliskMode() {
return this.isActiveCoinMode('basilisk');
}
isNativeMode() {
return this.isActiveCoinMode('native');
}
isFullMode() {
return this.isActiveCoinMode('full');
}
renderLB(_translationID) {
@ -89,13 +97,21 @@ class WalletsBalance extends React.Component {
);
}
isNativeBalanceActive() {
return this.isNativeMode() && this.props.ActiveCoin.nativeActiveSection === 'default';
}
isNonNativeBalanceActive() {
return !this.isNativeMode() && !this.props.ActiveCoin.send && !this.props.ActiveCoin.receive;
}
render() {
if (this.props &&
this.props.ActiveCoin &&
this.props.ActiveCoin.coin &&
this.props.ActiveCoin.mode !== 'native' &&
!this.props.ActiveCoin.send &&
!this.props.ActiveCoin.receive) {
// TODO the conditions below should be merged when native mode is fully merged into the rest of the components
(this.isNativeBalanceActive() || this.isNonNativeBalanceActive()))
{
return WalletsBalanceRender.call(this);
}

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

@ -5,7 +5,7 @@ const WalletsBalanceRender = function() {
return (
<div id="wallet-widgets">
<div className="col-xs-12">
<div className={ this.isActiveCoinMode('native') || (this.isActiveCoinMode('full') && !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">
<button
className="close"
@ -31,17 +31,24 @@ const WalletsBalanceRender = function() {
</div>
</div>
<div className={ this.isNativeOrBasiliskCoinMode() ? '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-content">
<div className="padding-20 padding-top-10">
<div className="clearfix">
<div className="pull-left padding-vertical-10">
<i className="icon fa-eye font-size-24 vertical-align-bottom margin-right-5"></i>
{ translate('INDEX.BALANCE')}
{ this.isNativeMode() ? translate('INDEX.TRANSPARENT_BALANCE') : translate('INDEX.BALANCE') }
</div>
<span className="pull-right padding-top-10 font-size-22">
{ this.renderBalance('main') } { this.props.ActiveCoin.coin }
{ this.isNativeMode() ?
this.props.ActiveCoin.balance.transparent ? this.props.ActiveCoin.balance.transparent : '-'
:
<span>
{ this.renderBalance('main') } { this.props.ActiveCoin.coin }
</span>
}
</span>
</div>
</div>
@ -49,7 +56,26 @@ const WalletsBalanceRender = function() {
</div>
</div>
<div className={ this.isNativeOrBasiliskCoinMode() ? 'col-lg-4 col-xs-12' : 'col-lg-4 col-xs-12 hide' }>
{ this.isNativeMode() &&
<div className="col-lg-3 col-xs-12">
<div className="widget widget-shadow">
<div className="padding-20 padding-top-10">
<div className="clearfix">
<div className="pull-left padding-vertical-10">
<i className="icon fa-eye-slash font-size-24 vertical-align-bottom margin-right-5"></i>
{ translate('INDEX.Z_BALANCE') }
</div>
<span className="pull-right padding-top-10 font-size-22">
{ this.props.ActiveCoin.balance.private ? this.props.ActiveCoin.balance.private : '-' }
</span>
</div>
</div>
</div>
</div>
}
<div className={ this.isNativeMode() ? 'col-lg-3 col-xs-12' :
this.isBasiliskMode() ? 'col-lg-4 col-xs-12' : 'col-lg-4 col-xs-12 hide' }>
<div className="widget widget-shadow">
<div className="widget-content">
<div className="padding-20 padding-top-10">
@ -59,7 +85,14 @@ const WalletsBalanceRender = function() {
{ translate('INDEX.INTEREST_EARNED') }
</div>
<span className="pull-right padding-top-10 font-size-22">
{ this.renderBalance('interest') } { this.props.ActiveCoin.coin }
{ this.isNativeMode() ?
this.props.Dashboard.progress
&& this.props.Dashboard.progress.interest ? this.props.Dashboard.progress.interest : '-'
:
<span>
{this.renderBalance('interest')} {this.props.ActiveCoin.coin}
</span>
}
</span>
</div>
</div>
@ -67,7 +100,8 @@ const WalletsBalanceRender = function() {
</div>
</div>
<div className={ this.isNativeOrBasiliskCoinMode() ? 'col-lg-4 col-xs-12' : 'col-lg-4 col-xs-12 hide' }>
<div className={ this.isNativeMode() ? 'col-lg-3 col-xs-12' :
this.isBasiliskMode() ? 'col-lg-4 col-xs-12' : 'col-lg-4 col-xs-12 hide' }>
<div className="widget widget-shadow">
<div className="widget-content">
<div className="padding-20 padding-top-10">
@ -77,7 +111,13 @@ const WalletsBalanceRender = function() {
{ translate('INDEX.TOTAL_BALANCE') }
</div>
<span className="pull-right padding-top-10 font-size-22">
{ this.renderBalance('total') } { this.props.ActiveCoin.coin }
{ this.isNativeMode() ?
this.props.ActiveCoin.balance.total ? this.props.ActiveCoin.balance.total : '-'
:
<span>
{ this.renderBalance('total') } { this.props.ActiveCoin.coin }
</span>
}
</span>
</div>
</div>

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

@ -1,7 +1,7 @@
import React from 'react';
import { translate } from '../../../translate/translate';
import { animation } from '../../../util/rc-tree-animate';
import { TreeNode } from 'rc-tree';
import Tree, { TreeNode } from 'rc-tree';
const WalletsCacheDataRender = function() {
return (

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

@ -1,7 +1,6 @@
import React from 'react';
import WalletsNativeBalance from '../walletsNativeBalance/walletsNativeBalance';
import WalletsBalance from '../walletsBalance/walletsBalance';
import WalletsNativeInfo from '../walletsNativeInfo/walletsNativeInfo';
import WalletsNativeReceive from '../walletsNativeReceive/walletsNativeReceive';
import WalletsNativeSend from '../walletsNativeSend/walletsNativeSend';
import WalletsProgress from '../walletsProgress/walletsProgress';
import WalletsNativeTxHistory from '../walletsNativeTxHistory/walletsNativeTxHistory';
@ -26,9 +25,8 @@ const WalletsNativeRender = function() {
<div className="page-content">
<WalletsProgress {...this.props} />
<div className="row">
<WalletsNativeBalance {...this.props} />
<WalletsBalance {...this.props} />
<WalletsNativeTxHistory {...this.props} />
<WalletsNativeReceive {...this.props} />
<WalletsNativeSend {...this.props} />
<WalletsNativeInfo {...this.props} />
</div>

15
react/src/components/dashboard/walletsNativeBalance/walletsNativeBalance.js

@ -1,15 +0,0 @@
import React from 'react';
import WalletsNativeBalanceRender from './walletsNativeBalance.render';
class WalletsNativeBalance extends React.Component {
render() {
if (this.props &&
this.props.ActiveCoin.nativeActiveSection === 'default') {
return WalletsNativeBalanceRender.call(this);
}
return null;
}
}
export default WalletsNativeBalance;

82
react/src/components/dashboard/walletsNativeBalance/walletsNativeBalance.render.js

@ -1,82 +0,0 @@
import React from 'react';
import { translate } from '../../../translate/translate';
const WalletsNativeBalanceRender = function() {
return (
<div className="col-xs-12">
<div className="col-lg-3 col-xs-12">
<div className="widget widget-shadow">
<div className="widget-content white bg-yellow-800">
<div className="padding-20 padding-top-10">
<div className="clearfix">
<div className="pull-left padding-vertical-10">
<i className="icon fa-eye font-size-24 vertical-align-bottom margin-right-5"></i>
{ translate('INDEX.TRANSPARENT_BALANCE') }
</div>
<span className="pull-right padding-top-10 font-size-22">
{ this.props.ActiveCoin.balance.transparent ? this.props.ActiveCoin.balance.transparent : '-' }
</span>
</div>
</div>
</div>
</div>
</div>
<div className="col-lg-3 col-xs-12">
<div className="widget widget-shadow">
<div className="widget-content white bg-blue-grey-800">
<div className="padding-20 padding-top-10">
<div className="clearfix">
<div className="pull-left padding-vertical-10">
<i className="icon fa-eye-slash font-size-24 vertical-align-bottom margin-right-5"></i>
{ translate('INDEX.Z_BALANCE') }
</div>
<span className="pull-right padding-top-10 font-size-22">
{ this.props.ActiveCoin.balance.private ? this.props.ActiveCoin.balance.private : '-' }
</span>
</div>
</div>
</div>
</div>
</div>
<div className="col-lg-3 col-xs-12">
<div className="widget widget-shadow">
<div className="widget-content white bg-cyan-700">
<div className="padding-20 padding-top-10">
<div className="clearfix">
<div className="pull-left padding-vertical-10">
<i className="icon fa-money font-size-24 vertical-align-bottom margin-right-5"></i>
{ translate('INDEX.INTEREST_EARNED') }
</div>
<span className="pull-right padding-top-10 font-size-22">
{ this.props.Dashboard.progress && this.props.Dashboard.progress.interest ? this.props.Dashboard.progress.interest : '-' }
</span>
</div>
</div>
</div>
</div>
</div>
<div className="col-lg-3 col-xs-12">
<div className="widget widget-shadow">
<div className="widget-content white bg-green-600">
<div className="padding-20 padding-top-10">
<div className="clearfix">
<div className="pull-left padding-vertical-10">
<i className="icon fa-bullseye font-size-24 vertical-align-bottom margin-right-5"></i>
{ translate('INDEX.ZT_BALANCE') }
</div>
<span className="pull-right padding-top-10 font-size-22">
{ this.props.ActiveCoin.balance.total ? this.props.ActiveCoin.balance.total : '-' }
</span>
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default WalletsNativeBalanceRender;

94
react/src/components/dashboard/walletsNativeReceive/walletsNativeReceive.js

@ -1,94 +0,0 @@
import React from 'react';
import {
copyCoinAddress,
getNewKMDAddresses
} from '../../../actions/actionCreators';
import Store from '../../../store';
import {
AddressListRender,
WalletsNativeReceiveRender
} from './walletsNativeReceive.render';
class WalletsNativeReceive extends React.Component {
constructor(props) {
super(props);
this.state = {
openDropMenu: false,
};
this.openDropMenu = this.openDropMenu.bind(this);
this.handleClickOutside = this.handleClickOutside.bind(this);
}
componentWillMount() {
document.addEventListener(
'click',
this.handleClickOutside,
false
);
}
componentWillUnmount() {
document.removeEventListener(
'click',
this.handleClickOutside,
false
);
}
handleClickOutside(e) {
if (e.srcElement.className.indexOf('dropdown') === -1 &&
(e.srcElement.offsetParent && e.srcElement.offsetParent.className.indexOf('dropdown') === -1)) {
this.setState({
openDropMenu: false,
});
}
}
openDropMenu() {
this.setState(Object.assign({}, this.state, {
openDropMenu: !this.state.openDropMenu,
}));
}
copyZAddress(address) {
Store.dispatch(copyCoinAddress(address));
}
renderAddressList(type) {
if (this.props.ActiveCoin.addresses &&
this.props.ActiveCoin.addresses[type] &&
this.props.ActiveCoin.addresses[type].length) {
return this.props.ActiveCoin.addresses[type].map(
(address) =>
AddressListRender.call(
this,
address,
type
)
);
}
return null;
}
getNewAddress(type) {
Store.dispatch(
getNewKMDAddresses(
this.props.ActiveCoin.coin,
type
)
);
}
render() {
if (this.props &&
this.props.ActiveCoin &&
this.props.ActiveCoin.nativeActiveSection === 'receive') {
return WalletsNativeReceiveRender.call(this);
}
return null;
}
}
export default WalletsNativeReceive;

90
react/src/components/dashboard/walletsNativeReceive/walletsNativeReceive.render.js

@ -1,90 +0,0 @@
import React from 'react';
import { translate } from '../../../translate/translate';
export const AddressListRender = function(address, type) {
return (
<tr key={ address.address }>
<td>
<span className={ type === 'public' ? 'label label-default' : 'label label-dark' }>
<i className={ type === 'public' ? 'icon fa-eye' : 'icon fa-eye-slash' }></i>
{ type === 'public' ? translate('IAPI.PUBLIC_SM') : translate('KMD_NATIVE.PRIVATE') }
</span>
<button
className="btn btn-default btn-xs clipboard-edexaddr margin-left-10"
onClick={ () => this.copyZAddress(address.address) }>
<i className="icon wb-copy"></i> { translate('INDEX.COPY') }
</button>
</td>
<td>{ type === 'public' ? address.address : address.address.substring(0, 34) + '...' }</td>
<td>{ address.amount }</td>
<td></td>
</tr>
);
};
export const WalletsNativeReceiveRender = function() {
return (
<div>
<div className="col-xs-12 margin-top-20">
<div className="panel nav-tabs-horizontal">
<div>
<div className="col-xlg-12 col-lg-12 col-sm-12 col-xs-12">
<div className="panel">
<header className="panel-heading">
<div className="panel-actions">
<div
className={ 'dropdown' + (this.state.openDropMenu ? ' open' : '') }
onClick={ this.openDropMenu }>
<a className="dropdown-toggle white btn btn-warning">
<i className="icon md-arrows margin-right-10"></i>
{ translate('INDEX.GET_NEW_ADDRESS') }
<span className="caret"></span>
</a>
<ul className="dropdown-menu dropdown-menu-right">
<li>
<a onClick={ () => this.getNewAddress('public') }>
<i className="icon fa-eye"></i>
{ translate('INDEX.TRANSPARENT_ADDRESS') }
</a>
</li>
<li>
<a onClick={ () => this.getNewAddress('private') }>
<i className="icon fa-eye-slash"></i>
{ translate('INDEX.PRIVATE_Z_ADDRESS') }
</a>
</li>
</ul>
</div>
</div>
<h3 className="panel-title">{ translate('INDEX.RECEIVING_ADDRESS') }</h3>
</header>
<div className="panel-body">
<table className="table table-hover dataTable table-striped">
<thead>
<tr>
<th>{ translate('INDEX.TYPE') }</th>
<th>{ translate('INDEX.ADDRESS') }</th>
<th>{ translate('INDEX.AMOUNT') }</th>
</tr>
</thead>
<tbody>
{ this.renderAddressList('public') }
{ this.renderAddressList('private') }
</tbody>
<tfoot>
<tr>
<th>{ translate('INDEX.TYPE') }</th>
<th>{ translate('INDEX.ADDRESS') }</th>
<th>{ translate('INDEX.AMOUNT') }</th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
};

4
react/src/components/dashboard/walletsNativeSend/walletsNativeSend.js

@ -79,7 +79,7 @@ class WalletsNativeSend extends React.Component {
if (this.state.sendFrom) {
return (
<span>
<i className={ this.state.addressType === 'public' ? 'icon fa-eye' : 'icon fa-eye-slash' }></i>
<i className={ this.state.addressType === 'public' ? 'icon fa-eye' : 'icon fa-eye-slash' }></i>
<span className="text">
[ { this.state.sendFromAmount } { this.props.ActiveCoin.coin } ]
{ this.state.sendFrom }
@ -119,7 +119,7 @@ class WalletsNativeSend extends React.Component {
return (
<span className={ `label label-${_satatusDef[opid.status].icon}` }>
<i className="icon fa-eye"></i>
<i className="icon fa-eye"></i>&nbsp;
<span>{ translate(`KMD_NATIVE.${_satatusDef[opid.status].label}`) }</span>
</span>
);

44
react/src/components/dashboard/walletsNativeSend/walletsNativeSend.render.js

@ -11,8 +11,8 @@ export const AddressListRender = function() {
onClick={ this.openDropMenu }>
<span className="filter-option pull-left">{ this.renderSelectorCurrentLabel() } </span>
<span className="bs-caret">
<span className="caret"></span>
</span>
<span className="caret"></span>
</span>
</button>
<div className="dropdown-menu open">
<ul className="dropdown-menu inner">
@ -115,7 +115,9 @@ export const WalletsNativeSendRender = function() {
<div className="col-lg-6 form-group form-material">
<label
className="control-label"
htmlFor="kmdWalletFee">{ translate('INDEX.FEE') }</label>
htmlFor="kmdWalletFee">
{ translate('INDEX.FEE') }
</label>
<input
type="text"
className="form-control"
@ -128,8 +130,8 @@ export const WalletsNativeSendRender = function() {
</div>
<div className="col-lg-12">
<span>
<strong>{ translate('INDEX.TOTAL') }:</strong>
{ this.state.amount } - { this.state.fee }/kb = { Number(this.state.amount) - Number(this.state.fee) }
<strong>{ translate('INDEX.TOTAL') }:</strong>
{ this.state.amount } - { this.state.fee }/kb = { Number(this.state.amount) - Number(this.state.fee) }
{ this.props.ActiveCoin.coin }
</span>
</div>
@ -155,30 +157,32 @@ export const WalletsNativeSendRender = function() {
<div className="col-xlg-12 col-lg-12 col-sm-12 col-xs-12">
<div className="panel">
<header className="panel-heading">
<h3 className="panel-title">{ translate('INDEX.OPERATIONS_STATUSES') }</h3>
<h3 className="panel-title">
{ translate('INDEX.OPERATIONS_STATUSES') }
</h3>
</header>
<div className="panel-body">
<table
className="table table-hover dataTable table-striped"
width="100%">
<thead>
<tr>
<th>{ translate('INDEX.STATUS') }</th>
<th>ID</th>
<th>{ translate('INDEX.TIME') }</th>
<th>{ translate('INDEX.RESULT') }</th>
</tr>
</thead>
<tr>
<th>{ translate('INDEX.STATUS') }</th>
<th>ID</th>
<th>{ translate('INDEX.TIME') }</th>
<th>{ translate('INDEX.RESULT') }</th>
</tr>
</thead>
<tbody>
{ this.renderOPIDList() }
{ this.renderOPIDList() }
</tbody>
<tfoot>
<tr>
<th>{ translate('INDEX.STATUS') }</th>
<th>ID</th>
<th>{ translate('INDEX.TIME') }</th>
<th>{ translate('INDEX.RESULT') }</th>
</tr>
<tr>
<th>{ translate('INDEX.STATUS') }</th>
<th>ID</th>
<th>{ translate('INDEX.TIME') }</th>
<th>{ translate('INDEX.RESULT') }</th>
</tr>
</tfoot>
</table>
</div>

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

@ -0,0 +1,139 @@
import React from 'react';
import { translate } from '../../../translate/translate';
import {
ChainActivationNotificationRender,
WalletsNativeSyncProgressRender
} from './walletsNativeSyncProgress.render';
class WalletsNativeSyncProgress extends React.Component {
renderSyncPercentagePlaceholder() {
if (this.props.Dashboard.progress &&
this.props.Dashboard.progress.blocks > 0 &&
this.props.Dashboard.progress.longestchain === 0) {
return (
<div className="progress-bar progress-bar-info progress-bar-striped active full-width font-size-80-percent">
<span className="full-width">{ translate('INDEX.SYNC_ERR_LONGESTCHAIN') }</span>
</div>
);
} else if (this.props.Dashboard.progress && this.props.Dashboard.progress.blocks === 0) {
return (
<div className="progress-bar progress-bar-info progress-bar-striped active full-width font-size-80-percent">
<span className="full-width">{ translate('INDEX.SYNC_ERR_BLOCKS') }</span>
</div>
);
} else {
if (this.props.Dashboard.progress &&
this.props.Dashboard.progress.blocks) {
const syncPercentage = (parseFloat(parseInt(this.props.Dashboard.progress.blocks, 10) * 100 / parseInt(this.props.Dashboard.progress.longestchain, 10)).toFixed(2) + '%').replace('NaN', 0);
return (
<div
className="progress-bar progress-bar-info progress-bar-striped active font-size-80-percent"
style={{ width: syncPercentage }}>
<span style={{ width: syncPercentage }}>{ syncPercentage }</span> | { this.props.Dashboard.progress.blocks } / { this.props.Dashboard.progress.longestchain } | { translate('INDEX.CONNECTIONS') }: { this.props.Dashboard.progress.connections }
</div>
);
} else {
return (
<div
className="progress-bar progress-bar-info progress-bar-striped active font-size-80-percent"
style={{ width: '100%' }}>
<span style={{ width: '100%' }}>Loading blocks...it can take up to 15 min to load blocks</span>
</div>
);
}
}
}
renderActivatingBestChainProgress() {
if (this.props.Settings &&
this.props.Settings.debugLog) {
console.log('debugLog');
if (this.props.Settings.debugLog.indexOf('UpdateTip') > -1 &&
!this.props.Dashboard.progress &&
!this.props.Dashboard.progress.blocks) {
const temp = this.props.Settings.debugLog.split(' ');
let currentBestChain;
let currentProgress;
for (let i = 0; i < temp.length; i++) {
if (temp[i].indexOf('height=') > -1) {
currentBestChain = temp[i].replace('height=', '');
}
if (temp[i].indexOf('progress=') > -1) {
currentProgress = Number(temp[i].replace('progress=', '')) * 100;
}
}
// fallback to local data if remote node is inaccessible
if (this.props.Dashboard.progress.remoteKMDNode &&
!this.props.Dashboard.progress.remoteKMDNode.blocks) {
return (
`: ${currentProgress}% (activating)`
);
} else {
if (this.props.Dashboard.progress.remoteKMDNode &&
this.props.Dashboard.progress.remoteKMDNode.blocks) {
return(
`: ${Math.floor(currentBestChain * 100 / this.props.Dashboard.progress.remoteKMDNode.blocks)}% (blocks ${currentBestChain} / ${this.props.Dashboard.progress.remoteKMDNode.blocks})`
);
}
}
} else if (
this.props.Settings.debugLog.indexOf('Still rescanning') > -1 &&
!this.props.Dashboard.progress ||
!this.props.Dashboard.progress.blocks
) {
const temp = this.props.Settings.debugLog.split(' ');
let currentProgress;
for (let i = 0; i < temp.length; i++) {
if (temp[i].indexOf('Progress=') > -1) {
currentProgress = Number(temp[i].replace('Progress=', '')) * 100;
}
}
return (
`: ${currentProgress}% (rescanning blocks)`
);
} else {
return (
<span> (downloading blocks)</span>
);
}
}
}
renderLB(_translationID) {
const _translationComponents = translate(_translationID).split('<br>');
return _translationComponents.map((_translation) =>
<span>
{ _translation }
<br />
</span>
);
}
renderChainActivationNotification() {
if (this.props.Dashboard.progress) {
if ((!this.props.Dashboard.progress.blocks && !this.props.Dashboard.progress.longestchain) ||
(this.props.Dashboard.progress.blocks < this.props.Dashboard.progress.longestchain)) {
return ChainActivationNotificationRender.call(this);
}
} else {
return null;
}
}
render() {
if (this.props &&
this.props.Dashboard) {
return WalletsNativeSyncProgressRender.call(this);
}
return null;
}
}
export default WalletsNativeSyncProgress;

34
react/src/components/dashboard/walletsNativeSyncProgress/walletsNativeSyncProgress.render.js

@ -0,0 +1,34 @@
import React from 'react';
import { translate } from '../../../translate/translate';
export const ChainActivationNotificationRender = function() {
return (
<div className="alert alert-info alert-dismissible margin-bottom-40">
<button
className="close"
type="button">
<span>×</span>
</button>
<h4>
{ translate('INDEX.ACTIVATING_CHAIN') }
{ this.renderActivatingBestChainProgress() }
</h4>
<p>{ this.renderLB('INDEX.KMD_STARTED') }</p>
</div>
);
};
export const WalletsNativeSyncProgressRender = function() {
return (
<div>
{ this.renderChainActivationNotification() }
<div className="row sync-progress-container">
<div className="col-xs-12">
<div className="progress">
{ this.renderSyncPercentagePlaceholder() }
</div>
</div>
</div>
</div>
);
};

26
react/src/components/dashboard/walletsNotariesList/walletsNotariesList.render.js

@ -4,19 +4,21 @@ import Tree, { TreeNode } from 'rc-tree';
import { animation } from '../../../util/rc-tree-animate';
export const NotariesListRender = function (node, index) {
<TreeNode
title={ `Node ${index}` }
key={ `node-${index}` }>
<TreeNode
key={ `node-${index}-btc` }
title={ `BTC: ${node.BTCaddress}` } />
<TreeNode
key={ `node-${index}-kmd` }
title={ `KMD: ${node.KMDaddress}` } />
return (
<TreeNode
key={ `node-${index}-pubkey` }
title={ `Pubkey: ${node.pubkey}` } />
</TreeNode>
title={ `Node ${index}` }
key={ `node-${index}` }>
<TreeNode
key={ `node-${index}-btc` }
title={ `BTC: ${node.BTCaddress}` } />
<TreeNode
key={ `node-${index}-kmd` }
title={ `KMD: ${node.KMDaddress}` } />
<TreeNode
key={ `node-${index}-pubkey` }
title={ `Pubkey: ${node.pubkey}` } />
</TreeNode>
);
};
export const WalletsNotariesListRender = function () {

149
react/src/components/login/login.js

@ -1,21 +1,19 @@
import React from 'react';
import { translate } from '../../translate/translate';
import {
toggleAddcoinModal,
iguanaWalletPassphrase,
iguanaActiveHandle,
startInterval,
stopInterval,
getDexCoins,
toggleSyncOnlyModal,
getSyncOnlyForks,
createNewWallet
} from '../../actions/actionCreators';
import Store from '../../store';
import { PassPhraseGenerator } from '../../util/crypto/passphrasegenerator';
import {PassPhraseGenerator} from '../../util/crypto/passphrasegenerator';
import SwallModalRender from './swall-modal.render';
import LoginRender from './login.render';
import {translate} from '../../translate/translate';
const IGUNA_ACTIVE_HANDLE_TIMEOUT = 3000;
const IGUNA_ACTIVE_COINS_TIMEOUT = 10000;
@ -28,14 +26,19 @@ class Login extends React.Component {
activeLoginSection: 'activateCoin',
loginPassphrase: null,
seedInputVisibility: false,
loginPassPhraseSeedType: null,
bitsOption: 256,
randomSeed: PassPhraseGenerator.generatePassPhrase(256),
randomSeedConfirm: '',
isSeedConfirmError: false,
isSeedBlank: false,
displaySeedBackupModal: false,
customWalletSeed: false,
isCustomSeedWeak: false,
};
this.toggleActivateCoinForm = this.toggleActivateCoinForm.bind(this);
this.updateInput = this.updateInput.bind(this);
this.updateRegisterConfirmPassPhraseInput = this.updateRegisterConfirmPassPhraseInput.bind(this);
this.updateLoginPassPhraseInput = this.updateLoginPassPhraseInput.bind(this);
this.loginSeed = this.loginSeed.bind(this);
this.toggleSeedInputVisibility = this.toggleSeedInputVisibility.bind(this);
this.handleRegisterWallet = this.handleRegisterWallet.bind(this);
@ -44,6 +47,31 @@ class Login extends React.Component {
this.execWalletCreate = this.execWalletCreate.bind(this);
}
isCustomWalletSeed() {
return this.state.customWalletSeed;
}
toggleCustomWalletSeed() {
this.setState({
customWalletSeed: !this.state.customWalletSeed
}, () => {
// if customWalletSeed is set to false, regenerate the seed
if (!this.state.customWalletSeed) {
this.setState({
randomSeed: PassPhraseGenerator.generatePassPhrase(this.state.bitsOption),
isSeedConfirmError: false,
isSeedBlank: false
});
} else {
// if customWalletSeed is set to true, reset to seed to an empty string
this.setState({
randomSeed: '',
randomSeedConfirm: ''
});
}
});
}
openSyncOnlyModal() {
Store.dispatch(getSyncOnlyForks());
@ -74,21 +102,22 @@ class Login extends React.Component {
this.setState(Object.assign({}, this.state, {
randomSeed: PassPhraseGenerator.generatePassPhrase(bits),
bitsOption: bits,
isSeedBlank: false
}));
}
componentWillReceiveProps(props) {
if (props &&
props.Main &&
props.Main.isLoggedIn) {
props.Main &&
props.Main.isLoggedIn) {
this.setState({
display: false,
});
}
if (props &&
props.Main &&
!props.Main.isLoggedIn) {
props.Main &&
!props.Main.isLoggedIn) {
this.setState({
display: true,
});
@ -105,8 +134,8 @@ class Login extends React.Component {
if (this.state.activeLoginSection !== 'signup') {
if (props &&
props.Main &&
props.Main.activeCoins) {
props.Main &&
props.Main.activeCoins) {
this.setState({
activeLoginSection: 'login',
});
@ -122,23 +151,84 @@ class Login extends React.Component {
Store.dispatch(toggleAddcoinModal(true, false));
}
updateInput(e) {
updateLoginPassPhraseInput(e) {
// remove any empty chars from the start/end of the string
const newValue = e.target.value ? e.target.value.trim() : null;
this.setState({
[e.target.name]: newValue,
loginPassPhraseSeedType: this.getLoginPassPhraseSeedType(newValue)
});
}
updateRegisterConfirmPassPhraseInput(e) {
this.setState({
[e.target.name]: e.target.value,
isSeedConfirmError: false,
isSeedBlank: this.isBlank(e.target.value)
});
}
updateWalletSeed(e) {
this.setState({
randomSeed: e.target.value,
isSeedConfirmError: false,
isSeedBlank: this.isBlank(e.target.value)
});
}
loginSeed() {
// reset the login pass phrase values so that when the user logs out, the values are clear
this.setState({
loginPassphrase: null,
loginPassPhraseSeedType: null,
});
Store.dispatch(
iguanaWalletPassphrase(this.state.loginPassphrase)
);
}
getLoginPassPhraseSeedType(passPhrase) {
if (!passPhrase) {
return null;
}
const passPhraseWords = passPhrase.split(" ");
if (!PassPhraseGenerator.arePassPhraseWordsValid(passPhraseWords))
return null;
if (PassPhraseGenerator.isPassPhraseValid(passPhraseWords, 256)) {
return translate('LOGIN.IGUANA_SEED');
}
if (PassPhraseGenerator.isPassPhraseValid(passPhraseWords, 160)) {
return translate('LOGIN.WAVES_SEED');
}
if (PassPhraseGenerator.isPassPhraseValid(passPhraseWords, 128)) {
return translate('LOGIN.NXT_SEED');
}
return null;
}
updateActiveLoginSection(name) {
// reset login/create form
this.setState({
activeLoginSection: name,
});
loginPassphrase: null,
loginPassPhraseSeedType: null,
seedInputVisibility: false,
bitsOption: 256,
randomSeed: PassPhraseGenerator.generatePassPhrase(256),
randomSeedConfirm: '',
isSeedConfirmError: false,
isSeedBlank: false,
displaySeedBackupModal: false,
customWalletSeed: false,
isCustomSeedWeak: false,
});
}
execWalletCreate() {
@ -156,16 +246,36 @@ class Login extends React.Component {
});
}
// TODO:
// 1) disable register btn if seed or seed conf is incorrect
// 2) display explicit custom seed validation message
handleRegisterWallet() {
if (this.state.randomSeed === this.state.randomSeedConfirm) {
const enteredSeedsMatch = this.state.randomSeed === this.state.randomSeedConfirm;
const isSeedBlank = this.isBlank(this.state.randomSeed);
// if custom seed check for string strength
// at least 1 letter in upper case
// at least 1 digit
// at least one special char
// min length 10 chars
const _customSeed = this.state.customWalletSeed ? this.state.randomSeed.match('^(?=.*[A-Z])(?=.*[^<>{}\"/|;:.,~!?@#$%^=&*\\]\\\\()\\[_+]*$)(?=.*[0-9])(?=.*[a-z]).{10,99}$') : false;
this.setState({
isCustomSeedWeak: _customSeed === null ? true : false,
isSeedConfirmError: !enteredSeedsMatch ? true : false,
isSeedBlank: isSeedBlank ? true : false,
});
if (enteredSeedsMatch && !isSeedBlank && _customSeed !== null) {
this.toggleSeedBackupModal();
} else {
this.setState({
isSeedConfirmError: true,
});
}
}
isBlank(str) {
return (!str || /^\s*$/.test(str));
}
handleKeydown(e) {
if (e.key === 'Enter') {
this.loginSeed();
@ -187,8 +297,7 @@ class Login extends React.Component {
}
render() {
if ((this.state && this.state.display) ||
!this.props.Main) {
if ((this.state && this.state.display) || !this.props.Main) {
return LoginRender.call(this);
}

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

@ -6,7 +6,7 @@ const LoginRender = function () {
<div>
{ this.renderSwallModal() }
<div className="page animsition vertical-align text-center fade-in">
<div className="page-content vertical-align-middle">
<div className="page-content vertical-align-middle col-xs-12 col-sm-6 col-sm-offset-3">
<div className="brand">
<img
className="brand-img"
@ -25,12 +25,16 @@ const LoginRender = function () {
<div className={ this.state.activeLoginSection === 'ieWarning' ? 'show' : 'hide' }>
<div className="panel">
<div className="panel-heading">
<h3 className="panel-title">{ translate('INDEX.UNSUPPORTED_BROWSER') }</h3>
<h3 className="panel-title">
{ translate('INDEX.UNSUPPORTED_BROWSER') }
</h3>
</div>
<div className="alert alert-danger alert-dismissible">
<button type="button">
<span>&times;</span>
<span className="sr-only">{ translate('INDEX.CLOSE') }</span>
<span className="sr-only">
{ translate('INDEX.CLOSE') }
</span>
</button>
{ translate('INDEX.IE_UNSUPPORTED') }
</div>
@ -49,54 +53,69 @@ const LoginRender = function () {
</div>
<div className={ this.state.activeLoginSection === 'login' ? 'show' : 'hide' }>
<h4 className="color-white">{translate('INDEX.WELCOME_LOGIN')}</h4>
<div className="login-form">
<div className="form-group form-material floating">
<input
type={ this.state.seedInputVisibility ? 'text' : 'password' }
className="form-control"
name="loginPassphrase"
onChange={ this.updateInput }
onKeyDown={ (event) => this.handleKeydown(event) } />
<i
className={ this.state.seedInputVisibility ? 'seed-toggle fa fa-eye-slash' : 'seed-toggle fa fa-eye' }
onClick={ this.toggleSeedInputVisibility }></i>
<label
className="floating-label"
htmlFor="inputPassword">{ translate('INDEX.WALLET_SEED') }</label>
</div>
<h4 className="color-white">
{translate('INDEX.WELCOME_LOGIN')}
</h4>
<div className="form-group form-material floating col-sm-9 horizontal-padding-0">
<input
type={ this.state.seedInputVisibility ? 'text' : 'password' }
className="form-control"
name="loginPassphrase"
onChange={ this.updateLoginPassPhraseInput }
onKeyDown={ (event) => this.handleKeydown(event) }/>
<i
className={ !this.state.seedInputVisibility ? 'seed-toggle fa fa-eye-slash' : 'seed-toggle fa fa-eye' }
onClick={ this.toggleSeedInputVisibility }></i>
<label
className="floating-label"
htmlFor="inputPassword">{ translate('INDEX.WALLET_SEED') }</label>
</div>
<div className="form-group form-material floating col-sm-3 horizontal-padding-0 margin-top-20">
{ this.state.loginPassPhraseSeedType
?
this.state.loginPassPhraseSeedType
:
<div className="placeholder-label">Seed Type</div>
}
</div>
<button
type="button"
className="btn btn-primary btn-block"
onClick={ this.loginSeed }
disabled={ !this.state.loginPassphrase
|| !this.state.loginPassphrase.length }>{ translate('INDEX.SIGN_IN') }</button>
<div className="form-group form-material floating">
<button
type="button"
className="btn btn-primary btn-block"
onClick={ this.loginSeed }
disabled={ !this.state.loginPassphrase || !this.state.loginPassphrase.length }>{ translate('INDEX.SIGN_IN') }</button>
<div className="form-group form-material floating">
<button
className="btn btn-lg btn-flat btn-block waves-effect"
id="register-btn"
onClick={ () => this.updateActiveLoginSection('signup') }>{ translate('INDEX.CREATE_WALLET') }</button>
<button
className="btn btn-lg btn-flat btn-block waves-effect hide"
id="logint-another-wallet">{ translate('INDEX.LOGIN_ANOTHER_WALLET') }</button>
<button
className="btn btn-lg btn-flat btn-block waves-effect margin-top-20"
id="register-btn"
onClick={ this.toggleActivateCoinForm }
disabled={ !this.props.Main }>
<span className="ladda-label">{ translate('ADD_COIN.ADD_ANOTHER_COIN') }</span>
</button>
</div>
className="btn btn-lg btn-flat btn-block waves-effect"
id="register-btn"
onClick={ () => this.updateActiveLoginSection('signup') }>{ translate('INDEX.CREATE_WALLET') }</button>
<button
className="btn btn-lg btn-flat btn-block waves-effect hide"
id="logint-another-wallet">{ translate('INDEX.LOGIN_ANOTHER_WALLET') }</button>
<button
className="btn btn-lg btn-flat btn-block waves-effect margin-top-20"
id="register-btn"
onClick={ this.toggleActivateCoinForm }
disabled={ !this.props.Main }>
<span className="ladda-label">
{ translate('ADD_COIN.ADD_ANOTHER_COIN') }
</span>
</button>
</div>
</div>
<div className={ this.state.activeLoginSection === 'activateCoin' ? 'show' : 'hide' }>
<h4 className="color-white">{ translate('INDEX.WELCOME_PLEASE_ADD') }</h4>
<div className="form-group form-material floating width-540 vertical-margin-30 horizontal-margin-0">
<h4 className="color-white">
{ translate('INDEX.WELCOME_PLEASE_ADD') }
</h4>
<div className="form-group form-material floating width-540 vertical-margin-30 auto-side-margin">
<button
className="btn btn-lg btn-primary btn-block ladda-button"
onClick={ this.toggleActivateCoinForm }
disabled={ !this.props.Main }>
<span className="ladda-label">{ translate('INDEX.ACTIVATE_COIN') }</span>
<span className="ladda-label">
{ translate('INDEX.ACTIVATE_COIN') }
</span>
</button>
</div>
</div>
@ -106,42 +125,86 @@ const LoginRender = function () {
<h4 className="hint color-white">
{ translate('INDEX.SELECT_SEED_TYPE') }:
</h4>
<div className="form-group form-material floating">
<div
className="radio-custom radio-default radio-inline"
onClick={ () => this.generateNewSeed(256) }>
<input
type="radio"
name="PassPhraseOptions"
checked={ this.state.bitsOption === 256 ? true : false } />
<label htmlFor="PassPhraseOptionsIguana">Iguana (256 bits)</label>
<div className="row">
<div className="col-sm-5 horizontal-padding-0">
<div className="toggle-box vertical-padding-20">
<span className="pointer">
<label className="switch">
<input
type="checkbox"
checked={ this.isCustomWalletSeed() } />
<div
className="slider"
onClick={ () => this.toggleCustomWalletSeed() }></div>
</label>
<div
className="toggle-label white"
onClick={ () => this.toggleCustomWalletSeed() }>
{ translate('LOGIN.CUSTOM_WALLET_SEED') }
</div>
</span>
</div>
</div>
<div
className="radio-custom radio-default radio-inline"
onClick={ () => this.generateNewSeed(160) }>
<input
type="radio"
name="PassPhraseOptions"
checked={ this.state.bitsOption === 160 ? true : false } />
<label htmlFor="PassPhraseOptionsWaves">Waves</label>
</div>
<div
className="radio-custom radio-default radio-inline"
onClick={ () => this.generateNewSeed(128) }>
<input
type="radio"
name="PassPhraseOptions"
checked={ this.state.bitsOption === 128 ? true : false } />
<label htmlFor="PassPhraseOptionsNXT">NXT</label>
<div className="col-sm-7 horizontal-padding-0">
{ !this.isCustomWalletSeed() &&
<div>
<div className="form-group form-material floating">
<div
className="radio-custom radio-default radio-inline"
onClick={ () => this.generateNewSeed(256) }>
<input
type="radio"
name="PassPhraseOptions"
checked={ this.state.bitsOption === 256 }/>
<label htmlFor="PassPhraseOptionsIguana">
{ translate('LOGIN.IGUANA_SEED') }
</label>
</div>
<div
className="radio-custom radio-default radio-inline"
onClick={ () => this.generateNewSeed(160) }>
<input
type="radio"
name="PassPhraseOptions"
checked={ this.state.bitsOption === 160 }/>
<label htmlFor="PassPhraseOptionsWaves">
{ translate('LOGIN.WAVES_SEED') }
</label>
</div>
<div
className="radio-custom radio-default radio-inline"
onClick={ () => this.generateNewSeed(128) }>
<input
type="radio"
name="PassPhraseOptions"
checked={ this.state.bitsOption === 128 }/>
<label htmlFor="PassPhraseOptionsNXT">
{ translate('LOGIN.NXT_SEED') }
</label>
</div>
</div>
</div>
}
</div>
</div>
<div className="form-group form-material floating">
<div className="form-group form-material floating seed-tooltip">
<textarea
className="form-control placeholder-no-fix height-100"
type="text"
id="walletseed"
value={ this.state.randomSeed }
readOnly="true"></textarea>
onChange={ (e) => this.updateWalletSeed(e) }
readOnly={ !this.isCustomWalletSeed() }
></textarea>
<span className={ this.state.isCustomSeedWeak ? 'tooltiptext' : 'hide' }>
<strong>Weak seed!</strong><br /><br />
Your seed must contain:<br />
- at least 1 upper case letter<br />
- at least 1 digit<br />
- at least 1 special character<br />
- minimum 10 characters long
</span>
<label
className="floating-label"
htmlFor="walletseed">{ translate('INDEX.WALLET_SEED') }</label>
@ -151,9 +214,15 @@ const LoginRender = function () {
className="form-control placeholder-no-fix height-100"
type="text"
name="randomSeedConfirm"
onChange={ this.updateInput }
value={ this.state.randomSeedConfirm }
onChange={ this.updateRegisterConfirmPassPhraseInput }
id="rwalletseed"></textarea>
<span className={ this.state.isSeedConfirmError ? 'help-block' : 'hide' }>{ translate('LOGIN.ENTER_VALUE_AGAIN') }.</span>
<span className={ this.state.isSeedBlank ? 'help-block' : 'hide' }>
{ translate('LOGIN.MUST_ENTER_SEED') }.
</span>
<span className={ this.state.isSeedConfirmError ? 'help-block' : 'hide' }>
{ translate('LOGIN.ENTER_VALUE_AGAIN') }.
</span>
<label
className="floating-label"
htmlFor="rwalletseed">{ translate('INDEX.CONFIRM_SEED') }</label>

40
react/src/components/login/login.scss

@ -32,6 +32,11 @@ button {
padding-bottom: 20px;
}
.horizontal-padding-0 {
padding-left: 0;
padding-right: 0;
}
.browser-usage-container {
color: #424242;
}
@ -49,4 +54,39 @@ textarea {
&.height-100 {
height: 100px;
}
}
.placeholder-label {
color: #808080;
}
.seed-tooltip {
.tooltiptext {
width: 230px;
padding: 10px 20px;
background-color: black;
color: #fff;
text-align: left;
border-radius: 6px;
position: absolute;
z-index: 1;
top: -5px;
left: 105%;
&::after {
content: '';
position: absolute;
top: 50%;
right: 100%;
margin-top: -5px;
border-width: 5px;
border-style: solid;
border-color: transparent black transparent transparent;
}
}
}
.auto-side-margin {
margin-left: auto;
margin-right: auto;
}

4
react/src/config.js

@ -6,4 +6,8 @@ module.exports = {
openAlias: false,
debug: true,
defaultLang: 'EN',
cli: {
passthru: true,
default: true
}
};

9
react/src/translate/en.js

@ -401,7 +401,14 @@ export const _lang = {
'SIGN_IN': 'Sign In',
'WELCOME': 'Welcome',
'DISPLAY_SYNC_ONLY': 'Display sync only coins progress',
'ENTER_VALUE_AGAIN': 'Please enter the same value again'
'ENTER_VALUE_AGAIN': 'Please enter the same value again',
'CUSTOM_WALLET_SEED': 'Custom wallet seed',
'MUST_ENTER_SEED': 'You must enter a seed',
'INVALID_SEED': 'Invalid Seed',
'SEED_NOT_OF_TYPE': 'The inserted seed is not of type',
'IGUANA_SEED': 'Iguana (256 bits)',
'WAVES_SEED': 'Waves',
'NXT_SEED': 'NXT'
},
'SIDEBAR': {
'EDEX_MOTTO': 'Most Secure, Easy and Native Decentralised Exchange',

24
react/src/util/crypto/passphrasegenerator.js

@ -80,6 +80,30 @@ export const PassPhraseGenerator = {
return this.passPhrase;
},
// checks if it's possible that the pass phrase words supplied as the first parameter
// were generated with the number of bits supplied as the second parameter
isPassPhraseValid: function (passPhraseWords, bits) {
// the required number of words based on the number of bits
// mirrors the generatePassPhrase function above
const wordsCount = bits / 32 * 3;
return passPhraseWords && passPhraseWords.length === wordsCount;
},
// checks if all pass phrase words are valid
// i.e. checks if all words are contained in ClientWordList
arePassPhraseWordsValid: function(passPhraseWords) {
if (!passPhraseWords) {
return false;
}
for (let word of passPhraseWords) {
if (this.words.indexOf(word) === -1)
return false;
}
return true;
},
reset: function() {
this.passPhrase = "";
this.seeds = 0;

2
react/www/index.html

@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui">
<meta name="description" content="bootstrap admin template">
<meta name="author" content="SuperNET Team">
<title>Agama (v0.2.0.1a-beta)</title>
<title>Agama (v0.2.0.2a-beta)</title>
<link rel="apple-touch-icon" href="assets/images/android-chrome-192x192.png">
<link rel="icon" type="image/png" href="assets/images/favicon-32x32.png" sizes="32x32">
<link rel="icon" type="image/png" href="assets/images/favicon-194x194.png" sizes="194x194">

Loading…
Cancel
Save