Browse Source

Merge pull request #103 from pbca26/redux

Redux
all-modes
pbca26 8 years ago
committed by GitHub
parent
commit
24e5a6acdf
  1. 332
      react/src/actions/actionCreators.js
  2. 6
      react/src/components/dashboard/coinTileItem.js
  3. 241
      react/src/components/dashboard/sendCoin.js
  4. 73
      react/src/components/dashboard/walletsData.js
  5. 66
      react/src/components/dashboard/walletsNativeSend.js
  6. 9
      react/src/components/dashboard/walletsNativeTxHistory.js
  7. 2
      react/src/config.js
  8. 5
      react/src/util/sort.js

332
react/src/actions/actionCreators.js

@ -48,6 +48,8 @@ export const DASHBOARD_DISPLAY_NOTARIES_MODAL = 'DASHBOARD_DISPLAY_NOTARIES_MODA
export const DASHBOARD_CONNECT_NOTARIES = 'DASHBOARD_CONNECT_NOTARIES'; export const DASHBOARD_CONNECT_NOTARIES = 'DASHBOARD_CONNECT_NOTARIES';
export const VIEW_CACHE_DATA = 'VIEW_CACHE_DATA'; export const VIEW_CACHE_DATA = 'VIEW_CACHE_DATA';
var iguanaForks = {}; // forks in mem array
export function toggleViewCacheModal(display) { export function toggleViewCacheModal(display) {
return { return {
type: VIEW_CACHE_DATA, type: VIEW_CACHE_DATA,
@ -157,7 +159,7 @@ function toggleSendReceiveCoinFormsState() {
} }
} }
function triggerToaster(display, message, title, _type) { export function triggerToaster(display, message, title, _type) {
return { return {
type: TOASTER_MESSAGE, type: TOASTER_MESSAGE,
display, display,
@ -305,6 +307,10 @@ export function dismissToasterMessage() {
export function addCoin(coin, mode) { export function addCoin(coin, mode) {
console.log('coin, mode', coin + ' ' + mode); console.log('coin, mode', coin + ' ' + mode);
/*startIguanaInstance(mode, coin)
.then(function(json) {
console.log('addCoin+startIguanaInstance', json);
});*/
if (mode === '-1') { if (mode === '-1') {
return dispatch => { return dispatch => {
dispatch(shepherdGetConfig(coin, mode)); dispatch(shepherdGetConfig(coin, mode));
@ -504,6 +510,8 @@ export function getDexCoins() {
'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'), 'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
'agent': 'InstantDEX', 'agent': 'InstantDEX',
'method': 'allcoins', 'method': 'allcoins',
'immediate': 60000,
'timeout': 60000
}) })
}) })
.catch(function(error) { .catch(function(error) {
@ -534,7 +542,8 @@ export function iguanaWalletPassphrase(_passphrase) {
'password': _passphrase, 'password': _passphrase,
'timeout': '2592000', 'timeout': '2592000',
'agent': 'bitcoinrpc', 'agent': 'bitcoinrpc',
'method': 'walletpassphrase' 'method': 'walletpassphrase',
'immediate': 60000,
}), }),
}) })
.catch(function(error) { .catch(function(error) {
@ -553,7 +562,9 @@ export function iguanaActiveHandle(getMainAddress) {
body: JSON.stringify({ body: JSON.stringify({
'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'), 'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
'agent': 'SuperNET', 'agent': 'SuperNET',
'method': 'activehandle' 'method': 'activehandle',
'immediate': 60000,
'timeout': 60000
}), }),
}) })
.catch(function(error) { .catch(function(error) {
@ -573,7 +584,9 @@ export function iguanaEdexBalance(coin) {
'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'), 'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
'agent': 'bitcoinrpc', 'agent': 'bitcoinrpc',
'method': 'getbalance', 'method': 'getbalance',
'coin': coin 'coin': coin,
'immediate': 60000,
'timeout': 60000
}), }),
}) })
.catch(function(error) { .catch(function(error) {
@ -613,7 +626,9 @@ export function encryptWallet(_passphrase, cb, coin) {
'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'), 'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
'agent': 'bitcoinrpc', 'agent': 'bitcoinrpc',
'method': 'encryptwallet', 'method': 'encryptwallet',
'passphrase': _passphrase 'passphrase': _passphrase,
'immediate': 60000,
'timeout': 60000
}; };
return dispatch => { return dispatch => {
@ -637,7 +652,8 @@ export function walletPassphrase(_passphrase) {
'agent': 'bitcoinrpc', 'agent': 'bitcoinrpc',
'method': 'walletpassphrase', 'method': 'walletpassphrase',
'password': _passphrase, 'password': _passphrase,
'timeout': '2592000' 'timeout': '2592000',
'immediate': 60000,
}; };
return dispatch => { return dispatch => {
@ -685,7 +701,9 @@ export function getFullTransactionsList(coin) {
0, 0,
9999999, 9999999,
[] []
] ],
'immediate': 60000,
'timeout': 60000
}; };
return dispatch => { return dispatch => {
@ -710,7 +728,9 @@ export function getBasiliskTransactionsList(coin, address) {
'address': address, 'address': address,
'count': 100, 'count': 100,
'skip': 0, 'skip': 0,
'symbol': coin 'symbol': coin,
'immediate': 60000,
'timeout': 60000
}; };
if (sessionStorage.getItem('useCache')) { if (sessionStorage.getItem('useCache')) {
@ -757,6 +777,8 @@ export function getPeersList(coin) {
'agent': 'SuperNET', 'agent': 'SuperNET',
'method': 'getpeers', 'method': 'getpeers',
'activecoin': coin, 'activecoin': coin,
'immediate': 60000,
'timeout': 60000
}; };
return dispatch => { return dispatch => {
@ -802,7 +824,9 @@ export function addPeerNode(coin, ip) {
'agent': 'iguana', 'agent': 'iguana',
'method': 'addnode', 'method': 'addnode',
'activecoin': coin, 'activecoin': coin,
'ipaddr': ip 'ipaddr': ip,
'immediate': 60000,
'timeout': 60000
}; };
return dispatch => { return dispatch => {
@ -820,13 +844,26 @@ export function addPeerNode(coin, ip) {
} }
export function getAddressesByAccountState(json, coin, mode) { export function getAddressesByAccountState(json, coin, mode) {
if (mode === 'full') {
let publicAddressArray = [];
for (let i = 0; i < json.result.length; i++) {
publicAddressArray.push({
'address': json.result[i],
'amount': 'N/A'
});
}
json.result = publicAddressArray;
}
if (mode === 'basilisk') { if (mode === 'basilisk') {
getDexBalance(coin, mode, json.result); getDexBalance(coin, mode, json.result);
} }
return { return {
type: ACTIVE_COIN_GET_ADDRESSES, type: ACTIVE_COIN_GET_ADDRESSES,
addresses: json.result, addresses: { 'public': json.result },
} }
} }
@ -836,7 +873,9 @@ export function getAddressesByAccount(coin, mode) {
'coin': coin, 'coin': coin,
'agent': 'bitcoinrpc', 'agent': 'bitcoinrpc',
'method': 'getaddressesbyaccount', 'method': 'getaddressesbyaccount',
'account': '*' 'account': '*',
'immediate': 60000,
'timeout': 60000
}; };
return dispatch => { return dispatch => {
@ -891,8 +930,8 @@ export function getSyncInfo(coin) {
'coin': coin, 'coin': coin,
'agent': 'bitcoinrpc', 'agent': 'bitcoinrpc',
'method': 'getinfo', 'method': 'getinfo',
'immediate': 100, 'immediate': 60000,
'timeout': 4000 'timeout': 60000
}; };
return dispatch => { return dispatch => {
@ -957,7 +996,9 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
'method': 'passthru', 'method': 'passthru',
'asset': coin, 'asset': coin,
'function': ajax_function_input, 'function': ajax_function_input,
'hex': tmplistaddr_hex_input 'hex': tmplistaddr_hex_input,
'immediate': 60000,
'timeout': 60000
}; };
} else { } else {
payload = { payload = {
@ -965,20 +1006,23 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
'agent': passthru_agent, 'agent': passthru_agent,
'method': 'passthru', 'method': 'passthru',
'function': ajax_function_input, 'function': ajax_function_input,
'hex': tmplistaddr_hex_input 'hex': tmplistaddr_hex_input,
'immediate': 60000,
'timeout': 60000
}; };
} }
if (mode === 'native' || mode === 'basilisk') { if (mode === 'full' || mode === 'basilisk') {
payload = { payload = {
'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'), 'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
'coin': coin, 'coin': coin,
'agent': 'bitcoinrpc', 'agent': 'bitcoinrpc',
'method': 'getaddressesbyaccount', 'method': 'getaddressesbyaccount',
'account': '*' 'account': '*',
'immediate': 60000,
'timeout': 60000
}; };
} }
console.log('pl', payload);
if (sessionStorage.getItem('useCache') && mode === 'basilisk') { if (sessionStorage.getItem('useCache') && mode === 'basilisk') {
const pubkey = JSON.parse(sessionStorage.getItem('IguanaActiveAccount')).pubkey; const pubkey = JSON.parse(sessionStorage.getItem('IguanaActiveAccount')).pubkey;
@ -1020,14 +1064,16 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
tmpIguanaRPCAuth = 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'); tmpIguanaRPCAuth = 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth');
var payload; var payload;
if (passthru_agent == 'iguana') { if (passthru_agent === 'iguana') {
payload = { payload = {
'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'), 'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
'agent': passthru_agent, 'agent': passthru_agent,
'method': 'passthru', 'method': 'passthru',
'asset': coin, 'asset': coin,
'function': 'listunspent', 'function': 'listunspent',
'hex': '' 'hex': '',
'immediate': 60000,
'timeout': 60000
}; };
} else { } else {
payload = { payload = {
@ -1035,7 +1081,9 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
'agent': passthru_agent, 'agent': passthru_agent,
'method': 'passthru', 'method': 'passthru',
'function': 'listunspent', 'function': 'listunspent',
'hex': '' 'hex': '',
'immediate': 60000,
'timeout': 60000
}; };
} }
@ -1047,7 +1095,9 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
'params': [ 'params': [
1, 1,
9999999, 9999999,
] ],
'immediate': 60000,
'timeout': 60000
}; };
} }
@ -1058,21 +1108,20 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
'agent': 'dex', 'agent': 'dex',
'method': 'listunspent', 'method': 'listunspent',
'address': currentAddress, 'address': currentAddress,
'symbol': coin 'symbol': coin,
'immediate': 60000,
'timeout': 60000
}; };
} }
function calcBalance(result, json, dispatch, mode) { function calcBalance(result, json, dispatch, mode) {
console.log('result', result); //console.log('result', result);
if (mode === 'full' || mode === 'basilisk') { if (mode === 'full' || mode === 'basilisk') {
result[0] = result[0].result; result[0] = result[0].result;
} else {
result[0] = result[0].result;
result[1] = result[1].result;
} }
console.log('calc result', result); //console.log('calc result', result);
console.log('calc json', json); //console.log('calc json', json);
if (mode !== 'basilisk') { if (mode !== 'basilisk') {
const allAddrArray = json.map(res => res.address).filter((x, i, a) => a.indexOf(x) == i); const allAddrArray = json.map(res => res.address).filter((x, i, a) => a.indexOf(x) == i);
@ -1112,8 +1161,8 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
} else { } else {
filteredArray = json.filter(res => res.address === result[a][b]).map(res => res.amount); filteredArray = json.filter(res => res.address === result[a][b]).map(res => res.amount);
} }
console.log('filteredArray', filteredArray); //console.log('filteredArray', filteredArray);
console.log('addr', result[a][b]); //console.log('addr', result[a][b]);
let sum = 0; let sum = 0;
@ -1123,7 +1172,7 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
newAddressArray[a][b] = { newAddressArray[a][b] = {
address: result[a][b], address: result[a][b],
amount: currentAddress === result[a][b] ? sum : 'N/A', amount: currentAddress === result[a][b] || mode === 'native' ? sum : 'N/A',
}; };
} }
} }
@ -1149,12 +1198,12 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
}) })
.then(response => response.json()) .then(response => response.json())
.then(function(json) { .then(function(json) {
var updatedCache = Object.assign({}, json.result);
json = json.result.basilisk; json = json.result.basilisk;
// if listunspent is not in cache file retrieve new copy // if listunspent is not in cache file retrieve new copy
// otherwise read from cache data // otherwise read from cache data
// TODO: save listunspent to cache file(?)
if (json[coin][currentAddress].listunspent) { if (json[coin][currentAddress].listunspent) {
calcBalance(result, json[coin][currentAddress].listunspent, dispatch, mode); calcBalance(result, json[coin][currentAddress].listunspent.data, dispatch, mode);
} else { } else {
fetch('http://127.0.0.1:' + (Config.useBasiliskInstance && mode === 'basilisk' ? Config.basiliskPort : Config.iguanaCorePort), { fetch('http://127.0.0.1:' + (Config.useBasiliskInstance && mode === 'basilisk' ? Config.basiliskPort : Config.iguanaCorePort), {
method: 'POST', method: 'POST',
@ -1166,6 +1215,12 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
}) })
.then(response => response.json()) .then(response => response.json())
.then(function(json) { .then(function(json) {
updatedCache.basilisk[coin][currentAddress].listunspent = {
'data': json,
'status': 'done',
'timestamp': Date.now(),
};
dispatch(shepherdGroomPost(pubkey, updatedCache));
calcBalance(result, json, dispatch, mode); calcBalance(result, json, dispatch, mode);
}) })
} }
@ -1188,6 +1243,27 @@ export function getKMDAddressesNative(coin, mode, currentAddress) {
} }
} }
export function shepherdGroomPost(_filename, _payload) {
return dispatch => {
return 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, 'shepherdGroomPost', 'Error', 'error'));
})
.then(response => response.json())
.then(json => console.log(json))
}
}
export function fetchUtxoCache(_payload) { export function fetchUtxoCache(_payload) {
const _userpass = '?userpass=tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'), const _userpass = '?userpass=tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
_pubkey = '&pubkey=' + _payload.pubkey, _pubkey = '&pubkey=' + _payload.pubkey,
@ -1294,7 +1370,9 @@ export function importPrivKey(wifKey) {
'params': [ 'params': [
wifKey, wifKey,
'imported' 'imported'
] ],
'immediate': 60000,
'timeout': 60000
}; };
return dispatch => { return dispatch => {
@ -1380,7 +1458,9 @@ export function getSyncInfoNative(coin) {
'method': 'passthru', 'method': 'passthru',
'asset': coin, 'asset': coin,
'function': 'getinfo', 'function': 'getinfo',
'hex': '' 'hex': '',
'immediate': 60000,
'timeout': 60000
}; };
return dispatch => { return dispatch => {
@ -1404,7 +1484,9 @@ export function getDexBalance(coin, addr) {
'agent': 'dex', 'agent': 'dex',
'method': 'listunspent', 'method': 'listunspent',
'address': _addr, 'address': _addr,
'symbol': coin 'symbol': coin,
'immediate': 60000,
'timeout': 60000
}; };
console.log('addr', _addr); console.log('addr', _addr);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -1438,7 +1520,9 @@ export function getKMDBalanceTotal(coin) {
'method': 'passthru', 'method': 'passthru',
'asset': coin, 'asset': coin,
'function': 'z_gettotalbalance', 'function': 'z_gettotalbalance',
'hex': '3000' 'hex': '3000',
'immediate': 60000,
'timeout': 60000
}; };
} else { } else {
payload = { payload = {
@ -1446,7 +1530,9 @@ export function getKMDBalanceTotal(coin) {
'agent': getPassthruAgent(coin), 'agent': getPassthruAgent(coin),
'method': 'passthru', 'method': 'passthru',
'function': 'z_gettotalbalance', 'function': 'z_gettotalbalance',
'hex': '3000' 'hex': '3000',
'immediate': 60000,
'timeout': 60000
}; };
} }
@ -1485,7 +1571,9 @@ export function getNativeTxHistory(coin) {
'method': 'passthru', 'method': 'passthru',
'asset': coin, 'asset': coin,
'function': 'listtransactions', 'function': 'listtransactions',
'hex': '' 'hex': '',
'immediate': 60000,
'timeout': 60000
}; };
} else { } else {
payload = { payload = {
@ -1493,7 +1581,9 @@ export function getNativeTxHistory(coin) {
'agent': getPassthruAgent(coin), 'agent': getPassthruAgent(coin),
'method': 'passthru', 'method': 'passthru',
'function': 'listtransactions', 'function': 'listtransactions',
'hex': '' 'hex': '',
'immediate': 60000,
'timeout': 60000
}; };
} }
@ -1551,7 +1641,9 @@ export function getNewKMDAddresses(coin, pubpriv) {
'method': 'passthru', 'method': 'passthru',
'asset': coin, 'asset': coin,
'function': ajax_function_input, 'function': ajax_function_input,
'hex': '' 'hex': '',
'immediate': 60000,
'timeout': 60000
}; };
} else { } else {
payload = { payload = {
@ -1559,7 +1651,9 @@ export function getNewKMDAddresses(coin, pubpriv) {
'agent': coin, 'agent': coin,
'method': 'passthru', 'method': 'passthru',
'function': ajax_function_input, 'function': ajax_function_input,
'hex': '' 'hex': '',
'immediate': 60000,
'timeout': 60000
}; };
} }
@ -1585,7 +1679,9 @@ export function iguanaHashHex(data) {
'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'), 'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
'agent': 'hash', 'agent': 'hash',
'method': 'hex', 'method': 'hex',
'message': data 'message': data,
'immediate': 60000,
'timeout': 60000
}; };
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -1617,7 +1713,9 @@ export function sendNativeTx(coin, _payload) {
'method': 'passthru', 'method': 'passthru',
'asset': coin, 'asset': coin,
'function': 'z_sendmany', 'function': 'z_sendmany',
'hex': hashHexJson 'hex': hashHexJson,
'immediate': 60000,
'timeout': 60000
}; };
} else { } else {
payload = { payload = {
@ -1625,7 +1723,9 @@ export function sendNativeTx(coin, _payload) {
'agent': getPassthruAgent(coin), 'agent': getPassthruAgent(coin),
'method': 'passthru', 'method': 'passthru',
'function': 'z_sendmany', 'function': 'z_sendmany',
'hex': hashHexJson 'hex': hashHexJson,
'immediate': 60000,
'timeout': 60000
}; };
} }
@ -1681,7 +1781,9 @@ export function getKMDOPID(opid, coin) {
'method': 'passthru', 'method': 'passthru',
'asset': coin, 'asset': coin,
'function': 'z_getoperationstatus', 'function': 'z_getoperationstatus',
'hex': hashHexJson 'hex': hashHexJson,
'immediate': 60000,
'timeout': 60000
}; };
} else { } else {
payload = { payload = {
@ -1689,7 +1791,9 @@ export function getKMDOPID(opid, coin) {
'agent': passthru_agent, 'agent': passthru_agent,
'method': 'passthru', 'method': 'passthru',
'function': 'z_getoperationstatus', 'function': 'z_getoperationstatus',
'hex': hashHexJson 'hex': hashHexJson,
'immediate': 60000,
'timeout': 60000
}; };
} }
@ -1725,6 +1829,13 @@ function sendToAddressState(json, dispatch) {
} }
} }
export function clearLastSendToResponseState() {
return {
type: DASHBOARD_ACTIVE_COIN_SENDTO,
lastSendToResponse: null,
}
}
export function sendToAddress(coin, _payload) { export function sendToAddress(coin, _payload) {
const payload = { const payload = {
'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'), 'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
@ -1735,7 +1846,9 @@ export function sendToAddress(coin, _payload) {
_payload.amount, _payload.amount,
'EasyDEX', 'EasyDEX',
'EasyDEXTransaction' 'EasyDEXTransaction'
] ],
'immediate': 60000,
'timeout': 60000
}; };
return dispatch => { return dispatch => {
@ -1752,6 +1865,36 @@ export function sendToAddress(coin, _payload) {
} }
} }
export function sendFromAddress(coin, _payload) {
const payload = {
'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
'coin': coin,
'method': 'sendfrom',
'params': [
_payload.sendFrom,
_payload.sendTo,
_payload.amount,
'EasyDEX',
'EasyDEXTransaction'
],
'immediate': 60000,
'timeout': 60000
};
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, 'sendFromAddress', 'Error', 'error'));
})
.then(response => response.json())
.then(json => dispatch(sendToAddressState(json, dispatch)))
}
}
function checkAddressBasiliskHandle(json) { function checkAddressBasiliskHandle(json) {
if (json && json.error) { if (json && json.error) {
return dispatch => { return dispatch => {
@ -1772,7 +1915,9 @@ export function checkAddressBasilisk(coin, address) {
'agent': 'dex', 'agent': 'dex',
'method': 'checkaddress', 'method': 'checkaddress',
'address': address, 'address': address,
'symbol': coin 'symbol': coin,
'immediate': 60000,
'timeout': 60000
}; };
return dispatch => { return dispatch => {
@ -1812,7 +1957,9 @@ export function validateAddressBasilisk(coin, address) {
'agent': 'dex', 'agent': 'dex',
'method': 'validateaddress', 'method': 'validateaddress',
'address': address, 'address': address,
'symbol': coin 'symbol': coin,
'immediate': 60000,
'timeout': 60000
}; };
return dispatch => { return dispatch => {
@ -1847,7 +1994,9 @@ export function getDexNotaries(coin) {
'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'), 'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
'agent': 'dex', 'agent': 'dex',
'method': 'getnotaries', 'method': 'getnotaries',
'symbol': coin 'symbol': coin,
'immediate': 60000,
'timeout': 60000
}; };
return dispatch => { return dispatch => {
@ -1881,7 +2030,9 @@ export function createNewWallet(_passphrase) {
'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'), 'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
'agent': 'bitcoinrpc', 'agent': 'bitcoinrpc',
'method': 'encryptwallet', 'method': 'encryptwallet',
'passphrase': _passphrase 'passphrase': _passphrase,
'immediate': 60000,
'timeout': 60000
}; };
return dispatch => { return dispatch => {
@ -1917,6 +2068,7 @@ export function deleteCacheFile(_payload) {
} }
export function fetchNewCacheData(_payload) { export function fetchNewCacheData(_payload) {
console.log('fetchNewCacheData', true);
const _userpass = '?userpass=tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'), const _userpass = '?userpass=tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
_pubkey = '&pubkey=' + _payload.pubkey, _pubkey = '&pubkey=' + _payload.pubkey,
_route = _payload.allcoins ? 'cache-all' : 'cache-one', _route = _payload.allcoins ? 'cache-all' : 'cache-one',
@ -1947,7 +2099,9 @@ function initNotaryNodesConSequence(nodes) {
'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'), 'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
'agent': 'dex', 'agent': 'dex',
'method': 'getinfo', 'method': 'getinfo',
'symbol': node 'symbol': node,
'immediate': 60000,
'timeout': 60000
}; };
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -2063,11 +2217,45 @@ export function restartIguanaInstance(pmid) {
}); });
} }
export function restartBasiliskInstance() {
return dispatch => {
getIguanaInstancesList()
.then(function(json) {
for (let port in json.result) {
if (json.result[port].mode === 'basilisk') {
restartIguanaInstance(json.result[port].pmid)
.then(function(json) {
console.log('restartBasiliskInstance', json);
});
}
}
});
}
}
export function resolveOpenAliasAddress(email) {
const url = email.replace('@', '.');
return new Promise((resolve, reject) => {
fetch('https://dns.google.com/resolve?name=' + url + '&type=txt', {
method: 'GET',
})
.catch(function(error) {
console.log(error);
dispatch(triggerToaster(true, 'resolveOpenAliasAddress', 'Error', 'error'));
})
.then(response => response.json())
.then(json => resolve(json))
});
}
export function connectNotaries() { export function connectNotaries() {
const payload = { const payload = {
'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'), 'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
'agent': 'dpow', 'agent': 'dpow',
'method': 'notarychains' 'method': 'notarychains,',
'immediate': 60000,
'timeout': 60000
}; };
return dispatch => { return dispatch => {
@ -2084,6 +2272,40 @@ export function connectNotaries() {
} }
} }
export function iguanaUTXORawTX(data) {
const payload = {
'userpass': 'tmpIgRPCUser@' + sessionStorage.getItem('IguanaRPCAuth'),
'symbol': data.coin,
'agent': 'basilisk',
'method': 'utxorawtx',
'vals': {
'timelock': 0,
'changeaddr': data.sendfrom,
'destaddr': data.sendtoaddr,
'txfee': data.txfee,
'amount': data.amount,
'sendflag': data.sendsig
},
'utxos': data.utxos,
'immediate': 60000,
'timeout': 60000
};
console.log('iguanaUTXORawTXExport', 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, 'iguanaUTXORawTX', 'Error', 'error'));
})
.then(response => response.json())
.then(json => resolve(json))
});
}
/*function Shepherd_SendPendValue() { /*function Shepherd_SendPendValue() {
Shepherd_SysInfo().then(function(result){ Shepherd_SysInfo().then(function(result){
var ram_data = formatBytes(result.totalmem_bytes) var ram_data = formatBytes(result.totalmem_bytes)

6
react/src/components/dashboard/coinTileItem.js

@ -45,11 +45,10 @@ class CoinTileItem extends React.Component {
Store.dispatch(iguanaActiveHandle(true)); Store.dispatch(iguanaActiveHandle(true));
Store.dispatch(getSyncInfo(coin)); Store.dispatch(getSyncInfo(coin));
Store.dispatch(iguanaEdexBalance(coin, mode)); Store.dispatch(iguanaEdexBalance(coin, mode));
Store.dispatch(getKMDAddressesNative(coin, mode)); //getAddressesByAccount(coin)); Store.dispatch(getAddressesByAccount(coin, mode));
Store.dispatch(getFullTransactionsList(coin)); Store.dispatch(getFullTransactionsList(coin));
} }
if (mode === 'basilisk') { if (mode === 'basilisk') {
console.log('dispatchCoinActions', mode);
const useAddress = this.props.ActiveCoin.mainBasiliskAddress ? this.props.ActiveCoin.mainBasiliskAddress : this.props.Dashboard.activeHandle[coin]; const useAddress = this.props.ActiveCoin.mainBasiliskAddress ? this.props.ActiveCoin.mainBasiliskAddress : this.props.Dashboard.activeHandle[coin];
Store.dispatch(iguanaActiveHandle(true)); Store.dispatch(iguanaActiveHandle(true));
@ -57,7 +56,7 @@ class CoinTileItem extends React.Component {
Store.dispatch(getShepherdCache(this.props.Dashboard.activeHandle.pubkey)); Store.dispatch(getShepherdCache(this.props.Dashboard.activeHandle.pubkey));
Store.dispatch(getBasiliskTransactionsList(coin, useAddress)); Store.dispatch(getBasiliskTransactionsList(coin, useAddress));
Store.dispatch(getKMDAddressesNative(coin, mode, useAddress)); Store.dispatch(getKMDAddressesNative(coin, mode, useAddress));
Store.dispatch(iguanaEdexBalance(coin, mode)); //Store.dispatch(iguanaEdexBalance(coin, mode));
} }
} }
} }
@ -69,6 +68,7 @@ class CoinTileItem extends React.Component {
Store.dispatch(dashboardChangeActiveCoin(coin, mode)); Store.dispatch(dashboardChangeActiveCoin(coin, mode));
this.dispatchCoinActions(coin, mode); this.dispatchCoinActions(coin, mode);
if (mode === 'full') { if (mode === 'full') {
var _iguanaActiveHandle = setInterval(function() { var _iguanaActiveHandle = setInterval(function() {
this.dispatchCoinActions(coin, mode); this.dispatchCoinActions(coin, mode);

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

@ -1,6 +1,16 @@
import React from 'react'; import React from 'react';
import Config from '../../config';
import { translate } from '../../translate/translate'; import { translate } from '../../translate/translate';
import { sendToAddress } from '../../actions/actionCreators'; import {
sendToAddress,
sendFromAddress,
sendNativeTx,
getKMDOPID,
resolveOpenAliasAddress,
triggerToaster,
iguanaUTXORawTX,
clearLastSendToResponseState
} from '../../actions/actionCreators';
import Store from '../../store'; import Store from '../../store';
// TODO: implement logic // TODO: implement logic
@ -8,27 +18,132 @@ import Store from '../../store';
class SendCoin extends React.Component { class SendCoin extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
currentStep: 0, currentStep: 0,
sendFrom: this.props.Dashboard && this.props.Dashboard.activeHandle ? this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin] : null, sendFrom: this.props.Dashboard && this.props.Dashboard.activeHandle ? this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin] : null,
sendFromAmount: 0, sendFromAmount: 0,
sendTo: null, sendTo: '',
sendToOA: null,
amount: 0, amount: 0,
fee: 0.0001, fee: 0.0001,
sendSig: false, sendSig: false,
sendApiType: false,
addressSelectorOpen: false,
}; };
this.updateInput = this.updateInput.bind(this); this.updateInput = this.updateInput.bind(this);
this.handleSubmit = this.handleSubmit.bind(this); this.handleBasiliskSend = this.handleBasiliskSend.bind(this);
this.openDropMenu = this.openDropMenu.bind(this);
this.toggleSendSig = this.toggleSendSig.bind(this); this.toggleSendSig = this.toggleSendSig.bind(this);
this.getOAdress = this.getOAdress.bind(this);
this.toggleSendAPIType = this.toggleSendAPIType.bind(this);
}
renderAddressAmount(address) {
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 === address) {
return this.props.ActiveCoin.addresses['public'][i].amount;
}
}
} else {
return 0;
}
}
renderAddressByType(type) {
if (this.props.ActiveCoin.addresses && this.props.ActiveCoin.addresses[type] && this.props.ActiveCoin.addresses[type].length) {
if (this.state.sendApiType) {
const mainAddress = this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin];
const mainAddressAmount = this.renderAddressAmount(mainAddress);
return(
<li data-original-index="2" key={mainAddress} className={mainAddressAmount <= 0 ? 'hide' : ''}>
<a tabIndex="0" data-tokens="null" onClick={() => this.updateAddressSelection(mainAddress, type, mainAddressAmount)}><i className={type === 'public' ? 'icon fa-eye' : 'icon fa-eye-slash'}></i> <span className="text">[ {mainAddressAmount} {this.props.ActiveCoin.coin} ] {mainAddress}</span><span className="glyphicon glyphicon-ok check-mark"></span></a>
</li>
);
} else {
return this.props.ActiveCoin.addresses[type].map((address) =>
<li data-original-index="2" key={address.address} className={address.amount <= 0 ? 'hide' : ''}>
<a tabIndex="0" data-tokens="null" onClick={() => this.updateAddressSelection(address.address, type, address.amount)}><i className={type === 'public' ? 'icon fa-eye' : 'icon fa-eye-slash'}></i> <span className="text">[ {address.amount} {this.props.ActiveCoin.coin} ] {address.address}</span><span className="glyphicon glyphicon-ok check-mark"></span></a>
</li>
);
}
} else {
return null;
}
}
renderSelectorCurrentLabel() {
if (this.state.sendFrom) {
return (
<span>
<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}</span>
</span>
);
} else if (this.state.sendApiType) {
const mainAddress = this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin];
const mainAddressAmount = this.renderAddressAmount(mainAddress);
return (
<span>
<i className={this.state.addressType === 'public' ? 'icon fa-eye' : 'icon fa-eye-slash'}></i> <span className="text">[ {mainAddressAmount} {this.props.ActiveCoin.coin} ] {mainAddress}</span>
</span>
);
} else {
return (
<span>- Select Transparent or Private Address -</span>
);
}
}
renderAddressList() {
return (
<div className={'btn-group bootstrap-select form-control form-material showkmdwalletaddrs show-tick ' + (this.state.addressSelectorOpen ? 'open' : '')}>
<button type="button" className="btn dropdown-toggle btn-info" data-toggle="dropdown" data-id="kmd_wallet_send_from" title="- Select Transparent or Private Address -" aria-expanded="true" onClick={this.openDropMenu}>
<span className="filter-option pull-left">{this.renderSelectorCurrentLabel()} </span>&nbsp;<span className="bs-caret"><span className="caret"></span></span>
</button>
<div className="dropdown-menu open">
<ul className="dropdown-menu inner" role="menu">
<li data-original-index="1" className="selected">
<a tabIndex="0" data-tokens="null"><span className="text"> - Select Transparent or Private Address - </span><span className="glyphicon glyphicon-ok check-mark"></span></a>
</li>
{this.renderAddressByType('public')}
</ul>
</div>
</div>
);
}
openDropMenu() {
this.setState(Object.assign({}, this.state, {
addressSelectorOpen: !this.state.addressSelectorOpen,
}));
}
updateAddressSelection(address, type, amount) {
this.setState(Object.assign({}, this.state, {
sendFrom: address,
addressType: type,
sendFromAmount: amount ? amount : this.props.ActiveCoin.addresses[type][address].amount,
addressSelectorOpen: !this.state.addressSelectorOpen,
}));
} }
changeSendCoinStep(step) { changeSendCoinStep(step) {
Store.dispatch(clearLastSendToResponseState());
this.setState(Object.assign({}, this.state, { this.setState(Object.assign({}, this.state, {
currentStep: step, currentStep: step,
})); }));
if (step === 2) { if (step === 2) {
Store.dispatch(sendToAddress(this.props.ActiveCoin.coin, this.state)); if (!this.state.sendApiType && this.props.ActiveCoin.mode === 'basilisk') {
handleBasiliskSend();
} else {
Store.dispatch(sendToAddress(this.props.ActiveCoin.coin, this.state));
}
//Store.dispatch(sendFromAddress(this.props.ActiveCoin.coin, this.state));
} }
} }
@ -38,18 +153,50 @@ class SendCoin extends React.Component {
})); }));
} }
toggleSendAPIType() {
this.setState(Object.assign({}, this.state, {
sendApiType: !this.state.sendApiType,
}));
}
updateInput(e) { updateInput(e) {
this.setState({ this.setState({
[e.target.name]: e.target.value, [e.target.name]: e.target.value,
}); });
console.log(this.state);
} }
handleSubmit() { handleBasiliskSend() {
Store.dispatch(sendNativeTx(this.props.ActiveCoin.coin, this.state)); const utxoSet = this.props.ActiveCoin.cache[this.props.ActiveCoin.coin][this.state.sendFrom].refresh;
setTimeout(function() { const sendData = {
'coin': this.props.ActiveCoin.coin,
'sendfrom': this.state.sendFrom,
'sendtoaddr': this.state.sendTo,
'amount': this.state.amount,
'txfee': this.state.fee,
'sendsig': this.state.sendSig === true ? 0 : 1,
'utxos': utxoSet
};
iguanaUTXORawTX(sendData)
.then(function(json) {
console.log('sendData', sendData);
console.log('iguanaUTXORawTXJSON', json);
if (json.result === 'success' && json.completed === true) {
Store.dispatch(triggerToaster(true, translate('TOASTR.SIGNED_TX_GENERATED') + '.', translate('TOASTR.WALLET_NOTIFICATION')));
if (sendData.sendsig === 1) {
Store.dispatch(triggerToaster(true, translate('TOASTR.SENDING_TX') + '.', translate('TOASTR.WALLET_NOTIFICATION')));
ajax_data_dexrawtx = {
'signedtx': json.signedtx,
'coin': sendData.coin
};
}
}
console.log(json);
});
//Store.dispatch(sendNativeTx(this.props.ActiveCoin.coin, this.state));
/*setTimeout(function() {
Store.dispatch(getKMDOPID(null, this.props.ActiveCoin.coin)); Store.dispatch(getKMDOPID(null, this.props.ActiveCoin.coin));
}, 1000); }, 1000);*/
} }
renderSignedTx(signedtx) { renderSignedTx(signedtx) {
@ -97,7 +244,7 @@ class SendCoin extends React.Component {
<span className="label label-danger">false</span> <span className="label label-danger">false</span>
); );
} }
} }
} }
renderSendCoinResponse() { renderSendCoinResponse() {
@ -108,6 +255,72 @@ class SendCoin extends React.Component {
<td>{this.renderKey(key)}</td> <td>{this.renderKey(key)}</td>
</tr> </tr>
); );
} else {
return (
<span>Processing transaction...</span>
);
}
}
getOAdress() {
resolveOpenAliasAddress(this.state.sendToOA)
.then(function(json) {
const reply = json.Answer;
if (reply && reply.length) {
for (let i = 0; i < reply.length; i++) {
const _address = reply[i].data.split(' ');
const coin = _address[0].replace('"oa1:', '');
const coinAddress = _address[1].replace('recipient_address=', '').replace(';', '');
if (coin.toUpperCase() === this.props.ActiveCoin.coin) {
this.setState(Object.assign({}, this.state, {
sendTo: coinAddress,
}));
}
}
if (this.state.sendTo === '') {
Store.dispatch(triggerToaster(true, 'Couldn\'t find any ' + this.props.ActiveCoin.coin + ' addresses', 'OpenAlias', 'error'));
}
} else {
Store.dispatch(triggerToaster(true, 'Couldn\'t find any addresses', 'OpenAlias', 'error'));
}
}.bind(this));
}
renderOASendUI() {
if (Config.openAlias) {
return (
<div className="row">
<div className="col-lg-6 form-group form-material">
<label className="control-label" data-extcoin="COIN" htmlFor="kmd_wallet_sendto">Fetch OpenAlias recipient address</label>
<input type="text" className="form-control" data-extcoin="COIN" name="sendToOA" onChange={this.updateInput} id="kmd_wallet_sendto" placeholder="Enter an alias as address@site.com" autoComplete="off" required />
</div>
<div className="col-lg-6 form-group form-material">
<button type="button" className="btn btn-primary waves-effect waves-light" data-toggle="modal" id="kmd_wallet_send_coins_btn" onClick={this.getOAdress}>
Get address
</button>
</div>
</div>
);
} else {
return null;
}
}
renderSendApiTypeSelector() {
if (this.props.ActiveCoin.mode === 'basilisk') {
return (
<div className="row">
<div className="col-lg-10 margin-bottom-10">
<div className="pull-left margin-right-10">
<input type="checkbox" id="edexcoin_send_api_type" data-plugin="switchery" data-size="small" />
</div>
<label className="padding-top-3" htmlFor="edexcoin_send_api_type" onClick={this.toggleSendAPIType}>Send via sendtoaddress API</label>
</div>
</div>
);
} else { } else {
return null; return null;
} }
@ -150,14 +363,18 @@ class SendCoin extends React.Component {
</div> </div>
<div className="panel-body container-fluid"> <div className="panel-body container-fluid">
<form className="edexcoin-send-form" data-edexcoin="COIN" method="post" role="form" autoComplete="off"> <form className="edexcoin-send-form" data-edexcoin="COIN" method="post" role="form" autoComplete="off">
{this.renderSendApiTypeSelector()}
<div className="row"> <div className="row">
<div className={this.props.ActiveCoin.mode === 'basilisk' ? 'col-xlg-12 form-group form-material' : 'hide'}> <div className={this.props.ActiveCoin.mode === 'basilisk' ? 'col-xlg-12 form-group form-material' : 'hide'}>
<label className="control-label" data-edexcoin="COIN" htmlFor="edexcoin_send_from">{translate('INDEX.SEND_FROM')}</label> <label className="control-label" data-edexcoin="COIN" htmlFor="edexcoin_send_from">{translate('INDEX.SEND_FROM')}</label>
<select className="form-control form-material showedexcoinaddrs show-tick" data-edexcoin="COIN" id="edexcoin_send_from" onChange={this.updateInput} title="Select Transparent or Private Address" data-size="5"></select> {this.renderAddressList()}
</div> </div>
</div>
{this.renderOASendUI()}
<div className="row">
<div className="col-xlg-12 form-group form-material"> <div className="col-xlg-12 form-group form-material">
<label className="control-label" data-edexcoin="COIN" htmlFor="edexcoin_sendto">{translate('INDEX.SEND_TO')}</label> <label className="control-label" data-edexcoin="COIN" htmlFor="edexcoin_sendto">{translate('INDEX.SEND_TO')}</label>
<input type="text" className="form-control" data-edexcoin="COIN" id="edexcoin_sendto" name="sendTo" placeholder="Enter address" autoComplete="off" onChange={this.updateInput} required /> <input type="text" className="form-control" data-edexcoin="COIN" id="edexcoin_sendto" name="sendTo" placeholder="Enter address" autoComplete="off" value={this.state.sendTo} onChange={this.updateInput} required />
</div> </div>
<div className="col-lg-6 form-group form-material"> <div className="col-lg-6 form-group form-material">
<label className="control-label" htmlFor="edexcoin_amount" data-edexcoin="COIN" id="edexcoin_amount_label"> <label className="control-label" htmlFor="edexcoin_amount" data-edexcoin="COIN" id="edexcoin_amount_label">

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

@ -2,6 +2,7 @@ import React from 'react';
import Config from '../../config'; import Config from '../../config';
import { translate } from '../../translate/translate'; import { translate } from '../../translate/translate';
import { secondsToString } from '../../util/time'; import { secondsToString } from '../../util/time';
import { sortByDate } from '../../util/sort';
import { import {
basiliskRefresh, basiliskRefresh,
basiliskConnection, basiliskConnection,
@ -15,8 +16,7 @@ import {
toggleViewCacheModal, toggleViewCacheModal,
fetchNewCacheData, fetchNewCacheData,
fetchUtxoCache, fetchUtxoCache,
getIguanaInstancesList, restartBasiliskInstance
restartIguanaInstance
} from '../../actions/actionCreators'; } from '../../actions/actionCreators';
import Store from '../../store'; import Store from '../../store';
@ -65,6 +65,7 @@ class WalletsData extends React.Component {
toggleCacheApi() { toggleCacheApi() {
const _useCache = !this.state.useCache; const _useCache = !this.state.useCache;
console.log('useCache is set to', _useCache); console.log('useCache is set to', _useCache);
sessionStorage.setItem('useCache', _useCache); sessionStorage.setItem('useCache', _useCache);
this.setState(Object.assign({}, this.state, { this.setState(Object.assign({}, this.state, {
@ -72,6 +73,10 @@ class WalletsData extends React.Component {
})); }));
} }
restartBasiliskInstance() {
Store.dispatch(restartBasiliskInstance());
}
_toggleViewCacheModal() { _toggleViewCacheModal() {
Store.dispatch(toggleViewCacheModal(!this.props.Dashboard.displayViewCacheModal)); Store.dispatch(toggleViewCacheModal(!this.props.Dashboard.displayViewCacheModal));
} }
@ -96,18 +101,6 @@ class WalletsData extends React.Component {
} }
} }
restartBasiliskInstance() {
getIguanaInstancesList().then(function(json) {
for (let port in json.result) {
if (json.result[port].mode === 'basilisk') {
restartIguanaInstance(json.result[port].pmid).then(function(json) {
console.log('restartBasiliskInstance', json);
});
}
}
});
}
removeAndFetchNewCache() { removeAndFetchNewCache() {
Store.dispatch(deleteCacheFile({ Store.dispatch(deleteCacheFile({
'pubkey': this.props.Dashboard.activeHandle.pubkey, 'pubkey': this.props.Dashboard.activeHandle.pubkey,
@ -158,7 +151,7 @@ class WalletsData extends React.Component {
} }
updateInput(e) { updateInput(e) {
let historyToSplit = this.props.ActiveCoin.txhistory; let historyToSplit = sortByDate(this.props.ActiveCoin.txhistory);
historyToSplit = historyToSplit.slice(0, e.target.value); historyToSplit = historyToSplit.slice(0, e.target.value);
this.setState({ this.setState({
@ -175,7 +168,7 @@ class WalletsData extends React.Component {
componentWillReceiveProps(props) { componentWillReceiveProps(props) {
if (this.props.ActiveCoin.txhistory && this.props.ActiveCoin.txhistory.length) { 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)) { if (!this.state.itemsList || (this.state.itemsList && !this.state.itemsList.length) || (props.ActiveCoin.txhistory !== this.props.ActiveCoin.txhistory)) {
let historyToSplit = this.props.ActiveCoin.txhistory; let historyToSplit = sortByDate(this.props.ActiveCoin.txhistory);
historyToSplit = historyToSplit.slice((this.state.activePage - 1) * this.state.itemsPerPage, this.state.activePage * this.state.itemsPerPage); historyToSplit = historyToSplit.slice((this.state.activePage - 1) * this.state.itemsPerPage, this.state.activePage * this.state.itemsPerPage);
this.setState(Object.assign({}, this.state, { this.setState(Object.assign({}, this.state, {
@ -192,7 +185,7 @@ class WalletsData extends React.Component {
} }
updateCurrentPage(page) { updateCurrentPage(page) {
let historyToSplit = this.props.ActiveCoin.txhistory; let historyToSplit = sortByDate(this.props.ActiveCoin.txhistory);
historyToSplit = historyToSplit.slice((page - 1) * this.state.itemsPerPage, page * this.state.itemsPerPage); historyToSplit = historyToSplit.slice((page - 1) * this.state.itemsPerPage, page * this.state.itemsPerPage);
this.setState(Object.assign({}, this.state, { this.setState(Object.assign({}, this.state, {
@ -250,7 +243,7 @@ class WalletsData extends React.Component {
<a aria-controls="kmd-tx-history-tbl" data-dt-idx="0" tabIndex="0" onClick={() => this.updateCurrentPage(this.state.activePage - 1)}>Previous</a> <a aria-controls="kmd-tx-history-tbl" data-dt-idx="0" tabIndex="0" onClick={() => this.updateCurrentPage(this.state.activePage - 1)}>Previous</a>
</li> </li>
{this.renderPaginationItems()} {this.renderPaginationItems()}
<li className={this.state.activePage === Math.floor(this.props.ActiveCoin.txhistory.length / this.state.itemsPerPage) ? 'paginate_button next disabled' : 'paginate_button next'} id="kmd-tx-history-tbl_next"> <li className={this.state.activePage > Math.floor(this.props.ActiveCoin.txhistory.length / this.state.itemsPerPage) ? 'paginate_button next disabled' : 'paginate_button next'} id="kmd-tx-history-tbl_next">
<a aria-controls="kmd-tx-history-tbl" data-dt-idx="2" tabIndex="0" onClick={() => this.updateCurrentPage(this.state.activePage + 1)}>Next</a> <a aria-controls="kmd-tx-history-tbl" data-dt-idx="2" tabIndex="0" onClick={() => this.updateCurrentPage(this.state.activePage + 1)}>Next</a>
</li> </li>
</ul> </ul>
@ -332,6 +325,7 @@ class WalletsData extends React.Component {
this.setState(Object.assign({}, this.state, { this.setState(Object.assign({}, this.state, {
currentAddress: address, currentAddress: address,
addressSelectorOpen: false, addressSelectorOpen: false,
activePage: 1,
})); }));
setTimeout(function() { setTimeout(function() {
@ -350,6 +344,21 @@ class WalletsData extends React.Component {
})); }));
} }
renderUseCacheToggle() {
if (this.props.ActiveCoin.mode === 'basilisk') {
return (
<div className="col-sm-2">
<div className="pull-left margin-right-10">
<input type="checkbox" id="edexcoin_cache_api" checked={this.state.useCache} data-plugin="switchery" data-size="small" />
</div>
<label className="padding-top-3" htmlFor="edexcoin_cache_api" onClick={this.toggleCacheApi}>Use cache</label>
</div>
);
} else {
return null;
}
}
renderAddressByType(type) { renderAddressByType(type) {
if (this.props.ActiveCoin.addresses && this.props.ActiveCoin.addresses[type] && this.props.ActiveCoin.addresses[type].length) { if (this.props.ActiveCoin.addresses && this.props.ActiveCoin.addresses[type] && this.props.ActiveCoin.addresses[type].length) {
return this.props.ActiveCoin.addresses[type].map((address) => return this.props.ActiveCoin.addresses[type].map((address) =>
@ -362,11 +371,23 @@ class WalletsData extends React.Component {
} }
} }
renderAddressAmount() {
if (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;
}
}
} else {
return 0;
}
}
renderSelectorCurrentLabel() { renderSelectorCurrentLabel() {
if (this.state.currentAddress) { if (this.state.currentAddress) {
return ( return (
<span> <span>
<i className={this.state.addressType === 'public' ? 'icon fa-eye' : 'icon fa-eye-slash'}></i> <span className="text">[ {this.state.sendFromAmount} {this.props.ActiveCoin.coin} ] {this.state.currentAddress}</span> <i className={this.state.addressType === 'public' ? 'icon fa-eye' : 'icon fa-eye-slash'}></i> <span className="text">[ {this.renderAddressAmount()} {this.props.ActiveCoin.coin} ] {this.state.currentAddress}</span>
</span> </span>
); );
} else { } else {
@ -440,7 +461,7 @@ class WalletsData extends React.Component {
</a> </a>
</li> </li>
<li data-edexcoin="COIN" role="presentation" className={!this.state.useCache ? 'hide' : ''}> <li data-edexcoin="COIN" role="presentation" className={!this.state.useCache ? 'hide' : ''}>
<a className="btn_edexcoin_dashboard_fetchdata" data-edexcoin="COIN" id="btn_edexcoin_dashboard_fetchdata" role="menuitem" onClick={this.basiliskRefreshAction}> <a className="btn_edexcoin_dashboard_fetchdata" data-edexcoin="COIN" id="btn_edexcoin_dashboard_fetchdata" role="menuitem" onClick={this.basiliskRefreshActionOne}>
<i className="icon fa-cloud-download" aria-hidden="true"></i> {translate('INDEX.FETCH_WALLET_DATA')} <i className="icon fa-cloud-download" aria-hidden="true"></i> {translate('INDEX.FETCH_WALLET_DATA')}
</a> </a>
</li> </li>
@ -454,6 +475,11 @@ class WalletsData extends React.Component {
<i className="icon fa-history" aria-hidden="true"></i> Update UTXO <i className="icon fa-history" aria-hidden="true"></i> Update UTXO
</a> </a>
</li> </li>
<li data-edexcoin="COIN" role="presentation" className={!this.state.useCache ? 'hide' : ''}>
<a role="menuitem" onClick={this.basiliskRefreshAction}>
<i className="icon fa-cloud-download" aria-hidden="true"></i> Fetch all
</a>
</li>
<li data-edexcoin="COIN" role="presentation" className={!this.state.useCache ? 'hide' : ''}> <li data-edexcoin="COIN" role="presentation" className={!this.state.useCache ? 'hide' : ''}>
<a role="menuitem" onClick={this.restartBasiliskInstance}> <a role="menuitem" onClick={this.restartBasiliskInstance}>
<i className="icon fa-refresh" aria-hidden="true"></i> Restart Basilisk Instance <i className="icon fa-refresh" aria-hidden="true"></i> Restart Basilisk Instance
@ -474,12 +500,7 @@ class WalletsData extends React.Component {
<div className="col-sm-6"> <div className="col-sm-6">
{this.renderAddressList()} {this.renderAddressList()}
</div> </div>
<div className="col-sm-2"> {this.renderUseCacheToggle}
<div className="pull-left margin-right-10">
<input type="checkbox" id="edexcoin_cache_api" checked={this.state.useCache} data-plugin="switchery" data-size="small" />
</div>
<label className="padding-top-3" htmlFor="edexcoin_cache_api" onClick={this.toggleCacheApi}>Use cache</label>
</div>
</div> </div>
<div className="row" style={{padding: '20px 0 10px 0'}}> <div className="row" style={{padding: '20px 0 10px 0'}}>
<div className="col-sm-6"> <div className="col-sm-6">

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

@ -1,7 +1,13 @@
import React from 'react'; import React from 'react';
import Config from '../../config';
import { translate } from '../../translate/translate'; import { translate } from '../../translate/translate';
import { secondsToString } from '../../util/time'; import { secondsToString } from '../../util/time';
import { sendNativeTx, getKMDOPID } from '../../actions/actionCreators'; import {
sendNativeTx,
getKMDOPID,
resolveOpenAliasAddress,
triggerToaster
} from '../../actions/actionCreators';
import Store from '../../store'; import Store from '../../store';
class WalletsNativeSend extends React.Component { class WalletsNativeSend extends React.Component {
@ -11,7 +17,8 @@ class WalletsNativeSend extends React.Component {
addressType: null, addressType: null,
sendFrom: null, sendFrom: null,
sendFromAmount: 0, sendFromAmount: 0,
sendTo: null, sendTo: '',
sendToOA: null,
amount: 0, amount: 0,
fee: 0.0001, fee: 0.0001,
addressSelectorOpen: false, addressSelectorOpen: false,
@ -19,6 +26,7 @@ class WalletsNativeSend extends React.Component {
this.updateInput = this.updateInput.bind(this); this.updateInput = this.updateInput.bind(this);
this.handleSubmit = this.handleSubmit.bind(this); this.handleSubmit = this.handleSubmit.bind(this);
this.openDropMenu = this.openDropMenu.bind(this); this.openDropMenu = this.openDropMenu.bind(this);
this.getOAdress = this.getOAdress.bind(this);
} }
renderAddressByType(type) { renderAddressByType(type) {
@ -182,6 +190,53 @@ class WalletsNativeSend extends React.Component {
}, 1000); }, 1000);
} }
getOAdress() {
resolveOpenAliasAddress(this.state.sendToOA)
.then(function(json) {
const reply = json.Answer;
if (reply && reply.length) {
for (let i = 0; i < reply.length; i++) {
const _address = reply[i].data.split(' ');
const coin = _address[0].replace('"oa1:', '');
const coinAddress = _address[1].replace('recipient_address=', '').replace(';', '');
if (coin.toUpperCase() === this.props.ActiveCoin.coin) {
this.setState(Object.assign({}, this.state, {
sendTo: coinAddress,
}));
}
}
if (this.state.sendTo === '') {
Store.dispatch(triggerToaster(true, 'Couldn\'t find any ' + this.props.ActiveCoin.coin +' addresses', 'OpenAlias', 'error'));
}
} else {
Store.dispatch(triggerToaster(true, 'Couldn\'t find any addresses', 'OpenAlias', 'error'));
}
}.bind(this));
}
renderOASendUI() {
if (Config.openAlias) {
return (
<div className="row">
<div className="col-lg-6 form-group form-material">
<label className="control-label" data-extcoin="COIN" htmlFor="kmd_wallet_sendto">{translate('INDEX.SEND_TO')} via Openalias address</label>
<input type="text" className="form-control" data-extcoin="COIN" name="sendToOA" onChange={this.updateInput} id="kmd_wallet_sendto" placeholder="Enter an alias as address@site.com" autoComplete="off" required />
</div>
<div className="col-lg-6 form-group form-material">
<button type="button" className="btn btn-primary waves-effect waves-light" data-toggle="modal" id="kmd_wallet_send_coins_btn" onClick={this.getOAdress}>
Get address
</button>
</div>
</div>
);
} else {
return null;
}
}
render() { render() {
if (this.props && this.props.ActiveCoin && this.props.ActiveCoin.nativeActiveSection === 'send') { if (this.props && this.props.ActiveCoin && this.props.ActiveCoin.nativeActiveSection === 'send') {
return ( return (
@ -200,13 +255,16 @@ class WalletsNativeSend extends React.Component {
<label className="control-label" data-extcoin="COIN" htmlFor="kmd_wallet_send_from">{translate('INDEX.SEND_FROM')}</label> <label className="control-label" data-extcoin="COIN" htmlFor="kmd_wallet_send_from">{translate('INDEX.SEND_FROM')}</label>
{this.renderAddressList()} {this.renderAddressList()}
</div> </div>
</div>
{this.renderOASendUI()}
<div className="row">
<div className="col-xlg-12 form-group form-material"> <div className="col-xlg-12 form-group form-material">
<label className="control-label" data-extcoin="COIN" htmlFor="kmd_wallet_sendto">{translate('INDEX.SEND_TO')}</label> <label className="control-label" data-extcoin="COIN" htmlFor="kmd_wallet_sendto">{translate('INDEX.SEND_TO')}</label>
<input type="text" className="form-control" data-extcoin="COIN" name="sendTo" onChange={this.updateInput} id="kmd_wallet_sendto" placeholder="Enter Transparent or Private address" autoComplete="off" required /> <input type="text" className="form-control" data-extcoin="COIN" name="sendTo" onChange={this.updateInput} value={this.state.sendTo} id="kmd_wallet_sendto" placeholder="Enter Transparent or Private address" autoComplete="off" required />
</div> </div>
<div className="col-lg-6 form-group form-material"> <div className="col-lg-6 form-group form-material">
<label className="control-label" htmlFor="kmd_wallet_amount" data-extcoin="COIN" id="kmd_wallet_amount_label"> <label className="control-label" htmlFor="kmd_wallet_amount" data-extcoin="COIN" id="kmd_wallet_amount_label">
<span data-extcoinname="COIN"></span> {this.props.ActiveCoin.coin}
</label> </label>
<input type="text" className="form-control" name="amount" onChange={this.updateInput} data-extcoin="COIN" id="kmd_wallet_amount" placeholder="0.000" autoComplete="off" /> <input type="text" className="form-control" name="amount" onChange={this.updateInput} data-extcoin="COIN" id="kmd_wallet_amount" placeholder="0.000" autoComplete="off" />
</div> </div>

9
react/src/components/dashboard/walletsNativeTxHistory.js

@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import { translate } from '../../translate/translate'; import { translate } from '../../translate/translate';
import { secondsToString } from '../../util/time'; import { secondsToString } from '../../util/time';
import { sortByDate } from '../../util/sort';
import { toggleDashboardTxInfoModal } from '../../actions/actionCreators'; import { toggleDashboardTxInfoModal } from '../../actions/actionCreators';
import Store from '../../store'; import Store from '../../store';
@ -25,7 +26,7 @@ class WalletsNativeTxHistory extends React.Component {
} }
updateInput(e) { updateInput(e) {
let historyToSplit = this.props.ActiveCoin.txhistory; let historyToSplit = sortByDate(this.props.ActiveCoin.txhistory);
historyToSplit = historyToSplit.slice(0, e.target.value); historyToSplit = historyToSplit.slice(0, e.target.value);
this.setState({ this.setState({
@ -81,7 +82,7 @@ class WalletsNativeTxHistory extends React.Component {
componentWillReceiveProps(props) { componentWillReceiveProps(props) {
if (!this.state.itemsList || (this.state.itemsList && !this.state.itemsList.length) || (props.ActiveCoin.txhistory !== this.props.ActiveCoin.txhistory)) { if (!this.state.itemsList || (this.state.itemsList && !this.state.itemsList.length) || (props.ActiveCoin.txhistory !== this.props.ActiveCoin.txhistory)) {
if (this.props.ActiveCoin.txhistory) { if (this.props.ActiveCoin.txhistory) {
let historyToSplit = this.props.ActiveCoin.txhistory; let historyToSplit = sortByDate(this.props.ActiveCoin.txhistory);
historyToSplit = historyToSplit.slice((this.state.activePage - 1) * this.state.itemsPerPage, this.state.activePage * this.state.itemsPerPage); historyToSplit = historyToSplit.slice((this.state.activePage - 1) * this.state.itemsPerPage, this.state.activePage * this.state.itemsPerPage);
this.setState(Object.assign({}, this.state, { this.setState(Object.assign({}, this.state, {
@ -92,7 +93,7 @@ class WalletsNativeTxHistory extends React.Component {
} }
updateCurrentPage(page) { updateCurrentPage(page) {
let historyToSplit = this.props.ActiveCoin.txhistory; let historyToSplit = sortByDate(this.props.ActiveCoin.txhistory);
historyToSplit = historyToSplit.slice((page - 1) * this.state.itemsPerPage, page * this.state.itemsPerPage); historyToSplit = historyToSplit.slice((page - 1) * this.state.itemsPerPage, page * this.state.itemsPerPage);
this.setState(Object.assign({}, this.state, { this.setState(Object.assign({}, this.state, {
@ -150,7 +151,7 @@ class WalletsNativeTxHistory extends React.Component {
<a aria-controls="kmd-tx-history-tbl" data-dt-idx="0" tabIndex="0" onClick={() => this.updateCurrentPage(this.state.activePage - 1)}>Previous</a> <a aria-controls="kmd-tx-history-tbl" data-dt-idx="0" tabIndex="0" onClick={() => this.updateCurrentPage(this.state.activePage - 1)}>Previous</a>
</li> </li>
{this.renderPaginationItems()} {this.renderPaginationItems()}
<li className={this.state.activePage === Math.floor(this.props.ActiveCoin.txhistory.length / this.state.itemsPerPage) ? 'paginate_button next disabled' : 'paginate_button next'} id="kmd-tx-history-tbl_next"> <li className={this.state.activePage > Math.floor(this.props.ActiveCoin.txhistory.length / this.state.itemsPerPage) ? 'paginate_button next disabled' : 'paginate_button next'} id="kmd-tx-history-tbl_next">
<a aria-controls="kmd-tx-history-tbl" data-dt-idx="2" tabIndex="0" onClick={() => this.updateCurrentPage(this.state.activePage + 1)}>Next</a> <a aria-controls="kmd-tx-history-tbl" data-dt-idx="2" tabIndex="0" onClick={() => this.updateCurrentPage(this.state.activePage + 1)}>Next</a>
</li> </li>
</ul> </ul>

2
react/src/config.js

@ -4,4 +4,6 @@ module.exports = {
agamaPort: 17777, agamaPort: 17777,
enableCacheApi: true, enableCacheApi: true,
useBasiliskInstance: true, useBasiliskInstance: true,
openAlias: true,
debug: true,
}; };

5
react/src/util/sort.js

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