Feature/slate serialization (#2534)
* - Add backwards compatability - Add hex serialization * rustfmt * rustfmt * Windows Compatibility Fixes #1 (#2535) * initial changes for windows build and unit/integration tests * rustfmt * wallet+store tests * rustfmt * fix linux daemonize * better encapsulate file rename * rustfmt * remove daemonize commands * rustfmt * remove server start/stop commands * add ability to drop pmmr backend files explicitly for txhashset unzip * rustfmt * fix pmmr tests * rustfmt * Windows TUI Fix (#2555) * switch pancurses backend to win32 * revert changes to restore test * compatibility fix + debug messages * rustfmt * Add content disposition for OK responses (#2545) * Testing http send and fixing accordingly * add repost method into wallet owner api (#2553) * add repost method into wallet owner api * rustfmt * Add ability to compare selection strategies (#2516) Before tx creation user can estimate fee and locked amount with different selection strategies by providing `-e` flag for `wallet send` command.
This commit is contained in:
committed by
Yeastplume
parent
0d36acf01b
commit
ee4eed71ea
+108
-9
@@ -15,13 +15,14 @@
|
||||
//! Controller for wallet.. instantiates and handles listeners (or single-run
|
||||
//! invocations) as needed.
|
||||
//! Still experimental
|
||||
use crate::adapters::util::get_versioned_slate;
|
||||
use crate::adapters::{FileWalletCommAdapter, HTTPWalletCommAdapter, KeybaseWalletCommAdapter};
|
||||
use crate::api::{ApiServer, BasicAuthMiddleware, Handler, ResponseFuture, Router, TLSConfig};
|
||||
use crate::core::core;
|
||||
use crate::core::core::Transaction;
|
||||
use crate::keychain::Keychain;
|
||||
use crate::libwallet::api::{APIForeign, APIOwner};
|
||||
use crate::libwallet::slate::Slate;
|
||||
use crate::libwallet::slate::{Slate, VersionedSlate};
|
||||
use crate::libwallet::types::{
|
||||
CbData, NodeClient, OutputData, SendTXArgs, TxLogEntry, WalletBackend, WalletInfo,
|
||||
};
|
||||
@@ -40,6 +41,7 @@ use std::marker::PhantomData;
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
use url::form_urlencoded;
|
||||
use uuid::Uuid;
|
||||
|
||||
/// Instantiate wallet Owner API for a single-use (command line) call
|
||||
/// Return a function containing a loaded API context to call
|
||||
@@ -467,6 +469,87 @@ where
|
||||
))
|
||||
}
|
||||
|
||||
pub fn repost(
|
||||
&self,
|
||||
req: Request<Body>,
|
||||
api: APIOwner<T, C, K>,
|
||||
) -> Box<dyn Future<Item = (), Error = Error> + Send> {
|
||||
let params = parse_params(&req);
|
||||
let mut id_int: Option<u32> = None;
|
||||
let mut tx_uuid: Option<Uuid> = None;
|
||||
|
||||
if let Some(id_string) = params.get("id") {
|
||||
match id_string[0].parse() {
|
||||
Ok(id) => id_int = Some(id),
|
||||
Err(e) => {
|
||||
error!("repost: could not parse id: {}", e);
|
||||
return Box::new(err(ErrorKind::GenericError(
|
||||
"repost: cannot repost transaction. Could not parse id in request."
|
||||
.to_owned(),
|
||||
)
|
||||
.into()));
|
||||
}
|
||||
}
|
||||
} else if let Some(tx_id_string) = params.get("tx_id") {
|
||||
match tx_id_string[0].parse() {
|
||||
Ok(tx_id) => tx_uuid = Some(tx_id),
|
||||
Err(e) => {
|
||||
error!("repost: could not parse tx_id: {}", e);
|
||||
return Box::new(err(ErrorKind::GenericError(
|
||||
"repost: cannot repost transaction. Could not parse tx_id in request."
|
||||
.to_owned(),
|
||||
)
|
||||
.into()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Box::new(err(ErrorKind::GenericError(
|
||||
"repost: Cannot repost transaction. Missing id or tx_id param in request."
|
||||
.to_owned(),
|
||||
)
|
||||
.into()));
|
||||
}
|
||||
|
||||
let res = api.retrieve_txs(true, id_int, tx_uuid);
|
||||
if let Err(e) = res {
|
||||
return Box::new(err(ErrorKind::GenericError(format!(
|
||||
"repost: cannot repost transaction. retrieve_txs failed, err: {:?}",
|
||||
e
|
||||
))
|
||||
.into()));
|
||||
}
|
||||
let (_, txs) = res.unwrap();
|
||||
let res = api.get_stored_tx(&txs[0]);
|
||||
if let Err(e) = res {
|
||||
return Box::new(err(ErrorKind::GenericError(format!(
|
||||
"repost: cannot repost transaction. get_stored_tx failed, err: {:?}",
|
||||
e
|
||||
))
|
||||
.into()));
|
||||
}
|
||||
let stored_tx = res.unwrap();
|
||||
if stored_tx.is_none() {
|
||||
error!(
|
||||
"Transaction with id {:?}/{:?} does not have transaction data. Not reposting.",
|
||||
id_int, tx_uuid,
|
||||
);
|
||||
return Box::new(err(ErrorKind::GenericError(
|
||||
"repost: Cannot repost transaction. Missing id or tx_id param in request."
|
||||
.to_owned(),
|
||||
)
|
||||
.into()));
|
||||
}
|
||||
|
||||
let fluff = params.get("fluff").is_some();
|
||||
Box::new(match api.post_tx(&stored_tx.unwrap(), fluff) {
|
||||
Ok(_) => ok(()),
|
||||
Err(e) => {
|
||||
error!("repost: failed with error: {}", e);
|
||||
err(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn handle_post_request(&self, req: Request<Body>) -> WalletResponseFuture {
|
||||
let api = APIOwner::new(self.wallet.clone());
|
||||
match req
|
||||
@@ -487,10 +570,14 @@ where
|
||||
),
|
||||
"cancel_tx" => Box::new(
|
||||
self.cancel_tx(req, api)
|
||||
.and_then(|_| ok(response(StatusCode::OK, ""))),
|
||||
.and_then(|_| ok(response(StatusCode::OK, "{}"))),
|
||||
),
|
||||
"post_tx" => Box::new(
|
||||
self.post_tx(req, api)
|
||||
.and_then(|_| ok(response(StatusCode::OK, "{}"))),
|
||||
),
|
||||
"repost" => Box::new(
|
||||
self.repost(req, api)
|
||||
.and_then(|_| ok(response(StatusCode::OK, ""))),
|
||||
),
|
||||
_ => Box::new(err(ErrorKind::GenericError(
|
||||
@@ -574,16 +661,17 @@ where
|
||||
&self,
|
||||
req: Request<Body>,
|
||||
mut api: APIForeign<T, C, K>,
|
||||
) -> Box<dyn Future<Item = Slate, Error = Error> + Send> {
|
||||
) -> Box<dyn Future<Item = VersionedSlate, Error = Error> + Send> {
|
||||
Box::new(parse_body(req).and_then(
|
||||
//TODO: No way to insert a message from the params
|
||||
move |mut slate| {
|
||||
move |slate: VersionedSlate| {
|
||||
let mut slate: Slate = slate.into();
|
||||
if let Err(e) = api.verify_slate_messages(&slate) {
|
||||
error!("Error validating participant messages: {}", e);
|
||||
err(e)
|
||||
} else {
|
||||
match api.receive_tx(&mut slate, None, None) {
|
||||
Ok(_) => ok(slate.clone()),
|
||||
Ok(_) => ok(get_versioned_slate(&slate.clone())),
|
||||
Err(e) => {
|
||||
error!("receive_tx: failed with error: {}", e);
|
||||
err(e)
|
||||
@@ -677,20 +765,31 @@ fn create_ok_response(json: &str) -> Response<Body> {
|
||||
"access-control-allow-headers",
|
||||
"Content-Type, Authorization",
|
||||
)
|
||||
.header(hyper::header::CONTENT_TYPE, "application/json")
|
||||
.body(json.to_string().into())
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Build a new hyper Response with the status code and body provided.
|
||||
///
|
||||
/// Whenever the status code is `StatusCode::OK` the text parameter should be
|
||||
/// valid JSON as the content type header will be set to `application/json'
|
||||
fn response<T: Into<Body>>(status: StatusCode, text: T) -> Response<Body> {
|
||||
Response::builder()
|
||||
let mut builder = &mut Response::builder();
|
||||
|
||||
builder = builder
|
||||
.status(status)
|
||||
.header("access-control-allow-origin", "*")
|
||||
.header(
|
||||
"access-control-allow-headers",
|
||||
"Content-Type, Authorization",
|
||||
)
|
||||
.body(text.into())
|
||||
.unwrap()
|
||||
);
|
||||
|
||||
if status == StatusCode::OK {
|
||||
builder = builder.header(hyper::header::CONTENT_TYPE, "application/json");
|
||||
}
|
||||
|
||||
builder.body(text.into()).unwrap()
|
||||
}
|
||||
|
||||
fn parse_params(req: &Request<Body>) -> HashMap<String, Vec<String>> {
|
||||
|
||||
Reference in New Issue
Block a user