start testing nasr implementation

This commit is contained in:
creating2morrow 2023-12-05 02:06:01 -05:00
parent 2b5cb6ef1f
commit 1e65a87127
6 changed files with 153 additions and 64 deletions

View file

@ -8,9 +8,9 @@ use lmdb::{
Environment, Environment,
}; };
use log::{ use log::{
info,
debug, debug,
error, error,
info,
}; };
use crate::utils; use crate::utils;

View file

@ -429,7 +429,12 @@ pub async fn sign(data: String) -> reqres::XmrRpcSignResponse {
/// Performs the xmr rpc 'verify' method /// Performs the xmr rpc 'verify' method
pub async fn verify(address: String, data: String, signature: String) -> bool { pub async fn verify(address: String, data: String, signature: String) -> bool {
info!("executing {} for sig: {} on {}", RpcFields::Verify.value(), &signature, &data); info!(
"executing {} for sig: {} on {}",
RpcFields::Verify.value(),
&signature,
&data
);
let client = reqwest::Client::new(); let client = reqwest::Client::new();
let host = get_rpc_host(); let host = get_rpc_host();
let params = reqres::XmrRpcVerifyParams { let params = reqres::XmrRpcVerifyParams {

View file

@ -4,6 +4,7 @@ use crate::{
contact, contact,
db, db,
gpg, gpg,
i2p,
message, message,
models::*, models::*,
monero, monero,
@ -287,11 +288,43 @@ pub async fn validate_order_for_ship(orid: &String) -> reqres::FinalizeOrderResp
} }
} }
/// NASR (neveko auto-ship request)
pub async fn trigger_nasr(
contact: &String,
jwp: &String,
orid: &String,
) -> Result<Order, Box<dyn Error>> {
info!("executing trigger_nasr");
let host = utils::get_i2p_http_proxy();
let proxy = reqwest::Proxy::http(&host)?;
let client = reqwest::Client::builder().proxy(proxy).build();
match client?
.get(format!("http://{}/ship/{}/{}", contact, orid, contact))
.header("proof", jwp)
.send()
.await
{
Ok(response) => {
let res = response.json::<Order>().await;
debug!("order retrieve response: {:?}", res);
match res {
Ok(r) => Ok(r),
_ => Ok(Default::default()),
}
}
Err(e) => {
error!("failed to trigger due to: {:?}", e);
Ok(Default::default())
}
}
}
/// Write encrypted delivery info to lmdb. Once the customer releases the signed /// Write encrypted delivery info to lmdb. Once the customer releases the signed
/// txset /// txset
/// ///
/// This will also attempt to notify the customer to trigger the NASR (neveko auto-ship request). /// This will also attempt to notify the customer to trigger the NASR (neveko
/// /// auto-ship request).
///
/// they will have access to this information (tracking number, locker code, /// they will have access to this information (tracking number, locker code,
/// etc.) /// etc.)
pub async fn upload_delivery_info( pub async fn upload_delivery_info(
@ -300,7 +333,8 @@ pub async fn upload_delivery_info(
) -> reqres::FinalizeOrderResponse { ) -> reqres::FinalizeOrderResponse {
info!("uploading delivery info"); info!("uploading delivery info");
let lookup: Order = order::find(orid); let lookup: Order = order::find(orid);
let e_delivery_info: Vec<u8> = gpg::encrypt(lookup.cid, &delivery_info).unwrap_or(Vec::new()); let e_delivery_info: Vec<u8> =
gpg::encrypt(String::from(&lookup.cid), &delivery_info).unwrap_or(Vec::new());
if e_delivery_info.is_empty() { if e_delivery_info.is_empty() {
error!("unable to encrypt delivery info"); error!("unable to encrypt delivery info");
} }
@ -313,11 +347,23 @@ pub async fn upload_delivery_info(
m_order.ship_date = chrono::offset::Utc::now().timestamp(); m_order.ship_date = chrono::offset::Utc::now().timestamp();
m_order.hash = String::from(&sweep.result.tx_hash_list.remove(0)); m_order.hash = String::from(&sweep.result.tx_hash_list.remove(0));
m_order.vend_msig_txset = sweep.result.multisig_txset; m_order.vend_msig_txset = sweep.result.multisig_txset;
// delivery info will be stored encrypted and separate from the rest of the order // delivery info will be stored encrypted and separate from the rest of the
// order
let s = db::Interface::async_open().await; let s = db::Interface::async_open().await;
let k = String::from(crate::DELIVERY_INFO_DB_KEY); let k = String::from(crate::DELIVERY_INFO_DB_KEY);
db::Interface::async_write(&s.env, &s.handle, &k, &hex::encode(&delivery_info)).await; db::Interface::async_write(&s.env, &s.handle, &k, &hex::encode(&delivery_info)).await;
modify(Json(m_order)); modify(Json(m_order));
// trigger nasr, this will cause the customer's neveko instance to request the
// txset
let i2p_address = i2p::get_destination(None);
let s = db::Interface::open();
// get jwp from db
let k = format!("{}-{}", crate::FTS_JWP_DB_KEY, &lookup.cid);
let jwp = db::Interface::read(&s.env, &s.handle, &k);
let nasr_order = trigger_nasr(&i2p_address, &jwp, orid).await;
if nasr_order.is_err() {
return Default::default();
}
FinalizeOrderResponse { FinalizeOrderResponse {
delivery_info: delivery_info.to_vec(), delivery_info: delivery_info.to_vec(),
orid: String::from(orid), orid: String::from(orid),
@ -471,11 +517,7 @@ pub async fn transmit_sor_request(
/// A decomposition trigger for the shipping request so that the logic /// A decomposition trigger for the shipping request so that the logic
/// ///
/// can be executed from the gui. /// can be executed from the gui.
pub async fn trigger_ship_request( pub async fn trigger_ship_request(contact: &String, jwp: &String, orid: &String) -> Order {
contact: &String,
jwp: &String,
orid: &String,
) -> Order {
info!("executing trigger_ship_request"); info!("executing trigger_ship_request");
let data = String::from(orid); let data = String::from(orid);
let wallet_password = let wallet_password =
@ -495,16 +537,17 @@ pub async fn trigger_ship_request(
} }
/// Decomposition trigger for the shipping request /// Decomposition trigger for the shipping request
pub async fn d_trigger_ship_request( pub async fn d_trigger_ship_request(contact: &String, orid: &String) -> Order {
contact: &String, // ugh, sorry seems we need to get jwp for vendor from fts cache
jwp: &String, // get jwp from db
orid: &String, let s = db::Interface::async_open().await;
) -> Order { 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_ship_request"); info!("executing d_trigger_ship_request");
// request shipment if the order status is MultisigComplete // request shipment if the order status is MultisigComplete
let trigger = trigger_ship_request(contact, jwp, orid).await; let trigger = trigger_ship_request(contact, &jwp, orid).await;
if trigger.status == order::StatusType::MulitsigComplete.value() { if trigger.status == order::StatusType::MulitsigComplete.value() {
let ship_res = transmit_ship_request(contact, jwp, orid).await; let ship_res = transmit_ship_request(contact, &jwp, orid).await;
if ship_res.is_err() { if ship_res.is_err() {
error!("failure to decompose trigger_ship_request"); error!("failure to decompose trigger_ship_request");
return Default::default(); return Default::default();

View file

@ -109,8 +109,8 @@ pub struct MarketApp {
_refresh_on_delete_product_rx: Receiver<bool>, _refresh_on_delete_product_rx: Receiver<bool>,
submit_order_tx: Sender<models::Order>, submit_order_tx: Sender<models::Order>,
submit_order_rx: Receiver<models::Order>, submit_order_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,
s_order: models::Order, s_order: models::Order,
vendor_status: utils::ContactStatus, vendor_status: utils::ContactStatus,
@ -132,7 +132,7 @@ impl Default for MarketApp {
let (get_vendor_products_tx, get_vendor_products_rx) = std::sync::mpsc::channel(); let (get_vendor_products_tx, get_vendor_products_rx) = std::sync::mpsc::channel();
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 (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();
@ -201,8 +201,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(),
ship_request_rx, // ship_request_rx,
ship_request_tx, // ship_request_tx,
submit_order_rx, submit_order_rx,
submit_order_tx, submit_order_tx,
vendor_status: Default::default(), vendor_status: Default::default(),
@ -301,12 +301,12 @@ impl eframe::App for MarketApp {
self.is_loading = false; self.is_loading = false;
} }
if let Ok(shipped) = self.ship_request_rx.try_recv() { // if let Ok(shipped) = self.ship_request_rx.try_recv() {
if shipped.status != order::StatusType::Shipped.value() { // if shipped.status != order::StatusType::Shipped.value() {
log::error!("failure to obtain shipment please contact vendor") // log::error!("failure to obtain shipment please contact vendor")
} // }
self.is_loading = false; // self.is_loading = false;
} // }
// Vendor status window // Vendor status window
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------
@ -625,32 +625,49 @@ impl eframe::App for MarketApp {
}); });
} }
if self.msig.completed_export && !self.msig.completed_shipping_request { 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
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.label("Request Shipping: \t"); ui.label(
if ui.button("Send").clicked() { RichText::new("Delivery Pending")
let vendor_prefix = String::from(crate::GUI_OVL_DB_KEY); .small()
let vendor = utils::search_gui_db(vendor_prefix, self.m_order.orid.clone()); .color(ui.visuals().code_bg_color),
self.is_loading = true; )
let jwp = utils::search_gui_db( .on_hover_text("Please wait for the vendor to upload delivery info.");
String::from(crate::GUI_JWP_DB_KEY),
String::from(&vendor),
);
shipping_req(
self.ship_request_tx.clone(),
ctx.clone(),
&self.m_order.orid,
&vendor,
&jwp,
);
}
if ui.button("Check").clicked() { if ui.button("Check").clicked() {
let order = order::find(&self.m_order.orid); let order = order::find(&self.m_order.orid.clone());
if order.status == order::StatusType::Shipped.value() { if order.status == order::StatusType::Shipped.value() {
self.msig.completed_shipping_request = true; self.msig.completed_shipping_request = true;
} }
} }
}); });
} }
// ui.horizontal(|ui| {
// ui.label("Request Shipping: \t");
// if ui.button("Send").clicked() {
// 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;
// let jwp = utils::search_gui_db(
// String::from(crate::GUI_JWP_DB_KEY),
// String::from(&vendor),
// );
// shipping_req(
// self.ship_request_tx.clone(),
// ctx.clone(),
// &self.m_order.orid,
// &vendor,
// &jwp,
// );
// }
// if ui.button("Check").clicked() {
// let order = order::find(&self.m_order.orid);
// if order.status == order::StatusType::Shipped.value() {
// self.msig.completed_shipping_request = true;
// }
// }
// });
// }
if self.msig.completed_shipping_request && !self.msig.completed_payment_release { if self.msig.completed_shipping_request && !self.msig.completed_payment_release {
ui.horizontal(|ui| { ui.horizontal(|ui| {
ui.label("Release Payment: \t"); ui.label("Release Payment: \t");
@ -2141,23 +2158,23 @@ fn send_import_info_req(tx: Sender<String>, ctx: egui::Context, orid: &String, v
ctx.request_repaint(); ctx.request_repaint();
} }
fn shipping_req( // fn shipping_req(
tx: Sender<models::Order>, // tx: Sender<models::Order>,
ctx: egui::Context, // ctx: egui::Context,
orid: &String, // orid: &String,
contact: &String, // contact: &String,
jwp: &String, // jwp: &String,
) { // ) {
let ship_orid = String::from(orid); // let ship_orid = String::from(orid);
let vendor_i2p = String::from(contact); // let vendor_i2p = String::from(contact);
let v_jwp = String::from(jwp); // let v_jwp = String::from(jwp);
tokio::spawn(async move { // tokio::spawn(async move {
log::info!("shipping order req: {}", ship_orid); // log::info!("shipping order req: {}", ship_orid);
let order = order::d_trigger_ship_request(&vendor_i2p, &v_jwp, &ship_orid).await; // let order = order::d_trigger_ship_request(&vendor_i2p, &v_jwp, &ship_orid).await;
let _ = tx.send(order); // let _ = tx.send(order);
ctx.request_repaint(); // ctx.request_repaint();
}); // });
} // }
// End Async fn requests // End Async fn requests
fn validate_msig_step( fn validate_msig_step(

View file

@ -102,6 +102,8 @@ pub async fn sign_and_submit_multisig(
/// API for uploading delivery info in vendor mode /// API for uploading delivery info in vendor mode
/// ///
/// Attempts to trigger NASR so that and automate txset draft from vendor.
///
/// Protected: true /// Protected: true
#[post("/<orid>", data = "<r_data>")] #[post("/<orid>", data = "<r_data>")]
pub async fn upload_delivery_info( pub async fn upload_delivery_info(

View file

@ -197,6 +197,28 @@ pub async fn request_shipment(
Custom(Status::Ok, Json(finalize)) Custom(Status::Ok, Json(finalize))
} }
/// The vendor should trigger nasr once they have uploaded delivery info.
///
/// This will automate txset release from the customer
///
/// orid - `order id of the nasr`
///
/// vedor - `vendor's .b32.i2p`
///
/// Protected: true
#[post("/ship/<vendor>/<orid>")]
pub async fn trigger_nasr(
orid: String,
vendor: String,
_jwp: proof::PaymentProof,
) -> Custom<Json<models::Order>> {
let order: models::Order = order::d_trigger_ship_request(&orid, &vendor).await;
if order.orid == utils::empty_string() {
return Custom(Status::BadRequest, Json(Default::default()));
}
Custom(Status::Ok, Json(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(