Add cancel_tx and retrieve by tx_slate_id in owner_api (#1963)
* Add retrieve by tx_id in owner_api * Add cancel tx by tx_slate_id * Add doc
This commit is contained in:
@@ -22,6 +22,7 @@ use std::io::{Read, Write};
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
use util::Mutex;
|
||||
use uuid::Uuid;
|
||||
|
||||
use serde_json as json;
|
||||
|
||||
@@ -106,6 +107,7 @@ where
|
||||
&self,
|
||||
refresh_from_node: bool,
|
||||
tx_id: Option<u32>,
|
||||
tx_slate_id: Option<Uuid>,
|
||||
) -> Result<(bool, Vec<TxLogEntry>), Error> {
|
||||
let mut w = self.wallet.lock();
|
||||
w.open_with_credentials()?;
|
||||
@@ -118,7 +120,7 @@ where
|
||||
|
||||
let res = Ok((
|
||||
validated,
|
||||
updater::retrieve_txs(&mut *w, tx_id, &parent_key_id)?,
|
||||
updater::retrieve_txs(&mut *w, tx_id, tx_slate_id, &parent_key_id)?,
|
||||
));
|
||||
|
||||
w.close()?;
|
||||
@@ -324,7 +326,11 @@ where
|
||||
/// output if you're recipient), and unlock all locked outputs associated
|
||||
/// with the transaction used when a transaction is created but never
|
||||
/// posted
|
||||
pub fn cancel_tx(&mut self, tx_id: u32) -> Result<(), Error> {
|
||||
pub fn cancel_tx(
|
||||
&mut self,
|
||||
tx_id: Option<u32>,
|
||||
tx_slate_id: Option<Uuid>,
|
||||
) -> Result<(), Error> {
|
||||
let mut w = self.wallet.lock();
|
||||
w.open_with_credentials()?;
|
||||
let parent_key_id = w.parent_key_id();
|
||||
@@ -333,7 +339,7 @@ where
|
||||
"Can't contact running Grin node. Not Cancelling.",
|
||||
))?;
|
||||
}
|
||||
tx::cancel_tx(&mut *w, &parent_key_id, tx_id)?;
|
||||
tx::cancel_tx(&mut *w, &parent_key_id, tx_id, tx_slate_id)?;
|
||||
w.close()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -207,7 +207,8 @@ where
|
||||
req: &Request<Body>,
|
||||
api: APIOwner<T, C, L, K>,
|
||||
) -> Result<(bool, Vec<TxLogEntry>), Error> {
|
||||
let mut id = None;
|
||||
let mut tx_id = None;
|
||||
let mut tx_slate_id = None;
|
||||
let mut update_from_node = false;
|
||||
|
||||
let params = parse_params(req);
|
||||
@@ -217,10 +218,15 @@ where
|
||||
}
|
||||
if let Some(ids) = params.get("id") {
|
||||
for i in ids {
|
||||
id = Some(i.parse().unwrap());
|
||||
tx_id = Some(i.parse().unwrap());
|
||||
}
|
||||
}
|
||||
api.retrieve_txs(update_from_node, id)
|
||||
if let Some(tx_slate_ids) = params.get("tx_id") {
|
||||
for i in tx_slate_ids {
|
||||
tx_slate_id = Some(i.parse().unwrap());
|
||||
}
|
||||
}
|
||||
api.retrieve_txs(update_from_node, tx_id, tx_slate_id)
|
||||
}
|
||||
|
||||
fn dump_stored_tx(
|
||||
@@ -345,7 +351,7 @@ where
|
||||
let params = parse_params(&req);
|
||||
if let Some(id_string) = params.get("id") {
|
||||
Box::new(match id_string[0].parse() {
|
||||
Ok(id) => match api.cancel_tx(id) {
|
||||
Ok(id) => match api.cancel_tx(Some(id), None) {
|
||||
Ok(_) => ok(()),
|
||||
Err(e) => {
|
||||
error!("cancel_tx: failed with error: {}", e);
|
||||
@@ -359,9 +365,25 @@ where
|
||||
).into())
|
||||
}
|
||||
})
|
||||
} else if let Some(tx_id_string) = params.get("tx_id") {
|
||||
Box::new(match tx_id_string[0].parse() {
|
||||
Ok(tx_id) => match api.cancel_tx(None, Some(tx_id)) {
|
||||
Ok(_) => ok(()),
|
||||
Err(e) => {
|
||||
error!("cancel_tx: failed with error: {}", e);
|
||||
err(e)
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
error!("cancel_tx: could not parse tx_id: {}", e);
|
||||
err(ErrorKind::TransactionCancellationError(
|
||||
"cancel_tx: cannot cancel transaction. Could not parse tx_id in request.",
|
||||
).into())
|
||||
}
|
||||
})
|
||||
} else {
|
||||
Box::new(err(ErrorKind::TransactionCancellationError(
|
||||
"cancel_tx: Cannot cancel transaction. Missing id param in request.",
|
||||
"cancel_tx: Cannot cancel transaction. Missing id or tx_id param in request.",
|
||||
).into()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,11 +150,11 @@ pub enum ErrorKind {
|
||||
|
||||
/// Transaction doesn't exist
|
||||
#[fail(display = "Transaction {} doesn't exist", _0)]
|
||||
TransactionDoesntExist(u32),
|
||||
TransactionDoesntExist(String),
|
||||
|
||||
/// Transaction already rolled back
|
||||
#[fail(display = "Transaction {} cannot be cancelled", _0)]
|
||||
TransactionNotCancellable(u32),
|
||||
TransactionNotCancellable(String),
|
||||
|
||||
/// Cancellation error
|
||||
#[fail(display = "Cancellation Error: {}", _0)]
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
use util::RwLock;
|
||||
use uuid::Uuid;
|
||||
|
||||
use core::core::verifier_cache::LruVerifierCache;
|
||||
use core::core::Transaction;
|
||||
@@ -158,7 +159,8 @@ where
|
||||
pub fn cancel_tx<T: ?Sized, C, L, K>(
|
||||
wallet: &mut T,
|
||||
parent_key_id: &Identifier,
|
||||
tx_id: u32,
|
||||
tx_id: Option<u32>,
|
||||
tx_slate_id: Option<Uuid>,
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
T: WalletBackend<C, L, K>,
|
||||
@@ -166,19 +168,25 @@ where
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let tx_vec = updater::retrieve_txs(wallet, Some(tx_id), &parent_key_id)?;
|
||||
let mut tx_id_string = String::new();
|
||||
if let Some(tx_id) = tx_id {
|
||||
tx_id_string = tx_id.to_string();
|
||||
} else if let Some(tx_slate_id) = tx_slate_id {
|
||||
tx_id_string = tx_slate_id.to_string();
|
||||
}
|
||||
let tx_vec = updater::retrieve_txs(wallet, tx_id, tx_slate_id, &parent_key_id)?;
|
||||
if tx_vec.len() != 1 {
|
||||
return Err(ErrorKind::TransactionDoesntExist(tx_id))?;
|
||||
return Err(ErrorKind::TransactionDoesntExist(tx_id_string))?;
|
||||
}
|
||||
let tx = tx_vec[0].clone();
|
||||
if tx.tx_type != TxLogEntryType::TxSent && tx.tx_type != TxLogEntryType::TxReceived {
|
||||
return Err(ErrorKind::TransactionNotCancellable(tx_id))?;
|
||||
return Err(ErrorKind::TransactionNotCancellable(tx_id_string))?;
|
||||
}
|
||||
if tx.confirmed == true {
|
||||
return Err(ErrorKind::TransactionNotCancellable(tx_id))?;
|
||||
return Err(ErrorKind::TransactionNotCancellable(tx_id_string))?;
|
||||
}
|
||||
// get outputs associated with tx
|
||||
let res = updater::retrieve_outputs(wallet, false, Some(tx_id), &parent_key_id)?;
|
||||
let res = updater::retrieve_outputs(wallet, false, Some(tx.id), &parent_key_id)?;
|
||||
let outputs = res.iter().map(|(out, _)| out).cloned().collect();
|
||||
updater::cancel_tx_and_outputs(wallet, tx, outputs, parent_key_id)?;
|
||||
Ok(())
|
||||
@@ -197,9 +205,9 @@ where
|
||||
L: WalletToWalletClient,
|
||||
K: Keychain,
|
||||
{
|
||||
let tx_vec = updater::retrieve_txs(wallet, Some(tx_id), parent_key_id)?;
|
||||
let tx_vec = updater::retrieve_txs(wallet, Some(tx_id), None, parent_key_id)?;
|
||||
if tx_vec.len() != 1 {
|
||||
return Err(ErrorKind::TransactionDoesntExist(tx_id))?;
|
||||
return Err(ErrorKind::TransactionDoesntExist(tx_id.to_string()))?;
|
||||
}
|
||||
let tx = tx_vec[0].clone();
|
||||
Ok((tx.confirmed, tx.tx_hex))
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
use failure::ResultExt;
|
||||
use std::collections::HashMap;
|
||||
use uuid::Uuid;
|
||||
|
||||
use core::consensus::reward;
|
||||
use core::core::{Output, TxKernel};
|
||||
@@ -81,6 +82,7 @@ where
|
||||
pub fn retrieve_txs<T: ?Sized, C, L, K>(
|
||||
wallet: &mut T,
|
||||
tx_id: Option<u32>,
|
||||
tx_slate_id: Option<Uuid>,
|
||||
parent_key_id: &Identifier,
|
||||
) -> Result<Vec<TxLogEntry>, Error>
|
||||
where
|
||||
@@ -97,6 +99,13 @@ where
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
} else if tx_slate_id.is_some() {
|
||||
let tx = wallet.tx_log_iter().find(|t| t.tx_slate_id == tx_slate_id);
|
||||
if let Some(t) = tx {
|
||||
vec![t]
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
} else {
|
||||
wallet
|
||||
.tx_log_iter()
|
||||
|
||||
Reference in New Issue
Block a user