diff --git a/react/src/actions/actionCreators.js b/react/src/actions/actionCreators.js
index c9fc0f2..dd305e4 100644
--- a/react/src/actions/actionCreators.js
+++ b/react/src/actions/actionCreators.js
@@ -40,6 +40,16 @@ export const DASHBOARD_ACTIVE_TXINFO_MODAL = 'DASHBOARD_ACTIVE_TXINFO_MODAL';
export const DASHBOARD_ACTIVE_COIN_NATIVE_BALANCE = 'DASHBOARD_ACTIVE_COIN_NATIVE_BALANCE';
export const DASHBOARD_ACTIVE_COIN_NATIVE_TXHISTORY = 'DASHBOARD_ACTIVE_COIN_NATIVE_TXHISTORY';
export const DASHBOARD_ACTIVE_COIN_NATIVE_OPIDS = 'DASHBOARD_ACTIVE_COIN_NATIVE_OPIDS';
+export const DASHBOARD_ACTIVE_COIN_SENDTO = 'DASHBOARD_ACTIVE_COIN_SENDTO';
+export const DASHBOARD_ACTIVE_COIN_GET_CACHE = 'DASHBOARD_ACTIVE_COIN_GET_CACHE';
+export const DASHBOARD_ACTIVE_COIN_MAIN_BASILISK_ADDR = 'DASHBOARD_ACTIVE_COIN_MAIN_BASILISK_ADDR';
+
+export function changeMainBasiliskAddress(address) {
+ return {
+ type: DASHBOARD_ACTIVE_COIN_MAIN_BASILISK_ADDR,
+ address,
+ }
+}
export function toggleDashboardActiveSection(name) {
return {
@@ -661,6 +671,31 @@ export function getFullTransactionsList(coin) {
}
}
+export function getBasiliskTransactionsList(coin, address) {
+ const payload = {
+ 'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
+ 'agent': 'dex',
+ 'method': 'listtransactions',
+ 'address': address,
+ 'count': 100,
+ 'skip': 0,
+ 'symbol': coin
+ };
+
+ return dispatch => {
+ return fetch('http://127.0.0.1:' + Config.iguanaCorePort, {
+ method: 'POST',
+ body: JSON.stringify(payload),
+ })
+ .catch(function(error) {
+ console.log(error);
+ dispatch(triggerToaster(true, 'getBasiliskTransactionsList', 'Error', 'error'));
+ })
+ .then(response => response.json())
+ .then(json => dispatch(getNativeTxHistoryState(json)))
+ }
+}
+
export function getPeersList(coin) {
const payload = {
'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
@@ -862,9 +897,13 @@ function getKMDAddressesNativeState(json) {
}
}
-export function getKMDAddressesNative(coin) {
+export function getKMDAddressesNative(coin, mode, currentAddress) {
const type = ['public', 'private'];
+ if (mode !== 'native') {
+ type.pop();
+ }
+
return dispatch => {
Promise.all(type.map((_type, index) => {
return new Promise((resolve, reject) => {
@@ -903,6 +942,16 @@ export function getKMDAddressesNative(coin) {
};
}
+ if (mode !== 'native' || mode !== 'basilisk') {
+ payload = {
+ 'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
+ 'coin': coin,
+ 'agent': 'bitcoinrpc',
+ 'method': 'getaddressesbyaccount',
+ 'account': '*'
+ };
+ }
+
fetch('http://127.0.0.1:' + Config.iguanaCorePort, {
method: 'POST',
body: JSON.stringify(payload),
@@ -940,6 +989,29 @@ export function getKMDAddressesNative(coin) {
};
}
+ if (mode === 'full') {
+ payload = {
+ 'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
+ 'coin': coin,
+ 'method': 'listunspent',
+ 'params': [
+ 1,
+ 9999999,
+ ]
+ };
+ }
+
+ // if api cache option is off
+ if (mode === 'basilisk') {
+ payload = {
+ 'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
+ 'agent': 'dex',
+ 'method': 'listunspent',
+ 'address': currentAddress,
+ 'symbol': coin
+ };
+ }
+
fetch('http://127.0.0.1:' + Config.iguanaCorePort, {
method: 'POST',
body: JSON.stringify(payload),
@@ -950,36 +1022,49 @@ export function getKMDAddressesNative(coin) {
})
.then(response => response.json())
.then(function(json) {
- const allAddrArray = json.map(res => res.address).filter((x, i, a) => a.indexOf(x) == i);
- for (let a=0; a < allAddrArray.length; a++) {
- const filteredArray = json.filter(res => res.address === allAddrArray[a]).map(res => res.amount);
-
- let isNewAddr = true;
- for (let x=0; x < 2 && isNewAddr; x++) {
- for (let y=0; y < result[x].length && isNewAddr; y++) {
- if (allAddrArray[a] === result[x][y]) {
- isNewAddr = false;
+ if (mode === 'full' || mode === 'basilisk') {
+ result[0] = result[0].result;
+ }
+
+ if (mode !== 'basilisk') {
+ const allAddrArray = json.map(res => res.address).filter((x, i, a) => a.indexOf(x) == i);
+ for (let a=0; a < allAddrArray.length; a++) {
+ const filteredArray = json.filter(res => res.address === allAddrArray[a]).map(res => res.amount);
+
+ let isNewAddr = true;
+ for (let x=0; x < result.length && isNewAddr; x++) {
+ for (let y=0; y < result[x].length && isNewAddr; y++) {
+ if (allAddrArray[a] === result[x][y]) {
+ isNewAddr = false;
+ }
}
}
- }
- if (isNewAddr) {
- if (allAddrArray[a].substring(0, 2) === 'zc' || allAddrArray[a].substring(0, 2) === 'zt') {
- result[1][result[1].length] = allAddrArray[a];
- } else {
- result[0][result[0].length] = allAddrArray[a];
+ if (isNewAddr) {
+ if (allAddrArray[a].substring(0, 2) === 'zc' || allAddrArray[a].substring(0, 2) === 'zt') {
+ result[1][result[1].length] = allAddrArray[a];
+ } else {
+ result[0][result[0].length] = allAddrArray[a];
+ }
+ console.log('new addr ' + allAddrArray[a] + ' | ' + allAddrArray[a].substring(0, 2));
}
- console.log('new addr ' + allAddrArray[a] + ' | ' + allAddrArray[a].substring(0, 2));
}
}
let newAddressArray = [];
- for (let a=0; a < 2; a++) {
+ for (let a=0; a < result.length; a++) {
newAddressArray[a] = [];
for (let b=0; b < result[a].length; b++) {
- const filteredArray = json.filter(res => res.address === result[a][b]).map(res => res.amount);
+ var filteredArray;
+
+ if (mode === 'basilisk') {
+ filteredArray = json.map(res => res.amount);
+ } else {
+ filteredArray = json.filter(res => res.address === result[a][b]).map(res => res.amount);
+ }
+
let sum = 0;
for (let i=0; i < filteredArray.length; i++) {
@@ -988,7 +1073,7 @@ export function getKMDAddressesNative(coin) {
newAddressArray[a][b] = {
address: result[a][b],
- amount: sum,
+ amount: currentAddress === result[a][b] ? sum : 'N/A',
};
}
}
@@ -1002,6 +1087,30 @@ export function getKMDAddressesNative(coin) {
}
}
+function getShepherdCacheState(json) {
+ return {
+ type: DASHBOARD_ACTIVE_COIN_GET_CACHE,
+ cache: json && json.result && json.result.basilisk ? json.result.basilisk : null,
+ }
+}
+
+export function getShepherdCache(pubkey) {
+ return dispatch => {
+ return fetch('http://127.0.0.1:' + Config.agamaPort + '/shepherd/cache?pubkey=' + pubkey, {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ })
+ .catch(function(error) {
+ console.log(error);
+ dispatch(triggerToaster(true, 'getShepherdCache', 'Error', 'error'));
+ })
+ .then(response => response.json())
+ .then(json => dispatch(getShepherdCacheState(json)))
+ }
+}
+
function getDebugLogState(json) {
const _data = json.result.replace('\n', '\r\n');
@@ -1281,7 +1390,9 @@ export function getNativeTxHistoryState(json) {
json = null;
} else if (json && json.result) {
json = json.result;
- }
+ } else if (!json.length) {
+ json = 'no data';
+ }
return {
type: DASHBOARD_ACTIVE_COIN_NATIVE_TXHISTORY,
@@ -1292,6 +1403,7 @@ export function getNativeTxHistoryState(json) {
function handleGetNewKMDAddresses(pubpriv, coin, dispatch) {
dispatch(triggerToaster(true, translate('KMD_NATIVE.NEW_ADDR_GENERATED'), translate('TOASTR.WALLET_NOTIFICATION'), 'success'));
dispatch(getKMDAddressesNative(coin));
+
return {};
}
@@ -1469,6 +1581,88 @@ export function getKMDOPID(opid, coin) {
}
}
+function sendToAddressState(json, dispatch) {
+ if (json && json.error) {
+ dispatch(triggerToaster(true, json.error, 'Error', 'error'));
+
+ return {
+ type: DASHBOARD_ACTIVE_COIN_SENDTO,
+ lastSendToResponse: json,
+ }
+ } else if (json && json.result && json.complete) {
+ dispatch(triggerToaster(true, translate('TOASTR.TX_SENT_ALT'), translate('TOASTR.WALLET_NOTIFICATION'), 'success'));
+
+ return {
+ type: DASHBOARD_ACTIVE_COIN_SENDTO,
+ lastSendToResponse: json,
+ }
+ }
+}
+
+export function sendToAddress(coin, _payload) {
+ const payload = {
+ 'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
+ 'coin': coin,
+ 'method': 'sendtoaddress',
+ 'params': [
+ _payload.sendTo,
+ _payload.amount,
+ 'EasyDEX',
+ 'EasyDEXTransaction'
+ ]
+ };
+
+ return dispatch => {
+ return fetch('http://127.0.0.1:' + Config.iguanaCorePort, {
+ method: 'POST',
+ body: JSON.stringify(payload),
+ })
+ .catch(function(error) {
+ console.log(error);
+ dispatch(triggerToaster(true, 'sendToAddress', 'Error', 'error'));
+ })
+ .then(response => response.json())
+ .then(json => dispatch(sendToAddressState(json, dispatch)))
+ }
+}
+
+function checkAddressBasiliskHandle(json) {
+ if (json && json.error) {
+ return dispatch => {
+ dispatch(triggerToaster(true, json.error, translate('TOASTR.WALLET_NOTIFICATION'), 'error'));
+ }
+ }
+
+ if (json && json.coin && json.randipbits) {
+ return dispatch => {
+ dispatch(triggerToaster(true, 'Address already registered', translate('TOASTR.WALLET_NOTIFICATION'), 'warning'));
+ }
+ }
+}
+
+export function checkAddressBasilisk(coin, address) {
+ const payload = {
+ 'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
+ 'agent': 'dex',
+ 'method': 'checkaddress',
+ 'address': address,
+ 'symbol': coin
+ };
+
+ return dispatch => {
+ return fetch('http://127.0.0.1:' + Config.iguanaCorePort, {
+ method: 'POST',
+ body: JSON.stringify(payload),
+ })
+ .catch(function(error) {
+ console.log(error);
+ dispatch(triggerToaster(true, 'checkAddressBasilisk', 'Error', 'error'));
+ })
+ .then(response => response.json())
+ .then(json => dispatch(checkAddressBasiliskHandle(json)))
+ }
+}
+
/*function Shepherd_SendPendValue() {
Shepherd_SysInfo().then(function(result){
var ram_data = formatBytes(result.totalmem_bytes)
diff --git a/react/src/components/dashboard/coinTileItem.js b/react/src/components/dashboard/coinTileItem.js
index bdc9c06..9e551c7 100644
--- a/react/src/components/dashboard/coinTileItem.js
+++ b/react/src/components/dashboard/coinTileItem.js
@@ -13,7 +13,9 @@ import {
getNativeTxHistory,
getKMDAddressesNative,
getKMDOPID,
- getFullTransactionsList
+ getFullTransactionsList,
+ getBasiliskTransactionsList,
+ getShepherdCache
} from '../../actions/actionCreators';
import Store from '../../store';
@@ -24,6 +26,11 @@ class CoinTileItem extends React.Component {
};
}
+ // TODO: 1) cache native/full node data to file
+ // 2) limit amount of req per update e.g. list of addresses don't change too often
+ // 3) limit req in basilisk as much as possible incl. activehandle
+ // 4) add pending requests store
+
dashboardChangeActiveCoin(coin, mode) {
if (coin !== this.props.ActiveCoin.coin) {
Store.dispatch(stopInterval('sync', this.props.Interval.interval));
@@ -33,7 +40,7 @@ class CoinTileItem extends React.Component {
var _iguanaActiveHandle = setInterval(function() {
Store.dispatch(getSyncInfo(coin));
Store.dispatch(iguanaEdexBalance(coin, mode));
- Store.dispatch(getAddressesByAccount(coin));
+ Store.dispatch(getKMDAddressesNative(coin, mode)); //getAddressesByAccount(coin));
Store.dispatch(getFullTransactionsList(coin));
}, 3000);
Store.dispatch(startInterval('sync', _iguanaActiveHandle));
@@ -50,7 +57,17 @@ class CoinTileItem extends React.Component {
Store.dispatch(startInterval('sync', _iguanaActiveHandle));
}
if (mode === 'basilisk') {
- Store.dispatch(getAddressesByAccount(coin));
+ var _iguanaActiveHandle = setInterval(function() {
+ const useAddress = this.props.ActiveCoin.mainBasiliskAddress ? this.props.ActiveCoin.mainBasiliskAddress : this.props.Dashboard.activeHandle[coin];
+
+ if (this.props && this.props.Dashboard && this.props.Dashboard.activeHandle && this.props.Dashboard.activeHandle[coin]) {
+ Store.dispatch(getBasiliskTransactionsList(coin, useAddress));
+ Store.dispatch(getKMDAddressesNative(coin, mode, useAddress));
+ Store.dispatch(getShepherdCache(this.props.Dashboard.activeHandle.pubkey));
+ Store.dispatch(iguanaEdexBalance(coin, mode));
+ }
+ }.bind(this), 3000);
+ Store.dispatch(startInterval('sync', _iguanaActiveHandle));
// basilisk
}
}
diff --git a/react/src/components/dashboard/dashboard.js b/react/src/components/dashboard/dashboard.js
index fbbbe17..2564891 100644
--- a/react/src/components/dashboard/dashboard.js
+++ b/react/src/components/dashboard/dashboard.js
@@ -17,6 +17,7 @@ import WalletsBasiliskRefresh from './walletsBasiliskRefresh';
import WalletsBasiliskConnection from './walletsBasiliskConnection';
import WalletsNative from './walletsNative';
import WalletsNativeTxInfo from './walletsNativeTxInfo';
+import WalletsTxInfo from './walletsTxInfo';
class Dashboard extends React.Component {
constructor(props) {
@@ -37,11 +38,12 @@ class Dashboard extends React.Component {
-
+
+
diff --git a/react/src/components/dashboard/receiveCoin.js b/react/src/components/dashboard/receiveCoin.js
index 6c23bf0..939dcdf 100644
--- a/react/src/components/dashboard/receiveCoin.js
+++ b/react/src/components/dashboard/receiveCoin.js
@@ -1,19 +1,59 @@
import React from 'react';
import { translate } from '../../translate/translate';
+import { checkAddressBasilisk, importAddressBasilisk } from '../../actions/actionCreators';
+import Store from '../../store';
+
+// TODO: implement sorting
+// TODO: add import address ui in basilisk
+// TODO: fallback to localstorage/stores data in case iguana is taking too long to respond
class ReceiveCoin extends React.Component {
+ constructor(props) {
+ super(props);
+ }
+
+ checkAddressBasilisk(address) {
+ Store.dispatch(checkAddressBasilisk(this.props.coin, address));
+ }
+
+ /*importAddressBasilisk(address) {
+ Store.dispatch(importAddressBasilisk(this.props.coin, address));
+ }
+ this.importAddressBasilisk(address)}>
+
+ */
+
+ renderAddressActions(address) {
+ if (this.props.mode === 'basilisk') {
+ return (
+
+
+ {translate('IAPI.PUBLIC_SM')}
+
+ this.checkAddressBasilisk(address)}>
+
+
+ |
+ );
+ } else {
+ return (
+
+
+ {translate('IAPI.PUBLIC_SM')}
+
+ |
+ );
+ }
+ }
+
renderAddressList() {
- if (this.props.addresses && this.props.addresses.length) {
- return this.props.addresses.map((address) =>
-
-
-
- {translate('IAPI.PUBLIC_SM')}
-
- |
- {address} |
- |
- |
+ if (this.props.addresses && this.props.addresses['public'] && this.props.addresses['public'].length) {
+ return this.props.addresses['public'].map((address) =>
+
+ {this.renderAddressActions(address.address)}
+ {address.address} |
+ {address.amount} |
+ {address.interest ? address.interest : 'N/A'} |
);
} else {
diff --git a/react/src/components/dashboard/sendCoin.js b/react/src/components/dashboard/sendCoin.js
index 06e69ac..2e2202c 100644
--- a/react/src/components/dashboard/sendCoin.js
+++ b/react/src/components/dashboard/sendCoin.js
@@ -1,7 +1,7 @@
import React from 'react';
import { translate } from '../../translate/translate';
-//import { } from '../../actions/actionCreators';
-//import Store from '../../store';
+import { sendToAddress } from '../../actions/actionCreators';
+import Store from '../../store';
// TODO: implement logic
@@ -10,17 +10,111 @@ class SendCoin extends React.Component {
super(props);
this.state = {
currentStep: 0,
+ sendFrom: this.props.Dashboard && this.props.Dashboard.activeHandle ? this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin] : null,
+ sendFromAmount: 0,
+ sendTo: null,
+ amount: 0,
+ fee: 0.0001,
+ sendSig: false,
};
+ this.updateInput = this.updateInput.bind(this);
+ this.handleSubmit = this.handleSubmit.bind(this);
+ this.toggleSendSig = this.toggleSendSig.bind(this);
}
changeSendCoinStep(step) {
this.setState(Object.assign({}, this.state, {
currentStep: step,
}));
+
+ if (step === 2) {
+ Store.dispatch(sendToAddress(this.props.ActiveCoin.coin, this.state));
+ }
+ }
+
+ toggleSendSig() {
+ this.setState(Object.assign({}, this.state, {
+ sendSig: !this.state.sendSig,
+ }));
+ }
+
+ updateInput(e) {
+ this.setState({
+ [e.target.name]: e.target.value,
+ });
+ console.log(this.state);
+ }
+
+ handleSubmit() {
+ Store.dispatch(sendNativeTx(this.props.ActiveCoin.coin, this.state));
+ setTimeout(function() {
+ Store.dispatch(getKMDOPID(null, this.props.ActiveCoin.coin));
+ }, 1000);
+ }
+
+ renderSignedTx(signedtx) {
+ const substrBlocks = 10;
+ const substrLength = this.props.ActiveCoin.lastSendToResponse['signedtx'].length / substrBlocks;
+ let out = [];
+
+ for (let i = 0; i < substrBlocks; i++) {
+ out.push(
+ {this.props.ActiveCoin.lastSendToResponse['signedtx'].substring(i * substrLength, substrLength * i + substrLength)}
+ );
+ }
+
+ return out.length ? out : null;
+ }
+
+ renderKey(key) {
+ if (key === 'signedtx') {
+ return this.renderSignedTx();
+ } else if (key === 'complete') {
+ if (this.props.ActiveCoin.lastSendToResponse[key] === true) {
+ return (
+ true
+ );
+ } else {
+ return (
+ false
+ );
+ }
+ } else if (key === 'result') {
+ return (
+ {this.props.ActiveCoin.lastSendToResponse[key]}
+ );
+ } else if (key === 'error') {
+ return (
+ {this.props.ActiveCoin.lastSendToResponse[key]}
+ );
+ } else if (key === 'sendrawtransaction') {
+ if (this.props.ActiveCoin.lastSendToResponse[key] === 'success') {
+ return (
+ true
+ );
+ } else {
+ return (
+ false
+ );
+ }
+ }
+ }
+
+ renderSendCoinResponse() {
+ if (this.props.ActiveCoin.lastSendToResponse) {
+ return Object.keys(this.props.ActiveCoin.lastSendToResponse).map((key, index) =>
+
+ {key} |
+ {this.renderKey(key)} |
+
+ );
+ } else {
+ return null;
+ }
}
render() {
- if (this.props && this.props.send && this.props.mode !== 'native') {
+ if (this.props.ActiveCoin && this.props.ActiveCoin.send && this.props.ActiveCoin.mode !== 'native') {
return (
@@ -51,49 +145,44 @@ class SendCoin extends React.Component {
- {translate('INDEX.SEND')}
+ {translate('INDEX.SEND')} {this.props.ActiveCoin.coin}
-
@@ -151,6 +240,7 @@ class SendCoin extends React.Component {
+ {this.renderSendCoinResponse()}
diff --git a/react/src/components/dashboard/walletsData.js b/react/src/components/dashboard/walletsData.js
index 92a1e0b..6e292f0 100644
--- a/react/src/components/dashboard/walletsData.js
+++ b/react/src/components/dashboard/walletsData.js
@@ -1,7 +1,14 @@
import React from 'react';
import { translate } from '../../translate/translate';
import { secondsToString } from '../../util/time';
-import { basiliskRefresh, basiliskConnection, getDexNotaries } from '../../actions/actionCreators';
+import {
+ basiliskRefresh,
+ basiliskConnection,
+ getDexNotaries,
+ toggleDashboardTxInfoModal,
+ getBasiliskTransactionsList,
+ changeMainBasiliskAddress
+} from '../../actions/actionCreators';
import Store from '../../store';
class WalletsData extends React.Component {
@@ -12,12 +19,16 @@ class WalletsData extends React.Component {
itemsPerPage: 10,
activePage: 1,
itemsList: null,
+ currentAddress: null,
+ addressSelectorOpen: false,
};
this.updateInput = this.updateInput.bind(this);
this.toggleBasiliskActionsMenu = this.toggleBasiliskActionsMenu.bind(this);
this.basiliskRefreshAction = this.basiliskRefreshAction.bind(this);
this.basiliskConnectionAction = this.basiliskConnectionAction.bind(this);
this.getDexNotariesAction = this.getDexNotariesAction.bind(this);
+ this.openDropMenu = this.openDropMenu.bind(this);
+ this.refreshTxList = this.refreshTxList.bind(this);
}
toggleBasiliskActionsMenu() {
@@ -53,6 +64,10 @@ class WalletsData extends React.Component {
});
}
+ toggleTxInfoModal(display, txIndex) {
+ Store.dispatch(toggleDashboardTxInfoModal(display, txIndex));
+ }
+
componentWillReceiveProps(props) {
if (this.props.ActiveCoin.txhistory && this.props.ActiveCoin.txhistory.length) {
if (!this.state.itemsList || (this.state.itemsList && !this.state.itemsList.length) || (props.ActiveCoin.txhistory !== this.props.ActiveCoin.txhistory)) {
@@ -64,6 +79,12 @@ class WalletsData extends React.Component {
}));
}
}
+
+ if (this.props.ActiveCoin.txhistory && this.props.ActiveCoin.txhistory === 'no data') {
+ this.setState(Object.assign({}, this.state, {
+ itemsList: 'no data',
+ }));
+ }
}
updateCurrentPage(page) {
@@ -97,8 +118,8 @@ class WalletsData extends React.Component {