Wallet Interactive-mode, Part 1 (#295)
* cli addition to yml * first experiments with CLI mode * rustfmt * modify owner_single_use to take optional instantiated API * refactor command functions to take owner api instance * modify commands to use single owner api instance * add ability to pass customised message handler to API * prevent update wallet attempt if wallet hasn't been opened * fix output when internal updater is running * add termion, use cli for status updates, remove logging output from CLI * some attempts to clean up the command prompt and accomodate scanning intervals * rework listener slightly to allow for cli mode, add close command * remove termion dependency
This commit is contained in:
Generated
+88
@@ -314,6 +314,16 @@ dependencies = [
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colored"
|
||||
version = "1.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.5"
|
||||
@@ -488,6 +498,26 @@ dependencies = [
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_users 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "doc-comment"
|
||||
version = "0.3.1"
|
||||
@@ -913,6 +943,7 @@ version = "3.1.0-beta.1"
|
||||
dependencies = [
|
||||
"built 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"colored 1.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ctrlc 3.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"easy-jsonrpc 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -923,14 +954,17 @@ dependencies = [
|
||||
"grin_wallet_impls 3.1.0-beta.1",
|
||||
"grin_wallet_libwallet 3.1.0-beta.1",
|
||||
"grin_wallet_util 3.1.0-beta.1",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"linefeed 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"prettytable-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rpassword 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustyline 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termion 1.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@@ -1710,6 +1744,11 @@ dependencies = [
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "numtoa"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "odds"
|
||||
version = "0.2.26"
|
||||
@@ -2136,6 +2175,14 @@ name = "redox_syscall"
|
||||
version = "0.1.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "redox_termios"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.3.4"
|
||||
@@ -2251,6 +2298,23 @@ dependencies = [
|
||||
"webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustyline"
|
||||
version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"utf8parse 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.2"
|
||||
@@ -2564,6 +2628,17 @@ dependencies = [
|
||||
"phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termion"
|
||||
version = "1.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.11.0"
|
||||
@@ -2941,6 +3016,11 @@ dependencies = [
|
||||
"percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "0.7.4"
|
||||
@@ -3154,6 +3234,7 @@ dependencies = [
|
||||
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
|
||||
"checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17"
|
||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
"checksum colored 1.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8815e2ab78f3a59928fc32e141fbeece88320a240e43f47b2fd64ea3a88a5b3d"
|
||||
"checksum constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
||||
"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
|
||||
"checksum croaring 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "71152d60cec9dfdc5d9d793bccfa9ad95927372b80cd00e983db5eb2ce103e3b"
|
||||
@@ -3174,6 +3255,8 @@ dependencies = [
|
||||
"checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
|
||||
"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
|
||||
"checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901"
|
||||
"checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
|
||||
"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b"
|
||||
"checksum doc-comment 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "923dea538cea0aa3025e8685b20d6ee21ef99c4f77e954a30febbaac5ec73a97"
|
||||
"checksum dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3"
|
||||
"checksum easy-jsonrpc 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "07e05c6cb07c5bb6fdedd8de84a96c9e0aafc5a9d4e725b735ca5eddb770ae33"
|
||||
@@ -3274,6 +3357,7 @@ dependencies = [
|
||||
"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
|
||||
"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
|
||||
"checksum num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6"
|
||||
"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
|
||||
"checksum odds 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "4eae0151b9dacf24fcc170d9995e511669a082856a91f958a2fe380bfab3fb22"
|
||||
"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
||||
"checksum ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518"
|
||||
@@ -3323,6 +3407,7 @@ dependencies = [
|
||||
"checksum rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9"
|
||||
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
||||
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
|
||||
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
|
||||
"checksum redox_users 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431"
|
||||
"checksum regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8"
|
||||
"checksum regex-syntax 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)" = "b28dfe3fe9badec5dbf0a79a9cccad2cfc2ab5484bdb3e44cbd1ae8b3ba2be06"
|
||||
@@ -3336,6 +3421,7 @@ dependencies = [
|
||||
"checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084"
|
||||
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
"checksum rustls 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "942b71057b31981152970d57399c25f72e27a6ee0d207a669d8304cabf44705b"
|
||||
"checksum rustyline 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de64be8eecbe428b6924f1d8430369a01719fbb182c26fa431ddbb0a95f5315d"
|
||||
"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
|
||||
"checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
|
||||
"checksum same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
@@ -3375,6 +3461,7 @@ dependencies = [
|
||||
"checksum term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42"
|
||||
"checksum termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
|
||||
"checksum terminfo 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8e51065bafd2abe106b6036483b69d1741f4a1ec56ce8a2378de341637de689e"
|
||||
"checksum termion 1.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c22cec9d8978d906be5ac94bceb5a010d885c626c4c8855721a4dbd20e3ac905"
|
||||
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
"checksum thread-id 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7fbf4c9d56b320106cd64fd024dadfa0be7cb4706725fc44a7d7ce952d820c1"
|
||||
"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
|
||||
@@ -3414,6 +3501,7 @@ dependencies = [
|
||||
"checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f"
|
||||
"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
|
||||
"checksum url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb"
|
||||
"checksum utf8parse 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d"
|
||||
"checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a"
|
||||
"checksum vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168"
|
||||
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
|
||||
|
||||
@@ -29,6 +29,9 @@ prettytable-rs = "0.7"
|
||||
log = "0.4"
|
||||
linefeed = "0.5"
|
||||
semver = "0.9"
|
||||
rustyline = "6"
|
||||
colored = "1.6"
|
||||
lazy_static = "1"
|
||||
|
||||
grin_wallet_api = { path = "./api", version = "3.1.0-beta.1" }
|
||||
grin_wallet_impls = { path = "./impls", version = "3.1.0-beta.1" }
|
||||
|
||||
+1
-1
@@ -427,7 +427,7 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env_foreign!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_owner = Owner::new(wallet.clone());
|
||||
/// let mut api_owner = Owner::new(wallet.clone(), None);
|
||||
/// let mut api_foreign = Foreign::new(wallet.clone(), None, None);
|
||||
///
|
||||
/// // . . .
|
||||
|
||||
+49
-39
@@ -97,6 +97,8 @@ where
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `wallet_in` - A reference-counted mutex containing an implementation of the
|
||||
/// * `custom_channel` - A custom MPSC Tx/Rx pair to capture status
|
||||
/// updates
|
||||
/// [`WalletBackend`](../grin_wallet_libwallet/types/trait.WalletBackend.html) trait.
|
||||
///
|
||||
/// # Returns
|
||||
@@ -157,22 +159,30 @@ where
|
||||
/// // All wallet functions operate on an Arc::Mutex to allow multithreading where needed
|
||||
/// let mut wallet = Arc::new(Mutex::new(wallet));
|
||||
///
|
||||
/// let api_owner = Owner::new(wallet.clone());
|
||||
/// let api_owner = Owner::new(wallet.clone(), None);
|
||||
/// // .. perform wallet operations
|
||||
///
|
||||
/// ```
|
||||
|
||||
pub fn new(wallet_inst: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>) -> Self {
|
||||
let (tx, rx) = channel();
|
||||
|
||||
pub fn new(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
custom_channel: Option<Sender<StatusMessage>>,
|
||||
) -> Self {
|
||||
let updater_running = Arc::new(AtomicBool::new(false));
|
||||
let updater = Arc::new(Mutex::new(owner_updater::Updater::new(
|
||||
wallet_inst.clone(),
|
||||
updater_running.clone(),
|
||||
)));
|
||||
|
||||
let updater_messages = Arc::new(Mutex::new(vec![]));
|
||||
let _ = start_updater_log_thread(rx, updater_messages.clone());
|
||||
|
||||
let tx = match custom_channel {
|
||||
Some(c) => c,
|
||||
None => {
|
||||
let (tx, rx) = channel();
|
||||
let _ = start_updater_log_thread(rx, updater_messages.clone());
|
||||
tx
|
||||
}
|
||||
};
|
||||
|
||||
Owner {
|
||||
wallet_inst,
|
||||
@@ -221,7 +231,7 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let api_owner = Owner::new(wallet.clone());
|
||||
/// let api_owner = Owner::new(wallet.clone(), None);
|
||||
///
|
||||
/// let result = api_owner.accounts(None);
|
||||
///
|
||||
@@ -272,7 +282,7 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let api_owner = Owner::new(wallet.clone());
|
||||
/// let api_owner = Owner::new(wallet.clone(), None);
|
||||
///
|
||||
/// let result = api_owner.create_account_path(None, "account1");
|
||||
///
|
||||
@@ -319,7 +329,7 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let api_owner = Owner::new(wallet.clone());
|
||||
/// let api_owner = Owner::new(wallet.clone(), None);
|
||||
///
|
||||
/// let result = api_owner.create_account_path(None, "account1");
|
||||
///
|
||||
@@ -375,7 +385,7 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let api_owner = Owner::new(wallet.clone());
|
||||
/// let api_owner = Owner::new(wallet.clone(), None);
|
||||
/// let show_spent = false;
|
||||
/// let update_from_node = true;
|
||||
/// let tx_id = None;
|
||||
@@ -443,7 +453,7 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let api_owner = Owner::new(wallet.clone());
|
||||
/// let api_owner = Owner::new(wallet.clone(), None);
|
||||
/// let update_from_node = true;
|
||||
/// let tx_id = None;
|
||||
/// let tx_slate_id = None;
|
||||
@@ -520,7 +530,7 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_owner = Owner::new(wallet.clone());
|
||||
/// let mut api_owner = Owner::new(wallet.clone(), None);
|
||||
/// let update_from_node = true;
|
||||
/// let minimum_confirmations=10;
|
||||
///
|
||||
@@ -606,7 +616,7 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_owner = Owner::new(wallet.clone());
|
||||
/// let mut api_owner = Owner::new(wallet.clone(), None);
|
||||
/// // Attempt to create a transaction using the 'default' account
|
||||
/// let args = InitTxArgs {
|
||||
/// src_acct_name: None,
|
||||
@@ -697,7 +707,7 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_owner = Owner::new(wallet.clone());
|
||||
/// let mut api_owner = Owner::new(wallet.clone(), None);
|
||||
///
|
||||
/// let args = IssueInvoiceTxArgs {
|
||||
/// amount: 60_000_000_000,
|
||||
@@ -752,7 +762,7 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_owner = Owner::new(wallet.clone());
|
||||
/// let mut api_owner = Owner::new(wallet.clone(), None);
|
||||
///
|
||||
/// // . . .
|
||||
/// // The slate has been recieved from the invoicer, somehow
|
||||
@@ -817,7 +827,7 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_owner = Owner::new(wallet.clone());
|
||||
/// let mut api_owner = Owner::new(wallet.clone(), None);
|
||||
/// let args = InitTxArgs {
|
||||
/// src_acct_name: None,
|
||||
/// amount: 2_000_000_000,
|
||||
@@ -881,7 +891,7 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_owner = Owner::new(wallet.clone());
|
||||
/// let mut api_owner = Owner::new(wallet.clone(), None);
|
||||
/// let args = InitTxArgs {
|
||||
/// src_acct_name: None,
|
||||
/// amount: 2_000_000_000,
|
||||
@@ -941,7 +951,7 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_owner = Owner::new(wallet.clone());
|
||||
/// let mut api_owner = Owner::new(wallet.clone(), None);
|
||||
/// let args = InitTxArgs {
|
||||
/// src_acct_name: None,
|
||||
/// amount: 2_000_000_000,
|
||||
@@ -1013,7 +1023,7 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_owner = Owner::new(wallet.clone());
|
||||
/// let mut api_owner = Owner::new(wallet.clone(), None);
|
||||
/// let args = InitTxArgs {
|
||||
/// src_acct_name: None,
|
||||
/// amount: 2_000_000_000,
|
||||
@@ -1079,7 +1089,7 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let api_owner = Owner::new(wallet.clone());
|
||||
/// let api_owner = Owner::new(wallet.clone(), None);
|
||||
/// let update_from_node = true;
|
||||
/// let tx_id = None;
|
||||
/// let tx_slate_id = None;
|
||||
@@ -1129,7 +1139,7 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_owner = Owner::new(wallet.clone());
|
||||
/// let mut api_owner = Owner::new(wallet.clone(), None);
|
||||
/// let args = InitTxArgs {
|
||||
/// src_acct_name: None,
|
||||
/// amount: 2_000_000_000,
|
||||
@@ -1209,7 +1219,7 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let mut api_owner = Owner::new(wallet.clone());
|
||||
/// let mut api_owner = Owner::new(wallet.clone(), None);
|
||||
/// let result = api_owner.scan(
|
||||
/// None,
|
||||
/// Some(20000),
|
||||
@@ -1267,7 +1277,7 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let api_owner = Owner::new(wallet.clone());
|
||||
/// let api_owner = Owner::new(wallet.clone(), None);
|
||||
/// let result = api_owner.node_height(None);
|
||||
///
|
||||
/// if let Ok(node_height_result) = result {
|
||||
@@ -1324,7 +1334,7 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let api_owner = Owner::new(wallet.clone());
|
||||
/// let api_owner = Owner::new(wallet.clone(), None);
|
||||
/// let result = api_owner.get_top_level_directory();
|
||||
///
|
||||
/// if let Ok(dir) = result {
|
||||
@@ -1372,7 +1382,7 @@ where
|
||||
/// # .ok_or("Failed to convert tmpdir path to string.".to_owned())
|
||||
/// # .unwrap();
|
||||
///
|
||||
/// let api_owner = Owner::new(wallet.clone());
|
||||
/// let api_owner = Owner::new(wallet.clone(), None);
|
||||
/// let result = api_owner.set_top_level_directory(dir);
|
||||
///
|
||||
/// if let Ok(dir) = result {
|
||||
@@ -1422,7 +1432,7 @@ where
|
||||
/// # .ok_or("Failed to convert tmpdir path to string.".to_owned())
|
||||
/// # .unwrap();
|
||||
///
|
||||
/// let api_owner = Owner::new(wallet.clone());
|
||||
/// let api_owner = Owner::new(wallet.clone(), None);
|
||||
/// let _ = api_owner.set_top_level_directory(dir);
|
||||
///
|
||||
/// let result = api_owner.create_config(&ChainTypes::Mainnet, None, None, None);
|
||||
@@ -1491,7 +1501,7 @@ where
|
||||
/// # .to_str()
|
||||
/// # .ok_or("Failed to convert tmpdir path to string.".to_owned())
|
||||
/// # .unwrap();
|
||||
/// let api_owner = Owner::new(wallet.clone());
|
||||
/// let api_owner = Owner::new(wallet.clone(), None);
|
||||
/// let _ = api_owner.set_top_level_directory(dir);
|
||||
///
|
||||
/// // Create configuration
|
||||
@@ -1558,7 +1568,7 @@ where
|
||||
/// # .to_str()
|
||||
/// # .ok_or("Failed to convert tmpdir path to string.".to_owned())
|
||||
/// # .unwrap();
|
||||
/// let api_owner = Owner::new(wallet.clone());
|
||||
/// let api_owner = Owner::new(wallet.clone(), None);
|
||||
/// let _ = api_owner.set_top_level_directory(dir);
|
||||
///
|
||||
/// // Create configuration
|
||||
@@ -1617,7 +1627,7 @@ where
|
||||
/// use grin_core::global::ChainTypes;
|
||||
///
|
||||
/// // Set up as above
|
||||
/// # let api_owner = Owner::new(wallet.clone());
|
||||
/// # let api_owner = Owner::new(wallet.clone(), None);
|
||||
///
|
||||
/// let res = api_owner.close_wallet(None);
|
||||
///
|
||||
@@ -1653,7 +1663,7 @@ where
|
||||
/// use grin_core::global::ChainTypes;
|
||||
///
|
||||
/// // Set up as above
|
||||
/// # let api_owner = Owner::new(wallet.clone());
|
||||
/// # let api_owner = Owner::new(wallet.clone(), None);
|
||||
///
|
||||
/// let pw = ZeroingString::from("my_password");
|
||||
/// let res = api_owner.get_mnemonic(None, pw);
|
||||
@@ -1698,7 +1708,7 @@ where
|
||||
/// use grin_core::global::ChainTypes;
|
||||
///
|
||||
/// // Set up as above
|
||||
/// # let api_owner = Owner::new(wallet.clone());
|
||||
/// # let api_owner = Owner::new(wallet.clone(), None);
|
||||
///
|
||||
/// let old = ZeroingString::from("my_password");
|
||||
/// let new = ZeroingString::from("new_password");
|
||||
@@ -1741,7 +1751,7 @@ where
|
||||
/// use grin_core::global::ChainTypes;
|
||||
///
|
||||
/// // Set up as above
|
||||
/// # let api_owner = Owner::new(wallet.clone());
|
||||
/// # let api_owner = Owner::new(wallet.clone(), None);
|
||||
///
|
||||
/// let res = api_owner.delete_wallet(None);
|
||||
///
|
||||
@@ -1797,7 +1807,7 @@ where
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// // Set up as above
|
||||
/// # let api_owner = Owner::new(wallet.clone());
|
||||
/// # let api_owner = Owner::new(wallet.clone(), None);
|
||||
///
|
||||
/// let res = api_owner.start_updater(None, Duration::from_secs(60));
|
||||
///
|
||||
@@ -1852,7 +1862,7 @@ where
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// // Set up as above
|
||||
/// # let api_owner = Owner::new(wallet.clone());
|
||||
/// # let api_owner = Owner::new(wallet.clone(), None);
|
||||
///
|
||||
/// let res = api_owner.start_updater(None, Duration::from_secs(60));
|
||||
///
|
||||
@@ -1894,7 +1904,7 @@ where
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// // Set up as above
|
||||
/// # let api_owner = Owner::new(wallet.clone());
|
||||
/// # let api_owner = Owner::new(wallet.clone(), None);
|
||||
///
|
||||
/// let res = api_owner.start_updater(None, Duration::from_secs(60));
|
||||
///
|
||||
@@ -1958,7 +1968,7 @@ where
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// // Set up as above
|
||||
/// # let api_owner = Owner::new(wallet.clone());
|
||||
/// # let api_owner = Owner::new(wallet.clone(), None);
|
||||
///
|
||||
/// let res = api_owner.get_public_proof_address(None, 0);
|
||||
///
|
||||
@@ -1998,7 +2008,7 @@ where
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// // Set up as above
|
||||
/// # let api_owner = Owner::new(wallet.clone());
|
||||
/// # let api_owner = Owner::new(wallet.clone(), None);
|
||||
///
|
||||
/// let res = api_owner.proof_address_from_onion_v3(
|
||||
/// "2a6at2obto3uvkpkitqp4wxcg6u36qf534eucbskqciturczzc5suyid"
|
||||
@@ -2047,7 +2057,7 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let api_owner = Owner::new(wallet.clone());
|
||||
/// let api_owner = Owner::new(wallet.clone(), None);
|
||||
/// let update_from_node = true;
|
||||
/// let tx_id = None;
|
||||
/// let tx_slate_id = Some(Uuid::parse_str("0436430c-2b02-624c-2032-570501212b00").unwrap());
|
||||
@@ -2116,7 +2126,7 @@ where
|
||||
/// ```
|
||||
/// # grin_wallet_api::doctest_helper_setup_doc_env!(wallet, wallet_config);
|
||||
///
|
||||
/// let api_owner = Owner::new(wallet.clone());
|
||||
/// let api_owner = Owner::new(wallet.clone(), None);
|
||||
/// let update_from_node = true;
|
||||
/// let tx_id = None;
|
||||
/// let tx_slate_id = Some(Uuid::parse_str("0436430c-2b02-624c-2032-570501212b00").unwrap());
|
||||
|
||||
@@ -1572,7 +1572,7 @@ pub fn run_doctest_owner(
|
||||
);
|
||||
}
|
||||
|
||||
let mut api_owner = Owner::new(wallet1);
|
||||
let mut api_owner = Owner::new(wallet1, None);
|
||||
api_owner.doctest_mode = true;
|
||||
let res = if use_token {
|
||||
let owner_api = &api_owner as &dyn OwnerRpcS;
|
||||
|
||||
+104
-59
@@ -15,6 +15,7 @@
|
||||
//! Grin wallet command-line function implementations
|
||||
|
||||
use crate::api::TLSConfig;
|
||||
use crate::apiwallet::Owner;
|
||||
use crate::config::{TorConfig, WalletConfig, WALLET_CONFIG_FILE_NAME};
|
||||
use crate::core::{core, global};
|
||||
use crate::error::{Error, ErrorKind};
|
||||
@@ -22,7 +23,7 @@ use crate::impls::{create_sender, KeybaseAllChannels, SlateGetter as _, SlateRec
|
||||
use crate::impls::{PathToSlate, SlatePutter};
|
||||
use crate::keychain;
|
||||
use crate::libwallet::{
|
||||
self, InitTxArgs, IssueInvoiceTxArgs, NodeClient, PaymentProof, WalletInst, WalletLCProvider,
|
||||
self, InitTxArgs, IssueInvoiceTxArgs, NodeClient, PaymentProof, WalletLCProvider,
|
||||
};
|
||||
use crate::util::secp::key::SecretKey;
|
||||
use crate::util::{Mutex, ZeroingString};
|
||||
@@ -31,6 +32,7 @@ use grin_wallet_util::OnionV3Address;
|
||||
use serde_json as json;
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
@@ -67,7 +69,7 @@ pub struct InitArgs {
|
||||
}
|
||||
|
||||
pub fn init<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
g_args: &GlobalArgs,
|
||||
args: InitArgs,
|
||||
) -> Result<(), Error>
|
||||
@@ -76,7 +78,7 @@ where
|
||||
C: NodeClient + 'static,
|
||||
K: keychain::Keychain + 'static,
|
||||
{
|
||||
let mut w_lock = wallet.lock();
|
||||
let mut w_lock = owner_api.wallet_inst.lock();
|
||||
let p = w_lock.lc_provider()?;
|
||||
p.create_config(
|
||||
&g_args.chain_type,
|
||||
@@ -103,16 +105,13 @@ pub struct RecoverArgs {
|
||||
pub passphrase: ZeroingString,
|
||||
}
|
||||
|
||||
pub fn recover<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
args: RecoverArgs,
|
||||
) -> Result<(), Error>
|
||||
pub fn recover<L, C, K>(owner_api: &mut Owner<L, C, K>, args: RecoverArgs) -> Result<(), Error>
|
||||
where
|
||||
L: WalletLCProvider<'static, C, K> + 'static,
|
||||
C: NodeClient + 'static,
|
||||
K: keychain::Keychain + 'static,
|
||||
{
|
||||
let mut w_lock = wallet.lock();
|
||||
let mut w_lock = owner_api.wallet_inst.lock();
|
||||
let p = w_lock.lc_provider()?;
|
||||
let m = p.get_mnemonic(None, args.passphrase)?;
|
||||
show_recovery_phrase(m);
|
||||
@@ -125,12 +124,13 @@ pub struct ListenArgs {
|
||||
}
|
||||
|
||||
pub fn listen<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
keychain_mask: Arc<Mutex<Option<SecretKey>>>,
|
||||
config: &WalletConfig,
|
||||
tor_config: &TorConfig,
|
||||
args: &ListenArgs,
|
||||
g_args: &GlobalArgs,
|
||||
cli_mode: bool,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
L: WalletLCProvider<'static, C, K> + 'static,
|
||||
@@ -138,13 +138,36 @@ where
|
||||
K: keychain::Keychain + 'static,
|
||||
{
|
||||
let res = match args.method.as_str() {
|
||||
"http" => controller::foreign_listener(
|
||||
wallet.clone(),
|
||||
keychain_mask,
|
||||
&config.api_listen_addr(),
|
||||
g_args.tls_conf.clone(),
|
||||
tor_config.use_tor_listener,
|
||||
),
|
||||
"http" => {
|
||||
let wallet_inst = owner_api.wallet_inst.clone();
|
||||
let config = config.clone();
|
||||
let tor_config = tor_config.clone();
|
||||
let g_args = g_args.clone();
|
||||
let api_thread = thread::Builder::new()
|
||||
.name("wallet-http-listener".to_string())
|
||||
.spawn(move || {
|
||||
let res = controller::foreign_listener(
|
||||
wallet_inst,
|
||||
keychain_mask,
|
||||
&config.api_listen_addr(),
|
||||
g_args.tls_conf.clone(),
|
||||
tor_config.use_tor_listener,
|
||||
);
|
||||
if let Err(e) = res {
|
||||
error!("Error starting listener: {}", e);
|
||||
}
|
||||
});
|
||||
if let Ok(t) = api_thread {
|
||||
if !cli_mode {
|
||||
let r = t.join();
|
||||
if let Err(_) = r {
|
||||
error!("Error starting listener");
|
||||
return Err(ErrorKind::ListenerError.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
"keybase" => KeybaseAllChannels::new()?.listen(
|
||||
config.clone(),
|
||||
g_args.password.clone().unwrap(),
|
||||
@@ -167,7 +190,7 @@ where
|
||||
}
|
||||
|
||||
pub fn owner_api<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
keychain_mask: Option<SecretKey>,
|
||||
config: &WalletConfig,
|
||||
tor_config: &TorConfig,
|
||||
@@ -182,7 +205,7 @@ where
|
||||
// also being run at the same time
|
||||
let km = Arc::new(Mutex::new(keychain_mask));
|
||||
let res = controller::owner_listener(
|
||||
wallet,
|
||||
owner_api.wallet_inst.clone(),
|
||||
km,
|
||||
config.owner_api_listen_addr().as_str(),
|
||||
g_args.api_secret.clone(),
|
||||
@@ -202,7 +225,7 @@ pub struct AccountArgs {
|
||||
}
|
||||
|
||||
pub fn account<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
args: AccountArgs,
|
||||
) -> Result<(), Error>
|
||||
@@ -212,7 +235,7 @@ where
|
||||
K: keychain::Keychain + 'static,
|
||||
{
|
||||
if args.create.is_none() {
|
||||
let res = controller::owner_single_use(wallet, keychain_mask, |api, m| {
|
||||
let res = controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
|
||||
let acct_mappings = api.accounts(m)?;
|
||||
// give logging thread a moment to catch up
|
||||
thread::sleep(Duration::from_millis(200));
|
||||
@@ -225,7 +248,7 @@ where
|
||||
}
|
||||
} else {
|
||||
let label = args.create.unwrap();
|
||||
let res = controller::owner_single_use(wallet, keychain_mask, |api, m| {
|
||||
let res = controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
|
||||
api.create_account_path(m, &label)?;
|
||||
thread::sleep(Duration::from_millis(200));
|
||||
info!("Account: '{}' Created!", label);
|
||||
@@ -258,7 +281,7 @@ pub struct SendArgs {
|
||||
}
|
||||
|
||||
pub fn send<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
tor_config: Option<TorConfig>,
|
||||
args: SendArgs,
|
||||
@@ -269,7 +292,8 @@ where
|
||||
C: NodeClient + 'static,
|
||||
K: keychain::Keychain + 'static,
|
||||
{
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
let wallet_inst = owner_api.wallet_inst.clone();
|
||||
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
|
||||
if args.estimate_selection_strategies {
|
||||
let strategies = vec!["smallest", "all"]
|
||||
.into_iter()
|
||||
@@ -333,7 +357,7 @@ where
|
||||
None => None,
|
||||
Some(&m) => Some(m.to_owned()),
|
||||
};
|
||||
controller::foreign_single_use(wallet, km, |api| {
|
||||
controller::foreign_single_use(wallet_inst, km, |api| {
|
||||
slate = api.receive_tx(&slate, Some(&args.dest), None)?;
|
||||
Ok(())
|
||||
})?;
|
||||
@@ -374,7 +398,7 @@ pub struct ReceiveArgs {
|
||||
}
|
||||
|
||||
pub fn receive<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
g_args: &GlobalArgs,
|
||||
args: ReceiveArgs,
|
||||
@@ -389,7 +413,7 @@ where
|
||||
None => None,
|
||||
Some(&m) => Some(m.to_owned()),
|
||||
};
|
||||
controller::foreign_single_use(wallet, km, |api| {
|
||||
controller::foreign_single_use(owner_api.wallet_inst.clone(), km, |api| {
|
||||
if let Err(e) = api.verify_slate_messages(&slate) {
|
||||
error!("Error validating participant messages: {}", e);
|
||||
return Err(e);
|
||||
@@ -414,7 +438,7 @@ pub struct FinalizeArgs {
|
||||
}
|
||||
|
||||
pub fn finalize<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
args: FinalizeArgs,
|
||||
) -> Result<(), Error>
|
||||
@@ -448,7 +472,7 @@ where
|
||||
None => None,
|
||||
Some(&m) => Some(m.to_owned()),
|
||||
};
|
||||
controller::foreign_single_use(wallet.clone(), km, |api| {
|
||||
controller::foreign_single_use(owner_api.wallet_inst.clone(), km, |api| {
|
||||
if let Err(e) = api.verify_slate_messages(&slate) {
|
||||
error!("Error validating participant messages: {}", e);
|
||||
return Err(e);
|
||||
@@ -457,7 +481,7 @@ where
|
||||
Ok(())
|
||||
})?;
|
||||
} else {
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
|
||||
if let Err(e) = api.verify_slate_messages(m, &slate) {
|
||||
error!("Error validating participant messages: {}", e);
|
||||
return Err(e);
|
||||
@@ -468,7 +492,7 @@ where
|
||||
}
|
||||
|
||||
if !args.nopost {
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
|
||||
let result = api.post_tx(m, &slate.tx, args.fluff);
|
||||
match result {
|
||||
Ok(_) => {
|
||||
@@ -501,7 +525,7 @@ pub struct IssueInvoiceArgs {
|
||||
}
|
||||
|
||||
pub fn issue_invoice_tx<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
args: IssueInvoiceArgs,
|
||||
) -> Result<(), Error>
|
||||
@@ -510,7 +534,7 @@ where
|
||||
C: NodeClient + 'static,
|
||||
K: keychain::Keychain + 'static,
|
||||
{
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
|
||||
let slate = api.issue_invoice_tx(m, args.issue_args)?;
|
||||
PathToSlate((&args.dest).into()).put_tx(&slate)?;
|
||||
Ok(())
|
||||
@@ -533,7 +557,7 @@ pub struct ProcessInvoiceArgs {
|
||||
|
||||
/// Process invoice
|
||||
pub fn process_invoice<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
tor_config: Option<TorConfig>,
|
||||
args: ProcessInvoiceArgs,
|
||||
@@ -545,7 +569,8 @@ where
|
||||
K: keychain::Keychain + 'static,
|
||||
{
|
||||
let slate = PathToSlate((&args.input).into()).get_tx()?;
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
let wallet_inst = owner_api.wallet_inst.clone();
|
||||
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
|
||||
if args.estimate_selection_strategies {
|
||||
let strategies = vec!["smallest", "all"]
|
||||
.into_iter()
|
||||
@@ -611,7 +636,7 @@ where
|
||||
None => None,
|
||||
Some(&m) => Some(m.to_owned()),
|
||||
};
|
||||
controller::foreign_single_use(wallet, km, |api| {
|
||||
controller::foreign_single_use(wallet_inst, km, |api| {
|
||||
slate = api.finalize_invoice_tx(&slate)?;
|
||||
Ok(())
|
||||
})?;
|
||||
@@ -633,7 +658,7 @@ pub struct InfoArgs {
|
||||
}
|
||||
|
||||
pub fn info<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
g_args: &GlobalArgs,
|
||||
args: InfoArgs,
|
||||
@@ -644,17 +669,23 @@ where
|
||||
C: NodeClient + 'static,
|
||||
K: keychain::Keychain + 'static,
|
||||
{
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
let updater_running = owner_api.updater_running.load(Ordering::Relaxed);
|
||||
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
|
||||
let (validated, wallet_info) =
|
||||
api.retrieve_summary_info(m, true, args.minimum_confirmations)?;
|
||||
display::info(&g_args.account, &wallet_info, validated, dark_scheme);
|
||||
display::info(
|
||||
&g_args.account,
|
||||
&wallet_info,
|
||||
validated || updater_running,
|
||||
dark_scheme,
|
||||
);
|
||||
Ok(())
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn outputs<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
g_args: &GlobalArgs,
|
||||
dark_scheme: bool,
|
||||
@@ -664,10 +695,17 @@ where
|
||||
C: NodeClient + 'static,
|
||||
K: keychain::Keychain + 'static,
|
||||
{
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
let updater_running = owner_api.updater_running.load(Ordering::Relaxed);
|
||||
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
|
||||
let res = api.node_height(m)?;
|
||||
let (validated, outputs) = api.retrieve_outputs(m, g_args.show_spent, true, None)?;
|
||||
display::outputs(&g_args.account, res.height, validated, outputs, dark_scheme)?;
|
||||
display::outputs(
|
||||
&g_args.account,
|
||||
res.height,
|
||||
validated || updater_running,
|
||||
outputs,
|
||||
dark_scheme,
|
||||
)?;
|
||||
Ok(())
|
||||
})?;
|
||||
Ok(())
|
||||
@@ -680,7 +718,7 @@ pub struct TxsArgs {
|
||||
}
|
||||
|
||||
pub fn txs<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
g_args: &GlobalArgs,
|
||||
args: TxsArgs,
|
||||
@@ -691,14 +729,15 @@ where
|
||||
C: NodeClient + 'static,
|
||||
K: keychain::Keychain + 'static,
|
||||
{
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
let updater_running = owner_api.updater_running.load(Ordering::Relaxed);
|
||||
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
|
||||
let res = api.node_height(m)?;
|
||||
let (validated, txs) = api.retrieve_txs(m, true, args.id, args.tx_slate_id)?;
|
||||
let include_status = !args.id.is_some() && !args.tx_slate_id.is_some();
|
||||
display::txs(
|
||||
&g_args.account,
|
||||
res.height,
|
||||
validated,
|
||||
validated || updater_running,
|
||||
&txs,
|
||||
include_status,
|
||||
dark_scheme,
|
||||
@@ -721,7 +760,13 @@ where
|
||||
|
||||
if id.is_some() {
|
||||
let (_, outputs) = api.retrieve_outputs(m, true, false, id)?;
|
||||
display::outputs(&g_args.account, res.height, validated, outputs, dark_scheme)?;
|
||||
display::outputs(
|
||||
&g_args.account,
|
||||
res.height,
|
||||
validated || updater_running,
|
||||
outputs,
|
||||
dark_scheme,
|
||||
)?;
|
||||
// should only be one here, but just in case
|
||||
for tx in txs {
|
||||
display::tx_messages(&tx, dark_scheme)?;
|
||||
@@ -741,7 +786,7 @@ pub struct PostArgs {
|
||||
}
|
||||
|
||||
pub fn post<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
args: PostArgs,
|
||||
) -> Result<(), Error>
|
||||
@@ -752,7 +797,7 @@ where
|
||||
{
|
||||
let slate = PathToSlate((&args.input).into()).get_tx()?;
|
||||
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
|
||||
api.post_tx(m, &slate.tx, args.fluff)?;
|
||||
info!("Posted transaction");
|
||||
return Ok(());
|
||||
@@ -768,7 +813,7 @@ pub struct RepostArgs {
|
||||
}
|
||||
|
||||
pub fn repost<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
args: RepostArgs,
|
||||
) -> Result<(), Error>
|
||||
@@ -777,7 +822,7 @@ where
|
||||
C: NodeClient + 'static,
|
||||
K: keychain::Keychain + 'static,
|
||||
{
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
|
||||
let (_, txs) = api.retrieve_txs(m, true, Some(args.id), None)?;
|
||||
let stored_tx = api.get_stored_tx(m, &txs[0])?;
|
||||
if stored_tx.is_none() {
|
||||
@@ -820,7 +865,7 @@ pub struct CancelArgs {
|
||||
}
|
||||
|
||||
pub fn cancel<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
args: CancelArgs,
|
||||
) -> Result<(), Error>
|
||||
@@ -829,7 +874,7 @@ where
|
||||
C: NodeClient + 'static,
|
||||
K: keychain::Keychain + 'static,
|
||||
{
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
|
||||
let result = api.cancel_tx(m, args.tx_id, args.tx_slate_id);
|
||||
match result {
|
||||
Ok(_) => {
|
||||
@@ -852,7 +897,7 @@ pub struct CheckArgs {
|
||||
}
|
||||
|
||||
pub fn scan<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
args: CheckArgs,
|
||||
) -> Result<(), Error>
|
||||
@@ -861,7 +906,7 @@ where
|
||||
C: NodeClient + 'static,
|
||||
K: keychain::Keychain + 'static,
|
||||
{
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
|
||||
warn!("Starting output scan ...",);
|
||||
let result = api.scan(m, args.start_height, args.delete_unconfirmed);
|
||||
match result {
|
||||
@@ -881,7 +926,7 @@ where
|
||||
|
||||
/// Payment Proof Address
|
||||
pub fn address<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
g_args: &GlobalArgs,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
) -> Result<(), Error>
|
||||
@@ -890,7 +935,7 @@ where
|
||||
C: NodeClient + 'static,
|
||||
K: keychain::Keychain + 'static,
|
||||
{
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
|
||||
// Just address at derivation index 0 for now
|
||||
let pub_key = api.get_public_proof_address(m, 0)?;
|
||||
let addr = OnionV3Address::from_bytes(pub_key.to_bytes());
|
||||
@@ -912,7 +957,7 @@ pub struct ProofExportArgs {
|
||||
}
|
||||
|
||||
pub fn proof_export<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
args: ProofExportArgs,
|
||||
) -> Result<(), Error>
|
||||
@@ -921,7 +966,7 @@ where
|
||||
C: NodeClient + 'static,
|
||||
K: keychain::Keychain + 'static,
|
||||
{
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
|
||||
let result = api.retrieve_payment_proof(m, true, args.id, args.tx_slate_id);
|
||||
match result {
|
||||
Ok(p) => {
|
||||
@@ -947,7 +992,7 @@ pub struct ProofVerifyArgs {
|
||||
}
|
||||
|
||||
pub fn proof_verify<L, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
args: ProofVerifyArgs,
|
||||
) -> Result<(), Error>
|
||||
@@ -956,7 +1001,7 @@ where
|
||||
C: NodeClient + 'static,
|
||||
K: keychain::Keychain + 'static,
|
||||
{
|
||||
controller::owner_single_use(wallet.clone(), keychain_mask, |api, m| {
|
||||
controller::owner_single_use(None, keychain_mask, Some(owner_api), |api, m| {
|
||||
let mut proof_f = match File::open(&args.input_file) {
|
||||
Ok(p) => p,
|
||||
Err(e) => {
|
||||
|
||||
@@ -121,8 +121,9 @@ where
|
||||
/// Instantiate wallet Owner API for a single-use (command line) call
|
||||
/// Return a function containing a loaded API context to call
|
||||
pub fn owner_single_use<L, F, C, K>(
|
||||
wallet: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
wallet: Option<Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>>,
|
||||
keychain_mask: Option<&SecretKey>,
|
||||
api_context: Option<&mut Owner<L, C, K>>,
|
||||
f: F,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
@@ -131,7 +132,21 @@ where
|
||||
C: NodeClient + 'static,
|
||||
K: Keychain + 'static,
|
||||
{
|
||||
f(&mut Owner::new(wallet), keychain_mask)?;
|
||||
match api_context {
|
||||
Some(c) => f(c, keychain_mask)?,
|
||||
None => {
|
||||
let wallet = match wallet {
|
||||
Some(w) => w,
|
||||
None => {
|
||||
return Err(ErrorKind::GenericError(format!(
|
||||
"Instantiated wallet or Owner API context must be provided"
|
||||
))
|
||||
.into())
|
||||
}
|
||||
};
|
||||
f(&mut Owner::new(wallet, None), keychain_mask)?
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -243,6 +258,12 @@ where
|
||||
C: NodeClient + 'static,
|
||||
K: Keychain + 'static,
|
||||
{
|
||||
// Check if wallet has been opened first
|
||||
{
|
||||
let mut w_lock = wallet.lock();
|
||||
let lc = w_lock.lc_provider()?;
|
||||
let _ = lc.wallet_inst()?;
|
||||
}
|
||||
// need to keep in scope while the main listener is running
|
||||
let _tor_process = match use_tor {
|
||||
true => match init_tor_listener(wallet.clone(), keychain_mask.clone(), addr) {
|
||||
@@ -325,7 +346,7 @@ where
|
||||
}
|
||||
|
||||
fn handle_post_request(&self, req: Request<Body>) -> WalletResponseFuture {
|
||||
let api = Owner::new(self.wallet.clone());
|
||||
let api = Owner::new(self.wallet.clone(), None);
|
||||
Box::new(
|
||||
self.call_api(req, api)
|
||||
.and_then(|resp| ok(json_response_pretty(&resp))),
|
||||
@@ -600,7 +621,7 @@ where
|
||||
tor_config: Option<TorConfig>,
|
||||
running_foreign: bool,
|
||||
) -> OwnerAPIHandlerV3<L, C, K> {
|
||||
let owner_api = Owner::new(wallet.clone());
|
||||
let owner_api = Owner::new(wallet.clone(), None);
|
||||
owner_api.set_tor_config(tor_config);
|
||||
let owner_api = Arc::new(owner_api);
|
||||
OwnerAPIHandlerV3 {
|
||||
|
||||
@@ -104,6 +104,10 @@ pub enum ErrorKind {
|
||||
#[fail(display = "{}", _0)]
|
||||
ArgumentError(String),
|
||||
|
||||
/// Other
|
||||
#[fail(display = "Listener Startup Error")]
|
||||
ListenerError,
|
||||
|
||||
/// Other
|
||||
#[fail(display = "Generic error: {}", _0)]
|
||||
GenericError(String),
|
||||
|
||||
@@ -76,7 +76,7 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
let cm = global::coinbase_maturity(); // assume all testing precedes soft fork height
|
||||
|
||||
// test default accounts exist
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let accounts = api.accounts(m)?;
|
||||
assert_eq!(accounts[0].label, "default");
|
||||
assert_eq!(accounts[0].path, ExtKeychain::derive_key_id(2, 0, 0, 0, 0));
|
||||
@@ -84,7 +84,7 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
})?;
|
||||
|
||||
// add some accounts
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let new_path = api.create_account_path(m, "account1").unwrap();
|
||||
assert_eq!(new_path, ExtKeychain::derive_key_id(2, 1, 0, 0, 0));
|
||||
let new_path = api.create_account_path(m, "account2").unwrap();
|
||||
@@ -98,7 +98,7 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
})?;
|
||||
|
||||
// add account to wallet 2
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
|
||||
let new_path = api.create_account_path(m, "listener_account").unwrap();
|
||||
assert_eq!(new_path, ExtKeychain::derive_key_id(2, 1, 0, 0, 0));
|
||||
Ok(())
|
||||
@@ -126,7 +126,7 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 5, false);
|
||||
|
||||
// Should have 5 in account1 (5 spendable), 5 in account (2 spendable)
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, 12);
|
||||
@@ -147,7 +147,7 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
w.set_parent_key_id_by_name("account1")?;
|
||||
}
|
||||
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
// check last confirmed height on this account is different from above (should be 0)
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(m, false, 1)?;
|
||||
assert_eq!(wallet1_info.last_confirmed_height, 0);
|
||||
@@ -167,7 +167,7 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
wallet_inst!(wallet1, w);
|
||||
w.set_parent_key_id_by_name("default")?;
|
||||
}
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(m, false, 1)?;
|
||||
assert_eq!(wallet1_info.last_confirmed_height, 0);
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
@@ -186,7 +186,7 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
wallet_inst!(wallet1, w);
|
||||
w.set_parent_key_id_by_name("account1")?;
|
||||
}
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount: reward,
|
||||
@@ -204,7 +204,7 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, 13);
|
||||
@@ -218,7 +218,7 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
wallet_inst!(wallet1, w);
|
||||
w.set_parent_key_id_by_name("account2")?;
|
||||
}
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(m, false, 1)?;
|
||||
assert_eq!(wallet1_info.last_confirmed_height, 12);
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
@@ -230,7 +230,7 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
})?;
|
||||
|
||||
// wallet 2 should only have this tx on the listener account
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
|
||||
let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet2_refreshed);
|
||||
assert_eq!(wallet2_info.last_confirmed_height, 13);
|
||||
@@ -243,7 +243,7 @@ fn accounts_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
wallet_inst!(wallet2, w);
|
||||
w.set_parent_key_id_by_name("default")?;
|
||||
}
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
|
||||
let (_, wallet2_info) = api.retrieve_summary_info(m, false, 1)?;
|
||||
assert_eq!(wallet2_info.last_confirmed_height, 0);
|
||||
let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
|
||||
+28
-28
@@ -89,7 +89,7 @@ fn scan_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
let cm = global::coinbase_maturity() as u64; // assume all testing precedes soft fork height
|
||||
|
||||
// add some accounts
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
api.create_account_path(m, "named_account_1")?;
|
||||
api.create_account_path(m, "account_2")?;
|
||||
api.create_account_path(m, "account_3")?;
|
||||
@@ -98,7 +98,7 @@ fn scan_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
})?;
|
||||
|
||||
// add account to wallet 2
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
|
||||
api.create_account_path(m, "account_1")?;
|
||||
api.set_active_account(m, "account_1")?;
|
||||
Ok(())
|
||||
@@ -110,7 +110,7 @@ fn scan_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, bh as usize, false);
|
||||
|
||||
// Sanity check contents
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
@@ -126,7 +126,7 @@ fn scan_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
|
||||
// Accidentally delete some outputs
|
||||
let mut w1_outputs_commits = vec![];
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
w1_outputs_commits = api.retrieve_outputs(m, false, true, None)?.1;
|
||||
Ok(())
|
||||
})?;
|
||||
@@ -146,7 +146,7 @@ fn scan_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
}
|
||||
|
||||
// check we have a problem now
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
let (_, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
let (c, _) = libwallet::TxLogEntry::sum_confirmed(&txs);
|
||||
@@ -155,13 +155,13 @@ fn scan_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
})?;
|
||||
|
||||
// this should restore our missing outputs
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
api.scan(m, None, true)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// check our outputs match again
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.total, bh * reward);
|
||||
@@ -174,7 +174,7 @@ fn scan_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
})?;
|
||||
|
||||
// perform a transaction, but don't let it finish
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
// send to send
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
@@ -194,7 +194,7 @@ fn scan_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
})?;
|
||||
|
||||
// check we're all locked
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert!(wallet1_info.amount_currently_spendable == 0);
|
||||
@@ -202,13 +202,13 @@ fn scan_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
})?;
|
||||
|
||||
// unlock/restore
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
api.scan(m, None, true)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// check spendable amount again
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert_eq!(wallet1_info.amount_currently_spendable, (bh - cm) * reward);
|
||||
Ok(())
|
||||
@@ -408,7 +408,7 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
bh += 3;
|
||||
|
||||
// 0) Check repair when all is okay should leave wallet contents alone
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
api.scan(m, None, true)?;
|
||||
let info = wallet_info!(wallet1.clone(), m)?;
|
||||
assert_eq!(info.amount_currently_spendable, base_amount * 6);
|
||||
@@ -458,12 +458,12 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
// seed + BIP32 path.
|
||||
|
||||
// 1) a full restore should recover all of them:
|
||||
wallet::controller::owner_single_use(wallet3.clone(), mask3, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet3.clone()), mask3, None, |api, m| {
|
||||
api.scan(m, None, false)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet3.clone(), mask3, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet3.clone()), mask3, None, |api, m| {
|
||||
let info = wallet_info!(wallet3.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
assert_eq!(outputs.len(), 6);
|
||||
@@ -473,12 +473,12 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
})?;
|
||||
|
||||
// 2) scan should recover them into a single wallet
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
api.scan(m, None, true)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let info = wallet_info!(wallet1.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
assert_eq!(outputs.len(), 6);
|
||||
@@ -516,7 +516,7 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), miner_mask, cm, false);
|
||||
bh += cm as u64;
|
||||
|
||||
wallet::controller::owner_single_use(wallet4.clone(), mask4, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet4.clone()), mask4, None, |api, m| {
|
||||
let info = wallet_info!(wallet4.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
assert_eq!(outputs.len(), 9);
|
||||
@@ -524,12 +524,12 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet5.clone(), mask5, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet5.clone()), mask5, None, |api, m| {
|
||||
api.scan(m, None, false)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet5.clone(), mask5, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet5.clone()), mask5, None, |api, m| {
|
||||
let info = wallet_info!(wallet5.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
assert_eq!(outputs.len(), 9);
|
||||
@@ -571,7 +571,7 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
);
|
||||
bh += cm as u64;
|
||||
|
||||
wallet::controller::owner_single_use(wallet6.clone(), mask6, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet6.clone()), mask6, None, |api, m| {
|
||||
let info = wallet_info!(wallet6.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
assert_eq!(outputs.len(), 12);
|
||||
@@ -579,12 +579,12 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet6.clone(), mask6, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet6.clone()), mask6, None, |api, m| {
|
||||
api.scan(m, None, true)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet6.clone(), mask6, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet6.clone()), mask6, None, |api, m| {
|
||||
let info = wallet_info!(wallet6.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
assert_eq!(outputs.len(), 12);
|
||||
@@ -619,7 +619,7 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
bh += 3;
|
||||
|
||||
// mix it up a bit
|
||||
wallet::controller::owner_single_use(wallet7.clone(), mask7, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet7.clone()), mask7, None, |api, m| {
|
||||
api.create_account_path(m, "account_1")?;
|
||||
api.set_active_account(m, "account_1")?;
|
||||
Ok(())
|
||||
@@ -652,7 +652,7 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), miner_mask, cm, false);
|
||||
bh += cm as u64;
|
||||
|
||||
wallet::controller::owner_single_use(wallet7.clone(), mask7, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet7.clone()), mask7, None, |api, m| {
|
||||
let info = wallet_info!(wallet7.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
assert_eq!(outputs.len(), 3);
|
||||
@@ -665,7 +665,7 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet8.clone(), mask8, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet8.clone()), mask8, None, |api, m| {
|
||||
api.scan(m, None, false)?;
|
||||
let info = wallet_info!(wallet8.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
@@ -683,7 +683,7 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
// ids on account 2 as well, scan should get all outputs created
|
||||
// to now into 2 accounts
|
||||
|
||||
wallet::controller::owner_single_use(wallet9.clone(), mask9, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet9.clone()), mask9, None, |api, m| {
|
||||
api.create_account_path(m, "account_1")?;
|
||||
api.set_active_account(m, "account_1")?;
|
||||
Ok(())
|
||||
@@ -713,7 +713,7 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
bh += 3;
|
||||
let _bh = bh;
|
||||
|
||||
wallet::controller::owner_single_use(wallet9.clone(), mask9, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet9.clone()), mask9, None, |api, m| {
|
||||
let info = wallet_info!(wallet9.clone(), m)?;
|
||||
let outputs = api.retrieve_outputs(m, true, false, None)?.1;
|
||||
assert_eq!(outputs.len(), 6);
|
||||
@@ -735,7 +735,7 @@ fn two_wallets_one_seed_impl(test_dir: &'static str) -> Result<(), libwallet::Er
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, miner.clone(), miner_mask, cm, false);
|
||||
|
||||
// 7) Ensure scan creates missing accounts
|
||||
wallet::controller::owner_single_use(wallet10.clone(), mask10, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet10.clone()), mask10, None, |api, m| {
|
||||
api.scan(m, None, true)?;
|
||||
api.set_active_account(m, "account_1")?;
|
||||
let info = wallet_info!(wallet10.clone(), m)?;
|
||||
|
||||
@@ -75,14 +75,14 @@ fn file_exchange_test_impl(test_dir: &'static str) -> Result<(), libwallet::Erro
|
||||
let reward = core::consensus::REWARD;
|
||||
|
||||
// add some accounts
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
api.create_account_path(m, "mining")?;
|
||||
api.create_account_path(m, "listener")?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// add some accounts
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
|
||||
api.create_account_path(m, "account1")?;
|
||||
api.create_account_path(m, "account2")?;
|
||||
Ok(())
|
||||
@@ -104,7 +104,7 @@ fn file_exchange_test_impl(test_dir: &'static str) -> Result<(), libwallet::Erro
|
||||
let message = "sender test message, sender test message";
|
||||
|
||||
// Should have 5 in account1 (5 spendable), 5 in account (2 spendable)
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
@@ -138,7 +138,7 @@ fn file_exchange_test_impl(test_dir: &'static str) -> Result<(), libwallet::Erro
|
||||
naughty_slate.participant_data[0].message = Some("I changed the message".to_owned());
|
||||
|
||||
// verify messages on slate match
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
api.verify_slate_messages(m, &slate)?;
|
||||
assert!(api.verify_slate_messages(m, &naughty_slate).is_err());
|
||||
Ok(())
|
||||
@@ -154,7 +154,7 @@ fn file_exchange_test_impl(test_dir: &'static str) -> Result<(), libwallet::Erro
|
||||
})?;
|
||||
|
||||
// wallet 1 finalises and posts
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let mut slate = PathToSlate(receive_file.into()).get_tx()?;
|
||||
api.verify_slate_messages(m, &slate)?;
|
||||
slate = api.finalize_tx(m, &slate)?;
|
||||
@@ -167,7 +167,7 @@ fn file_exchange_test_impl(test_dir: &'static str) -> Result<(), libwallet::Erro
|
||||
bh += 3;
|
||||
|
||||
// Check total in mining account
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
@@ -176,7 +176,7 @@ fn file_exchange_test_impl(test_dir: &'static str) -> Result<(), libwallet::Erro
|
||||
})?;
|
||||
|
||||
// Check total in 'wallet 2' account
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
|
||||
let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet2_refreshed);
|
||||
assert_eq!(wallet2_info.last_confirmed_height, bh);
|
||||
@@ -185,7 +185,7 @@ fn file_exchange_test_impl(test_dir: &'static str) -> Result<(), libwallet::Erro
|
||||
})?;
|
||||
|
||||
// Check messages, all participants should have both
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (_, tx) = api.retrieve_txs(m, true, None, Some(slate.id))?;
|
||||
assert_eq!(
|
||||
tx[0].clone().messages.unwrap().messages[0].message,
|
||||
@@ -201,7 +201,7 @@ fn file_exchange_test_impl(test_dir: &'static str) -> Result<(), libwallet::Erro
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
|
||||
let (_, tx) = api.retrieve_txs(m, true, None, Some(slate.id))?;
|
||||
assert_eq!(
|
||||
tx[0].clone().messages.unwrap().messages[0].message,
|
||||
|
||||
@@ -69,7 +69,7 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
let reward = core::consensus::REWARD;
|
||||
|
||||
// add some accounts
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
api.create_account_path(m, "mining")?;
|
||||
api.create_account_path(m, "listener")?;
|
||||
Ok(())
|
||||
@@ -85,7 +85,7 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, bh as usize, false);
|
||||
|
||||
// Sanity check wallet 1 contents
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
@@ -95,7 +95,7 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
|
||||
let mut slate = Slate::blank(2);
|
||||
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
|
||||
// Wallet 2 inititates an invoice transaction, requesting payment
|
||||
let args = IssueInvoiceTxArgs {
|
||||
amount: reward * 2,
|
||||
@@ -105,7 +105,7 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
// Wallet 1 receives the invoice transaction
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
@@ -129,7 +129,7 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
})?;
|
||||
|
||||
// wallet 1 posts so wallet 2 doesn't get the mined amount
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
api.post_tx(m, &slate.tx, false)?;
|
||||
Ok(())
|
||||
})?;
|
||||
@@ -139,7 +139,7 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
bh += 3;
|
||||
|
||||
// Check transaction log for wallet 2
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
|
||||
let (_, wallet2_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert!(refreshed);
|
||||
@@ -155,7 +155,7 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
|
||||
// Check transaction log for wallet 1, ensure only 1 entry
|
||||
// exists
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert!(refreshed);
|
||||
@@ -168,7 +168,7 @@ fn invoice_tx_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
})?;
|
||||
|
||||
// Test self-sending
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
// Wallet 1 inititates an invoice transaction, requesting payment
|
||||
let args = IssueInvoiceTxArgs {
|
||||
amount: reward * 2,
|
||||
|
||||
@@ -75,7 +75,7 @@ fn no_change_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
|
||||
// send a single block's worth of transactions with minimal strategy
|
||||
let mut slate = Slate::blank(2);
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount: reward - fee,
|
||||
@@ -94,7 +94,7 @@ fn no_change_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
})?;
|
||||
|
||||
// Refresh and check transaction log for wallet 1
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask2, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask2, None, |api, m| {
|
||||
let (refreshed, txs) = api.retrieve_txs(m, true, None, Some(slate.id))?;
|
||||
assert!(refreshed);
|
||||
let tx = txs[0].clone();
|
||||
@@ -104,7 +104,7 @@ fn no_change_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
})?;
|
||||
|
||||
// ensure invoice TX works as well with no change
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
|
||||
// Wallet 2 inititates an invoice transaction, requesting payment
|
||||
let args = IssueInvoiceTxArgs {
|
||||
amount: reward - fee,
|
||||
@@ -114,7 +114,7 @@ fn no_change_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
// Wallet 1 receives the invoice transaction
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
@@ -136,13 +136,13 @@ fn no_change_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
slate = api.finalize_invoice_tx(&slate)?;
|
||||
Ok(())
|
||||
})?;
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet2.clone()), mask1, None, |api, m| {
|
||||
api.post_tx(m, &slate.tx, false)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// Refresh and check transaction log for wallet 1
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask2, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask2, None, |api, m| {
|
||||
let (refreshed, txs) = api.retrieve_txs(m, true, None, Some(slate.id))?;
|
||||
assert!(refreshed);
|
||||
for tx in txs {
|
||||
|
||||
@@ -77,7 +77,7 @@ fn payment_proofs_test_impl(test_dir: &'static str) -> Result<(), libwallet::Err
|
||||
test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, bh as usize, false);
|
||||
|
||||
let mut address = None;
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
|
||||
address = Some(api.get_public_proof_address(m, 0)?);
|
||||
Ok(())
|
||||
})?;
|
||||
@@ -86,7 +86,7 @@ fn payment_proofs_test_impl(test_dir: &'static str) -> Result<(), libwallet::Err
|
||||
println!("Public address is: {:?}", address);
|
||||
let amount = 60_000_000_000;
|
||||
let mut slate = Slate::blank(1);
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |sender_api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |sender_api, m| {
|
||||
// note this will increment the block count as part of the transaction "Posting"
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
@@ -139,7 +139,7 @@ fn payment_proofs_test_impl(test_dir: &'static str) -> Result<(), libwallet::Err
|
||||
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 2, false);
|
||||
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |sender_api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |sender_api, m| {
|
||||
// Check payment proof here
|
||||
let mut pp = sender_api.retrieve_payment_proof(m, true, None, Some(slate.id))?;
|
||||
|
||||
|
||||
+11
-11
@@ -72,14 +72,14 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
let reward = core::consensus::REWARD;
|
||||
|
||||
// add some accounts
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
api.create_account_path(m, "mining")?;
|
||||
api.create_account_path(m, "listener")?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// add some accounts
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
|
||||
api.create_account_path(m, "account1")?;
|
||||
api.create_account_path(m, "account2")?;
|
||||
Ok(())
|
||||
@@ -100,7 +100,7 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
let mut slate = Slate::blank(2);
|
||||
|
||||
// Should have 5 in account1 (5 spendable), 5 in account (2 spendable)
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
@@ -144,14 +144,14 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
}
|
||||
|
||||
// wallet 1 finalize
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
slate = PathToSlate((&receive_file).into()).get_tx()?;
|
||||
slate = api.finalize_tx(m, &slate)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// Now repost from cached
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (_, txs) = api.retrieve_txs(m, true, None, Some(slate.id))?;
|
||||
let stored_tx = api.get_stored_tx(m, &txs[0])?;
|
||||
api.post_tx(m, &stored_tx.unwrap(), false)?;
|
||||
@@ -163,7 +163,7 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
bh += 3;
|
||||
|
||||
// update/test contents of both accounts
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
@@ -176,7 +176,7 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
w.set_parent_key_id_by_name("listener")?;
|
||||
}
|
||||
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet2_refreshed);
|
||||
assert_eq!(wallet2_info.last_confirmed_height, bh);
|
||||
@@ -197,7 +197,7 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
let mut slate = Slate::blank(2);
|
||||
let amount = 60_000_000_000;
|
||||
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |sender_api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |sender_api, m| {
|
||||
// note this will increment the block count as part of the transaction "Posting"
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
@@ -219,7 +219,7 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
bh += 3;
|
||||
|
||||
// Now repost from cached
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (_, txs) = api.retrieve_txs(m, true, None, Some(slate.id))?;
|
||||
let stored_tx = api.get_stored_tx(m, &txs[0])?;
|
||||
api.post_tx(m, &stored_tx.unwrap(), false)?;
|
||||
@@ -231,7 +231,7 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
bh += 3;
|
||||
//
|
||||
// update/test contents of both accounts
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
@@ -239,7 +239,7 @@ fn file_repost_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
|
||||
let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet2_refreshed);
|
||||
assert_eq!(wallet2_info.last_confirmed_height, bh);
|
||||
|
||||
@@ -60,7 +60,7 @@ fn self_send_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
let reward = core::consensus::REWARD;
|
||||
|
||||
// add some accounts
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
api.create_account_path(m, "mining")?;
|
||||
api.create_account_path(m, "listener")?;
|
||||
Ok(())
|
||||
@@ -76,7 +76,7 @@ fn self_send_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, bh as usize, false);
|
||||
|
||||
// Should have 5 in account1 (5 spendable), 5 in account (2 spendable)
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
@@ -108,7 +108,7 @@ fn self_send_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
bh += 3;
|
||||
|
||||
// Check total in mining account
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
@@ -121,7 +121,7 @@ fn self_send_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
wallet_inst!(wallet1, w);
|
||||
w.set_parent_key_id_by_name("listener")?;
|
||||
}
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet1_refreshed);
|
||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
|
||||
@@ -77,7 +77,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 10, false);
|
||||
|
||||
// Check wallet 1 contents are as expected
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
debug!(
|
||||
"Wallet 1 Info Pre-Transaction, after {} blocks: {:?}",
|
||||
@@ -96,7 +96,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
// and a single use api for a send command
|
||||
let amount = 60_000_000_000;
|
||||
let mut slate = Slate::blank(1);
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |sender_api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |sender_api, m| {
|
||||
// note this will increment the block count as part of the transaction "Posting"
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
@@ -128,7 +128,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
})?;
|
||||
|
||||
// Check transaction log for wallet 1
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert!(refreshed);
|
||||
@@ -151,7 +151,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
})?;
|
||||
|
||||
// Check transaction log for wallet 2
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
|
||||
let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert!(refreshed);
|
||||
// we should have a transaction entry for this slate
|
||||
@@ -167,13 +167,13 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
})?;
|
||||
|
||||
// post transaction
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
api.post_tx(m, &slate.tx, false)?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// Check wallet 1 contents are as expected
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
debug!(
|
||||
"Wallet 1 Info Post Transaction, after {} blocks: {:?}",
|
||||
@@ -213,7 +213,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 3, false);
|
||||
|
||||
// refresh wallets and retrieve info/tests for each wallet after maturity
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (wallet1_refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
debug!("Wallet 1 Info: {:?}", wallet1_info);
|
||||
assert!(wallet1_refreshed);
|
||||
@@ -228,7 +228,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
|
||||
let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet2_refreshed);
|
||||
assert_eq!(wallet2_info.amount_currently_spendable, amount);
|
||||
@@ -245,7 +245,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
})?;
|
||||
|
||||
// Estimate fee and locked amount for a transaction
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |sender_api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |sender_api, m| {
|
||||
let init_args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount: amount * 2,
|
||||
@@ -279,7 +279,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
|
||||
// Send another transaction, but don't post to chain immediately and use
|
||||
// the stored transaction instead
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |sender_api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |sender_api, m| {
|
||||
// note this will increment the block count as part of the transaction "Posting"
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
@@ -297,7 +297,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |sender_api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |sender_api, m| {
|
||||
let (refreshed, _wallet1_info) = sender_api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(refreshed);
|
||||
let (_, txs) = sender_api.retrieve_txs(m, true, None, None)?;
|
||||
@@ -321,7 +321,7 @@ fn basic_transaction_api(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 3, false);
|
||||
|
||||
// check wallet2 has stored transaction
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
|
||||
let (wallet2_refreshed, wallet2_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert!(wallet2_refreshed);
|
||||
assert_eq!(wallet2_info.amount_currently_spendable, amount * 3);
|
||||
@@ -387,7 +387,7 @@ fn tx_rollback(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
|
||||
let amount = 30_000_000_000;
|
||||
let mut slate = Slate::blank(1);
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |sender_api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |sender_api, m| {
|
||||
// note this will increment the block count as part of the transaction "Posting"
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
@@ -407,7 +407,7 @@ fn tx_rollback(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
})?;
|
||||
|
||||
// Check transaction log for wallet 1
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
let (refreshed, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
println!(
|
||||
"last confirmed height: {}",
|
||||
@@ -438,7 +438,7 @@ fn tx_rollback(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
})?;
|
||||
|
||||
// Check transaction log for wallet 2
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
|
||||
let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert!(refreshed);
|
||||
let mut unconfirmed_count = 0;
|
||||
@@ -465,7 +465,7 @@ fn tx_rollback(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 5, false);
|
||||
|
||||
// Wallet 1 decides to roll back instead
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
// can't roll back coinbase
|
||||
let res = api.cancel_tx(m, Some(1), None);
|
||||
assert!(res.is_err());
|
||||
@@ -495,7 +495,7 @@ fn tx_rollback(test_dir: &'static str) -> Result<(), libwallet::Error> {
|
||||
})?;
|
||||
|
||||
// Wallet 2 rolls back
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
|
||||
let (_, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
let tx = txs
|
||||
.iter()
|
||||
|
||||
@@ -76,7 +76,7 @@ fn ttl_cutoff_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
|
||||
let amount = 60_000_000_000;
|
||||
let mut slate = Slate::blank(1);
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |sender_api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |sender_api, m| {
|
||||
// note this will increment the block count as part of the transaction "Posting"
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
@@ -103,7 +103,7 @@ fn ttl_cutoff_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
// Now mine past the block, and check again. Transaction should be gone.
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 2, false);
|
||||
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |sender_api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |sender_api, m| {
|
||||
let (_, txs) = sender_api.retrieve_txs(m, true, None, Some(slate.id))?;
|
||||
let tx = txs[0].clone();
|
||||
|
||||
@@ -113,7 +113,7 @@ fn ttl_cutoff_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
})?;
|
||||
|
||||
// Should also be gone in wallet 2, and output gone
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |sender_api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |sender_api, m| {
|
||||
let (_, txs) = sender_api.retrieve_txs(m, true, None, Some(slate.id))?;
|
||||
let tx = txs[0].clone();
|
||||
let outputs = sender_api.retrieve_outputs(m, false, true, None)?.1;
|
||||
@@ -126,7 +126,7 @@ fn ttl_cutoff_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
|
||||
// try again, except try and send off the transaction for completion beyond the expiry
|
||||
let mut slate = Slate::blank(1);
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |sender_api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |sender_api, m| {
|
||||
// note this will increment the block count as part of the transaction "Posting"
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
@@ -153,13 +153,13 @@ fn ttl_cutoff_test_impl(test_dir: &'static str) -> Result<(), libwallet::Error>
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 2, false);
|
||||
|
||||
// Wallet 2 will need to have updated past the TTL
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |sender_api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |sender_api, m| {
|
||||
let (_, _) = sender_api.retrieve_txs(m, true, None, Some(slate.id))?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// And when wallet 1 sends, should be rejected
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |_sender_api, _m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |_sender_api, _m| {
|
||||
let res = client1.send_tx_slate_direct("wallet2", &slate);
|
||||
println!("Send after TTL result is: {:?}", res);
|
||||
assert!(res.is_err());
|
||||
|
||||
@@ -69,14 +69,14 @@ fn updater_thread_test_impl(test_dir: &'static str) -> Result<(), libwallet::Err
|
||||
});
|
||||
|
||||
// add some accounts
|
||||
wallet::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet1.clone()), mask1, None, |api, m| {
|
||||
api.create_account_path(m, "mining")?;
|
||||
api.create_account_path(m, "listener")?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
// add some accounts
|
||||
wallet::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
wallet::controller::owner_single_use(Some(wallet2.clone()), mask2, None, |api, m| {
|
||||
api.create_account_path(m, "account1")?;
|
||||
api.create_account_path(m, "account2")?;
|
||||
Ok(())
|
||||
@@ -91,7 +91,7 @@ fn updater_thread_test_impl(test_dir: &'static str) -> Result<(), libwallet::Err
|
||||
let _ =
|
||||
test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, bh as usize, false);
|
||||
|
||||
let owner_api = api::Owner::new(wallet1);
|
||||
let owner_api = api::Owner::new(wallet1, None);
|
||||
owner_api.start_updater(mask1, Duration::from_secs(5))?;
|
||||
|
||||
// let updater thread run a bit
|
||||
|
||||
@@ -122,13 +122,23 @@ where
|
||||
) -> Result<(), Error> {
|
||||
self.is_running.store(true, Ordering::Relaxed);
|
||||
loop {
|
||||
let wallet_opened = {
|
||||
let mut w_lock = self.wallet_inst.lock();
|
||||
let w_provider = w_lock.lc_provider()?;
|
||||
match w_provider.wallet_inst() {
|
||||
Ok(_) => true,
|
||||
Err(_) => false,
|
||||
}
|
||||
};
|
||||
// Business goes here
|
||||
owner::update_wallet_state(
|
||||
self.wallet_inst.clone(),
|
||||
(&keychain_mask).as_ref(),
|
||||
status_send_channel,
|
||||
false,
|
||||
)?;
|
||||
if wallet_opened {
|
||||
owner::update_wallet_state(
|
||||
self.wallet_inst.clone(),
|
||||
(&keychain_mask).as_ref(),
|
||||
status_send_channel,
|
||||
false,
|
||||
)?;
|
||||
}
|
||||
if !self.is_running.load(Ordering::Relaxed) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
use crate::config::ConfigError;
|
||||
@@ -128,7 +127,12 @@ fn real_main() -> i32 {
|
||||
//config.members.as_mut().unwrap().wallet.chain_type = Some(chain_type);
|
||||
|
||||
// Load logging config
|
||||
let l = config.members.as_mut().unwrap().logging.clone().unwrap();
|
||||
let mut l = config.members.as_mut().unwrap().logging.clone().unwrap();
|
||||
// no logging to stdout if we're running cli
|
||||
match args.subcommand() {
|
||||
("cli", _) => l.log_to_stdout = true,
|
||||
_ => {}
|
||||
};
|
||||
init_logger(Some(l), None);
|
||||
info!(
|
||||
"Using wallet configuration file at {}",
|
||||
|
||||
@@ -43,6 +43,8 @@ args:
|
||||
long: api_server_address
|
||||
takes_value: true
|
||||
subcommands:
|
||||
- cli:
|
||||
about: Start the wallet in interactive CLI mode (EXPERIMENTAL and UNDER DEVELOPMENT)
|
||||
- account:
|
||||
about: List wallet accounts or create a new account
|
||||
args:
|
||||
@@ -346,6 +348,10 @@ subcommands:
|
||||
short: r
|
||||
long: recover
|
||||
takes_value: false
|
||||
- open:
|
||||
about: Opens a wallet (interactive mode only)
|
||||
- close:
|
||||
about: Closes the wallet (interactive mode only)
|
||||
- recover:
|
||||
about: Displays a recovery phrase for the wallet. (use `init -r` to perform recovery)
|
||||
- address:
|
||||
|
||||
+312
@@ -0,0 +1,312 @@
|
||||
// Copyright 2020 The Grin Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::cmd::wallet_args;
|
||||
use crate::util::secp::key::SecretKey;
|
||||
use crate::util::Mutex;
|
||||
use clap::App;
|
||||
//use colored::Colorize;
|
||||
use grin_wallet_api::Owner;
|
||||
use grin_wallet_config::{TorConfig, WalletConfig};
|
||||
use grin_wallet_controller::command::GlobalArgs;
|
||||
use grin_wallet_controller::Error;
|
||||
use grin_wallet_impls::DefaultWalletImpl;
|
||||
use grin_wallet_libwallet::{NodeClient, StatusMessage, WalletInst, WalletLCProvider};
|
||||
use grin_wallet_util::grin_keychain as keychain;
|
||||
use rustyline::completion::{Completer, FilenameCompleter, Pair};
|
||||
use rustyline::error::ReadlineError;
|
||||
use rustyline::highlight::{Highlighter, MatchingBracketHighlighter};
|
||||
use rustyline::hint::Hinter;
|
||||
use rustyline::validate::Validator;
|
||||
use rustyline::{CompletionType, Config, Context, EditMode, Editor, Helper, OutputStreamType};
|
||||
use std::borrow::Cow::{self, Borrowed, Owned};
|
||||
use std::sync::mpsc::{channel, Receiver};
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
const COLORED_PROMPT: &'static str = "\x1b[36mgrin-wallet>\x1b[0m ";
|
||||
const PROMPT: &'static str = "grin-wallet> ";
|
||||
//const HISTORY_PATH: &str = ".history";
|
||||
|
||||
// static for keeping track of current stdin buffer contents
|
||||
lazy_static! {
|
||||
static ref STDIN_CONTENTS: Mutex<String> = { Mutex::new(String::from("")) };
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! cli_message_inline {
|
||||
($fmt_string:expr, $( $arg:expr ),+) => {
|
||||
{
|
||||
use std::io::Write;
|
||||
let contents = STDIN_CONTENTS.lock();
|
||||
/* use crate::common::{is_cli, COLORED_PROMPT}; */
|
||||
/* if is_cli() { */
|
||||
print!("\r");
|
||||
print!($fmt_string, $( $arg ),*);
|
||||
print!(" {}", COLORED_PROMPT);
|
||||
print!("\x1B[J");
|
||||
print!("{}", *contents);
|
||||
std::io::stdout().flush().unwrap();
|
||||
/*} else {
|
||||
info!($fmt_string, $( $arg ),*);
|
||||
}*/
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! cli_message {
|
||||
($fmt_string:expr, $( $arg:expr ),+) => {
|
||||
{
|
||||
use std::io::Write;
|
||||
/* use crate::common::{is_cli, COLORED_PROMPT}; */
|
||||
/* if is_cli() { */
|
||||
//print!("\r");
|
||||
print!($fmt_string, $( $arg ),*);
|
||||
println!();
|
||||
std::io::stdout().flush().unwrap();
|
||||
/*} else {
|
||||
info!($fmt_string, $( $arg ),*);
|
||||
}*/
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// function to catch updates
|
||||
pub fn start_updater_thread(rx: Receiver<StatusMessage>) -> Result<(), Error> {
|
||||
let _ = thread::Builder::new()
|
||||
.name("wallet-updater-status".to_string())
|
||||
.spawn(move || loop {
|
||||
while let Ok(m) = rx.recv() {
|
||||
match m {
|
||||
StatusMessage::UpdatingOutputs(s) => cli_message_inline!("{}", s),
|
||||
StatusMessage::UpdatingTransactions(s) => cli_message_inline!("{}", s),
|
||||
StatusMessage::FullScanWarn(s) => cli_message_inline!("{}", s),
|
||||
StatusMessage::Scanning(_, m) => {
|
||||
//debug!("{}", s);
|
||||
cli_message_inline!("Scanning - {}% complete - Please Wait", m);
|
||||
}
|
||||
StatusMessage::ScanningComplete(s) => cli_message_inline!("{}", s),
|
||||
StatusMessage::UpdateWarning(s) => cli_message_inline!("{}", s),
|
||||
}
|
||||
}
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn command_loop<L, C, K>(
|
||||
wallet_inst: Arc<Mutex<Box<dyn WalletInst<'static, L, C, K>>>>,
|
||||
keychain_mask: Option<SecretKey>,
|
||||
wallet_config: &WalletConfig,
|
||||
tor_config: &TorConfig,
|
||||
global_wallet_args: &GlobalArgs,
|
||||
test_mode: bool,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
DefaultWalletImpl<'static, C>: WalletInst<'static, L, C, K>,
|
||||
L: WalletLCProvider<'static, C, K> + 'static,
|
||||
C: NodeClient + 'static,
|
||||
K: keychain::Keychain + 'static,
|
||||
{
|
||||
let editor = Config::builder()
|
||||
.history_ignore_space(true)
|
||||
.completion_type(CompletionType::List)
|
||||
.edit_mode(EditMode::Emacs)
|
||||
.output_stream(OutputStreamType::Stdout)
|
||||
.build();
|
||||
|
||||
let mut reader = Editor::with_config(editor);
|
||||
reader.set_helper(Some(EditorHelper(
|
||||
FilenameCompleter::new(),
|
||||
MatchingBracketHighlighter::new(),
|
||||
)));
|
||||
|
||||
/*let history_file = self
|
||||
.api
|
||||
.config()
|
||||
.get_data_path()
|
||||
.unwrap()
|
||||
.parent()
|
||||
.unwrap()
|
||||
.join(HISTORY_PATH);
|
||||
if history_file.exists() {
|
||||
let _ = reader.load_history(&history_file);
|
||||
}*/
|
||||
|
||||
let yml = load_yaml!("../bin/grin-wallet.yml");
|
||||
let mut app = App::from_yaml(yml).version(crate_version!());
|
||||
let mut keychain_mask = keychain_mask;
|
||||
|
||||
// catch updater messages
|
||||
let (tx, rx) = channel();
|
||||
let mut owner_api = Owner::new(wallet_inst, Some(tx));
|
||||
start_updater_thread(rx)?;
|
||||
|
||||
// start the automatic updater
|
||||
owner_api.start_updater((&keychain_mask).as_ref(), Duration::from_secs(30))?;
|
||||
let mut wallet_opened = false;
|
||||
loop {
|
||||
match reader.readline(PROMPT) {
|
||||
Ok(command) => {
|
||||
if command.is_empty() {
|
||||
continue;
|
||||
}
|
||||
// TODO tidy up a bit
|
||||
if command.to_lowercase() == "exit" {
|
||||
break;
|
||||
}
|
||||
/* use crate::common::{is_cli, COLORED_PROMPT}; */
|
||||
|
||||
// reset buffer
|
||||
{
|
||||
let mut contents = STDIN_CONTENTS.lock();
|
||||
*contents = String::from("");
|
||||
}
|
||||
|
||||
// Just add 'grin-wallet' to each command behind the scenes
|
||||
// so we don't need to maintain a separate definition file
|
||||
let augmented_command = format!("grin-wallet {}", command);
|
||||
let args =
|
||||
app.get_matches_from_safe_borrow(augmented_command.trim().split_whitespace());
|
||||
let done = match args {
|
||||
Ok(args) => {
|
||||
// handle opening /closing separately
|
||||
keychain_mask = match args.subcommand() {
|
||||
("open", Some(_)) => {
|
||||
let mut wallet_lock = owner_api.wallet_inst.lock();
|
||||
let lc = wallet_lock.lc_provider().unwrap();
|
||||
let mask = match lc.open_wallet(
|
||||
None,
|
||||
wallet_args::prompt_password(&global_wallet_args.password),
|
||||
false,
|
||||
false,
|
||||
) {
|
||||
Ok(m) => {
|
||||
wallet_opened = true;
|
||||
m
|
||||
}
|
||||
Err(e) => {
|
||||
cli_message!("{}", e);
|
||||
None
|
||||
}
|
||||
};
|
||||
if let Some(account) = args.value_of("account") {
|
||||
if wallet_opened {
|
||||
let wallet_inst = lc.wallet_inst()?;
|
||||
wallet_inst.set_parent_key_id_by_name(account)?;
|
||||
}
|
||||
}
|
||||
mask
|
||||
}
|
||||
("close", Some(_)) => {
|
||||
let mut wallet_lock = owner_api.wallet_inst.lock();
|
||||
let lc = wallet_lock.lc_provider().unwrap();
|
||||
lc.close_wallet(None)?;
|
||||
None
|
||||
}
|
||||
_ => keychain_mask,
|
||||
};
|
||||
match wallet_args::parse_and_execute(
|
||||
&mut owner_api,
|
||||
keychain_mask.clone(),
|
||||
&wallet_config,
|
||||
&tor_config,
|
||||
&global_wallet_args,
|
||||
&args,
|
||||
test_mode,
|
||||
true,
|
||||
) {
|
||||
Ok(_) => {
|
||||
cli_message!("Command '{}' completed", args.subcommand().0);
|
||||
false
|
||||
}
|
||||
Err(err) => {
|
||||
cli_message!("{}", err);
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
cli_message!("{}", err);
|
||||
false
|
||||
}
|
||||
};
|
||||
reader.add_history_entry(command);
|
||||
if done {
|
||||
println!();
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Unable to read line: {}", err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
||||
//let _ = reader.save_history(&history_file);
|
||||
}
|
||||
|
||||
struct EditorHelper(FilenameCompleter, MatchingBracketHighlighter);
|
||||
|
||||
impl Completer for EditorHelper {
|
||||
type Candidate = Pair;
|
||||
|
||||
fn complete(
|
||||
&self,
|
||||
line: &str,
|
||||
pos: usize,
|
||||
ctx: &Context<'_>,
|
||||
) -> std::result::Result<(usize, Vec<Pair>), ReadlineError> {
|
||||
self.0.complete(line, pos, ctx)
|
||||
}
|
||||
}
|
||||
|
||||
impl Hinter for EditorHelper {
|
||||
fn hint(&self, line: &str, _pos: usize, _ctx: &Context<'_>) -> Option<String> {
|
||||
let mut contents = STDIN_CONTENTS.lock();
|
||||
*contents = line.into();
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl Highlighter for EditorHelper {
|
||||
fn highlight<'l>(&self, line: &'l str, pos: usize) -> Cow<'l, str> {
|
||||
self.1.highlight(line, pos)
|
||||
}
|
||||
|
||||
fn highlight_prompt<'b, 's: 'b, 'p: 'b>(
|
||||
&'s self,
|
||||
prompt: &'p str,
|
||||
default: bool,
|
||||
) -> Cow<'b, str> {
|
||||
if default {
|
||||
Borrowed(COLORED_PROMPT)
|
||||
} else {
|
||||
Borrowed(prompt)
|
||||
}
|
||||
}
|
||||
|
||||
fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
|
||||
Owned("\x1b[1m".to_owned() + hint + "\x1b[m")
|
||||
}
|
||||
|
||||
fn highlight_char(&self, line: &str, pos: usize) -> bool {
|
||||
self.1.highlight_char(line, pos)
|
||||
}
|
||||
}
|
||||
impl Validator for EditorHelper {}
|
||||
impl Helper for EditorHelper {}
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright 2020 The Grin Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
mod cli;
|
||||
|
||||
pub use cli::command_loop;
|
||||
+91
-37
@@ -13,12 +13,15 @@
|
||||
// limitations under the License.
|
||||
|
||||
use crate::api::TLSConfig;
|
||||
use crate::cli::command_loop;
|
||||
use crate::config::GRIN_WALLET_DIR;
|
||||
use crate::util::file::get_first_line;
|
||||
use crate::util::secp::key::SecretKey;
|
||||
use crate::util::{Mutex, ZeroingString};
|
||||
/// Argument parsing and error handling for wallet commands
|
||||
use clap::ArgMatches;
|
||||
use failure::Fail;
|
||||
use grin_wallet_api::Owner;
|
||||
use grin_wallet_config::{config_file_exists, TorConfig, WalletConfig};
|
||||
use grin_wallet_controller::command;
|
||||
use grin_wallet_controller::{Error, ErrorKind};
|
||||
@@ -922,6 +925,7 @@ where
|
||||
match wallet_args.subcommand() {
|
||||
("init", Some(_)) => open_wallet = false,
|
||||
("recover", _) => open_wallet = false,
|
||||
("cli", _) => open_wallet = false,
|
||||
("owner_api", _) => {
|
||||
// If wallet exists, open it. Otherwise, that's fine too.
|
||||
let mut wallet_lock = wallet.lock();
|
||||
@@ -950,34 +954,81 @@ where
|
||||
false => None,
|
||||
};
|
||||
|
||||
let km = (&keychain_mask).as_ref();
|
||||
|
||||
let res = match wallet_args.subcommand() {
|
||||
("cli", Some(_)) => command_loop(
|
||||
wallet,
|
||||
keychain_mask,
|
||||
&wallet_config,
|
||||
&tor_config,
|
||||
&global_wallet_args,
|
||||
test_mode,
|
||||
),
|
||||
_ => {
|
||||
let mut owner_api = Owner::new(wallet, None);
|
||||
parse_and_execute(
|
||||
&mut owner_api,
|
||||
keychain_mask,
|
||||
&wallet_config,
|
||||
&tor_config,
|
||||
&global_wallet_args,
|
||||
&wallet_args,
|
||||
test_mode,
|
||||
false,
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(e) = res {
|
||||
Err(e)
|
||||
} else {
|
||||
Ok(wallet_args.subcommand().0.to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_and_execute<L, C, K>(
|
||||
owner_api: &mut Owner<L, C, K>,
|
||||
keychain_mask: Option<SecretKey>,
|
||||
wallet_config: &WalletConfig,
|
||||
tor_config: &TorConfig,
|
||||
global_wallet_args: &command::GlobalArgs,
|
||||
wallet_args: &ArgMatches,
|
||||
test_mode: bool,
|
||||
cli_mode: bool,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
DefaultWalletImpl<'static, C>: WalletInst<'static, L, C, K>,
|
||||
L: WalletLCProvider<'static, C, K> + 'static,
|
||||
C: NodeClient + 'static,
|
||||
K: keychain::Keychain + 'static,
|
||||
{
|
||||
let km = (&keychain_mask).as_ref();
|
||||
match wallet_args.subcommand() {
|
||||
("init", Some(args)) => {
|
||||
let a = arg_parse!(parse_init_args(
|
||||
wallet.clone(),
|
||||
&wallet_config,
|
||||
&global_wallet_args,
|
||||
owner_api.wallet_inst.clone(),
|
||||
wallet_config,
|
||||
global_wallet_args,
|
||||
&args,
|
||||
test_mode,
|
||||
));
|
||||
command::init(wallet, &global_wallet_args, a)
|
||||
command::init(owner_api, &global_wallet_args, a)
|
||||
}
|
||||
("recover", Some(_)) => {
|
||||
let a = arg_parse!(parse_recover_args(&global_wallet_args,));
|
||||
command::recover(wallet, a)
|
||||
command::recover(owner_api, a)
|
||||
}
|
||||
("listen", Some(args)) => {
|
||||
let mut c = wallet_config.clone();
|
||||
let mut t = tor_config.clone();
|
||||
let a = arg_parse!(parse_listen_args(&mut c, &mut t, &args));
|
||||
command::listen(
|
||||
wallet,
|
||||
owner_api,
|
||||
Arc::new(Mutex::new(keychain_mask)),
|
||||
&c,
|
||||
&t,
|
||||
&a,
|
||||
&global_wallet_args.clone(),
|
||||
cli_mode,
|
||||
)
|
||||
}
|
||||
("owner_api", Some(args)) => {
|
||||
@@ -985,47 +1036,47 @@ where
|
||||
let mut g = global_wallet_args.clone();
|
||||
g.tls_conf = None;
|
||||
arg_parse!(parse_owner_api_args(&mut c, &args));
|
||||
command::owner_api(wallet, keychain_mask, &c, &tor_config, &g)
|
||||
command::owner_api(owner_api, keychain_mask, &c, &tor_config, &g)
|
||||
}
|
||||
("web", Some(_)) => command::owner_api(
|
||||
wallet,
|
||||
owner_api,
|
||||
keychain_mask,
|
||||
&wallet_config,
|
||||
&tor_config,
|
||||
&global_wallet_args,
|
||||
wallet_config,
|
||||
tor_config,
|
||||
global_wallet_args,
|
||||
),
|
||||
("account", Some(args)) => {
|
||||
let a = arg_parse!(parse_account_args(&args));
|
||||
command::account(wallet, km, a)
|
||||
command::account(owner_api, km, a)
|
||||
}
|
||||
("send", Some(args)) => {
|
||||
let a = arg_parse!(parse_send_args(&args));
|
||||
command::send(
|
||||
wallet,
|
||||
owner_api,
|
||||
km,
|
||||
Some(tor_config),
|
||||
Some(tor_config.clone()),
|
||||
a,
|
||||
wallet_config.dark_background_color_scheme.unwrap_or(true),
|
||||
)
|
||||
}
|
||||
("receive", Some(args)) => {
|
||||
let a = arg_parse!(parse_receive_args(&args));
|
||||
command::receive(wallet, km, &global_wallet_args, a)
|
||||
command::receive(owner_api, km, &global_wallet_args, a)
|
||||
}
|
||||
("finalize", Some(args)) => {
|
||||
let a = arg_parse!(parse_finalize_args(&args));
|
||||
command::finalize(wallet, km, a)
|
||||
command::finalize(owner_api, km, a)
|
||||
}
|
||||
("invoice", Some(args)) => {
|
||||
let a = arg_parse!(parse_issue_invoice_args(&args));
|
||||
command::issue_invoice_tx(wallet, km, a)
|
||||
command::issue_invoice_tx(owner_api, km, a)
|
||||
}
|
||||
("pay", Some(args)) => {
|
||||
let a = arg_parse!(parse_process_invoice_args(&args, !test_mode));
|
||||
command::process_invoice(
|
||||
wallet,
|
||||
owner_api,
|
||||
km,
|
||||
Some(tor_config),
|
||||
Some(tor_config.clone()),
|
||||
a,
|
||||
wallet_config.dark_background_color_scheme.unwrap_or(true),
|
||||
)
|
||||
@@ -1033,15 +1084,15 @@ where
|
||||
("info", Some(args)) => {
|
||||
let a = arg_parse!(parse_info_args(&args));
|
||||
command::info(
|
||||
wallet,
|
||||
owner_api,
|
||||
km,
|
||||
&global_wallet_args,
|
||||
global_wallet_args,
|
||||
a,
|
||||
wallet_config.dark_background_color_scheme.unwrap_or(true),
|
||||
)
|
||||
}
|
||||
("outputs", Some(_)) => command::outputs(
|
||||
wallet,
|
||||
owner_api,
|
||||
km,
|
||||
&global_wallet_args,
|
||||
wallet_config.dark_background_color_scheme.unwrap_or(true),
|
||||
@@ -1049,7 +1100,7 @@ where
|
||||
("txs", Some(args)) => {
|
||||
let a = arg_parse!(parse_txs_args(&args));
|
||||
command::txs(
|
||||
wallet,
|
||||
owner_api,
|
||||
km,
|
||||
&global_wallet_args,
|
||||
a,
|
||||
@@ -1058,37 +1109,40 @@ where
|
||||
}
|
||||
("post", Some(args)) => {
|
||||
let a = arg_parse!(parse_post_args(&args));
|
||||
command::post(wallet, km, a)
|
||||
command::post(owner_api, km, a)
|
||||
}
|
||||
("repost", Some(args)) => {
|
||||
let a = arg_parse!(parse_repost_args(&args));
|
||||
command::repost(wallet, km, a)
|
||||
command::repost(owner_api, km, a)
|
||||
}
|
||||
("cancel", Some(args)) => {
|
||||
let a = arg_parse!(parse_cancel_args(&args));
|
||||
command::cancel(wallet, km, a)
|
||||
command::cancel(owner_api, km, a)
|
||||
}
|
||||
("export_proof", Some(args)) => {
|
||||
let a = arg_parse!(parse_export_proof_args(&args));
|
||||
command::proof_export(wallet, km, a)
|
||||
command::proof_export(owner_api, km, a)
|
||||
}
|
||||
("verify_proof", Some(args)) => {
|
||||
let a = arg_parse!(parse_verify_proof_args(&args));
|
||||
command::proof_verify(wallet, km, a)
|
||||
command::proof_verify(owner_api, km, a)
|
||||
}
|
||||
("address", Some(_)) => command::address(wallet, &global_wallet_args, km),
|
||||
("address", Some(_)) => command::address(owner_api, &global_wallet_args, km),
|
||||
("scan", Some(args)) => {
|
||||
let a = arg_parse!(parse_check_args(&args));
|
||||
command::scan(wallet, km, a)
|
||||
command::scan(owner_api, km, a)
|
||||
}
|
||||
("open", Some(_)) => {
|
||||
// for CLI mode only, should be handled externally
|
||||
Ok(())
|
||||
}
|
||||
("close", Some(_)) => {
|
||||
// for CLI mode only, should be handled externally
|
||||
Ok(())
|
||||
}
|
||||
_ => {
|
||||
let msg = format!("Unknown wallet command, use 'grin-wallet help' for details");
|
||||
return Err(ErrorKind::ArgumentError(msg).into());
|
||||
}
|
||||
};
|
||||
if let Err(e) = res {
|
||||
Err(e)
|
||||
} else {
|
||||
Ok(wallet_args.subcommand().0.to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,14 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
#[macro_use]
|
||||
extern crate clap;
|
||||
|
||||
use grin_wallet_config as config;
|
||||
use grin_wallet_util::grin_api as api;
|
||||
use grin_wallet_util::grin_util as util;
|
||||
|
||||
mod cli;
|
||||
pub mod cmd;
|
||||
|
||||
+73
-43
@@ -151,10 +151,15 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
|
||||
let (wallet1, mask1_i) =
|
||||
instantiate_wallet(wallet_config1, client1.clone(), "password", "default")?;
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
grin_wallet_controller::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
api.set_active_account(m, "mining")?;
|
||||
Ok(())
|
||||
})?;
|
||||
grin_wallet_controller::controller::owner_single_use(
|
||||
Some(wallet1.clone()),
|
||||
mask1,
|
||||
None,
|
||||
|api, m| {
|
||||
api.set_active_account(m, "mining")?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
let mut bh = 10u64;
|
||||
let _ =
|
||||
@@ -234,16 +239,21 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
|
||||
// Check our transaction log, should have 10 entries
|
||||
grin_wallet_controller::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
api.set_active_account(m, "mining")?;
|
||||
let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert!(refreshed);
|
||||
assert_eq!(txs.len(), bh as usize);
|
||||
for t in txs {
|
||||
assert!(t.kernel_excess.is_some());
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
grin_wallet_controller::controller::owner_single_use(
|
||||
Some(wallet1.clone()),
|
||||
mask1,
|
||||
None,
|
||||
|api, m| {
|
||||
api.set_active_account(m, "mining")?;
|
||||
let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert!(refreshed);
|
||||
assert_eq!(txs.len(), bh as usize);
|
||||
for t in txs {
|
||||
assert!(t.kernel_excess.is_some());
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
let _ = test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, 10, false);
|
||||
bh += 10;
|
||||
@@ -265,13 +275,18 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
|
||||
)?;
|
||||
let mask2 = (&mask2_i).as_ref();
|
||||
|
||||
grin_wallet_controller::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
api.set_active_account(m, "account_1")?;
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
assert_eq!(wallet1_info.amount_currently_spendable, 10_000_000_000);
|
||||
Ok(())
|
||||
})?;
|
||||
grin_wallet_controller::controller::owner_single_use(
|
||||
Some(wallet2.clone()),
|
||||
mask2,
|
||||
None,
|
||||
|api, m| {
|
||||
api.set_active_account(m, "account_1")?;
|
||||
let (_, wallet1_info) = api.retrieve_summary_info(m, true, 1)?;
|
||||
assert_eq!(wallet1_info.last_confirmed_height, bh);
|
||||
assert_eq!(wallet1_info.amount_currently_spendable, 10_000_000_000);
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
// Self-send to same account, using smallest strategy
|
||||
let arg_vec = vec![
|
||||
@@ -330,13 +345,18 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
|
||||
)?;
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
|
||||
grin_wallet_controller::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
api.set_active_account(m, "mining")?;
|
||||
let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert!(refreshed);
|
||||
assert_eq!(txs.len(), bh as usize + 1);
|
||||
Ok(())
|
||||
})?;
|
||||
grin_wallet_controller::controller::owner_single_use(
|
||||
Some(wallet1.clone()),
|
||||
mask1,
|
||||
None,
|
||||
|api, m| {
|
||||
api.set_active_account(m, "mining")?;
|
||||
let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert!(refreshed);
|
||||
assert_eq!(txs.len(), bh as usize + 1);
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
// Try using the self-send method, splitting up outputs for the fun of it
|
||||
let arg_vec = vec![
|
||||
@@ -371,13 +391,18 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
|
||||
)?;
|
||||
let mask1 = (&mask1_i).as_ref();
|
||||
|
||||
grin_wallet_controller::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
|
||||
api.set_active_account(m, "mining")?;
|
||||
let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert!(refreshed);
|
||||
assert_eq!(txs.len(), bh as usize + 2);
|
||||
Ok(())
|
||||
})?;
|
||||
grin_wallet_controller::controller::owner_single_use(
|
||||
Some(wallet1.clone()),
|
||||
mask1,
|
||||
None,
|
||||
|api, m| {
|
||||
api.set_active_account(m, "mining")?;
|
||||
let (refreshed, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
assert!(refreshed);
|
||||
assert_eq!(txs.len(), bh as usize + 2);
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
// Another file exchange, don't send, but unlock with repair command
|
||||
let arg_vec = vec![
|
||||
@@ -507,14 +532,19 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
|
||||
|
||||
// get tx output via -tx parameter
|
||||
let mut tx_id = "".to_string();
|
||||
grin_wallet_controller::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
api.set_active_account(m, "default")?;
|
||||
let (_, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
let some_tx_id = txs[0].tx_slate_id.clone();
|
||||
assert!(some_tx_id.is_some());
|
||||
tx_id = some_tx_id.unwrap().to_hyphenated().to_string().clone();
|
||||
Ok(())
|
||||
})?;
|
||||
grin_wallet_controller::controller::owner_single_use(
|
||||
Some(wallet2.clone()),
|
||||
mask2,
|
||||
None,
|
||||
|api, m| {
|
||||
api.set_active_account(m, "default")?;
|
||||
let (_, txs) = api.retrieve_txs(m, true, None, None)?;
|
||||
let some_tx_id = txs[0].tx_slate_id.clone();
|
||||
assert!(some_tx_id.is_some());
|
||||
tx_id = some_tx_id.unwrap().to_hyphenated().to_string().clone();
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
let arg_vec = vec!["grin-wallet", "-p", "password", "txs", "-t", &tx_id[..]];
|
||||
execute_command(&app, test_dir, "wallet2", &client2, arg_vec)?;
|
||||
|
||||
|
||||
+21
-16
@@ -339,23 +339,28 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> {
|
||||
let mut slate: Slate = res.unwrap().into();
|
||||
|
||||
// give this slate over to wallet 2 manually
|
||||
grin_wallet_controller::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount: slate.amount,
|
||||
minimum_confirmations: 1,
|
||||
max_outputs: 500,
|
||||
num_change_outputs: 1,
|
||||
selection_strategy_is_use_all: false,
|
||||
..Default::default()
|
||||
};
|
||||
let res = api.process_invoice_tx(m, &slate, args);
|
||||
assert!(res.is_ok());
|
||||
slate = res.unwrap();
|
||||
api.tx_lock_outputs(m, &slate, 0)?;
|
||||
grin_wallet_controller::controller::owner_single_use(
|
||||
Some(wallet2.clone()),
|
||||
mask2,
|
||||
None,
|
||||
|api, m| {
|
||||
let args = InitTxArgs {
|
||||
src_acct_name: None,
|
||||
amount: slate.amount,
|
||||
minimum_confirmations: 1,
|
||||
max_outputs: 500,
|
||||
num_change_outputs: 1,
|
||||
selection_strategy_is_use_all: false,
|
||||
..Default::default()
|
||||
};
|
||||
let res = api.process_invoice_tx(m, &slate, args);
|
||||
assert!(res.is_ok());
|
||||
slate = res.unwrap();
|
||||
api.tx_lock_outputs(m, &slate, 0)?;
|
||||
|
||||
Ok(())
|
||||
})?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
//16) Finalize the invoice tx (to foreign api)
|
||||
// (Tests that foreign API on same port also has its stored mask updated)
|
||||
|
||||
Reference in New Issue
Block a user