mirror of
https://github.com/creating2morrow/neveko.git
synced 2024-12-22 11:39:22 +00:00
submit txset and finalize order - untested
This commit is contained in:
parent
bb492fce8c
commit
6340119435
5 changed files with 154 additions and 30 deletions
|
@ -9,8 +9,7 @@ use crate::{
|
|||
monero,
|
||||
order,
|
||||
product,
|
||||
reqres,
|
||||
utils,
|
||||
utils, reqres,
|
||||
};
|
||||
use log::{
|
||||
debug,
|
||||
|
@ -421,12 +420,120 @@ pub async fn upload_delivery_info(
|
|||
/// upon a `vendor_update_success: true` response
|
||||
pub async fn finalize_order(orid: &String) -> reqres::FinalizeOrderResponse {
|
||||
info!("finalizing order: {}", orid);
|
||||
|
||||
// verify recipient and unlock time
|
||||
let mut m_order: Order = order::find(orid);
|
||||
if m_order.vend_msig_txset == utils::empty_string() {
|
||||
error!("txset missing");
|
||||
return Default::default();
|
||||
}
|
||||
// get draft payment txset
|
||||
let wallet_password = utils::empty_string();
|
||||
monero::open_wallet(orid, &wallet_password).await;
|
||||
monero::refresh().await;
|
||||
let address: String = String::from(&m_order.subaddress);
|
||||
let m_describe = monero::describe_transfer(&m_order.vend_msig_txset).await;
|
||||
let check_destination: reqres::Destination = reqres::Destination {
|
||||
address,
|
||||
..Default::default()
|
||||
};
|
||||
let valid = m_describe.result.desc[0].recepients.contains(&check_destination)
|
||||
&& m_describe.result.desc[0].unlock_time < monero::LockTimeLimit::Blocks.value();
|
||||
if !valid {
|
||||
monero::close_wallet(orid, &wallet_password).await;
|
||||
error!("invalid txset");
|
||||
return Default::default();
|
||||
}
|
||||
// verify order wallet has been swept clean
|
||||
let balance = monero::get_balance().await;
|
||||
if balance.result.unlocked_balance != 0 {
|
||||
monero::close_wallet(orid, &wallet_password).await;
|
||||
error!("order wallet not swept");
|
||||
return Default::default();
|
||||
}
|
||||
m_order.status = order::StatusType::Delivered.value();
|
||||
order::modify(Json(m_order));
|
||||
reqres::FinalizeOrderResponse {
|
||||
vendor_update_success: true,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Executes POST /order/finalize/{orid}
|
||||
///
|
||||
/// finalizing the order on the vendor side.
|
||||
///
|
||||
/// Customer needs to verify the response and update their lmdb.
|
||||
///
|
||||
/// see `finalize_order`
|
||||
pub async fn transmit_finalize_request(
|
||||
contact: &String,
|
||||
jwp: &String,
|
||||
orid: &String,
|
||||
) -> Result<reqres::FinalizeOrderResponse, 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/finalize/{}", contact, orid
|
||||
))
|
||||
.header("proof", jwp)
|
||||
.send()
|
||||
.await
|
||||
{
|
||||
Ok(response) => {
|
||||
let res = response.json::<reqres::FinalizeOrderResponse>().await;
|
||||
debug!("finalize order response: {:?}", res);
|
||||
match res {
|
||||
Ok(r) => Ok(r),
|
||||
_ => Ok(Default::default()),
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!("failed to finalize order due to: {:?}", e);
|
||||
Ok(Default::default())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A post-decomposition trigger for the finalize request so that the logic
|
||||
///
|
||||
/// can be executed from the gui.
|
||||
pub async fn trigger_finalize_request(contact: &String, jwp: &String, orid: &String) -> reqres::FinalizeOrderResponse {
|
||||
info!("executing trigger_finalize_request");
|
||||
let finalize = transmit_finalize_request(contact, jwp, orid).await;
|
||||
// cache finalize order request to db
|
||||
if finalize.is_err() {
|
||||
log::error!("failed to trigger cancel request");
|
||||
return Default::default();
|
||||
}
|
||||
let unwrap: reqres::FinalizeOrderResponse = finalize.unwrap();
|
||||
let mut m_order: Order = order::find(&orid);
|
||||
m_order.status = order::StatusType::Delivered.value();
|
||||
backup(&m_order);
|
||||
unwrap
|
||||
}
|
||||
|
||||
/// Decomposition trigger for `finalize_order()`
|
||||
pub async fn d_trigger_finalize_request(contact: &String, orid: &String) -> reqres::FinalizeOrderResponse {
|
||||
// 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_finalize_request");
|
||||
// request finalize if the order status is shipped
|
||||
let order: Order = order::find(&orid);
|
||||
if order.status != order::StatusType::Shipped.value() {
|
||||
let trigger = trigger_finalize_request(contact, &jwp, orid).await;
|
||||
if trigger.vendor_update_success {
|
||||
return trigger;
|
||||
}
|
||||
}
|
||||
Default::default()
|
||||
}
|
||||
|
||||
/// Send order request to vendor and start multisig flow
|
||||
pub async fn transmit_order_request(
|
||||
contact: String,
|
||||
|
@ -638,7 +745,7 @@ pub async fn transmit_cancel_request(
|
|||
}
|
||||
}
|
||||
|
||||
/// Decomposition trigger for the shipping request
|
||||
/// Decomposition trigger for the cancel 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
|
||||
|
|
|
@ -106,7 +106,7 @@ pub struct XmrRpcGetTxByIdParams {
|
|||
pub txid: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
#[derive(Deserialize, Serialize, Debug, PartialEq)]
|
||||
pub struct Destination {
|
||||
pub address: String,
|
||||
pub amount: u128,
|
||||
|
|
|
@ -111,8 +111,8 @@ pub struct MarketApp {
|
|||
_refresh_on_delete_product_rx: Receiver<bool>,
|
||||
submit_order_tx: Sender<models::Order>,
|
||||
submit_order_rx: Receiver<models::Order>,
|
||||
_submit_txset_tx: Sender<bool>,
|
||||
_submit_txset_rx: Receiver<bool>,
|
||||
submit_txset_tx: Sender<bool>,
|
||||
submit_txset_rx: Receiver<bool>,
|
||||
cancel_request_tx: Sender<models::Order>,
|
||||
cancel_request_rx: Receiver<models::Order>,
|
||||
// ship_request_tx: Sender<models::Order>,
|
||||
|
@ -144,7 +144,7 @@ impl Default for MarketApp {
|
|||
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_funded_tx, order_funded_rx) = std::sync::mpsc::channel();
|
||||
let (_submit_txset_tx, _submit_txset_rx) = std::sync::mpsc::channel();
|
||||
let (submit_txset_tx, submit_txset_rx) = std::sync::mpsc::channel();
|
||||
let contents = std::fs::read("./assets/qr.png").unwrap_or(Vec::new());
|
||||
MarketApp {
|
||||
contact_info_rx,
|
||||
|
@ -217,8 +217,8 @@ impl Default for MarketApp {
|
|||
// ship_request_tx,
|
||||
submit_order_rx,
|
||||
submit_order_tx,
|
||||
_submit_txset_rx,
|
||||
_submit_txset_tx,
|
||||
submit_txset_rx,
|
||||
submit_txset_tx,
|
||||
vendor_status: Default::default(),
|
||||
vendors: Vec::new(),
|
||||
}
|
||||
|
@ -332,6 +332,13 @@ impl eframe::App for MarketApp {
|
|||
self.is_loading = false;
|
||||
}
|
||||
|
||||
if let Ok(finalized) = self.submit_txset_rx.try_recv() {
|
||||
if !finalized {
|
||||
log::error!("failure to finalize shipment please contact vendor")
|
||||
}
|
||||
self.is_loading = false;
|
||||
}
|
||||
|
||||
// Vendor status window
|
||||
//-----------------------------------------------------------------------------------
|
||||
let mut is_showing_vendor_status = self.is_showing_vendor_status;
|
||||
|
@ -649,8 +656,7 @@ impl eframe::App for MarketApp {
|
|||
});
|
||||
}
|
||||
if self.msig.completed_export && !self.msig.completed_shipping_request {
|
||||
// idk if manual shipping request will be necessary with the new nasr logic,
|
||||
// let's see
|
||||
// idk if manual shipping request will be necessary with the new nasr logic
|
||||
ui.horizontal(|ui| {
|
||||
ui.label(
|
||||
RichText::new("Delivery Pending")
|
||||
|
@ -698,19 +704,18 @@ impl eframe::App for MarketApp {
|
|||
ui.horizontal(|ui| {
|
||||
ui.label("Release Payment: \t");
|
||||
if ui.button("Submit Txset").clicked() {
|
||||
self.is_loading = true;
|
||||
let vendor_prefix = String::from(crate::GUI_OVL_DB_KEY);
|
||||
let vendor =
|
||||
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone());
|
||||
// async trigger for signing and submitted the txset
|
||||
// do something
|
||||
release_txset(
|
||||
utils::empty_string(),
|
||||
utils::empty_string(),
|
||||
vendor,
|
||||
self.m_order.orid.clone(),
|
||||
ctx.clone(),
|
||||
utils::empty_string(),
|
||||
self._submit_txset_tx.clone(),
|
||||
self.submit_txset_tx.clone(),
|
||||
);
|
||||
}
|
||||
if ui.button("Check").clicked() {
|
||||
// the multisig wallet should have a zero balance if the sweep succeeded
|
||||
}
|
||||
});
|
||||
}
|
||||
// ui.horizontal(|ui| {
|
||||
|
@ -2296,10 +2301,9 @@ fn validate_msig_step(
|
|||
}
|
||||
|
||||
fn release_txset(
|
||||
_contact: String,
|
||||
contact: String,
|
||||
orid: String,
|
||||
ctx: egui::Context,
|
||||
_jwp: String,
|
||||
tx: Sender<bool>,
|
||||
) {
|
||||
tokio::spawn(async move {
|
||||
|
@ -2311,12 +2315,9 @@ fn release_txset(
|
|||
let _ = tx.send(false);
|
||||
return;
|
||||
}
|
||||
// TODO(c2m): we need to build an API that tells the vendor
|
||||
// to verify the txset was submitted successfully
|
||||
// return boolean.
|
||||
|
||||
let finalize = order::d_trigger_finalize_request(&contact, &orid).await;
|
||||
// update order to delivered if success
|
||||
let _ = tx.send(true);
|
||||
let _ = tx.send(finalize.vendor_update_success);
|
||||
ctx.request_repaint();
|
||||
todo!()
|
||||
});
|
||||
|
|
|
@ -12,6 +12,7 @@ use rocket::{
|
|||
use neveko_core::*;
|
||||
|
||||
// JSON APIs exposed over i2p
|
||||
// Take care not to put any admin APIs inside of here
|
||||
|
||||
/// Get payment API version
|
||||
///
|
||||
|
@ -236,14 +237,28 @@ pub async fn cancel_order(
|
|||
if m_order.cid == utils::empty_string() {
|
||||
return Custom(Status::BadRequest, Json(Default::default()));
|
||||
}
|
||||
Custom(Status::Created, Json(m_order))
|
||||
Custom(Status::Ok, Json(m_order))
|
||||
}
|
||||
|
||||
/// Create a dispute (customer)
|
||||
/// Customer finalize order logic. Vendor updates order
|
||||
///
|
||||
/// to `Delivered` status.
|
||||
///
|
||||
/// Protected: true
|
||||
#[post("/order/finalize/<orid>")]
|
||||
pub async fn finalize_order(orid: String, _jwp: proof::PaymentProof) -> Custom<Json<reqres::FinalizeOrderResponse>> {
|
||||
let finalize = order::finalize_order(&orid).await;
|
||||
if !finalize.vendor_update_success {
|
||||
return Custom(Status::BadRequest, Json(Default::default()));
|
||||
}
|
||||
Custom(Status::Ok, Json(finalize))
|
||||
}
|
||||
|
||||
/// Create a dispute
|
||||
#[post("/create", data = "<dispute>")]
|
||||
pub async fn create_dispute(
|
||||
dispute: Json<models::Dispute>,
|
||||
_token: auth::BearerToken,
|
||||
_jwp: proof::PaymentProof,
|
||||
) -> Custom<Json<models::Dispute>> {
|
||||
let m_dispute: models::Dispute = dispute::create(dispute);
|
||||
Custom(Status::Ok, Json(m_dispute))
|
||||
|
|
|
@ -50,6 +50,7 @@ async fn rocket() -> _ {
|
|||
controller::request_shipment,
|
||||
controller::retrieve_order,
|
||||
controller::trigger_nasr,
|
||||
controller::finalize_order,
|
||||
],
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue