add prepare mulitsig info orchestration

This commit is contained in:
creating2morrow 2023-06-01 10:14:15 -04:00
parent 06cab5460e
commit e97f3394bc
10 changed files with 308 additions and 125 deletions

View file

@ -75,8 +75,9 @@ NEVidebla-MESago (invisible message)
* nevmes-auth - `internal` auth server * nevmes-auth - `internal` auth server
* nevmes-contact - `internal` add contacts server * nevmes-contact - `internal` add contacts server
* nevmes-gui - primary user interface * nevmes-gui - primary user interface
* nevmes-market - `internal` marketplace admin server
* nevmes-message - `internal` message tx/read etc. server * nevmes-message - `internal` message tx/read etc. server
* nevmes - `external` primary server for contact share, payment, message rx etc. * nevmes - `external` primary server for contact share, payment, market, message rx etc.
* [monerod](https://www.getmonero.org/downloads/#cli) - (not included) monero-wallet-rpc needs this * [monerod](https://www.getmonero.org/downloads/#cli) - (not included) monero-wallet-rpc needs this
* can be overriden with remote node * can be overriden with remote node
* use the `--remote-node` flag * use the `--remote-node` flag

View file

@ -6,7 +6,7 @@ use crate::{
i2p, i2p,
models::*, models::*,
reqres, reqres,
utils, utils, monero,
}; };
use log::{ use log::{
debug, debug,
@ -17,9 +17,25 @@ use reqwest::StatusCode;
use rocket::serde::json::Json; use rocket::serde::json::Json;
use std::error::Error; use std::error::Error;
#[derive(PartialEq)]
pub enum MessageType {
Normal,
Multisig,
}
struct MultisigMessageData {
info: String,
sub_type: String,
orid: String,
}
/// Create a new message /// Create a new message
pub async fn create(m: Json<Message>, jwp: String) -> Message { pub async fn create(m: Json<Message>, jwp: String, m_type: MessageType) -> Message {
let f_mid: String = format!("m{}", utils::generate_rnd()); let rnd = utils::generate_rnd();
let mut f_mid: String = format!("m{}", &rnd);
if m_type == MessageType::Multisig {
f_mid = format!("msig{}", &rnd);
}
info!("creating message: {}", &f_mid); info!("creating message: {}", &f_mid);
let created = chrono::offset::Utc::now().timestamp(); let created = chrono::offset::Utc::now().timestamp();
// get contact public gpg key and encrypt the message // get contact public gpg key and encrypt the message
@ -47,7 +63,7 @@ pub async fn create(m: Json<Message>, jwp: String) -> Message {
debug!("writing message index {} for id: {}", msg_list, list_key); debug!("writing message index {} for id: {}", msg_list, list_key);
db::Interface::write(&s.env, &s.handle, &String::from(list_key), &msg_list); db::Interface::write(&s.env, &s.handle, &String::from(list_key), &msg_list);
info!("attempting to send message"); info!("attempting to send message");
let send = send_message(&new_message, &jwp).await; let send = send_message(&new_message, &jwp, m_type).await;
send.unwrap(); send.unwrap();
new_message new_message
} }
@ -88,6 +104,68 @@ pub async fn rx(m: Json<Message>) {
db::Interface::write(&s.env, &s.handle, &String::from(list_key), &msg_list); db::Interface::write(&s.env, &s.handle, &String::from(list_key), &msg_list);
} }
/// Parse the multisig message type and info
fn parse_multisig_message(mid: String) -> MultisigMessageData {
let d: reqres::DecryptedMessageBody = decrypt_body(mid);
let mut bytes = hex::decode(d.body.into_bytes()).unwrap_or(Vec::new());
let decoded = String::from_utf8(bytes).unwrap_or(utils::empty_string());
let values = decoded.split(":");
let mut v: Vec<String> = values.map(|s| String::from(s)).collect();
let sub_type: String = v.remove(0);
let orid: String = v.remove(0);
let info: String = v.remove(0);
bytes = Vec::new();
debug!("zero decryption bytes: {:?}", bytes);
MultisigMessageData { info, sub_type, orid }
}
/// Rx multisig message
///
/// Upon multisig message receipt the message is automatically
///
/// decrypted for convenience sake. The client must determine which
///
/// .b32.i2p address belongs to the vendor / mediator.
///
/// ### Example
///
/// ```rust
/// // lookup prepare info for vendor
/// let s = db::Interface::open();
/// let key = "prepare-o123-test.b32.i2p";
/// db::Interface::read(&s.env, &s.handle, &key);
/// ```
pub async fn rx_multisig(m: Json<Message>) {
// make sure the message isn't something strange
let is_valid = validate_message(&m);
if !is_valid {
return;
}
// don't allow messages from outside the contact list
let is_in_contact_list = contact::exists(&m.from);
if !is_in_contact_list {
return;
}
let f_mid: String = format!("m{}", utils::generate_rnd());
let new_message = Message {
mid: String::from(&f_mid),
uid: String::from("rx"),
from: String::from(&m.from),
body: m.body.iter().cloned().collect(),
created: chrono::offset::Utc::now().timestamp(),
to: String::from(&m.to),
};
debug!("insert multisig message: {:?}", &new_message);
let s = db::Interface::open();
let k = &new_message.mid;
db::Interface::async_write(&s.env, &s.handle, k, &Message::to_db(&new_message)).await;
let data: MultisigMessageData = parse_multisig_message(new_message.mid);
debug!("writing multisig message type {} for order {}", &data.sub_type, &data.orid);
// lookup msig message data by {type}-{order id}-{contact .b32.i2p address}
let msig_key = format!("{}-{}-{}", &data.sub_type, &data.orid, &m.from);
db::Interface::write(&s.env, &s.handle, &msig_key, &data.info);
}
/// Message lookup /// Message lookup
pub fn find(mid: &String) -> Message { pub fn find(mid: &String) -> Message {
let s = db::Interface::open(); let s = db::Interface::open();
@ -134,18 +212,21 @@ pub fn find_all() -> Vec<Message> {
} }
/// Tx message /// Tx message
async fn send_message(out: &Message, jwp: &str) -> Result<(), Box<dyn Error>> { async fn send_message(out: &Message, jwp: &str, m_type: MessageType) -> Result<(), Box<dyn Error>> {
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)?;
let client = reqwest::Client::builder().proxy(proxy).build(); let client = reqwest::Client::builder().proxy(proxy).build();
let mut url = format!("http://{}/message/rx", out.to);
if m_type == MessageType::Multisig {
url = format!("http://{}/message/rx/multisig", out.to)
}
// check if the contact is online // check if the contact is online
let is_online: bool = is_contact_online(&out.to, String::from(jwp)) let is_online: bool = is_contact_online(&out.to, String::from(jwp))
.await .await
.unwrap_or(false); .unwrap_or(false);
if is_online { if is_online {
return match client? return match client?
.post(format!("http://{}/message/rx", out.to)) .post(url)
.header("proof", jwp) .header("proof", jwp)
.json(&out) .json(&out)
.send() .send()
@ -314,7 +395,12 @@ pub async fn retry_fts() {
let k = format!("{}-{}", "fts-jwp", &message.to); let k = format!("{}-{}", "fts-jwp", &message.to);
let jwp = db::Interface::read(&s.env, &s.handle, &k); let jwp = db::Interface::read(&s.env, &s.handle, &k);
if jwp != utils::empty_string() { if jwp != utils::empty_string() {
send_message(&message, &jwp).await.unwrap(); let m_type = if message.mid.contains("misg") {
MessageType::Multisig
} else {
MessageType::Normal
};
send_message(&message, &jwp, m_type).await.unwrap();
} else { } else {
error!("not jwp found for fts id: {}", &message.mid); error!("not jwp found for fts id: {}", &message.mid);
} }
@ -339,6 +425,24 @@ fn is_fts_clear(r: String) -> bool {
v.len() >= 2 && v[v.len() - 1] == utils::empty_string() && v[0] == utils::empty_string() v.len() >= 2 && v[v.len() - 1] == utils::empty_string() && v[0] == utils::empty_string()
} }
pub async fn send_prepare_info(orid:String, contact:String) {
let s = db::Interface::open();
let prepare_info = monero::prepare_wallet().await;
let k = format!("{}-{}", "fts-jwp", &contact);
let jwp = db::Interface::read(&s.env, &s.handle, &k);
let body_str = format!("prepare:{}:{}", &orid, &prepare_info.result.multisig_info);
let message: Message = Message {
mid: utils::empty_string(),
uid: utils::empty_string(),
body: body_str.into_bytes(),
created: chrono::Utc::now().timestamp(),
from: utils::empty_string(),
to: String::from(&contact),
};
let j_message: Json<Message> = utils::message_to_json(&message);
create(j_message, jwp, MessageType::Multisig).await;
}
// Tests // Tests
//------------------------------------------------------------------------------- //-------------------------------------------------------------------------------
@ -366,7 +470,7 @@ mod tests {
let j_message = utils::message_to_json(&message); let j_message = utils::message_to_json(&message);
let jwp = String::from("test-jwp"); let jwp = String::from("test-jwp");
tokio::spawn(async move { tokio::spawn(async move {
let test_message = create(j_message, jwp).await; let test_message = create(j_message, jwp, MessageType::Normal).await;
let expected: Message = Default::default(); let expected: Message = Default::default();
assert_eq!(test_message.body, expected.body); assert_eq!(test_message.body, expected.body);
cleanup(&test_message.mid).await; cleanup(&test_message.mid).await;

View file

@ -315,17 +315,20 @@ pub struct Order {
pub cust_msig_txset: String, pub cust_msig_txset: String,
pub date: i64, pub date: i64,
pub deliver_date: i64, pub deliver_date: i64,
/// Transaction hash from vendor or customer signed txset
pub hash: String, pub hash: String,
pub mediator_kex_1: String, pub mediator_kex_1: String,
pub mediator_kex_2: String, pub mediator_kex_2: String,
pub mediator_kex_3: String, pub mediator_kex_3: String,
pub mediator_msig_make: String, pub mediator_msig_make: String,
pub mediator_msig_prepare: String, pub mediator_msig_prepare: String,
/// Address gpg key encrypted bytes
pub ship_address: Vec<u8>,
pub ship_date: i64, pub ship_date: i64,
/// This is the final destination for the payment /// This is the final destination for the payment
pub subaddress: String, pub subaddress: String,
pub status: String, pub status: String,
pub quantity: i64, pub quantity: u64,
pub vend_kex_1: String, pub vend_kex_1: String,
pub vend_kex_2: String, pub vend_kex_2: String,
pub vend_kex_3: String, pub vend_kex_3: String,
@ -350,13 +353,14 @@ impl Default for Order {
cust_msig_txset: utils::empty_string(), cust_msig_txset: utils::empty_string(),
date: 0, date: 0,
deliver_date: 0, deliver_date: 0,
ship_date: 0,
hash: utils::empty_string(), hash: utils::empty_string(),
mediator_kex_1: utils::empty_string(), mediator_kex_1: utils::empty_string(),
mediator_kex_2: utils::empty_string(), mediator_kex_2: utils::empty_string(),
mediator_kex_3: utils::empty_string(), mediator_kex_3: utils::empty_string(),
mediator_msig_make: utils::empty_string(), mediator_msig_make: utils::empty_string(),
mediator_msig_prepare: utils::empty_string(), mediator_msig_prepare: utils::empty_string(),
ship_address: Vec::new(),
ship_date: 0,
subaddress: utils::empty_string(), subaddress: utils::empty_string(),
status: utils::empty_string(), status: utils::empty_string(),
quantity: 0, quantity: 0,
@ -372,8 +376,9 @@ impl Default for Order {
impl Order { impl Order {
pub fn to_db(o: &Order) -> String { pub fn to_db(o: &Order) -> String {
let ship_address = hex::encode(&o.ship_address);
format!( format!(
"{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}", "{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}",
o.cid, o.cid,
o.pid, o.pid,
o.cust_kex_1, o.cust_kex_1,
@ -390,6 +395,7 @@ impl Order {
o.mediator_kex_1, o.mediator_kex_1,
o.mediator_kex_2, o.mediator_kex_2,
o.mediator_kex_3, o.mediator_kex_3,
ship_address,
o.ship_date, o.ship_date,
o.subaddress, o.subaddress,
o.status, o.status,
@ -429,13 +435,14 @@ impl Order {
let mediator_kex_1 = v.remove(0); let mediator_kex_1 = v.remove(0);
let mediator_kex_2 = v.remove(0); let mediator_kex_2 = v.remove(0);
let mediator_kex_3 = v.remove(0); let mediator_kex_3 = v.remove(0);
let ship_address = hex::decode(v.remove(0)).unwrap_or(Vec::new());
let ship_date = match v.remove(0).parse::<i64>() { let ship_date = match v.remove(0).parse::<i64>() {
Ok(d) => d, Ok(d) => d,
Err(_) => 0, Err(_) => 0,
}; };
let subaddress = v.remove(0); let subaddress = v.remove(0);
let status = v.remove(0); let status = v.remove(0);
let quantity = match v.remove(0).parse::<i64>() { let quantity = match v.remove(0).parse::<u64>() {
Ok(d) => d, Ok(d) => d,
Err(_) => 0, Err(_) => 0,
}; };
@ -464,6 +471,7 @@ impl Order {
mediator_kex_3, mediator_kex_3,
mediator_msig_make, mediator_msig_make,
mediator_msig_prepare, mediator_msig_prepare,
ship_address,
ship_date, ship_date,
subaddress, subaddress,
status, status,
@ -496,6 +504,7 @@ impl Order {
mediator_kex_3: String::from(&o.mediator_kex_3), mediator_kex_3: String::from(&o.mediator_kex_3),
mediator_msig_make: String::from(&o.mediator_msig_make), mediator_msig_make: String::from(&o.mediator_msig_make),
mediator_msig_prepare: String::from(&o.mediator_msig_prepare), mediator_msig_prepare: String::from(&o.mediator_msig_prepare),
ship_address: o.ship_address.iter().cloned().collect(),
ship_date: o.ship_date, ship_date: o.ship_date,
subaddress: String::from(&o.subaddress), subaddress: String::from(&o.subaddress),
status: String::from(&o.status), status: String::from(&o.status),

View file

@ -1080,3 +1080,24 @@ impl Default for ErrorResponse {
} }
} }
} }
/// Handle intial information for request
#[derive(Serialize, Deserialize, Debug)]
#[serde(crate = "rocket::serde")]
pub struct OrderRequest {
pub cid: String,
pub pid: String,
pub ship_address: Vec<u8>,
pub quantity: u64,
}
impl Default for OrderRequest {
fn default() -> Self {
OrderRequest {
cid: utils::empty_string(),
pid: utils::empty_string(),
ship_address: Vec::new(),
quantity: 0,
}
}
}

View file

@ -778,7 +778,8 @@ fn send_message_req(tx: Sender<bool>, ctx: egui::Context, body: String, to: Stri
}; };
let j_message = utils::message_to_json(&m); let j_message = utils::message_to_json(&m);
tokio::spawn(async move { tokio::spawn(async move {
let result = message::create(j_message, jwp).await; let m_type = message::MessageType::Normal;
let result = message::create(j_message, jwp, m_type).await;
if result.mid != utils::empty_string() { if result.mid != utils::empty_string() {
log::info!("sent message: {}", result.mid); log::info!("sent message: {}", result.mid);
let _ = tx.send(true); let _ = tx.send(true);

View file

@ -13,7 +13,7 @@ async fn rocket() -> _ {
..rocket::Config::debug_default() ..rocket::Config::debug_default()
}; };
env_logger::init(); env_logger::init();
log::info!("nevmes-auth is online"); log::info!("nevmes-market is online");
rocket::custom(&config) rocket::custom(&config)
.mount( .mount(
"/dispute", "/dispute",

View file

@ -1,109 +1,94 @@
// use nevmes_core::*; use nevmes_core::*;
// use log::{debug, error, info}; use log::{debug, error, info};
// use rocket::serde::json::Json; use rocket::serde::json::Json;
// use crate::product;
// enum StatusType { enum StatusType {
// Delivered, _Delivered,
// MultisigMissing, MultisigMissing,
// MulitsigComplete, _MulitsigComplete,
// Shipped, _Shipped,
// } }
// impl StatusType { impl StatusType {
// pub fn value(&self) -> String { pub fn value(&self) -> String {
// match *self { match *self {
// 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"),
// StatusType::Shipped => String::from("Shipped"), StatusType::_Shipped => String::from("Shipped"),
// } }
// } }
// } }
// /// Create a skeleton for order /// Create a intial order
// pub fn create(cid: String, pid: String) -> models::Order { pub async fn create(j_order: Json<reqres::OrderRequest>) -> models::Order {
// let ts = chrono::offset::Utc::now().timestamp(); info!("creating order");
// let orid: String = format!("O{}", utils::generate_rnd()); let ts = chrono::offset::Utc::now().timestamp();
// let m_product: models::Product = product::find(&pid); let orid: String = format!("O{}", utils::generate_rnd());
// let new_order = models::Order { let r_subaddress = monero::create_address().await;
// orid, let subaddress = r_subaddress.result.address;
// cid: String::from(&cid), let new_order = models::Order {
// pid: String::from(&pid), orid: String::from(&orid),
// cust_kex_1: utils::empty_string(), cid: String::from(&j_order.cid),
// cust_kex_2: utils::empty_string(), pid: String::from(&j_order.pid),
// cust_kex_3: utils::empty_string(), date: ts,
// cust_msig_make: utils::empty_string(), ship_address: j_order.ship_address.iter().cloned().collect(),
// cust_msig_prepare: utils::empty_string(), subaddress,
// cust_msig_txset: utils::empty_string(), status: StatusType::MultisigMissing.value(),
// date: 0, quantity: j_order.quantity,
// deliver_date: 0, ..Default::default()
// hash: utils::empty_string(), };
// mediator_kex_1: utils::empty_string(), debug!("insert order: {:?}", new_order);
// mediator_kex_2: utils::empty_string(), let m_wallet = monero::create_wallet(String::from(&orid), &utils::empty_string()).await;
// mediator_kex_3: utils::empty_string(), if !m_wallet {
// mediator_msig_make: utils::empty_string(), error!("error creating msig wallet for order {}", &orid);
// mediator_msig_prepare: utils::empty_string(), return Default::default();
// ship_date: 0, }
// subaddress: utils::empty_string(), debug!("insert order: {:?}", &new_order);
// status: utils::empty_string(), let s = db::Interface::open();
// quantity: 0, let k = &new_order.orid;
// vend_kex_1: utils::empty_string(), db::Interface::write(&s.env, &s.handle, k, &models::Order::to_db(&new_order));
// vend_kex_2: utils::empty_string(), // in order to retrieve all orders, write keys to with ol
// vend_kex_3: utils::empty_string(), let list_key = format!("ol");
// vend_msig_make: utils::empty_string(), let r = db::Interface::read(&s.env, &s.handle, &String::from(&list_key));
// vend_msig_prepare: utils::empty_string(), if r == utils::empty_string() {
// vend_msig_txset: utils::empty_string(), debug!("creating order index");
// xmr_address: utils::empty_string(), }
// }; let order_list = [r, String::from(&orid)].join(",");
// debug!("insert order: {:?}", new_order); debug!("writing order index {} for id: {}", order_list, list_key);
// let m_wallet = monero::create_wallet(String::from(&orid), &utils::empty_string()).await; db::Interface::write(&s.env, &s.handle, &String::from(list_key), &order_list);
// if !m_wallet { new_order
// error!("error creating msig wallet for order {}", &orid); }
// }
// debug!("insert order: {:?}", &new_order);
// let s = db::Interface::open();
// let k = &new_order.orid;
// db::Interface::write(&s.env, &s.handle, k, &models::Order::to_db(&new_order));
// // in order to retrieve all orders, write keys to with ol
// let list_key = format!("ol");
// let r = db::Interface::read(&s.env, &s.handle, &String::from(&list_key));
// if r == utils::empty_string() {
// debug!("creating order index");
// }
// let order_list = [r, String::from(&orid)].join(",");
// debug!("writing order index {} for id: {}", order_list, list_key);
// db::Interface::write(&s.env, &s.handle, &String::from(list_key), &order_list);
// new_order
// }
// /// Lookup order /// Lookup order
// pub fn find(oid: String) -> models::Order { pub fn find(oid: String) -> models::Order {
// let s = db::Interface::open(); info!("find order: {}", &oid);
// let r = db::Interface::read(&s.env, &s.handle, &String::from(&oid)); let s = db::Interface::open();
// if r == utils::empty_string() { let r = db::Interface::read(&s.env, &s.handle, &String::from(&oid));
// error!("order not found"); if r == utils::empty_string() {
// return Default::default(); error!("order not found");
// } return Default::default();
// models::Order::from_db(String::from(&oid), r) }
// } models::Order::from_db(String::from(&oid), r)
}
// /// Lookup all orders for customer /// Lookup all orders for customer
// pub async fn find_all_customer_orders(cid: String) -> Vec<models::Order> { pub async fn find_all_customer_orders(cid: String) -> Vec<models::Order> {
// let i_s = db::Interface::open(); info!("lookup orders for customer: {}", &cid);
// let i_list_key = format!("ol"); let i_s = db::Interface::open();
// let i_r = db::Interface::read(&i_s.env, &i_s.handle, &String::from(i_list_key)); let i_list_key = format!("ol");
// if i_r == utils::empty_string() { let i_r = db::Interface::read(&i_s.env, &i_s.handle, &String::from(i_list_key));
// error!("order index not found"); if i_r == utils::empty_string() {
// } error!("order index not found");
// let i_v_oid = i_r.split(","); }
// let i_v: Vec<String> = i_v_oid.map(|s| String::from(s)).collect(); let i_v_oid = i_r.split(",");
// let mut orders: Vec<models::Order> = Vec::new(); let i_v: Vec<String> = i_v_oid.map(|s| String::from(s)).collect();
// for o in i_v { let mut orders: Vec<models::Order> = Vec::new();
// let order: models::Order = find(o); for o in i_v {
// if order.orid != utils::empty_string() && order.cid == cid { let order: models::Order = find(o);
// orders.push(order); if order.orid != utils::empty_string() && order.cid == cid {
// } orders.push(order);
// } }
// orders }
// } orders
}

View file

@ -15,12 +15,18 @@ use nevmes_core::{
}; };
/// Send message /// Send message
#[post("/", data = "<m_req>")] #[post("/<r_type>", data = "<m_req>")]
pub async fn send_message( pub async fn send_message(
m_req: Json<Message>, m_req: Json<Message>,
r_type: String,
token: proof::PaymentProof, token: proof::PaymentProof,
) -> Custom<Json<Message>> { ) -> Custom<Json<Message>> {
let res: Message = message::create(m_req, token.get_jwp()).await; let m_type: message::MessageType = if r_type == "multisig" {
message::MessageType::Multisig
} else {
message::MessageType::Normal
};
let res: Message = message::create(m_req, token.get_jwp(), m_type).await;
Custom(Status::Ok, Json(res)) Custom(Status::Ok, Json(res))
} }

View file

@ -37,7 +37,7 @@ pub async fn get_i2p_status() -> Custom<Json<i2p::HttpProxyStatus>> {
} }
/// Share your contact information /// Share your contact information
/// TODO(c2m): configurable option to only allow adding after JWP creation ///
/// Protected: false /// Protected: false
#[get("/")] #[get("/")]
pub async fn share_contact_info() -> Custom<Json<models::Contact>> { pub async fn share_contact_info() -> Custom<Json<models::Contact>> {
@ -78,11 +78,66 @@ pub async fn gen_jwp(proof: Json<proof::TxProof>) -> Custom<Json<reqres::Jwp>> {
// NEVMES Market APIs // NEVMES Market APIs
//----------------------------------------------- //-----------------------------------------------
/// Get all products by passing vendor address /// Get all products
/// ///
/// Protected: true /// Protected: false
#[get("/products")] #[get("/products")]
pub async fn get_products(_jwp: proof::PaymentProof) -> Custom<Json<Vec<models::Product>>> { pub async fn get_products(_jwp: proof::PaymentProof) -> Custom<Json<Vec<models::Product>>> {
let m_products: Vec<models::Product> = product::find_all(); let m_products: Vec<models::Product> = product::find_all();
Custom(Status::Ok, Json(m_products)) Custom(Status::Ok, Json(m_products))
} }
/// Create order
///
/// Protected: true
#[post("/order/create", data = "<r_order>")]
pub async fn create_order(
r_order: Json<reqres::OrderRequest>,
_jwp: proof::PaymentProof) -> Custom<Json<models::Order>> {
let m_order: models::Order = order::create(r_order).await;
Custom(Status::Created, Json(m_order))
}
/// Customer order retreival. Must send `signature`
///
/// which is the order id signed by the wallet.
///
/// Protected: true
#[get("/order/retrieve/<orid>/<_signature>")]
pub async fn retrieve_order(
orid: String,
_signature: String,
_jwp: proof::PaymentProof) -> Custom<Json<models::Order>> {
// get customer address
// send address, orid and signature to verify()
let m_order: models::Order = order::find(orid);
Custom(Status::Created, Json(m_order))
}
/// Create order
///
/// Protected: true
#[get("/multisig/prepare/<orid>/<contact>")]
pub async fn get_prepare_multisig_info(
orid: String,
contact: String,
_jwp: proof::PaymentProof) -> Custom<Json<models::Order>> {
// TODO(c2m): create a multisig message
message::send_prepare_info(orid, contact).await;
Custom(Status::Ok, Json(Default::default()))
}
/// Recieve multisig messages here
///
/// Protected: true
#[post("/", data = "<message>")]
pub async fn rx_multisig_message(
_jwp: proof::PaymentProof,
message: Json<models::Message>,
) -> Custom<Json<models::Message>> {
message::rx_multisig(message).await;
Custom(Status::Ok, Json(Default::default()))
}

View file

@ -54,6 +54,7 @@ async fn rocket() -> _ {
.register("/", catchers![internal_error, not_found, payment_required]) .register("/", catchers![internal_error, not_found, payment_required])
.mount("/invoice", routes![controller::gen_invoice]) .mount("/invoice", routes![controller::gen_invoice])
.mount("/message/rx", routes![controller::rx_message]) .mount("/message/rx", routes![controller::rx_message])
.mount("/message/rx/multisig", routes![controller::rx_multisig_message])
.mount("/prove", routes![controller::gen_jwp]) .mount("/prove", routes![controller::gen_jwp])
.mount("/share", routes![controller::share_contact_info]) .mount("/share", routes![controller::share_contact_info])
.mount("/i2p", routes![controller::get_i2p_status]) .mount("/i2p", routes![controller::get_i2p_status])