@ -8,7 +8,6 @@
# include "version.h"
# include "version.h"
# include "websockets.h"
# include "websockets.h"
using json = nlohmann : : json ;
RPC : : RPC ( MainWindow * main ) {
RPC : : RPC ( MainWindow * main ) {
auto cl = new ConnectionLoader ( main , this ) ;
auto cl = new ConnectionLoader ( main , this ) ;
@ -102,18 +101,18 @@ void RPC::setConnection(Connection* c) {
refresh ( true ) ;
refresh ( true ) ;
}
}
json RPC : : makePayload ( std : : string method , std : : s tring params ) {
QJsonValue RPC : : makePayload ( QString method , QS tring params ) {
json payload = {
QJsonObject payload = {
{ " jsonrpc " , " 1.0 " } ,
{ " jsonrpc " , " 1.0 " } ,
{ " id " , " 42 " } ,
{ " id " , " 42 " } ,
{ " method " , method } ,
{ " method " , method } ,
{ " params " , { params } }
{ " params " , QJsonArray { params } }
} ;
} ;
return payload ;
return payload ;
}
}
json RPC : : makePayload ( std : : s tring method ) {
QJsonValue RPC : : makePayload ( QS tring method ) {
json payload = {
QJsonObject payload = {
{ " jsonrpc " , " 1.0 " } ,
{ " jsonrpc " , " 1.0 " } ,
{ " id " , " 42 " } ,
{ " id " , " 42 " } ,
{ " method " , method } ,
{ " method " , method } ,
@ -121,41 +120,41 @@ json RPC::makePayload(std::string method) {
return payload ;
return payload ;
}
}
void RPC : : getTAddresses ( const std : : function < void ( json ) > & cb ) {
void RPC : : getTAddresses ( const std : : function < void ( QJsonValue ) > & cb ) {
std : : s tring method = " getaddressesbyaccount " ;
QS tring method = " getaddressesbyaccount " ;
std : : s tring params = " " ;
QS tring params = " " ;
conn - > doRPCWithDefaultErrorHandling ( makePayload ( method , std : : string ( " " ) ) , cb ) ;
conn - > doRPCWithDefaultErrorHandling ( makePayload ( method , " " ) , cb ) ;
}
}
void RPC : : getZAddresses ( const std : : function < void ( json ) > & cb ) {
void RPC : : getZAddresses ( const std : : function < void ( QJsonValue ) > & cb ) {
std : : s tring method = " z_listaddresses " ;
QS tring method = " z_listaddresses " ;
conn - > doRPCWithDefaultErrorHandling ( makePayload ( method ) , cb ) ;
conn - > doRPCWithDefaultErrorHandling ( makePayload ( method ) , cb ) ;
}
}
void RPC : : getTransparentUnspent ( const std : : function < void ( json ) > & cb ) {
void RPC : : getTransparentUnspent ( const std : : function < void ( QJsonValue ) > & cb ) {
json payload = {
QJsonObject payload = {
{ " jsonrpc " , " 1.0 " } ,
{ " jsonrpc " , " 1.0 " } ,
{ " id " , " someid " } ,
{ " id " , " someid " } ,
{ " method " , " listunspent " } ,
{ " method " , " listunspent " } ,
{ " params " , { 0 } } // Get UTXOs with 0 confirmations as well.
{ " params " , QJsonArray { 0 } } // Get UTXOs with 0 confirmations as well.
} ;
} ;
conn - > doRPCWithDefaultErrorHandling ( payload , cb ) ;
conn - > doRPCWithDefaultErrorHandling ( payload , cb ) ;
}
}
void RPC : : getZUnspent ( const std : : function < void ( json ) > & cb ) {
void RPC : : getZUnspent ( const std : : function < void ( QJsonValue ) > & cb ) {
json payload = {
QJsonObject payload = {
{ " jsonrpc " , " 1.0 " } ,
{ " jsonrpc " , " 1.0 " } ,
{ " id " , " someid " } ,
{ " id " , " someid " } ,
{ " method " , " z_listunspent " } ,
{ " method " , " z_listunspent " } ,
{ " params " , { 0 } } // Get UTXOs with 0 confirmations as well.
{ " params " , QJsonArray { 0 } } // Get UTXOs with 0 confirmations as well.
} ;
} ;
conn - > doRPCWithDefaultErrorHandling ( payload , cb ) ;
conn - > doRPCWithDefaultErrorHandling ( payload , cb ) ;
}
}
void RPC : : newZaddr ( const std : : function < void ( json ) > & cb ) {
void RPC : : newZaddr ( const std : : function < void ( QJsonValue ) > & cb ) {
json payload = {
QJsonObject payload = {
{ " jsonrpc " , " 1.0 " } ,
{ " jsonrpc " , " 1.0 " } ,
{ " id " , " someid " } ,
{ " id " , " someid " } ,
{ " method " , " z_getnewaddress " } ,
{ " method " , " z_getnewaddress " } ,
@ -165,33 +164,33 @@ void RPC::newZaddr(const std::function<void(json)>& cb) {
conn - > doRPCWithDefaultErrorHandling ( payload , cb ) ;
conn - > doRPCWithDefaultErrorHandling ( payload , cb ) ;
}
}
void RPC : : newTaddr ( const std : : function < void ( json ) > & cb ) {
void RPC : : newTaddr ( const std : : function < void ( QJsonValue ) > & cb ) {
std : : s tring method = " getnewaddress " ;
QS tring method = " getnewaddress " ;
conn - > doRPCWithDefaultErrorHandling ( makePayload ( method ) , cb ) ;
conn - > doRPCWithDefaultErrorHandling ( makePayload ( method ) , cb ) ;
}
}
void RPC : : getZViewKey ( QString addr , const std : : function < void ( json ) > & cb ) {
void RPC : : getZViewKey ( QString addr , const std : : function < void ( QJsonValue ) > & cb ) {
std : : s tring method = " z_exportviewingkey " ;
QS tring method = " z_exportviewingkey " ;
conn - > doRPCWithDefaultErrorHandling ( makePayload ( method , addr . toStdString ( ) ) , cb ) ;
conn - > doRPCWithDefaultErrorHandling ( makePayload ( method , addr ) , cb ) ;
}
}
void RPC : : getZPrivKey ( QString addr , const std : : function < void ( json ) > & cb ) {
void RPC : : getZPrivKey ( QString addr , const std : : function < void ( QJsonValue ) > & cb ) {
std : : s tring method = " z_exportkey " ;
QS tring method = " z_exportkey " ;
conn - > doRPCWithDefaultErrorHandling ( makePayload ( method , addr . toStdString ( ) ) , cb ) ;
conn - > doRPCWithDefaultErrorHandling ( makePayload ( method , addr ) , cb ) ;
}
}
void RPC : : getTPrivKey ( QString addr , const std : : function < void ( json ) > & cb ) {
void RPC : : getTPrivKey ( QString addr , const std : : function < void ( QJsonValue ) > & cb ) {
std : : s tring method = " dumpprivkey " ;
QS tring method = " dumpprivkey " ;
conn - > doRPCWithDefaultErrorHandling ( makePayload ( method , addr . toStdString ( ) ) , cb ) ;
conn - > doRPCWithDefaultErrorHandling ( makePayload ( method , addr ) , cb ) ;
}
}
void RPC : : importZPrivKey ( QString privkey , bool rescan , const std : : function < void ( json ) > & cb ) {
void RPC : : importZPrivKey ( QString privkey , bool rescan , const std : : function < void ( QJsonValue ) > & cb ) {
json payload = {
QJsonObject payload = {
{ " jsonrpc " , " 1.0 " } ,
{ " jsonrpc " , " 1.0 " } ,
{ " id " , " someid " } ,
{ " id " , " someid " } ,
{ " method " , " z_importkey " } ,
{ " method " , " z_importkey " } ,
{ " params " , { privkey . toStdString ( ) , ( rescan ? " yes " : " no " ) } } ,
{ " params " , QJsonArray { privkey , ( rescan ? " yes " : " no " ) } } ,
} ;
} ;
conn - > doRPCWithDefaultErrorHandling ( payload , cb ) ;
conn - > doRPCWithDefaultErrorHandling ( payload , cb ) ;
@ -199,8 +198,8 @@ void RPC::importZPrivKey(QString privkey, bool rescan, const std::function<void(
// TODO: support rescan height and prefix
// TODO: support rescan height and prefix
void RPC : : importTPrivKey ( QString privkey , bool rescan , const std : : function < void ( json ) > & cb ) {
void RPC : : importTPrivKey ( QString privkey , bool rescan , const std : : function < void ( QJsonValue ) > & cb ) {
json payload ;
QJsonObject payload ;
// If privkey starts with 5, K or L, use old-style Hush params, same as BTC+ZEC
// If privkey starts with 5, K or L, use old-style Hush params, same as BTC+ZEC
if ( privkey . startsWith ( " 5 " ) | | privkey . startsWith ( " K " ) | | privkey . startsWith ( " L " ) ) {
if ( privkey . startsWith ( " 5 " ) | | privkey . startsWith ( " K " ) | | privkey . startsWith ( " L " ) ) {
@ -209,7 +208,7 @@ void RPC::importTPrivKey(QString privkey, bool rescan, const std::function<void(
{ " jsonrpc " , " 1.0 " } ,
{ " jsonrpc " , " 1.0 " } ,
{ " id " , " someid " } ,
{ " id " , " someid " } ,
{ " method " , " importprivkey " } ,
{ " method " , " importprivkey " } ,
{ " params " , { privkey . toStdString ( ) , " " , " false " , " 0 " , " 128 " } } ,
{ " params " , QJsonArray { privkey , " " , " false " , " 0 " , " 128 " } } ,
} ;
} ;
} else {
} else {
qDebug ( ) < < " Detected new-style HUSH WIF " ;
qDebug ( ) < < " Detected new-style HUSH WIF " ;
@ -217,7 +216,7 @@ void RPC::importTPrivKey(QString privkey, bool rescan, const std::function<void(
{ " jsonrpc " , " 1.0 " } ,
{ " jsonrpc " , " 1.0 " } ,
{ " id " , " someid " } ,
{ " id " , " someid " } ,
{ " method " , " importprivkey " } ,
{ " method " , " importprivkey " } ,
{ " params " , { privkey . toStdString ( ) , ( rescan ? " yes " : " no " ) } } ,
{ " params " , QJsonArray { privkey , ( rescan ? " yes " : " no " ) } } ,
} ;
} ;
}
}
@ -226,39 +225,39 @@ void RPC::importTPrivKey(QString privkey, bool rescan, const std::function<void(
conn - > doRPCWithDefaultErrorHandling ( payload , cb ) ;
conn - > doRPCWithDefaultErrorHandling ( payload , cb ) ;
}
}
void RPC : : validateAddress ( QString address , const std : : function < void ( json ) > & cb ) {
void RPC : : validateAddress ( QString address , const std : : function < void ( QJsonValue ) > & cb ) {
QString method = address . startsWith ( " z " ) ? " z_validateaddress " : " validateaddress " ;
QString method = address . startsWith ( " z " ) ? " z_validateaddress " : " validateaddress " ;
conn - > doRPCWithDefaultErrorHandling ( makePayload ( method . toStdString ( ) , address . toStdString ( ) ) , cb ) ;
conn - > doRPCWithDefaultErrorHandling ( makePayload ( method , address ) , cb ) ;
}
}
void RPC : : getBalance ( const std : : function < void ( json ) > & cb ) {
void RPC : : getBalance ( const std : : function < void ( QJsonValue ) > & cb ) {
json payload = {
QJsonObject payload = {
{ " jsonrpc " , " 1.0 " } ,
{ " jsonrpc " , " 1.0 " } ,
{ " id " , " someid " } ,
{ " id " , " someid " } ,
{ " method " , " z_gettotalbalance " } ,
{ " method " , " z_gettotalbalance " } ,
{ " params " , { 0 } } // Get Unconfirmed balance as well.
{ " params " , QJsonArray { 0 } } // Get Unconfirmed balance as well.
} ;
} ;
conn - > doRPCWithDefaultErrorHandling ( payload , cb ) ;
conn - > doRPCWithDefaultErrorHandling ( payload , cb ) ;
}
}
void RPC : : getTransactions ( const std : : function < void ( json ) > & cb ) {
void RPC : : getTransactions ( const std : : function < void ( QJsonValue ) > & cb ) {
std : : s tring method = " listtransactions " ;
QS tring method = " listtransactions " ;
conn - > doRPCWithDefaultErrorHandling ( makePayload ( method ) , cb ) ;
conn - > doRPCWithDefaultErrorHandling ( makePayload ( method ) , cb ) ;
}
}
void RPC : : sendZTransaction ( json params , const std : : function < void ( json ) > & cb ,
void RPC : : sendZTransaction ( QJsonValue params , const std : : function < void ( QJsonValue ) > & cb ,
const std : : function < void ( QString ) > & err ) {
const std : : function < void ( QString ) > & err ) {
json payload = {
QJsonObject payload = {
{ " jsonrpc " , " 1.0 " } ,
{ " jsonrpc " , " 1.0 " } ,
{ " id " , " someid " } ,
{ " id " , " someid " } ,
{ " method " , " z_sendmany " } ,
{ " method " , " z_sendmany " } ,
{ " params " , params }
{ " params " , params }
} ;
} ;
conn - > doRPC ( payload , cb , [ = ] ( auto reply , auto parsed ) {
conn - > doRPC ( payload , cb , [ = ] ( QNetworkReply * reply , const QJsonValue & parsed ) {
if ( ! parsed . is_discard ed ( ) & & ! parsed [ " error " ] [ " message " ] . is_n ull ( ) ) {
if ( ! parsed . isUndefin ed ( ) & & ! parsed [ " error " ] . toObject ( ) [ " message " ] . isN ull ( ) ) {
err ( QString : : fromStdString ( parsed [ " error " ] [ " message " ] ) ) ;
err ( parsed [ " error " ] . toObject ( ) [ " message " ] . toString ( ) ) ;
} else {
} else {
err ( reply - > errorString ( ) ) ;
err ( reply - > errorString ( ) ) ;
}
}
@ -299,32 +298,32 @@ void RPC::getAllPrivKeys(const std::function<void(QList<QPair<QString, QString>>
} ;
} ;
// A utility fn to do the batch calling
// A utility fn to do the batch calling
auto fnDoBatchGetPrivKeys = [ = ] ( json getAddressPayload , std : : s tring privKeyDumpMethodName ) {
auto fnDoBatchGetPrivKeys = [ = ] ( QJsonValue getAddressPayload , QS tring privKeyDumpMethodName ) {
conn - > doRPCWithDefaultErrorHandling ( getAddressPayload , [ = ] ( json resp ) {
conn - > doRPCWithDefaultErrorHandling ( getAddressPayload , [ = ] ( QJsonValue resp ) {
QList < QString > addrs ;
QList < QString > addrs ;
for ( auto addr : resp . get < json : : array_t > ( ) ) {
for ( auto addr : resp . toArray ( ) ) {
addrs . push_back ( QString : : fromStdString ( addr . get < json : : string_t > ( ) ) ) ;
addrs . push_back ( addr . toString ( ) ) ;
}
}
// Then, do a batch request to get all the private keys
// Then, do a batch request to get all the private keys
conn - > doBatchRPC < QString > (
conn - > doBatchRPC < QString > (
addrs ,
addrs ,
[ = ] ( auto addr ) {
[ = ] ( auto addr ) {
json payload = {
QJsonObject payload = {
{ " jsonrpc " , " 1.0 " } ,
{ " jsonrpc " , " 1.0 " } ,
{ " id " , " someid " } ,
{ " id " , " someid " } ,
{ " method " , privKeyDumpMethodName } ,
{ " method " , privKeyDumpMethodName } ,
{ " params " , { addr . toStdString ( ) } } ,
{ " params " , QJsonArray { addr } } ,
} ;
} ;
return payload ;
return payload ;
} ,
} ,
[ = ] ( QMap < QString , json > * privkeys ) {
[ = ] ( QMap < QString , QJsonValue > * privkeys ) {
QList < QPair < QString , QString > > allTKeys ;
QList < QPair < QString , QString > > allTKeys ;
for ( QString addr : privkeys - > keys ( ) ) {
for ( QString addr : privkeys - > keys ( ) ) {
allTKeys . push_back (
allTKeys . push_back (
QPair < QString , QString > (
QPair < QString , QString > (
addr ,
addr ,
QString : : fromStdString ( privkeys - > value ( addr ) . get < json : : string_t > ( ) ) ) ) ;
privkeys - > value ( addr ) . toString ( ) ) ) ;
}
}
fnCombineTwoLists ( allTKeys ) ;
fnCombineTwoLists ( allTKeys ) ;
@ -335,14 +334,14 @@ void RPC::getAllPrivKeys(const std::function<void(QList<QPair<QString, QString>>
} ;
} ;
// First get all the t and z addresses.
// First get all the t and z addresses.
json payloadT = {
QJsonObject payloadT = {
{ " jsonrpc " , " 1.0 " } ,
{ " jsonrpc " , " 1.0 " } ,
{ " id " , " someid " } ,
{ " id " , " someid " } ,
{ " method " , " getaddressesbyaccount " } ,
{ " method " , " getaddressesbyaccount " } ,
{ " params " , { " " } }
{ " params " , QJsonArray { " " } }
} ;
} ;
json payloadZ = {
QJsonObject payloadZ = {
{ " jsonrpc " , " 1.0 " } ,
{ " jsonrpc " , " 1.0 " } ,
{ " id " , " someid " } ,
{ " id " , " someid " } ,
{ " method " , " z_listaddresses " }
{ " method " , " z_listaddresses " }
@ -354,29 +353,31 @@ void RPC::getAllPrivKeys(const std::function<void(QList<QPair<QString, QString>>
// Build the RPC JSON Parameters for this tx
// Build the RPC JSON Parameters for this tx
void RPC : : fillTxJsonParams ( json & params , Tx tx ) {
void RPC : : fillTxJsonParams ( QJsonArray & params , Tx tx ) {
Q_ASSERT ( params . is_array ( ) ) ;
Q_ASSERT ( QJsonValue ( params ) . isArray ( ) ) ;
// Get all the addresses and amounts
// Get all the addresses and amounts
json allRecepients = json : : array ( ) ;
QJsonArray allRecepients ;
// For each addr/amt/memo, construct the JSON and also build the confirm dialog box
// For each addr/amt/memo, construct the JSON and also build the confirm dialog box
for ( int i = 0 ; i < tx . toAddrs . size ( ) ; i + + ) {
for ( int i = 0 ; i < tx . toAddrs . size ( ) ; i + + ) {
auto toAddr = tx . toAddrs [ i ] ;
auto toAddr = tx . toAddrs [ i ] ;
// Construct the JSON params
// Construct the JSON params
json rec = json : : object ( ) ;
QJsonObject rec ;
rec [ " address " ] = toAddr . addr . toStdString ( ) ;
rec [ " address " ] = toAddr . addr ;
// Force it through string for rounding. Without this, decimal points beyond 8 places
// Force it through string for rounding. Without this, decimal points beyond 8 places
// will appear, causing an "invalid amount" error
// will appear, causing an "invalid amount" error
rec [ " amount " ] = Settings : : getDecimalString ( toAddr . amount ) . toStdString ( ) ; //.toDouble();
rec [ " amount " ] = Settings : : getDecimalString ( toAddr . amount ) ; //.toDouble();
if ( toAddr . addr . startsWith ( " z " ) & & ! toAddr . encodedMemo . trimmed ( ) . isEmpty ( ) )
if ( toAddr . addr . startsWith ( " z " ) & & ! toAddr . encodedMemo . trimmed ( ) . isEmpty ( ) )
rec [ " memo " ] = toAddr . encodedMemo . toStdString ( ) ;
rec [ " memo " ] = toAddr . encodedMemo ;
allRecepients . push_back ( rec ) ;
allRecepients . push_back ( rec ) ;
}
}
// Add sender
// Add sender
params . push_back ( tx . fromAddr . toStdString ( ) ) ;
params . push_back ( tx . fromAddr ) ;
params . push_back ( allRecepients ) ;
params . push_back ( allRecepients ) ;
// Add fees if custom fees are allowed.
// Add fees if custom fees are allowed.
@ -384,6 +385,7 @@ void RPC::fillTxJsonParams(json& params, Tx tx) {
params . push_back ( 1 ) ; // minconf
params . push_back ( 1 ) ; // minconf
params . push_back ( tx . fee ) ;
params . push_back ( tx . fee ) ;
}
}
}
}
@ -440,36 +442,36 @@ void RPC::refreshReceivedZTrans(QList<QString> zaddrs) {
// 1. For each z-Addr, get list of received txs
// 1. For each z-Addr, get list of received txs
conn - > doBatchRPC < QString > ( zaddrs ,
conn - > doBatchRPC < QString > ( zaddrs ,
[ = ] ( QString zaddr ) {
[ = ] ( QString zaddr ) {
json payload = {
QJsonObject payload = {
{ " jsonrpc " , " 1.0 " } ,
{ " jsonrpc " , " 1.0 " } ,
{ " id " , " z_lrba " } ,
{ " id " , " z_lrba " } ,
{ " method " , " z_listreceivedbyaddress " } ,
{ " method " , " z_listreceivedbyaddress " } ,
{ " params " , { zaddr . toStdString ( ) , 0 } } // Accept 0 conf as well.
{ " params " , QJsonArray { zaddr , 0 } } // Accept 0 conf as well.
} ;
} ;
return payload ;
return payload ;
} ,
} ,
[ = ] ( QMap < QString , json > * zaddrTxids ) {
[ = ] ( QMap < QString , QJsonValue > * zaddrTxids ) {
// Process all txids, removing duplicates. This can happen if the same address
// Process all txids, removing duplicates. This can happen if the same address
// appears multiple times in a single tx's outputs.
// appears multiple times in a single tx's outputs.
QSet < QString > txids ;
QSet < QString > txids ;
QMap < QString , QString > memos ;
QMap < QString , QString > memos ;
for ( auto it = zaddrTxids - > constBegin ( ) ; it ! = zaddrTxids - > constEnd ( ) ; it + + ) {
for ( auto it = zaddrTxids - > constBegin ( ) ; it ! = zaddrTxids - > constEnd ( ) ; it + + ) {
auto zaddr = it . key ( ) ;
auto zaddr = it . key ( ) ;
for ( auto & i : it . value ( ) . get < json : : array_t > ( ) ) {
for ( const auto & i : it . value ( ) . toArray ( ) ) {
// Mark the address as used
// Mark the address as used
usedAddresses - > insert ( zaddr , true ) ;
usedAddresses - > insert ( zaddr , true ) ;
// Filter out change txs
// Filter out change txs
if ( ! i [ " change " ] . get < json : : boolean_t > ( ) ) {
if ( ! i . toObject ( ) [ " change " ] . toBool ( ) ) {
auto txid = QString : : fromStdString ( i [ " txid " ] . get < json : : string_t > ( ) ) ;
auto txid = i . toObject ( ) [ " txid " ] . toString ( ) ;
txids . insert ( txid ) ;
txids . insert ( txid ) ;
// Check for Memos
// Check for Memos
QString memoBytes = QString : : fromStdString ( i [ " memo " ] . get < json : : string_t > ( ) ) ;
QString memoBytes = i . toObject ( ) [ " memo " ] . toString ( ) ;
if ( ! memoBytes . startsWith ( " f600 " ) ) {
if ( ! memoBytes . startsWith ( " f600 " ) ) {
QString memo ( QByteArray : : fromHex (
QString memo ( QByteArray : : fromHex (
QByteArray : : fromStdString ( i [ " memo " ] . get < json : : string_t > ( ) ) ) ) ;
i . toObject ( ) [ " memo " ] . toString ( ) . toUtf8 ( ) ) ) ;
if ( ! memo . trimmed ( ) . isEmpty ( ) )
if ( ! memo . trimmed ( ) . isEmpty ( ) )
memos [ zaddr + txid ] = memo ;
memos [ zaddr + txid ] = memo ;
}
}
@ -480,40 +482,40 @@ void RPC::refreshReceivedZTrans(QList<QString> zaddrs) {
// 2. For all txids, go and get the details of that txid.
// 2. For all txids, go and get the details of that txid.
conn - > doBatchRPC < QString > ( txids . toList ( ) ,
conn - > doBatchRPC < QString > ( txids . toList ( ) ,
[ = ] ( QString txid ) {
[ = ] ( QString txid ) {
json payload = {
QJsonObject payload = {
{ " jsonrpc " , " 1.0 " } ,
{ " jsonrpc " , " 1.0 " } ,
{ " id " , " gettx " } ,
{ " id " , " gettx " } ,
{ " method " , " gettransaction " } ,
{ " method " , " gettransaction " } ,
{ " params " , { txid . toStdString ( ) } }
{ " params " , QJsonArray { txid } }
} ;
} ;
return payload ;
return payload ;
} ,
} ,
[ = ] ( QMap < QString , json > * txidDetails ) {
[ = ] ( QMap < QString , QJsonValue > * txidDetails ) {
QList < TransactionItem > txdata ;
QList < TransactionItem > txdata ;
// Combine them both together. For every zAddr's txid, get the amount, fee, confirmations and time
// Combine them both together. For every zAddr's txid, get the amount, fee, confirmations and time
for ( auto it = zaddrTxids - > constBegin ( ) ; it ! = zaddrTxids - > constEnd ( ) ; it + + ) {
for ( auto it = zaddrTxids - > constBegin ( ) ; it ! = zaddrTxids - > constEnd ( ) ; it + + ) {
for ( auto & i : it . value ( ) . get < json : : array_t > ( ) ) {
for ( const auto & i : it . value ( ) . toArray ( ) ) {
// Filter out change txs
// Filter out change txs
if ( i [ " change " ] . get < json : : boolean_t > ( ) )
if ( i . toObject ( ) [ " change " ] . toBool ( ) )
continue ;
continue ;
auto zaddr = it . key ( ) ;
auto zaddr = it . key ( ) ;
auto txid = QString : : fromStdString ( i [ " txid " ] . get < json : : string_t > ( ) ) ;
auto txid = i . toObject ( ) [ " txid " ] . toString ( ) ;
// Lookup txid in the map
// Lookup txid in the map
auto txidInfo = txidDetails - > value ( txid ) ;
auto txidInfo = txidDetails - > value ( txid ) ;
qint64 timestamp ;
qint64 timestamp ;
if ( txidInfo . find ( " time " ) ! = txidInfo . en d( ) ) {
if ( ! txidInfo . toObject ( ) [ " time " ] . isUndefine d( ) ) {
timestamp = txidInfo [ " time " ] . get < json : : number_unsigned_t > ( ) ;
timestamp = txidInfo . toObject ( ) [ " time " ] . toInt ( ) ;
} else {
} else {
timestamp = txidInfo [ " blocktime " ] . get < json : : number_unsigned_t > ( ) ;
timestamp = txidInfo . toObject ( ) [ " blocktime " ] . toInt ( ) ;
}
}
auto amount = i [ " amount " ] . get < json : : number_float_t > ( ) ;
auto amount = i . toObject ( ) [ " amount " ] . toDouble ( ) ;
auto confirmations = ( unsigned long ) txidInfo [ " confirmations " ] . get < json : : number_unsigned_t > ( ) ;
auto confirmations = ( unsigned long ) txidInfo [ " confirmations " ] . toInt ( ) ;
TransactionItem tx { QString ( " receive " ) , timestamp , zaddr , txid , amount ,
TransactionItem tx { QString ( " receive " ) , timestamp , zaddr , txid , amount ,
confirmations , " " , memos . value ( zaddr + txid , " " ) } ;
confirmations , " " , memos . value ( zaddr + txid , " " ) } ;
@ -547,12 +549,13 @@ void RPC::getInfoThenRefresh(bool force) {
return noConnection ( ) ;
return noConnection ( ) ;
static bool prevCallSucceeded = false ;
static bool prevCallSucceeded = false ;
std : : string method = " getinfo " ;
QString method = " getinfo " ;
conn - > doRPC ( makePayload ( method ) , [ = ] ( const json & reply ) {
conn - > doRPC ( makePayload ( method ) , [ = ] ( const QJsonValue & reply ) {
prevCallSucceeded = true ;
prevCallSucceeded = true ;
// Testnet?
// Testnet?
if ( ! reply [ " testnet " ] . is_n ull ( ) ) {
if ( ! reply [ " testnet " ] . isN ull ( ) ) {
Settings : : getInstance ( ) - > setTestnet ( reply [ " testnet " ] . get < json : : boolean_t > ( ) ) ;
Settings : : getInstance ( ) - > setTestnet ( reply [ " testnet " ] . toBool ( ) ) ;
} ;
} ;
// TODO: checkmark only when getinfo.synced == true!
// TODO: checkmark only when getinfo.synced == true!
@ -561,20 +564,20 @@ void RPC::getInfoThenRefresh(bool force) {
main - > statusIcon - > setPixmap ( i . pixmap ( 16 , 16 ) ) ;
main - > statusIcon - > setPixmap ( i . pixmap ( 16 , 16 ) ) ;
static int lastBlock = 0 ;
static int lastBlock = 0 ;
int curBlock = reply [ " blocks " ] . get < json : : number_integer_t > ( ) ;
int curBlock = reply [ " blocks " ] . toInt ( ) ;
int longestchain = reply [ " longestchain " ] . get < json : : number_integer_t > ( ) ;
int longestchain = reply [ " longestchain " ] . toInt ( ) ;
int version = reply [ " version " ] . get < json : : number_integer_t > ( ) ;
int version = reply [ " version " ] . toInt ( ) ;
int p2pport = reply [ " p2pport " ] . get < json : : number_integer_t > ( ) ;
int p2pport = reply [ " p2pport " ] . toInt ( ) ;
int rpcport = reply [ " rpcport " ] . get < json : : number_integer_t > ( ) ;
int rpcport = reply [ " rpcport " ] . toInt ( ) ;
int notarized = reply [ " notarized " ] . get < json : : number_integer_t > ( ) ;
int notarized = reply [ " notarized " ] . toInt ( ) ;
int protocolversion = reply [ " protocolversion " ] . get < json : : number_integer_t > ( ) ;
int protocolversion = reply [ " protocolversion " ] . toInt ( ) ;
int lag = curBlock - notarized ;
int lag = curBlock - notarized ;
int blocks_until_halving = 340000 - curBlock ;
int blocks_until_halving = 340000 - curBlock ;
char halving_days [ 8 ] ;
char halving_days [ 8 ] ;
sprintf ( halving_days , " %.2f " , ( double ) ( blocks_until_halving * 150 ) / ( 60 * 60 * 24 ) ) ;
sprintf ( halving_days , " %.2f " , ( double ) ( blocks_until_halving * 150 ) / ( 60 * 60 * 24 ) ) ;
QString ntzhash = QString : : fromStdString ( reply [ " notarizedhash " ] . get < json : : string_t > ( ) ) ;
QString ntzhash = reply [ " notarizedhash " ] . toString ( ) ;
QString ntztxid = QString : : fromStdString ( reply [ " notarizedtxid " ] . get < json : : string_t > ( ) ) ;
QString ntztxid = reply [ " notarizedtxid " ] . toString ( ) ;
QString kmdver = QString : : fromStdString ( reply [ " KMDversion " ] . get < json : : string_t > ( ) ) ;
QString kmdver = reply [ " KMDversion " ] . toString ( ) ;
Settings : : getInstance ( ) - > setZcashdVersion ( version ) ;
Settings : : getInstance ( ) - > setZcashdVersion ( version ) ;
@ -598,7 +601,7 @@ void RPC::getInfoThenRefresh(bool force) {
refreshTransactions ( ) ;
refreshTransactions ( ) ;
}
}
int connections = reply [ " connections " ] . get < json : : number_integer_t > ( ) ;
int connections = reply [ " connections " ] . toInt ( ) ;
Settings : : getInstance ( ) - > setPeers ( connections ) ;
Settings : : getInstance ( ) - > setPeers ( connections ) ;
if ( connections = = 0 ) {
if ( connections = = 0 ) {
@ -608,15 +611,15 @@ void RPC::getInfoThenRefresh(bool force) {
}
}
// Get network sol/s
// Get network sol/s
json payload = {
QJsonObject payload = {
{ " jsonrpc " , " 1.0 " } ,
{ " jsonrpc " , " 1.0 " } ,
{ " id " , " someid " } ,
{ " id " , " someid " } ,
{ " method " , " getnetworksolps " }
{ " method " , " getnetworksolps " }
} ;
} ;
std : : s tring method = " getnetworksolps " ;
QS tring method = " getnetworksolps " ;
conn - > doRPCIgnoreError ( makePayload ( method ) , [ = ] ( const json & reply ) {
conn - > doRPCIgnoreError ( makePayload ( method ) , [ = ] ( const QJsonValue & reply ) {
qint64 solrate = reply . get < json : : number_unsigned_t > ( ) ;
qint64 solrate = reply . toInt ( ) ;
ui - > numconnections - > setText ( QString : : number ( connections ) ) ;
ui - > numconnections - > setText ( QString : : number ( connections ) ) ;
ui - > solrate - > setText ( QString : : number ( solrate ) % " Sol/s " ) ;
ui - > solrate - > setText ( QString : : number ( solrate ) % " Sol/s " ) ;
@ -629,42 +632,42 @@ void RPC::getInfoThenRefresh(bool force) {
{ " method " , " getnetworkinfo " }
{ " method " , " getnetworkinfo " }
} ;
} ;
conn - > doRPCIgnoreError ( payload , [ = ] ( const json & reply ) {
conn - > doRPCIgnoreError ( payload , [ = ] ( const QJsonValue & reply ) {
QString clientname = QString : : fromStdString ( reply [ " subversion " ] . get < json : : string_t > ( ) ) ;
QString clientname = reply [ " subversion " ] . toString ( ) ;
QString localservices = QString : : fromStdString ( reply [ " localservices " ] . get < json : : string_t > ( ) ) ;
QString localservices = reply [ " localservices " ] . toString ( ) ;
ui - > clientname - > setText ( clientname ) ;
ui - > clientname - > setText ( clientname ) ;
ui - > localservices - > setText ( localservices ) ;
ui - > localservices - > setText ( localservices ) ;
} ) ;
} ) ;
conn - > doRPCIgnoreError ( makePayload ( " getwalletinfo " ) , [ = ] ( const json & reply ) {
conn - > doRPCIgnoreError ( makePayload ( " getwalletinfo " ) , [ = ] ( const QJsonValue & reply ) {
int txcount = reply [ " txcount " ] . get < json : : number_integer_t > ( ) ;
int txcount = reply [ " txcount " ] . toInt ( ) ;
ui - > txcount - > setText ( QString : : number ( txcount ) ) ;
ui - > txcount - > setText ( QString : : number ( txcount ) ) ;
} ) ;
} ) ;
//TODO: If -zindex is enabled, show stats
//TODO: If -zindex is enabled, show stats
conn - > doRPCIgnoreError ( makePayload ( " getchaintxstats " ) , [ = ] ( const json & reply ) {
conn - > doRPCIgnoreError ( makePayload ( " getchaintxstats " ) , [ = ] ( const QJsonValue & reply ) {
int txcount = reply [ " txcount " ] . get < json : : number_integer_t > ( ) ;
int txcount = reply [ " txcount " ] . toInt ( ) ;
ui - > chaintxcount - > setText ( QString : : number ( txcount ) ) ;
ui - > chaintxcount - > setText ( QString : : number ( txcount ) ) ;
} ) ;
} ) ;
// Call to see if the blockchain is syncing.
// Call to see if the blockchain is syncing.
conn - > doRPCIgnoreError ( makePayload ( " getblockchaininfo " ) , [ = ] ( const json & reply ) {
conn - > doRPCIgnoreError ( makePayload ( " getblockchaininfo " ) , [ = ] ( const QJsonValue & reply ) {
auto progress = reply [ " verificationprogress " ] . get < double > ( ) ;
auto progress = reply [ " verificationprogress " ] . toDouble ( ) ;
// TODO: use getinfo.synced
// TODO: use getinfo.synced
bool isSyncing = progress < 0.9999 ; // 99.99%
bool isSyncing = progress < 0.9999 ; // 99.99%
int blockNumber = reply [ " blocks " ] . get < json : : number_unsigned_t > ( ) ;
int blockNumber = reply [ " blocks " ] . toInt ( ) ;
int estimatedheight = 0 ;
int estimatedheight = 0 ;
if ( reply . find ( " estimatedheight " ) ! = reply . en d( ) ) {
if ( ! reply . toObject ( ) [ " estimatedheight " ] . isUndefine d( ) ) {
estimatedheight = reply [ " estimatedheight " ] . get < json : : number_unsigned_t > ( ) ;
estimatedheight = reply [ " estimatedheight " ] . toInt ( ) ;
}
}
auto s = Settings : : getInstance ( ) ;
auto s = Settings : : getInstance ( ) ;
s - > setSyncing ( isSyncing ) ;
s - > setSyncing ( isSyncing ) ;
s - > setBlockNumber ( blockNumber ) ;
s - > setBlockNumber ( blockNumber ) ;
std : : s tring ticker = s - > get_currency_name ( ) ;
QS tring ticker = s - > get_currency_name ( ) ;
// Update hushd tab
// Update hushd tab
if ( isSyncing ) {
if ( isSyncing ) {
@ -690,7 +693,7 @@ void RPC::getInfoThenRefresh(bool force) {
}
}
QString price = " " ;
QString price = " " ;
if ( ticker_price > 0 ) {
if ( ticker_price > 0 ) {
price = QString ( " , " ) % " HUSH " % " = " % QString : : number ( ( double ) ticker_price , ' f ' , 8 ) % " " % QString : : fromStdString ( ticker ) % " " % extra ;
price = QString ( " , " ) % " HUSH " % " = " % QString : : number ( ( double ) ticker_price , ' f ' , 8 ) % " " % ticker % " " % extra ;
}
}
// Update the status bar
// Update the status bar
@ -721,7 +724,7 @@ void RPC::getInfoThenRefresh(bool force) {
main - > statusIcon - > setToolTip ( tooltip ) ;
main - > statusIcon - > setToolTip ( tooltip ) ;
} ) ;
} ) ;
} , [ = ] ( QNetworkReply * reply , const json & ) {
} , [ = ] ( QNetworkReply * reply , const QJsonValue & ) {
// hushd has probably disappeared.
// hushd has probably disappeared.
this - > noConnection ( ) ;
this - > noConnection ( ) ;
@ -744,9 +747,9 @@ void RPC::refreshAddresses() {
auto newzaddresses = new QList < QString > ( ) ;
auto newzaddresses = new QList < QString > ( ) ;
getZAddresses ( [ = ] ( json reply ) {
getZAddresses ( [ = ] ( QJsonValue reply ) {
for ( auto & it : reply . get < json : : array_t > ( ) ) {
for ( const auto & it : reply . toArray ( ) ) {
auto addr = QString : : fromStdString ( it . get < json : : string_t > ( ) ) ;
auto addr = it . toString ( ) ;
newzaddresses - > push_back ( addr ) ;
newzaddresses - > push_back ( addr ) ;
}
}
@ -760,9 +763,9 @@ void RPC::refreshAddresses() {
auto newtaddresses = new QList < QString > ( ) ;
auto newtaddresses = new QList < QString > ( ) ;
getTAddresses ( [ = ] ( json reply ) {
getTAddresses ( [ = ] ( QJsonValue reply ) {
for ( auto & it : reply . get < json : : array_t > ( ) ) {
for ( const auto & it : reply . toArray ( ) ) {
auto addr = QString : : fromStdString ( it . get < json : : string_t > ( ) ) ;
auto addr = it . toString ( ) ;
if ( Settings : : isTAddress ( addr ) )
if ( Settings : : isTAddress ( addr ) )
newtaddresses - > push_back ( addr ) ;
newtaddresses - > push_back ( addr ) ;
}
}
@ -784,21 +787,21 @@ void RPC::updateUI(bool anyUnconfirmed) {
} ;
} ;
// Function to process reply of the listunspent and z_listunspent API calls, used below.
// Function to process reply of the listunspent and z_listunspent API calls, used below.
bool RPC : : processUnspent ( const json & reply , QMap < QString , double > * balancesMap , QList < UnspentOutput > * newUtxos ) {
bool RPC : : processUnspent ( const QJsonValue & reply , QMap < QString , double > * balancesMap , QList < UnspentOutput > * newUtxos ) {
bool anyUnconfirmed = false ;
bool anyUnconfirmed = false ;
for ( auto & it : reply . get < json : : array_t > ( ) ) {
for ( const auto & it : reply . toArray ( ) ) {
QString qsAddr = QString : : fromStdString ( it [ " address " ] ) ;
QString qsAddr = it . toObject ( ) [ " address " ] . toString ( ) ;
auto confirmations = it [ " confirmations " ] . get < json : : number_unsigned_t > ( ) ;
auto confirmations = it . toObject ( ) [ " confirmations " ] . toInt ( ) ;
if ( confirmations = = 0 ) {
if ( confirmations = = 0 ) {
anyUnconfirmed = true ;
anyUnconfirmed = true ;
}
}
newUtxos - > push_back (
newUtxos - > push_back (
UnspentOutput { qsAddr , QString : : fromStdString ( it [ " txid " ] ) ,
UnspentOutput { qsAddr , it . toObject ( ) [ " txid " ] . toString ( ) ,
Settings : : getDecimalString ( it [ " amount " ] . get < json : : number_float_t > ( ) ) ,
Settings : : getDecimalString ( it . toObject ( ) [ " amount " ] . toDouble ( ) ) ,
( int ) confirmations , it [ " spendable " ] . get < json : : boolean_t > ( ) } ) ;
( int ) confirmations , it . toObject ( ) [ " spendable " ] . toBool ( ) } ) ;
( * balancesMap ) [ qsAddr ] = ( * balancesMap ) [ qsAddr ] + it [ " amount " ] . get < json : : number_float_t > ( ) ;
( * balancesMap ) [ qsAddr ] = ( * balancesMap ) [ qsAddr ] + it . toObject ( ) [ " amount " ] . toDouble ( ) ;
}
}
return anyUnconfirmed ;
return anyUnconfirmed ;
} ;
} ;
@ -808,10 +811,11 @@ void RPC::refreshBalances() {
return noConnection ( ) ;
return noConnection ( ) ;
// 1. Get the Balances
// 1. Get the Balances
getBalance ( [ = ] ( json reply ) {
getBalance ( [ = ] ( QJsonValue reply ) {
auto balT = QString : : fromStdString ( reply [ " transparent " ] ) . toDouble ( ) ;
auto balZ = QString : : fromStdString ( reply [ " private " ] ) . toDouble ( ) ;
auto balT = reply [ " transparent " ] . toString ( ) . toDouble ( ) ;
auto balTotal = QString : : fromStdString ( reply [ " total " ] ) . toDouble ( ) ;
auto balZ = reply [ " private " ] . toString ( ) . toDouble ( ) ;
auto balTotal = reply [ " total " ] . toString ( ) . toDouble ( ) ;
AppDataModel : : getInstance ( ) - > setBalances ( balT , balZ ) ;
AppDataModel : : getInstance ( ) - > setBalances ( balT , balZ ) ;
@ -833,10 +837,10 @@ void RPC::refreshBalances() {
auto newBalances = new QMap < QString , double > ( ) ;
auto newBalances = new QMap < QString , double > ( ) ;
// Call the Transparent and Z unspent APIs serially and then, once they're done, update the UI
// Call the Transparent and Z unspent APIs serially and then, once they're done, update the UI
getTransparentUnspent ( [ = ] ( json reply ) {
getTransparentUnspent ( [ = ] ( QJsonValue reply ) {
auto anyTUnconfirmed = processUnspent ( reply , newBalances , newUtxos ) ;
auto anyTUnconfirmed = processUnspent ( reply , newBalances , newUtxos ) ;
getZUnspent ( [ = ] ( json reply ) {
getZUnspent ( [ = ] ( QJsonValue reply ) {
auto anyZUnconfirmed = processUnspent ( reply , newBalances , newUtxos ) ;
auto anyZUnconfirmed = processUnspent ( reply , newBalances , newUtxos ) ;
// Swap out the balances and UTXOs
// Swap out the balances and UTXOs
@ -857,24 +861,24 @@ void RPC::refreshTransactions() {
if ( conn = = nullptr )
if ( conn = = nullptr )
return noConnection ( ) ;
return noConnection ( ) ;
getTransactions ( [ = ] ( json reply ) {
getTransactions ( [ = ] ( QJsonValue reply ) {
QList < TransactionItem > txdata ;
QList < TransactionItem > txdata ;
for ( auto & it : reply . get < json : : array_t > ( ) ) {
for ( const auto & it : reply . toArray ( ) ) {
double fee = 0 ;
double fee = 0 ;
if ( ! it [ " fee " ] . is_n ull ( ) ) {
if ( ! it . toObject ( ) [ " fee " ] . isN ull ( ) ) {
fee = it [ " fee " ] . get < json : : number_float_t > ( ) ;
fee = it . toObject ( ) [ " fee " ] . toDouble ( ) ;
}
}
QString address = ( it [ " address " ] . is_n ull ( ) ? " " : QString : : fromStdString ( it [ " address " ] ) ) ;
QString address = ( it . toObject ( ) [ " address " ] . isN ull ( ) ? " " : it . toObject ( ) [ " address " ] . toString ( ) ) ;
TransactionItem tx {
TransactionItem tx {
QString : : fromStdString ( it [ " category " ] ) ,
it . toObject ( ) [ " category " ] . toString ( ) ,
( qint64 ) it [ " time " ] . get < json : : number_unsigned_t > ( ) ,
( qint64 ) it . toObject ( ) [ " time " ] . toInt ( ) ,
address ,
address ,
QString : : fromStdString ( it [ " txid " ] ) ,
it . toObject ( ) [ " txid " ] . toString ( ) ,
it [ " amount " ] . get < json : : number_float_t > ( ) + fee ,
it . toObject ( ) [ " amount " ] . toDouble ( ) + fee ,
( unsigned long ) it [ " confirmations " ] . get < json : : number_unsigned_t > ( ) ,
( unsigned long ) it . toObject ( ) [ " confirmations " ] . toInt ( ) ,
" " , " " } ;
" " , " " } ;
txdata . push_back ( tx ) ;
txdata . push_back ( tx ) ;
@ -910,16 +914,16 @@ void RPC::refreshSentZTrans() {
// Look up all the txids to get the confirmation count for them.
// Look up all the txids to get the confirmation count for them.
conn - > doBatchRPC < QString > ( txids ,
conn - > doBatchRPC < QString > ( txids ,
[ = ] ( QString txid ) {
[ = ] ( QString txid ) {
json payload = {
QJsonObject payload = {
{ " jsonrpc " , " 1.0 " } ,
{ " jsonrpc " , " 1.0 " } ,
{ " id " , " senttxid " } ,
{ " id " , " senttxid " } ,
{ " method " , " gettransaction " } ,
{ " method " , " gettransaction " } ,
{ " params " , { txid . toStdString ( ) } }
{ " params " , QJsonArray { txid } }
} ;
} ;
return payload ;
return payload ;
} ,
} ,
[ = ] ( QMap < QString , json > * txidList ) {
[ = ] ( QMap < QString , QJsonValue > * txidList ) {
auto newSentZTxs = sentZTxs ;
auto newSentZTxs = sentZTxs ;
// Update the original sent list with the confirmation count
// Update the original sent list with the confirmation count
// TODO: This whole thing is kinda inefficient. We should probably just update the file
// TODO: This whole thing is kinda inefficient. We should probably just update the file
@ -927,11 +931,11 @@ void RPC::refreshSentZTrans() {
// sent items.
// sent items.
for ( TransactionItem & sentTx : newSentZTxs ) {
for ( TransactionItem & sentTx : newSentZTxs ) {
auto j = txidList - > value ( sentTx . txid ) ;
auto j = txidList - > value ( sentTx . txid ) ;
if ( j . is_n ull ( ) )
if ( j . isN ull ( ) )
continue ;
continue ;
auto error = j [ " confirmations " ] . is_n ull ( ) ;
auto error = j [ " confirmations " ] . isN ull ( ) ;
if ( ! error )
if ( ! error )
sentTx . confirmations = j [ " confirmations " ] . get < json : : number_unsigned_t > ( ) ;
sentTx . confirmations = j [ " confirmations " ] . toInt ( ) ;
}
}
transactionsTableModel - > addZSentData ( newSentZTxs ) ;
transactionsTableModel - > addZSentData ( newSentZTxs ) ;
@ -953,12 +957,12 @@ void RPC::executeTransaction(Tx tx,
const std : : function < void ( QString opid , QString txid ) > computed ,
const std : : function < void ( QString opid , QString txid ) > computed ,
const std : : function < void ( QString opid , QString errStr ) > error ) {
const std : : function < void ( QString opid , QString errStr ) > error ) {
// First, create the json params
// First, create the json params
json params = json : : array ( ) ;
QJsonArray params ;
fillTxJsonParams ( params , tx ) ;
fillTxJsonParams ( params , tx ) ;
std : : cout < < std : : setw ( 2 ) < < params < < std : : endl ;
//std::cout << std::setw(2) << params << std::endl;
sendZTransaction ( params , [ = ] ( const json & reply ) {
sendZTransaction ( params , [ = ] ( const QJsonValue & reply ) {
QString opid = QString : : fromStdString ( reply . get < json : : string_t > ( ) ) ;
QString opid = reply . toString ( ) ;
// And then start monitoring the transaction
// And then start monitoring the transaction
addNewTxToWatch ( opid , WatchedTx { opid , tx , computed , error } ) ;
addNewTxToWatch ( opid , WatchedTx { opid , tx , computed , error } ) ;
@ -975,35 +979,35 @@ void RPC::watchTxStatus() {
return noConnection ( ) ;
return noConnection ( ) ;
// Make an RPC to load pending operation statues
// Make an RPC to load pending operation statues
conn - > doRPCIgnoreError ( makePayload ( " z_getoperationstatus " ) , [ = ] ( const json & reply ) {
conn - > doRPCIgnoreError ( makePayload ( " z_getoperationstatus " ) , [ = ] ( const QJsonValue & reply ) {
// conn->doRPCIgnoreError(payload, [=] (const json& reply) {
// conn->doRPCIgnoreError(payload, [=] (const json& reply) {
// There's an array for each item in the status
// There's an array for each item in the status
for ( auto & it : reply . get < json : : array_t > ( ) ) {
for ( const auto & it : reply . toArray ( ) ) {
// If we were watching this Tx and its status became "success", then we'll show a status bar alert
// If we were watching this Tx and its status became "success", then we'll show a status bar alert
QString id = QString : : fromStdString ( it [ " id " ] ) ;
QString id = it . toObject ( ) [ " id " ] . toString ( ) ;
if ( watchingOps . contains ( id ) ) {
if ( watchingOps . contains ( id ) ) {
// log any txs we are watching
// log any txs we are watching
// "creation_time": 1515969376,
// "creation_time": 1515969376,
// "execution_secs": 50.416337,
// "execution_secs": 50.416337,
// And if it ended up successful
// And if it ended up successful
QString status = QString : : fromStdString ( it [ " status " ] ) ;
QString status = it . toObject ( ) [ " status " ] . toString ( ) ;
main - > loadingLabel - > setVisible ( false ) ;
main - > loadingLabel - > setVisible ( false ) ;
if ( status = = " success " ) {
if ( status = = " success " ) {
auto txid = QString : : fromStdString ( it [ " result " ] [ " txid " ] ) ;
auto txid = it . toObject ( ) [ " result " ] . toObject ( ) [ " txid " ] . toString ( ) ;
SentTxStore : : addToSentTx ( watchingOps [ id ] . tx , txid ) ;
SentTxStore : : addToSentTx ( watchingOps [ id ] . tx , txid ) ;
auto wtx = watchingOps [ id ] ;
auto wtx = watchingOps [ id ] ;
watchingOps . remove ( id ) ;
watchingOps . remove ( id ) ;
wtx . completed ( id , txid ) ;
wtx . completed ( id , txid ) ;
qDebug ( ) < < " opid " < < id < < " started at " < < QString : : number ( ( unsigned int ) it [ " creation_time " ] ) < < " took " < < QString : : number ( ( double ) it [ " execution_secs " ] ) < < " seconds " ;
qDebug ( ) < < " opid " < < id < < " started at " < < QString : : number ( ( unsigned int ) it . toObject ( ) [ " creation_time " ] . toInt ( ) ) < < " took " < < QString : : number ( ( double ) it . toObject ( ) [ " execution_secs " ] . toDouble ( ) ) < < " seconds " ;
// Refresh balances to show unconfirmed balances
// Refresh balances to show unconfirmed balances
refresh ( true ) ;
refresh ( true ) ;
} else if ( status = = " failed " ) {
} else if ( status = = " failed " ) {
// If it failed, then we'll actually show a warning.
// If it failed, then we'll actually show a warning.
auto errorMsg = QString : : fromStdString ( it [ " error " ] [ " message " ] ) ;
auto errorMsg = it . toObject ( ) [ " error " ] . toObject ( ) [ " message " ] . toString ( ) ;
auto wtx = watchingOps [ id ] ;
auto wtx = watchingOps [ id ] ;
watchingOps . remove ( id ) ;
watchingOps . remove ( id ) ;
@ -1116,11 +1120,18 @@ void RPC::refreshPrice() {
reply - > deleteLater ( ) ;
reply - > deleteLater ( ) ;
try {
try {
QByteArray ba_raw_reply = reply - > readAll ( ) ;
QString raw_reply = QString : : fromUtf8 ( ba_raw_reply ) ;
QByteArray unescaped_raw_reply = raw_reply . toUtf8 ( ) ;
QJsonDocument jd_reply = QJsonDocument : : fromJson ( unescaped_raw_reply ) ;
QJsonObject parsed = jd_reply . object ( ) ;
if ( reply - > error ( ) ! = QNetworkReply : : NoError ) {
if ( reply - > error ( ) ! = QNetworkReply : : NoError ) {
qDebug ( ) < < " Parsing price feed response " ;
qDebug ( ) < < " Parsing price feed response " ;
auto parsed = json : : parse ( reply - > readAll ( ) , nullptr , false ) ;
if ( ! parsed . is_discarded ( ) & & ! parsed [ " error " ] [ " message " ] . is_null ( ) ) {
if ( ! parsed . isEmpty ( ) & & ! parsed [ " error " ] . toObject ( ) [ " message " ] . isN ull ( ) ) {
qDebug ( ) < < QString : : fromStdString ( parsed [ " error " ] [ " message " ] ) ;
qDebug ( ) < < parsed [ " error " ] . toObject ( ) [ " message " ] . toString ( ) ;
} else {
} else {
qDebug ( ) < < reply - > errorString ( ) ;
qDebug ( ) < < reply - > errorString ( ) ;
}
}
@ -1130,9 +1141,8 @@ void RPC::refreshPrice() {
}
}
qDebug ( ) < < " No network errors " ;
qDebug ( ) < < " No network errors " ;
auto all = reply - > readAll ( ) ;
auto parsed = json : : parse ( all , nullptr , false ) ;
if ( parsed . isEmpty ( ) ) {
if ( parsed . is_discarded ( ) ) {
s - > setZECPrice ( 0 ) ;
s - > setZECPrice ( 0 ) ;
s - > setBTCPrice ( 0 ) ;
s - > setBTCPrice ( 0 ) ;
return ;
return ;
@ -1140,51 +1150,53 @@ void RPC::refreshPrice() {
qDebug ( ) < < " Parsed JSON " ;
qDebug ( ) < < " Parsed JSON " ;
const json & item = parsed . get < json : : object_t > ( ) ;
const QJsonValue & item = parsed ;
const json & hush = item [ " hush " ] . get < json : : object_t > ( ) ;
const QJsonValue & hush = item [ " hush " ] . toObject ( ) ;
std : : s tring ticker = s - > get_currency_name ( ) ;
QS tring ticker = s - > get_currency_name ( ) ;
std : : for_each ( ticker . begin ( ) , ticker . end ( ) , [ ] ( char & c ) { c = : : tolower ( c ) ; } ) ;
ticker = ticker . toLower ( ) ;
fprintf ( stderr , " ticker=%s \n " , ticker . c_str ( ) ) ;
fprintf ( stderr , " ticker=%s \n " , ticker . toLocal8Bit ( ) . data ( ) ) ;
//qDebug() << "Ticker = " + ticker;
//qDebug() << "Ticker = " + ticker;
if ( hush [ ticker ] > = 0 ) {
if ( ! hush [ ticker ] . isUndefined ( ) ) {
qDebug ( ) < < " Found hush key in price json " ;
qDebug ( ) < < " Found hush key in price json " ;
//QString price = QString::fromStdString(hush["usd"].get<json::string_t> ());
//QString price = hush["usd"].toString ());
qDebug ( ) < < " HUSH = $ " < < QString : : number ( ( double ) hush [ " usd " ] ) < < " USD " ;
qDebug ( ) < < " HUSH = $ " < < QString : : number ( hush [ " usd " ] . toDouble ( ) ) < < " USD " ;
qDebug ( ) < < " HUSH = " < < QString : : number ( ( double ) hush [ " eur " ] ) < < " EUR " ;
qDebug ( ) < < " HUSH = " < < QString : : number ( hush [ " eur " ] . toDouble ( ) ) < < " EUR " ;
qDebug ( ) < < " HUSH = " < < QString : : number ( ( int ) 100000000 * ( double ) hush [ " btc " ] ) < < " sat " ;
qDebug ( ) < < " HUSH = " < < QString : : number ( ( int ) 100000000 * hush [ " btc " ] . toDouble ( ) ) < < " sat " ;
s - > setZECPrice ( hush [ ticker ] ) ;
s - > setZECPrice ( hush [ ticker ] . toDouble ( ) ) ;
s - > setBTCPrice ( ( unsigned int ) 100000000 * ( double ) hush [ " btc " ] ) ;
s - > setBTCPrice ( ( unsigned int ) 100000000 * hush [ " btc " ] . toDouble ( ) ) ;
std : : for_each ( ticker . begin ( ) , ticker . end ( ) , [ ] ( char & c ) { c = : : tolower ( c ) ; } ) ;
ticker = ticker . toLower ( ) ;
qDebug ( ) < < " ticker= " < < QString : : fromStdString ( ticker ) ;
qDebug ( ) < < " ticker= " < < ticker ;
// TODO: work harder to prevent coredumps!
// TODO: work harder to prevent coredumps!
auto price = hush [ ticker ] ;
auto price = hush [ ticker ] . toDouble ( ) ;
auto vol = hush [ ticker + " _24h_vol " ] ;
auto vol = hush [ ticker + " _24h_vol " ] . toDouble ( ) ;
auto mcap = hush [ ticker + " _market_cap " ] ;
auto mcap = hush [ ticker + " _market_cap " ] . toDouble ( ) ;
auto btcprice = hush [ " btc " ] ;
auto btcprice = hush [ " btc " ] . toDouble ( ) ;
auto btcvol = hush [ " btc_24h_vol " ] ;
auto btcvol = hush [ " btc_24h_vol " ] . toDouble ( ) ;
auto btcmcap = hush [ " btc_market_cap " ] ;
auto btcmcap = hush [ " btc_market_cap " ] . toDouble ( ) ;
s - > set_price ( ticker , price ) ;
s - > set_price ( ticker , price ) ;
s - > set_volume ( ticker , vol ) ;
s - > set_volume ( ticker , vol ) ;
s - > set_volume ( " BTC " , btcvol ) ;
s - > set_volume ( " BTC " , btcvol ) ;
s - > set_marketcap ( ticker , mcap ) ;
s - > set_marketcap ( ticker , mcap ) ;
qDebug ( ) < < " Volume = " < < ( double ) vol ;
qDebug ( ) < < " Volume = " < < ( double ) vol ;
std : : for_each ( ticker . begin ( ) , ticker . end ( ) , [ ] ( char & c ) { c = : : toupper ( c ) ; } ) ;
ui - > volume - > setText ( QString : : number ( ( double ) vol , ' f ' , 2 ) + " " + QString : : fromStdString ( ticker ) ) ;
ticker = ticker . toUpper ( ) ;
ui - > volume - > setText ( QString : : number ( ( double ) vol , ' f ' , 2 ) + " " + ticker ) ;
ui - > volumeBTC - > setText ( QString : : number ( ( double ) btcvol , ' f ' , 2 ) + " BTC " ) ;
ui - > volumeBTC - > setText ( QString : : number ( ( double ) btcvol , ' f ' , 2 ) + " BTC " ) ;
std : : for_each ( ticker . begin ( ) , ticker . end ( ) , [ ] ( char & c ) { c = : : toupper ( c ) ; } ) ;
ticker = ticker . toUpper ( ) ;
// We don't get an actual HUSH volume stat, so we calculate it
// We don't get an actual HUSH volume stat, so we calculate it
if ( price > 0 )
if ( price > 0 )
ui - > volumeLocal - > setText ( QString : : number ( ( double ) vol / ( double ) price ) + " HUSH " ) ;
ui - > volumeLocal - > setText ( QString : : number ( ( double ) vol / ( double ) price ) + " HUSH " ) ;
qDebug ( ) < < " Mcap = " < < ( double ) mcap ;
qDebug ( ) < < " Mcap = " < < ( double ) mcap ;
ui - > marketcap - > setText ( QString : : number ( ( double ) mcap , ' f ' , 2 ) + " " + QString : : fromStdString ( ticker ) ) ;
ui - > marketcap - > setText ( QString : : number ( ( double ) mcap , ' f ' , 2 ) + " " + ticker ) ;
ui - > marketcapBTC - > setText ( QString : : number ( ( double ) btcmcap , ' f ' , 2 ) + " BTC " ) ;
ui - > marketcapBTC - > setText ( QString : : number ( ( double ) btcmcap , ' f ' , 2 ) + " BTC " ) ;
//ui->marketcapLocal->setText( QString::number((double) mcap * (double) price) + " " + QString::fromStdString( ticker) );
//ui->marketcapLocal->setText( QString::number((double) mcap * (double) price) + " " + ticker );
refresh ( true ) ;
refresh ( true ) ;
return ;
return ;
@ -1209,7 +1221,7 @@ void RPC::shutdownZcashd() {
return ;
return ;
}
}
std : : s tring method = " stop " ;
QS tring method = " stop " ;
conn - > doRPCWithDefaultErrorHandling ( makePayload ( method ) , [ = ] ( auto ) { } ) ;
conn - > doRPCWithDefaultErrorHandling ( makePayload ( method ) , [ = ] ( auto ) { } ) ;
conn - > shutdown ( ) ;
conn - > shutdown ( ) ;