Browse Source

Merge pull request #1 from MyHush/master

Update from upstream
pull/187/head
jahway603 4 years ago
committed by GitHub
parent
commit
2d037bef81
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      README.md
  2. 1
      application.qrc
  3. BIN
      res/silentdragon-animated-startup-dark.gif
  4. BIN
      res/silentdragon-animated-startup.gif
  5. 347
      res/silentdragon_bg.ts
  6. 355
      res/silentdragon_de.ts
  7. 355
      res/silentdragon_es.ts
  8. 355
      res/silentdragon_fi.ts
  9. 347
      res/silentdragon_fil.ts
  10. 355
      res/silentdragon_fr.ts
  11. 347
      res/silentdragon_hr.ts
  12. 347
      res/silentdragon_id.ts
  13. 355
      res/silentdragon_it.ts
  14. 355
      res/silentdragon_nl.ts
  15. 355
      res/silentdragon_pt.ts
  16. 2262
      res/silentdragon_ro.ts
  17. 347
      res/silentdragon_ru.ts
  18. 347
      res/silentdragon_sr.ts
  19. 355
      res/silentdragon_tr.ts
  20. 347
      res/silentdragon_uk.ts
  21. 359
      res/silentdragon_zh.ts
  22. 3
      silentdragon.pro
  23. 18928
      src/3rdparty/json/json.hpp
  24. 51
      src/connection.cpp
  25. 36
      src/connection.h
  26. 51
      src/mainwindow.cpp
  27. 4
      src/mainwindow.h
  28. 1
      src/precompiled.h
  29. 420
      src/rpc.cpp
  30. 40
      src/rpc.h
  31. 3
      src/sendtab.cpp
  32. 41
      src/settings.cpp
  33. 22
      src/settings.h
  34. 2
      src/version.h
  35. 4
      src/websockets.cpp

3
README.md

@ -1,6 +1,6 @@
# SilentDragon
SilentDragon desktop wallet for HUSH ($HUSH) runs on Linux, Windows and macOS.
SilentDragon desktop wallet for HUSH runs on Linux, Windows and macOS.
This is experimental software under active development!
![Screenshots](silentdragon.png?raw=true)
@ -49,6 +49,7 @@ hushd, or compile hushd as well.
sudo apt-get -y install qt5-default qt5-qmake libqt5websockets5-dev qtcreator
git clone https://github.com/MyHush/SilentDragon.git
cd SilentDragon
./build.sh linguist # compile translations
./build.sh
./silentdragon
```

1
application.qrc

@ -28,6 +28,7 @@
<file>res/silentdragon_id.qm</file>
<file>res/silentdragon_nl.qm</file>
<file>res/silentdragon_pt.qm</file>
<file>res/silentdragon_ro.qm</file>
<file>res/silentdragon_ru.qm</file>
<file>res/silentdragon_sr.qm</file>
<file>res/silentdragon_tr.qm</file>

BIN
res/silentdragon-animated-startup-dark.gif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 MiB

After

Width:  |  Height:  |  Size: 1.0 MiB

BIN
res/silentdragon-animated-startup.gif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

347
res/silentdragon_bg.ts

@ -112,22 +112,22 @@
<location filename="../src/mainwindow.ui" line="404"/>
<location filename="../src/mainwindow.ui" line="411"/>
<location filename="../src/mainwindow.ui" line="872"/>
<location filename="../src/sendtab.cpp" line="219"/>
<location filename="../src/sendtab.cpp" line="224"/>
<location filename="../src/sendtab.cpp" line="218"/>
<location filename="../src/sendtab.cpp" line="223"/>
<source>Address</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.ui" line="418"/>
<location filename="../src/sendtab.cpp" line="234"/>
<location filename="../src/sendtab.cpp" line="233"/>
<source>Address Book</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.ui" line="429"/>
<location filename="../src/mainwindow.ui" line="445"/>
<location filename="../src/sendtab.cpp" line="247"/>
<location filename="../src/sendtab.cpp" line="251"/>
<location filename="../src/sendtab.cpp" line="246"/>
<location filename="../src/sendtab.cpp" line="250"/>
<source>Amount</source>
<translation type="unfinished"></translation>
</message>
@ -143,9 +143,9 @@
</message>
<message>
<location filename="../src/mainwindow.ui" line="498"/>
<location filename="../src/mainwindow.cpp" line="1184"/>
<location filename="../src/mainwindow.cpp" line="1251"/>
<location filename="../src/sendtab.cpp" line="273"/>
<location filename="../src/mainwindow.cpp" line="1189"/>
<location filename="../src/mainwindow.cpp" line="1256"/>
<location filename="../src/sendtab.cpp" line="272"/>
<source>Memo</source>
<translation type="unfinished"></translation>
</message>
@ -171,7 +171,7 @@
</message>
<message>
<location filename="../src/mainwindow.ui" line="634"/>
<location filename="../src/sendtab.cpp" line="640"/>
<location filename="../src/sendtab.cpp" line="639"/>
<source>Miner Fee</source>
<translation type="unfinished"></translation>
</message>
@ -237,7 +237,7 @@
</message>
<message>
<location filename="../src/mainwindow.ui" line="850"/>
<location filename="../src/mainwindow.cpp" line="1388"/>
<location filename="../src/mainwindow.cpp" line="1393"/>
<source>Export Private Key</source>
<translation type="unfinished"></translation>
</message>
@ -284,8 +284,8 @@
<location filename="../src/mainwindow.ui" line="1399"/>
<location filename="../src/mainwindow.ui" line="1413"/>
<location filename="../src/mainwindow.ui" line="1434"/>
<location filename="../src/mainwindow.cpp" line="883"/>
<location filename="../src/mainwindow.cpp" line="947"/>
<location filename="../src/mainwindow.cpp" line="888"/>
<location filename="../src/mainwindow.cpp" line="952"/>
<source>Loading...</source>
<translation type="unfinished"></translation>
</message>
@ -522,7 +522,7 @@
</message>
<message>
<location filename="../src/mainwindow.ui" line="1630"/>
<location filename="../src/mainwindow.cpp" line="823"/>
<location filename="../src/mainwindow.cpp" line="828"/>
<source>Export transactions</source>
<translation type="unfinished"></translation>
</message>
@ -552,398 +552,398 @@
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="310"/>
<location filename="../src/mainwindow.cpp" line="308"/>
<source>Theme Change</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="310"/>
<location filename="../src/mainwindow.cpp" line="321"/>
<location filename="../src/mainwindow.cpp" line="308"/>
<location filename="../src/mainwindow.cpp" line="318"/>
<source>This change can take a few seconds.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="321"/>
<location filename="../src/mainwindow.cpp" line="318"/>
<source>Currency Change</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="348"/>
<location filename="../src/mainwindow.cpp" line="345"/>
<source>Tor configuration is available only when running an embedded hushd.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="435"/>
<location filename="../src/mainwindow.cpp" line="432"/>
<source>You&apos;re using an external hushd. Please restart hushd with -rescan</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="438"/>
<location filename="../src/mainwindow.cpp" line="435"/>
<source>You&apos;re using an external hushd. Please restart hushd with -reindex</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="464"/>
<location filename="../src/mainwindow.cpp" line="461"/>
<source>Enable Tor</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="465"/>
<location filename="../src/mainwindow.cpp" line="462"/>
<source>Connection over Tor has been enabled. To use this feature, you need to restart SilentDragon.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="474"/>
<location filename="../src/mainwindow.cpp" line="471"/>
<source>Disable Tor</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="475"/>
<location filename="../src/mainwindow.cpp" line="472"/>
<source>Connection over Tor has been disabled. To fully disconnect from Tor, you need to restart SilentDragon.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="556"/>
<location filename="../src/mainwindow.cpp" line="553"/>
<source>SilentDragon needs to restart to rescan,reindex,consolidation or deletetx. SilentDragon will now close, please restart SilentDragon to continue</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="558"/>
<location filename="../src/mainwindow.cpp" line="564"/>
<location filename="../src/mainwindow.cpp" line="555"/>
<location filename="../src/mainwindow.cpp" line="561"/>
<source>Restart SilentDragon</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="562"/>
<location filename="../src/mainwindow.cpp" line="559"/>
<source>SilentDragon needs to reindex for zindex. SilentDragon will now close, please restart SilentDragon to continue</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="606"/>
<location filename="../src/mainwindow.cpp" line="603"/>
<source>Some feedback about SilentDragon or Hush...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="608"/>
<location filename="../src/mainwindow.cpp" line="605"/>
<source>Send Duke some private and shielded feedback about </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="608"/>
<location filename="../src/mainwindow.cpp" line="605"/>
<source> or SilentDragon</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="624"/>
<location filename="../src/mainwindow.cpp" line="621"/>
<source>Enter Address to validate</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="625"/>
<location filename="../src/mainwindow.cpp" line="622"/>
<source>Transparent or Shielded Address:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="665"/>
<location filename="../src/mainwindow.cpp" line="670"/>
<source>Private key import rescan finished</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="730"/>
<location filename="../src/mainwindow.cpp" line="735"/>
<source>Paste HUSH URI</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="742"/>
<location filename="../src/mainwindow.cpp" line="747"/>
<source>Error paying Hush URI</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="743"/>
<location filename="../src/mainwindow.cpp" line="748"/>
<source>URI should be of the form &apos;hush:&lt;addr&gt;?amt=x&amp;memo=y</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="778"/>
<location filename="../src/mainwindow.cpp" line="783"/>
<source>Please paste your private keys here, one per line</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="779"/>
<location filename="../src/mainwindow.cpp" line="784"/>
<source>The keys will be imported into your connected Hush node</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="810"/>
<location filename="../src/mainwindow.cpp" line="815"/>
<source>The keys were imported! It may take several minutes to rescan the blockchain. Until then, functionality may be limited</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="829"/>
<location filename="../src/mainwindow.cpp" line="834"/>
<source>Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="830"/>
<location filename="../src/mainwindow.cpp" line="835"/>
<source>Error exporting transactions, file was not saved</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="852"/>
<location filename="../src/mainwindow.cpp" line="857"/>
<source>No wallet.dat</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="852"/>
<location filename="../src/mainwindow.cpp" line="857"/>
<source>Couldn&apos;t find the wallet.dat on this computer</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="853"/>
<location filename="../src/mainwindow.cpp" line="858"/>
<source>You need to back it up from the machine hushd is running on</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="857"/>
<location filename="../src/mainwindow.cpp" line="862"/>
<source>Backup wallet.dat</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="862"/>
<location filename="../src/mainwindow.cpp" line="867"/>
<source>Couldn&apos;t backup</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="862"/>
<location filename="../src/mainwindow.cpp" line="867"/>
<source>Couldn&apos;t backup the wallet.dat file.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="863"/>
<location filename="../src/mainwindow.cpp" line="868"/>
<source>You need to back it up manually.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="894"/>
<location filename="../src/mainwindow.cpp" line="962"/>
<location filename="../src/mainwindow.cpp" line="899"/>
<location filename="../src/mainwindow.cpp" line="967"/>
<source>Save File</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="898"/>
<location filename="../src/mainwindow.cpp" line="966"/>
<location filename="../src/mainwindow.cpp" line="903"/>
<location filename="../src/mainwindow.cpp" line="971"/>
<source>Unable to open file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="952"/>
<location filename="../src/mainwindow.cpp" line="957"/>
<source>These are all the private keys for all the addresses in your wallet</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="954"/>
<location filename="../src/mainwindow.cpp" line="959"/>
<source>Private key for </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="1060"/>
<location filename="../src/mainwindow.cpp" line="1213"/>
<location filename="../src/mainwindow.cpp" line="1065"/>
<location filename="../src/mainwindow.cpp" line="1218"/>
<source>Copy address</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="1063"/>
<location filename="../src/mainwindow.cpp" line="1209"/>
<location filename="../src/mainwindow.cpp" line="1215"/>
<location filename="../src/mainwindow.cpp" line="1068"/>
<location filename="../src/mainwindow.cpp" line="1214"/>
<location filename="../src/mainwindow.cpp" line="1220"/>
<source>Copied to clipboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="1066"/>
<location filename="../src/mainwindow.cpp" line="1071"/>
<source>Get private key</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="1071"/>
<location filename="../src/mainwindow.cpp" line="1076"/>
<source>Get viewing key</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="1087"/>
<location filename="../src/mainwindow.cpp" line="1092"/>
<source>Shield balance to Sapling</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="1092"/>
<location filename="../src/mainwindow.cpp" line="1219"/>
<location filename="../src/mainwindow.cpp" line="1097"/>
<location filename="../src/mainwindow.cpp" line="1224"/>
<source>View on block explorer</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="1114"/>
<location filename="../src/mainwindow.cpp" line="1119"/>
<source>Address Asset Viewer</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="1120"/>
<location filename="../src/mainwindow.cpp" line="1125"/>
<source>Convert Address</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="1207"/>
<location filename="../src/mainwindow.cpp" line="1212"/>
<source>Copy txid</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="1230"/>
<location filename="../src/mainwindow.cpp" line="1235"/>
<source>Copy block explorer link</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="1243"/>
<location filename="../src/mainwindow.cpp" line="1248"/>
<source>View Payment Request</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="1250"/>
<location filename="../src/mainwindow.cpp" line="1255"/>
<source>View Memo</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="1264"/>
<location filename="../src/mainwindow.cpp" line="1269"/>
<source>Reply to </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="1345"/>
<location filename="../src/mainwindow.cpp" line="1350"/>
<source>Created new t-Addr</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="1394"/>
<location filename="../src/mainwindow.cpp" line="1399"/>
<source>Copy Address</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="1460"/>
<location filename="../src/mainwindow.cpp" line="1465"/>
<source>Address has been previously used</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/mainwindow.cpp" line="1462"/>
<location filename="../src/mainwindow.cpp" line="1467"/>
<source>Address is unused</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="210"/>
<location filename="../src/sendtab.cpp" line="209"/>
<source>Recipient </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="283"/>
<location filename="../src/sendtab.cpp" line="335"/>
<location filename="../src/sendtab.cpp" line="282"/>
<location filename="../src/sendtab.cpp" line="334"/>
<source>File Upload</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="326"/>
<location filename="../src/sendtab.cpp" line="325"/>
<source>Only z-addresses can have memos</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="346"/>
<location filename="../src/sendtab.cpp" line="345"/>
<source>File size too large</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="347"/>
<location filename="../src/sendtab.cpp" line="346"/>
<source>The file size </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="347"/>
<location filename="../src/sendtab.cpp" line="346"/>
<source> bytes is greater than </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="347"/>
<location filename="../src/sendtab.cpp" line="346"/>
<source>bytes</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="362"/>
<location filename="../src/sendtab.cpp" line="361"/>
<source>Memos can only be used with z-addresses</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="363"/>
<location filename="../src/sendtab.cpp" line="362"/>
<source>The memo field can only be used with a z-address.
</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="363"/>
<location filename="../src/sendtab.cpp" line="362"/>
<source>
doesn&apos;t look like a z-address</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="534"/>
<location filename="../src/sendtab.cpp" line="533"/>
<source>Change from </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="675"/>
<location filename="../src/sendtab.cpp" line="674"/>
<source>Current balance : </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="677"/>
<location filename="../src/sendtab.cpp" line="676"/>
<source>Balance after this Tx: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="698"/>
<location filename="../src/sendtab.cpp" line="697"/>
<source>Transaction Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="730"/>
<location filename="../src/sendtab.cpp" line="729"/>
<source>Please wait...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="731"/>
<location filename="../src/sendtab.cpp" line="730"/>
<source>Computing your transaction</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="738"/>
<location filename="../src/sendtab.cpp" line="737"/>
<source>Computing transaction: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="745"/>
<location filename="../src/sendtab.cpp" line="744"/>
<source>Done!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="776"/>
<location filename="../src/sendtab.cpp" line="775"/>
<source>From Address is Invalid!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="782"/>
<location filename="../src/sendtab.cpp" line="781"/>
<source>Recipient Address </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="782"/>
<location filename="../src/sendtab.cpp" line="781"/>
<source> is Invalid</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="788"/>
<location filename="../src/sendtab.cpp" line="787"/>
<source>Amount &apos;%1&apos; is invalid!</source>
<translation type="unfinished"></translation>
</message>
@ -1176,197 +1176,197 @@ Not starting embedded hushd because --no-embedded was passed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/connection.cpp" line="257"/>
<location filename="../src/connection.cpp" line="260"/>
<source>All Downloads Finished Successfully!</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/connection.cpp" line="280"/>
<location filename="../src/connection.cpp" line="283"/>
<source>Couldn&apos;t download params. Please check the help site for more info.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/connection.cpp" line="306"/>
<location filename="../src/connection.cpp" line="322"/>
<location filename="../src/connection.cpp" line="309"/>
<location filename="../src/connection.cpp" line="325"/>
<source>Downloading </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/connection.cpp" line="306"/>
<location filename="../src/connection.cpp" line="309"/>
<source> more remaining )</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/connection.cpp" line="307"/>
<location filename="../src/connection.cpp" line="310"/>
<source>MB of </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/connection.cpp" line="307"/>
<location filename="../src/connection.cpp" line="310"/>
<source>MB at </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/connection.cpp" line="322"/>
<location filename="../src/connection.cpp" line="325"/>
<source> failed. Please check the help site for more info</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/connection.cpp" line="346"/>
<location filename="../src/connection.cpp" line="349"/>
<source>hushd error</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/connection.cpp" line="426"/>
<location filename="../src/connection.cpp" line="429"/>
<source>A manual connection was requested, but the settings are not configured.
Please set the host/port and user/password in the Edit-&gt;Settings menu.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/connection.cpp" line="438"/>
<location filename="../src/connection.cpp" line="441"/>
<source>Could not connect to hushd configured in settings.
Please set the host/port and user/password in the Edit-&gt;Settings menu.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/connection.cpp" line="501"/>
<location filename="../src/connection.cpp" line="504"/>
<source>Authentication failed. The username / password you specified was not accepted by hushd. Try changing it in the Edit-&gt;Settings menu</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/connection.cpp" line="516"/>
<location filename="../src/connection.cpp" line="519"/>
<source>Your hushd is starting up. Please wait.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/connection.cpp" line="533"/>
<location filename="../src/connection.cpp" line="536"/>
<source>This may take several hours, grab some popcorn</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/connection.cpp" line="550"/>
<location filename="../src/rpc.cpp" line="732"/>
<location filename="../src/connection.cpp" line="553"/>
<location filename="../src/rpc.cpp" line="735"/>
<source>Connection Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/connection.cpp" line="820"/>
<location filename="../src/sendtab.cpp" line="766"/>
<location filename="../src/connection.cpp" line="831"/>
<location filename="../src/sendtab.cpp" line="765"/>
<source>Transaction Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/connection.cpp" line="820"/>
<location filename="../src/connection.cpp" line="831"/>
<source>There was an error! : </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/rpc.cpp" line="394"/>
<location filename="../src/rpc.cpp" line="396"/>
<location filename="../src/rpc.cpp" line="398"/>
<source>No Connection</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/rpc.cpp" line="680"/>
<location filename="../src/rpc.cpp" line="683"/>
<source>Downloading blocks</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/rpc.cpp" line="683"/>
<location filename="../src/rpc.cpp" line="686"/>
<source>Block height</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/rpc.cpp" line="698"/>
<location filename="../src/rpc.cpp" line="701"/>
<source>Syncing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/rpc.cpp" line="698"/>
<location filename="../src/rpc.cpp" line="701"/>
<source>Connected</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/rpc.cpp" line="700"/>
<location filename="../src/rpc.cpp" line="703"/>
<source>testnet:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/rpc.cpp" line="710"/>
<location filename="../src/rpc.cpp" line="713"/>
<source>Connected to hushd</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/rpc.cpp" line="713"/>
<location filename="../src/rpc.cpp" line="716"/>
<source>hushd has no peer connections! Network issues?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/rpc.cpp" line="732"/>
<location filename="../src/rpc.cpp" line="735"/>
<source>There was an error connecting to hushd. The error was</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/rpc.cpp" line="1026"/>
<location filename="../src/rpc.cpp" line="1030"/>
<source> transaction computing.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/rpc.cpp" line="1075"/>
<location filename="../src/rpc.cpp" line="1079"/>
<source>Update Available</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/rpc.cpp" line="1076"/>
<location filename="../src/rpc.cpp" line="1080"/>
<source>A new release v%1 is available! You have v%2.
Would you like to visit the releases page?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/rpc.cpp" line="1088"/>
<location filename="../src/rpc.cpp" line="1092"/>
<source>No updates available</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/rpc.cpp" line="1089"/>
<location filename="../src/rpc.cpp" line="1093"/>
<source>You already have the latest release v%1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/rpc.cpp" line="1235"/>
<location filename="../src/rpc.cpp" line="1247"/>
<source>Please enhance your calm and wait for SilentDragon to exit</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/rpc.cpp" line="1236"/>
<location filename="../src/rpc.cpp" line="1248"/>
<source>Waiting for hushd to exit, y&apos;all</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="761"/>
<location filename="../src/sendtab.cpp" line="760"/>
<source> Transaction </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="761"/>
<location filename="../src/sendtab.cpp" line="760"/>
<source> failed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="764"/>
<location filename="../src/sendtab.cpp" line="763"/>
<source>The transaction with id </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/sendtab.cpp" line="764"/>
<location filename="../src/sendtab.cpp" line="763"/>
<source> failed. The error was</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.cpp" line="312"/>
<location filename="../src/settings.cpp" line="313"/>
<source>Transaction submitted (right click to copy) txid:</source>
<translation type="unfinished"></translation>
</message>
@ -1810,162 +1810,167 @@ Would you like to visit the releases page?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="464"/>
<location filename="../src/settings.ui" line="435"/>
<source>midnight</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="469"/>
<source>Connect via Tor</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="471"/>
<location filename="../src/settings.ui" line="476"/>
<source>Check github for updates at startup</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="485"/>
<location filename="../src/settings.ui" line="490"/>
<source>Remember shielded transactions</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="492"/>
<location filename="../src/settings.ui" line="497"/>
<source>Normally, change from t-Addresses goes to another t-Address. Checking this option will send the change to your shielded sapling address instead. Check this option to increase your privacy.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="502"/>
<location filename="../src/settings.ui" line="507"/>
<source>Allow overriding the default fees when sending transactions. Enabling this option may compromise your privacy since fees are transparent. </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="512"/>
<location filename="../src/settings.ui" line="517"/>
<source>Clear History</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="519"/>
<location filename="../src/settings.ui" line="524"/>
<source>Shielded transactions are saved locally and shown in the transactions tab. If you uncheck this, shielded transactions will not appear in the transactions tab.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="529"/>
<location filename="../src/settings.ui" line="534"/>
<source>Allow custom fees</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="536"/>
<location filename="../src/settings.ui" line="541"/>
<source>Shield change from t-Addresses to your sapling address</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="543"/>
<location filename="../src/settings.ui" line="548"/>
<source>Connect to the Tor network via SOCKS proxy running on 127.0.0.1:9050. Please note that you&apos;ll have to install and run the Tor service externally.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="553"/>
<location filename="../src/settings.ui" line="558"/>
<source>Connect to github on startup to check for updates</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="560"/>
<location filename="../src/settings.ui" line="565"/>
<source>Connect to the internet to fetch HUSH prices</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="567"/>
<location filename="../src/settings.ui" line="572"/>
<source>Fetch HUSH prices</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="575"/>
<location filename="../src/settings.ui" line="580"/>
<source>Explorer</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="587"/>
<location filename="../src/settings.ui" line="592"/>
<source>Tx Explorer URL</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="626"/>
<location filename="../src/settings.ui" line="631"/>
<source>Address Explorer URL</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="652"/>
<location filename="../src/settings.ui" line="657"/>
<source>Testnet Tx Explorer URL</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="678"/>
<location filename="../src/settings.ui" line="683"/>
<source>Testnet Address Explorer URL</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="697"/>
<location filename="../src/settings.ui" line="702"/>
<source>Troubleshooting</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="709"/>
<location filename="../src/settings.ui" line="714"/>
<source>Reindex</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="722"/>
<location filename="../src/settings.ui" line="727"/>
<source>Rescan the blockchain for any missing wallet transactions and to correct your wallet balance. This may take several hours. You need to restart SilentDragon for this to take effect</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="738"/>
<location filename="../src/settings.ui" line="743"/>
<source>Rescan</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="777"/>
<location filename="../src/settings.ui" line="782"/>
<source>Rebuild the entire blockchain from the genesis block, by rescanning all the block files. This may take several hours to days, depending on your hardware. You need to restart SilentDragon for this to take effect</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="819"/>
<location filename="../src/settings.ui" line="824"/>
<source>This code can greatly reduce the size of wallets and increase performance for service providers. It&apos;s designed mostly for exchanges and mining pools but anybody with a large wallet will benefit.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="835"/>
<location filename="../src/settings.ui" line="840"/>
<source>Enable Old Transaction Deletion</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="864"/>
<location filename="../src/settings.ui" line="869"/>
<source>Consolidation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="877"/>
<location filename="../src/settings.ui" line="882"/>
<source>Deletetx</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="903"/>
<location filename="../src/settings.ui" line="908"/>
<source>The new experimental Shielded Index (-zindex) which keeps track of many stats that can be seen via the new getchaintxstats RPC. These include shielded payments, anonymity set size and many other things.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="919"/>
<location filename="../src/settings.ui" line="924"/>
<source>Zindex </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="932"/>
<location filename="../src/settings.ui" line="937"/>
<source>100</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="945"/>
<location filename="../src/settings.ui" line="950"/>
<source>Wallet.dat Size :</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/settings.ui" line="958"/>
<location filename="../src/settings.ui" line="963"/>
<source>MB</source>
<translation type="unfinished"></translation>
</message>

355
res/silentdragon_de.ts

File diff suppressed because it is too large

355
res/silentdragon_es.ts

File diff suppressed because it is too large

355
res/silentdragon_fi.ts

File diff suppressed because it is too large

347
res/silentdragon_fil.ts

File diff suppressed because it is too large

355
res/silentdragon_fr.ts

File diff suppressed because it is too large

347
res/silentdragon_hr.ts

File diff suppressed because it is too large

347
res/silentdragon_id.ts

File diff suppressed because it is too large

355
res/silentdragon_it.ts

File diff suppressed because it is too large

355
res/silentdragon_nl.ts

File diff suppressed because it is too large

355
res/silentdragon_pt.ts

File diff suppressed because it is too large

2262
res/silentdragon_ro.ts

File diff suppressed because it is too large

347
res/silentdragon_ru.ts

File diff suppressed because it is too large

347
res/silentdragon_sr.ts

File diff suppressed because it is too large

355
res/silentdragon_tr.ts

File diff suppressed because it is too large

347
res/silentdragon_uk.ts

File diff suppressed because it is too large

359
res/silentdragon_zh.ts

File diff suppressed because it is too large

3
silentdragon.pro

@ -25,6 +25,7 @@ DEFINES += \
QT_DEPRECATED_WARNINGS
INCLUDEPATH += src/3rdparty/
INCLUDEPATH += src/
mac: LIBS+= -Wl,-dead_strip
mac: LIBS+= -Wl,-dead_strip_dylibs
@ -72,7 +73,6 @@ HEADERS += \
src/3rdparty/qrcode/BitBuffer.hpp \
src/3rdparty/qrcode/QrCode.hpp \
src/3rdparty/qrcode/QrSegment.hpp \
src/3rdparty/json/json.hpp \
src/settings.h \
src/txtablemodel.h \
src/senttxstore.h \
@ -122,6 +122,7 @@ TRANSLATIONS = res/silentdragon_bg.ts \
res/silentdragon_it.ts \
res/silentdragon_nl.ts \
res/silentdragon_pt.ts \
res/silentdragon_ro.ts \
res/silentdragon_ru.ts \
res/silentdragon_sr.ts \
res/silentdragon_tr.ts \

18928
src/3rdparty/json/json.hpp

File diff suppressed because it is too large

51
src/connection.cpp

@ -9,7 +9,6 @@
#include "precompiled.h"
using json = nlohmann::json;
ConnectionLoader::ConnectionLoader(MainWindow* main, RPC* rpc) {
this->main = main;
@ -23,7 +22,8 @@ ConnectionLoader::ConnectionLoader(MainWindow* main, RPC* rpc) {
QMovie *movie2 = new QMovie(":/img/res/silentdragon-animated-startup-dark.gif");;
auto theme = Settings::getInstance()->get_theme_name();
auto size = QSize(512,512);
if (theme == "dark" || "midnight") {
if (theme == "dark" || theme == "midnight") {
movie2->setScaledSize(size);
connD->topIcon->setMovie(movie2);
movie2->start();
@ -214,6 +214,9 @@ void ConnectionLoader::createZcashConf() {
out << "rpcworkqueue=256\n";
out << "rpcallowip=127.0.0.1\n";
// Consolidation is now defaulted to ON for new wallets
out << "consolidation=1\n";
if (!datadir.isEmpty()) {
out << "datadir=" % datadir % "\n";
}
@ -476,7 +479,7 @@ Connection* ConnectionLoader::makeConnection(std::shared_ptr<ConnectionConfig> c
void ConnectionLoader::refreshZcashdState(Connection* connection, std::function<void(void)> refused) {
main->logger->write("refreshing state");
json payload = {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "getinfo"}
@ -488,10 +491,10 @@ void ConnectionLoader::refreshZcashdState(Connection* connection, std::function<
// Delay 1 second to ensure loading (splash) is seen at least 1 second.
QTimer::singleShot(1000, [=]() { this->doRPCSetConnection(connection); });
},
[=] (auto reply, auto res) {
[=] (QNetworkReply* reply, const QJsonValue &res) {
// Failed, see what it is.
auto err = reply->error();
//qDebug() << err << ":" << QString::fromStdString(res.dump());
//qDebug() << err << res;
if (err == QNetworkReply::NetworkError::ConnectionRefusedError) {
refused();
@ -503,9 +506,9 @@ void ConnectionLoader::refreshZcashdState(Connection* connection, std::function<
this->showError(explanation);
} else if (err == QNetworkReply::NetworkError::InternalServerError &&
!res.is_discarded()) {
!res.isNull()) {
// The server is loading, so just poll until it succeeds
QString status = QString::fromStdString(res["error"]["message"]);
QString status = res["error"].toObject()["message"].toString();
{
static int dots = 0;
status = status.left(status.length() - 3) + QString(".").repeated(dots);
@ -758,16 +761,19 @@ Connection::~Connection() {
delete request;
}
void Connection::doRPC(const json& payload, const std::function<void(json)>& cb,
const std::function<void(QNetworkReply*, const json&)>& ne) {
void Connection::doRPC(const QJsonValue& payload, const std::function<void(QJsonValue)>& cb,
const std::function<void(QNetworkReply*, const QJsonValue&)>& ne) {
if (shutdownInProgress) {
// Ignoring RPC because shutdown in progress
return;
}
qDebug() << "RPC:" << QString::fromStdString(payload["method"]) << QString::fromStdString(payload.dump());
qDebug() << "RPC:" << payload["method"].toString() << payload;
QJsonDocument jd_rpc_call(payload.toObject());
QByteArray ba_rpc_call = jd_rpc_call.toJson();
QNetworkReply *reply = restclient->post(*request, QByteArray::fromStdString(payload.dump()));
QNetworkReply *reply = restclient->post(*request, ba_rpc_call);
QObject::connect(reply, &QNetworkReply::finished, [=] {
reply->deleteLater();
@ -776,15 +782,20 @@ void Connection::doRPC(const json& payload, const std::function<void(json)>& cb,
return;
}
QJsonDocument jd_reply = QJsonDocument::fromJson(reply->readAll());
QJsonValue parsed;
if (jd_reply.isObject())
parsed = jd_reply.object();
else
parsed = jd_reply.array();
if (reply->error() != QNetworkReply::NoError) {
auto parsed = json::parse(reply->readAll(), nullptr, false);
ne(reply, parsed);
return;
}
auto parsed = json::parse(reply->readAll(), nullptr, false);
if (parsed.is_discarded()) {
if (parsed.isNull()) {
ne(reply, "Unknown error");
}
@ -792,17 +803,17 @@ void Connection::doRPC(const json& payload, const std::function<void(json)>& cb,
});
}
void Connection::doRPCWithDefaultErrorHandling(const json& payload, const std::function<void(json)>& cb) {
doRPC(payload, cb, [=] (auto reply, auto parsed) {
if (!parsed.is_discarded() && !parsed["error"]["message"].is_null()) {
this->showTxError(QString::fromStdString(parsed["error"]["message"]));
void Connection::doRPCWithDefaultErrorHandling(const QJsonValue& payload, const std::function<void(QJsonValue)>& cb) {
doRPC(payload, cb, [=] (QNetworkReply* reply, const QJsonValue &parsed) {
if (!parsed.isUndefined() && !parsed["error"].toObject()["message"].isNull()) {
this->showTxError(parsed["error"].toObject()["message"].toString());
} else {
this->showTxError(reply->errorString());
}
});
}
void Connection::doRPCIgnoreError(const json& payload, const std::function<void(json)>& cb) {
void Connection::doRPCIgnoreError(const QJsonValue& payload, const std::function<void(QJsonValue)>& cb) {
doRPC(payload, cb, [=] (auto, auto) {
// Ignored error handling
});

36
src/connection.h

@ -5,8 +5,6 @@
#include "ui_connection.h"
#include "precompiled.h"
using json = nlohmann::json;
class RPC;
enum ConnectionType {
@ -99,19 +97,19 @@ public:
void shutdown();
void doRPC(const json& payload, const std::function<void(json)>& cb,
const std::function<void(QNetworkReply*, const json&)>& ne);
void doRPCWithDefaultErrorHandling(const json& payload, const std::function<void(json)>& cb);
void doRPCIgnoreError(const json& payload, const std::function<void(json)>& cb) ;
void doRPC(const QJsonValue& payload, const std::function<void(QJsonValue)>& cb,
const std::function<void(QNetworkReply*, const QJsonValue&)>& ne);
void doRPCWithDefaultErrorHandling(const QJsonValue& payload, const std::function<void(QJsonValue)>& cb);
void doRPCIgnoreError(const QJsonValue& payload, const std::function<void(QJsonValue)>& cb) ;
void showTxError(const QString& error);
// Batch method. Note: Because of the template, it has to be in the header file.
template<class T>
void doBatchRPC(const QList<T>& payloads,
std::function<json(T)> payloadGenerator,
std::function<void(QMap<T, json>*)> cb) {
auto responses = new QMap<T, json>(); // zAddr -> list of responses for each call.
std::function<QJsonValue(T)> payloadGenerator,
std::function<void(QMap<T, QJsonValue>*)> cb) {
auto responses = new QMap<T, QJsonValue>(); // zAddr -> list of responses for each call.
int totalSize = payloads.size();
if (totalSize == 0)
return;
@ -120,17 +118,21 @@ public:
// any overlapping calls
static QMap<QString, bool> inProgress;
QString method = QString::fromStdString(payloadGenerator(payloads[0])["method"]);
QString method = payloadGenerator(payloads[0])["method"].toString();
//if (inProgress.value(method, false)) {
// qDebug() << "In progress batch, skipping";
// return;
//}
for (auto item: payloads) {
json payload = payloadGenerator(item);
QJsonValue payload = payloadGenerator(item);
inProgress[method] = true;
QNetworkReply *reply = restclient->post(*request, QByteArray::fromStdString(payload.dump()));
QJsonDocument jd_rpc_call(payload.toObject());
QByteArray ba_rpc_call = jd_rpc_call.toJson();
QNetworkReply *reply = restclient->post(*request, ba_rpc_call);
QObject::connect(reply, &QNetworkReply::finished, [=] {
reply->deleteLater();
@ -140,16 +142,16 @@ public:
}
auto all = reply->readAll();
auto parsed = json::parse(all.toStdString(), nullptr, false);
auto parsed = QJsonDocument::fromJson(all);
if (reply->error() != QNetworkReply::NoError) {
qDebug() << QString::fromStdString(parsed.dump());
qDebug() << parsed.toJson();
qDebug() << reply->errorString();
(*responses)[item] = json::object(); // Empty object
(*responses)[item] = {}; // Empty object
} else {
if (parsed.is_discarded()) {
(*responses)[item] = json::object(); // Empty object
if (parsed.isEmpty()) {
(*responses)[item] = {}; // Empty object
} else {
(*responses)[item] = parsed["result"];
}

51
src/mainwindow.cpp

@ -22,7 +22,6 @@
#include "requestdialog.h"
#include "websockets.h"
using json = nlohmann::json;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
@ -280,11 +279,11 @@ void MainWindow::setupSettingsModal() {
Settings::getInstance()->setSaveZtxs(checked);
});
std::string currency_name;
QString currency_name;
try {
currency_name = Settings::getInstance()->get_currency_name();
} catch (const std::exception& e) {
qDebug() << QString("Currency name exception! : ") << e.what();
qDebug() << QString("Currency name exception! : ");
currency_name = "USD";
}
@ -310,11 +309,11 @@ void MainWindow::setupSettingsModal() {
});
// Set local currency
QString ticker = QString::fromStdString( Settings::getInstance()->get_currency_name() );
QString ticker = Settings::getInstance()->get_currency_name();
int currency_index = settings.comboBoxCurrency->findText(ticker, Qt::MatchExactly);
settings.comboBoxCurrency->setCurrentIndex(currency_index);
QObject::connect(settings.comboBoxCurrency, &QComboBox::currentTextChanged, [=] (QString ticker) {
this->slot_change_currency(ticker.toStdString());
this->slot_change_currency(ticker);
rpc->refresh(true);
QMessageBox::information(this, tr("Currency Change"), tr("This change can take a few seconds."), QMessageBox::Ok);
});
@ -625,7 +624,7 @@ void MainWindow::validateAddress() {
if (!ok)
return;
getRPC()->validateAddress(address, [=] (json props) {
getRPC()->validateAddress(address, [=] (QJsonValue props) {
QDialog d(this);
Ui_ValidateAddress va;
va.setupUi(&d);
@ -636,11 +635,19 @@ void MainWindow::validateAddress() {
va.lblAddress->setText(address);
QList<QPair<QString, QString>> propsList;
for (auto it = props.begin(); it != props.end(); it++) {
for (QString property_name: props.toObject().keys()) {
QString property_value;
if (props.toObject()[property_name].isString())
property_value = props.toObject()[property_name].toString();
else
property_value = props.toObject()[property_name].toBool() ? "true" : "false" ;
propsList.append(
QPair<QString, QString>(
QString::fromStdString(it.key()), QString::fromStdString(it.value().dump()))
QPair<QString, QString>( property_name,
property_value )
);
}
@ -916,9 +923,9 @@ void MainWindow::getViewKey(QString addr) {
vui.buttonBox->button(QDialogButtonBox::Save)->setEnabled(true);
};
auto fnAddKey = [=](json key) {
auto fnAddKey = [=](QJsonValue key) {
QList<QPair<QString, QString>> singleAddrKey;
singleAddrKey.push_back(QPair<QString, QString>(addr, QString::fromStdString(key.get<json::string_t>())));
singleAddrKey.push_back(QPair<QString, QString>(addr, key.toString()));
fnUpdateUIWithKeys(singleAddrKey);
};
@ -988,9 +995,9 @@ void MainWindow::exportKeys(QString addr) {
rpc->getAllPrivKeys(fnUpdateUIWithKeys);
}
else {
auto fnAddKey = [=](json key) {
auto fnAddKey = [=](QJsonValue key) {
QList<QPair<QString, QString>> singleAddrKey;
singleAddrKey.push_back(QPair<QString, QString>(addr, QString::fromStdString(key.get<json::string_t>())));
singleAddrKey.push_back(QPair<QString, QString>(addr, key.toString()));
fnUpdateUIWithKeys(singleAddrKey);
};
@ -1168,7 +1175,7 @@ void MainWindow::setupMarketTab() {
auto ticker = s->get_currency_name();
ui->volume->setText(QString::number((double) s->get_volume("HUSH") ,'f',8) + " HUSH");
ui->volumeLocal->setText(QString::number((double) s->get_volume(ticker) ,'f',8) + " " + QString::fromStdString(ticker));
ui->volumeLocal->setText(QString::number((double) s->get_volume(ticker) ,'f',8) + " " + ticker);
ui->volumeBTC->setText(QString::number((double) s->get_volume("BTC") ,'f',8) + " BTC");
}
@ -1285,8 +1292,8 @@ void MainWindow::setupTransactionsTab() {
}
void MainWindow::addNewZaddr() {
rpc->newZaddr( [=] (json reply) {
QString addr = QString::fromStdString(reply.get<json::string_t>());
rpc->newZaddr( [=] (QJsonValue reply) {
QString addr = reply.toString();
// Make sure the RPC class reloads the z-addrs for future use
rpc->refreshAddresses();
@ -1329,9 +1336,9 @@ std::function<void(bool)> MainWindow::addZAddrsToComboList(bool sapling) {
void MainWindow::setupReceiveTab() {
auto addNewTAddr = [=] () {
rpc->newTaddr([=] (json reply) {
rpc->newTaddr([=] (QJsonValue reply) {
qDebug() << "New addr button clicked";
QString addr = QString::fromStdString(reply.get<json::string_t>());
QString addr = reply.toString();
// Make sure the RPC class reloads the t-addrs for future use
rpc->refreshAddresses();
@ -1541,7 +1548,7 @@ void MainWindow::updateLabels() {
updateLabelsAutoComplete();
}
void MainWindow::slot_change_currency(const std::string& currency_name)
void MainWindow::slot_change_currency(const QString& currency_name)
{
qDebug() << "slot_change_currency"; //<< ": " << currency_name;
Settings::getInstance()->set_currency_name(currency_name);
@ -1549,11 +1556,11 @@ void MainWindow::slot_change_currency(const std::string& currency_name)
rpc->refreshPrice();
// Include currency
std::string saved_currency_name;
QString saved_currency_name;
try {
saved_currency_name = Settings::getInstance()->get_currency_name();
} catch (const std::exception& e) {
qDebug() << QString("Ignoring currency change Exception! : ") << e.what();
qDebug() << QString("Ignoring currency change Exception! : ");
saved_currency_name = "USD";
}
}
@ -1567,7 +1574,7 @@ void MainWindow::slot_change_theme(const QString& theme_name)
try {
saved_theme_name = Settings::getInstance()->get_theme_name();
} catch (const std::exception& e) {
qDebug() << QString("Ignoring theme change Exception! : ") << e.what();
qDebug() << QString("Ignoring theme change Exception! : ");
saved_theme_name = "default";
}

4
src/mainwindow.h

@ -10,8 +10,6 @@ class Settings;
class WSServer;
class WormholeClient;
using json = nlohmann::json;
// Struct used to hold destination info when sending a Tx.
struct ToFields {
QString addr;
@ -85,7 +83,7 @@ private:
void setupMarketTab();
void slot_change_theme(const QString& themeName);
void slot_change_currency(const std::string& currencyName);
void slot_change_currency(const QString& currencyName);
void setupTurnstileDialog();
void setupSettingsModal();
void setupStatusBar();

1
src/precompiled.h

@ -70,7 +70,6 @@
#include <QApplication>
#include <QDesktopWidget>
#include "3rdparty/json/json.hpp"
#include "3rdparty/qrcode/QrCode.hpp"
#define SODIUM_STATIC

420
src/rpc.cpp

@ -8,7 +8,6 @@
#include "version.h"
#include "websockets.h"
using json = nlohmann::json;
RPC::RPC(MainWindow* main) {
auto cl = new ConnectionLoader(main, this);
@ -102,18 +101,18 @@ void RPC::setConnection(Connection* c) {
refresh(true);
}
json RPC::makePayload(std::string method, std::string params) {
json payload = {
QJsonValue RPC::makePayload(QString method, QString params) {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "42" },
{"method", method },
{"params", {params}}
{"params", QJsonArray {params}}
};
return payload;
}
json RPC::makePayload(std::string method) {
json payload = {
QJsonValue RPC::makePayload(QString method) {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "42" },
{"method", method },
@ -121,77 +120,77 @@ json RPC::makePayload(std::string method) {
return payload;
}
void RPC::getTAddresses(const std::function<void(json)>& cb) {
std::string method = "getaddressesbyaccount";
std::string params = "";
conn->doRPCWithDefaultErrorHandling(makePayload(method, std::string("")), cb);
void RPC::getTAddresses(const std::function<void(QJsonValue)>& cb) {
QString method = "getaddressesbyaccount";
QString params = "";
conn->doRPCWithDefaultErrorHandling(makePayload(method, ""), cb);
}
void RPC::getZAddresses(const std::function<void(json)>& cb) {
std::string method = "z_listaddresses";
void RPC::getZAddresses(const std::function<void(QJsonValue)>& cb) {
QString method = "z_listaddresses";
conn->doRPCWithDefaultErrorHandling(makePayload(method), cb);
}
void RPC::getTransparentUnspent(const std::function<void(json)>& cb) {
json payload = {
void RPC::getTransparentUnspent(const std::function<void(QJsonValue)>& cb) {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"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);
}
void RPC::getZUnspent(const std::function<void(json)>& cb) {
json payload = {
void RPC::getZUnspent(const std::function<void(QJsonValue)>& cb) {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"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);
}
void RPC::newZaddr(const std::function<void(json)>& cb) {
json payload = {
void RPC::newZaddr(const std::function<void(QJsonValue)>& cb) {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "z_getnewaddress"},
{"params", { "sapling" }},
{"params", QJsonArray { "sapling" }},
};
conn->doRPCWithDefaultErrorHandling(payload, cb);
}
void RPC::newTaddr(const std::function<void(json)>& cb) {
void RPC::newTaddr(const std::function<void(QJsonValue)>& cb) {
std::string method = "getnewaddress";
QString method = "getnewaddress";
conn->doRPCWithDefaultErrorHandling(makePayload(method), cb);
}
void RPC::getZViewKey(QString addr, const std::function<void(json)>& cb) {
std::string method = "z_exportviewingkey";
conn->doRPCWithDefaultErrorHandling(makePayload(method, addr.toStdString()), cb);
void RPC::getZViewKey(QString addr, const std::function<void(QJsonValue)>& cb) {
QString method = "z_exportviewingkey";
conn->doRPCWithDefaultErrorHandling(makePayload(method, addr), cb);
}
void RPC::getZPrivKey(QString addr, const std::function<void(json)>& cb) {
std::string method = "z_exportkey";
conn->doRPCWithDefaultErrorHandling(makePayload(method, addr.toStdString()), cb);
void RPC::getZPrivKey(QString addr, const std::function<void(QJsonValue)>& cb) {
QString method = "z_exportkey";
conn->doRPCWithDefaultErrorHandling(makePayload(method, addr), cb);
}
void RPC::getTPrivKey(QString addr, const std::function<void(json)>& cb) {
std::string method = "dumpprivkey";
conn->doRPCWithDefaultErrorHandling(makePayload(method, addr.toStdString()), cb);
void RPC::getTPrivKey(QString addr, const std::function<void(QJsonValue)>& cb) {
QString method = "dumpprivkey";
conn->doRPCWithDefaultErrorHandling(makePayload(method, addr), cb);
}
void RPC::importZPrivKey(QString privkey, bool rescan, const std::function<void(json)>& cb) {
json payload = {
void RPC::importZPrivKey(QString privkey, bool rescan, const std::function<void(QJsonValue)>& cb) {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "z_importkey"},
{"params", { privkey.toStdString(), (rescan? "yes" : "no") }},
{"params", QJsonArray { privkey, (rescan ? "yes" : "no") }},
};
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
void RPC::importTPrivKey(QString privkey, bool rescan, const std::function<void(json)>& cb) {
json payload;
void RPC::importTPrivKey(QString privkey, bool rescan, const std::function<void(QJsonValue)>& cb) {
QJsonObject payload;
// 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") ) {
@ -209,7 +208,7 @@ void RPC::importTPrivKey(QString privkey, bool rescan, const std::function<void(
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "importprivkey"},
{"params", { privkey.toStdString(), "", "false", "0", "128" }},
{"params", QJsonArray { privkey, "", "false", "0", "128" }},
};
} else {
qDebug() << "Detected new-style HUSH WIF";
@ -217,7 +216,7 @@ void RPC::importTPrivKey(QString privkey, bool rescan, const std::function<void(
{"jsonrpc", "1.0"},
{"id", "someid"},
{"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);
}
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";
conn->doRPCWithDefaultErrorHandling(makePayload(method.toStdString(), address.toStdString()), cb);
conn->doRPCWithDefaultErrorHandling(makePayload(method, address), cb);
}
void RPC::getBalance(const std::function<void(json)>& cb) {
json payload = {
void RPC::getBalance(const std::function<void(QJsonValue)>& cb) {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "z_gettotalbalance"},
{"params", {0}} // Get Unconfirmed balance as well.
{"params", QJsonArray {0}} // Get Unconfirmed balance as well.
};
conn->doRPCWithDefaultErrorHandling(payload, cb);
}
void RPC::getTransactions(const std::function<void(json)>& cb) {
std::string method = "listtransactions";
void RPC::getTransactions(const std::function<void(QJsonValue)>& cb) {
QString method = "listtransactions";
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) {
json payload = {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "z_sendmany"},
{"params", params}
};
conn->doRPC(payload, cb, [=] (auto reply, auto parsed) {
if (!parsed.is_discarded() && !parsed["error"]["message"].is_null()) {
err(QString::fromStdString(parsed["error"]["message"]));
conn->doRPC(payload, cb, [=] (QNetworkReply *reply, const QJsonValue &parsed) {
if (!parsed.isUndefined() && !parsed["error"].toObject()["message"].isNull()) {
err(parsed["error"].toObject()["message"].toString());
} else {
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
auto fnDoBatchGetPrivKeys = [=](json getAddressPayload, std::string privKeyDumpMethodName) {
conn->doRPCWithDefaultErrorHandling(getAddressPayload, [=] (json resp) {
auto fnDoBatchGetPrivKeys = [=](QJsonValue getAddressPayload, QString privKeyDumpMethodName) {
conn->doRPCWithDefaultErrorHandling(getAddressPayload, [=] (QJsonValue resp) {
QList<QString> addrs;
for (auto addr : resp.get<json::array_t>()) {
addrs.push_back(QString::fromStdString(addr.get<json::string_t>()));
for (auto addr : resp.toArray()) {
addrs.push_back(addr.toString());
}
// Then, do a batch request to get all the private keys
conn->doBatchRPC<QString>(
addrs,
[=] (auto addr) {
json payload = {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", privKeyDumpMethodName},
{"params", { addr.toStdString() }},
{"params", QJsonArray { addr }},
};
return payload;
},
[=] (QMap<QString, json>* privkeys) {
[=] (QMap<QString, QJsonValue>* privkeys) {
QList<QPair<QString, QString>> allTKeys;
for (QString addr: privkeys->keys()) {
allTKeys.push_back(
QPair<QString, QString>(
addr,
QString::fromStdString(privkeys->value(addr).get<json::string_t>())));
privkeys->value(addr).toString()));
}
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.
json payloadT = {
QJsonObject payloadT = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "getaddressesbyaccount"},
{"params", {""} }
{"params", QJsonArray {""} }
};
json payloadZ = {
QJsonObject payloadZ = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"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
void RPC::fillTxJsonParams(json& params, Tx tx) {
Q_ASSERT(params.is_array());
void RPC::fillTxJsonParams(QJsonArray& params, Tx tx) {
Q_ASSERT(QJsonValue(params).isArray());
// 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 (int i=0; i < tx.toAddrs.size(); i++) {
auto toAddr = tx.toAddrs[i];
// Construct the JSON params
json rec = json::object();
rec["address"] = toAddr.addr.toStdString();
QJsonObject rec;
rec["address"] = toAddr.addr;
// Force it through string for rounding. Without this, decimal points beyond 8 places
// 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())
rec["memo"] = toAddr.encodedMemo.toStdString();
rec["memo"] = toAddr.encodedMemo;
allRecepients.push_back(rec);
}
// Add sender
params.push_back(tx.fromAddr.toStdString());
params.push_back(tx.fromAddr);
params.push_back(allRecepients);
// 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(tx.fee);
}
}
@ -440,36 +442,36 @@ void RPC::refreshReceivedZTrans(QList<QString> zaddrs) {
// 1. For each z-Addr, get list of received txs
conn->doBatchRPC<QString>(zaddrs,
[=] (QString zaddr) {
json payload = {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "z_lrba"},
{"method", "z_listreceivedbyaddress"},
{"params", {zaddr.toStdString(), 0}} // Accept 0 conf as well.
{"params", QJsonArray {zaddr, 0}} // Accept 0 conf as well.
};
return payload;
},
[=] (QMap<QString, json>* zaddrTxids) {
[=] (QMap<QString, QJsonValue>* zaddrTxids) {
// Process all txids, removing duplicates. This can happen if the same address
// appears multiple times in a single tx's outputs.
QSet<QString> txids;
QMap<QString, QString> memos;
for (auto it = zaddrTxids->constBegin(); it != zaddrTxids->constEnd(); it++) {
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
usedAddresses->insert(zaddr, true);
// Filter out change txs
if (! i["change"].get<json::boolean_t>()) {
auto txid = QString::fromStdString(i["txid"].get<json::string_t>());
if (! i.toObject()["change"].toBool()) {
auto txid = i.toObject()["txid"].toString();
txids.insert(txid);
// Check for Memos
QString memoBytes = QString::fromStdString(i["memo"].get<json::string_t>());
QString memoBytes = i.toObject()["memo"].toString();
if (!memoBytes.startsWith("f600")) {
QString memo(QByteArray::fromHex(
QByteArray::fromStdString(i["memo"].get<json::string_t>())));
i.toObject()["memo"].toString().toUtf8()));
if (!memo.trimmed().isEmpty())
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.
conn->doBatchRPC<QString>(txids.toList(),
[=] (QString txid) {
json payload = {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "gettx"},
{"method", "gettransaction"},
{"params", {txid.toStdString()}}
{"params", QJsonArray {txid}}
};
return payload;
},
[=] (QMap<QString, json>* txidDetails) {
[=] (QMap<QString, QJsonValue>* txidDetails) {
QList<TransactionItem> txdata;
// 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& i : it.value().get<json::array_t>()) {
for (const auto& i : it.value().toArray()) {
// Filter out change txs
if (i["change"].get<json::boolean_t>())
if (i.toObject()["change"].toBool())
continue;
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
auto txidInfo = txidDetails->value(txid);
qint64 timestamp;
if (txidInfo.find("time") != txidInfo.end()) {
timestamp = txidInfo["time"].get<json::number_unsigned_t>();
if (!txidInfo.toObject()["time"].isUndefined()) {
timestamp = txidInfo.toObject()["time"].toInt();
} else {
timestamp = txidInfo["blocktime"].get<json::number_unsigned_t>();
timestamp = txidInfo.toObject()["blocktime"].toInt();
}
auto amount = i["amount"].get<json::number_float_t>();
auto confirmations = (unsigned long)txidInfo["confirmations"].get<json::number_unsigned_t>();
auto amount = i.toObject()["amount"].toDouble();
auto confirmations = (unsigned long)txidInfo["confirmations"].toInt();
TransactionItem tx{ QString("receive"), timestamp, zaddr, txid, amount,
confirmations, "", memos.value(zaddr + txid, "") };
@ -547,12 +549,13 @@ void RPC::getInfoThenRefresh(bool force) {
return noConnection();
static bool prevCallSucceeded = false;
std::string method = "getinfo";
conn->doRPC(makePayload(method), [=] (const json& reply) {
QString method = "getinfo";
conn->doRPC(makePayload(method), [=] (const QJsonValue& reply) {
prevCallSucceeded = true;
// Testnet?
if (!reply["testnet"].is_null()) {
Settings::getInstance()->setTestnet(reply["testnet"].get<json::boolean_t>());
if (!reply["testnet"].isNull()) {
Settings::getInstance()->setTestnet(reply["testnet"].toBool());
};
// TODO: checkmark only when getinfo.synced == true!
@ -561,20 +564,20 @@ void RPC::getInfoThenRefresh(bool force) {
main->statusIcon->setPixmap(i.pixmap(16, 16));
static int lastBlock = 0;
int curBlock = reply["blocks"].get<json::number_integer_t>();
int longestchain = reply["longestchain"].get<json::number_integer_t>();
int version = reply["version"].get<json::number_integer_t>();
int p2pport = reply["p2pport"].get<json::number_integer_t>();
int rpcport = reply["rpcport"].get<json::number_integer_t>();
int notarized = reply["notarized"].get<json::number_integer_t>();
int protocolversion = reply["protocolversion"].get<json::number_integer_t>();
int curBlock = reply["blocks"].toInt();
int longestchain = reply["longestchain"].toInt();
int version = reply["version"].toInt();
int p2pport = reply["p2pport"].toInt();
int rpcport = reply["rpcport"].toInt();
int notarized = reply["notarized"].toInt();
int protocolversion = reply["protocolversion"].toInt();
int lag = curBlock - notarized;
int blocks_until_halving= 340000 - curBlock;
char halving_days[8];
sprintf(halving_days, "%.2f", (double) (blocks_until_halving * 150) / (60*60*24) );
QString ntzhash = QString::fromStdString( reply["notarizedhash"].get<json::string_t>() );
QString ntztxid = QString::fromStdString( reply["notarizedtxid"].get<json::string_t>() );
QString kmdver = QString::fromStdString( reply["KMDversion"].get<json::string_t>() );
QString ntzhash = reply["notarizedhash"].toString();
QString ntztxid = reply["notarizedtxid"].toString();
QString kmdver = reply["KMDversion"].toString();
Settings::getInstance()->setZcashdVersion(version);
@ -598,7 +601,7 @@ void RPC::getInfoThenRefresh(bool force) {
refreshTransactions();
}
int connections = reply["connections"].get<json::number_integer_t>();
int connections = reply["connections"].toInt();
Settings::getInstance()->setPeers(connections);
if (connections == 0) {
@ -608,15 +611,15 @@ void RPC::getInfoThenRefresh(bool force) {
}
// Get network sol/s
json payload = {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "getnetworksolps"}
};
std::string method = "getnetworksolps";
conn->doRPCIgnoreError(makePayload(method), [=](const json& reply) {
qint64 solrate = reply.get<json::number_unsigned_t>();
QString method = "getnetworksolps";
conn->doRPCIgnoreError(makePayload(method), [=](const QJsonValue& reply) {
qint64 solrate = reply.toInt();
ui->numconnections->setText(QString::number(connections));
ui->solrate->setText(QString::number(solrate) % " Sol/s");
@ -629,42 +632,42 @@ void RPC::getInfoThenRefresh(bool force) {
{"method", "getnetworkinfo"}
};
conn->doRPCIgnoreError(payload, [=](const json& reply) {
QString clientname = QString::fromStdString( reply["subversion"].get<json::string_t>() );
QString localservices = QString::fromStdString( reply["localservices"].get<json::string_t>() );
conn->doRPCIgnoreError(payload, [=](const QJsonValue& reply) {
QString clientname = reply["subversion"].toString();
QString localservices = reply["localservices"].toString();
ui->clientname->setText(clientname);
ui->localservices->setText(localservices);
});
conn->doRPCIgnoreError(makePayload("getwalletinfo"), [=](const json& reply) {
int txcount = reply["txcount"].get<json::number_integer_t>();
conn->doRPCIgnoreError(makePayload("getwalletinfo"), [=](const QJsonValue& reply) {
int txcount = reply["txcount"].toInt();
ui->txcount->setText(QString::number(txcount));
});
//TODO: If -zindex is enabled, show stats
conn->doRPCIgnoreError(makePayload("getchaintxstats"), [=](const json& reply) {
int txcount = reply["txcount"].get<json::number_integer_t>();
conn->doRPCIgnoreError(makePayload("getchaintxstats"), [=](const QJsonValue& reply) {
int txcount = reply["txcount"].toInt();
ui->chaintxcount->setText(QString::number(txcount));
});
// Call to see if the blockchain is syncing.
conn->doRPCIgnoreError(makePayload("getblockchaininfo"), [=](const json& reply) {
auto progress = reply["verificationprogress"].get<double>();
conn->doRPCIgnoreError(makePayload("getblockchaininfo"), [=](const QJsonValue& reply) {
auto progress = reply["verificationprogress"].toDouble();
// TODO: use getinfo.synced
bool isSyncing = progress < 0.9999; // 99.99%
int blockNumber = reply["blocks"].get<json::number_unsigned_t>();
int blockNumber = reply["blocks"].toInt();
int estimatedheight = 0;
if (reply.find("estimatedheight") != reply.end()) {
estimatedheight = reply["estimatedheight"].get<json::number_unsigned_t>();
if (!reply.toObject()["estimatedheight"].isUndefined()) {
estimatedheight = reply["estimatedheight"].toInt();
}
auto s = Settings::getInstance();
s->setSyncing(isSyncing);
s->setBlockNumber(blockNumber);
std::string ticker = s->get_currency_name();
QString ticker = s->get_currency_name();
// Update hushd tab
if (isSyncing) {
@ -690,7 +693,7 @@ void RPC::getInfoThenRefresh(bool force) {
}
QString price = "";
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
@ -721,7 +724,7 @@ void RPC::getInfoThenRefresh(bool force) {
main->statusIcon->setToolTip(tooltip);
});
}, [=](QNetworkReply* reply, const json&) {
}, [=](QNetworkReply* reply, const QJsonValue&) {
// hushd has probably disappeared.
this->noConnection();
@ -744,9 +747,9 @@ void RPC::refreshAddresses() {
auto newzaddresses = new QList<QString>();
getZAddresses([=] (json reply) {
for (auto& it : reply.get<json::array_t>()) {
auto addr = QString::fromStdString(it.get<json::string_t>());
getZAddresses([=] (QJsonValue reply) {
for (const auto& it : reply.toArray()) {
auto addr = it.toString();
newzaddresses->push_back(addr);
}
@ -760,9 +763,9 @@ void RPC::refreshAddresses() {
auto newtaddresses = new QList<QString>();
getTAddresses([=] (json reply) {
for (auto& it : reply.get<json::array_t>()) {
auto addr = QString::fromStdString(it.get<json::string_t>());
getTAddresses([=] (QJsonValue reply) {
for (const auto& it : reply.toArray()) {
auto addr = it.toString();
if (Settings::isTAddress(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.
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;
for (auto& it : reply.get<json::array_t>()) {
QString qsAddr = QString::fromStdString(it["address"]);
auto confirmations = it["confirmations"].get<json::number_unsigned_t>();
for (const auto& it : reply.toArray()) {
QString qsAddr = it.toObject()["address"].toString();
auto confirmations = it.toObject()["confirmations"].toInt();
if (confirmations == 0) {
anyUnconfirmed = true;
}
newUtxos->push_back(
UnspentOutput{ qsAddr, QString::fromStdString(it["txid"]),
Settings::getDecimalString(it["amount"].get<json::number_float_t>()),
(int)confirmations, it["spendable"].get<json::boolean_t>() });
UnspentOutput{ qsAddr, it.toObject()["txid"].toString(),
Settings::getDecimalString(it.toObject()["amount"].toDouble()),
(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;
};
@ -808,10 +811,11 @@ void RPC::refreshBalances() {
return noConnection();
// 1. Get the Balances
getBalance([=] (json reply) {
auto balT = QString::fromStdString(reply["transparent"]).toDouble();
auto balZ = QString::fromStdString(reply["private"]).toDouble();
auto balTotal = QString::fromStdString(reply["total"]).toDouble();
getBalance([=] (QJsonValue reply) {
auto balT = reply["transparent"].toString().toDouble();
auto balZ = reply["private"].toString().toDouble();
auto balTotal = reply["total"].toString().toDouble();
AppDataModel::getInstance()->setBalances(balT, balZ);
@ -833,10 +837,10 @@ void RPC::refreshBalances() {
auto newBalances = new QMap<QString, double>();
// 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);
getZUnspent([=] (json reply) {
getZUnspent([=] (QJsonValue reply) {
auto anyZUnconfirmed = processUnspent(reply, newBalances, newUtxos);
// Swap out the balances and UTXOs
@ -857,24 +861,24 @@ void RPC::refreshTransactions() {
if (conn == nullptr)
return noConnection();
getTransactions([=] (json reply) {
getTransactions([=] (QJsonValue reply) {
QList<TransactionItem> txdata;
for (auto& it : reply.get<json::array_t>()) {
for (const auto& it : reply.toArray()) {
double fee = 0;
if (!it["fee"].is_null()) {
fee = it["fee"].get<json::number_float_t>();
if (!it.toObject()["fee"].isNull()) {
fee = it.toObject()["fee"].toDouble();
}
QString address = (it["address"].is_null() ? "" : QString::fromStdString(it["address"]));
QString address = (it.toObject()["address"].isNull() ? "" : it.toObject()["address"].toString());
TransactionItem tx{
QString::fromStdString(it["category"]),
(qint64)it["time"].get<json::number_unsigned_t>(),
it.toObject()["category"].toString(),
(qint64)it.toObject()["time"].toInt(),
address,
QString::fromStdString(it["txid"]),
it["amount"].get<json::number_float_t>() + fee,
(unsigned long)it["confirmations"].get<json::number_unsigned_t>(),
it.toObject()["txid"].toString(),
it.toObject()["amount"].toDouble() + fee,
(unsigned long)it.toObject()["confirmations"].toInt(),
"", "" };
txdata.push_back(tx);
@ -910,16 +914,16 @@ void RPC::refreshSentZTrans() {
// Look up all the txids to get the confirmation count for them.
conn->doBatchRPC<QString>(txids,
[=] (QString txid) {
json payload = {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "senttxid"},
{"method", "gettransaction"},
{"params", {txid.toStdString()}}
{"params", QJsonArray {txid}}
};
return payload;
},
[=] (QMap<QString, json>* txidList) {
[=] (QMap<QString, QJsonValue>* txidList) {
auto newSentZTxs = sentZTxs;
// Update the original sent list with the confirmation count
// TODO: This whole thing is kinda inefficient. We should probably just update the file
@ -927,11 +931,11 @@ void RPC::refreshSentZTrans() {
// sent items.
for (TransactionItem& sentTx: newSentZTxs) {
auto j = txidList->value(sentTx.txid);
if (j.is_null())
if (j.isNull())
continue;
auto error = j["confirmations"].is_null();
auto error = j["confirmations"].isNull();
if (!error)
sentTx.confirmations = j["confirmations"].get<json::number_unsigned_t>();
sentTx.confirmations = j["confirmations"].toInt();
}
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 errStr)> error) {
// First, create the json params
json params = json::array();
QJsonArray params;
fillTxJsonParams(params, tx);
std::cout << std::setw(2) << params << std::endl;
//std::cout << std::setw(2) << params << std::endl;
sendZTransaction(params, [=](const json& reply) {
QString opid = QString::fromStdString(reply.get<json::string_t>());
sendZTransaction(params, [=](const QJsonValue& reply) {
QString opid = reply.toString();
// And then start monitoring the transaction
addNewTxToWatch( opid, WatchedTx { opid, tx, computed, error} );
@ -975,35 +979,35 @@ void RPC::watchTxStatus() {
return noConnection();
// 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) {
// 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
QString id = QString::fromStdString(it["id"]);
QString id = it.toObject()["id"].toString();
if (watchingOps.contains(id)) {
// log any txs we are watching
// "creation_time": 1515969376,
// "execution_secs": 50.416337,
// And if it ended up successful
QString status = QString::fromStdString(it["status"]);
QString status = it.toObject()["status"].toString();
main->loadingLabel->setVisible(false);
if (status == "success") {
auto txid = QString::fromStdString(it["result"]["txid"]);
auto txid = it.toObject()["result"].toObject()["txid"].toString();
SentTxStore::addToSentTx(watchingOps[id].tx, txid);
auto wtx = watchingOps[id];
watchingOps.remove(id);
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(true);
} else if (status == "failed") {
// 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];
watchingOps.remove(id);
@ -1116,11 +1120,18 @@ void RPC::refreshPrice() {
reply->deleteLater();
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) {
qDebug() << "Parsing price feed response";
auto parsed = json::parse(reply->readAll(), nullptr, false);
if (!parsed.is_discarded() && !parsed["error"]["message"].is_null()) {
qDebug() << QString::fromStdString(parsed["error"]["message"]);
if (!parsed.isEmpty() && !parsed["error"].toObject()["message"].isNull()) {
qDebug() << parsed["error"].toObject()["message"].toString();
} else {
qDebug() << reply->errorString();
}
@ -1130,9 +1141,8 @@ void RPC::refreshPrice() {
}
qDebug() << "No network errors";
auto all = reply->readAll();
auto parsed = json::parse(all, nullptr, false);
if (parsed.is_discarded()) {
if (parsed.isEmpty()) {
s->setZECPrice(0);
s->setBTCPrice(0);
return;
@ -1140,51 +1150,53 @@ void RPC::refreshPrice() {
qDebug() << "Parsed JSON";
const json& item = parsed.get<json::object_t>();
const json& hush = item["hush"].get<json::object_t>();
std::string ticker = s->get_currency_name();
std::for_each(ticker.begin(), ticker.end(), [](char & c){ c = ::tolower(c); });
fprintf(stderr,"ticker=%s\n", ticker.c_str());
const QJsonValue& item = parsed;
const QJsonValue& hush = item["hush"].toObject();
QString ticker = s->get_currency_name();
ticker = ticker.toLower();
fprintf(stderr,"ticker=%s\n", ticker.toLocal8Bit().data());
//qDebug() << "Ticker = " + ticker;
if (hush[ticker] >= 0) {
if (!hush[ticker].isUndefined()) {
qDebug() << "Found hush key in price json";
//QString price = QString::fromStdString(hush["usd"].get<json::string_t>());
qDebug() << "HUSH = $" << QString::number((double)hush["usd"]) << " USD";
qDebug() << "HUSH = " << QString::number((double)hush["eur"]) << " EUR";
qDebug() << "HUSH = " << QString::number((int) 100000000 * (double) hush["btc"]) << " sat ";
//QString price = hush["usd"].toString());
qDebug() << "HUSH = $" << QString::number(hush["usd"].toDouble()) << " USD";
qDebug() << "HUSH = " << QString::number(hush["eur"].toDouble()) << " EUR";
qDebug() << "HUSH = " << QString::number((int) 100000000 * hush["btc"].toDouble()) << " sat ";
s->setZECPrice( hush[ticker] );
s->setBTCPrice( (unsigned int) 100000000 * (double)hush["btc"] );
s->setZECPrice( hush[ticker].toDouble() );
s->setBTCPrice( (unsigned int) 100000000 * hush["btc"].toDouble() );
std::for_each(ticker.begin(), ticker.end(), [](char & c){ c = ::tolower(c); });
qDebug() << "ticker=" << QString::fromStdString(ticker);
ticker = ticker.toLower();
qDebug() << "ticker=" << ticker;
// TODO: work harder to prevent coredumps!
auto price = hush[ticker];
auto vol = hush[ticker + "_24h_vol"];
auto mcap = hush[ticker + "_market_cap"];
auto price = hush[ticker].toDouble();
auto vol = hush[ticker + "_24h_vol"].toDouble();
auto mcap = hush[ticker + "_market_cap"].toDouble();
auto btcprice = hush["btc"];
auto btcvol = hush["btc_24h_vol"];
auto btcmcap = hush["btc_market_cap"];
//auto btcprice = hush["btc"].toDouble();
auto btcvol = hush["btc_24h_vol"].toDouble();
auto btcmcap = hush["btc_market_cap"].toDouble();
s->set_price(ticker, price);
s->set_volume(ticker, vol);
s->set_volume("BTC", btcvol);
s->set_marketcap(ticker, mcap);
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" );
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
if (price > 0)
ui->volumeLocal->setText( QString::number((double) vol / (double) price) + " HUSH");
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->marketcapLocal->setText( QString::number((double) mcap * (double) price) + " " + QString::fromStdString(ticker) );
//ui->marketcapLocal->setText( QString::number((double) mcap * (double) price) + " " + ticker );
refresh(true);
return;
@ -1193,7 +1205,7 @@ void RPC::refreshPrice() {
}
} catch (const std::exception& e) {
// If anything at all goes wrong, just set the price to 0 and move on.
qDebug() << QString("Price feed update failure : ") << e.what();
qDebug() << QString("Price feed update failure : ");
}
// If nothing, then set the price to 0;
@ -1209,7 +1221,7 @@ void RPC::shutdownZcashd() {
return;
}
std::string method = "stop";
QString method = "stop";
conn->doRPCWithDefaultErrorHandling(makePayload(method), [=](auto) {});
conn->shutdown();
@ -1222,7 +1234,7 @@ void RPC::shutdownZcashd() {
QMovie *movie1 = new QMovie(":/img/res/silentdragon-animated.gif");;
QMovie *movie2 = new QMovie(":/img/res/silentdragon-animated-dark.gif");;
auto theme = Settings::getInstance()->get_theme_name();
if (theme == "dark" || "midnight") {
if (theme == "dark" || theme == "midnight") {
movie2->setScaledSize(QSize(512,512));
connD.topIcon->setMovie(movie2);
movie2->start();

40
src/rpc.h

@ -9,8 +9,6 @@
#include "mainwindow.h"
#include "connection.h"
using json = nlohmann::json;
class Turnstile;
struct TransactionItem {
@ -54,8 +52,8 @@ public:
const std::function<void(QString opid, QString txid)> computed,
const std::function<void(QString opid, QString errStr)> error);
void fillTxJsonParams(json& params, Tx tx);
void sendZTransaction(json params, const std::function<void(json)>& cb, const std::function<void(QString)>& err);
void fillTxJsonParams(QJsonArray& params, Tx tx);
void sendZTransaction(QJsonValue params, const std::function<void(QJsonValue)>& cb, const std::function<void(QString)>& err);
void watchTxStatus();
const QMap<QString, WatchedTx> getWatchingTxns() { return watchingOps; }
@ -68,15 +66,15 @@ public:
const QMap<QString, double>* getAllBalances() { return allBalances; }
const QMap<QString, bool>* getUsedAddresses() { return usedAddresses; }
void newZaddr(const std::function<void(json)>& cb);
void newTaddr(const std::function<void(json)>& cb);
void newZaddr(const std::function<void(QJsonValue)>& cb);
void newTaddr(const std::function<void(QJsonValue)>& cb);
void getZPrivKey(QString addr, const std::function<void(json)>& cb);
void getZViewKey(QString addr, const std::function<void(json)>& cb);
void getTPrivKey(QString addr, const std::function<void(json)>& cb);
void importZPrivKey(QString addr, bool rescan, const std::function<void(json)>& cb);
void importTPrivKey(QString addr, bool rescan, const std::function<void(json)>& cb);
void validateAddress(QString address, const std::function<void(json)>& cb);
void getZPrivKey(QString addr, const std::function<void(QJsonValue)>& cb);
void getZViewKey(QString addr, const std::function<void(QJsonValue)>& cb);
void getTPrivKey(QString addr, const std::function<void(QJsonValue)>& cb);
void importZPrivKey(QString addr, bool rescan, const std::function<void(QJsonValue)>& cb);
void importTPrivKey(QString addr, bool rescan, const std::function<void(QJsonValue)>& cb);
void validateAddress(QString address, const std::function<void(QJsonValue)>& cb);
void shutdownZcashd();
void noConnection();
@ -97,20 +95,20 @@ private:
void refreshSentZTrans();
void refreshReceivedZTrans(QList<QString> zaddresses);
bool processUnspent (const json& reply, QMap<QString, double>* newBalances, QList<UnspentOutput>* newUtxos);
bool processUnspent (const QJsonValue& reply, QMap<QString, double>* newBalances, QList<UnspentOutput>* newUtxos);
void updateUI (bool anyUnconfirmed);
void getInfoThenRefresh(bool force);
void getBalance(const std::function<void(json)>& cb);
json makePayload(std::string method, std::string params);
json makePayload(std::string method);
void getBalance(const std::function<void(QJsonValue)>& cb);
QJsonValue makePayload(QString method, QString params);
QJsonValue makePayload(QString method);
void getTransparentUnspent (const std::function<void(json)>& cb);
void getZUnspent (const std::function<void(json)>& cb);
void getTransactions (const std::function<void(json)>& cb);
void getZAddresses (const std::function<void(json)>& cb);
void getTAddresses (const std::function<void(json)>& cb);
void getTransparentUnspent (const std::function<void(QJsonValue)>& cb);
void getZUnspent (const std::function<void(QJsonValue)>& cb);
void getTransactions (const std::function<void(QJsonValue)>& cb);
void getZAddresses (const std::function<void(QJsonValue)>& cb);
void getTAddresses (const std::function<void(QJsonValue)>& cb);
Connection* conn = nullptr;
std::shared_ptr<QProcess> ezcashd = nullptr;

3
src/sendtab.cpp

@ -10,7 +10,6 @@
#include "recurring.h"
#include <QFileDialog>
using json = nlohmann::json;
void MainWindow::setupSendTab() {
// Create the validator for send to/amount fields
@ -715,7 +714,7 @@ void MainWindow::sendButton() {
QMovie *movie1 = new QMovie(":/img/res/silentdragon-animated.gif");;
QMovie *movie2 = new QMovie(":/img/res/silentdragon-animated-dark.gif");;
auto theme = Settings::getInstance()->get_theme_name();
if (theme == "dark" || "midnight") {
if (theme == "dark" || theme == "midnight") {
movie2->setScaledSize(QSize(512,512));
connD->topIcon->setMovie(movie2);
movie2->start();

41
src/settings.cpp

@ -163,9 +163,9 @@ double Settings::getZECPrice() {
return zecPrice;
}
double Settings::get_price(std::string currency) {
std::for_each(currency.begin(), currency.end(), [](char & c){ c = ::tolower(c); });
QString ticker = QString::fromStdString(currency);
double Settings::get_price(QString currency) {
currency = currency.toLower();
QString ticker = currency;
auto search = prices.find(currency);
if (search != prices.end()) {
qDebug() << "Found price of " << ticker << " = " << search->second;
@ -176,21 +176,22 @@ double Settings::get_price(std::string currency) {
}
}
void Settings::set_price(std::string curr, double price) {
QString ticker = QString::fromStdString(curr);
void Settings::set_price(QString curr, double price) {
QString ticker = curr;
qDebug() << "Setting price of " << ticker << "=" << QString::number(price);
prices.insert( std::make_pair(curr, price) );
prices.insert( std::make_pair(curr, price) );
}
void Settings::set_volume(std::string curr, double volume) {
QString ticker = QString::fromStdString(curr);
void Settings::set_volume(QString curr, double volume) {
QString ticker = curr;
qDebug() << "Setting volume of " << ticker << "=" << QString::number(volume);
volumes.insert( std::make_pair(curr, volume) );
}
double Settings::get_volume(std::string currency) {
std::for_each(currency.begin(), currency.end(), [](char & c){ c = ::tolower(c); });
QString ticker = QString::fromStdString(currency);
double Settings::get_volume(QString currency) {
currency = currency.toLower();
QString ticker = currency;
auto search = volumes.find(currency);
if (search != volumes.end()) {
qDebug() << "Found volume of " << ticker << " = " << search->second;
@ -201,15 +202,15 @@ double Settings::get_volume(std::string currency) {
}
}
void Settings::set_marketcap(std::string curr, double marketcap) {
QString ticker = QString::fromStdString(curr);
void Settings::set_marketcap(QString curr, double marketcap) {
QString ticker = curr;
qDebug() << "Setting marketcap of " << ticker << "=" << QString::number(marketcap);
marketcaps.insert( std::make_pair(curr, marketcap) );
}
double Settings::get_marketcap(std::string currency) {
std::for_each(currency.begin(), currency.end(), [](char & c){ c = ::tolower(c); });
QString ticker = QString::fromStdString(currency);
double Settings::get_marketcap(QString currency) {
currency = currency.toLower();
QString ticker = currency;
auto search = marketcaps.find(currency);
if (search != marketcaps.end()) {
qDebug() << "Found marketcap of " << ticker << " = " << search->second;
@ -281,7 +282,7 @@ void Settings::saveRestore(QDialog* d) {
QString Settings::getUSDFormat(double bal) {
//TODO: respect current locale!
return QLocale(QLocale::English).toString(bal * Settings::getInstance()->getZECPrice(), 'f', 8) + " " + QString::fromStdString(Settings::getInstance()->get_currency_name());
return QLocale(QLocale::English).toString(bal * Settings::getInstance()->getZECPrice(), 'f', 8) + " " +Settings::getInstance()->get_currency_name();
}
QString Settings::getDecimalString(double amt) {
@ -341,13 +342,13 @@ bool Settings::addToZcashConf(QString confLocation, QString line) {
return true;
}
std::string Settings::get_currency_name() {
QString Settings::get_currency_name() {
// Load from the QT Settings.
return QSettings().value("options/currency_name", "BTC").toString().toStdString();
return QSettings().value("options/currency_name", "BTC").toString();
}
void Settings::set_currency_name(std::string currency_name) {
QSettings().setValue("options/currency_name", QString::fromStdString(currency_name));
void Settings::set_currency_name(QString currency_name) {
QSettings().setValue("options/currency_name", currency_name);
}

22
src/settings.h

@ -85,8 +85,8 @@ public:
QString get_theme_name();
void set_theme_name(QString theme_name);
std::string get_currency_name();
void set_currency_name(std::string currency_name);
QString get_currency_name();
void set_currency_name(QString currency_name);
void setUsingZcashConf(QString confLocation);
const QString& getZcashdConfLocation() { return _confLocation; }
@ -97,12 +97,12 @@ public:
double getZECPrice();
double get_fiat_price();
unsigned int getBTCPrice();
double get_price(std::string currency);
void set_price(std::string currency, double price);
double get_volume(std::string ticker);
void set_volume(std::string curr, double volume);
double get_marketcap(std::string curr);
void set_marketcap(std::string curr, double marketcap);
double get_price(QString currency);
void set_price(QString currency, double price);
double get_volume(QString ticker);
void set_volume(QString curr, double volume);
double get_marketcap(QString curr);
void set_marketcap(QString curr, double marketcap);
void setPeers(int peers);
int getPeers();
@ -165,9 +165,9 @@ private:
double zecPrice = 0.0;
double fiat_price = 0.0;
unsigned int btcPrice = 0;
std::map<std::string, double> prices;
std::map<std::string, double> volumes;
std::map<std::string, double> marketcaps;
std::map<QString, double> prices;
std::map<QString, double> volumes;
std::map<QString, double> marketcaps;
};
#endif // SETTINGS_H

2
src/version.h

@ -1 +1 @@
#define APP_VERSION "0.9.1"
#define APP_VERSION "0.9.2"

4
src/websockets.cpp

@ -784,9 +784,9 @@ void AppDataServer::processSendTx(QJsonObject sendTx, MainWindow* mainwindow, st
return;
}
json params = json::array();
QJsonArray params;
mainwindow->getRPC()->fillTxJsonParams(params, tx);
std::cout << std::setw(2) << params << std::endl;
//std::cout << std::setw(2) << params << std::endl;
// And send the Tx
mainwindow->getRPC()->executeTransaction(tx,

Loading…
Cancel
Save