Browse Source

Merge pull request #1 from adityapk00/master

merge latest updates
pull/19/head
Denio 5 years ago
committed by GitHub
parent
commit
a69e5532fe
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 82
      README.md
  2. 116
      lib/Cargo.lock
  3. 2
      lib/Cargo.toml
  4. 12
      lib/src/lib.rs
  5. 2
      lib/zecwalletlitelib.h
  6. 15
      src/connection.cpp
  7. 265
      src/controller.cpp
  8. 25
      src/controller.h
  9. 4
      src/datamodel.cpp
  10. 5
      src/datamodel.h
  11. 457
      src/liteinterface.cpp
  12. 45
      src/liteinterface.h
  13. 36
      src/main.cpp
  14. 230
      src/mainwindow.cpp
  15. 6
      src/mainwindow.h
  16. 23
      src/mainwindow.ui
  17. 12
      src/recurring.cpp
  18. 15
      src/sendtab.cpp
  19. 115
      src/senttxstore.cpp
  20. 20
      src/senttxstore.h
  21. 192
      src/turnstileprogress.ui
  22. 137
      src/txtablemodel.cpp
  23. 10
      src/txtablemodel.h
  24. 37
      src/validateaddress.cpp
  25. 23
      src/validateaddress.h
  26. 85
      src/validateaddress.ui
  27. 20
      src/websockets.cpp
  28. 170
      src/zboard.ui
  29. 7
      zecwallet-lite.pro

82
README.md

@ -1,88 +1,20 @@
ZecWallet is a z-Addr first, Sapling compatible wallet and full node for zcashd that runs on Linux, Windows and macOS.
![Screenshot](docs/screenshot-main.png?raw=true)
![Screenshots](docs/screenshot-sub.png?raw=true)
# Installation
Head over to the releases page and grab the latest installers or binary. https://github.com/ZcashFoundation/zecwallet/releases
### Linux
If you are on Debian/Ubuntu, please download the `.deb` package and install it.
```
sudo dpkg -i linux-deb-zecwallet-v0.7.9.deb
sudo apt install -f
```
Or you can download and run the binaries directly.
```
tar -xvf zecwallet-v0.7.9.tar.gz
./zecwallet-v0.7.9/zecwallet
```
### Windows
Download and run the `.msi` installer and follow the prompts. Alternately, you can download the release binary, unzip it and double click on `zecwallet.exe` to start.
### macOS
Double-click on the `.dmg` file to open it, and drag `zecwallet` on to the Applications link to install.
## zcashd
ZecWallet needs a Zcash node running zcashd. If you already have a zcashd node running, ZecWallet will connect to it.
If you don't have one, ZecWallet will start its embedded zcashd node.
Additionally, if this is the first time you're running ZecWallet or a zcashd daemon, ZecWallet will download the zcash params (~1.7 GB) and configure `zcash.conf` for you.
Pass `--no-embedded` to disable the embedded zcashd and force ZecWallet to connect to an external node.
ZecWallet-lite is z-Addr first, Sapling compatible wallet lightwallet for Zcash
## Compiling from source
ZecWallet is written in C++ 14, and can be compiled with g++/clang++/visual c++. It also depends on Qt5, which you can get from [here](https://www.qt.io/download). Note that if you are compiling from source, you won't get the embedded zcashd by default. You can either run an external zcashd, or compile zcashd as well.
See detailed build instructions [on the wiki](https://github.com/ZcashFoundation/zecwallet/wiki/Compiling-from-source-code)
* ZecWallet is written in C++ 14, and can be compiled with g++/clang++/visual c++.
* It also depends on Qt5, which you can get from [here](https://www.qt.io/download).
* You'll need Rust v1.37 +
### Building on Linux
```
git clone https://github.com/ZcashFoundation/zecwallet.git
git clone https://github.com/adityapk/zecwallet-lite.git
cd zecwallet
/path/to/qt5/bin/qmake zec-qt-wallet.pro CONFIG+=debug
/path/to/qt5/bin/qmake zecwallet-lite.pro CONFIG+=debug
make -j$(nproc)
./zecwallet
```
### Building on Windows
You need Visual Studio 2017 (The free C++ Community Edition works just fine).
From the VS Tools command prompt
```
git clone https://github.com/ZcashFoundation/zecwallet.git
cd zecwallet
c:\Qt5\bin\qmake.exe zec-qt-wallet.pro -spec win32-msvc CONFIG+=debug
nmake
debug\zecwallet.exe
```
To create the Visual Studio project files so you can compile and run from Visual Studio:
```
c:\Qt5\bin\qmake.exe zec-qt-wallet.pro -tp vc CONFIG+=debug
```
### Building on macOS
You need to install the Xcode app or the Xcode command line tools first, and then install Qt.
```
git clone https://github.com/ZcashFoundation/zecwallet.git
cd zecwallet
/path/to/qt5/bin/qmake zec-qt-wallet.pro CONFIG+=debug
make
./zecwallet.app/Contents/MacOS/zecwallet
```
### [Troubleshooting Guide & FAQ](https://github.com/ZcashFoundation/zecwallet/wiki/Troubleshooting-&-FAQ)
Please read the [troubleshooting guide](https://docs.zecwallet.co/troubleshooting/) for common problems and solutions.
For support or other questions, tweet at [@zecwallet](https://twitter.com/zecwallet) or [file an issue](https://github.com/ZcashFoundation/zecwallet/issues).
Right now, you'll also need to run `lightwalletd` on your local machine for Zecwallet to connect to.
_PS: ZecWallet is NOT an official wallet, and is not affiliated with the Electric Coin Company in any way._

116
lib/Cargo.lock

@ -64,22 +64,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "backtrace"
version = "0.3.38"
version = "0.3.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
"backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "backtrace-sys"
version = "0.1.31"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -125,7 +125,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bitflags"
version = "1.2.0"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -214,7 +214,7 @@ dependencies = [
[[package]]
name = "cc"
version = "1.0.45"
version = "1.0.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -227,7 +227,7 @@ name = "chrono"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
@ -238,7 +238,7 @@ name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -351,7 +351,7 @@ version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -371,7 +371,7 @@ name = "failure"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)",
"backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
"failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -426,7 +426,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"miniz_oxide 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -457,7 +457,7 @@ name = "fuchsia-zircon"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -494,7 +494,7 @@ version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -517,7 +517,7 @@ dependencies = [
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
"http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
"http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
"indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -558,7 +558,7 @@ dependencies = [
[[package]]
name = "http"
version = "0.1.18"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
@ -573,7 +573,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
"http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
"http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -582,7 +582,7 @@ name = "http-connection"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
"http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -604,7 +604,7 @@ name = "iovec"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -644,7 +644,7 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.62"
version = "0.2.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -693,7 +693,7 @@ dependencies = [
"flate2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log-mdc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
@ -731,7 +731,7 @@ dependencies = [
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
@ -745,7 +745,7 @@ version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -771,7 +771,7 @@ version = "0.2.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -812,7 +812,7 @@ name = "num_cpus"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -871,7 +871,7 @@ name = "parking_lot_core"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
@ -885,7 +885,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1010,8 +1010,8 @@ name = "qtlib"
version = "0.1.0"
dependencies = [
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"zecwalletlitelib 0.1.0 (git+https://github.com/adityapk00/zecwallet-lite-lib)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"zecwalletlitelib 0.1.0 (git+https://github.com/adityapk00/zecwallet-light-cli?rev=e3a0fd2dea59c0cf6434148bf77fef84830cce02)",
]
[[package]]
@ -1046,7 +1046,7 @@ version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1064,7 +1064,7 @@ version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1138,7 +1138,7 @@ name = "rand_jitter"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1150,7 +1150,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1227,9 +1227,9 @@ name = "ring"
version = "0.14.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1312,7 +1312,7 @@ dependencies = [
[[package]]
name = "ryu"
version = "1.0.1"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -1347,7 +1347,7 @@ name = "secp256k1"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -1393,7 +1393,7 @@ version = "1.0.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"ryu 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1517,7 +1517,7 @@ version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
"remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1529,7 +1529,7 @@ name = "thread-id"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1539,7 +1539,7 @@ name = "time"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1750,7 +1750,7 @@ dependencies = [
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
"iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)",
"mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1807,7 +1807,7 @@ dependencies = [
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
"h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
"http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
"http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
"http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1834,7 +1834,7 @@ dependencies = [
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
"h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
"http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
"http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-connect 0.1.0 (git+https://github.com/carllerche/tokio-connect)",
"tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1858,7 +1858,7 @@ version = "0.1.0"
source = "git+https://github.com/tower-rs/tower-http#cb393c933f5167f934abde9d4f902e44d9ea2d50"
dependencies = [
"futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
"http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
"http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
"http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"http-connection 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1904,7 +1904,7 @@ version = "0.1.0"
source = "git+https://github.com/tower-rs/tower-http#cb393c933f5167f934abde9d4f902e44d9ea2d50"
dependencies = [
"futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
"http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
"http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
"tower-service 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2069,7 +2069,7 @@ version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -2182,7 +2182,7 @@ dependencies = [
[[package]]
name = "zecwalletlitelib"
version = "0.1.0"
source = "git+https://github.com/adityapk00/zecwallet-lite-lib#93830f9e99651a7845c15dc992eab9941d251355"
source = "git+https://github.com/adityapk00/zecwallet-light-cli?rev=e3a0fd2dea59c0cf6434148bf77fef84830cce02#e3a0fd2dea59c0cf6434148bf77fef84830cce02"
dependencies = [
"base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bellman 0.1.0 (git+https://github.com/adityapk00/librustzcash.git?rev=188537ea025fcb7fbdfc11266f307a084a5451e4)",
@ -2192,7 +2192,7 @@ dependencies = [
"ff 0.4.0 (git+https://github.com/adityapk00/librustzcash.git?rev=188537ea025fcb7fbdfc11266f307a084a5451e4)",
"futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
"hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
"http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
"json 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2233,14 +2233,14 @@ dependencies = [
"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9"
"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"
"checksum backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "690a62be8920ccf773ee00ef0968649b0e724cda8bd5b12286302b4ae955fdf5"
"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b"
"checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea"
"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491"
"checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83"
"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
"checksum bech32 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0089c35ab7c6f2bc55ab23f769913f0ac65b1023e7e74638a1f43128dd5df2"
"checksum bellman 0.1.0 (git+https://github.com/adityapk00/librustzcash.git?rev=188537ea025fcb7fbdfc11266f307a084a5451e4)" = "<none>"
"checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f"
"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2"
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
"checksum blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182"
"checksum blake2s_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "979da0ce13c897d6be19e005ea77ac12b0fea0157aeeee7feb8c49f91386f0ea"
"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
@ -2251,7 +2251,7 @@ dependencies = [
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c"
"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101"
"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be"
"checksum cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)" = "0213d356d3c4ea2c18c40b037c3be23cd639825c18f25ee670ac7813beeef99c"
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
"checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
@ -2293,7 +2293,7 @@ dependencies = [
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
"checksum hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695"
"checksum http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "372bcb56f939e449117fb0869c2e8fd8753a8223d92a172c6e808cf123a5b6e4"
"checksum http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "d7e06e336150b178206af098a055e3621e8336027e2b4d126bda0bc64824baaf"
"checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d"
"checksum http-connection 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f6080cea47f7371d4da9a46dd52787c598ce93886393e400bc178f9039bac27"
"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
@ -2304,7 +2304,7 @@ dependencies = [
"checksum json 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3ca41abbeb7615d56322a984e63be5e5d0a117dfaca86c14393e32a762ccac1"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8"
"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc"
@ -2377,7 +2377,7 @@ dependencies = [
"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
"checksum rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f271e3552cd835fa28c541c34a7e8fdd8cdff09d77fe4eb8f6c42e87a11b096e"
"checksum ryu 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "19d2271fa48eaf61e53cc88b4ad9adcbafa2d512c531e7fadb6dc11a4d3656c5"
"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
"checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421"
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
@ -2467,4 +2467,4 @@ dependencies = [
"checksum zcash_client_backend 0.0.0 (git+https://github.com/adityapk00/librustzcash.git?rev=188537ea025fcb7fbdfc11266f307a084a5451e4)" = "<none>"
"checksum zcash_primitives 0.0.0 (git+https://github.com/adityapk00/librustzcash.git?rev=188537ea025fcb7fbdfc11266f307a084a5451e4)" = "<none>"
"checksum zcash_proofs 0.0.0 (git+https://github.com/adityapk00/librustzcash.git?rev=188537ea025fcb7fbdfc11266f307a084a5451e4)" = "<none>"
"checksum zecwalletlitelib 0.1.0 (git+https://github.com/adityapk00/zecwallet-lite-lib)" = "<none>"
"checksum zecwalletlitelib 0.1.0 (git+https://github.com/adityapk00/zecwallet-light-cli?rev=e3a0fd2dea59c0cf6434148bf77fef84830cce02)" = "<none>"

2
lib/Cargo.toml

@ -11,4 +11,4 @@ crate-type = ["staticlib"]
[dependencies]
libc = "0.2.58"
lazy_static = "1.4.0"
zecwalletlitelib = { git = "https://github.com/adityapk00/zecwallet-lite-lib" }
zecwalletlitelib = { git = "https://github.com/adityapk00/zecwallet-light-cli", rev = "e3a0fd2dea59c0cf6434148bf77fef84830cce02" }

12
lib/src/lib.rs

@ -49,13 +49,19 @@ pub extern fn litelib_initialze(dangerous: bool, server: *const c_char) -> *mut
}
#[no_mangle]
pub extern fn litelib_execute(cmd: *const c_char) -> *mut c_char {
pub extern fn litelib_execute(cmd: *const c_char, args: *const c_char) -> *mut c_char {
let cmd_str = unsafe {
assert!(!cmd.is_null());
CStr::from_ptr(cmd).to_string_lossy().into_owned()
};
let arg_str = unsafe {
assert!(!args.is_null());
CStr::from_ptr(args).to_string_lossy().into_owned()
};
let resp: String;
{
let lc = LIGHTCLIENT.lock().unwrap();
@ -65,7 +71,9 @@ pub extern fn litelib_execute(cmd: *const c_char) -> *mut c_char {
return e_str.into_raw();
}
resp = commands::do_user_command(&cmd_str, &vec![], lc.borrow().as_ref().unwrap()).clone();
let args = if arg_str.is_empty() { vec![] } else { vec![arg_str.as_ref()] };
resp = commands::do_user_command(&cmd_str, &args, lc.borrow().as_ref().unwrap()).clone();
};
let c_str = CString::new(resp.as_bytes()).unwrap();

2
lib/zecwalletlitelib.h

@ -6,7 +6,7 @@ extern "C"{
#endif
extern char * litelib_initialze (bool dangerous, const char* server);
extern char * litelib_execute (const char* s);
extern char * litelib_execute (const char* s, const char* args);
extern void litelib_rust_free_string (char* s);
#ifdef __cplusplus

15
src/connection.cpp

@ -100,7 +100,7 @@ void ConnectionLoader::showError(QString explanation) {
* Connection, Executor and Callback Class
************************************************************************************/
void Executor::run() {
char* resp = litelib_execute(this->cmd.toStdString().c_str());
char* resp = litelib_execute(this->cmd.toStdString().c_str(), this->args.toStdString().c_str());
// Copy the string, since we need to return this back to rust
char* resp_copy = new char[strlen(resp) + 1];
@ -111,14 +111,17 @@ void Executor::run() {
memset(resp_copy, '-', strlen(resp_copy));
delete[] resp_copy;
qDebug() << "Reply=" << reply;
qDebug() << "Reply=" << reply;
auto parsed = json::parse(reply.toStdString().c_str(), nullptr, false);
const bool isGuiThread =
QThread::currentThread() == QCoreApplication::instance()->thread();
if (parsed.is_discarded() || parsed.is_null()) {
emit handleError(reply);
} else {
const bool isGuiThread =
QThread::currentThread() == QCoreApplication::instance()->thread();
qDebug() << "executing RPC: isGUI=" << isGuiThread;
emit responseReady(parsed);
emit responseReady(parsed);
}
}

265
src/controller.cpp

@ -2,7 +2,6 @@
#include "addressbook.h"
#include "settings.h"
#include "senttxstore.h"
#include "version.h"
#include "websockets.h"
@ -40,14 +39,6 @@ Controller::Controller(MainWindow* main) {
});
timer->start(Settings::updateSpeed);
// Set up the timer to watch for tx status
txTimer = new QTimer(main);
QObject::connect(txTimer, &QTimer::timeout, [=]() {
watchTxStatus();
});
// Start at every 10s. When an operation is pending, this will change to every second
txTimer->start(Settings::updateSpeed);
// Create the data model
model = new DataModel();
@ -95,10 +86,8 @@ void Controller::setConnection(Connection* c) {
// Build the RPC JSON Parameters for this tx
void Controller::fillTxJsonParams(json& params, Tx tx) {
Q_ASSERT(params.is_array());
// Get all the addresses and amounts
json allRecepients = json::array();
void Controller::fillTxJsonParams(json& allRecepients, Tx tx) {
Q_ASSERT(allRecepients.is_array());
// For each addr/amt/memo, construct the JSON and also build the confirm dialog box
for (int i=0; i < tx.toAddrs.size(); i++) {
@ -107,24 +96,18 @@ void Controller::fillTxJsonParams(json& params, Tx tx) {
// Construct the JSON params
json rec = json::object();
rec["address"] = toAddr.addr.toStdString();
// 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();
if (Settings::isZAddress(toAddr.addr) && !toAddr.encodedMemo.trimmed().isEmpty())
rec["memo"] = toAddr.encodedMemo.toStdString();
rec["amount"] = toAddr.amount;
if (Settings::isZAddress(toAddr.addr) && !toAddr.memo.trimmed().isEmpty())
rec["memo"] = toAddr.memo.toStdString();
allRecepients.push_back(rec);
}
// Add sender
params.push_back(tx.fromAddr.toStdString());
params.push_back(allRecepients);
// Add fees if custom fees are allowed.
if (Settings::getInstance()->getAllowCustomFees()) {
params.push_back(1); // minconf
params.push_back(tx.fee);
}
// // Add fees if custom fees are allowed.
// if (Settings::getInstance()->getAllowCustomFees()) {
// params.push_back(1); // minconf
// params.push_back(tx.fee);
// }
}
@ -143,9 +126,7 @@ void Controller::noConnection() {
// Clear Transactions table.
QList<TransactionItem> emptyTxs;
transactionsTableModel->addTData(emptyTxs);
transactionsTableModel->addZRecvData(emptyTxs);
transactionsTableModel->addZSentData(emptyTxs);
transactionsTableModel->replaceData(emptyTxs);
// Clear balances
ui->balSheilded->setText("");
@ -160,28 +141,6 @@ void Controller::noConnection() {
ui->inputsCombo->clear();
}
// Refresh received z txs by calling z_listreceivedbyaddress/gettransaction
void Controller::refreshReceivedZTrans(QList<QString> zaddrs) {
if (!zrpc->haveConnection())
return noConnection();
// We'll only refresh the received Z txs if settings allows us.
if (!Settings::getInstance()->getSaveZtxs()) {
QList<TransactionItem> emptylist;
transactionsTableModel->addZRecvData(emptylist);
return;
}
zrpc->fetchReceivedZTrans(zaddrs,
[=] (QString addr) {
model->markAddressUsed(addr);
},
[=] (QList<TransactionItem> txdata) {
transactionsTableModel->addZRecvData(txdata);
}
);
}
/// This will refresh all the balance data from zcashd
void Controller::refresh(bool force) {
if (!zrpc->haveConnection())
@ -190,7 +149,6 @@ void Controller::refresh(bool force) {
getInfoThenRefresh(force);
}
void Controller::getInfoThenRefresh(bool force) {
if (!zrpc->haveConnection())
return noConnection();
@ -217,6 +175,7 @@ void Controller::getInfoThenRefresh(bool force) {
static int lastBlock = 0;
int curBlock = reply["latest_block_height"].get<json::number_integer_t>();
model->setLatestBlock(curBlock);
//int version = reply["version"].get<json::string_t>();
int version = 1;
Settings::getInstance()->setZcashdVersion(version);
@ -254,31 +213,30 @@ void Controller::refreshAddresses() {
return noConnection();
auto newzaddresses = new QList<QString>();
auto newtaddresses = new QList<QString>();
zrpc->fetchZAddresses([=] (json reply) {
for (auto& it : reply.get<json::array_t>()) {
zrpc->fetchAddresses([=] (json reply) {
auto zaddrs = reply["z_addresses"].get<json::array_t>();
for (auto& it : zaddrs) {
auto addr = QString::fromStdString(it.get<json::string_t>());
newzaddresses->push_back(addr);
}
model->replaceZaddresses(newzaddresses);
// Refresh the sent and received txs from all these z-addresses
refreshSentZTrans();
refreshReceivedZTrans(model->getAllZAddresses());
});
auto newtaddresses = new QList<QString>();
zrpc->fetchTAddresses([=] (json reply) {
for (auto& it : reply.get<json::array_t>()) {
auto taddrs = reply["t_addresses"].get<json::array_t>();
for (auto& it : taddrs) {
auto addr = QString::fromStdString(it.get<json::string_t>());
if (Settings::isTAddress(addr))
newtaddresses->push_back(addr);
}
model->replaceTaddresses(newtaddresses);
// Refresh the sent and received txs from all these z-addresses
refreshTransactions();
});
}
// Function to create the data model and update the views, used below.
@ -361,77 +319,80 @@ void Controller::refreshTransactions() {
return noConnection();
zrpc->fetchTransactions([=] (json reply) {
QList<TransactionItem> txdata;
QList<TransactionItem> txdata;
for (auto& it : reply.get<json::array_t>()) {
double fee = 0;
if (!it["fee"].is_null()) {
fee = it["fee"].get<json::number_float_t>();
}
QString address;
qint64 total_amount;
QList<TransactionItemDetail> items;
// First, check if there's outgoing metadata
if (!it["outgoing_metadata"].is_null()) {
for (auto o: it["outgoing_metadata"].get<json::array_t>()) {
QString address = QString::fromStdString(o["address"]);
qint64 amount = -1 * o["value"].get<json::number_integer_t>(); // Sent items are -ve
QString memo;
if (!o["memo"].is_null()) {
memo = QString::fromStdString(o["memo"]);
}
QString address = (it["address"].is_null() ? "" : QString::fromStdString(it["address"]));
items.push_back(TransactionItemDetail{address, amount, memo});
total_amount += amount;
}
TransactionItem tx{
QString::fromStdString(it["category"]),
(qint64)it["time"].get<json::number_unsigned_t>(),
address,
QString::fromStdString(it["txid"]),
it["amount"].get<json::number_float_t>() + fee,
static_cast<long>(it["confirmations"].get<json::number_unsigned_t>()),
"", "" };
if (items.length() == 1) {
address = items[0].address;
} else {
address = "(Multiple)";
}
txdata.push_back(tx);
if (!address.isEmpty())
txdata.push_back(TransactionItem{
"Sent",
it["datetime"].get<json::number_unsigned_t>(),
address,
QString::fromStdString(it["txid"]),
model->getLatestBlock() - it["block_height"].get<json::number_unsigned_t>(),
items
});
} else {
// Incoming Transaction
address = (it["address"].is_null() ? "" : QString::fromStdString(it["address"]));
model->markAddressUsed(address);
items.push_back(TransactionItemDetail{
address,
it["amount"].get<json::number_integer_t>(),
""
});
TransactionItem tx{
"Receive",
it["datetime"].get<json::number_unsigned_t>(),
address,
QString::fromStdString(it["txid"]),
model->getLatestBlock() - it["block_height"].get<json::number_unsigned_t>(),
items
};
txdata.push_back(tx);
}
}
// Update model data, which updates the table view
transactionsTableModel->addTData(txdata);
transactionsTableModel->replaceData(txdata);
});
}
// Read sent Z transactions from the file.
void Controller::refreshSentZTrans() {
if (!zrpc->haveConnection())
return noConnection();
auto sentZTxs = SentTxStore::readSentTxFile();
// If there are no sent z txs, then empty the table.
// This happens when you clear history.
if (sentZTxs.isEmpty()) {
transactionsTableModel->addZSentData(sentZTxs);
return;
}
QList<QString> txids;
for (auto sentTx: sentZTxs) {
txids.push_back(sentTx.txid);
}
// Look up all the txids to get the confirmation count for them.
zrpc->fetchReceivedTTrans(txids, sentZTxs, [=](auto newSentZTxs) {
transactionsTableModel->addZSentData(newSentZTxs);
});
}
void Controller::addNewTxToWatch(const QString& newOpid, WatchedTx wtx) {
watchingOps.insert(newOpid, wtx);
watchTxStatus();
}
/**
* Execute a transaction with the standard UI. i.e., standard status bar message and standard error
* handling
*/
void Controller::executeStandardUITransaction(Tx tx) {
executeTransaction(tx,
[=] (QString opid) {
ui->statusBar->showMessage(QObject::tr("Computing Tx: ") % opid);
},
[=] (QString, QString txid) {
executeTransaction(tx,
[=] (QString txid) {
ui->statusBar->showMessage(Settings::txidStatusMessage + " " + txid);
},
[=] (QString opid, QString errStr) {
@ -448,20 +409,20 @@ void Controller::executeStandardUITransaction(Tx tx) {
// Execute a transaction!
void Controller::executeTransaction(Tx tx,
const std::function<void(QString opid)> submitted,
const std::function<void(QString opid, QString txid)> computed,
const std::function<void(QString opid, QString errStr)> error) {
const std::function<void(QString txid)> submitted,
const std::function<void(QString txid, QString errStr)> error) {
// First, create the json params
json params = json::array();
fillTxJsonParams(params, tx);
std::cout << std::setw(2) << params << std::endl;
zrpc->sendZTransaction(params, [=](const json& reply) {
QString opid = QString::fromStdString(reply.get<json::string_t>());
zrpc->sendTransaction(QString::fromStdString(params.dump()), [=](const json& reply) {
if (reply["result"].is_null() || reply["result"] != "success") {
error("", "Couldn't understand Response: " + QString::fromStdString(reply.dump()));
}
// And then start monitoring the transaction
addNewTxToWatch( opid, WatchedTx { opid, tx, computed, error} );
submitted(opid);
QString txid = QString::fromStdString(reply["txid"].get<json::string_t>());
submitted(txid);
},
[=](QString errStr) {
error("", errStr);
@ -469,58 +430,6 @@ void Controller::executeTransaction(Tx tx,
}
void Controller::watchTxStatus() {
if (!zrpc->haveConnection())
return noConnection();
zrpc->fetchOpStatus([=] (const json& reply) {
// There's an array for each item in the status
for (auto& it : reply.get<json::array_t>()) {
// 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"]);
if (watchingOps.contains(id)) {
// And if it ended up successful
QString status = QString::fromStdString(it["status"]);
main->loadingLabel->setVisible(false);
if (status == "success") {
auto txid = QString::fromStdString(it["result"]["txid"]);
SentTxStore::addToSentTx(watchingOps[id].tx, txid);
auto wtx = watchingOps[id];
watchingOps.remove(id);
wtx.completed(id, txid);
// 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 wtx = watchingOps[id];
watchingOps.remove(id);
wtx.error(id, errorMsg);
}
}
if (watchingOps.isEmpty()) {
txTimer->start(Settings::updateSpeed);
} else {
txTimer->start(Settings::quickUpdateSpeed);
}
}
// If there is some op that we are watching, then show the loading bar, otherwise hide it
if (watchingOps.empty()) {
main->loadingLabel->setVisible(false);
} else {
main->loadingLabel->setVisible(true);
main->loadingLabel->setToolTip(QString::number(watchingOps.size()) + QObject::tr(" tx computing. This can take several minutes."));
}
});
}
void Controller::checkForUpdate(bool silent) {
if (!zrpc->haveConnection())
return noConnection();

25
src/controller.h

@ -50,17 +50,11 @@ public:
void executeStandardUITransaction(Tx tx);
void executeTransaction(Tx tx,
const std::function<void(QString opid)> submitted,
const std::function<void(QString opid, QString txid)> computed,
const std::function<void(QString opid, QString errStr)> error);
const std::function<void(QString txid)> submitted,
const std::function<void(QString txid, QString errStr)> error);
void fillTxJsonParams(json& params, Tx tx);
void watchTxStatus();
const QMap<QString, WatchedTx> getWatchingTxns() { return watchingOps; }
void addNewTxToWatch(const QString& newOpid, WatchedTx wtx);
const TxTableModel* getTransactionsModel() { return transactionsTableModel; }
void shutdownZcashd();
@ -70,14 +64,11 @@ public:
void createNewZaddr(bool sapling, const std::function<void(json)>& cb) { zrpc->createNewZaddr(sapling, cb); }
void createNewTaddr(const std::function<void(json)>& cb) { zrpc->createNewTaddr(cb); }
void validateAddress(QString address, const std::function<void(json)>& cb) { zrpc->validateAddress(address, cb); }
void fetchPrivKey(QString addr, const std::function<void(json)>& cb) { zrpc->fetchPrivKey(addr, cb); }
void fetchAllPrivKeys(const std::function<void(json)> cb) { zrpc->fetchAllPrivKeys(cb); }
void fetchZPrivKey(QString addr, const std::function<void(json)>& cb) { zrpc->fetchZPrivKey(addr, cb); }
void fetchTPrivKey(QString addr, const std::function<void(json)>& cb) { zrpc->fetchTPrivKey(addr, cb); }
void fetchAllPrivKeys(const std::function<void(QList<QPair<QString, QString>>)> cb) { zrpc->fetchAllPrivKeys(cb); }
void importZPrivKey(QString addr, bool rescan, const std::function<void(json)>& cb) { zrpc->importZPrivKey(addr, rescan, cb); }
void importTPrivKey(QString addr, bool rescan, const std::function<void(json)>& cb) { zrpc->importTPrivKey(addr, rescan, cb); }
// void importZPrivKey(QString addr, bool rescan, const std::function<void(json)>& cb) { zrpc->importZPrivKey(addr, rescan, cb); }
// void importTPrivKey(QString addr, bool rescan, const std::function<void(json)>& cb) { zrpc->importTPrivKey(addr, rescan, cb); }
QString getDefaultSaplingAddress();
QString getDefaultTAddress();
@ -86,8 +77,6 @@ private:
void refreshBalances();
void refreshTransactions();
void refreshSentZTrans();
void refreshReceivedZTrans(QList<QString> zaddresses);
bool processUnspent (const json& reply, QMap<QString, qint64>* newBalances, QList<UnspentOutput>* newUtxos);
void updateUI (bool anyUnconfirmed);
@ -96,8 +85,6 @@ private:
QProcess* ezcashd = nullptr;
QMap<QString, WatchedTx> watchingOps;
TxTableModel* transactionsTableModel = nullptr;
BalancesTableModel* balancesTableModel = nullptr;

4
src/datamodel.cpp

@ -23,6 +23,10 @@ DataModel::~DataModel() {
delete taddresses;
}
void DataModel::setLatestBlock(int blockHeight) {
this->latestBlock = blockHeight;
}
void DataModel::replaceZaddresses(QList<QString>* newZ) {
QWriteLocker locker(lock);
Q_ASSERT(newZ);

5
src/datamodel.h

@ -23,6 +23,9 @@ public:
void markAddressUsed(QString address);
void setLatestBlock(int blockHeight);
int getLatestBlock() { return this->latestBlock; }
const QList<QString> getAllZAddresses() { QReadLocker locker(lock); return *zaddresses; }
const QList<QString> getAllTAddresses() { QReadLocker locker(lock); return *taddresses; }
const QList<UnspentOutput> getUTXOs() { QReadLocker locker(lock); return *utxos; }
@ -33,7 +36,7 @@ public:
DataModel();
~DataModel();
private:
int latestBlock;
QList<UnspentOutput>* utxos = nullptr;
QMap<QString, qint64>* balances = nullptr;

457
src/liteinterface.cpp

@ -20,148 +20,70 @@ bool LiteInterface::haveConnection() {
return conn != nullptr;
}
void LiteInterface::fetchTAddresses(const std::function<void(json)>& cb) {
void LiteInterface::fetchAddresses(const std::function<void(json)>& cb) {
if (conn == nullptr)
return;
// json payload = {
// {"jsonrpc", "1.0"},
// {"id", "someid"},
// {"method", "getaddressesbyaccount"},
// {"params", {""}}
// };
// conn->doRPCWithDefaultErrorHandling(payload, cb);
conn->doRPCWithDefaultErrorHandling("addresses", "", cb);
}
void LiteInterface::fetchZAddresses(const std::function<void(json)>& cb) {
if (conn == nullptr)
return;
// json payload = {
// {"jsonrpc", "1.0"},
// {"id", "someid"},
// {"method", "z_listaddresses"},
// };
// conn->doRPCWithDefaultErrorHandling(payload, cb);
}
void LiteInterface::fetchUnspent(const std::function<void(json)>& cb) {
if (conn == nullptr)
return;
conn->doRPCWithDefaultErrorHandling("notes", "", cb);
// json payload = {
// {"jsonrpc", "1.0"},
// {"id", "someid"},
// {"method", "listunspent"},
// {"params", {0}} // Get UTXOs with 0 confirmations as well.
// };
// conn->doRPCWithDefaultErrorHandling(payload, cb);
}
void LiteInterface::createNewZaddr(bool sapling, const std::function<void(json)>& cb) {
void LiteInterface::createNewZaddr(bool, const std::function<void(json)>& cb) {
if (conn == nullptr)
return;
// json payload = {
// {"jsonrpc", "1.0"},
// {"id", "someid"},
// {"method", "z_getnewaddress"},
// {"params", { sapling ? "sapling" : "sprout" }},
// };
// conn->doRPCWithDefaultErrorHandling(payload, cb);
conn->doRPCWithDefaultErrorHandling("new", "z", cb);
}
void LiteInterface::createNewTaddr(const std::function<void(json)>& cb) {
if (conn == nullptr)
return;
// json payload = {
// {"jsonrpc", "1.0"},
// {"id", "someid"},
// {"method", "getnewaddress"},
// };
// conn->doRPCWithDefaultErrorHandling(payload, cb);
conn->doRPCWithDefaultErrorHandling("new", "t", cb);
}
void LiteInterface::fetchZPrivKey(QString addr, const std::function<void(json)>& cb) {
void LiteInterface::fetchPrivKey(QString addr, const std::function<void(json)>& cb) {
if (conn == nullptr)
return;
// json payload = {
// {"jsonrpc", "1.0"},
// {"id", "someid"},
// {"method", "z_exportkey"},
// {"params", { addr.toStdString() }},
// };
// conn->doRPCWithDefaultErrorHandling(payload, cb);
conn->doRPCWithDefaultErrorHandling("export", addr, cb);
}
void LiteInterface::fetchTPrivKey(QString addr, const std::function<void(json)>& cb) {
if (conn == nullptr)
return;
// void LiteInterface::importZPrivKey(QString addr, bool rescan, const std::function<void(json)>& cb) {
// if (conn == nullptr)
// return;
// json payload = {
// {"jsonrpc", "1.0"},
// {"id", "someid"},
// {"method", "dumpprivkey"},
// {"params", { addr.toStdString() }},
// };
// // json payload = {
// // {"jsonrpc", "1.0"},
// // {"id", "someid"},
// // {"method", "z_importkey"},
// // {"params", { addr.toStdString(), (rescan? "yes" : "no") }},
// // };
// conn->doRPCWithDefaultErrorHandling(payload, cb);
}
// // conn->doRPCWithDefaultErrorHandling(payload, cb);
// }
void LiteInterface::importZPrivKey(QString addr, bool rescan, const std::function<void(json)>& cb) {
if (conn == nullptr)
return;
// json payload = {
// {"jsonrpc", "1.0"},
// {"id", "someid"},
// {"method", "z_importkey"},
// {"params", { addr.toStdString(), (rescan? "yes" : "no") }},
// };
// conn->doRPCWithDefaultErrorHandling(payload, cb);
}
// void LiteInterface::importTPrivKey(QString addr, bool rescan, const std::function<void(json)>& cb) {
// if (conn == nullptr)
// return;
void LiteInterface::importTPrivKey(QString addr, bool rescan, const std::function<void(json)>& cb) {
if (conn == nullptr)
return;
// json payload = {
// {"jsonrpc", "1.0"},
// {"id", "someid"},
// {"method", "importprivkey"},
// {"params", { addr.toStdString(), (rescan? "yes" : "no") }},
// };
// conn->doRPCWithDefaultErrorHandling(payload, cb);
}
void LiteInterface::validateAddress(QString address, const std::function<void(json)>& cb) {
if (conn == nullptr)
return;
// QString method = Settings::isZAddress(address) ? "z_validateaddress" : "validateaddress";
// json payload = {
// {"jsonrpc", "1.0"},
// {"id", "someid"},
// {"method", method.toStdString() },
// {"params", { address.toStdString() } },
// };
// // json payload = {
// // {"jsonrpc", "1.0"},
// // {"id", "someid"},
// // {"method", "importprivkey"},
// // {"params", { addr.toStdString(), (rescan? "yes" : "no") }},
// // };
// conn->doRPCWithDefaultErrorHandling(payload, cb);
}
// // conn->doRPCWithDefaultErrorHandling(payload, cb);
// }
void LiteInterface::fetchBalance(const std::function<void(json)>& cb) {
if (conn == nullptr)
@ -174,34 +96,15 @@ void LiteInterface::fetchTransactions(const std::function<void(json)>& cb) {
if (conn == nullptr)
return;
// json payload = {
// {"jsonrpc", "1.0"},
// {"id", "someid"},
// {"method", "listtransactions"}
// };
// conn->doRPCWithDefaultErrorHandling(payload, cb);
conn->doRPCWithDefaultErrorHandling("list", "", cb);
}
void LiteInterface::sendZTransaction(json params, const std::function<void(json)>& cb,
void LiteInterface::sendTransaction(QString params, const std::function<void(json)>& cb,
const std::function<void(QString)>& err) {
if (conn == nullptr)
return;
// json 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"]));
// } else {
// err(reply->errorString());
// }
// });
conn->doRPC("send", params, cb, err);
}
void LiteInterface::fetchInfo(const std::function<void(json)>& cb,
@ -212,309 +115,17 @@ void LiteInterface::fetchInfo(const std::function<void(json)>& cb,
conn->doRPC("info", "", cb, err);
}
void LiteInterface::fetchBlockchainInfo(const std::function<void(json)>& cb) {
if (conn == nullptr)
return;
// json payload = {
// {"jsonrpc", "1.0"},
// {"id", "someid"},
// {"method", "getblockchaininfo"}
// };
// conn->doRPCIgnoreError(payload, cb);
}
void LiteInterface::fetchNetSolOps(const std::function<void(qint64)> cb) {
if (conn == nullptr)
return;
// json payload = {
// {"jsonrpc", "1.0"},
// {"id", "someid"},
// {"method", "getnetworksolps"}
// };
// conn->doRPCIgnoreError(payload, [=](const json& reply) {
// qint64 solrate = reply.get<json::number_unsigned_t>();
// cb(solrate);
// });
}
void LiteInterface::fetchMigrationStatus(const std::function<void(json)>& cb) {
if (conn == nullptr)
return;
// json payload = {
// {"jsonrpc", "1.0"},
// {"id", "someid"},
// {"method", "z_getmigrationstatus"},
// };
// conn->doRPCWithDefaultErrorHandling(payload, cb);
}
void LiteInterface::setMigrationStatus(bool enabled) {
if (conn == nullptr)
return;
// json payload = {
// {"jsonrpc", "1.0"},
// {"id", "someid"},
// {"method", "z_setmigration"},
// {"params", {enabled}}
// };
// conn->doRPCWithDefaultErrorHandling(payload, [=](json) {
// // Ignore return value.
// });
}
/**
* Method to get all the private keys for both z and t addresses. It will make 2 batch calls,
* combine the result, and call the callback with a single list containing both the t-addr and z-addr
* private keys
*/
void LiteInterface::fetchAllPrivKeys(const std::function<void(QList<QPair<QString, QString>>)> cb) {
void LiteInterface::fetchAllPrivKeys(const std::function<void(json)> cb) {
if (conn == nullptr) {
// No connection, just return
return;
}
// // A special function that will call the callback when two lists have been added
// auto holder = new QPair<int, QList<QPair<QString, QString>>>();
// holder->first = 0; // This is the number of times the callback has been called, initialized to 0
// auto fnCombineTwoLists = [=] (QList<QPair<QString, QString>> list) {
// // Increment the callback counter
// holder->first++;
// // Add all
// std::copy(list.begin(), list.end(), std::back_inserter(holder->second));
// // And if the caller has been called twice, do the parent callback with the
// // collected list
// if (holder->first == 2) {
// // Sort so z addresses are on top
// std::sort(holder->second.begin(), holder->second.end(),
// [=] (auto a, auto b) { return a.first > b.first; });
// cb(holder->second);
// delete holder;
// }
// };
// // A utility fn to do the batch calling
// auto fnDoBatchGetPrivKeys = [=](json getAddressPayload, std::string privKeyDumpMethodName) {
// conn->doRPCWithDefaultErrorHandling(getAddressPayload, [=] (json resp) {
// QList<QString> addrs;
// for (auto addr : resp.get<json::array_t>()) {
// addrs.push_back(QString::fromStdString(addr.get<json::string_t>()));
// }
// // Then, do a batch request to get all the private keys
// conn->doBatchRPC<QString>(
// addrs,
// [=] (auto addr) {
// json payload = {
// {"jsonrpc", "1.0"},
// {"id", "someid"},
// {"method", privKeyDumpMethodName},
// {"params", { addr.toStdString() }},
// };
// return payload;
// },
// [=] (QMap<QString, json>* 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>())));
// }
// fnCombineTwoLists(allTKeys);
// delete privkeys;
// }
// );
// });
// };
// // First get all the t and z addresses.
// json payloadT = {
// {"jsonrpc", "1.0"},
// {"id", "someid"},
// {"method", "getaddressesbyaccount"},
// {"params", {""} }
// };
// json payloadZ = {
// {"jsonrpc", "1.0"},
// {"id", "someid"},
// {"method", "z_listaddresses"}
// };
// fnDoBatchGetPrivKeys(payloadT, "dumpprivkey");
// fnDoBatchGetPrivKeys(payloadZ, "z_exportkey");
}
void LiteInterface::fetchOpStatus(const std::function<void(json)>& cb) {
if (conn == nullptr)
return;
// Make an RPC to load pending operation statues
// json payload = {
// {"jsonrpc", "1.0"},
// {"id", "someid"},
// {"method", "z_getoperationstatus"},
// };
// conn->doRPCIgnoreError(payload, cb);
}
void LiteInterface::fetchReceivedTTrans(QList<QString> txids, QList<TransactionItem> sentZTxs,
const std::function<void(QList<TransactionItem>)> txdataFn) {
if (conn == nullptr)
return;
// Look up all the txids to get the confirmation count for them.
// conn->doBatchRPC<QString>(txids,
// [=] (QString txid) {
// json payload = {
// {"jsonrpc", "1.0"},
// {"id", "senttxid"},
// {"method", "gettransaction"},
// {"params", {txid.toStdString()}}
// };
// return payload;
// },
// [=] (QMap<QString, json>* 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
// // with the confirmed block number, so we don't have to keep calling gettransaction for the
// // sent items.
// for (TransactionItem& sentTx: newSentZTxs) {
// auto j = txidList->value(sentTx.txid);
// if (j.is_null())
// continue;
// auto error = j["confirmations"].is_null();
// if (!error)
// sentTx.confirmations = j["confirmations"].get<json::number_integer_t>();
// }
// txdataFn(newSentZTxs);
// delete txidList;
// }
// );
conn->doRPCWithDefaultErrorHandling("export", "", cb);
}
// Refresh received z txs by calling z_listreceivedbyaddress/gettransaction
void LiteInterface::fetchReceivedZTrans(QList<QString> zaddrs, const std::function<void(QString)> usedAddrFn,
const std::function<void(QList<TransactionItem>)> txdataFn) {
if (conn == nullptr)
return;
// This method is complicated because z_listreceivedbyaddress only returns the txid, and
// we have to make a follow up call to gettransaction to get details of that transaction.
// Additionally, it has to be done in batches, because there are multiple z-Addresses,
// and each z-Addr can have multiple received txs.
// 1. For each z-Addr, get list of received txs
// conn->doBatchRPC<QString>(zaddrs,
// [=] (QString zaddr) {
// json payload = {
// {"jsonrpc", "1.0"},
// {"id", "z_lrba"},
// {"method", "z_listreceivedbyaddress"},
// {"params", {zaddr.toStdString(), 0}} // Accept 0 conf as well.
// };
// return payload;
// },
// [=] (QMap<QString, json>* 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>()) {
// // Mark the address as used
// usedAddrFn(zaddr);
// // Filter out change txs
// if (! i["change"].get<json::boolean_t>()) {
// auto txid = QString::fromStdString(i["txid"].get<json::string_t>());
// txids.insert(txid);
// // Check for Memos
// QString memoBytes = QString::fromStdString(i["memo"].get<json::string_t>());
// if (!memoBytes.startsWith("f600")) {
// QString memo(QByteArray::fromHex(
// QByteArray::fromStdString(i["memo"].get<json::string_t>())));
// if (!memo.trimmed().isEmpty())
// memos[zaddr + txid] = memo;
// }
// }
// }
// }
// // 2. For all txids, go and get the details of that txid.
// conn->doBatchRPC<QString>(txids.toList(),
// [=] (QString txid) {
// json payload = {
// {"jsonrpc", "1.0"},
// {"id", "gettx"},
// {"method", "gettransaction"},
// {"params", {txid.toStdString()}}
// };
// return payload;
// },
// [=] (QMap<QString, json>* 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>()) {
// // Filter out change txs
// if (i["change"].get<json::boolean_t>())
// continue;
// auto zaddr = it.key();
// auto txid = QString::fromStdString(i["txid"].get<json::string_t>());
// // 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>();
// } else {
// timestamp = txidInfo["blocktime"].get<json::number_unsigned_t>();
// }
// auto amount = i["amount"].get<json::number_float_t>();
// auto confirmations = static_cast<long>(txidInfo["confirmations"].get<json::number_integer_t>());
// TransactionItem tx{ QString("receive"), timestamp, zaddr, txid, amount,
// confirmations, "", memos.value(zaddr + txid, "") };
// txdata.push_front(tx);
// }
// }
// txdataFn(txdata);
// // Cleanup both responses;
// delete zaddrTxids;
// delete txidDetails;
// }
// );
// }
// );
}

45
src/liteinterface.h

@ -7,15 +7,24 @@
using json = nlohmann::json;
// Since each transaction can contain multiple outputs, we separate them out individually
// into a struct with address, amount, memo
struct TransactionItemDetail {
QString address;
qint64 amount;
QString memo;
};
// Represents a row in the transactions table. Note that each transaction can contain
// multiple addresses (i.e., Multiple TransctionItemDetail)
struct TransactionItem {
QString type;
qint64 datetime;
QString address;
QString txid;
double amount;
long confirmations;
QString fromAddr;
QString memo;
QList<TransactionItemDetail> items;
};
@ -30,37 +39,23 @@ public:
void fetchUnspent (const std::function<void(json)>& cb);
void fetchTransactions (const std::function<void(json)>& cb);
void fetchZAddresses (const std::function<void(json)>& cb);
void fetchTAddresses (const std::function<void(json)>& cb);
void fetchReceivedZTrans(QList<QString> zaddrs, const std::function<void(QString)> usedAddrFn,
const std::function<void(QList<TransactionItem>)> txdataFn);
void fetchReceivedTTrans(QList<QString> txids, QList<TransactionItem> sentZtxs,
const std::function<void(QList<TransactionItem>)> txdataFn);
void fetchAddresses (const std::function<void(json)>& cb);
void fetchInfo(const std::function<void(json)>& cb,
const std::function<void(QString)>& err);
void fetchBlockchainInfo(const std::function<void(json)>& cb);
void fetchNetSolOps(const std::function<void(qint64)> cb);
void fetchOpStatus(const std::function<void(json)>& cb);
void fetchMigrationStatus(const std::function<void(json)>& cb);
void setMigrationStatus(bool enabled);
void fetchBalance(const std::function<void(json)>& cb);
void createNewZaddr(bool sapling, const std::function<void(json)>& cb);
void createNewTaddr(const std::function<void(json)>& cb);
void fetchZPrivKey(QString addr, const std::function<void(json)>& cb);
void fetchTPrivKey(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 fetchAllPrivKeys(const std::function<void(QList<QPair<QString, QString>>)>);
void fetchPrivKey(QString addr, const std::function<void(json)>& cb);
void fetchAllPrivKeys(const std::function<void(json)>);
void sendZTransaction(json params, const std::function<void(json)>& cb, const std::function<void(QString)>& err);
//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 sendTransaction(QString params, const std::function<void(json)>& cb, const std::function<void(QString)>& err);
private:
Connection* conn = nullptr;

36
src/main.cpp

@ -147,17 +147,9 @@ public:
// Command line parser
QCommandLineParser parser;
parser.setApplicationDescription("Shielded desktop wallet and embedded full node for Zcash");
parser.setApplicationDescription("Shielded desktop light wallet for Zcash");
parser.addHelpOption();
// A boolean option for running it headless
QCommandLineOption headlessOption(QStringList() << "headless", "Running it via GUI.");
parser.addOption(headlessOption);
// No embedded will disable the embedded zcashd node
QCommandLineOption noembeddedOption(QStringList() << "no-embedded", "Disable embedded zcashd");
parser.addOption(noembeddedOption);
// Add an option to specify the conf file
QCommandLineOption confOption(QStringList() << "conf", "Use the zcash.conf specified instead of looking for the default one.",
"confFile");
@ -177,8 +169,8 @@ public:
return 0;
}
QCoreApplication::setOrganizationName("zec-qt-wallet-org");
QCoreApplication::setApplicationName("zec-qt-wallet");
QCoreApplication::setOrganizationName("zecwallet-org");
QCoreApplication::setApplicationName("zecwallet");
QString locale = QLocale::system().name();
locale.truncate(locale.lastIndexOf('_')); // Get the language code
@ -214,20 +206,15 @@ public:
exit(0);
}
// Check for embedded option
if (parser.isSet(noembeddedOption)) {
Settings::getInstance()->setUseEmbedded(false);
} else {
Settings::getInstance()->setUseEmbedded(true);
}
Settings::getInstance()->setUseEmbedded(false);
// Check to see if a conf location was specified
if (parser.isSet(confOption)) {
Settings::getInstance()->setUsingZcashConf(parser.value(confOption));
}
w = new MainWindow();
w->setWindowTitle("ZecWallet FullNode v" + QString(APP_VERSION));
w->setWindowTitle("Zecwallet v" + QString(APP_VERSION));
// If there was a payment URI on the command line, pay it
if (parser.positionalArguments().length() > 0) {
@ -246,14 +233,9 @@ public:
a.installEventFilter(w);
// Check if starting headless
if (parser.isSet(headlessOption)) {
Settings::getInstance()->setHeadless(true);
a.setQuitOnLastWindowClosed(false);
} else {
Settings::getInstance()->setHeadless(false);
w->show();
}
Settings::getInstance()->setHeadless(false);
w->show();
return QApplication::exec();
}

230
src/mainwindow.cpp

@ -1,7 +1,6 @@
#include "mainwindow.h"
#include "addressbook.h"
#include "viewalladdresses.h"
#include "validateaddress.h"
#include "ui_mainwindow.h"
#include "ui_mobileappconnector.h"
#include "ui_addressbook.h"
@ -9,15 +8,12 @@
#include "ui_privkey.h"
#include "ui_about.h"
#include "ui_settings.h"
#include "ui_turnstile.h"
#include "ui_turnstileprogress.h"
#include "ui_viewalladdresses.h"
#include "ui_validateaddress.h"
#include "controller.h"
#include "balancestablemodel.h"
#include "settings.h"
#include "version.h"
#include "senttxstore.h"
#include "connection.h"
#include "requestdialog.h"
#include "websockets.h"
@ -85,9 +81,6 @@ MainWindow::MainWindow(QWidget *parent) :
payZcashURI();
});
// Import Private Key
QObject::connect(ui->actionImport_Private_Key, &QAction::triggered, this, &MainWindow::importPrivKey);
// Export All Private Keys
QObject::connect(ui->actionExport_All_Private_Keys, &QAction::triggered, this, &MainWindow::exportAllKeys);
@ -97,13 +90,6 @@ MainWindow::MainWindow(QWidget *parent) :
// Export transactions
QObject::connect(ui->actionExport_transactions, &QAction::triggered, this, &MainWindow::exportTransactions);
// Z-board seems to have been abandoned
// z-Board.net
// QObject::connect(ui->actionz_board_net, &QAction::triggered, this, &MainWindow::postToZBoard);
// Validate Address
QObject::connect(ui->actionValidate_Address, &QAction::triggered, this, &MainWindow::validateAddress);
// Connect mobile app
QObject::connect(ui->actionConnect_Mobile_App, &QAction::triggered, this, [=] () {
if (rpc->getConnection() == nullptr)
@ -276,17 +262,6 @@ void MainWindow::setupSettingsModal() {
Settings::getInstance()->setSaveZtxs(checked);
});
// Setup clear button
QObject::connect(settings.btnClearSaved, &QCheckBox::clicked, [=]() {
if (QMessageBox::warning(this, "Clear saved history?",
"Shielded z-Address transactions are stored locally in your wallet, outside zcashd. You may delete this saved information safely any time for your privacy.\nDo you want to delete the saved shielded transactions now?",
QMessageBox::Yes, QMessageBox::Cancel)) {
SentTxStore::deleteHistory();
// Reload after the clear button so existing txs disappear
rpc->refresh(true);
}
});
// Setup theme combo
int theme_index = settings.comboBoxTheme->findText(Settings::getInstance()->get_theme_name(), Qt::MatchExactly);
settings.comboBoxTheme->setCurrentIndex(theme_index);
@ -460,73 +435,30 @@ void MainWindow::donate() {
ui->tabWidget->setCurrentIndex(1);
}
/**
* Validate an address
*/
void MainWindow::validateAddress() {
// Make sure everything is up and running
if (!getRPC() || !getRPC()->getConnection())
return;
// First thing is ask the user for an address
bool ok;
auto address = QInputDialog::getText(this, tr("Enter Address to validate"),
tr("Transparent or Shielded Address:") + QString(" ").repeated(140), // Pad the label so the dialog box is wide enough
QLineEdit::Normal, "", &ok);
if (!ok)
return;
getRPC()->validateAddress(address, [=] (json props) {
QDialog d(this);
Ui_ValidateAddress va;
va.setupUi(&d);
Settings::saveRestore(&d);
Settings::saveRestoreTableHeader(va.tblProps, &d, "validateaddressprops");
va.tblProps->horizontalHeader()->setStretchLastSection(true);
va.lblAddress->setText(address);
QList<QPair<QString, QString>> propsList;
for (auto it = props.begin(); it != props.end(); it++) {
propsList.append(
QPair<QString, QString>(
QString::fromStdString(it.key()), QString::fromStdString(it.value().dump()))
);
}
ValidateAddressesModel model(va.tblProps, propsList);
va.tblProps->setModel(&model);
d.exec();
});
}
void MainWindow::doImport(QList<QString>* keys) {
if (rpc->getConnection() == nullptr) {
// No connection, just return
return;
}
// void MainWindow::doImport(QList<QString>* keys) {
// if (rpc->getConnection() == nullptr) {
// // No connection, just return
// return;
// }
if (keys->isEmpty()) {
delete keys;
ui->statusBar->showMessage(tr("Private key import rescan finished"));
return;
}
// if (keys->isEmpty()) {
// delete keys;
// ui->statusBar->showMessage(tr("Private key import rescan finished"));
// return;
// }
// Pop the first key
QString key = keys->first();
keys->pop_front();
bool rescan = keys->isEmpty();
// // Pop the first key
// QString key = keys->first();
// keys->pop_front();
// bool rescan = keys->isEmpty();
if (key.startsWith("SK") ||
key.startsWith("secret")) { // Z key
rpc->importZPrivKey(key, rescan, [=] (auto) { this->doImport(keys); });
} else {
rpc->importTPrivKey(key, rescan, [=] (auto) { this->doImport(keys); });
}
}
// if (key.startsWith("SK") ||
// key.startsWith("secret")) { // Z key
// rpc->importZPrivKey(key, rescan, [=] (auto) { this->doImport(keys); });
// } else {
// rpc->importTPrivKey(key, rescan, [=] (auto) { this->doImport(keys); });
// }
// }
// Callback invoked when the RPC has finished loading all the balances, and the UI
@ -619,50 +551,50 @@ void MainWindow::payZcashURI(QString uri, QString myAddr) {
}
void MainWindow::importPrivKey() {
QDialog d(this);
Ui_PrivKey pui;
pui.setupUi(&d);
Settings::saveRestore(&d);
pui.buttonBox->button(QDialogButtonBox::Save)->setVisible(false);
pui.helpLbl->setText(QString() %
tr("Please paste your private keys (z-Addr or t-Addr) here, one per line") % ".\n" %
tr("The keys will be imported into your connected zcashd node"));
if (d.exec() == QDialog::Accepted && !pui.privKeyTxt->toPlainText().trimmed().isEmpty()) {
auto rawkeys = pui.privKeyTxt->toPlainText().trimmed().split("\n");
QList<QString> keysTmp;
// Filter out all the empty keys.
std::copy_if(rawkeys.begin(), rawkeys.end(), std::back_inserter(keysTmp), [=] (auto key) {
return !key.startsWith("#") && !key.trimmed().isEmpty();
});
auto keys = new QList<QString>();
std::transform(keysTmp.begin(), keysTmp.end(), std::back_inserter(*keys), [=](auto key) {
return key.trimmed().split(" ")[0];
});
// Special case.
// Sometimes, when importing from a paperwallet or such, the key is split by newlines, and might have
// been pasted like that. So check to see if the whole thing is one big private key
if (Settings::getInstance()->isValidSaplingPrivateKey(keys->join(""))) {
auto multiline = keys;
keys = new QList<QString>();
keys->append(multiline->join(""));
delete multiline;
}
// Start the import. The function takes ownership of keys
QTimer::singleShot(1, [=]() {doImport(keys);});
// Show the dialog that keys will be imported.
QMessageBox::information(this,
"Imported", tr("The keys were imported. It may take several minutes to rescan the blockchain. Until then, functionality may be limited"),
QMessageBox::Ok);
}
}
// void MainWindow::importPrivKey() {
// QDialog d(this);
// Ui_PrivKey pui;
// pui.setupUi(&d);
// Settings::saveRestore(&d);
// pui.buttonBox->button(QDialogButtonBox::Save)->setVisible(false);
// pui.helpLbl->setText(QString() %
// tr("Please paste your private keys (z-Addr or t-Addr) here, one per line") % ".\n" %
// tr("The keys will be imported into your connected zcashd node"));
// if (d.exec() == QDialog::Accepted && !pui.privKeyTxt->toPlainText().trimmed().isEmpty()) {
// auto rawkeys = pui.privKeyTxt->toPlainText().trimmed().split("\n");
// QList<QString> keysTmp;
// // Filter out all the empty keys.
// std::copy_if(rawkeys.begin(), rawkeys.end(), std::back_inserter(keysTmp), [=] (auto key) {
// return !key.startsWith("#") && !key.trimmed().isEmpty();
// });
// auto keys = new QList<QString>();
// std::transform(keysTmp.begin(), keysTmp.end(), std::back_inserter(*keys), [=](auto key) {
// return key.trimmed().split(" ")[0];
// });
// // Special case.
// // Sometimes, when importing from a paperwallet or such, the key is split by newlines, and might have
// // been pasted like that. So check to see if the whole thing is one big private key
// if (Settings::getInstance()->isValidSaplingPrivateKey(keys->join(""))) {
// auto multiline = keys;
// keys = new QList<QString>();
// keys->append(multiline->join(""));
// delete multiline;
// }
// // Start the import. The function takes ownership of keys
// QTimer::singleShot(1, [=]() {doImport(keys);});
// // Show the dialog that keys will be imported.
// QMessageBox::information(this,
// "Imported", tr("The keys were imported. It may take several minutes to rescan the blockchain. Until then, functionality may be limited"),
// QMessageBox::Ok);
// }
// }
/**
* Export transaction history into a CSV file
@ -763,13 +695,20 @@ void MainWindow::exportKeys(QString addr) {
// Call the API
auto isDialogAlive = std::make_shared<bool>(true);
auto fnUpdateUIWithKeys = [=](QList<QPair<QString, QString>> privKeys) {
auto fnUpdateUIWithKeys = [=](json reply) {
// Check to see if we are still showing.
if (! *(isDialogAlive.get()) ) return;
if (reply.is_discarded() || !reply.is_array()) {
pui.privKeyTxt->setPlainText(tr("Error loading private keys"));
pui.buttonBox->button(QDialogButtonBox::Save)->setEnabled(false);
return;
}
QString allKeysTxt;
for (auto keypair : privKeys) {
allKeysTxt = allKeysTxt % keypair.second % " # addr=" % keypair.first % "\n";
for (auto i : reply.get<json::array_t>()) {
allKeysTxt = allKeysTxt % QString::fromStdString(i["private_key"]) % " # addr=" % QString::fromStdString(i["address"]) % "\n";
}
pui.privKeyTxt->setPlainText(allKeysTxt);
@ -779,19 +718,8 @@ void MainWindow::exportKeys(QString addr) {
if (allKeys) {
rpc->fetchAllPrivKeys(fnUpdateUIWithKeys);
}
else {
auto fnAddKey = [=](json key) {
QList<QPair<QString, QString>> singleAddrKey;
singleAddrKey.push_back(QPair<QString, QString>(addr, QString::fromStdString(key.get<json::string_t>())));
fnUpdateUIWithKeys(singleAddrKey);
};
if (Settings::getInstance()->isZAddress(addr)) {
rpc->fetchZPrivKey(addr, fnAddKey);
}
else {
rpc->fetchTPrivKey(addr, fnAddKey);
}
else {
rpc->fetchPrivKey(addr, fnUpdateUIWithKeys);
}
d.exec();
@ -980,7 +908,7 @@ void MainWindow::setupTransactionsTab() {
void MainWindow::addNewZaddr(bool sapling) {
rpc->createNewZaddr(sapling, [=] (json reply) {
QString addr = QString::fromStdString(reply.get<json::string_t>());
QString addr = QString::fromStdString(reply.get<json::array_t>()[0]);
// Make sure the RPC class reloads the z-addrs for future use
rpc->refreshAddresses();
@ -1031,7 +959,7 @@ std::function<void(bool)> MainWindow::addZAddrsToComboList(bool sapling) {
void MainWindow::setupReceiveTab() {
auto addNewTAddr = [=] () {
rpc->createNewTaddr([=] (json reply) {
QString addr = QString::fromStdString(reply.get<json::string_t>());
QString addr = QString::fromStdString(reply.get<json::array_t>()[0]);
// Make sure the RPC class reloads the t-addrs for future use
rpc->refreshAddresses();

6
src/mainwindow.h

@ -18,8 +18,7 @@ using json = nlohmann::json;
struct ToFields {
QString addr;
double amount;
QString txtMemo;
QString encodedMemo;
QString memo;
};
// Struct used to represent a Transaction.
@ -58,8 +57,6 @@ public:
void balancesReady();
void payZcashURI(QString uri = "", QString myAddr = "");
void validateAddress();
void updateLabels();
void updateTAddrCombo(bool checked);
void updateFromCombo();
@ -120,7 +117,6 @@ private:
void donate();
void addressBook();
//void postToZBoard();
void importPrivKey();
void exportAllKeys();
void exportKeys(QString addr = "");

23
src/mainwindow.ui

@ -1062,7 +1062,6 @@
<addaction name="actionRequest_zcash"/>
<addaction name="actionPay_URI"/>
<addaction name="separator"/>
<addaction name="actionImport_Private_Key"/>
<addaction name="actionExport_All_Private_Keys"/>
<addaction name="actionBackup_wallet_dat"/>
<addaction name="separator"/>
@ -1084,10 +1083,6 @@
<string>&amp;Apps</string>
</property>
<addaction name="actionConnect_Mobile_App"/>
<addaction name="actionValidate_Address"/>
<addaction name="separator"/>
<addaction name="actionz_board_net"/>
<addaction name="actionTurnstile_Migration"/>
</widget>
<widget class="QMenu" name="menu_Edit">
<property name="title">
@ -1131,19 +1126,6 @@
<string>Check github.com for &amp;updates</string>
</property>
</action>
<action name="actionTurnstile_Migration">
<property name="text">
<string>Sapling &amp;turnstile</string>
</property>
<property name="shortcut">
<string>Ctrl+A, Ctrl+T</string>
</property>
</action>
<action name="actionImport_Private_Key">
<property name="text">
<string>&amp;Import private key</string>
</property>
</action>
<action name="actionExport_All_Private_Keys">
<property name="text">
<string>&amp;Export all private keys</string>
@ -1195,11 +1177,6 @@
<string>File a bug...</string>
</property>
</action>
<action name="actionValidate_Address">
<property name="text">
<string>Validate Address</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>

12
src/recurring.cpp

@ -137,7 +137,7 @@ RecurringPaymentInfo* Recurring::getNewRecurringFromTx(QWidget* parent, MainWind
// Default is USD
ui.lblAmt->setText(Settings::getUSDFromZecAmount(tx.toAddrs[0].amount));
ui.txtMemo->setPlainText(tx.toAddrs[0].txtMemo);
ui.txtMemo->setPlainText(tx.toAddrs[0].memo);
ui.txtMemo->setEnabled(false);
}
@ -199,7 +199,7 @@ RecurringPaymentInfo* Recurring::getNewRecurringFromTx(QWidget* parent, MainWind
void Recurring::updateInfoWithTx(RecurringPaymentInfo* r, Tx tx) {
r->toAddr = tx.toAddrs[0].addr;
r->memo = tx.toAddrs[0].txtMemo;
r->memo = tx.toAddrs[0].memo;
r->fromAddr = tx.fromAddr;
if (r->currency.isEmpty() || r->currency == "USD") {
r->currency = "USD";
@ -485,7 +485,7 @@ void Recurring::executeRecurringPayment(MainWindow* main, RecurringPaymentInfo r
if (paymentNumbers.size() > 1)
amt *= paymentNumbers.size();
tx.toAddrs.append(ToFields { rpi.toAddr, amt, rpi.memo, rpi.memo.toUtf8().toHex() });
tx.toAddrs.append(ToFields { rpi.toAddr, amt, rpi.memo });
// To prevent some weird race conditions, we immediately mark the payment as paid.
// If something goes wrong, we'll get the error callback below, and the status will be
@ -514,10 +514,8 @@ void Recurring::executeRecurringPayment(MainWindow* main, RecurringPaymentInfo r
* Execute a send Tx
*/
void Recurring::doSendTx(MainWindow* mainwindow, Tx tx, std::function<void(QString, QString)> cb) {
mainwindow->getRPC()->executeTransaction(tx, [=] (QString opid) {
mainwindow->ui->statusBar->showMessage(QObject::tr("Computing Recurring Tx: ") % opid);
},
[=] (QString /*opid*/, QString txid) {
mainwindow->getRPC()->executeTransaction(tx,
[=] (QString txid) {
mainwindow->ui->statusBar->showMessage(Settings::txidStatusMessage + " " + txid);
cb(txid, "");
},

15
src/sendtab.cpp

@ -521,7 +521,7 @@ Tx MainWindow::createTxFromSendPage() {
totalAmt += amt;
QString memo = ui->sendToWidgets->findChild<QLabel*>(QString("MemoTxt") % QString::number(i+1))->text().trimmed();
tx.toAddrs.push_back( ToFields{addr, amt, memo, memo.toUtf8().toHex()} );
tx.toAddrs.push_back( ToFields{addr, amt, memo} );
}
if (Settings::getInstance()->getAllowCustomFees()) {
@ -550,7 +550,7 @@ Tx MainWindow::createTxFromSendPage() {
if (Settings::getDecimalString(change) != "0") {
QString changeMemo = tr("Change from ") + tx.fromAddr;
tx.toAddrs.push_back(ToFields{ *saplingAddr, change, changeMemo, changeMemo.toUtf8().toHex() });
tx.toAddrs.push_back(ToFields{ *saplingAddr, change, changeMemo });
}
}
}
@ -649,11 +649,11 @@ bool MainWindow::confirmTx(Tx tx, RecurringPaymentInfo* rpi) {
confirm.gridLayout->addWidget(AmtUSD, row, 2, 1, 1);
// Memo
if (Settings::isZAddress(toAddr.addr) && !toAddr.txtMemo.isEmpty()) {
if (Settings::isZAddress(toAddr.addr) && !toAddr.memo.isEmpty()) {
row++;
auto Memo = new QLabel(confirm.sendToAddrs);
Memo->setObjectName(QStringLiteral("Memo") % QString::number(i + 1));
Memo->setText(toAddr.txtMemo);
Memo->setText(toAddr.memo);
QFont font1 = Addr->font();
font1.setPointSize(font1.pointSize() - 1);
Memo->setFont(font1);
@ -769,12 +769,7 @@ void MainWindow::sendButton() {
// And send the Tx
rpc->executeTransaction(tx,
// Submitted
[=] (QString opid) {
ui->statusBar->showMessage(tr("Computing Tx: ") % opid);
},
// Accepted
[=] (QString, QString txid) {
[=] (QString txid) {
ui->statusBar->showMessage(Settings::txidStatusMessage + " " + txid);
// If this was a recurring payment, update the payment with the info

115
src/senttxstore.cpp

@ -1,115 +0,0 @@
#include "senttxstore.h"
#include "settings.h"
/// Get the location of the app data file to be written.
QString SentTxStore::writeableFile() {
auto filename = QStringLiteral("senttxstore.dat");
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
if (!dir.exists())
QDir().mkpath(dir.absolutePath());
if (Settings::getInstance()->isTestnet()) {
return dir.filePath("testnet-" % filename);
} else {
return dir.filePath(filename);
}
}
// delete the sent history.
void SentTxStore::deleteHistory() {
QFile data(writeableFile());
data.remove();
data.close();
}
QList<TransactionItem> SentTxStore::readSentTxFile() {
QFile data(writeableFile());
if (!data.exists()) {
return QList<TransactionItem>();
}
QJsonDocument jsonDoc;
data.open(QFile::ReadOnly);
jsonDoc = QJsonDocument::fromJson(data.readAll());
data.close();
QList<TransactionItem> items;
for (auto i : jsonDoc.array()) {
auto sentTx = i.toObject();
TransactionItem t{"send", (qint64)sentTx["datetime"].toVariant().toLongLong(),
sentTx["address"].toString(),
sentTx["txid"].toString(),
sentTx["amount"].toDouble() + sentTx["fee"].toDouble(),
0, sentTx["from"].toString(), ""};
items.push_back(t);
}
return items;
}
void SentTxStore::addToSentTx(Tx tx, QString txid) {
// Save transactions only if the settings are allowed
if (!Settings::getInstance()->getSaveZtxs())
return;
// Also, only store outgoing txs where the from address is a z-Addr. Else, regular zcashd
// stores it just fine
if (! Settings::isZAddress(tx.fromAddr))
return;
QFile data(writeableFile());
QJsonDocument jsonDoc;
// If data doesn't exist, then create a blank one
if (!data.exists()) {
QJsonArray a;
jsonDoc.setArray(a);
QFile newFile(writeableFile());
newFile.open(QFile::WriteOnly);
newFile.write(jsonDoc.toJson());
newFile.close();
} else {
data.open(QFile::ReadOnly);
jsonDoc = QJsonDocument().fromJson(data.readAll());
data.close();
}
// Calculate total amount in this tx
double totalAmount = 0;
for (auto i : tx.toAddrs) {
totalAmount += i.amount;
}
QString toAddresses;
if (tx.toAddrs.length() == 1) {
toAddresses = tx.toAddrs[0].addr;
} else {
// Concatenate all the toAddresses
for (auto a : tx.toAddrs) {
toAddresses += a.addr % "(" % Settings::getZECDisplayFormat(a.amount) % ") ";
}
}
auto list = jsonDoc.array();
QJsonObject txItem;
txItem["type"] = "sent";
txItem["from"] = tx.fromAddr;
txItem["datetime"] = QDateTime::currentMSecsSinceEpoch() / (qint64)1000;
txItem["address"] = toAddresses;
txItem["txid"] = txid;
txItem["amount"] = -totalAmount;
txItem["fee"] = -tx.fee;
list.append(txItem);
jsonDoc.setArray(list);
QFile writer(writeableFile());
if (writer.open(QFile::WriteOnly | QFile::Truncate)) {
writer.write(jsonDoc.toJson());
}
writer.close();
}

20
src/senttxstore.h

@ -1,20 +0,0 @@
#ifndef SENTTXSTORE_H
#define SENTTXSTORE_H
#include "precompiled.h"
#include "mainwindow.h"
#include "controller.h"
class SentTxStore {
public:
static void deleteHistory();
static QList<TransactionItem> readSentTxFile();
static void addToSentTx(Tx tx, QString txid);
private:
static QString writeableFile();
};
#endif // SENTTXSTORE_H

192
src/turnstileprogress.ui

@ -1,192 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TurnstileProgress</class>
<widget class="QDialog" name="TurnstileProgress">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Turnstile Migration Progress</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>From</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>To</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="QLabel" name="fromAddr">
<property name="text">
<string notr="true">From Address</string>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QLabel" name="progressTxt">
<property name="text">
<string notr="true">4 / 12</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="12" column="1" colspan="2">
<widget class="QLabel" name="label_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Please ensure you have your wallet.dat backed up!</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="9" column="0" colspan="3">
<widget class="QLabel" name="nextTx">
<property name="text">
<string>Next Transaction in 4 hours</string>
</property>
</widget>
</item>
<item row="7" column="0" colspan="3">
<widget class="QProgressBar" name="progressBar">
<property name="value">
<number>33</number>
</property>
</widget>
</item>
<item row="13" column="0" colspan="3">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Migration Progress</string>
</property>
</widget>
</item>
<item row="14" column="0" colspan="3">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close|QDialogButtonBox::Discard</set>
</property>
<property name="centerButtons">
<bool>false</bool>
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QLabel" name="msgIcon">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="11" column="0" colspan="3">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="0" colspan="3">
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QLabel" name="toAddr">
<property name="text">
<string notr="true">To Address</string>
</property>
</widget>
</item>
<item row="10" column="0" colspan="3">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>TurnstileProgress</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>TurnstileProgress</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

137
src/txtablemodel.cpp

@ -9,34 +9,20 @@ TxTableModel::TxTableModel(QObject *parent)
TxTableModel::~TxTableModel() {
delete modeldata;
delete tTrans;
delete zsTrans;
delete zrTrans;
}
void TxTableModel::addZSentData(const QList<TransactionItem>& data) {
delete zsTrans;
zsTrans = new QList<TransactionItem>();
std::copy(data.begin(), data.end(), std::back_inserter(*zsTrans));
updateAllData();
}
void TxTableModel::addZRecvData(const QList<TransactionItem>& data) {
delete zrTrans;
zrTrans = new QList<TransactionItem>();
std::copy(data.begin(), data.end(), std::back_inserter(*zrTrans));
updateAllData();
}
void TxTableModel::replaceData(const QList<TransactionItem>& data) {
delete modeldata;
modeldata = new QList<TransactionItem>();
void TxTableModel::addTData(const QList<TransactionItem>& data) {
delete tTrans;
tTrans = new QList<TransactionItem>();
std::copy(data.begin(), data.end(), std::back_inserter(*tTrans));
// Copy over the data and sort it
std::copy(data.begin(), data.end(), std::back_inserter(*modeldata));
std::sort(modeldata->begin(), modeldata->end(), [=] (auto a, auto b) {
return a.datetime > b.datetime; // reverse sort
});
updateAllData();
dataChanged(index(0, 0), index(modeldata->size()-1, columnCount(index(0,0))-1));
layoutChanged();
}
bool TxTableModel::exportToCsv(QString fileName) const {
@ -61,8 +47,9 @@ bool TxTableModel::exportToCsv(QString fileName) const {
for (int col = 0; col < headers.length(); col++) {
out << "\"" << data(index(row, col), Qt::DisplayRole).toString() << "\",";
}
// Memo
out << "\"" << modeldata->at(row).memo << "\"";
out << "\"" << this->getMemo(row) << "\"";
out << endl;
}
@ -70,25 +57,6 @@ bool TxTableModel::exportToCsv(QString fileName) const {
return true;
}
void TxTableModel::updateAllData() {
auto newmodeldata = new QList<TransactionItem>();
if (tTrans != nullptr) std::copy( tTrans->begin(), tTrans->end(), std::back_inserter(*newmodeldata));
if (zsTrans != nullptr) std::copy(zsTrans->begin(), zsTrans->end(), std::back_inserter(*newmodeldata));
if (zrTrans != nullptr) std::copy(zrTrans->begin(), zrTrans->end(), std::back_inserter(*newmodeldata));
// Sort by reverse time
std::sort(newmodeldata->begin(), newmodeldata->end(), [=] (auto a, auto b) {
return a.datetime > b.datetime; // reverse sort
});
// And then swap out the modeldata with the new one.
delete modeldata;
modeldata = newmodeldata;
dataChanged(index(0, 0), index(modeldata->size()-1, columnCount(index(0,0))-1));
layoutChanged();
}
int TxTableModel::rowCount(const QModelIndex&) const
{
@ -135,18 +103,31 @@ void TxTableModel::updateAllData() {
}
case Column::Time: return QDateTime::fromMSecsSinceEpoch(dat.datetime * (qint64)1000).toLocalTime().toString();
case Column::Confirmations: return QString::number(dat.confirmations);
case Column::Amount: return Settings::getZECDisplayFormat(dat.amount);
case Column::Amount: {
// Sum up all the amounts
qint64 total = 0;
for (int i=0; i < dat.items.length(); i++) {
total += dat.items[i].amount;
}
return Settings::getZECDisplayFormat(total);
}
}
}
if (role == Qt::ToolTipRole) {
switch (index.column()) {
case Column::Type: {
if (dat.memo.startsWith("zcash:")) {
return Settings::paymentURIPretty(Settings::parseURI(dat.memo));
// If there are multiple memos, then mark them as such
if (dat.items.length() == 1) {
auto memo = dat.items[0].memo;
if (memo.startsWith("zcash:")) {
return Settings::paymentURIPretty(Settings::parseURI(memo));
} else {
return modeldata->at(index.row()).type +
(memo.isEmpty() ? "" : " tx memo: \"" + memo + "\"");
}
} else {
return modeldata->at(index.row()).type +
(dat.memo.isEmpty() ? "" : " tx memo: \"" + dat.memo + "\"");
return "Multiple";
}
}
case Column::Address: {
@ -158,21 +139,33 @@ void TxTableModel::updateAllData() {
}
case Column::Time: return QDateTime::fromMSecsSinceEpoch(modeldata->at(index.row()).datetime * (qint64)1000).toLocalTime().toString();
case Column::Confirmations: return QString("%1 Network Confirmations").arg(QString::number(dat.confirmations));
case Column::Amount: return Settings::getInstance()->getUSDFromZecAmount(modeldata->at(index.row()).amount);
case Column::Amount: {
// Sum up all the amounts
qint64 total = 0;
for (int i=0; i < dat.items.length(); i++) {
total += dat.items[i].amount;
}
return Settings::getInstance()->getUSDFromZecAmount(total);
}
}
}
if (role == Qt::DecorationRole && index.column() == 0) {
if (!dat.memo.isEmpty()) {
// If the memo is a Payment URI, then show a payment request icon
if (dat.memo.startsWith("zcash:")) {
QIcon icon(":/icons/res/paymentreq.gif");
return QVariant(icon.pixmap(16, 16));
} else {
// Return the info pixmap to indicate memo
QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation);
return QVariant(icon.pixmap(16, 16));
}
bool hasMemo = false;
for (int i=0; i < dat.items.length(); i++) {
if (!dat.items[i].memo.isEmpty()) {
hasMemo = true;
}
}
// If the memo is a Payment URI, then show a payment request icon
if (dat.items.length() == 1 && dat.items[0].memo.startsWith("zcash:")) {
QIcon icon(":/icons/res/paymentreq.gif");
return QVariant(icon.pixmap(16, 16));
} else if (hasMemo) {
// Return the info pixmap to indicate memo
QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation);
return QVariant(icon.pixmap(16, 16));
} else {
// Empty pixmap to make it align
QPixmap p(16, 16);
@ -208,7 +201,21 @@ QString TxTableModel::getTxId(int row) const {
}
QString TxTableModel::getMemo(int row) const {
return modeldata->at(row).memo;
auto dat = modeldata->at(row);
bool hasMemo = false;
for (int i=0; i < dat.items.length(); i++) {
if (!dat.items[i].memo.isEmpty()) {
hasMemo = true;
}
}
if (dat.items.length() == 1) {
return dat.items[0].memo;
} else if (hasMemo) {
return "(Multiple)";
} else {
return "";
}
}
qint64 TxTableModel::getConfirmations(int row) const {
@ -228,5 +235,11 @@ QString TxTableModel::getType(int row) const {
}
QString TxTableModel::getAmt(int row) const {
return Settings::getDecimalString(modeldata->at(row).amount);
auto dat = modeldata->at(row);
qint64 total = 0;
for (int i=0; i < dat.items.length(); i++) {
total += dat.items[i].amount;
}
return Settings::getDecimalString(total);
}

10
src/txtablemodel.h

@ -20,9 +20,7 @@ public:
Amount = 4
};
void addTData (const QList<TransactionItem>& data);
void addZSentData(const QList<TransactionItem>& data);
void addZRecvData(const QList<TransactionItem>& data);
void replaceData (const QList<TransactionItem>& data);
QString getTxId(int row) const;
QString getMemo(int row) const;
@ -40,12 +38,6 @@ public:
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
private:
void updateAllData();
QList<TransactionItem>* tTrans = nullptr;
QList<TransactionItem>* zrTrans = nullptr; // Z received
QList<TransactionItem>* zsTrans = nullptr; // Z sent
QList<TransactionItem>* modeldata = nullptr;
QList<QString> headers;

37
src/validateaddress.cpp

@ -1,37 +0,0 @@
#include "validateaddress.h"
ValidateAddressesModel::ValidateAddressesModel(QTableView *parent, QList<QPair<QString, QString>> props)
: QAbstractTableModel(parent) {
headers << tr("Property") << tr("Value");
this->props = props;
}
int ValidateAddressesModel::rowCount(const QModelIndex&) const {
return props.size();
}
int ValidateAddressesModel::columnCount(const QModelIndex&) const {
return headers.size();
}
QVariant ValidateAddressesModel::data(const QModelIndex &index, int role) const {
QPair<QString, QString> p = props.at(index.row());
if (role == Qt::DisplayRole) {
switch(index.column()) {
case 0: return p.first;
case 1: return p.second;
}
}
return QVariant();
}
QVariant ValidateAddressesModel::headerData(int section, Qt::Orientation orientation, int role) const {
if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
return headers.at(section);
}
return QVariant();
}

23
src/validateaddress.h

@ -1,23 +0,0 @@
#ifndef VALIDATEADDRESS_H
#define VALIDATEADDRESS_H
#include "precompiled.h"
class ValidateAddressesModel : public QAbstractTableModel {
public:
ValidateAddressesModel(QTableView* parent, QList<QPair<QString, QString>> props);
~ValidateAddressesModel() = default;
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
private:
QList<QPair<QString, QString>> props;
QStringList headers;
};
#endif // VALIDATEADDRESS_H

85
src/validateaddress.ui

@ -1,85 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ValidateAddress</class>
<widget class="QDialog" name="ValidateAddress">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Validate Address</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QLabel" name="lblAddress">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Address:</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QTableView" name="tblProps">
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>ValidateAddress</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>ValidateAddress</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

20
src/websockets.cpp

@ -683,7 +683,7 @@ void AppDataServer::processSendTx(QJsonObject sendTx, MainWindow* mainwindow, st
});
tx.fromAddr = bals[0].first;
tx.toAddrs = { ToFields{ sendTx["to"].toString(), amt, sendTx["memo"].toString(), sendTx["memo"].toString().toUtf8().toHex()} };
tx.toAddrs = { ToFields{ sendTx["to"].toString(), amt, sendTx["memo"].toString()} };
// TODO: Respect the autoshield change setting
@ -699,9 +699,7 @@ void AppDataServer::processSendTx(QJsonObject sendTx, MainWindow* mainwindow, st
// And send the Tx
mainwindow->getRPC()->executeTransaction(tx,
[=] (QString) {},
// Submitted Tx successfully
[=] (QString, QString txid) {
[=] (QString txid) {
auto r = QJsonDocument(QJsonObject{
{"version", 1.0},
{"command", "sendTxSubmitted"},
@ -771,20 +769,6 @@ void AppDataServer::processGetInfo(QJsonObject jobj, MainWindow* mainWindow, std
void AppDataServer::processGetTransactions(MainWindow* mainWindow, std::shared_ptr<ClientWebSocket> pClient) {
QJsonArray txns;
auto model = mainWindow->getRPC()->getTransactionsModel();
// Manually add pending ops, so that computing transactions will also show up
auto wtxns = mainWindow->getRPC()->getWatchingTxns();
for (auto opid : wtxns.keys()) {
txns.append(QJsonObject{
{"type", "send"},
{"datetime", QDateTime::currentSecsSinceEpoch()},
{"amount", Settings::getDecimalString(wtxns[opid].tx.toAddrs[0].amount)},
{"txid", ""},
{"address", wtxns[opid].tx.toAddrs[0].addr},
{"memo", wtxns[opid].tx.toAddrs[0].txtMemo},
{"confirmations", 0}
});
}
// Add transactions
for (int i = 0; i < model->rowCount(QModelIndex()) && i < Settings::getMaxMobileAppTxns(); i++) {

170
src/zboard.ui

@ -1,170 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>zboard</class>
<widget class="QDialog" name="zboard">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>588</width>
<height>431</height>
</rect>
</property>
<property name="windowTitle">
<string>Post to z-board.net</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="14" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Total Fee</string>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QLabel" name="feeAmount">
<property name="text">
<string notr="true">feeamount</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="12" column="1">
<widget class="QLabel" name="memoSize">
<property name="text">
<string notr="true">0 / 512</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="16" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Memo</string>
</property>
</widget>
</item>
<item row="11" column="0" colspan="2">
<widget class="QLineEdit" name="postAs">
<property name="placeholderText">
<string>(optional)</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Send From</string>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Post As:</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label_2">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;ZBoard: Fully anonymous and untraceable chat messages based on the ZCash blockchain. &lt;a href=&quot;http://www.z-board.net/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://www.z-board.net/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="13" column="0" colspan="2">
<widget class="QPlainTextEdit" name="memoTxt"/>
</item>
<item row="6" column="0" colspan="2">
<widget class="QComboBox" name="fromAddr"/>
</item>
<item row="15" column="0">
<widget class="QLabel" name="testnetWarning">
<property name="styleSheet">
<string notr="true">color:red;</string>
</property>
<property name="text">
<string>Warning</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="topicsList"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Posting to Board</string>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>fromAddr</tabstop>
<tabstop>postAs</tabstop>
<tabstop>memoTxt</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>zboard</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>zboard</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

7
zecwallet-lite.pro

@ -44,7 +44,6 @@ SOURCES += \
src/3rdparty/qrcode/QrSegment.cpp \
src/settings.cpp \
src/sendtab.cpp \
src/senttxstore.cpp \
src/txtablemodel.cpp \
src/qrcodelabel.cpp \
src/connection.cpp \
@ -52,7 +51,6 @@ SOURCES += \
src/addressbook.cpp \
src/logger.cpp \
src/addresscombo.cpp \
src/validateaddress.cpp \
src/websockets.cpp \
src/mobileappconnector.cpp \
src/recurring.cpp \
@ -73,14 +71,12 @@ HEADERS += \
src/3rdparty/json/json.hpp \
src/settings.h \
src/txtablemodel.h \
src/senttxstore.h \
src/qrcodelabel.h \
src/connection.h \
src/fillediconlabel.h \
src/addressbook.h \
src/logger.h \
src/addresscombo.h \
src/validateaddress.h \
src/websockets.h \
src/mobileappconnector.h \
src/recurring.h \
@ -99,13 +95,10 @@ FORMS += \
src/settings.ui \
src/about.ui \
src/confirm.ui \
src/turnstileprogress.ui \
src/privkey.ui \
src/memodialog.ui \
src/validateaddress.ui \
src/viewalladdresses.ui \
src/connection.ui \
src/zboard.ui \
src/addressbook.ui \
src/mobileappconnector.ui \
src/createzcashconfdialog.ui \

Loading…
Cancel
Save