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

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
OKtadP.json Normal file
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"]}]

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>

6
lib/Cargo.lock generated
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"

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" }

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

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,32 +13,130 @@ 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
// 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_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 { let server_str = unsafe {
assert!(!server.is_null()); assert!(!server.is_null());
CStr::from_ptr(server).to_string_lossy().into_owned() 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 server = LightClientConfig::get_server_or_default(Some(server_str));
let (config, _latest_block_height) = match LightClientConfig::create(server, dangerous) { let (config, _latest_block_height) = match LightClientConfig::create(server, dangerous) {
Ok((c, h)) => (c, h), Ok((c, h)) => (c, h),
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::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
#[no_mangle]
pub extern fn litelib_initialize_existing(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::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.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

2162
res/zec_qt_wallet_pot.ts Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

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.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

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 \
@@ -115,6 +120,7 @@ TRANSLATIONS = res/zec_qt_wallet_es.ts \
res/zec_qt_wallet_it.ts \ res/zec_qt_wallet_it.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
silentdragonlite Executable file

Binary file not shown.

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())));
} }
} }

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;

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);

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;
}; };
/** /**

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)); ui->balSheilded ->setToolTip(Settings::gethushDisplayFormat(balZ /10000000));
ui->balTransparent->setToolTip(Settings::gethushDisplayFormat(balT)); ui->balTransparent->setToolTip(Settings::gethushDisplayFormat(balT /10000000));
ui->balTotal ->setToolTip(Settings::gethushDisplayFormat(balTotal)); ui->balTotal ->setToolTip(Settings::gethushDisplayFormat(balTotal /10000000));
}); });
// 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()) {
@@ -353,7 +359,7 @@ void Controller::refreshTransactions() {
it["datetime"].get<json::number_unsigned_t>(), it["datetime"].get<json::number_unsigned_t>(),
address, address,
QString::fromStdString(it["txid"]), QString::fromStdString(it["txid"]),
model->getLatestBlock() - it["block_height"].get<json::number_unsigned_t>(), model->getLatestBlock() - it["block_height"].get<json::number_unsigned_t>(),
items items
}); });
} else { } else {
@@ -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,11 +514,12 @@ 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);
QNetworkAccessManager *manager = new QNetworkAccessManager(this->main); QNetworkAccessManager *manager = new QNetworkAccessManager(this->main);
QNetworkReply *reply = manager->get(req); QNetworkReply *reply = manager->get(req);
@@ -524,34 +531,41 @@ void Controller::refreshhushPrice() {
if (reply->error() != QNetworkReply::NoError) { if (reply->error() != QNetworkReply::NoError) {
auto parsed = json::parse(reply->readAll(), nullptr, false); auto parsed = json::parse(reply->readAll(), nullptr, false);
if (!parsed.is_discarded() && !parsed["error"]["message"].is_null()) { if (!parsed.is_discarded() && !parsed["error"]["message"].is_null()) {
qDebug() << QString::fromStdString(parsed["error"]["message"]); qDebug() << QString::fromStdString(parsed["error"]["message"]);
} else { } else {
qDebug() << reply->errorString(); qDebug() << reply->errorString();
} }
Settings::getInstance()->sethushPrice(0); Settings::getInstance()->sethushPrice(0);
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
*/ */

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);

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);

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
src/firsttimewizard.cpp Normal file
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
src/firsttimewizard.h Normal file
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

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)

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;
}; };
@@ -45,12 +45,15 @@ public:
const std::function<void(QString)>& err); const std::function<void(QString)>& err);
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);

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 {

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
src/newseed.ui Normal file
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
src/newwallet.ui Normal file
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>

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
src/restoreseed.ui Normal file
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>

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() {

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