mirror of
https://github.com/creating2morrow/neveko.git
synced 2024-12-22 19:49:24 +00:00
add cancel order flow - untested
This commit is contained in:
parent
92ccd3836e
commit
bb492fce8c
7 changed files with 208 additions and 27 deletions
|
@ -1,3 +1,5 @@
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use rocket::{
|
use rocket::{
|
||||||
get,
|
get,
|
||||||
http::Status,
|
http::Status,
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use rocket::{
|
use rocket::{
|
||||||
get,
|
get,
|
||||||
http::Status,
|
http::Status,
|
||||||
|
|
|
@ -5,15 +5,11 @@ use crate::{
|
||||||
db,
|
db,
|
||||||
gpg,
|
gpg,
|
||||||
i2p,
|
i2p,
|
||||||
|
|
||||||
models::*,
|
models::*,
|
||||||
monero,
|
monero,
|
||||||
order,
|
order,
|
||||||
product,
|
product,
|
||||||
reqres::{
|
reqres,
|
||||||
self,
|
|
||||||
FinalizeOrderResponse,
|
|
||||||
},
|
|
||||||
utils,
|
utils,
|
||||||
};
|
};
|
||||||
use log::{
|
use log::{
|
||||||
|
@ -24,7 +20,7 @@ use log::{
|
||||||
use rocket::serde::json::Json;
|
use rocket::serde::json::Json;
|
||||||
|
|
||||||
pub enum StatusType {
|
pub enum StatusType {
|
||||||
_Cancelled,
|
Cancelled,
|
||||||
Delivered,
|
Delivered,
|
||||||
MultisigMissing,
|
MultisigMissing,
|
||||||
MulitsigComplete,
|
MulitsigComplete,
|
||||||
|
@ -34,7 +30,7 @@ pub enum StatusType {
|
||||||
impl StatusType {
|
impl StatusType {
|
||||||
pub fn value(&self) -> String {
|
pub fn value(&self) -> String {
|
||||||
match *self {
|
match *self {
|
||||||
StatusType::_Cancelled => String::from("Cancelled"),
|
StatusType::Cancelled => String::from("Cancelled"),
|
||||||
StatusType::Delivered => String::from("Delivered"),
|
StatusType::Delivered => String::from("Delivered"),
|
||||||
StatusType::MultisigMissing => String::from("MultisigMissing"),
|
StatusType::MultisigMissing => String::from("MultisigMissing"),
|
||||||
StatusType::MulitsigComplete => String::from("MulitsigComplete"),
|
StatusType::MulitsigComplete => String::from("MulitsigComplete"),
|
||||||
|
@ -163,7 +159,10 @@ pub fn find_all_backup() -> Vec<Order> {
|
||||||
let mut orders: Vec<Order> = Vec::new();
|
let mut orders: Vec<Order> = Vec::new();
|
||||||
for o in i_v {
|
for o in i_v {
|
||||||
let order: Order = find(&o);
|
let order: Order = find(&o);
|
||||||
if order.orid != utils::empty_string() {
|
let visible = order.orid != utils::empty_string()
|
||||||
|
&& order.status != order::StatusType::Delivered.value()
|
||||||
|
&& order.status != order::StatusType::Cancelled.value();
|
||||||
|
if visible {
|
||||||
orders.push(order);
|
orders.push(order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,6 +255,39 @@ pub async fn secure_retrieval(orid: &String, signature: &String) -> Order {
|
||||||
m_order
|
m_order
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// In order for the order (...ha) to only be cancelled by the customer
|
||||||
|
///
|
||||||
|
/// they must sign the order id with their NEVEKO wallet instance.
|
||||||
|
pub async fn cancel_order(orid: &String, signature: &String) -> Order {
|
||||||
|
info!("cancel order {}", orid);
|
||||||
|
// get customer address for NEVEKO NOT order wallet
|
||||||
|
let mut m_order: Order = find(&orid);
|
||||||
|
let mut xmr_address: String = String::new();
|
||||||
|
let a_customers: Vec<Contact> = contact::find_all();
|
||||||
|
for customer in a_customers {
|
||||||
|
if customer.i2p_address == m_order.cid {
|
||||||
|
xmr_address = customer.xmr_address;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// send address, orid and signature to verify()
|
||||||
|
let id: String = String::from(&m_order.orid);
|
||||||
|
let sig: String = String::from(signature);
|
||||||
|
let wallet_password =
|
||||||
|
std::env::var(crate::MONERO_WALLET_PASSWORD).unwrap_or(String::from("password"));
|
||||||
|
let wallet_name = String::from(crate::APP_NAME);
|
||||||
|
monero::open_wallet(&wallet_name, &wallet_password).await;
|
||||||
|
let is_valid_signature = monero::verify(xmr_address, id, sig).await;
|
||||||
|
monero::close_wallet(&wallet_name, &wallet_password).await;
|
||||||
|
if !is_valid_signature {
|
||||||
|
return Default::default();
|
||||||
|
}
|
||||||
|
// update the order status and send to customer
|
||||||
|
m_order.status = order::StatusType::Cancelled.value();
|
||||||
|
order::modify(Json(m_order));
|
||||||
|
order::find(&orid)
|
||||||
|
}
|
||||||
|
|
||||||
/// Check for import multisig info, validate block time and that the
|
/// Check for import multisig info, validate block time and that the
|
||||||
///
|
///
|
||||||
/// order wallet has been funded properly. Update the order to multisig complete
|
/// order wallet has been funded properly. Update the order to multisig complete
|
||||||
|
@ -375,7 +407,7 @@ pub async fn upload_delivery_info(
|
||||||
if nasr_order.is_err() {
|
if nasr_order.is_err() {
|
||||||
return Default::default();
|
return Default::default();
|
||||||
}
|
}
|
||||||
FinalizeOrderResponse {
|
reqres::FinalizeOrderResponse {
|
||||||
delivery_info: delivery_info.to_vec(),
|
delivery_info: delivery_info.to_vec(),
|
||||||
orid: String::from(orid),
|
orid: String::from(orid),
|
||||||
vendor_update_success: false,
|
vendor_update_success: false,
|
||||||
|
@ -390,7 +422,6 @@ pub async fn upload_delivery_info(
|
||||||
pub async fn finalize_order(orid: &String) -> reqres::FinalizeOrderResponse {
|
pub async fn finalize_order(orid: &String) -> reqres::FinalizeOrderResponse {
|
||||||
info!("finalizing order: {}", orid);
|
info!("finalizing order: {}", orid);
|
||||||
|
|
||||||
|
|
||||||
reqres::FinalizeOrderResponse {
|
reqres::FinalizeOrderResponse {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
|
@ -433,7 +464,7 @@ pub async fn transmit_ship_request(
|
||||||
contact: &String,
|
contact: &String,
|
||||||
jwp: &String,
|
jwp: &String,
|
||||||
orid: &String,
|
orid: &String,
|
||||||
) -> Result<FinalizeOrderResponse, Box<dyn Error>> {
|
) -> Result<reqres::FinalizeOrderResponse, Box<dyn Error>> {
|
||||||
info!("executing transmit_ship_request");
|
info!("executing transmit_ship_request");
|
||||||
let host = utils::get_i2p_http_proxy();
|
let host = utils::get_i2p_http_proxy();
|
||||||
let proxy = reqwest::Proxy::http(&host)?;
|
let proxy = reqwest::Proxy::http(&host)?;
|
||||||
|
@ -445,7 +476,7 @@ pub async fn transmit_ship_request(
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
let res = response.json::<FinalizeOrderResponse>().await;
|
let res = response.json::<reqres::FinalizeOrderResponse>().await;
|
||||||
debug!("ship request response: {:?}", res);
|
debug!("ship request response: {:?}", res);
|
||||||
match res {
|
match res {
|
||||||
Ok(r) => Ok(r),
|
Ok(r) => Ok(r),
|
||||||
|
@ -520,6 +551,28 @@ pub async fn trigger_ship_request(contact: &String, jwp: &String, orid: &String)
|
||||||
unwrap_order
|
unwrap_order
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A post-decomposition trigger for the cancel request so that the logic
|
||||||
|
///
|
||||||
|
/// can be executed from the gui.
|
||||||
|
pub async fn trigger_cancel_request(contact: &String, jwp: &String, orid: &String) -> Order {
|
||||||
|
info!("executing trigger_cancel_request");
|
||||||
|
let data = String::from(orid);
|
||||||
|
let wallet_password =
|
||||||
|
std::env::var(crate::MONERO_WALLET_PASSWORD).unwrap_or(String::from("password"));
|
||||||
|
monero::open_wallet(&String::from(crate::APP_NAME), &wallet_password).await;
|
||||||
|
let pre_sign = monero::sign(data).await;
|
||||||
|
monero::close_wallet(&String::from(crate::APP_NAME), &wallet_password).await;
|
||||||
|
let order = transmit_cancel_request(contact, jwp, orid, &pre_sign.result.signature).await;
|
||||||
|
// cache order request to db
|
||||||
|
if order.is_err() {
|
||||||
|
log::error!("failed to trigger cancel request");
|
||||||
|
return Default::default();
|
||||||
|
}
|
||||||
|
let unwrap_order: Order = order.unwrap();
|
||||||
|
backup(&unwrap_order);
|
||||||
|
unwrap_order
|
||||||
|
}
|
||||||
|
|
||||||
/// Decomposition trigger for the shipping request
|
/// Decomposition trigger for the shipping request
|
||||||
pub async fn d_trigger_ship_request(contact: &String, orid: &String) -> Order {
|
pub async fn d_trigger_ship_request(contact: &String, orid: &String) -> Order {
|
||||||
// ugh, sorry seems we need to get jwp for vendor from fts cache
|
// ugh, sorry seems we need to get jwp for vendor from fts cache
|
||||||
|
@ -544,6 +597,66 @@ pub async fn d_trigger_ship_request(contact: &String, orid: &String) -> Order {
|
||||||
trigger
|
trigger
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Executes POST /order/cancel/orid/signature
|
||||||
|
///
|
||||||
|
/// cancelling the order on the vendor side.
|
||||||
|
///
|
||||||
|
/// Customer needs to verify the response and update their lmdb.
|
||||||
|
///
|
||||||
|
/// see `cancel_order`
|
||||||
|
pub async fn transmit_cancel_request(
|
||||||
|
contact: &String,
|
||||||
|
jwp: &String,
|
||||||
|
orid: &String,
|
||||||
|
signature: &String,
|
||||||
|
) -> Result<Order, Box<dyn Error>> {
|
||||||
|
info!("executing transmit_cancel_request");
|
||||||
|
let host = utils::get_i2p_http_proxy();
|
||||||
|
let proxy = reqwest::Proxy::http(&host)?;
|
||||||
|
let client = reqwest::Client::builder().proxy(proxy).build();
|
||||||
|
match client?
|
||||||
|
.post(format!(
|
||||||
|
"http://{}/market/order/cancel/{}/{}",
|
||||||
|
contact, orid, signature
|
||||||
|
))
|
||||||
|
.header("proof", jwp)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(response) => {
|
||||||
|
let res = response.json::<Order>().await;
|
||||||
|
debug!("cancel order response: {:?}", res);
|
||||||
|
match res {
|
||||||
|
Ok(r) => Ok(r),
|
||||||
|
_ => Ok(Default::default()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("failed to cancel order due to: {:?}", e);
|
||||||
|
Ok(Default::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decomposition trigger for the shipping request
|
||||||
|
pub async fn d_trigger_cancel_request(contact: &String, orid: &String) -> Order {
|
||||||
|
// ugh, sorry seems we need to get jwp for vendor from fts cache
|
||||||
|
// get jwp from db
|
||||||
|
let s = db::Interface::async_open().await;
|
||||||
|
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &contact);
|
||||||
|
let jwp = db::Interface::async_read(&s.env, &s.handle, &k).await;
|
||||||
|
info!("executing d_trigger_cancel_request");
|
||||||
|
// request cancel if the order status is not MultisigComplete
|
||||||
|
let order: Order = order::find(&orid);
|
||||||
|
if order.status != order::StatusType::MulitsigComplete.value() {
|
||||||
|
let trigger = trigger_cancel_request(contact, &jwp, orid).await;
|
||||||
|
if trigger.status == order::StatusType::Cancelled.value() {
|
||||||
|
return trigger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn init_mediator_wallet(orid: &String) {
|
pub async fn init_mediator_wallet(orid: &String) {
|
||||||
let password = utils::empty_string();
|
let password = utils::empty_string();
|
||||||
let m_wallet = monero::create_wallet(orid, &password).await;
|
let m_wallet = monero::create_wallet(orid, &password).await;
|
||||||
|
|
|
@ -113,6 +113,8 @@ pub struct MarketApp {
|
||||||
submit_order_rx: Receiver<models::Order>,
|
submit_order_rx: Receiver<models::Order>,
|
||||||
_submit_txset_tx: Sender<bool>,
|
_submit_txset_tx: Sender<bool>,
|
||||||
_submit_txset_rx: Receiver<bool>,
|
_submit_txset_rx: Receiver<bool>,
|
||||||
|
cancel_request_tx: Sender<models::Order>,
|
||||||
|
cancel_request_rx: Receiver<models::Order>,
|
||||||
// ship_request_tx: Sender<models::Order>,
|
// ship_request_tx: Sender<models::Order>,
|
||||||
// ship_request_rx: Receiver<models::Order>,
|
// ship_request_rx: Receiver<models::Order>,
|
||||||
s_contact: models::Contact,
|
s_contact: models::Contact,
|
||||||
|
@ -137,6 +139,7 @@ impl Default for MarketApp {
|
||||||
let (get_vendor_product_tx, get_vendor_product_rx) = std::sync::mpsc::channel();
|
let (get_vendor_product_tx, get_vendor_product_rx) = std::sync::mpsc::channel();
|
||||||
let (submit_order_tx, submit_order_rx) = std::sync::mpsc::channel();
|
let (submit_order_tx, submit_order_rx) = std::sync::mpsc::channel();
|
||||||
// let (ship_request_tx, ship_request_rx) = std::sync::mpsc::channel();
|
// let (ship_request_tx, ship_request_rx) = std::sync::mpsc::channel();
|
||||||
|
let (cancel_request_tx, cancel_request_rx) = std::sync::mpsc::channel();
|
||||||
let (our_prepare_info_tx, our_prepare_info_rx) = std::sync::mpsc::channel();
|
let (our_prepare_info_tx, our_prepare_info_rx) = std::sync::mpsc::channel();
|
||||||
let (our_make_info_tx, our_make_info_rx) = std::sync::mpsc::channel();
|
let (our_make_info_tx, our_make_info_rx) = std::sync::mpsc::channel();
|
||||||
let (order_xmr_address_tx, order_xmr_address_rx) = std::sync::mpsc::channel();
|
let (order_xmr_address_tx, order_xmr_address_rx) = std::sync::mpsc::channel();
|
||||||
|
@ -208,6 +211,8 @@ impl Default for MarketApp {
|
||||||
_refresh_on_delete_product_rx,
|
_refresh_on_delete_product_rx,
|
||||||
s_contact: Default::default(),
|
s_contact: Default::default(),
|
||||||
s_order: Default::default(),
|
s_order: Default::default(),
|
||||||
|
cancel_request_rx,
|
||||||
|
cancel_request_tx,
|
||||||
// ship_request_rx,
|
// ship_request_rx,
|
||||||
// ship_request_tx,
|
// ship_request_tx,
|
||||||
submit_order_rx,
|
submit_order_rx,
|
||||||
|
@ -320,6 +325,13 @@ impl eframe::App for MarketApp {
|
||||||
// self.is_loading = false;
|
// self.is_loading = false;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
if let Ok(cancelled) = self.cancel_request_rx.try_recv() {
|
||||||
|
if cancelled.status != order::StatusType::Cancelled.value() {
|
||||||
|
log::error!("failure to cancel shipment please contact vendor")
|
||||||
|
}
|
||||||
|
self.is_loading = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Vendor status window
|
// Vendor status window
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
let mut is_showing_vendor_status = self.is_showing_vendor_status;
|
let mut is_showing_vendor_status = self.is_showing_vendor_status;
|
||||||
|
@ -693,7 +705,7 @@ impl eframe::App for MarketApp {
|
||||||
utils::empty_string(),
|
utils::empty_string(),
|
||||||
ctx.clone(),
|
ctx.clone(),
|
||||||
utils::empty_string(),
|
utils::empty_string(),
|
||||||
self._submit_txset_tx.clone()
|
self._submit_txset_tx.clone(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if ui.button("Check").clicked() {
|
if ui.button("Check").clicked() {
|
||||||
|
@ -833,11 +845,13 @@ impl eframe::App for MarketApp {
|
||||||
if ui.button("DINFO").clicked() {
|
if ui.button("DINFO").clicked() {
|
||||||
let e_info: String = utils::search_gui_db(
|
let e_info: String = utils::search_gui_db(
|
||||||
String::from(neveko_core::DELIVERY_INFO_DB_KEY),
|
String::from(neveko_core::DELIVERY_INFO_DB_KEY),
|
||||||
String::from(&o.orid)
|
String::from(&o.orid),
|
||||||
);
|
);
|
||||||
let bytes = hex::decode(e_info.into_bytes()).unwrap_or(Vec::new());
|
let bytes =
|
||||||
|
hex::decode(e_info.into_bytes()).unwrap_or(Vec::new());
|
||||||
let d_bytes = gpg::decrypt(&String::from(&o.orid), &bytes);
|
let d_bytes = gpg::decrypt(&String::from(&o.orid), &bytes);
|
||||||
let dinfo: String = String::from_utf8(d_bytes.unwrap_or(Vec::new()))
|
let dinfo: String =
|
||||||
|
String::from_utf8(d_bytes.unwrap_or(Vec::new()))
|
||||||
.unwrap_or(utils::empty_string());
|
.unwrap_or(utils::empty_string());
|
||||||
self.decrypted_delivery_info = dinfo;
|
self.decrypted_delivery_info = dinfo;
|
||||||
self.is_showing_decrypted_delivery_info = true;
|
self.is_showing_decrypted_delivery_info = true;
|
||||||
|
@ -847,7 +861,18 @@ impl eframe::App for MarketApp {
|
||||||
ui.style_mut().wrap = Some(false);
|
ui.style_mut().wrap = Some(false);
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
if ui.button("Cancel").clicked() {
|
if ui.button("Cancel").clicked() {
|
||||||
// TODO(c2m): Cancel order logic
|
let vendor_prefix = String::from(crate::GUI_OVL_DB_KEY);
|
||||||
|
let vendor = utils::search_gui_db(
|
||||||
|
vendor_prefix,
|
||||||
|
self.m_order.orid.clone(),
|
||||||
|
);
|
||||||
|
self.is_loading = true;
|
||||||
|
cancel_order_req(
|
||||||
|
self.cancel_request_tx.clone(),
|
||||||
|
ctx.clone(),
|
||||||
|
&self.m_order.orid,
|
||||||
|
&vendor,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1704,7 +1729,6 @@ fn send_prepare_info_req(
|
||||||
);
|
);
|
||||||
// Request mediator and vendor while we're at it
|
// Request mediator and vendor while we're at it
|
||||||
// Will coordinating send this on make requests next
|
// Will coordinating send this on make requests next
|
||||||
|
|
||||||
let s = db::Interface::async_open().await;
|
let s = db::Interface::async_open().await;
|
||||||
let m_msig_key = format!(
|
let m_msig_key = format!(
|
||||||
"{}-{}-{}",
|
"{}-{}-{}",
|
||||||
|
@ -2217,7 +2241,6 @@ fn send_import_info_req(tx: Sender<String>, ctx: egui::Context, orid: &String, v
|
||||||
ctx.request_repaint();
|
ctx.request_repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO(c2m): do we need a manual trigger for the shipping request?
|
// TODO(c2m): do we need a manual trigger for the shipping request?
|
||||||
|
|
||||||
// fn shipping_req(
|
// fn shipping_req(
|
||||||
|
@ -2239,6 +2262,23 @@ fn send_import_info_req(tx: Sender<String>, ctx: egui::Context, orid: &String, v
|
||||||
// }
|
// }
|
||||||
// End Async fn requests
|
// End Async fn requests
|
||||||
|
|
||||||
|
fn cancel_order_req(
|
||||||
|
tx: Sender<models::Order>,
|
||||||
|
ctx: egui::Context,
|
||||||
|
orid: &String,
|
||||||
|
contact: &String,
|
||||||
|
) {
|
||||||
|
let ship_orid = String::from(orid);
|
||||||
|
let vendor_i2p = String::from(contact);
|
||||||
|
tokio::spawn(async move {
|
||||||
|
log::info!("cancel order req: {}", ship_orid);
|
||||||
|
let order = order::d_trigger_cancel_request(&vendor_i2p, &ship_orid).await;
|
||||||
|
let _ = tx.send(order);
|
||||||
|
ctx.request_repaint();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// End Async fn requests
|
||||||
|
|
||||||
fn validate_msig_step(
|
fn validate_msig_step(
|
||||||
mediator: &String,
|
mediator: &String,
|
||||||
orid: &String,
|
orid: &String,
|
||||||
|
@ -2271,7 +2311,7 @@ fn release_txset(
|
||||||
let _ = tx.send(false);
|
let _ = tx.send(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO(next commit): we need to build an API that tells the vendor
|
// TODO(c2m): we need to build an API that tells the vendor
|
||||||
// to verify the txset was submitted successfully
|
// to verify the txset was submitted successfully
|
||||||
// return boolean.
|
// return boolean.
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use rocket::{
|
use rocket::{
|
||||||
get,
|
get,
|
||||||
http::Status,
|
http::Status,
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use rocket::{
|
use rocket::{
|
||||||
get,
|
get,
|
||||||
http::Status,
|
http::Status,
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use rocket::{
|
use rocket::{
|
||||||
catch,
|
catch,
|
||||||
get,
|
get,
|
||||||
|
@ -219,6 +221,24 @@ pub async fn trigger_nasr(
|
||||||
Custom(Status::Ok, Json(order))
|
Custom(Status::Ok, Json(order))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Customer cancel order logic. Must send `signature`
|
||||||
|
///
|
||||||
|
/// which is the order id signed by the NEVEKO wallet.
|
||||||
|
///
|
||||||
|
/// Protected: true
|
||||||
|
#[post("/order/cancel/<orid>/<signature>")]
|
||||||
|
pub async fn cancel_order(
|
||||||
|
orid: String,
|
||||||
|
signature: String,
|
||||||
|
_jwp: proof::PaymentProof,
|
||||||
|
) -> Custom<Json<models::Order>> {
|
||||||
|
let m_order = order::cancel_order(&orid, &signature).await;
|
||||||
|
if m_order.cid == utils::empty_string() {
|
||||||
|
return Custom(Status::BadRequest, Json(Default::default()));
|
||||||
|
}
|
||||||
|
Custom(Status::Created, Json(m_order))
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a dispute (customer)
|
/// Create a dispute (customer)
|
||||||
#[post("/create", data = "<dispute>")]
|
#[post("/create", data = "<dispute>")]
|
||||||
pub async fn create_dispute(
|
pub async fn create_dispute(
|
||||||
|
|
Loading…
Reference in a new issue