Merge pull request #8 from DenioD/dev

switch to Hush unit
This commit is contained in:
Denio
2019-10-26 00:03:21 +02:00
committed by GitHub
46 changed files with 5697 additions and 4232 deletions
+2 -2
View File
@@ -18,10 +18,10 @@ script:
- qmake -v - qmake -v
- clang++ -v - clang++ -v
- g++-8 -v - g++-8 -v
- qmake hush-qt-wallet.pro CONFIG+=release -spec linux-clang - qmake silentdragon-lite.pro CONFIG+=release -spec linux-clang
- make CC=clang CXX=clang++ -j2 - make CC=clang CXX=clang++ -j2
- make distclean - make distclean
- qmake hush-qt-wallet.pro CONFIG+=release -spec linux-g++ - qmake silentdragon-lite.pro CONFIG+=release -spec linux-g++
- res/libsodium/buildlibsodium.sh - res/libsodium/buildlibsodium.sh
- make CC=gcc-8 CXX=g++-8 -j2 - make CC=gcc-8 CXX=g++-8 -j2
+1
View File
@@ -0,0 +1 @@
[{"excluded":[],"includePaths":["/home/denio/silentdragon-lite/src/3rdparty","/home/denio/silentdragon-lite/src","/home/denio/silentdragon-lite/singleapplication","/home/denio/silentdragon-lite/res","/home/denio/Qt5.13.1/5.13.1/gcc_64/include","/home/denio/Qt5.13.1/5.13.1/gcc_64/include/QtWidgets","/home/denio/Qt5.13.1/5.13.1/gcc_64/include/QtGui","/home/denio/Qt5.13.1/5.13.1/gcc_64/include/QtWebSockets","/home/denio/Qt5.13.1/5.13.1/gcc_64/include/QtNetwork","/home/denio/Qt5.13.1/5.13.1/gcc_64/include/QtCore","/home/denio/silentdragon-lite/bin","/usr/include/libdrm","/home/denio/silentdragon-lite/src"],"projectFile":"/home/denio/silentdragon-lite/silentdragon-lite.pro","sources":["/home/denio/silentdragon-lite/lib/silentdragonlitelib.h","/home/denio/silentdragon-lite/singleapplication/singleapplication.cpp","/home/denio/silentdragon-lite/singleapplication/singleapplication.h","/home/denio/silentdragon-lite/singleapplication/singleapplication_p.cpp","/home/denio/silentdragon-lite/singleapplication/singleapplication_p.h","/home/denio/silentdragon-lite/src/3rdparty/json/json.hpp","/home/denio/silentdragon-lite/src/3rdparty/qrcode/BitBuffer.cpp","/home/denio/silentdragon-lite/src/3rdparty/qrcode/BitBuffer.hpp","/home/denio/silentdragon-lite/src/3rdparty/qrcode/QrCode.cpp","/home/denio/silentdragon-lite/src/3rdparty/qrcode/QrCode.hpp","/home/denio/silentdragon-lite/src/3rdparty/qrcode/QrSegment.cpp","/home/denio/silentdragon-lite/src/3rdparty/qrcode/QrSegment.hpp","/home/denio/silentdragon-lite/src/about.ui","/home/denio/silentdragon-lite/src/addressbook.cpp","/home/denio/silentdragon-lite/src/addressbook.h","/home/denio/silentdragon-lite/src/addressbook.ui","/home/denio/silentdragon-lite/src/addresscombo.cpp","/home/denio/silentdragon-lite/src/addresscombo.h","/home/denio/silentdragon-lite/src/balancestablemodel.cpp","/home/denio/silentdragon-lite/src/balancestablemodel.h","/home/denio/silentdragon-lite/src/confirm.ui","/home/denio/silentdragon-lite/src/connection.cpp","/home/denio/silentdragon-lite/src/connection.h","/home/denio/silentdragon-lite/src/connection.ui","/home/denio/silentdragon-lite/src/controller.cpp","/home/denio/silentdragon-lite/src/controller.h","/home/denio/silentdragon-lite/src/createhushconfdialog.ui","/home/denio/silentdragon-lite/src/datamodel.cpp","/home/denio/silentdragon-lite/src/datamodel.h","/home/denio/silentdragon-lite/src/fillediconlabel.cpp","/home/denio/silentdragon-lite/src/fillediconlabel.h","/home/denio/silentdragon-lite/src/liteinterface.cpp","/home/denio/silentdragon-lite/src/liteinterface.h","/home/denio/silentdragon-lite/src/logger.cpp","/home/denio/silentdragon-lite/src/logger.h","/home/denio/silentdragon-lite/src/main.cpp","/home/denio/silentdragon-lite/src/mainwindow.cpp","/home/denio/silentdragon-lite/src/mainwindow.h","/home/denio/silentdragon-lite/src/mainwindow.ui","/home/denio/silentdragon-lite/src/memodialog.ui","/home/denio/silentdragon-lite/src/memoedit.cpp","/home/denio/silentdragon-lite/src/memoedit.h","/home/denio/silentdragon-lite/src/migration.ui","/home/denio/silentdragon-lite/src/mobileappconnector.cpp","/home/denio/silentdragon-lite/src/mobileappconnector.h","/home/denio/silentdragon-lite/src/mobileappconnector.ui","/home/denio/silentdragon-lite/src/newrecurring.ui","/home/denio/silentdragon-lite/src/precompiled.h","/home/denio/silentdragon-lite/src/privkey.ui","/home/denio/silentdragon-lite/src/qrcodelabel.cpp","/home/denio/silentdragon-lite/src/qrcodelabel.h","/home/denio/silentdragon-lite/src/recurring.cpp","/home/denio/silentdragon-lite/src/recurring.h","/home/denio/silentdragon-lite/src/recurringdialog.ui","/home/denio/silentdragon-lite/src/recurringmultiple.ui","/home/denio/silentdragon-lite/src/recurringpayments.ui","/home/denio/silentdragon-lite/src/requestdialog.cpp","/home/denio/silentdragon-lite/src/requestdialog.h","/home/denio/silentdragon-lite/src/requestdialog.ui","/home/denio/silentdragon-lite/src/sendtab.cpp","/home/denio/silentdragon-lite/src/settings.cpp","/home/denio/silentdragon-lite/src/settings.h","/home/denio/silentdragon-lite/src/settings.ui","/home/denio/silentdragon-lite/src/txtablemodel.cpp","/home/denio/silentdragon-lite/src/txtablemodel.h","/home/denio/silentdragon-lite/src/viewalladdresses.cpp","/home/denio/silentdragon-lite/src/viewalladdresses.h","/home/denio/silentdragon-lite/src/viewalladdresses.ui","/home/denio/silentdragon-lite/src/websockets.cpp","/home/denio/silentdragon-lite/src/websockets.h"],"translations":["/home/denio/silentdragon-lite/res/zec_qt_wallet_es.ts","/home/denio/silentdragon-lite/res/zec_qt_wallet_fr.ts","/home/denio/silentdragon-lite/res/zec_qt_wallet_de.ts","/home/denio/silentdragon-lite/res/zec_qt_wallet_pt.ts","/home/denio/silentdragon-lite/res/zec_qt_wallet_it.ts","/home/denio/silentdragon-lite/res/zec_qt_wallet_zh.ts","/home/denio/silentdragon-lite/res/zec_qt_wallet_tr.ts","/home/denio/silentdragon-lite/res/zec_qt_wallet_template.ts"]}]
+1 -6
View File
@@ -13,12 +13,7 @@
<file>res/logobig.gif</file> <file>res/logobig.gif</file>
</qresource> </qresource>
<qresource prefix="/translations"> <qresource prefix="/translations">
<file>res/zec_qt_wallet_es.qm</file> <file>res/zec_qt_wallet_de.qm</file>
<file>res/zec_qt_wallet_fr.qm</file>
<file>res/zec_qt_wallet_pt.qm</file>
<file>res/zec_qt_wallet_it.qm</file>
<file>res/zec_qt_wallet_zh.qm</file>
<file>res/zec_qt_wallet_tr.qm</file>
</qresource> </qresource>
<qresource prefix="/css"> <qresource prefix="/css">
<file>res/css/blue.css</file> <file>res/css/blue.css</file>
+3 -3
View File
@@ -1051,7 +1051,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"lazy_static 1.4.0 (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.65 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"silentdragonlitelib 0.1.0 (git+https://github.com/DenioD/silentdragonlite-cli?rev=a9d235e117da1fdbe3c576d0713b87cfdf97baf6)", "silentdragonlitelib 0.1.0 (git+https://github.com/DenioD/silentdragonlite-cli?rev=11d5d15e8b03c0a5b6eae1af00ac17fb7660a004)",
] ]
[[package]] [[package]]
@@ -1467,7 +1467,7 @@ dependencies = [
[[package]] [[package]]
name = "silentdragonlitelib" name = "silentdragonlitelib"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/DenioD/silentdragonlite-cli?rev=a9d235e117da1fdbe3c576d0713b87cfdf97baf6#a9d235e117da1fdbe3c576d0713b87cfdf97baf6" source = "git+https://github.com/DenioD/silentdragonlite-cli?rev=11d5d15e8b03c0a5b6eae1af00ac17fb7660a004#11d5d15e8b03c0a5b6eae1af00ac17fb7660a004"
dependencies = [ dependencies = [
"base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bellman 0.1.0 (git+https://github.com/DenioD/librustzcash.git?rev=caaee693c47c2ee9ecd1e1546b8fe3c714f342bc)", "bellman 0.1.0 (git+https://github.com/DenioD/librustzcash.git?rev=caaee693c47c2ee9ecd1e1546b8fe3c714f342bc)",
@@ -2481,7 +2481,7 @@ dependencies = [
"checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" "checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2"
"checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" "checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35"
"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d"
"checksum silentdragonlitelib 0.1.0 (git+https://github.com/DenioD/silentdragonlite-cli?rev=a9d235e117da1fdbe3c576d0713b87cfdf97baf6)" = "<none>" "checksum silentdragonlitelib 0.1.0 (git+https://github.com/DenioD/silentdragonlite-cli?rev=11d5d15e8b03c0a5b6eae1af00ac17fb7660a004)" = "<none>"
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7"
"checksum sodiumoxide 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585232e78a4fc18133eef9946d3080befdf68b906c51b621531c37e91787fa2b" "checksum sodiumoxide 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585232e78a4fc18133eef9946d3080befdf68b906c51b621531c37e91787fa2b"
+1 -1
View File
@@ -11,4 +11,4 @@ crate-type = ["staticlib"]
[dependencies] [dependencies]
libc = "0.2.58" libc = "0.2.58"
lazy_static = "1.4.0" lazy_static = "1.4.0"
silentdragonlitelib = { git = "https://github.com/DenioD/silentdragonlite-cli", rev = "a9d235e117da1fdbe3c576d0713b87cfdf97baf6" } silentdragonlitelib = { git = "https://github.com/DenioD/silentdragonlite-cli", rev = "11d5d15e8b03c0a5b6eae1af00ac17fb7660a004" }
+12 -4
View File
@@ -5,13 +5,21 @@
extern "C" { extern "C" {
#endif #endif
extern bool litelib_wallet_exists (const char* chain_name, const char* dir); extern bool litelib_wallet_exists (const char* chain_name);
extern char * litelib_initialze_existing (bool dangerous, const char* server); extern char * litelib_initialize_new (bool dangerous, const char* server);
extern char * litelib_execute (const char* s, const char* args); extern char * litelib_initialize_new_from_phrase
extern void litelib_rust_free_string (char* s); (bool dangerous, const char* server, const char* seed,
unsigned long long birthday);
extern char * litelib_initialize_existing (bool dangerous, const char* server);
extern char * litelib_execute (const char* s, const char* args);
extern void litelib_rust_free_string (char* s);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
// This is a function implemented in connection.cpp that will process a string response from
// the litelib and turn into into a QString in a memory-safe way.
QString litelib_process_response(char* resp);
#endif #endif
+116 -13
View File
@@ -4,7 +4,7 @@ extern crate lazy_static;
use libc::{c_char}; use libc::{c_char};
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::sync::{Mutex}; use std::sync::{Mutex, Arc};
use std::cell::RefCell; use std::cell::RefCell;
use silentdragonlitelib::{commands, lightclient::{LightClient, LightClientConfig}}; use silentdragonlitelib::{commands, lightclient::{LightClient, LightClientConfig}};
@@ -13,15 +13,115 @@ use silentdragonlitelib::{commands, lightclient::{LightClient, LightClientConfig
// so we don't have to keep creating it. We need to store it here, in rust // so we don't have to keep creating it. We need to store it here, in rust
// because we can't return such a complex structure back to C++ // because we can't return such a complex structure back to C++
lazy_static! { lazy_static! {
static ref LIGHTCLIENT: Mutex<RefCell<Option<LightClient>>> = Mutex::new(RefCell::new(None)); static ref LIGHTCLIENT: Mutex<RefCell<Option<Arc<LightClient>>>> = Mutex::new(RefCell::new(None));
} }
// Check if there is an existing wallet // Check if there is an existing wallet
#[no_mangle]
pub extern fn litelib_wallet_exists(chain_name: *const c_char) -> bool {
let chain_name_str = unsafe {
assert!(!chain_name.is_null());
CStr::from_ptr(chain_name).to_string_lossy().into_owned()
};
let config = LightClientConfig::create_unconnected(chain_name_str, None);
println!("Wallet exists: {}", config.wallet_exists());
config.wallet_exists()
}
/// Create a new wallet and return the seed for the newly created wallet.
#[no_mangle]
pub extern fn litelib_initialize_new(dangerous: bool, server: *const c_char) -> *mut c_char {
let server_str = unsafe {
assert!(!server.is_null());
CStr::from_ptr(server).to_string_lossy().into_owned()
};
let server = LightClientConfig::get_server_or_default(Some(server_str));
let (config, latest_block_height) = match LightClientConfig::create(server, dangerous) {
Ok((c, h)) => (c, h),
Err(e) => {
let e_str = CString::new(format!("Error: {}", e)).unwrap();
return e_str.into_raw();
}
};
let lightclient = match LightClient::new(&config, latest_block_height) {
Ok(l) => l,
Err(e) => {
let e_str = CString::new(format!("Error: {}", e)).unwrap();
return e_str.into_raw();
}
};
let seed = match lightclient.do_seed_phrase() {
Ok(s) => s.dump(),
Err(e) => {
let e_str = CString::new(format!("Error: {}", e)).unwrap();
return e_str.into_raw();
}
};
LIGHTCLIENT.lock().unwrap().replace(Some(Arc::new(lightclient)));
// Return the wallet's seed
let s_str = CString::new(seed).unwrap();
return s_str.into_raw();
}
/// Restore a wallet from the seed phrase
#[no_mangle]
pub extern fn litelib_initialize_new_from_phrase(dangerous: bool, server: *const c_char,
seed: *const c_char, birthday: u64) -> *mut c_char {
let server_str = unsafe {
assert!(!server.is_null());
CStr::from_ptr(server).to_string_lossy().into_owned()
};
let seed_str = unsafe {
assert!(!seed.is_null());
CStr::from_ptr(seed).to_string_lossy().into_owned()
};
let server = LightClientConfig::get_server_or_default(Some(server_str));
let (config, _latest_block_height) = match LightClientConfig::create(server, dangerous) {
Ok((c, h)) => (c, h),
Err(e) => {
let e_str = CString::new(format!("Error: {}", e)).unwrap();
return e_str.into_raw();
}
};
let lightclient = match LightClient::new_from_phrase(seed_str, &config, birthday) {
Ok(l) => l,
Err(e) => {
let e_str = CString::new(format!("Error: {}", e)).unwrap();
return e_str.into_raw();
}
};
let seed = match lightclient.do_seed_phrase() {
Ok(s) => s.dump(),
Err(e) => {
let e_str = CString::new(format!("Error: {}", e)).unwrap();
return e_str.into_raw();
}
};
LIGHTCLIENT.lock().unwrap().replace(Some(Arc::new(lightclient)));
let c_str = CString::new("OK").unwrap();
return c_str.into_raw();
}
// Initialize a new lightclient and store its value // Initialize a new lightclient and store its value
#[no_mangle] #[no_mangle]
pub extern fn litelib_initialze_existing(dangerous: bool, server: *const c_char) -> *mut c_char { pub extern fn litelib_initialize_existing(dangerous: bool, server: *const c_char) -> *mut c_char {
let server_str = unsafe { let server_str = unsafe {
assert!(!server.is_null()); assert!(!server.is_null());
@@ -34,11 +134,9 @@ pub extern fn litelib_initialze_existing(dangerous: bool, server: *const c_char)
Err(e) => { Err(e) => {
let e_str = CString::new(format!("Error: {}", e)).unwrap(); let e_str = CString::new(format!("Error: {}", e)).unwrap();
return e_str.into_raw(); return e_str.into_raw();
} }
}; };
let lightclient = match LightClient::read_from_disk(&config) { let lightclient = match LightClient::read_from_disk(&config) {
Ok(l) => l, Ok(l) => l,
Err(e) => { Err(e) => {
@@ -47,7 +145,7 @@ pub extern fn litelib_initialze_existing(dangerous: bool, server: *const c_char)
} }
}; };
LIGHTCLIENT.lock().unwrap().replace(Some(lightclient)); LIGHTCLIENT.lock().unwrap().replace(Some(Arc::new(lightclient)));
let c_str = CString::new("OK").unwrap(); let c_str = CString::new("OK").unwrap();
return c_str.into_raw(); return c_str.into_raw();
@@ -69,16 +167,21 @@ pub extern fn litelib_execute(cmd: *const c_char, args: *const c_char) -> *mut c
let resp: String; let resp: String;
{ {
let lc = LIGHTCLIENT.lock().unwrap(); let lightclient: Arc<LightClient>;
{
let lc = LIGHTCLIENT.lock().unwrap();
if lc.borrow().is_none() { if lc.borrow().is_none() {
let e_str = CString::new("Error: Light Client is not initialized").unwrap(); let e_str = CString::new("Error: Light Client is not initialized").unwrap();
return e_str.into_raw(); return e_str.into_raw();
} }
lightclient = lc.borrow().as_ref().unwrap().clone();
};
let args = if arg_str.is_empty() { vec![] } else { vec![arg_str.as_ref()] }; 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(); resp = commands::do_user_command(&cmd_str, &args, lightclient.as_ref()).clone();
}; };
let c_str = CString::new(resp.as_bytes()).unwrap(); let c_str = CString::new(resp.as_bytes()).unwrap();
Binary file not shown.
+537 -1003
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.
+557 -1039
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.
+316 -397
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.
+314 -415
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
Binary file not shown.
+311 -412
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.
+5 -5
View File
@@ -215,7 +215,7 @@
</message> </message>
<message> <message>
<location filename="../src/mainwindow.ui" line="864"/> <location filename="../src/mainwindow.ui" line="864"/>
<source>You are currently not mining</source> <source>This is a Lightwallet, you cant mine with it! not mining</source>
<translation type="unfinished">YOUR_TRANSLATION_HERE</translation> <translation type="unfinished">YOUR_TRANSLATION_HERE</translation>
</message> </message>
<message> <message>
@@ -228,17 +228,17 @@
</message> </message>
<message> <message>
<location filename="../src/mainwindow.ui" line="891"/> <location filename="../src/mainwindow.ui" line="891"/>
<source>Block height</source> <source>Blockheight</source>
<translation type="unfinished">YOUR_TRANSLATION_HERE</translation> <translation type="unfinished">YOUR_TRANSLATION_HERE</translation>
</message> </message>
<message> <message>
<location filename="../src/mainwindow.ui" line="905"/> <location filename="../src/mainwindow.ui" line="905"/>
<source>Network solution rate</source> <source>Version hushd light rate</source>
<translation type="unfinished">YOUR_TRANSLATION_HERE</translation> <translation type="unfinished">YOUR_TRANSLATION_HERE</translation>
</message> </message>
<message> <message>
<location filename="../src/mainwindow.ui" line="912"/> <location filename="../src/mainwindow.ui" line="912"/>
<source>Connections</source> <source>Vendor</source>
<translation type="unfinished">YOUR_TRANSLATION_HERE</translation> <translation type="unfinished">YOUR_TRANSLATION_HERE</translation>
</message> </message>
<message> <message>
@@ -659,7 +659,7 @@ Not starting embedded hushd because --no-embedded was passed</source>
</message> </message>
<message> <message>
<location filename="../src/rpc.cpp" line="578"/> <location filename="../src/rpc.cpp" line="578"/>
<source>Block height</source> <source>Blockheight</source>
<translation type="unfinished">YOUR_TRANSLATION_HERE</translation> <translation type="unfinished">YOUR_TRANSLATION_HERE</translation>
</message> </message>
<message> <message>
Binary file not shown.
+334 -346
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.
+326 -369
View File
File diff suppressed because it is too large Load Diff
+6
View File
@@ -36,6 +36,7 @@ UI_DIR = src
CONFIG += c++14 CONFIG += c++14
SOURCES += \ SOURCES += \
src/firsttimewizard.cpp \
src/main.cpp \ src/main.cpp \
src/mainwindow.cpp \ src/mainwindow.cpp \
src/balancestablemodel.cpp \ src/balancestablemodel.cpp \
@@ -62,6 +63,7 @@ SOURCES += \
src/liteinterface.cpp src/liteinterface.cpp
HEADERS += \ HEADERS += \
src/firsttimewizard.h \
src/mainwindow.h \ src/mainwindow.h \
src/precompiled.h \ src/precompiled.h \
src/balancestablemodel.h \ src/balancestablemodel.h \
@@ -91,7 +93,10 @@ HEADERS += \
FORMS += \ FORMS += \
src/mainwindow.ui \ src/mainwindow.ui \
src/migration.ui \ src/migration.ui \
src/newseed.ui \
src/newwallet.ui \
src/recurringpayments.ui \ src/recurringpayments.ui \
src/restoreseed.ui \
src/settings.ui \ src/settings.ui \
src/about.ui \ src/about.ui \
src/confirm.ui \ src/confirm.ui \
@@ -116,6 +121,7 @@ TRANSLATIONS = res/zec_qt_wallet_es.ts \
res/zec_qt_wallet_zh.ts \ res/zec_qt_wallet_zh.ts \
res/zec_qt_wallet_tr.ts res/zec_qt_wallet_tr.ts
include(singleapplication/singleapplication.pri) include(singleapplication/singleapplication.pri)
DEFINES += QAPPLICATION_CLASS=QApplication DEFINES += QAPPLICATION_CLASS=QApplication
BIN
View File
Binary file not shown.
+3 -4
View File
@@ -2,12 +2,11 @@
#include "addressbook.h" #include "addressbook.h"
#include "settings.h" #include "settings.h"
BalancesTableModel::BalancesTableModel(QObject *parent) BalancesTableModel::BalancesTableModel(QObject *parent)
: QAbstractTableModel(parent) { : QAbstractTableModel(parent) {
} }
void BalancesTableModel::setNewData(const QMap<QString, qint64> balances, void BalancesTableModel::setNewData(const QMap<QString, double> balances,
const QList<UnspentOutput> outputs) const QList<UnspentOutput> outputs)
{ {
loading = false; loading = false;
@@ -22,7 +21,7 @@ void BalancesTableModel::setNewData(const QMap<QString, qint64> balances,
// Process the address balances into a list // Process the address balances into a list
delete modeldata; delete modeldata;
modeldata = new QList<std::tuple<QString, qint64>>(); modeldata = new QList<std::tuple<QString, double>>();
std::for_each(balances.keyBegin(), balances.keyEnd(), [=] (auto keyIt) { std::for_each(balances.keyBegin(), balances.keyEnd(), [=] (auto keyIt) {
if (balances.value(keyIt) > 0) if (balances.value(keyIt) > 0)
modeldata->push_back(std::make_tuple(keyIt, balances.value(keyIt))); modeldata->push_back(std::make_tuple(keyIt, balances.value(keyIt)));
@@ -95,7 +94,7 @@ QVariant BalancesTableModel::data(const QModelIndex &index, int role) const
if(role == Qt::ToolTipRole) { if(role == Qt::ToolTipRole) {
switch (index.column()) { switch (index.column()) {
case 0: return AddressBook::addLabelToAddress(std::get<0>(modeldata->at(index.row()))); case 0: return AddressBook::addLabelToAddress(std::get<0>(modeldata->at(index.row())));
case 1: return Settings::getUSDFromhushAmount(std::get<1>(modeldata->at(index.row()))); case 1: return Settings::getUSDFormat(std::get<1>(modeldata->at(index.row())));
} }
} }
+3 -2
View File
@@ -4,13 +4,14 @@
#include "precompiled.h" #include "precompiled.h"
#include "datamodel.h" #include "datamodel.h"
class BalancesTableModel : public QAbstractTableModel class BalancesTableModel : public QAbstractTableModel
{ {
public: public:
BalancesTableModel(QObject* parent); BalancesTableModel(QObject* parent);
~BalancesTableModel(); ~BalancesTableModel();
void setNewData(const QMap<QString, qint64> balances, const QList<UnspentOutput> outputs); void setNewData(const QMap<QString, double> balances, const QList<UnspentOutput> outputs);
int rowCount(const QModelIndex &parent) const; int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const; int columnCount(const QModelIndex &parent) const;
@@ -18,7 +19,7 @@ public:
QVariant headerData(int section, Qt::Orientation orientation, int role) const; QVariant headerData(int section, Qt::Orientation orientation, int role) const;
private: private:
QList<std::tuple<QString, qint64>>* modeldata = nullptr; QList<std::tuple<QString, double>>* modeldata = nullptr;
QList<UnspentOutput>* utxos = nullptr; QList<UnspentOutput>* utxos = nullptr;
bool loading = true; bool loading = true;
+81 -32
View File
@@ -2,9 +2,11 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "settings.h" #include "settings.h"
#include "ui_connection.h" #include "ui_connection.h"
#include "firsttimewizard.h"
#include "ui_createhushconfdialog.h" #include "ui_createhushconfdialog.h"
#include "controller.h" #include "controller.h"
#include "../lib/silentdragonlitelib.h" #include "../lib/silentdragonlitelib.h"
#include "precompiled.h" #include "precompiled.h"
@@ -20,9 +22,12 @@ ConnectionLoader::ConnectionLoader(MainWindow* main, Controller* rpc) {
connD->setupUi(d); connD->setupUi(d);
QPixmap logo(":/img/res/logobig.gif"); QPixmap logo(":/img/res/logobig.gif");
connD->topIcon->setBasePixmap(logo.scaled(256, 256, Qt::KeepAspectRatio, Qt::SmoothTransformation)); connD->topIcon->setBasePixmap(logo.scaled(256, 256, Qt::KeepAspectRatio, Qt::SmoothTransformation));
isSyncing = new QAtomicInteger<bool>();
} }
ConnectionLoader::~ConnectionLoader() { ConnectionLoader::~ConnectionLoader() {
delete isSyncing;
delete connD; delete connD;
delete d; delete d;
} }
@@ -42,19 +47,77 @@ void ConnectionLoader::doAutoConnect() {
// Initialize the library // Initialize the library
main->logger->write(QObject::tr("Attempting to initialize")); main->logger->write(QObject::tr("Attempting to initialize"));
litelib_initialze_existing(config->dangerous, config->server.toStdString().c_str());
// Check to see if there's an existing wallet
if (litelib_wallet_exists(Settings::getChainName().toStdString().c_str())) {
main->logger->write(QObject::tr("Using existing wallet."));
litelib_initialize_existing(config->dangerous, config->server.toStdString().c_str());
} else {
main->logger->write(QObject::tr("Create/restore wallet."));
litelib_initialize_existing(config->dangerous, config->server.toStdString().c_str());
d->show();
}
auto connection = makeConnection(config); auto connection = makeConnection(config);
// After the lib is initialized, try to do get info // After the lib is initialized, try to do get info
connection->doRPC("info", "", [=](auto reply) { connection->doRPC("info", "", [=](auto reply) {
// If success, set the connection // If success, set the connection
main->logger->write("Connection is online."); main->logger->write("Connection is online.");
this->doRPCSetConnection(connection);
}, [=](auto err) {}); isSyncing = new QAtomicInteger<bool>();
isSyncing->store(true);
// Do a sync at startup
syncTimer = new QTimer(main);
connection->doRPCWithDefaultErrorHandling("sync", "", [=](auto) {
isSyncing->store(false);
// Cancel the timer
syncTimer->deleteLater();
// When sync is done, set the connection
this->doRPCSetConnection(connection);
});
// While it is syncing, we'll show the status updates while it is alive.
QObject::connect(syncTimer, &QTimer::timeout, [=]() {
// Check the sync status
if (isSyncing != nullptr && isSyncing->load()) {
// Get the sync status
connection->doRPC("syncstatus", "", [=](json reply) {
if (isSyncing != nullptr && reply.find("synced_blocks") != reply.end()) {
qint64 synced = reply["synced_blocks"].get<json::number_unsigned_t>();
qint64 total = reply["total_blocks"].get<json::number_unsigned_t>();
showInformation("Synced " + QString::number(synced) + " / " + QString::number(total));
}
},
[=](QString err) {
qDebug() << "Sync error" << err;
});
}
});
syncTimer->setInterval(1* 1000);
syncTimer->start();
}, [=](QString err) {
showError(err);
});
}
void ConnectionLoader::createOrRestore(bool dangerous, QString server) {
// Close the startup dialog, since we'll be showing the wizard
d->hide();
// Create a wizard
FirstTimeWizard wizard(dangerous, server);
wizard.exec();
} }
void ConnectionLoader::doRPCSetConnection(Connection* conn) { void ConnectionLoader::doRPCSetConnection(Connection* conn) {
qDebug() << "Connectionloader finished, setting connection";
rpc->setConnection(conn); rpc->setConnection(conn);
d->accept(); d->accept();
@@ -68,20 +131,9 @@ Connection* ConnectionLoader::makeConnection(std::shared_ptr<ConnectionConfig> c
// Update the UI with the status // Update the UI with the status
void ConnectionLoader::showInformation(QString info, QString detail) { void ConnectionLoader::showInformation(QString info, QString detail) {
static int rescanCount = 0; qDebug() << "Showing info " << info << ":" << detail;
if (detail.toLower().startsWith("rescan")) {
rescanCount++;
}
if (rescanCount > 10) {
detail = detail + "\n" + QObject::tr("This may take several hours");
}
connD->status->setText(info); connD->status->setText(info);
connD->statusDetail->setText(detail); connD->statusDetail->setText(detail);
if (rescanCount < 10)
main->logger->write(info + ":" + detail);
} }
/** /**
@@ -94,15 +146,7 @@ void ConnectionLoader::showError(QString explanation) {
d->close(); d->close();
} }
QString litelib_process_response(char* resp) {
/***********************************************************************************
* Connection, Executor and Callback Class
************************************************************************************/
void Executor::run() {
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]; char* resp_copy = new char[strlen(resp) + 1];
strcpy(resp_copy, resp); strcpy(resp_copy, resp);
litelib_rust_free_string(resp); litelib_rust_free_string(resp);
@@ -111,6 +155,17 @@ void Executor::run() {
memset(resp_copy, '-', strlen(resp_copy)); memset(resp_copy, '-', strlen(resp_copy));
delete[] resp_copy; delete[] resp_copy;
return reply;
}
/***********************************************************************************
* Connection, Executor and Callback Class
************************************************************************************/
void Executor::run() {
char* resp = litelib_execute(this->cmd.toStdString().c_str(), this->args.toStdString().c_str());
QString reply = litelib_process_response(resp);
qDebug() << "Reply=" << reply; qDebug() << "Reply=" << reply;
auto parsed = json::parse(reply.toStdString().c_str(), nullptr, false); auto parsed = json::parse(reply.toStdString().c_str(), nullptr, false);
if (parsed.is_discarded() || parsed.is_null()) { if (parsed.is_discarded() || parsed.is_null()) {
@@ -126,8 +181,6 @@ void Executor::run() {
void Callback::processRPCCallback(json resp) { void Callback::processRPCCallback(json resp) {
const bool isGuiThread = QThread::currentThread() == QCoreApplication::instance()->thread();
qDebug() << "Doing RPC callback: isGUI=" << isGuiThread;
this->cb(resp); this->cb(resp);
// Destroy self // Destroy self
@@ -135,8 +188,6 @@ void Callback::processRPCCallback(json resp) {
} }
void Callback::processError(QString resp) { void Callback::processError(QString resp) {
const bool isGuiThread = QThread::currentThread() == QCoreApplication::instance()->thread();
qDebug() << "Doing RPC callback: isGUI=" << isGuiThread;
this->errCb(resp); this->errCb(resp);
// Destroy self // Destroy self
@@ -158,9 +209,7 @@ void Connection::doRPC(const QString cmd, const QString args, const std::functio
return; return;
} }
const bool isGuiThread = qDebug() << "Doing RPC: " << cmd;
QThread::currentThread() == QCoreApplication::instance()->thread();
qDebug() << "Doing RPC: isGUI=" << isGuiThread;
// Create a runner. // Create a runner.
auto runner = new Executor(cmd, args); auto runner = new Executor(cmd, args);
+9 -4
View File
@@ -33,16 +33,21 @@ private:
void doAutoConnect(); void doAutoConnect();
void createOrRestore(bool dangerous, QString server);
void showError(QString explanation); void showError(QString explanation);
void showInformation(QString info, QString detail = ""); void showInformation(QString info, QString detail = "");
void doRPCSetConnection(Connection* conn); void doRPCSetConnection(Connection* conn);
QDialog* d; QTimer* syncTimer = nullptr;
Ui_ConnectionDialog* connD; QAtomicInteger<bool>* isSyncing = nullptr;
MainWindow* main; QDialog* d = nullptr;
Controller* rpc; Ui_ConnectionDialog* connD = nullptr;
MainWindow* main = nullptr;
Controller* rpc = nullptr;
}; };
/** /**
+68 -141
View File
@@ -64,7 +64,7 @@ void Controller::setConnection(Connection* c) {
this->zrpc->setConnection(c); this->zrpc->setConnection(c);
ui->statusBar->showMessage("Ready!"); ui->statusBar->showMessage("Your hushd is connected");
// See if we need to remove the reindex/rescan flags from the hush.conf file // See if we need to remove the reindex/rescan flags from the hush.conf file
auto hushConfLocation = Settings::getInstance()->gethushdConfLocation(); auto hushConfLocation = Settings::getInstance()->gethushdConfLocation();
@@ -96,7 +96,7 @@ void Controller::fillTxJsonParams(json& allRecepients, Tx tx) {
// Construct the JSON params // Construct the JSON params
json rec = json::object(); json rec = json::object();
rec["address"] = toAddr.addr.toStdString(); rec["address"] = toAddr.addr.toStdString();
rec["amount"] = toAddr.amount; rec["amount"] = toAddr.amount * 10000000;
if (Settings::isZAddress(toAddr.addr) && !toAddr.memo.trimmed().isEmpty()) if (Settings::isZAddress(toAddr.addr) && !toAddr.memo.trimmed().isEmpty())
rec["memo"] = toAddr.memo.toStdString(); rec["memo"] = toAddr.memo.toStdString();
@@ -120,7 +120,7 @@ void Controller::noConnection() {
main->ui->statusBar->showMessage(QObject::tr("No Connection"), 1000); main->ui->statusBar->showMessage(QObject::tr("No Connection"), 1000);
// Clear balances table. // Clear balances table.
QMap<QString, qint64> emptyBalances; QMap<QString, double> emptyBalances;
QList<UnspentOutput> emptyOutputs; QList<UnspentOutput> emptyOutputs;
balancesTableModel->setNewData(emptyBalances, emptyOutputs); balancesTableModel->setNewData(emptyBalances, emptyOutputs);
@@ -161,21 +161,25 @@ void Controller::getInfoThenRefresh(bool force) {
prevCallSucceeded = true; prevCallSucceeded = true;
// Testnet? // Testnet?
QString chainName;
if (!reply["chain_name"].is_null()) { if (!reply["chain_name"].is_null()) {
Settings::getInstance()->setTestnet(reply["chain_name"].get<json::string_t>() == "test"); chainName = QString::fromStdString(reply["chain_name"].get<json::string_t>());
Settings::getInstance()->setTestnet(chainName == "test");
}; };
// Recurring pamynets are testnet only // Recurring pamynets are testnet only
if (!Settings::getInstance()->isTestnet()) if (!Settings::getInstance()->isTestnet())
main->disableRecurring(); main->disableRecurring();
// Connected, so display checkmark.
QIcon i(":/icons/res/connected.gif");
main->statusIcon->setPixmap(i.pixmap(16, 16));
static int lastBlock = 0; static int lastBlock = 0;
int curBlock = reply["latest_block_height"].get<json::number_integer_t>(); int curBlock = reply["latest_block_height"].get<json::number_integer_t>();
model->setLatestBlock(curBlock); model->setLatestBlock(curBlock);
// Connected, so display checkmark.
QIcon i(":/icons/res/connected.gif");
main->statusLabel->setText(chainName + "(" + QString::number(curBlock) + ")");
main->statusIcon->setPixmap(i.pixmap(16, 16));
//int version = reply["version"].get<json::string_t>(); //int version = reply["version"].get<json::string_t>();
int version = 1; int version = 1;
Settings::getInstance()->sethushdVersion(version); Settings::getInstance()->sethushdVersion(version);
@@ -251,7 +255,7 @@ void Controller::updateUI(bool anyUnconfirmed) {
}; };
// Function to process reply of the listunspent and z_listunspent API calls, used below. // Function to process reply of the listunspent and z_listunspent API calls, used below.
bool Controller::processUnspent(const json& reply, QMap<QString, qint64>* balancesMap, QList<UnspentOutput>* newUtxos) { bool Controller::processUnspent(const json& reply, QMap<QString, double>* balancesMap, QList<UnspentOutput>* newUtxos) {
bool anyUnconfirmed = false; bool anyUnconfirmed = false;
auto processFn = [=](const json& array) { auto processFn = [=](const json& array) {
@@ -259,11 +263,11 @@ bool Controller::processUnspent(const json& reply, QMap<QString, qint64>* balanc
QString qsAddr = QString::fromStdString(it["address"]); QString qsAddr = QString::fromStdString(it["address"]);
int block = it["created_in_block"].get<json::number_unsigned_t>(); int block = it["created_in_block"].get<json::number_unsigned_t>();
QString txid = QString::fromStdString(it["created_in_txid"]); QString txid = QString::fromStdString(it["created_in_txid"]);
QString amount = Settings::getDecimalString(it["value"].get<json::number_unsigned_t>()); QString amount = Settings::getDecimalString(it["value"].get<json::number_float_t>());
newUtxos->push_back(UnspentOutput{ qsAddr, txid, amount, block, true }); newUtxos->push_back(UnspentOutput{ qsAddr, txid, amount, block, true });
(*balancesMap)[qsAddr] = (*balancesMap)[qsAddr] + it["value"].get<json::number_unsigned_t>(); (*balancesMap)[qsAddr] = ((*balancesMap)[qsAddr] + it["value"].get<json::number_float_t>()) /10000000;
} }
}; };
@@ -279,26 +283,28 @@ void Controller::refreshBalances() {
// 1. Get the Balances // 1. Get the Balances
zrpc->fetchBalance([=] (json reply) { zrpc->fetchBalance([=] (json reply) {
auto balT = reply["tbalance"].get<json::number_unsigned_t>(); auto balT = reply["tbalance"].get<json::number_float_t>();
auto balZ = reply["zbalance"].get<json::number_unsigned_t>(); auto balZ = reply["zbalance"].get<json::number_float_t>();
auto balTotal = balT + balZ; auto balTotal = balT + balZ;
AppDataModel::getInstance()->setBalances(balT, balZ); AppDataModel::getInstance()->setBalances(balT, balZ);
ui->balSheilded ->setText(Settings::gethushDisplayFormat(balZ)); ui->balSheilded ->setText(Settings::gethushDisplayFormat(balZ /10000000));
ui->balTransparent->setText(Settings::gethushDisplayFormat(balT)); ui->balTransparent->setText(Settings::gethushDisplayFormat(balT /10000000));
ui->balTotal ->setText(Settings::gethushDisplayFormat(balTotal)); ui->balTotal ->setText(Settings::gethushDisplayFormat(balTotal /10000000));
ui->balSheilded ->setToolTip(Settings::gethushDisplayFormat(balZ /10000000));
ui->balTransparent->setToolTip(Settings::gethushDisplayFormat(balT /10000000));
ui->balTotal ->setToolTip(Settings::gethushDisplayFormat(balTotal /10000000));
ui->balSheilded ->setToolTip(Settings::gethushDisplayFormat(balZ));
ui->balTransparent->setToolTip(Settings::gethushDisplayFormat(balT));
ui->balTotal ->setToolTip(Settings::gethushDisplayFormat(balTotal));
}); });
// 2. Get the UTXOs // 2. Get the UTXOs
// First, create a new UTXO list. It will be replacing the existing list when everything is processed. // First, create a new UTXO list. It will be replacing the existing list when everything is processed.
auto newUtxos = new QList<UnspentOutput>(); auto newUtxos = new QList<UnspentOutput>();
auto newBalances = new QMap<QString, qint64>(); auto newBalances = new QMap<QString, double>();
// Call the Transparent and Z unspent APIs serially and then, once they're done, update the UI // Call the Transparent and Z unspent APIs serially and then, once they're done, update the UI
zrpc->fetchUnspent([=] (json reply) { zrpc->fetchUnspent([=] (json reply) {
@@ -323,7 +329,7 @@ void Controller::refreshTransactions() {
for (auto& it : reply.get<json::array_t>()) { for (auto& it : reply.get<json::array_t>()) {
QString address; QString address;
qint64 total_amount; double total_amount;
QList<TransactionItemDetail> items; QList<TransactionItemDetail> items;
// First, check if there's outgoing metadata // First, check if there's outgoing metadata
@@ -331,7 +337,7 @@ void Controller::refreshTransactions() {
for (auto o: it["outgoing_metadata"].get<json::array_t>()) { for (auto o: it["outgoing_metadata"].get<json::array_t>()) {
QString address = QString::fromStdString(o["address"]); QString address = QString::fromStdString(o["address"]);
qint64 amount = -1 * o["value"].get<json::number_integer_t>(); // Sent items are -ve double amount = -1 * o["value"].get<json::number_float_t>() /10000000;// Sent items are -ve
QString memo; QString memo;
if (!o["memo"].is_null()) { if (!o["memo"].is_null()) {
@@ -363,7 +369,7 @@ void Controller::refreshTransactions() {
items.push_back(TransactionItemDetail{ items.push_back(TransactionItemDetail{
address, address,
it["amount"].get<json::number_integer_t>(), it["amount"].get<json::number_float_t>(),
"" ""
}); });
@@ -417,7 +423,7 @@ void Controller::executeTransaction(Tx tx,
std::cout << std::setw(2) << params << std::endl; std::cout << std::setw(2) << params << std::endl;
zrpc->sendTransaction(QString::fromStdString(params.dump()), [=](const json& reply) { zrpc->sendTransaction(QString::fromStdString(params.dump()), [=](const json& reply) {
if (reply["result"].is_null() || reply["result"] != "success") { if (reply.find("txid") == reply.end()) {
error("", "Couldn't understand Response: " + QString::fromStdString(reply.dump())); error("", "Couldn't understand Response: " + QString::fromStdString(reply.dump()));
} }
@@ -508,7 +514,8 @@ void Controller::refreshhushPrice() {
if (!zrpc->haveConnection()) if (!zrpc->haveConnection())
return noConnection(); return noConnection();
QUrl cmcURL("https://api.coingecko.com/api/v3/simple/price?ids=hush&vs_currencies=btc%2Cusd%2Ceur&include_market_cap=true&include_24hr_vol=true&include_24hr_change=true"); // TODO: use/render all this data
QUrl cmcURL("ncies=btc%2Cusd%2Ceur&include_market_cap=true&include_24hr_vol=true&include_24hr_change=true");
QNetworkRequest req; QNetworkRequest req;
req.setUrl(cmcURL); req.setUrl(cmcURL);
@@ -532,26 +539,33 @@ void Controller::refreshhushPrice() {
return; return;
} }
qDebug() << "No network errors";
auto all = reply->readAll(); auto all = reply->readAll();
auto parsed = json::parse(all, nullptr, false); auto parsed = json::parse(all, nullptr, false);
if (parsed.is_discarded()) { if (parsed.is_discarded()) {
Settings::getInstance()->sethushPrice(0); Settings::getInstance()->sethushPrice(0);
return; return;
} }
for (const json& item : parsed.get<json::array_t>()) { qDebug() << "Parsed JSON";
if (item["symbol"].get<json::string_t>() == Settings::getTokenName().toStdString()) {
QString price = QString::fromStdString(item["price_usd"].get<json::string_t>());
qDebug() << Settings::getTokenName() << " Price=" << price;
Settings::getInstance()->sethushPrice(price.toDouble());
return; const json& item = parsed.get<json::object_t>();
} const json& hush = item["Hush"].get<json::object_t>();
if (hush["usd"] >= 0) {
qDebug() << "Found hush key in price json";
// TODO: support BTC/EUR prices as well
QString price = QString::fromStdString(hush["usd"].get<json::string_t>());
qDebug() << "HUSH = $" << QString::number((double)hush["usd"]);
Settings::getInstance()->sethushPrice( hush["usd"] );
return;
} else {
qDebug() << "No hush key found in JSON! API might be down or we are rate-limited\n";
} }
} catch (...) { } catch (const std::exception& e) {
// If anything at all goes wrong, just set the price to 0 and move on. // If anything at all goes wrong, just set the price to 0 and move on.
qDebug() << QString("Caught something nasty"); qDebug() << QString("Caught something nasty: ") << e.what();
} }
// If nothing, then set the price to 0; // If nothing, then set the price to 0;
@@ -560,115 +574,28 @@ void Controller::refreshhushPrice() {
} }
void Controller::shutdownhushd() { void Controller::shutdownhushd() {
// Shutdown embedded hushd if it was started // Save the wallet and exit the lightclient library cleanly.
if (ehushd == nullptr || ehushd->processId() == 0 || !zrpc->haveConnection()) { if (zrpc->haveConnection()) {
// No hushd running internally, just return QDialog d(main);
return; Ui_ConnectionDialog connD;
connD.setupUi(&d);
connD.topIcon->setBasePixmap(QIcon(":/icons/res/icon.ico").pixmap(256, 256));
connD.status->setText(QObject::tr("Please wait for SilentDragonLite to exit"));
connD.statusDetail->setText(QObject::tr("Waiting for hushd to exit"));
bool finished = false;
zrpc->saveWallet([&] (json) {
if (!finished)
d.accept();
finished = true;
});
if (!finished)
d.exec();
} }
// json payload = {
// {"jsonrpc", "1.0"},
// {"id", "someid"},
// {"method", "stop"}
// };
// getConnection()->doRPCWithDefaultErrorHandling(payload, [=](auto) {});
// getConnection()->shutdown();
// QDialog d(main);
// Ui_ConnectionDialog connD;
// connD.setupUi(&d);
// connD.topIcon->setBasePixmap(QIcon(":/icons/res/icon.ico").pixmap(256, 256));
// connD.status->setText(QObject::tr("Please wait for silentdragon to exit"));
// connD.statusDetail->setText(QObject::tr("Waiting for hushd to exit"));
// QTimer waiter(main);
// // We capture by reference all the local variables because of the d.exec()
// // below, which blocks this function until we exit.
// int waitCount = 0;
// QObject::connect(&waiter, &QTimer::timeout, [&] () {
// waitCount++;
// if ((ehushd->atEnd() && ehushd->processId() == 0) ||
// waitCount > 30 ||
// getConnection()->config->hushDaemon) { // If hushd is daemon, then we don't have to do anything else
// qDebug() << "Ended";
// waiter.stop();
// QTimer::singleShot(1000, [&]() { d.accept(); });
// } else {
// qDebug() << "Not ended, continuing to wait...";
// }
// });
// waiter.start(1000);
// // Wait for the hush process to exit.
// if (!Settings::getInstance()->isHeadless()) {
// d.exec();
// } else {
// while (waiter.isActive()) {
// QCoreApplication::processEvents();
// QThread::sleep(1);
// }
// }
} }
// // Fetch the Z-board topics list
// void Controller::getZboardTopics(std::function<void(QMap<QString, QString>)> cb) {
// if (!zrpc->haveConnection())
// return noConnection();
// QUrl cmcURL("http://z-board.net/listTopics");
// QNetworkRequest req;
// req.setUrl(cmcURL);
// QNetworkReply *reply = conn->restclient->get(req);
// QObject::connect(reply, &QNetworkReply::finished, [=] {
// reply->deleteLater();
// try {
// if (reply->error() != QNetworkReply::NoError) {
// auto parsed = json::parse(reply->readAll(), nullptr, false);
// if (!parsed.is_discarded() && !parsed["error"]["message"].is_null()) {
// qDebug() << QString::fromStdString(parsed["error"]["message"]);
// }
// else {
// qDebug() << reply->errorString();
// }
// return;
// }
// auto all = reply->readAll();
// auto parsed = json::parse(all, nullptr, false);
// if (parsed.is_discarded()) {
// return;
// }
// QMap<QString, QString> topics;
// for (const json& item : parsed["topics"].get<json::array_t>()) {
// if (item.find("addr") == item.end() || item.find("topicName") == item.end())
// return;
// QString addr = QString::fromStdString(item["addr"].get<json::string_t>());
// QString topic = QString::fromStdString(item["topicName"].get<json::string_t>());
// topics.insert(topic, addr);
// }
// cb(topics);
// }
// catch (...) {
// // If anything at all goes wrong, just set the price to 0 and move on.
// qDebug() << QString("Caught something nasty");
// }
// });
// }
/** /**
* Get a Sapling address from the user's wallet * Get a Sapling address from the user's wallet
*/ */
+1 -1
View File
@@ -78,7 +78,7 @@ private:
void refreshTransactions(); void refreshTransactions();
bool processUnspent (const json& reply, QMap<QString, qint64>* newBalances, QList<UnspentOutput>* newUtxos); bool processUnspent (const json& reply, QMap<QString, double>* newBalances, QList<UnspentOutput>* newUtxos);
void updateUI (bool anyUnconfirmed); void updateUI (bool anyUnconfirmed);
void getInfoThenRefresh(bool force); void getInfoThenRefresh(bool force);
+2 -2
View File
@@ -7,7 +7,7 @@ DataModel::DataModel() {
QWriteLocker locker(lock); QWriteLocker locker(lock);
utxos = new QList<UnspentOutput>(); utxos = new QList<UnspentOutput>();
balances = new QMap<QString, qint64>(); balances = new QMap<QString, double>();
usedAddresses = new QMap<QString, bool>(); usedAddresses = new QMap<QString, bool>();
zaddresses = new QList<QString>(); zaddresses = new QList<QString>();
taddresses = new QList<QString>(); taddresses = new QList<QString>();
@@ -44,7 +44,7 @@ void DataModel::replaceTaddresses(QList<QString>* newT) {
taddresses = newT; taddresses = newT;
} }
void DataModel::replaceBalances(QMap<QString, qint64>* newBalances) { void DataModel::replaceBalances(QMap<QString, double>* newBalances) {
QWriteLocker locker(lock); QWriteLocker locker(lock);
Q_ASSERT(newBalances); Q_ASSERT(newBalances);
+4 -4
View File
@@ -18,7 +18,7 @@ class DataModel {
public: public:
void replaceZaddresses(QList<QString>* newZ); void replaceZaddresses(QList<QString>* newZ);
void replaceTaddresses(QList<QString>* newZ); void replaceTaddresses(QList<QString>* newZ);
void replaceBalances(QMap<QString, qint64>* newBalances); void replaceBalances(QMap<QString, double>* newBalances);
void replaceUTXOs(QList<UnspentOutput>* utxos); void replaceUTXOs(QList<UnspentOutput>* utxos);
void markAddressUsed(QString address); void markAddressUsed(QString address);
@@ -29,8 +29,8 @@ public:
const QList<QString> getAllZAddresses() { QReadLocker locker(lock); return *zaddresses; } const QList<QString> getAllZAddresses() { QReadLocker locker(lock); return *zaddresses; }
const QList<QString> getAllTAddresses() { QReadLocker locker(lock); return *taddresses; } const QList<QString> getAllTAddresses() { QReadLocker locker(lock); return *taddresses; }
const QList<UnspentOutput> getUTXOs() { QReadLocker locker(lock); return *utxos; } const QList<UnspentOutput> getUTXOs() { QReadLocker locker(lock); return *utxos; }
const QMap<QString, qint64> getAllBalances() { QReadLocker locker(lock); return *balances; } const QMap<QString, double> getAllBalances() { QReadLocker locker(lock); return *balances; }
const QMap<QString, bool> getUsedAddresses() { QReadLocker locker(lock); return *usedAddresses; } const QMap<QString, bool> getUsedAddresses() { QReadLocker locker(lock); return *usedAddresses; }
DataModel(); DataModel();
@@ -39,7 +39,7 @@ private:
int latestBlock; int latestBlock;
QList<UnspentOutput>* utxos = nullptr; QList<UnspentOutput>* utxos = nullptr;
QMap<QString, qint64>* balances = nullptr; QMap<QString, double>* balances = nullptr;
QMap<QString, bool>* usedAddresses = nullptr; QMap<QString, bool>* usedAddresses = nullptr;
QList<QString>* zaddresses = nullptr; QList<QString>* zaddresses = nullptr;
QList<QString>* taddresses = nullptr; QList<QString>* taddresses = nullptr;
+178
View File
@@ -0,0 +1,178 @@
#include "firsttimewizard.h"
#include "ui_newseed.h"
#include "ui_restoreseed.h"
#include "ui_newwallet.h"
#include "../lib/silentdragonlitelib.h"
using json = nlohmann::json;
FirstTimeWizard::FirstTimeWizard(bool dangerous, QString server)
{
setWindowTitle("New wallet wizard");
this->dangerous = dangerous;
this->server = server;
// Create the pages
setPage(Page_NewOrRestore, new NewOrRestorePage(this));
setPage(Page_New, new NewSeedPage(this));
setPage(Page_Restore,new RestoreSeedPage(this));
}
int FirstTimeWizard::nextId() const {
switch (currentId()) {
case Page_NewOrRestore:
if (field("intro.new").toBool()) {
return Page_New;
} else {
return Page_Restore;
}
case Page_New:
case Page_Restore:
default:
return -1;
}
}
NewOrRestorePage::NewOrRestorePage(FirstTimeWizard *parent) : QWizardPage(parent) {
setTitle("Create or Restore wallet.");
QWidget* pageWidget = new QWidget();
Ui_CreateWalletForm form;
form.setupUi(pageWidget);
// Exclusive buttons
QObject::connect(form.radioNewWallet, &QRadioButton::clicked, [=](bool checked) {
if (checked) {
form.radioRestoreWallet->setChecked(false);
}
});
QObject::connect(form.radioRestoreWallet, &QRadioButton::clicked, [=](bool checked) {
if (checked) {
form.radioNewWallet->setChecked(false);
}
});
form.radioNewWallet->setChecked(true);
registerField("intro.new", form.radioNewWallet);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(pageWidget);
setLayout(layout);
setCommitPage(true);
setButtonText(QWizard::CommitButton, "Next");
}
NewSeedPage::NewSeedPage(FirstTimeWizard *parent) : QWizardPage(parent) {
this->parent = parent;
setTitle("Your new wallet");
QWidget* pageWidget = new QWidget();
form.setupUi(pageWidget);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(pageWidget);
setLayout(layout);
}
void NewSeedPage::initializePage() {
// Call the library to create a new wallet.
char* resp = litelib_initialize_new(parent->dangerous, parent->server.toStdString().c_str());
QString reply = litelib_process_response(resp);
auto parsed = json::parse(reply.toStdString().c_str(), nullptr, false);
if (parsed.is_discarded() || parsed.is_null() || parsed.find("seed") == parsed.end()) {
form.txtSeed->setPlainText(tr("Error creating a wallet") + "\n" + reply);
} else {
QString seed = QString::fromStdString(parsed["seed"].get<json::string_t>());
form.txtSeed->setPlainText(seed);
}
}
// Will be called just before closing. Make sure we can save the seed in the wallet
// before we allow the page to be closed
bool NewSeedPage::validatePage() {
char* resp = litelib_execute("save", "");
QString reply = litelib_process_response(resp);
auto parsed = json::parse(reply.toStdString().c_str(), nullptr, false);
if (parsed.is_discarded() || parsed.is_null() || parsed.find("result") == parsed.end()) {
QMessageBox::warning(this, tr("Failed to save wallet"),
tr("Couldn't save the wallet") + "\n" + reply,
QMessageBox::Ok);
return false;
} else {
return true;
}
}
RestoreSeedPage::RestoreSeedPage(FirstTimeWizard *parent) : QWizardPage(parent) {
this->parent = parent;
setTitle("Restore wallet from seed");
QWidget* pageWidget = new QWidget();
form.setupUi(pageWidget);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(pageWidget);
setLayout(layout);
}
bool RestoreSeedPage::validatePage() {
// 1. Validate that we do have 24 words
QString seed = form.txtSeed->toPlainText().replace(QRegExp("[ \n\r\t]+"), " ");
if (seed.trimmed().split(" ").length() != 24) {
QMessageBox::warning(this, tr("Failed to restore wallet"),
tr("SilentDragonLite needs 24 words to restore wallet"),
QMessageBox::Ok);
return false;
}
// 2. Validate birthday
QString birthday_str = form.txtBirthday->text();
bool ok;
qint64 birthday = birthday_str.toUInt(&ok);
if (!ok) {
QMessageBox::warning(this, tr("Failed to parse wallet birthday"),
tr("Couldn't understand wallet birthday. This should be a block height from where to rescan the wallet. You can leave it as '0' if you don't know what it should be."),
QMessageBox::Ok);
return false;
}
// 3. Attempt to restore wallet with the seed phrase
{
char* resp = litelib_initialize_new_from_phrase(parent->dangerous, parent->server.toStdString().c_str(),
seed.toStdString().c_str(), birthday);
QString reply = litelib_process_response(resp);
if (reply.toUpper().trimmed() != "OK") {
QMessageBox::warning(this, tr("Failed to restore wallet"),
tr("Couldn't restore the wallet") + "\n" + reply,
QMessageBox::Ok);
return false;
}
}
// 4. Finally attempt to save the wallet
{
char* resp = litelib_execute("save", "");
QString reply = litelib_process_response(resp);
auto parsed = json::parse(reply.toStdString().c_str(), nullptr, false);
if (parsed.is_discarded() || parsed.is_null() || parsed.find("result") == parsed.end()) {
QMessageBox::warning(this, tr("Failed to save wallet"),
tr("Couldn't save the wallet") + "\n" + reply,
QMessageBox::Ok);
return false;
} else {
return true;
}
}
}
+66
View File
@@ -0,0 +1,66 @@
#ifndef FIRSTTIMEWIZARD_H
#define FIRSTTIMEWIZARD_H
#include "precompiled.h"
#include "ui_newseed.h"
#include "ui_restoreseed.h"
class FirstTimeWizard: public QWizard
{
public:
FirstTimeWizard(bool dangerous, QString server);
protected:
int nextId() const;
private:
enum {
Page_NewOrRestore,
Page_New,
Page_Restore
};
bool dangerous;
QString server;
friend class NewOrRestorePage;
friend class NewSeedPage;
friend class RestoreSeedPage;
};
class NewOrRestorePage: public QWizardPage {
public:
NewOrRestorePage(FirstTimeWizard* parent);
};
class NewSeedPage: public QWizardPage {
public:
NewSeedPage(FirstTimeWizard* parent);
protected:
virtual void initializePage();
virtual bool validatePage();
private:
FirstTimeWizard* parent;
Ui_NewSeedForm form;
};
class RestoreSeedPage: public QWizardPage {
public:
RestoreSeedPage(FirstTimeWizard* parent);
protected:
bool validatePage();
private:
FirstTimeWizard* parent;
Ui_RestoreSeedForm form;
};
#endif // FIRSTTIMEWIZARD_H
+8 -1
View File
@@ -39,7 +39,7 @@ void LiteInterface::createNewZaddr(bool, const std::function<void(json)>& cb) {
if (conn == nullptr) if (conn == nullptr)
return; return;
conn->doRPCWithDefaultErrorHandling("new", "zs", cb); conn->doRPCWithDefaultErrorHandling("new", "zs1", cb);
} }
void LiteInterface::createNewTaddr(const std::function<void(json)>& cb) { void LiteInterface::createNewTaddr(const std::function<void(json)>& cb) {
@@ -70,6 +70,13 @@ void LiteInterface::fetchTransactions(const std::function<void(json)>& cb) {
conn->doRPCWithDefaultErrorHandling("list", "", cb); conn->doRPCWithDefaultErrorHandling("list", "", cb);
} }
void LiteInterface::saveWallet(const std::function<void(json)>& cb) {
if (conn == nullptr)
return;
conn->doRPCWithDefaultErrorHandling("save", "", cb);
}
void LiteInterface::sendTransaction(QString params, const std::function<void(json)>& cb, void LiteInterface::sendTransaction(QString params, const std::function<void(json)>& cb,
const std::function<void(QString)>& err) { const std::function<void(QString)>& err) {
if (conn == nullptr) if (conn == nullptr)
+5 -2
View File
@@ -11,7 +11,7 @@ using json = nlohmann::json;
// into a struct with address, amount, memo // into a struct with address, amount, memo
struct TransactionItemDetail { struct TransactionItemDetail {
QString address; QString address;
qint64 amount; double amount;
QString memo; QString memo;
}; };
@@ -46,11 +46,14 @@ public:
void fetchBalance(const std::function<void(json)>& cb); void fetchBalance(const std::function<void(json)>& cb);
void createNewZaddr(bool sapling, 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 createNewTaddr(const std::function<void(json)>& cb);
void fetchPrivKey(QString addr, const std::function<void(json)>& cb); void fetchPrivKey(QString addr, const std::function<void(json)>& cb);
void fetchAllPrivKeys(const std::function<void(json)>); void fetchAllPrivKeys(const std::function<void(json)>);
void saveWallet(const std::function<void(json)>& cb);
//void importZPrivKey(QString addr, bool rescan, 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 importTPrivKey(QString addr, bool rescan, const std::function<void(json)>& cb);
+1 -1
View File
@@ -25,7 +25,7 @@ struct ToFields {
struct Tx { struct Tx {
QString fromAddr; QString fromAddr;
QList<ToFields> toAddrs; QList<ToFields> toAddrs;
double fee; double fee;
}; };
namespace Ui { namespace Ui {
+12 -12
View File
@@ -22,7 +22,7 @@
<item row="0" column="0"> <item row="0" column="0">
<widget class="QTabWidget" name="tabWidget"> <widget class="QTabWidget" name="tabWidget">
<property name="currentIndex"> <property name="currentIndex">
<number>2</number> <number>4</number>
</property> </property>
<widget class="QWidget" name="tab"> <widget class="QWidget" name="tab">
<attribute name="title"> <attribute name="title">
@@ -935,7 +935,7 @@
<item row="5" column="0" colspan="3"> <item row="5" column="0" colspan="3">
<widget class="QLabel" name="label_14"> <widget class="QLabel" name="label_14">
<property name="text"> <property name="text">
<string>You are currently not mining</string> <string>This is a Lightwallet, you cant mine with it!</string>
</property> </property>
</widget> </widget>
</item> </item>
@@ -953,7 +953,7 @@
</spacer> </spacer>
</item> </item>
<item row="2" column="2"> <item row="2" column="2">
<widget class="QLabel" name="numconnections"> <widget class="QLabel" name="version">
<property name="text"> <property name="text">
<string>Loading...</string> <string>Loading...</string>
</property> </property>
@@ -962,12 +962,12 @@
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="heightLabel"> <widget class="QLabel" name="heightLabel">
<property name="text"> <property name="text">
<string>Block height</string> <string>Blockheight</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="2"> <item row="3" column="2">
<widget class="QLabel" name="solrate"> <widget class="QLabel" name="Vendor">
<property name="text"> <property name="text">
<string>Loading...</string> <string>Loading...</string>
</property> </property>
@@ -976,19 +976,19 @@
<item row="3" column="0"> <item row="3" column="0">
<widget class="QLabel" name="label_12"> <widget class="QLabel" name="label_12">
<property name="text"> <property name="text">
<string>Network solution rate</string> <string>Version hushd light</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="2" column="0">
<widget class="QLabel" name="label_8"> <widget class="QLabel" name="label_8">
<property name="text"> <property name="text">
<string>Connections</string> <string>Vendor</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="2"> <item row="1" column="2">
<widget class="QLabel" name="blockheight"> <widget class="QLabel" name="blockHeight">
<property name="text"> <property name="text">
<string>Loading...</string> <string>Loading...</string>
</property> </property>
@@ -1122,17 +1122,17 @@
<property name="text"> <property name="text">
<string>&amp;Send Duke Feedback</string> <string>&amp;Send Duke Feedback</string>
</property> </property>
</action> </action>
<action name="actionDiscord"> <action name="actionDiscord">
<property name="text"> <property name="text">
<string>&amp;Hush Discord</string> <string>&amp;Hush Discord</string>
</property> </property>
</action> </action>
<action name="actionWebsite"> <action name="actionWebsite">
<property name="text"> <property name="text">
<string>&amp;Hush Website</string> <string>&amp;Hush Website</string>
</property> </property>
</action> </action>
<action name="actionCheck_for_Updates"> <action name="actionCheck_for_Updates">
<property name="text"> <property name="text">
<string>Check github.com for &amp;updates</string> <string>Check github.com for &amp;updates</string>
+63
View File
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>NewSeedForm</class>
<widget class="QWidget" name="NewSeedForm">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>This is your new wallet's seed phrase. PLEASE BACK IT UP SECURELY.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>The seed phrase is the only way to restore the wallet. If you forget the seed phrase, THERE IS NO WAY TO RESTORE YOUR WALLET AND THE FUNDS in it</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPlainTextEdit" name="txtSeed">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+85
View File
@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CreateWalletForm</class>
<widget class="QWidget" name="CreateWalletForm">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string/>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QRadioButton" name="radioRestoreWallet">
<property name="text">
<string>Restore wallet from seed</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Restore an existing wallet, using the 24-word seed. </string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string/>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QRadioButton" name="radioNewWallet">
<property name="text">
<string>Create a new Wallet</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Create a new wallet with a randomly generated seed.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+2
View File
@@ -17,6 +17,8 @@
#include <QAbstractTableModel> #include <QAbstractTableModel>
#include <QTranslator> #include <QTranslator>
#include <QClipboard> #include <QClipboard>
#include <QWizard>
#include <QWizardPage>
#include <QStringBuilder> #include <QStringBuilder>
#include <QAbstractItemModel> #include <QAbstractItemModel>
#include <QTableView> #include <QTableView>
+89
View File
@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>RestoreSeedForm</class>
<widget class="QWidget" name="RestoreSeedForm">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Please enter your 24-word seed below</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Wallet Seed</string>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="txtSeed">
<property name="readOnly">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Wallet Birthday</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="txtBirthday">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="font">
<font>
<pointsize>9</pointsize>
</font>
</property>
<property name="text">
<string>Wallet birthday is the block height at which the wallet had the first transaction. If you don't know this, you can leave it as &quot;0&quot; (It'll take longer to rescan)</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+1 -1
View File
@@ -315,7 +315,7 @@ bool Settings::removeFromhushConf(QString confLocation, QString option) {
} }
double Settings::getMinerFee() { double Settings::getMinerFee() {
return 0.0001; return 0.01;
} }
double Settings::getZboardAmount() { double Settings::getZboardAmount() {
+2
View File
@@ -119,6 +119,8 @@ public:
static bool addTohushConf(QString confLocation, QString line); static bool addTohushConf(QString confLocation, QString line);
static bool removeFromhushConf(QString confLocation, QString option); static bool removeFromhushConf(QString confLocation, QString option);
static QString getChainName() { return QString("test"); }
static const QString labelRegExp; static const QString labelRegExp;
static const int updateSpeed = 20 * 1000; // 10 sec static const int updateSpeed = 20 * 1000; // 10 sec