Serve up web wallet application (#1367)

* first addition of static wallet file server

* rustfmt

* add custom build functions to download and untar particular release of the web-wallet

* rustfmt

* remove comments
This commit is contained in:
Yeastplume
2018-08-17 18:51:50 +01:00
committed by GitHub
parent adeaea4622
commit 103c9cda77
9 changed files with 660 additions and 21 deletions
+29 -19
View File
@@ -13,7 +13,6 @@
// limitations under the License.
/// Wallet commands processing
use std::process::exit;
use std::sync::{Arc, Mutex};
use std::thread;
@@ -23,9 +22,10 @@ use clap::ArgMatches;
use config::GlobalConfig;
use core::core;
use grin_wallet::{self, libwallet, controller, display};
use grin_wallet::{self, controller, display, libwallet};
use grin_wallet::{HTTPWalletClient, LMDBBackend, WalletConfig, WalletInst, WalletSeed};
use keychain;
use servers::start_webwallet_server;
use util::LOGGER;
pub fn init_wallet_seed(wallet_config: WalletConfig) {
@@ -132,6 +132,16 @@ pub fn wallet_command(wallet_args: &ArgMatches, global_config: GlobalConfig) {
)
});
}
("web", Some(_api_args)) => {
// start owner listener and run static file server
start_webwallet_server();
controller::owner_listener(wallet, "127.0.0.1:13420").unwrap_or_else(|e| {
panic!(
"Error creating wallet api listener: {:?} Config: {:?}",
e, wallet_config
)
});
}
_ => {}
};
}
@@ -233,7 +243,9 @@ pub fn wallet_command(wallet_args: &ArgMatches, global_config: GlobalConfig) {
let priv_file = send_args
.value_of("private")
.expect("Private transaction file required");
let slate = api.file_finalize_tx(priv_file, tx_file).expect("Finalize failed");
let slate = api
.file_finalize_tx(priv_file, tx_file)
.expect("Finalize failed");
let result = api.post_tx(&slate, fluff);
match result {
@@ -279,13 +291,12 @@ pub fn wallet_command(wallet_args: &ArgMatches, global_config: GlobalConfig) {
("outputs", Some(_)) => {
let (height, _) = api.node_height()?;
let (validated, outputs) = api.retrieve_outputs(show_spent, true, None)?;
let _res =
display::outputs(height, validated, outputs).unwrap_or_else(|e| {
panic!(
"Error getting wallet outputs: {:?} Config: {:?}",
e, wallet_config
)
});
let _res = display::outputs(height, validated, outputs).unwrap_or_else(|e| {
panic!(
"Error getting wallet outputs: {:?} Config: {:?}",
e, wallet_config
)
});
Ok(())
}
("txs", Some(txs_args)) => {
@@ -299,8 +310,8 @@ pub fn wallet_command(wallet_args: &ArgMatches, global_config: GlobalConfig) {
let (height, _) = api.node_height()?;
let (validated, txs) = api.retrieve_txs(true, tx_id)?;
let include_status = !tx_id.is_some();
let _res = display::txs(height, validated, txs, include_status)
.unwrap_or_else(|e| {
let _res =
display::txs(height, validated, txs, include_status).unwrap_or_else(|e| {
panic!(
"Error getting wallet outputs: {} Config: {:?}",
e, wallet_config
@@ -310,13 +321,12 @@ pub fn wallet_command(wallet_args: &ArgMatches, global_config: GlobalConfig) {
// inputs/outputs
if tx_id.is_some() {
let (_, outputs) = api.retrieve_outputs(true, false, tx_id)?;
let _res =
display::outputs(height, validated, outputs).unwrap_or_else(|e| {
panic!(
"Error getting wallet outputs: {} Config: {:?}",
e, wallet_config
)
});
let _res = display::outputs(height, validated, outputs).unwrap_or_else(|e| {
panic!(
"Error getting wallet outputs: {} Config: {:?}",
e, wallet_config
)
});
};
Ok(())
}
+3 -2
View File
@@ -179,6 +179,9 @@ fn main() {
.subcommand(SubCommand::with_name("owner_api")
.about("Runs the wallet's local web API."))
.subcommand(SubCommand::with_name("web")
.about("Runs the local web wallet which can be accessed through a browser"))
.subcommand(SubCommand::with_name("send")
.about("Builds a transaction to send coins and sends it to the specified \
listener directly.")
@@ -352,5 +355,3 @@ fn main() {
}
}
}
+96
View File
@@ -15,10 +15,22 @@
//! Build hooks to spit out version+build time info
extern crate built;
extern crate flate2;
extern crate reqwest;
extern crate tar;
use flate2::read::GzDecoder;
use std::env;
use std::fs::{self, File};
use std::io::prelude::*;
use std::io::Read;
use std::path::{self, Path, PathBuf};
use tar::Archive;
const WEB_WALLET_TAG: &str = "0.3.0.1";
fn main() {
// build and versioning information
let mut opts = built::Options::default();
opts.set_dependencies(true);
built::write_built_file_with_opts(
@@ -26,4 +38,88 @@ fn main() {
env!("CARGO_MANIFEST_DIR"),
format!("{}{}", env::var("OUT_DIR").unwrap(), "/built.rs"),
).expect("Failed to acquire build-time information");
install_web_wallet();
}
fn download_and_decompress(target_file: &str) {
let req_path = format!("https://github.com/mimblewimble/grin-web-wallet/releases/download/{}/grin-web-wallet.tar.gz", WEB_WALLET_TAG);
let resp = reqwest::get(&req_path);
// don't interfere if this doesn't work
if resp.is_err() {
println!("Warning: Failed to download grin-web-wallet. Web wallet will not be available");
return;
}
let mut resp = resp.unwrap();
if resp.status().is_success() {
// read response
let mut out: Vec<u8> = vec![];
let r2 = resp.read_to_end(&mut out);
if r2.is_err() {
println!(
"Warning: Failed to download grin-web-wallet. Web wallet will not be available"
);
return;
}
// Gunzip
let mut d = GzDecoder::new(&out[..]);
let mut decomp: Vec<u8> = vec![];
d.read_to_end(&mut decomp).unwrap();
// write temp file
let mut buffer = File::create(target_file.clone()).unwrap();
buffer.write_all(&decomp).unwrap();
buffer.flush().unwrap();
}
}
/// Download and unzip tagged web-wallet build
fn install_web_wallet() {
let target_file = format!(
"{}/grin-web-wallet-{}.tar",
env::var("OUT_DIR").unwrap(),
WEB_WALLET_TAG
);
let out_dir = env::var("OUT_DIR").unwrap();
let mut out_path = PathBuf::from(&out_dir);
out_path.pop();
out_path.pop();
out_path.pop();
// only re-download if needed
if !Path::new(&target_file).is_file() {
download_and_decompress(&target_file);
}
// remove old version
let mut remove_path = out_path.clone();
remove_path.push("grin-wallet");
let _ = fs::remove_dir_all(remove_path);
// Untar
let file = File::open(target_file).unwrap();
let mut a = Archive::new(file);
for file in a.entries().unwrap() {
let mut file = file.unwrap();
let h = file.header().clone();
let path = h.path().unwrap().clone().into_owned();
let is_dir = path.to_str().unwrap().ends_with(path::MAIN_SEPARATOR);
let path = path.strip_prefix("dist").unwrap();
let mut final_path = out_path.clone();
final_path.push(path);
let mut tmp: Vec<u8> = vec![];
file.read_to_end(&mut tmp).unwrap();
if is_dir {
fs::create_dir_all(final_path).unwrap();
} else {
let mut buffer = File::create(final_path).unwrap();
buffer.write_all(&tmp).unwrap();
buffer.flush().unwrap();
}
}
}