Browse Source

Merge pull request #108 from pbca26/redux

Redux
all-modes
pbca26 8 years ago
committed by GitHub
parent
commit
236f7d48fb
  1. 1
      .gitignore
  2. 171
      react/src/actions/actionCreators.js
  3. 8
      react/src/components/addcoin/addcoinOptionsCrypto.js
  4. 1
      react/src/components/app/app.js
  5. 116
      react/src/components/dashboard/sendCoin.js
  6. 18
      react/src/components/dashboard/walletsBalance.js
  7. 23
      react/src/components/login/login.js
  8. 2
      react/src/components/main/walletMain.js
  9. 2
      react/src/reducers/index.js
  10. 41
      react/src/styles/index.scss
  11. 41
      react/src/util/cacheFormat.js

1
.gitignore

@ -0,0 +1 @@
react

171
react/src/actions/actionCreators.js

@ -47,9 +47,20 @@ export const DASHBOARD_GET_NOTARIES_LIST = 'DASHBOARD_GET_NOTARIES_LIST';
export const DASHBOARD_DISPLAY_NOTARIES_MODAL = 'DASHBOARD_DISPLAY_NOTARIES_MODAL';
export const DASHBOARD_CONNECT_NOTARIES = 'DASHBOARD_CONNECT_NOTARIES';
export const VIEW_CACHE_DATA = 'VIEW_CACHE_DATA';
export const SYNC_ONLY_MODAL_TOGGLE = 'SYNC_ONLY_MODAL_TOGGLE';
export const SYNC_ONLY_DATA = 'SYNC_ONLY_DATA';
export const LOAD_APP_CONFIG = 'LOAD_APP_CONFIG';
export const SAVE_APP_CONFIG = 'SAVE_APP_CONFIG';
var iguanaForks = {}; // forks in mem array
export function toggleSyncOnlyModal(display) {
return {
type: SYNC_ONLY_MODAL_TOGGLE,
display,
}
}
export function toggleViewCacheModal(display) {
return {
type: VIEW_CACHE_DATA,
@ -305,7 +316,7 @@ export function dismissToasterMessage() {
}
}
export function addCoin(coin, mode, syncOnly) {
export function addCoin(coin, mode, syncOnly, port) {
console.log('coin, mode, syncOnly', coin + ' ' + mode + ' ' + syncOnly);
/*startIguanaInstance(mode, coin)
.then(function(json) {
@ -343,22 +354,30 @@ export function addCoin(coin, mode, syncOnly) {
return dispatch => {
startIguanaInstance(modeToValue[mode] + '/sync', coin)
.then(function(json) {
console.log('started ' + coin + ' / ' + modeToValue[mode] + ' fork', json);
dispatch(iguanaAddCoin(coin, mode, _acData));
setTimeout(function() {
console.log('started ' + coin + ' / ' + modeToValue[mode] + ' fork', json);
dispatch(iguanaAddCoin(coin, mode, _acData, json.result));
}, 2000);
});
}
} else {
return dispatch => {
dispatch(iguanaAddCoin(coin, mode, _acData));
if (port) {
return dispatch => {
dispatch(iguanaAddCoin(coin, mode, _acData, port));
}
} else {
return dispatch => {
dispatch(iguanaAddCoin(coin, mode, _acData));
}
}
}
}
}
}
export function iguanaAddCoin(coin, mode, acData) {
export function iguanaAddCoin(coin, mode, acData, port) {
function _iguanaAddCoin(dispatch) {
return fetch('http://127.0.0.1:' + Config.iguanaCorePort, {
return fetch('http://127.0.0.1:' + (port ? port : Config.iguanaCorePort), {
method: 'POST',
body: JSON.stringify(acData),
})
@ -2094,6 +2113,25 @@ export function deleteCacheFile(_payload) {
}
}
export function getCacheFile() {
const _pubkey = JSON.parse(sessionStorage.getItem('IguanaActiveAccount')).pubkey;
return new Promise((resolve, reject) => {
fetch('http://127.0.0.1:' + Config.agamaPort + '/shepherd/groom?pubkey=' + _pubkey, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
.catch(function(error) {
console.log(error);
dispatch(triggerToaster(true, 'getCacheFile', 'Error', 'error'))
})
.then(response => response.json())
.then(json => resolve(json))
})
}
export function fetchNewCacheData(_payload) {
console.log('fetchNewCacheData', true);
const _userpass = '?userpass=tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
@ -2364,6 +2402,125 @@ export function dexSendRawTX(data) {
});
}
export function edexGetTransaction(data) {
const payload = {
'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
'symbol': data.coin,
'agent': 'dex',
'method': 'gettransaction',
'vout': 1,
'txid': data.txid
};
console.log('edexGetTransaction', payload);
return new Promise((resolve, reject) => {
fetch('http://127.0.0.1:' + Config.iguanaCorePort, {
method: 'POST',
body: JSON.stringify(payload),
})
.catch(function(error) {
console.log(error);
dispatch(triggerToaster(true, 'edexGetTransaction', 'Error', 'error'));
})
.then(response => response.json())
.then(json => resolve(json))
});
}
/*export function saveAppConfig() {
const payload = {
'herdname': target,
'lastLines': linesCount
};
return dispatch => {
return fetch('http://127.0.0.1:' + Config.agamaPort + '/shepherd/debuglog', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
})
.catch(function(error) {
console.log(error);
dispatch(triggerToaster(true, 'getDebugLog', 'Error', 'error'));
})
.then(response => response.json())
.then(json => dispatch(getDebugLogState(json)))
}
}*/
function getAppConfigState(json) {
return {
type: LOAD_APP_CONFIG,
config: json,
}
}
export function getAppConfig() {
return dispatch => {
return fetch('http://127.0.0.1:' + Config.agamaPort + '/shepherd/appconf', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
.catch(function(error) {
console.log(error);
dispatch(triggerToaster(true, 'getAppConfig', 'Error', 'error'));
})
.then(response => response.json())
.then(json => dispatch(getAppConfigState(json)))
}
}
function getSyncOnlyForksState(json) {
/*try {
JSON.parse(json.result);
} catch(e) {
console.log(e);
}*/
return {
type: SYNC_ONLY_DATA,
forks: JSON.parse(json.result),
}
}
export function getSyncOnlyForks() {
return dispatch => {
return fetch('http://127.0.0.1:' + Config.agamaPort + '/shepherd/forks/info/show', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
.catch(function(error) {
console.log(error);
dispatch(triggerToaster(true, 'getSyncOnlyForks', 'Error', 'error'));
})
.then(response => response.json())
.then(json => dispatch(getSyncOnlyForksState(json)))
}
}
export function stopIguanaFork(pmid) {
return dispatch => {
return fetch('http://127.0.0.1:' + Config.agamaPort + '/shepherd/forks/stop?pmid=' + pmid, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
.catch(function(error) {
console.log(error);
dispatch(triggerToaster(true, 'stopIguanaFork', 'Error', 'error'));
})
.then(response => response.json())
.then(json => dispatch(triggerToaster(true, 'Iguana instance is stopped', translate('TOASTR.SERVICE_NOTIFICATION'), 'success')))
}
}
/*function Shepherd_SendPendValue() {
Shepherd_SysInfo().then(function(result){
var ram_data = formatBytes(result.totalmem_bytes)

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

@ -3,13 +3,13 @@ import { translate } from '../../translate/translate';
class AddCoinOptionsCrypto extends React.Component {
render() {
//<option value="ANC|full" data-full-mode="true">AnonCoin (ANC)</option>
//<option value="BTCD|full">BitcoinDark (BTCD)</option>
//<option value="MZC|full">MazaCoin (MZC)</option>
//<option value="SYS|full">SysCoin (SYS)</option>
return (
<optgroup label="Crypto Currencies">
<option value="BTCD|full">BitcoinDark (BTCD)</option>
<option value="BTC|full|basilisk">Bitcoin (BTC)</option>
<option value="ANC|full" data-full-mode="true">AnonCoin (ANC)</option>
<option value="MZC|full">MazaCoin (MZC)</option>
<option value="SYS|full">SysCoin (SYS)</option>
<option value="BTM|full">Bitmark (BTM)</option>
<option value="CARB|full">Carboncoin (CARB)</option>
<option value="DGB|full">Digibyte (DGB)</option>

1
react/src/components/app/app.js

@ -13,6 +13,7 @@ function mapStateToProps(state) {
Atomic: state.Atomic,
Settings: state.Settings,
Interval: state.Interval,
SyncOnly: state.SyncOnly,
};
}

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

@ -1,7 +1,12 @@
import React from 'react';
import Config from '../../config';
import { translate } from '../../translate/translate';
import { checkTimestamp, secondsElapsedToString, secondsToString } from '../../util/time';
import {
checkTimestamp,
secondsElapsedToString,
secondsToString
} from '../../util/time';
import { edexGetTxIDList, edexRemoveTXID } from '../../util/cacheFormat';
import {
sendToAddress,
sendFromAddress,
@ -14,7 +19,9 @@ import {
sendToAddressStateAlt,
dexSendRawTX,
fetchUtxoCache,
basiliskRefresh
basiliskRefresh,
edexGetTransaction,
getCacheFile
} from '../../actions/actionCreators';
import Store from '../../store';
@ -39,6 +46,26 @@ class SendCoin extends React.Component {
addressSelectorOpen: false,
currentStackLength: 0,
totalStackLength: 0,
vin: [
{
"txid": "8f5d3bc7ff1d8abdedefa4ed71c2a085a5fec62b8491c08e4a6ed53925df0235",
"vout": 0,
"scriptSig": {
"asm": "3045022100ea6442b209ab48b7109f13399fa12f85915ee2204a21698b85454987d9303fe1022025e4630c684af9b982b243420d69e094d0fc708aaccf11b83fd9320fe4dd45f701 02bee71575d87c7285eda952358175af10879081a0cc6b94623aac6cb2c6a51eae",
"hex": "483045022100ea6442b209ab48b7109f13399fa12f85915ee2204a21698b85454987d9303fe1022025e4630c684af9b982b243420d69e094d0fc708aaccf11b83fd9320fe4dd45f7012102bee71575d87c7285eda952358175af10879081a0cc6b94623aac6cb2c6a51eae"
},
"sequence": 4294967295
},
{
"txid": "4cfb597119d4239e8fa75486d1ba4c62cef615a52568aca1bc9be3b457c12eac",
"vout": 0,
"scriptSig": {
"asm": "3044022001c1481b5fb142a1f38f8387c8d0ba6e4d6c6a96a8c6765ce805ce841cb2a58b02206caec099e209a469b78c22c674be77d92698fff94b4521c0d5e462ac5b19627c01 02bee71575d87c7285eda952358175af10879081a0cc6b94623aac6cb2c6a51eae",
"hex": "473044022001c1481b5fb142a1f38f8387c8d0ba6e4d6c6a96a8c6765ce805ce841cb2a58b02206caec099e209a469b78c22c674be77d92698fff94b4521c0d5e462ac5b19627c012102bee71575d87c7285eda952358175af10879081a0cc6b94623aac6cb2c6a51eae"
},
"sequence": 4294967295
}
]
};
this.updateInput = this.updateInput.bind(this);
this.handleBasiliskSend = this.handleBasiliskSend.bind(this);
@ -214,6 +241,12 @@ class SendCoin extends React.Component {
sendFromAmount: amount ? amount : this.props.ActiveCoin.addresses[type][address].amount,
addressSelectorOpen: !this.state.addressSelectorOpen,
}));
this.renderCachedUTXOInfo();
}
renderCachedUTXOInfo() {
}
changeSendCoinStep(step) {
@ -229,7 +262,6 @@ class SendCoin extends React.Component {
} else {
Store.dispatch(sendToAddress(this.props.ActiveCoin.coin, this.state));
}
//Store.dispatch(sendFromAddress(this.props.ActiveCoin.coin, this.state));
}
}
@ -273,20 +305,84 @@ class SendCoin extends React.Component {
Store.dispatch(triggerToaster(true, translate('TOASTR.SIGNED_TX_GENERATED') + '.', translate('TOASTR.WALLET_NOTIFICATION'), 'success'));
if (sendData.sendsig === 1) {
//Store.dispatch(triggerToaster(true, translate('TOASTR.SENDING_TX') + '.', translate('TOASTR.WALLET_NOTIFICATION'), 'success'));
// Store.dispatch(triggerToaster(true, translate('TOASTR.SENDING_TX') + '.', translate('TOASTR.WALLET_NOTIFICATION'), 'success'));
const dexrawtxData = {
'signedtx': json.signedtx,
'coin': sendData.coin
};
dexSendRawTX(dexrawtxData)
.then(function(dexRawTxJson) {
console.log('dexRawTxJson', dexRawTxJson);
if (dexRawTxJson.indexOf('"error":{"code"') > -1) {
.then(function(dexRawTxJSON) {
console.log('dexRawTxJSON', dexRawTxJSON);
if (dexRawTxJSON.indexOf('"error":{"code"') > -1) {
Store.dispatch(triggerToaster(true, 'Transaction failed', translate('TOASTR.WALLET_NOTIFICATION'), 'error'));
Store.dispatch(sendToAddressStateAlt(JSON.parse(dexRawTxJson)));
Store.dispatch(sendToAddressStateAlt(JSON.parse(dexRawTxJSON)));
} else {
Store.dispatch(triggerToaster(true, translate('TOASTR.SIGNED_TX_SENT'), translate('TOASTR.WALLET_NOTIFICATION'), 'success'));
Store.dispatch(sendToAddressStateAlt(json));
let getTxidData = function() {
return new Promise(function(resolve, reject) {
Store.dispatch(triggerToaster(true, translate('TOASTR.GETTING_TXID_INFO') + '.', translate('TOASTR.WALLET_NOTIFICATION'), 'info'));
edexGetTransaction({
'coin': sendData.coin,
'txid': dexRawTxJSON.txid
})
.then(function(json) {
console.log('gettx', json);
resolve(json);
});
});
}
let processRefreshUTXOs = function(vinData) {
return new Promise(function(resolve, reject) {
let edexGetTxIDListRes = edexGetTxIDList(vinData);
resolve(edexGetTxIDListRes);
});
}
let getDataCacheContents = function(txidListToRemove) {
return new Promise(function(resolve, reject) {
console.log(txidListToRemove);
console.log(sendData);
getCacheFile()
.then(function(result) {
console.log(result);
let saveThisData = edexRemoveTXID(result, txidListToRemove);
console.log(saveThisData);
resolve(saveThisData);
});
});
}
let saveNewCacheData = function(saveThisData) {
return new Promise(function(resolve, reject) {
console.log('saveNewCacheData', saveThisData);
shepherdGroomPost(saveThisData)
.then(function(result) {
console.log('saveNewCacheData', saveThisData);
console.log(result);
resolve(result);
});
});
}
setTimeout(function() {
getTxidData()
.then(function(gettxdata) {
return processRefreshUTXOs(gettxdata.vin);
})
.then(function(new_utxos_set) {
return getDataCacheContents(new_utxos_set);
})
.then(function(save_this_data) {
return saveNewCacheData(save_this_data);
});
}, 2000);
console.log('utxo remove', true);
}
});
@ -299,10 +395,6 @@ class SendCoin extends React.Component {
}
console.log(json);
});
//Store.dispatch(sendNativeTx(this.props.ActiveCoin.coin, this.state));
/*setTimeout(function() {
Store.dispatch(getKMDOPID(null, this.props.ActiveCoin.coin));
}, 1000);*/
}
renderSignedTx(isRawTx) {

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

@ -2,6 +2,22 @@ import React from 'react';
import { translate } from '../../translate/translate';
class WalletsBalance extends React.Component {
constructor(props) {
super(props);
this.isFullySynced = this.isFullySynced.bind(bind);
}
isFullySynced() {
if ((Number(this.props.Dashboard.progress.balances) +
Number(this.props.Dashboard.progress.validated) +
Number(this.props.Dashboard.progress.bundles) +
Number(this.props.Dashboard.progress.utxo)) / 4 === 100) {
return true;
} else {
return false;
}
}
render() {
if (this.props &&
this.props.ActiveCoin &&
@ -12,7 +28,7 @@ class WalletsBalance extends React.Component {
return (
<div id="wallet-widgets" data-plugin="masonry" data-edexcoin="COIN">
<div className="col-xs-12">
<div className={this.props.ActiveCoin.mode === 'native' || this.props.ActiveCoin.mode === 'full' ? 'col-xs-12' : 'col-xs-12 hide'}>
<div className={this.props.ActiveCoin.mode === 'native' || (this.props.ActiveCoin.mode === 'full' && !this.isFullySynced()) ? 'col-xs-12' : 'col-xs-12 hide'}>
<div role="alert" className="alert alert-info alert-dismissible" data-edexcoin="COIN" id="edexcoin-wallet-waitingrt-alert">
<button aria-label="Close" data-dismiss="alert" className="close" type="button">
<span aria-hidden="true">×</span>

23
react/src/components/login/login.js

@ -4,7 +4,10 @@ import {
toggleAddcoinModal,
iguanaWalletPassphrase,
createNewWallet,
iguanaActiveHandle
iguanaActiveHandle,
toggleSyncOnlyModal,
startInterval,
getSyncOnlyForks
} from '../../actions/actionCreators';
import Store from '../../store';
import { PassPhraseGenerator } from '../../util/crypto/passphrasegenerator';
@ -27,6 +30,18 @@ class Login extends React.Component {
this.loginSeed = this.loginSeed.bind(this);
this.toggleSeedInputVisibility = this.toggleSeedInputVisibility.bind(this);
this.handleRegisterWallet = this.handleRegisterWallet.bind(this);
this.openSyncOnlyModal = this.openSyncOnlyModal.bind(this);
}
openSyncOnlyModal() {
Store.dispatch(getSyncOnlyForks());
var _iguanaActiveHandle = setInterval(function() {
Store.dispatch(getSyncOnlyForks());
}.bind(this), 3000);
Store.dispatch(startInterval('syncOnly', _iguanaActiveHandle));
Store.dispatch(toggleSyncOnlyModal(true));
}
componentDidMount() {
@ -115,6 +130,12 @@ class Login extends React.Component {
<img className="brand-img" src="assets/images/easydex-logo-big.png" alt="SuperNET Iguana" />
</div>
<div style={{padding: '20px 0'}}>
<span className="display-sync-only-coins-toggle" onClick={this.openSyncOnlyModal}>
<i className="fa fa-cubes"></i> Display sync only coins progress
</span>
</div>
<div id="section-ie-warning" className={this.state.activeLoginSection === 'ieWarning' ? 'show' : 'hide'}>
<div className="panel">
<div className="panel-heading">

2
react/src/components/main/walletMain.js

@ -3,11 +3,13 @@ import Toaster from '../toaster/toaster';
import AddCoin from '../addcoin/addcoin';
import Login from '../login/login';
import Dashboard from '../dashboard/dashboard';
import SyncOnly from '../dashboard/syncOnly';
class WalletMain extends React.Component {
render() {
return (
<div style={{height: '100%'}}>
<SyncOnly {...this.props} />
<Dashboard {...this.props} />
<AddCoin {...this.props.AddCoin} />
<Login {...this.props} />

2
react/src/reducers/index.js

@ -9,6 +9,7 @@ import { ActiveCoin } from './activeCoin';
import { Atomic } from './atomic';
import { Settings } from './settings';
import { Interval } from './interval';
import { SyncOnly } from './syncOnly';
const rootReducer = combineReducers({
AddCoin,
@ -19,6 +20,7 @@ const rootReducer = combineReducers({
Atomic,
Settings,
Interval,
SyncOnly,
routing: routerReducer,
});

41
react/src/styles/index.scss

@ -154,6 +154,47 @@ body {
height: 100%;
}
.display-sync-only-coins-toggle {
cursor: pointer;
}
.display-sync-only-coins-toggle:hover {
color: #ffa726;
}
.sync-only-forks {
color: #757575;
.modal-body {
overflow-y: auto;
}
.badge.up {
position: absolute;
top: 40px;
left: 65px;
margin: 0 5px;
}
.avatar {
width: 20%;
display: inline-block;
text-align: center;
vertical-align: top;
img {
width: 55px;
display: inherit;
}
}
.progress-bars {
padding-left: 40px;
display: inline-block;
width: 80%;
margin: 0 auto;
}
.padding-bottom-60:last-child {
padding-bottom: 0 !important;
}
}
/*.toaster .single-toast:nth-child(0) {
bottom: 12px;
}

41
react/src/util/cacheFormat.js

@ -0,0 +1,41 @@
export function edexGetTxIDList(getTxData) {
let getTxidList = [];
for (let i = 0; i < getTxData.length; i++) {
getTxidList.push(getTxData[i].txid);
}
console.log(getTxidList);
return getTxidList;
}
export function edexRemoveTXID(_obj, txidArray) {
let txidToStr = txidArray.join(':');
console.log(txidToStr);
if (_obj, _obj.basilisk) {
if (Object.keys(_obj.basilisk).length === 0) {
console.log('no coin nodes to parse');
} else {
for (let key in _obj.basilisk) {
for (let coinAddr in _obj.basilisk[key]) {
if (_obj.basilisk[key][coinAddr] !== 'addresses') {
if (_obj.basilisk[key][coinAddr].refresh &&
_obj.basilisk[key][coinAddr].refresh.data &&
_obj.basilisk[key][coinAddr].refresh.data.length > 0) {
for (let i = 0; i < _obj.basilisk[key][coinAddr].refresh.data.length; i++) {
if (txidToStr.indexOf(_obj.basilisk[key][coinAddr].refresh.data[i].txid) > -1) {
_obj.basilisk[key][coinAddr].refresh.data.splice(i, 1);
}
}
}
}
}
}
}
} else {
console.log('basilisk node is missing');
}
}
Loading…
Cancel
Save