diff --git a/react/src/actions/actionCreators.js b/react/src/actions/actionCreators.js
index 367d8ce..af58301 100644
--- a/react/src/actions/actionCreators.js
+++ b/react/src/actions/actionCreators.js
@@ -52,9 +52,17 @@ export const SYNC_ONLY_DATA = 'SYNC_ONLY_DATA';
export const LOAD_APP_CONFIG = 'LOAD_APP_CONFIG';
export const SAVE_APP_CONFIG = 'SAVE_APP_CONFIG';
export const SERVICE_ERROR = 'SERVICE_ERROR';
+export const DASHBOARD_ACTIVE_ADDRESS = 'DASHBOARD_ACTIVE_ADDRESS';
var iguanaForks = {}; // forks in mem array
+export function changeActiveAddress(address) {
+ return {
+ type: DASHBOARD_ACTIVE_ADDRESS,
+ address,
+ }
+}
+
function updateErrosStack(method) {
return {
apiMethod: method,
@@ -795,7 +803,7 @@ export function getBasiliskTransactionsList(coin, address) {
})
.then(response => response.json())
.then(function(json) {
- if (json.result && json.result.indexOf('no file with handle') > -1) {
+ if (json.result && !json.result.basilisk && json.result.indexOf('no file with handle') > -1) {
console.log('new cache');
}
@@ -1091,6 +1099,7 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
.then(response => response.json())
.then(function(json) {
json = json.result.basilisk;
+
if (json[coin].addresses) {
resolve({ 'result': json[coin].addresses });
}
@@ -1254,8 +1263,8 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
json = json.result.basilisk;
// if listunspent is not in cache file retrieve new copy
// otherwise read from cache data
- if (json[coin][currentAddress].listunspent) {
- calcBalance(result, json[coin][currentAddress].listunspent.data, dispatch, mode);
+ if (json[coin][currentAddress].refresh) {
+ calcBalance(result, json[coin][currentAddress].refresh.data, dispatch, mode);
} else {
fetch('http://127.0.0.1:' + (Config.useBasiliskInstance && mode === 'basilisk' ? Config.basiliskPort : Config.iguanaCorePort), {
method: 'POST',
@@ -1267,7 +1276,7 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
})
.then(response => response.json())
.then(function(json) {
- updatedCache.basilisk[coin][currentAddress].listunspent = {
+ updatedCache.basilisk[coin][currentAddress].refresh = {
'data': json,
'status': 'done',
'timestamp': Date.now(),
@@ -1296,6 +1305,9 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
}
export function shepherdGroomPost(_filename, _payload) {
+ console.log('shepherdGroomPost to file ', _filename);
+ console.log('shepherdGroomPost payload ', _payload);
+
return dispatch => {
return fetch('http://127.0.0.1:' + Config.agamaPort + '/shepherd/groom/', {
method: 'POST',
@@ -1316,13 +1328,37 @@ export function shepherdGroomPost(_filename, _payload) {
}
}
+export function shepherdGroomPostPromise(_filename, _payload) {
+ console.log('shepherdGroomPostPromise to file ', _filename);
+ console.log('shepherdGroomPostPromise payload ', _payload);
+
+ return new Promise((resolve, reject) => {
+ fetch('http://127.0.0.1:' + Config.agamaPort + '/shepherd/groom/', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ 'filename': _filename,
+ 'payload': JSON.stringify(_payload),
+ }),
+ })
+ .catch(function(error) {
+ console.log(error);
+ dispatch(triggerToaster(true, 'shepherdGroomPostPromise', 'Error', 'error'));
+ })
+ .then(response => response.json())
+ .then(json => resolve(json))
+ })
+}
+
export function fetchUtxoCache(_payload) {
const _userpass = '?userpass=tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
_pubkey = '&pubkey=' + _payload.pubkey,
_route = _payload.allcoins ? 'cache-all' : 'cache-one',
_coin = '&coin=' + _payload.coin,
_calls = '&calls=' + _payload.calls,
- _address = '&address=' + _payload.address,
+ _address = _payload.address ? ('&address=' + _payload.address) : '',
_iguanaInstancePort = Config.useBasiliskInstance ? '&port=' + Config.basiliskPort : '';
return dispatch => {
@@ -1343,7 +1379,7 @@ export function fetchUtxoCache(_payload) {
function getShepherdCacheState(json, pubkey, coin) {
if (json.result && json.error && json.result.indexOf('no file with handle') > -1) {
- console.log('new cache');
+ console.log('request new cache', true);
return dispatch => {
dispatch(fetchNewCacheData({
'pubkey': pubkey,
@@ -1585,7 +1621,6 @@ export function getKMDBalanceTotal(coin) {
'asset': coin,
'function': 'z_gettotalbalance',
'hex': '3000',
- 'immediate': 60000,
'timeout': 60000
};
} else {
@@ -1595,7 +1630,6 @@ export function getKMDBalanceTotal(coin) {
'method': 'passthru',
'function': 'z_gettotalbalance',
'hex': '3000',
- 'immediate': 60000,
'timeout': 60000
};
}
@@ -1802,7 +1836,13 @@ export function sendNativeTx(coin, _payload) {
dispatch(triggerToaster(true, 'sendNativeTx', 'Error', 'error'));
})
.then(response => response.json())
- .then(json => dispatch(triggerToaster(true, translate('TOASTR.TX_SENT_ALT'), translate('TOASTR.WALLET_NOTIFICATION'), 'success')))
+ .then(function(json) {
+ if (json.error && json.error.toString().indexOf('code:') > -1) {
+ dispatch(triggerToaster(true, 'Send failed', translate('TOASTR.WALLET_NOTIFICATION'), 'error'));
+ } else {
+ dispatch(triggerToaster(true, translate('TOASTR.TX_SENT_ALT'), translate('TOASTR.WALLET_NOTIFICATION'), 'success'));
+ }
+ })
.catch(function(ex) {
dispatch(triggerToaster(true, translate('TOASTR.TX_SENT_ALT'), translate('TOASTR.WALLET_NOTIFICATION'), 'success'));
console.log('parsing failed', ex);
@@ -2138,11 +2178,11 @@ export function deleteCacheFile(_payload) {
}
}
-export function getCacheFile() {
- const _pubkey = JSON.parse(sessionStorage.getItem('IguanaActiveAccount')).pubkey;
+export function getCacheFile(pubkey) {
+ const _pubkey = pubkey || JSON.parse(sessionStorage.getItem('IguanaActiveAccount')).pubkey;
return new Promise((resolve, reject) => {
- fetch('http://127.0.0.1:' + Config.agamaPort + '/shepherd/groom?pubkey=' + _pubkey, {
+ fetch('http://127.0.0.1:' + Config.agamaPort + '/shepherd/groom?filename=' + _pubkey, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
@@ -2164,10 +2204,11 @@ export function fetchNewCacheData(_payload) {
_route = _payload.allcoins ? 'cache-all' : 'cache-one',
_coin = '&coin=' + _payload.coin,
_calls = '&calls=' + _payload.calls,
+ _address = _payload.address ? ('&address=' + _payload.address) : '',
_iguanaInstancePort = Config.useBasiliskInstance ? '&port=' + Config.basiliskPort : '';
return dispatch => {
- return fetch('http://127.0.0.1:' + Config.agamaPort + '/shepherd/' + _route + _userpass + _pubkey + _coin + _calls + _iguanaInstancePort, {
+ return fetch('http://127.0.0.1:' + Config.agamaPort + '/shepherd/' + _route + _userpass + _pubkey + _coin + _calls + _address + _iguanaInstancePort, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
diff --git a/react/src/components/dashboard/appSettings.js b/react/src/components/dashboard/appSettings.js
new file mode 100644
index 0000000..2efba73
--- /dev/null
+++ b/react/src/components/dashboard/appSettings.js
@@ -0,0 +1,39 @@
+import React from 'react';
+import { translate } from '../../translate/translate';
+import {
+
+} from '../../actions/actionCreators';
+import Store from '../../store';
+
+class AppSettings extends React.Component {
+ constructor(props) {
+ super(props);
+ //this.closeSyncOnlyModal = this.closeSyncOnlyModal.bind(this);
+ }
+
+ render() {
+ /*if (this.props && this.props.SyncOnly.display) {
+ return (
+
+
+
+
+
+ {this.renderForksList()}
+
+
+
+
+
+
+
+
+
+ );
+ } else {
+ return null;
+ }*/
+ }
+}
+
+export default AppSettings;
\ No newline at end of file
diff --git a/react/src/components/dashboard/coinTileItem.js b/react/src/components/dashboard/coinTileItem.js
index 6166468..4945df5 100644
--- a/react/src/components/dashboard/coinTileItem.js
+++ b/react/src/components/dashboard/coinTileItem.js
@@ -16,7 +16,8 @@ import {
getFullTransactionsList,
getBasiliskTransactionsList,
getShepherdCache,
- fetchNewCacheData
+ fetchNewCacheData,
+ changeActiveAddress
} from '../../actions/actionCreators';
import Store from '../../store';
@@ -32,6 +33,9 @@ class CoinTileItem extends React.Component {
// 3) limit req in basilisk as much as possible incl. activehandle
// 4) add pending requests store
+ // TODO: update all addresses once in 20 min, current address every 10 min
+ // always fetch main addr data and current selected address
+
dispatchCoinActions(coin, mode) {
if (mode === 'native') {
Store.dispatch(iguanaActiveHandle(true));
@@ -51,9 +55,9 @@ class CoinTileItem extends React.Component {
if (mode === 'basilisk') {
const useAddress = this.props.ActiveCoin.mainBasiliskAddress ? this.props.ActiveCoin.mainBasiliskAddress : this.props.Dashboard.activeHandle[coin];
Store.dispatch(iguanaActiveHandle(true));
+ Store.dispatch(getShepherdCache(JSON.parse(sessionStorage.getItem('IguanaActiveAccount')).pubkey, coin));
if (this.props && this.props.Dashboard && this.props.Dashboard.activeHandle && this.props.Dashboard.activeHandle[coin]) {
- Store.dispatch(getShepherdCache(this.props.Dashboard.activeHandle.pubkey, coin));
Store.dispatch(getBasiliskTransactionsList(coin, useAddress));
Store.dispatch(getKMDAddressesNative(coin, mode, useAddress));
//Store.dispatch(iguanaEdexBalance(coin, mode));
@@ -83,21 +87,35 @@ class CoinTileItem extends React.Component {
Store.dispatch(startInterval('sync', _iguanaActiveHandle));
}
if (mode === 'basilisk') {
- var _iguanaActiveHandle = setInterval(function() {
- this.dispatchCoinActions(coin, mode);
- }.bind(this), 3000);
+ const _basiliskMainAddress = this.props.Dashboard.activeHandle[coin] || JSON.parse(sessionStorage.getItem('IguanaActiveAccount'))[coin];
+ Store.dispatch(changeActiveAddress(_basiliskMainAddress));
- var _basiliskCache = setInterval(function() {
+ if (_basiliskMainAddress) {
Store.dispatch(fetchNewCacheData({
'pubkey': this.props.Dashboard.activeHandle.pubkey,
'allcoins': false,
- 'coin': this.props.ActiveCoin.coin,
+ 'coin': coin,
'calls': 'listtransactions:getbalance',
+ 'address': _basiliskMainAddress,
}));
- }.bind(this), 60000);
- Store.dispatch(startInterval('sync', _iguanaActiveHandle));
- Store.dispatch(startInterval('basilisk', _basiliskCache));
- // basilisk
+
+ var _iguanaActiveHandle = setInterval(function() {
+ this.dispatchCoinActions(coin, mode);
+ }.bind(this), 3000);
+
+ var _basiliskCache = setInterval(function() {
+ Store.dispatch(fetchNewCacheData({
+ 'pubkey': this.props.Dashboard.activeHandle.pubkey,
+ 'allcoins': false,
+ 'coin': this.props.ActiveCoin.coin,
+ 'calls': 'listtransactions:getbalance',
+ 'address': _basiliskMainAddress,
+ }));
+ }.bind(this), 240000);
+ Store.dispatch(startInterval('sync', _iguanaActiveHandle));
+ Store.dispatch(startInterval('basilisk', _basiliskCache));
+ // basilisk
+ }
}
}
}
diff --git a/react/src/components/dashboard/sendCoin.js b/react/src/components/dashboard/sendCoin.js
index fbe2bac..7cbbbc0 100644
--- a/react/src/components/dashboard/sendCoin.js
+++ b/react/src/components/dashboard/sendCoin.js
@@ -21,7 +21,8 @@ import {
fetchUtxoCache,
basiliskRefresh,
edexGetTransaction,
- getCacheFile
+ getCacheFile,
+ shepherdGroomPostPromise
} from '../../actions/actionCreators';
import Store from '../../store';
@@ -32,7 +33,6 @@ const socket = io.connect('http://127.0.0.1:' + Config.agamaPort);
class SendCoin extends React.Component {
constructor(props) {
super(props);
-
this.state = {
currentStep: 0,
sendFrom: this.props.Dashboard && this.props.Dashboard.activeHandle ? this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin] : null,
@@ -46,26 +46,7 @@ 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
- }
- ]
+ utxoMethodInProgress: false,
};
this.updateInput = this.updateInput.bind(this);
this.handleBasiliskSend = this.handleBasiliskSend.bind(this);
@@ -73,11 +54,18 @@ class SendCoin extends React.Component {
this.toggleSendSig = this.toggleSendSig.bind(this);
this.getOAdress = this.getOAdress.bind(this);
this.toggleSendAPIType = this.toggleSendAPIType.bind(this);
- this.renderUTXOCacheInfo = this.renderUTXOCacheInfo.bind(this);
this._fetchNewUTXOData = this._fetchNewUTXOData.bind(this);
socket.on('messages', msg => this.updateSocketsData(msg));
}
+ componentWillReceiveProps(props) {
+ if (!this.state.sendFrom && this.props.ActiveCoin.activeAddress) {
+ this.setState(Object.assign({}, this.state, {
+ sendFrom: this.props.ActiveCoin.activeAddress,
+ }));
+ }
+ }
+
updateSocketsData(data) {
console.log('sockets', data);
if (data && data.message && data.message.shepherd.iguanaAPI &&
@@ -107,40 +95,55 @@ class SendCoin extends React.Component {
'calls': 'refresh',
'address': this.state.sendFrom,
}));
- console.log('_fetchUtxoCache', {
- 'pubkey': this.props.Dashboard.activeHandle.pubkey,
- 'allcoins': false,
- 'coin': this.props.ActiveCoin.coin,
- 'calls': 'refresh',
- 'address': this.state.sendFrom,
- });
}
renderUTXOCacheInfo() {
if (this.props.ActiveCoin.mode === 'basilisk' &&
this.state.sendFrom &&
!this.state.sendApiType &&
- this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom] &&
- this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].refresh) {
- const refreshCacheData = this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].refresh;
- const timestamp = checkTimestamp(refreshCacheData.timestamp);
- const isReadyToUpdate = timestamp > 600 ? true : false;
+ this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom]) {
+ let refreshCacheData,
+ timestamp,
+ isReadyToUpdate,
+ waitUntilCallIsFinished = this.state.currentStackLength > 1 ? true : false;
+
+ if (this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].refresh ||
+ this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].listunspent) {
+ refreshCacheData = this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].refresh || this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].listunspent;
+ timestamp = checkTimestamp(refreshCacheData.timestamp);
+ isReadyToUpdate = timestamp > 600 ? true : false;
+ } else {
+ isReadyToUpdate = true;
+ }
+
+ if (this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].refresh &&
+ this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].refresh.data &&
+ this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].refresh.data.error &&
+ this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].refresh.data.error === 'request failed') {
+ timestamp = null;
+ }
return (
- Total UTXO available: {refreshCacheData.data.length}
- Last updated @ {secondsToString(refreshCacheData.timestamp, true)} | {secondsElapsedToString(timestamp)} ago
+ Total UTXO available: {refreshCacheData ? refreshCacheData.data && refreshCacheData.data.length : 'N/A. Press update button.'}
+
+ Last updated @ {secondsToString(refreshCacheData ? refreshCacheData.timestamp : 0, true)} | {secondsElapsedToString(timestamp || 0)} ago
+
Next update available in {secondsElapsedToString(600 - timestamp)}s
Processing requests: {this.state.currentStackLength} / {this.state.totalStackLength}
-
);
} else {
@@ -241,12 +244,6 @@ class SendCoin extends React.Component {
sendFromAmount: amount ? amount : this.props.ActiveCoin.addresses[type][address].amount,
addressSelectorOpen: !this.state.addressSelectorOpen,
}));
-
- this.renderCachedUTXOInfo();
- }
-
- renderCachedUTXOInfo() {
-
}
changeSendCoinStep(step) {
@@ -254,6 +251,7 @@ class SendCoin extends React.Component {
this.setState(Object.assign({}, this.state, {
currentStep: step,
+ utxoMethodInProgress: !this.state.sendApiType && this.props.ActiveCoin.mode === 'basilisk' ? true : false,
}));
if (step === 2) {
@@ -274,6 +272,7 @@ class SendCoin extends React.Component {
toggleSendAPIType() {
this.setState(Object.assign({}, this.state, {
sendApiType: !this.state.sendApiType,
+ sendFrom: this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin],
}));
}
@@ -286,7 +285,9 @@ class SendCoin extends React.Component {
handleBasiliskSend() {
const refreshData = this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].refresh;
const listunspentData = this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].listunspent;
- const utxoSet = refreshData && refreshData.data || listunspentData && listunspentData.data;
+ const utxoSet = (refreshData && refreshData.data) || (listunspentData && listunspentData.data);
+ const _pubkey = this.props.Dashboard.activeHandle.pubkey;
+ const forceUpdateCache = this._fetchNewUTXOData;
const sendData = {
'coin': this.props.ActiveCoin.coin,
'sendfrom': this.state.sendFrom,
@@ -305,7 +306,6 @@ 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'));
const dexrawtxData = {
'signedtx': json.signedtx,
'coin': sendData.coin
@@ -316,6 +316,10 @@ class SendCoin extends React.Component {
if (dexRawTxJSON.indexOf('"error":{"code"') > -1) {
Store.dispatch(triggerToaster(true, 'Transaction failed', translate('TOASTR.WALLET_NOTIFICATION'), 'error'));
Store.dispatch(sendToAddressStateAlt(JSON.parse(dexRawTxJSON)));
+
+ this.setState(Object.assign({}, this.state, {
+ utxoMethodInProgress: false,
+ }));
} else {
Store.dispatch(triggerToaster(true, translate('TOASTR.SIGNED_TX_SENT'), translate('TOASTR.WALLET_NOTIFICATION'), 'success'));
Store.dispatch(sendToAddressStateAlt(json));
@@ -326,7 +330,7 @@ class SendCoin extends React.Component {
edexGetTransaction({
'coin': sendData.coin,
- 'txid': dexRawTxJSON.txid
+ 'txid': dexRawTxJSON.txid ? dexRawTxJSON.txid : dexRawTxJSON
})
.then(function(json) {
console.log('gettx', json);
@@ -336,6 +340,8 @@ class SendCoin extends React.Component {
}
let processRefreshUTXOs = function(vinData) {
+ console.log('vin', vinData);
+
return new Promise(function(resolve, reject) {
let edexGetTxIDListRes = edexGetTxIDList(vinData);
resolve(edexGetTxIDListRes);
@@ -347,11 +353,11 @@ class SendCoin extends React.Component {
console.log(txidListToRemove);
console.log(sendData);
- getCacheFile()
+ getCacheFile(_pubkey)
.then(function(result) {
- console.log(result);
- let saveThisData = edexRemoveTXID(result, txidListToRemove);
- console.log(saveThisData);
+ console.log('got cache file', result);
+ let saveThisData = edexRemoveTXID(result.result, txidListToRemove);
+ console.log('saveThisData', saveThisData);
resolve(saveThisData);
});
});
@@ -361,16 +367,26 @@ class SendCoin extends React.Component {
return new Promise(function(resolve, reject) {
console.log('saveNewCacheData', saveThisData);
- shepherdGroomPost(saveThisData)
+ shepherdGroomPostPromise(_pubkey, saveThisData)
.then(function(result) {
console.log('saveNewCacheData', saveThisData);
console.log(result);
resolve(result);
- });
- });
- }
+ forceUpdateCache();
+ Store.dispatch(triggerToaster(true, 'Local UTXO data is updated. Ready to send new transaction.', translate('TOASTR.WALLET_NOTIFICATION'), 'info'));
+
+ this.setState(Object.assign({}, this.state, {
+ utxoMethodInProgress: false,
+ }));
+ }.bind(this));
+ }.bind(this));
+ }.bind(this);
+
+ Store.dispatch(triggerToaster(true, 'Awaiting transaction data response...', translate('TOASTR.WALLET_NOTIFICATION'), 'info'));
+
+ function waterfallUTXOProcess() {
+ Store.dispatch(triggerToaster(true, 'Processing UTXO...', translate('TOASTR.WALLET_NOTIFICATION'), 'info'));
- setTimeout(function() {
getTxidData()
.then(function(gettxdata) {
return processRefreshUTXOs(gettxdata.vin);
@@ -381,20 +397,39 @@ class SendCoin extends React.Component {
.then(function(save_this_data) {
return saveNewCacheData(save_this_data);
});
- }, 2000);
+ }
+
+ let sentTxData = setInterval(function() {
+ getTxidData()
+ .then(function(gettxdata) {
+ if (gettxdata.vin && gettxdata.vin.length) {
+ clearInterval(sentTxData);
+ waterfallUTXOProcess();
+ }
+ })
+ }, 1000);
console.log('utxo remove', true);
}
- });
+ }.bind(this));
} else {
Store.dispatch(sendToAddressStateAlt(json));
+
+ this.setState(Object.assign({}, this.state, {
+ utxoMethodInProgress: false,
+ }));
}
} else {
Store.dispatch(sendToAddressStateAlt(json));
Store.dispatch(triggerToaster(true, translate('TOASTR.SIGNED_TX_GENERATED_FAIL') + '.', translate('TOASTR.WALLET_NOTIFICATION'), 'error'));
+
+ this.setState(Object.assign({}, this.state, {
+ utxoMethodInProgress: false,
+ }));
}
+
console.log(json);
- });
+ }.bind(this));
}
renderSignedTx(isRawTx) {
@@ -480,7 +515,10 @@ class SendCoin extends React.Component {
} else {
return (
-
Processing transaction...
+
+ Processing transaction...
+ Note: it may take a few minutes to complete the transaction.
+
@@ -712,6 +750,9 @@ class SendCoin extends React.Component {
{translate('INDEX.TRANSACTION_RESULT')}
+
+ You picked option "{translate('INDEX.DONT_SEND')}"
+
@@ -725,7 +766,7 @@ class SendCoin extends React.Component {
- this.changeSendCoinStep(0)}>{translate('INDEX.MAKE_ANOTHER_TX')}
+ this.changeSendCoinStep(0)} disabled={this.state.utxoMethodInProgress}>{!this.state.utxoMethodInProgress ? translate('INDEX.MAKE_ANOTHER_TX') : 'Please wait...'}
diff --git a/react/src/components/dashboard/settings.js b/react/src/components/dashboard/settings.js
index 0b71cc3..5ff81a1 100644
--- a/react/src/components/dashboard/settings.js
+++ b/react/src/components/dashboard/settings.js
@@ -7,7 +7,8 @@ import {
importPrivKey,
getDebugLog,
getPeersList,
- addPeerNode
+ addPeerNode,
+ getAppConfig
} from '../../actions/actionCreators';
import Store from '../../store';
import AddCoinOptionsCrypto from '../addcoin/addcoinOptionsCrypto';
@@ -42,6 +43,7 @@ class Settings extends React.Component {
componentDidMount() {
Store.dispatch(iguanaActiveHandle());
+ Store.dispatch(getAppConfig());
}
openTab(elemId, tab) {
@@ -388,6 +390,43 @@ class Settings extends React.Component {
+
+
+
+
+
+
Manage app settings
+
+
+
+
+
+
diff --git a/react/src/components/dashboard/walletsBalance.js b/react/src/components/dashboard/walletsBalance.js
index 0a84b48..bdb28df 100644
--- a/react/src/components/dashboard/walletsBalance.js
+++ b/react/src/components/dashboard/walletsBalance.js
@@ -18,6 +18,49 @@ class WalletsBalance extends React.Component {
}
}
+ renderBalance(type) {
+ let _balance = '0';
+
+ if (this.props.ActiveCoin.mode === 'full') {
+ _balance = this.props.ActiveCoin.balance || 0;
+ } else {
+ if (this.props.ActiveCoin.cache) {
+ if (type === 'main' &&
+ this.props.ActiveCoin.mode === 'basilisk' &&
+ this.props.ActiveCoin.activeAddress &&
+ this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance &&
+ this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data &&
+ this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data.balance) {
+ _balance = this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data.balance;
+ }
+
+ if (type === 'interest' &&
+ this.props.ActiveCoin.mode === 'basilisk' &&
+ this.props.ActiveCoin.activeAddress &&
+ this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance &&
+ this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data &&
+ this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data.interest) {
+ _balance = this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data.interest;
+ }
+
+ if (type === 'total' &&
+ this.props.ActiveCoin.mode === 'basilisk' &&
+ this.props.ActiveCoin.activeAddress &&
+ this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance &&
+ this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data &&
+ (this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data.balance ||
+ this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data.interest)) {
+ const _regBalance = this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data.balance ? this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data.balance : 0;
+ const _regInterest = this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data.interest ? this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.props.ActiveCoin.activeAddress].getbalance.data.interest : 0;
+
+ _balance = _regBalance + _regInterest;
+ }
+ }
+ }
+
+ return _balance;
+ }
+
render() {
if (this.props &&
this.props.ActiveCoin &&
@@ -58,7 +101,7 @@ class WalletsBalance extends React.Component {
{translate('INDEX.BALANCE')}
- {this.props.ActiveCoin && this.props.ActiveCoin.balance ? this.props.ActiveCoin.balance : 0}
+ {this.renderBalance('main')} {this.props.ActiveCoin.coin}
@@ -66,7 +109,7 @@ class WalletsBalance extends React.Component {
-
+
@@ -83,7 +126,7 @@ class WalletsBalance extends React.Component {
-
+
diff --git a/react/src/components/dashboard/walletsData.js b/react/src/components/dashboard/walletsData.js
index d86fb51..6d51695 100644
--- a/react/src/components/dashboard/walletsData.js
+++ b/react/src/components/dashboard/walletsData.js
@@ -16,7 +16,8 @@ import {
toggleViewCacheModal,
fetchNewCacheData,
fetchUtxoCache,
- restartBasiliskInstance
+ restartBasiliskInstance,
+ changeActiveAddress
} from '../../actions/actionCreators';
import Store from '../../store';
@@ -50,7 +51,6 @@ class WalletsData extends React.Component {
this.basiliskConnectionAction = this.basiliskConnectionAction.bind(this);
this.getDexNotariesAction = this.getDexNotariesAction.bind(this);
this.openDropMenu = this.openDropMenu.bind(this);
- this.refreshTxList = this.refreshTxList.bind(this);
this.removeAndFetchNewCache = this.removeAndFetchNewCache.bind(this);
this._toggleViewCacheModal = this._toggleViewCacheModal.bind(this);
this.toggleCacheApi = this.toggleCacheApi.bind(this);
@@ -133,15 +133,22 @@ class WalletsData extends React.Component {
}));
}
+ basiliskRefreshActionOne() {
+ Store.dispatch(fetchNewCacheData({
+ 'pubkey': this.props.Dashboard.activeHandle.pubkey,
+ 'allcoins': false,
+ 'coin': this.props.ActiveCoin.coin,
+ 'calls': 'listtransactions:getbalance',
+ }));
+ }
+
basiliskRefreshAction() {
- /*if (this.props.Dashboard) {
- Store.dispatch(basiliskRefresh(!this.props.Dashboard.basiliskRefresh));
- }*/
Store.dispatch(fetchNewCacheData({
'pubkey': this.props.Dashboard.activeHandle.pubkey,
'allcoins': false,
'coin': this.props.ActiveCoin.coin,
'calls': 'listtransactions:getbalance',
+ 'address': this.props.ActiveCoin.activeAddress,
}));
}
@@ -173,6 +180,12 @@ class WalletsData extends React.Component {
}
componentWillReceiveProps(props) {
+ if (!this.state.currentAddress && this.props.ActiveCoin.activeAddress) {
+ this.setState(Object.assign({}, this.state, {
+ currentAddress: this.props.ActiveCoin.activeAddress,
+ }));
+ }
+
if (this.props.ActiveCoin.txhistory && this.props.ActiveCoin.txhistory !== 'loading' && this.props.ActiveCoin.txhistory !== 'no data' && this.props.ActiveCoin.txhistory.length) {
if (!this.state.itemsList || (this.state.itemsList && !this.state.itemsList.length) || (props.ActiveCoin.txhistory !== this.props.ActiveCoin.txhistory)) {
let historyToSplit = sortByDate(this.props.ActiveCoin.txhistory);
@@ -329,6 +342,8 @@ class WalletsData extends React.Component {
}
updateAddressSelection(address, type, amount) {
+ Store.dispatch(changeActiveAddress(address));
+
this.setState(Object.assign({}, this.state, {
currentAddress: address,
addressSelectorOpen: false,
@@ -341,16 +356,35 @@ class WalletsData extends React.Component {
}.bind(this), 100);
}
- refreshTxList() {
- Store.dispatch(getBasiliskTransactionsList(this.props.ActiveCoin.coin, this.props.ActiveCoin.mainBasiliskAddress));
- }
-
openDropMenu() {
this.setState(Object.assign({}, this.state, {
addressSelectorOpen: !this.state.addressSelectorOpen,
}));
}
+ /*filterTable() {
+ function myFunction() {
+ // Declare variables
+ var input, filter, table, tr, td, i;
+ input = document.getElementById("myInput");
+ filter = input.value.toUpperCase();
+ table = document.getElementById("myTable");
+ tr = table.getElementsByTagName("tr");
+
+ // Loop through all table rows, and hide those who don't match the search query
+ for (i = 0; i < tr.length; i++) {
+ td = tr[i].getElementsByTagName("td")[0];
+ if (td) {
+ if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
+ tr[i].style.display = "";
+ } else {
+ tr[i].style.display = "none";
+ }
+ }
+ }
+ }
+ }*/
+
renderUseCacheToggle() {
if (this.props.ActiveCoin.mode === 'basilisk') {
return (
@@ -379,7 +413,7 @@ class WalletsData extends React.Component {
}
renderAddressAmount() {
- if (this.props.ActiveCoin.addresses['public'] && this.props.ActiveCoin.addresses['public'].length) {
+ if (this.props.ActiveCoin.addresses && this.props.ActiveCoin.addresses['public'] && this.props.ActiveCoin.addresses['public'].length) {
for (let i = 0; i < this.props.ActiveCoin.addresses['public'].length; i++) {
if (this.props.ActiveCoin.addresses['public'][i].address === this.state.currentAddress) {
return this.props.ActiveCoin.addresses['public'][i].amount;
@@ -430,7 +464,12 @@ class WalletsData extends React.Component {
}
render() {
- if (this.props && this.props.ActiveCoin && this.props.ActiveCoin.coin && this.props.ActiveCoin.mode !== 'native' && !this.props.ActiveCoin.send && !this.props.ActiveCoin.receive) {
+ if (this.props &&
+ this.props.ActiveCoin &&
+ this.props.ActiveCoin.coin &&
+ this.props.ActiveCoin.mode !== 'native' &&
+ !this.props.ActiveCoin.send &&
+ !this.props.ActiveCoin.receive) {
return (
@@ -450,9 +489,6 @@ class WalletsData extends React.Component {
Processing requests: {this.state.currentStackLength} / {this.state.totalStackLength}
-
- {translate('INDEX.REFRESH')}
-
@@ -472,7 +508,12 @@ class WalletsData extends React.Component {
- {translate('INDEX.FETCH_WALLET_DATA')}
+ {translate('INDEX.FETCH_WALLET_DATA')} (active address)
+
+
+
+
+ Fetch (all addresses)
@@ -480,19 +521,14 @@ class WalletsData extends React.Component {
{translate('INDEX.REFETCH_WALLET_DATA')}
-
+
Update UTXO
-
-
- Fetch all
-
-
- Restart Basilisk Instance
+ Restart Basilisk Instance (!)
@@ -507,7 +543,7 @@ class WalletsData extends React.Component {
-
+
{this.renderAddressList()}
{this.renderUseCacheToggle}
diff --git a/react/src/components/dashboard/walletsNativeSend.js b/react/src/components/dashboard/walletsNativeSend.js
index 3cc33ef..ba30dd2 100644
--- a/react/src/components/dashboard/walletsNativeSend.js
+++ b/react/src/components/dashboard/walletsNativeSend.js
@@ -187,7 +187,7 @@ class WalletsNativeSend extends React.Component {
Store.dispatch(sendNativeTx(this.props.ActiveCoin.coin, this.state));
setTimeout(function() {
Store.dispatch(getKMDOPID(null, this.props.ActiveCoin.coin));
- }, 1000);
+ }.bind(this), 1000);
}
getOAdress() {
diff --git a/react/src/components/login/login.js b/react/src/components/login/login.js
index e72ffb8..a747eaa 100644
--- a/react/src/components/login/login.js
+++ b/react/src/components/login/login.js
@@ -68,9 +68,8 @@ class Login extends React.Component {
this.setState({
display: false,
});
-
- // Store.dispatch(stopInterval('activeCoins', this.props.Interval.interval));
}
+
if (props && props.Main && !props.Main.isLoggedIn) {
this.setState({
display: true,
@@ -85,6 +84,7 @@ class Login extends React.Component {
document.body.className = 'page-login layout-full page-dark';
}
+
if (this.state.activeLoginSection !== 'signup') {
if (props && props.Main && props.Main.activeCoins) {
this.setState({
@@ -124,6 +124,7 @@ class Login extends React.Component {
this.setState({
isSeedConfirmError: false,
});
+
Store.dispatch(createNewWallet(this.state.randomSeedConfirm, this.props.Dashboard.activeHandle));
} else {
this.setState({
@@ -132,6 +133,12 @@ class Login extends React.Component {
}
}
+ handleKeydown(e) {
+ if (e.key === 'Enter') {
+ this.loginSeed();
+ }
+ }
+
render() {
if ((this.state && this.state.display) || !this.props.Main) {
return (
@@ -178,7 +185,7 @@ class Login extends React.Component {
{translate('INDEX.WELCOME_LOGIN')}
-
+ this.handleKeydown(event)} />
diff --git a/react/src/reducers/activeCoin.js b/react/src/reducers/activeCoin.js
index 0c9c2bf..58200d9 100644
--- a/react/src/reducers/activeCoin.js
+++ b/react/src/reducers/activeCoin.js
@@ -14,7 +14,8 @@ import {
DASHBOARD_ACTIVE_COIN_GET_CACHE,
DASHBOARD_ACTIVE_COIN_MAIN_BASILISK_ADDR,
DASHBOARD_GET_NOTARIES_LIST,
- DASHBOARD_DISPLAY_NOTARIES_MODAL
+ DASHBOARD_DISPLAY_NOTARIES_MODAL,
+ DASHBOARD_ACTIVE_ADDRESS,
} from '../actions/actionCreators';
// TODO: refactor
@@ -36,6 +37,7 @@ export function ActiveCoin(state = {
mainBasiliskAddress: null,
notaries: null,
displayNotariesModal: false,
+ activeAddress: null,
}, action) {
switch (action.type) {
case DASHBOARD_ACTIVE_COIN_CHANGE:
@@ -55,6 +57,7 @@ export function ActiveCoin(state = {
lastSendToResponse: state.lastSendToResponse,
mainBasiliskAddress: state.mainBasiliskAddress,
opids: state.opids,
+ activeBasiliskAddress: state.activeBasiliskAddress,
};
let _coins = state.coins;
_coins[state.coin] = _coinDataToStore;
@@ -74,6 +77,7 @@ export function ActiveCoin(state = {
lastSendToResponse: _coinData.lastSendToResponse,
mainBasiliskAddress: _coinData.mainBasiliskAddress,
opids: _coinData.opids,
+ activeBasiliskAddress: _coinData.activeBasiliskAddress,
});
} else {
if (state.coin) {
@@ -91,6 +95,7 @@ export function ActiveCoin(state = {
lastSendToResponse: state.lastSendToResponse,
mainBasiliskAddress: state.mainBasiliskAddress,
opids: state.opids,
+ activeBasiliskAddress: state.activeBasiliskAddress,
};
let _coins = state.coins;
_coins[state.coin] = _coinData;
@@ -185,6 +190,10 @@ export function ActiveCoin(state = {
return Object.assign({}, state, {
displayNotariesModal: action.display,
});
+ case DASHBOARD_ACTIVE_ADDRESS:
+ return Object.assign({}, state, {
+ activeAddress: action.address,
+ });
default:
return state;
}
diff --git a/react/src/styles/index.scss b/react/src/styles/index.scss
index fc7e6f4..608d56f 100644
--- a/react/src/styles/index.scss
+++ b/react/src/styles/index.scss
@@ -272,6 +272,10 @@ body {
}
}
+.center {
+ text-align: center;
+}
+
/*.toaster .single-toast:nth-child(0) {
bottom: 12px;
}
diff --git a/react/src/util/cacheFormat.js b/react/src/util/cacheFormat.js
index 90f4cb0..0ea9bfb 100644
--- a/react/src/util/cacheFormat.js
+++ b/react/src/util/cacheFormat.js
@@ -11,7 +11,7 @@ export function edexGetTxIDList(getTxData) {
}
export function edexRemoveTXID(_obj, txidArray) {
- let txidToStr = txidArray.join(':');
+ let txidToStr = ':' + txidArray.join(':') + ':';
console.log(txidToStr);
@@ -26,8 +26,21 @@ export function edexRemoveTXID(_obj, txidArray) {
_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) {
+ if (txidToStr.indexOf(_obj.basilisk[key][coinAddr].refresh.data[i].txid.toString()) > -1) {
+ console.log('cacheformat remove node', _obj.basilisk[key][coinAddr].refresh.data[i].txid);
_obj.basilisk[key][coinAddr].refresh.data.splice(i, 1);
+ _obj.basilisk[key][coinAddr].refresh.timestamp = Date.now();
+ }
+ }
+ }
+ if (_obj.basilisk[key][coinAddr].listunspent &&
+ _obj.basilisk[key][coinAddr].listunspent.data &&
+ _obj.basilisk[key][coinAddr].listunspent.data.length > 0) {
+ for (let i = 0; i < _obj.basilisk[key][coinAddr].listunspent.data.length; i++) {
+ if (txidToStr.indexOf(_obj.basilisk[key][coinAddr].listunspent.data[i].txid.toString()) > -1) {
+ console.log('cacheformat remove node', _obj.basilisk[key][coinAddr].listunspent.data[i].txid);
+ _obj.basilisk[key][coinAddr].listunspent.data.splice(i, 1);
+ _obj.basilisk[key][coinAddr].listunspent.timestamp = Date.now();
}
}
}
@@ -38,4 +51,6 @@ export function edexRemoveTXID(_obj, txidArray) {
} else {
console.log('basilisk node is missing');
}
+
+ return _obj;
}
\ No newline at end of file