mirror of
https://github.com/mimblewimble/grin.git
synced 2025-02-01 17:01:09 +03:00
[WIP] Updates to support web-wallet (#1160)
* updates to support web wallet workflow * rustfmt * functions to support wallet, error handling * rustfmt * rebase rustfmt * test fix
This commit is contained in:
parent
922b04608f
commit
88616fd341
22 changed files with 260 additions and 89 deletions
|
@ -201,7 +201,7 @@ impl OutputHandler {
|
|||
);
|
||||
|
||||
let mut return_vec = vec![];
|
||||
for i in start_height..end_height + 1 {
|
||||
for i in (start_height..=end_height).rev() {
|
||||
let res = self.outputs_at_height(i, commitments.clone(), include_rp);
|
||||
if res.outputs.len() > 0 {
|
||||
return_vec.push(res);
|
||||
|
|
|
@ -20,10 +20,10 @@ use std::fs::File;
|
|||
use std::sync::{Arc, Mutex, RwLock};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use core::core::Committed;
|
||||
use core::core::hash::{Hash, Hashed};
|
||||
use core::core::pmmr::MerkleProof;
|
||||
use core::core::target::Difficulty;
|
||||
use core::core::Committed;
|
||||
use core::core::{Block, BlockHeader, Output, OutputIdentifier, Transaction, TxKernel};
|
||||
use core::global;
|
||||
use grin_store::Error::NotFoundErr;
|
||||
|
@ -31,8 +31,8 @@ use pipe;
|
|||
use store;
|
||||
use txhashset;
|
||||
use types::*;
|
||||
use util::secp::pedersen::{Commitment, RangeProof};
|
||||
use util::LOGGER;
|
||||
use util::secp::pedersen::{Commitment, RangeProof};
|
||||
|
||||
/// Orphan pool size is limited by MAX_ORPHAN_SIZE
|
||||
pub const MAX_ORPHAN_SIZE: usize = 200;
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
|
||||
//! Transactions
|
||||
|
||||
use std::cmp::max;
|
||||
use std::cmp::Ordering;
|
||||
use std::cmp::max;
|
||||
use std::collections::HashSet;
|
||||
use std::io::Cursor;
|
||||
use std::{error, fmt};
|
||||
|
@ -26,12 +26,12 @@ use util::{kernel_sig_msg, static_secp_instance};
|
|||
|
||||
use consensus;
|
||||
use consensus::VerifySortOrder;
|
||||
use core::BlockHeader;
|
||||
use core::Committed;
|
||||
use core::committed;
|
||||
use core::global;
|
||||
use core::hash::{Hash, Hashed, ZERO_HASH};
|
||||
use core::pmmr::MerkleProof;
|
||||
use core::BlockHeader;
|
||||
use core::Committed;
|
||||
use keychain;
|
||||
use keychain::BlindingFactor;
|
||||
use ser::{self, read_and_verify_sorted, ser_vec, PMMRable, Readable, Reader, Writeable,
|
||||
|
|
|
@ -675,7 +675,7 @@ impl NetAdapter for Peers {
|
|||
|
||||
fn peer_difficulty(&self, addr: SocketAddr, diff: Difficulty, height: u64) {
|
||||
if diff != self.total_difficulty() || height != self.total_height() {
|
||||
debug!(
|
||||
trace!(
|
||||
LOGGER,
|
||||
"ping/pong: {}: {} @ {} vs us: {} @ {}",
|
||||
addr,
|
||||
|
|
|
@ -29,9 +29,9 @@ use std::sync::{Arc, RwLock};
|
|||
|
||||
use core::core::{Block, BlockHeader};
|
||||
|
||||
use chain::ChainStore;
|
||||
use chain::txhashset;
|
||||
use chain::types::Tip;
|
||||
use chain::ChainStore;
|
||||
use core::core::target::Difficulty;
|
||||
|
||||
use keychain::{ExtKeychain, Keychain};
|
||||
|
|
|
@ -35,8 +35,8 @@ use core::core::transaction::Transaction;
|
|||
use p2p;
|
||||
use pool;
|
||||
use store;
|
||||
use util::OneTime;
|
||||
use util::LOGGER;
|
||||
use util::OneTime;
|
||||
|
||||
// All adapters use `Weak` references instead of `Arc` to avoid cycles that
|
||||
// can never be destroyed. These 2 functions are simple helpers to reduce the
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::time::Duration;
|
||||
use std::{cmp, thread};
|
||||
use time;
|
||||
|
@ -457,7 +457,7 @@ mod test {
|
|||
assert_eq!(
|
||||
get_locator_heights(10000),
|
||||
vec![
|
||||
10000, 9998, 9994, 9986, 9970, 9938, 9874, 9746, 9490, 8978, 7954, 5906, 1810, 0,
|
||||
10000, 9998, 9994, 9986, 9970, 9938, 9874, 9746, 9490, 8978, 7954, 5906, 1810, 0
|
||||
]
|
||||
);
|
||||
}
|
||||
|
|
|
@ -305,7 +305,7 @@ impl LocalServerContainer {
|
|||
let mut wallet = FileWallet::new(config.clone(), "")
|
||||
.unwrap_or_else(|e| panic!("Error creating wallet: {:?} Config: {:?}", e, config));
|
||||
wallet.keychain = Some(keychain);
|
||||
wallet::libwallet::internal::updater::retrieve_info(&mut wallet).unwrap()
|
||||
wallet::libwallet::internal::updater::retrieve_info(&mut wallet, true).unwrap()
|
||||
}
|
||||
|
||||
pub fn send_amount_to(
|
||||
|
|
|
@ -681,7 +681,7 @@ fn wallet_command(wallet_args: &ArgMatches, global_config: GlobalConfig) {
|
|||
Ok(())
|
||||
}
|
||||
("info", Some(_)) => {
|
||||
let _res = wallet::display::info(&api.retrieve_summary_info()?.1)
|
||||
let _res = wallet::display::info(&api.retrieve_summary_info(true)?)
|
||||
.unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"Error getting wallet info: {:?} Config: {:?}",
|
||||
|
@ -692,7 +692,7 @@ fn wallet_command(wallet_args: &ArgMatches, global_config: GlobalConfig) {
|
|||
}
|
||||
("outputs", Some(_)) => {
|
||||
let (height, validated) = api.node_height()?;
|
||||
let (_, outputs) = api.retrieve_outputs(show_spent)?;
|
||||
let (_, outputs) = api.retrieve_outputs(show_spent, true)?;
|
||||
let _res =
|
||||
wallet::display::outputs(height, validated, outputs).unwrap_or_else(|e| {
|
||||
panic!(
|
||||
|
|
|
@ -41,10 +41,8 @@
|
|||
//! Adapted from https://github.com/behnam/rust-cursive-table-view
|
||||
//! A basic table view implementation for [cursive](https://crates.io/crates/cursive).
|
||||
|
||||
#![deny(
|
||||
missing_docs, missing_copy_implementations, trivial_casts, trivial_numeric_casts, unsafe_code,
|
||||
unused_import_braces, unused_qualifications
|
||||
)]
|
||||
#![deny(missing_docs, missing_copy_implementations, trivial_casts, trivial_numeric_casts,
|
||||
unsafe_code, unused_import_braces, unused_qualifications)]
|
||||
|
||||
// Crate Dependencies ---------------------------------------------------------
|
||||
extern crate cursive;
|
||||
|
@ -56,6 +54,7 @@ use std::hash::Hash;
|
|||
use std::rc::Rc;
|
||||
|
||||
// External Dependencies ------------------------------------------------------
|
||||
use cursive::With;
|
||||
use cursive::align::HAlign;
|
||||
use cursive::direction::Direction;
|
||||
use cursive::event::{Callback, Event, EventResult, Key};
|
||||
|
@ -63,7 +62,6 @@ use cursive::theme::ColorStyle;
|
|||
use cursive::theme::PaletteColor::*;
|
||||
use cursive::vec::Vec2;
|
||||
use cursive::view::{ScrollBase, View};
|
||||
use cursive::With;
|
||||
use cursive::{Cursive, Printer};
|
||||
|
||||
/// A trait for displaying and sorting items inside a
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
|
||||
//! Types specific to the UI module
|
||||
|
||||
use cursive::view::View;
|
||||
use cursive::Cursive;
|
||||
use cursive::view::View;
|
||||
use servers::ServerStats;
|
||||
|
||||
/// Main message struct to communicate between the UI and
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
|
||||
use core::core;
|
||||
use core::core::amount_to_hr_string;
|
||||
use libwallet::types::{OutputData, WalletInfo};
|
||||
use libwallet::Error;
|
||||
use libwallet::types::{OutputData, WalletInfo};
|
||||
use prettytable;
|
||||
use std::io::prelude::*;
|
||||
use term;
|
||||
|
|
|
@ -414,15 +414,26 @@ impl<K> WalletClient for FileWallet<K> {
|
|||
dest: &str,
|
||||
block_fees: &BlockFees,
|
||||
) -> Result<CbData, libwallet::Error> {
|
||||
let res =
|
||||
client::create_coinbase(dest, block_fees).context(libwallet::ErrorKind::WalletComms)?;
|
||||
Ok(res)
|
||||
let res = client::create_coinbase(dest, block_fees);
|
||||
match res {
|
||||
Ok(r) => Ok(r),
|
||||
Err(e) => {
|
||||
let message = format!("{}", e.cause().unwrap());
|
||||
Err(libwallet::ErrorKind::WalletComms(message))?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Send a transaction slate to another listening wallet and return result
|
||||
fn send_tx_slate(&self, dest: &str, slate: &Slate) -> Result<Slate, libwallet::Error> {
|
||||
let res = client::send_tx_slate(dest, slate).context(libwallet::ErrorKind::WalletComms)?;
|
||||
Ok(res)
|
||||
let res = client::send_tx_slate(dest, slate);
|
||||
match res {
|
||||
Ok(r) => Ok(r),
|
||||
Err(e) => {
|
||||
let message = format!("{}", e.cause().unwrap());
|
||||
Err(libwallet::ErrorKind::WalletComms(message))?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Posts a tranaction to a grin node
|
||||
|
|
|
@ -23,8 +23,8 @@ use keychain::{BlindSum, BlindingFactor, Keychain};
|
|||
use libtx::error::{Error, ErrorKind};
|
||||
use libtx::{aggsig, build, tx_fee};
|
||||
|
||||
use util::secp::key::{PublicKey, SecretKey};
|
||||
use util::secp::Signature;
|
||||
use util::secp::key::{PublicKey, SecretKey};
|
||||
use util::{secp, LOGGER};
|
||||
|
||||
/// Public data for each participant in the slate
|
||||
|
|
|
@ -60,8 +60,12 @@ where
|
|||
pub fn retrieve_outputs(
|
||||
&mut self,
|
||||
include_spent: bool,
|
||||
refresh_from_node: bool,
|
||||
) -> Result<(bool, Vec<OutputData>), Error> {
|
||||
let validated = self.update_outputs();
|
||||
let mut validated = false;
|
||||
if refresh_from_node {
|
||||
validated = self.update_outputs();
|
||||
}
|
||||
Ok((
|
||||
validated,
|
||||
updater::retrieve_outputs(self.wallet, include_spent)?,
|
||||
|
@ -69,9 +73,12 @@ where
|
|||
}
|
||||
|
||||
/// Retrieve summary info for wallet
|
||||
pub fn retrieve_summary_info(&mut self) -> Result<(bool, WalletInfo), Error> {
|
||||
let validated = self.update_outputs();
|
||||
Ok((validated, updater::retrieve_info(self.wallet)?))
|
||||
pub fn retrieve_summary_info(&mut self, refresh_from_node: bool) -> Result<WalletInfo, Error> {
|
||||
let mut validated = false;
|
||||
if refresh_from_node {
|
||||
validated = self.update_outputs();
|
||||
}
|
||||
updater::retrieve_info(self.wallet, validated)
|
||||
}
|
||||
|
||||
/// Issues a send transaction and sends to recipient
|
||||
|
@ -139,7 +146,7 @@ where
|
|||
match self.wallet.get_chain_height(self.wallet.node_url()) {
|
||||
Ok(height) => Ok((height, true)),
|
||||
Err(_) => {
|
||||
let outputs = self.retrieve_outputs(true)?;
|
||||
let outputs = self.retrieve_outputs(true, false)?;
|
||||
let height = match outputs.1.iter().map(|out| out.height).max() {
|
||||
Some(height) => height,
|
||||
None => 0,
|
||||
|
|
|
@ -21,17 +21,20 @@ use std::sync::{Arc, Mutex};
|
|||
|
||||
use bodyparser;
|
||||
use iron::Handler;
|
||||
use iron::Headers;
|
||||
use iron::prelude::*;
|
||||
use iron::status;
|
||||
use serde::Serialize;
|
||||
use serde_json;
|
||||
use urlencoded::UrlEncodedQuery;
|
||||
|
||||
use failure::Fail;
|
||||
|
||||
use keychain::Keychain;
|
||||
use libtx::slate::Slate;
|
||||
use libwallet::api::{APIForeign, APIOwner};
|
||||
use libwallet::types::{BlockFees, CbData, OutputData, WalletBackend, WalletClient, WalletInfo};
|
||||
use libwallet::types::{BlockFees, CbData, OutputData, SendTXArgs, WalletBackend, WalletClient,
|
||||
WalletInfo};
|
||||
use libwallet::{Error, ErrorKind};
|
||||
|
||||
use util::LOGGER;
|
||||
|
@ -69,13 +72,19 @@ where
|
|||
pub fn owner_listener<T, K>(wallet: T, addr: &str) -> Result<(), Error>
|
||||
where
|
||||
T: WalletBackend<K> + WalletClient,
|
||||
OwnerAPIHandler<T, K>: Handler,
|
||||
OwnerAPIGetHandler<T, K>: Handler,
|
||||
OwnerAPIPostHandler<T, K>: Handler,
|
||||
K: Keychain,
|
||||
{
|
||||
let api_handler = OwnerAPIHandler::new(Arc::new(Mutex::new(wallet)));
|
||||
let wallet_arc = Arc::new(Mutex::new(wallet));
|
||||
let api_get_handler = OwnerAPIGetHandler::new(wallet_arc.clone());
|
||||
let api_post_handler = OwnerAPIPostHandler::new(wallet_arc);
|
||||
let api_options_handler = OwnerAPIOptionsHandler {};
|
||||
|
||||
let router = router!(
|
||||
receive_tx: get "/wallet/owner/*" => api_handler,
|
||||
owner_options: options "/wallet/owner/*" => api_options_handler,
|
||||
owner_get: get "/wallet/owner/*" => api_get_handler,
|
||||
owner_post: post "/wallet/owner/*" => api_post_handler,
|
||||
);
|
||||
|
||||
let mut apis = ApiServer::new("/v1".to_string());
|
||||
|
@ -117,7 +126,7 @@ where
|
|||
}
|
||||
/// API Handler/Wrapper for owner functions
|
||||
|
||||
pub struct OwnerAPIHandler<T, K>
|
||||
pub struct OwnerAPIGetHandler<T, K>
|
||||
where
|
||||
T: WalletBackend<K>,
|
||||
K: Keychain,
|
||||
|
@ -127,13 +136,13 @@ where
|
|||
phantom: PhantomData<K>,
|
||||
}
|
||||
|
||||
impl<T, K> OwnerAPIHandler<T, K>
|
||||
impl<T, K> OwnerAPIGetHandler<T, K>
|
||||
where
|
||||
T: WalletBackend<K> + WalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
pub fn new(wallet: Arc<Mutex<T>>) -> OwnerAPIHandler<T, K> {
|
||||
OwnerAPIHandler {
|
||||
pub fn new(wallet: Arc<Mutex<T>>) -> OwnerAPIGetHandler<T, K> {
|
||||
OwnerAPIGetHandler {
|
||||
wallet,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
|
@ -143,9 +152,14 @@ where
|
|||
&self,
|
||||
req: &mut Request,
|
||||
api: &mut APIOwner<T, K>,
|
||||
) -> Result<Vec<OutputData>, Error> {
|
||||
let res = api.retrieve_outputs(false)?;
|
||||
Ok(res.1)
|
||||
) -> Result<(bool, Vec<OutputData>), Error> {
|
||||
let mut update_from_node = false;
|
||||
if let Ok(params) = req.get_ref::<UrlEncodedQuery>() {
|
||||
if let Some(_) = params.get("refresh") {
|
||||
update_from_node = true;
|
||||
}
|
||||
}
|
||||
api.retrieve_outputs(false, update_from_node)
|
||||
}
|
||||
|
||||
fn retrieve_summary_info(
|
||||
|
@ -153,31 +167,32 @@ where
|
|||
req: &mut Request,
|
||||
api: &mut APIOwner<T, K>,
|
||||
) -> Result<WalletInfo, Error> {
|
||||
let res = api.retrieve_summary_info()?;
|
||||
Ok(res.1)
|
||||
let mut update_from_node = false;
|
||||
if let Ok(params) = req.get_ref::<UrlEncodedQuery>() {
|
||||
if let Some(_) = params.get("refresh") {
|
||||
update_from_node = true;
|
||||
}
|
||||
}
|
||||
api.retrieve_summary_info(update_from_node)
|
||||
}
|
||||
|
||||
fn issue_send_tx(&self, req: &mut Request, api: &mut APIOwner<T, K>) -> Result<(), Error> {
|
||||
// TODO: Args
|
||||
api.issue_send_tx(60, 10, "", 1000, true, true)
|
||||
}
|
||||
|
||||
fn issue_burn_tx(&self, req: &mut Request, api: &mut APIOwner<T, K>) -> Result<(), Error> {
|
||||
// TODO: Args
|
||||
api.issue_burn_tx(60, 10, 1000)
|
||||
fn node_height(
|
||||
&self,
|
||||
req: &mut Request,
|
||||
api: &mut APIOwner<T, K>,
|
||||
) -> Result<(u64, bool), Error> {
|
||||
api.node_height()
|
||||
}
|
||||
|
||||
fn handle_request(&self, req: &mut Request, api: &mut APIOwner<T, K>) -> IronResult<Response> {
|
||||
let url = req.url.clone();
|
||||
let path_elems = url.path();
|
||||
match *path_elems.last().unwrap() {
|
||||
"retrieve_outputs" => json_response_pretty(&self.retrieve_outputs(req, api)
|
||||
"retrieve_outputs" => json_response(&self.retrieve_outputs(req, api)
|
||||
.map_err(|e| IronError::new(Fail::compat(e), status::BadRequest))?),
|
||||
"retrieve_summary_info" => json_response_pretty(&self.retrieve_summary_info(req, api)
|
||||
"retrieve_summary_info" => json_response(&self.retrieve_summary_info(req, api)
|
||||
.map_err(|e| IronError::new(Fail::compat(e), status::BadRequest))?),
|
||||
"issue_send_tx" => json_response_pretty(&self.issue_send_tx(req, api)
|
||||
.map_err(|e| IronError::new(Fail::compat(e), status::BadRequest))?),
|
||||
"issue_burn_tx" => json_response_pretty(&self.issue_burn_tx(req, api)
|
||||
"node_height" => json_response(&self.node_height(req, api)
|
||||
.map_err(|e| IronError::new(Fail::compat(e), status::BadRequest))?),
|
||||
_ => Err(IronError::new(
|
||||
Fail::compat(ErrorKind::Hyper),
|
||||
|
@ -187,7 +202,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, K> Handler for OwnerAPIHandler<T, K>
|
||||
impl<T, K> Handler for OwnerAPIGetHandler<T, K>
|
||||
where
|
||||
T: WalletBackend<K> + WalletClient + Send + Sync + 'static,
|
||||
K: Keychain + 'static,
|
||||
|
@ -203,11 +218,13 @@ where
|
|||
})?;
|
||||
let mut api = APIOwner::new(&mut *wallet);
|
||||
let mut resp_json = self.handle_request(req, &mut api);
|
||||
resp_json
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.headers
|
||||
.set_raw("access-control-allow-origin", vec![b"*".to_vec()]);
|
||||
if !resp_json.is_err() {
|
||||
resp_json
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.headers
|
||||
.set_raw("access-control-allow-origin", vec![b"*".to_vec()]);
|
||||
}
|
||||
api.wallet
|
||||
.close()
|
||||
.map_err(|e| IronError::new(Fail::compat(e), status::BadRequest))?;
|
||||
|
@ -215,6 +232,138 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub struct OwnerAPIPostHandler<T, K>
|
||||
where
|
||||
T: WalletBackend<K>,
|
||||
K: Keychain,
|
||||
{
|
||||
/// Wallet instance
|
||||
pub wallet: Arc<Mutex<T>>,
|
||||
phantom: PhantomData<K>,
|
||||
}
|
||||
|
||||
impl<T, K> OwnerAPIPostHandler<T, K>
|
||||
where
|
||||
T: WalletBackend<K> + WalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
pub fn new(wallet: Arc<Mutex<T>>) -> OwnerAPIPostHandler<T, K> {
|
||||
OwnerAPIPostHandler {
|
||||
wallet,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
fn issue_send_tx(&self, req: &mut Request, api: &mut APIOwner<T, K>) -> Result<(), Error> {
|
||||
let struct_body = req.get::<bodyparser::Struct<SendTXArgs>>();
|
||||
match struct_body {
|
||||
Ok(Some(args)) => api.issue_send_tx(
|
||||
args.amount,
|
||||
args.minimum_confirmations,
|
||||
&args.dest,
|
||||
args.max_outputs,
|
||||
args.selection_strategy_is_use_all,
|
||||
args.fluff,
|
||||
),
|
||||
Ok(None) => {
|
||||
error!(LOGGER, "Missing request body: issue_send_tx");
|
||||
Err(ErrorKind::GenericError(
|
||||
"Invalid request body: issue_send_tx",
|
||||
))?
|
||||
}
|
||||
Err(e) => {
|
||||
error!(LOGGER, "Invalid request body: issue_send_tx {:?}", e);
|
||||
Err(ErrorKind::GenericError(
|
||||
"Invalid request body: issue_send_tx",
|
||||
))?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn issue_burn_tx(&self, req: &mut Request, api: &mut APIOwner<T, K>) -> Result<(), Error> {
|
||||
// TODO: Args
|
||||
api.issue_burn_tx(60, 10, 1000)
|
||||
}
|
||||
|
||||
fn handle_request(&self, req: &mut Request, api: &mut APIOwner<T, K>) -> Result<String, Error> {
|
||||
let url = req.url.clone();
|
||||
let path_elems = url.path();
|
||||
match *path_elems.last().unwrap() {
|
||||
"issue_send_tx" => json_response_pretty(&self.issue_send_tx(req, api)?),
|
||||
"issue_burn_tx" => json_response_pretty(&self.issue_burn_tx(req, api)?),
|
||||
_ => Err(ErrorKind::GenericError(
|
||||
"Unknown error handling post request",
|
||||
))?,
|
||||
}
|
||||
}
|
||||
|
||||
fn create_error_response(&self, e: Error) -> IronResult<Response> {
|
||||
let mut headers = Headers::new();
|
||||
headers.set_raw("access-control-allow-origin", vec![b"*".to_vec()]);
|
||||
headers.set_raw(
|
||||
"access-control-allow-headers",
|
||||
vec![b"Content-Type".to_vec()],
|
||||
);
|
||||
let message = format!("{}", e.kind());
|
||||
let mut r = Response::with((status::InternalServerError, message));
|
||||
r.headers = headers;
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
fn create_ok_response(&self, json: &str) -> IronResult<Response> {
|
||||
let mut headers = Headers::new();
|
||||
headers.set_raw("access-control-allow-origin", vec![b"*".to_vec()]);
|
||||
let mut r = Response::with((status::Ok, json));
|
||||
r.headers = headers;
|
||||
Ok(r)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, K> Handler for OwnerAPIPostHandler<T, K>
|
||||
where
|
||||
T: WalletBackend<K> + WalletClient + Send + Sync + 'static,
|
||||
K: Keychain + 'static,
|
||||
{
|
||||
fn handle(&self, req: &mut Request) -> IronResult<Response> {
|
||||
// every request should open with stored credentials,
|
||||
// do its thing and then de-init whatever secrets have been
|
||||
// stored
|
||||
let mut wallet = self.wallet.lock().unwrap();
|
||||
wallet.open_with_credentials().map_err(|e| {
|
||||
error!(LOGGER, "Error opening wallet: {:?}", e);
|
||||
IronError::new(Fail::compat(e), status::BadRequest)
|
||||
})?;
|
||||
let mut api = APIOwner::new(&mut *wallet);
|
||||
let resp = match self.handle_request(req, &mut api) {
|
||||
Ok(r) => self.create_ok_response(&r),
|
||||
Err(e) => {
|
||||
error!(LOGGER, "Request Error: {:?}", e);
|
||||
self.create_error_response(e)
|
||||
}
|
||||
};
|
||||
api.wallet
|
||||
.close()
|
||||
.map_err(|e| IronError::new(Fail::compat(e), status::BadRequest))?;
|
||||
resp
|
||||
}
|
||||
}
|
||||
|
||||
/// Options handler
|
||||
pub struct OwnerAPIOptionsHandler {}
|
||||
|
||||
impl Handler for OwnerAPIOptionsHandler where {
|
||||
fn handle(&self, _req: &mut Request) -> IronResult<Response> {
|
||||
let mut resp_json = Ok(Response::with((status::Ok, "{}")));
|
||||
let mut headers = Headers::new();
|
||||
headers.set_raw("access-control-allow-origin", vec![b"*".to_vec()]);
|
||||
headers.set_raw(
|
||||
"access-control-allow-headers",
|
||||
vec![b"Content-Type".to_vec()],
|
||||
);
|
||||
resp_json.as_mut().unwrap().headers = headers;
|
||||
resp_json
|
||||
}
|
||||
}
|
||||
/// API Handler/Wrapper for foreign functions
|
||||
|
||||
pub struct ForeignAPIHandler<T, K>
|
||||
|
@ -291,7 +440,6 @@ where
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, K> Handler for ForeignAPIHandler<T, K>
|
||||
where
|
||||
T: WalletBackend<K> + WalletClient + Send + Sync + 'static,
|
||||
|
@ -328,12 +476,12 @@ where
|
|||
}
|
||||
|
||||
// pretty-printed version of above
|
||||
fn json_response_pretty<T>(s: &T) -> IronResult<Response>
|
||||
fn json_response_pretty<T>(s: &T) -> Result<String, Error>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
match serde_json::to_string_pretty(s) {
|
||||
Ok(json) => Ok(Response::with((status::Ok, json))),
|
||||
Err(_) => Ok(Response::with((status::InternalServerError, ""))),
|
||||
Ok(json) => Ok(json),
|
||||
Err(_) => Err(ErrorKind::Format)?,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,8 +94,8 @@ pub enum ErrorKind {
|
|||
Node,
|
||||
|
||||
/// Error contacting wallet API
|
||||
#[fail(display = "Wallet communication error")]
|
||||
WalletComms,
|
||||
#[fail(display = "Wallet Communication Error: {}", _0)]
|
||||
WalletComms(String),
|
||||
|
||||
/// Error originating from hyper.
|
||||
#[fail(display = "Hyper error")]
|
||||
|
|
|
@ -24,8 +24,8 @@ use keychain::{Identifier, Keychain};
|
|||
use libtx::proof;
|
||||
use libwallet::types::*;
|
||||
use util;
|
||||
use util::secp::pedersen;
|
||||
use util::LOGGER;
|
||||
use util::secp::pedersen;
|
||||
|
||||
fn get_merkle_proof_for_commit(node_addr: &str, commit: &str) -> Result<MerkleProofWrapper, Error> {
|
||||
let url = format!("{}/v1/txhashset/merkleproof?id={}", node_addr, commit);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
//! Selection of inputs for building transactions
|
||||
|
||||
use keychain::{Identifier, Keychain};
|
||||
use libtx::{build, slate::Slate, tx_fee};
|
||||
use libtx::{build, tx_fee, slate::Slate};
|
||||
use libwallet::error::{Error, ErrorKind};
|
||||
use libwallet::internal::{keys, sigcontext};
|
||||
use libwallet::types::*;
|
||||
|
@ -93,12 +93,7 @@ where
|
|||
let coin = wallet_data.get_output(&id).unwrap().clone();
|
||||
wallet_data.lock_output(&coin);
|
||||
}
|
||||
// probably just want to leave as unconfirmed for now
|
||||
// or create a new status
|
||||
/*for id in lock_outputs {
|
||||
let coin = wallet_data.get_output(&id).unwrap().clone();
|
||||
wallet_data.lock_output(&coin);
|
||||
}*/ })
|
||||
})
|
||||
};
|
||||
|
||||
Ok((slate, context, update_sender_wallet_fn))
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
//! the wallet storage and update them.
|
||||
|
||||
use failure::ResultExt;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::hash_map::Entry;
|
||||
|
||||
use core::consensus::reward;
|
||||
use core::core::{Output, TxKernel};
|
||||
|
@ -29,8 +29,8 @@ use libwallet::error::{Error, ErrorKind};
|
|||
use libwallet::internal::keys;
|
||||
use libwallet::types::*;
|
||||
use util;
|
||||
use util::secp::pedersen;
|
||||
use util::LOGGER;
|
||||
use util::secp::pedersen;
|
||||
|
||||
/// Retrieve all of the outputs (doesn't attempt to update from node)
|
||||
pub fn retrieve_outputs<T, K>(wallet: &mut T, show_spent: bool) -> Result<Vec<OutputData>, Error>
|
||||
|
@ -241,13 +241,12 @@ where
|
|||
}
|
||||
|
||||
/// Retrieve summary info about the wallet
|
||||
pub fn retrieve_info<T, K>(wallet: &mut T) -> Result<WalletInfo, Error>
|
||||
/// caller should refresh first if desired
|
||||
pub fn retrieve_info<T, K>(wallet: &mut T, refreshed: bool) -> Result<WalletInfo, Error>
|
||||
where
|
||||
T: WalletBackend<K> + WalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let result = refresh_outputs(wallet);
|
||||
|
||||
let height_res = wallet.get_chain_height(&wallet.node_url());
|
||||
|
||||
let ret_val = wallet.read_wallet(|wallet_data| {
|
||||
|
@ -282,10 +281,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
let mut data_confirmed = true;
|
||||
if let Err(_) = result {
|
||||
data_confirmed = false;
|
||||
}
|
||||
Ok(WalletInfo {
|
||||
current_height: current_height,
|
||||
total: unspent_total + unconfirmed_total,
|
||||
|
@ -293,7 +288,7 @@ where
|
|||
amount_confirmed_but_locked: unspent_but_locked_total,
|
||||
amount_currently_spendable: unspent_total - unspent_but_locked_total,
|
||||
amount_locked: locked_total,
|
||||
data_confirmed: data_confirmed,
|
||||
data_confirmed: refreshed,
|
||||
data_confirmed_from: String::from(from),
|
||||
})
|
||||
});
|
||||
|
|
|
@ -423,3 +423,20 @@ pub struct TxWrapper {
|
|||
/// hex representation of transaction
|
||||
pub tx_hex: String,
|
||||
}
|
||||
|
||||
/// Send TX API Args
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct SendTXArgs {
|
||||
/// amount to send
|
||||
pub amount: u64,
|
||||
/// minimum confirmations
|
||||
pub minimum_confirmations: u64,
|
||||
/// destination url
|
||||
pub dest: String,
|
||||
/// Max number of outputs
|
||||
pub max_outputs: usize,
|
||||
/// whether to use all outputs (combine)
|
||||
pub selection_strategy_is_use_all: bool,
|
||||
/// dandelion control
|
||||
pub fluff: bool,
|
||||
}
|
||||
|
|
|
@ -29,8 +29,8 @@ mod common;
|
|||
use std::fs;
|
||||
use std::sync::Arc;
|
||||
|
||||
use chain::types::*;
|
||||
use chain::Chain;
|
||||
use chain::types::*;
|
||||
use core::global::ChainTypes;
|
||||
use core::{global, pow};
|
||||
use util::LOGGER;
|
||||
|
|
Loading…
Reference in a new issue