mirror of
https://github.com/creating2morrow/neveko.git
synced 2024-12-22 11:39:22 +00:00
nevmes-market intial commit
This commit is contained in:
parent
69b399d25b
commit
21978de991
25 changed files with 3446 additions and 387 deletions
12
Cargo.lock
generated
12
Cargo.lock
generated
|
@ -1934,6 +1934,7 @@ dependencies = [
|
|||
"nevmes_contact",
|
||||
"nevmes_core",
|
||||
"nevmes_gui",
|
||||
"nevmes_market",
|
||||
"nevmes_message",
|
||||
"rocket",
|
||||
]
|
||||
|
@ -2007,6 +2008,17 @@ dependencies = [
|
|||
"wasm-bindgen-futures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nevmes_market"
|
||||
version = "0.5.0-alpha"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"env_logger",
|
||||
"log 0.4.17",
|
||||
"nevmes_core",
|
||||
"rocket",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nevmes_message"
|
||||
version = "0.5.0-alpha"
|
||||
|
|
|
@ -11,5 +11,6 @@ nevmes_auth = { path = "./nevmes-auth" }
|
|||
nevmes_contact = { path = "./nevmes-contact" }
|
||||
nevmes_core = { path = "./nevmes-core" }
|
||||
nevmes_gui = { path = "./nevmes-gui" }
|
||||
nevmes_market = { path = "./nevmes-market" }
|
||||
nevmes_message = { path = "./nevmes-message" }
|
||||
rocket = { version = "0.5.0-rc.2", features = ["json"] }
|
||||
|
|
|
@ -89,6 +89,9 @@ pub struct Args {
|
|||
/// Messaging sending port
|
||||
#[arg(long, help = "Set app message sending port", default_value = "9045")]
|
||||
pub message_port: u16,
|
||||
/// Marketplace admin port
|
||||
#[arg(long, help = "Set app marketplace admin port", default_value = "9046")]
|
||||
pub marketplace_port: u16,
|
||||
/// Auto trust contact gpg keys (DISABLED)
|
||||
#[arg(
|
||||
long,
|
||||
|
|
|
@ -175,7 +175,7 @@ impl Message {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct User {
|
||||
pub uid: String,
|
||||
|
@ -217,13 +217,13 @@ impl User {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct Product {
|
||||
pub pid: String,
|
||||
pub vid: String,
|
||||
pub in_stock: bool,
|
||||
pub description: String,
|
||||
pub image: Vec<u8>,
|
||||
pub in_stock: bool,
|
||||
pub name: String,
|
||||
pub price: i64,
|
||||
pub qty: i64,
|
||||
|
@ -233,8 +233,8 @@ impl Default for Product {
|
|||
fn default() -> Self {
|
||||
Product {
|
||||
pid: utils::empty_string(),
|
||||
vid: utils::empty_string(),
|
||||
description: utils::empty_string(),
|
||||
image: Vec::new(),
|
||||
in_stock: false,
|
||||
name: utils::empty_string(),
|
||||
price: 0,
|
||||
|
@ -245,16 +245,17 @@ impl Default for Product {
|
|||
|
||||
impl Product {
|
||||
pub fn to_db(p: &Product) -> String {
|
||||
let image: String = hex::encode(&p.image);
|
||||
format!(
|
||||
"{}:{}:{}:{}:{}:{}",
|
||||
p.vid, p.description, p.in_stock, p.name, p.price, p.qty
|
||||
p.description, image, p.in_stock, p.name, p.price, p.qty
|
||||
)
|
||||
}
|
||||
pub fn from_db(k: String, v: String) -> Product {
|
||||
let values = v.split(":");
|
||||
let mut v: Vec<String> = values.map(|s| String::from(s)).collect();
|
||||
let vid = v.remove(0);
|
||||
let description = v.remove(0);
|
||||
let image = hex::decode(v.remove(0)).unwrap_or(Vec::new());
|
||||
let in_stock = match v.remove(0).parse::<bool>() {
|
||||
Ok(b) => b,
|
||||
Err(_) => false,
|
||||
|
@ -270,8 +271,8 @@ impl Product {
|
|||
};
|
||||
Product {
|
||||
pid: k,
|
||||
vid,
|
||||
description,
|
||||
image,
|
||||
in_stock,
|
||||
name,
|
||||
price,
|
||||
|
@ -281,6 +282,7 @@ impl Product {
|
|||
pub fn update(
|
||||
p: Product,
|
||||
description: String,
|
||||
image: Vec<u8>,
|
||||
in_stock: bool,
|
||||
name: String,
|
||||
price: i64,
|
||||
|
@ -288,8 +290,8 @@ impl Product {
|
|||
) -> Product {
|
||||
Product {
|
||||
pid: p.pid,
|
||||
vid: p.vid,
|
||||
description,
|
||||
image,
|
||||
in_stock,
|
||||
name,
|
||||
price,
|
||||
|
@ -298,74 +300,200 @@ impl Product {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: add mediator fields
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct Order {
|
||||
pub orid: String,
|
||||
pub c_id: String,
|
||||
pub p_id: String,
|
||||
pub v_id: String,
|
||||
pub xmr_address: String,
|
||||
pub cust_msig_info: String,
|
||||
pub cust_msig_txset: String,
|
||||
/// Order customer id is their .b32.i2p address
|
||||
pub cid: String,
|
||||
pub pid: String,
|
||||
pub cust_kex_1: String,
|
||||
pub cust_kex_2: String,
|
||||
pub cust_kex_3: String,
|
||||
pub cust_msig_make: String,
|
||||
pub cust_msig_prepare: String,
|
||||
pub cust_msig_txset: String,
|
||||
pub date: i64,
|
||||
pub deliver_date: i64,
|
||||
pub ship_date: i64,
|
||||
pub hash: String,
|
||||
pub msig_prepare: String,
|
||||
pub msig_make: String,
|
||||
pub msig_kex_1: String,
|
||||
pub msig_kex_2: String,
|
||||
pub msig_kex_3: String,
|
||||
pub mediator_kex_1: String,
|
||||
pub mediator_kex_2: String,
|
||||
pub mediator_kex_3: String,
|
||||
pub mediator_msig_make: String,
|
||||
pub mediator_msig_prepare: String,
|
||||
pub ship_date: i64,
|
||||
/// This is the final destination for the payment
|
||||
pub subaddress: String,
|
||||
pub status: String,
|
||||
pub quantity: i64,
|
||||
pub vend_kex_1: String,
|
||||
pub vend_kex_2: String,
|
||||
pub vend_kex_3: String,
|
||||
pub vend_msig_info: String,
|
||||
pub vend_msig_make: String,
|
||||
pub vend_msig_prepare: String,
|
||||
pub vend_msig_txset: String,
|
||||
pub xmr_address: String,
|
||||
}
|
||||
|
||||
impl Default for Order {
|
||||
fn default() -> Self {
|
||||
Order {
|
||||
orid: utils::empty_string(),
|
||||
c_id: utils::empty_string(),
|
||||
p_id: utils::empty_string(),
|
||||
v_id: utils::empty_string(),
|
||||
cid: utils::empty_string(),
|
||||
pid: utils::empty_string(),
|
||||
xmr_address: utils::empty_string(),
|
||||
cust_msig_info: utils::empty_string(),
|
||||
cust_msig_txset: utils::empty_string(),
|
||||
cust_kex_1: utils::empty_string(),
|
||||
cust_kex_2: utils::empty_string(),
|
||||
cust_kex_3: utils::empty_string(),
|
||||
cust_msig_make: utils::empty_string(),
|
||||
cust_msig_prepare: utils::empty_string(),
|
||||
cust_msig_txset: utils::empty_string(),
|
||||
date: 0,
|
||||
deliver_date: 0,
|
||||
ship_date: 0,
|
||||
hash: utils::empty_string(),
|
||||
msig_prepare: utils::empty_string(),
|
||||
msig_make: utils::empty_string(),
|
||||
msig_kex_1: utils::empty_string(),
|
||||
msig_kex_2: utils::empty_string(),
|
||||
msig_kex_3: utils::empty_string(),
|
||||
mediator_kex_1: utils::empty_string(),
|
||||
mediator_kex_2: utils::empty_string(),
|
||||
mediator_kex_3: utils::empty_string(),
|
||||
mediator_msig_make: utils::empty_string(),
|
||||
mediator_msig_prepare: utils::empty_string(),
|
||||
subaddress: utils::empty_string(),
|
||||
status: utils::empty_string(),
|
||||
quantity: 0,
|
||||
vend_kex_1: utils::empty_string(),
|
||||
vend_kex_2: utils::empty_string(),
|
||||
vend_kex_3: utils::empty_string(),
|
||||
vend_msig_info: utils::empty_string(),
|
||||
vend_msig_make: utils::empty_string(),
|
||||
vend_msig_prepare: utils::empty_string(),
|
||||
vend_msig_txset: utils::empty_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
impl Order {
|
||||
pub fn to_db(o: &Order) -> String {
|
||||
format!(
|
||||
"{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}:{}",
|
||||
o.cid, o.pid, o.cust_kex_1, o.cust_kex_2, o.cust_kex_3, o.cust_msig_make,
|
||||
o.cust_msig_prepare, o.cust_msig_txset, o.date, o.deliver_date,
|
||||
o.hash, o.mediator_msig_make, o.mediator_msig_prepare, o.mediator_kex_1,
|
||||
o.mediator_kex_2, o.mediator_kex_3, o.ship_date, o.subaddress, o.status,
|
||||
o.quantity, o.vend_kex_1, o.vend_kex_2, o.vend_kex_3, o.vend_msig_make,
|
||||
o.vend_msig_prepare, o.vend_msig_txset, o.xmr_address,
|
||||
)
|
||||
}
|
||||
pub fn from_db(k: String, v: String) -> Order {
|
||||
let values = v.split(":");
|
||||
let mut v: Vec<String> = values.map(|s| String::from(s)).collect();
|
||||
let orid = k;
|
||||
let cid = v.remove(0);
|
||||
let pid = v.remove(0);
|
||||
let cust_kex_1 = v.remove(0);
|
||||
let cust_kex_2 = v.remove(0);
|
||||
let cust_kex_3 = v.remove(0);
|
||||
let cust_msig_make = v.remove(0);
|
||||
let cust_msig_prepare = v.remove(0);
|
||||
let cust_msig_txset = v.remove(0);
|
||||
let date = match v.remove(0).parse::<i64>() {
|
||||
Ok(d) => d,
|
||||
Err(_) => 0,
|
||||
};
|
||||
let deliver_date = match v.remove(0).parse::<i64>() {
|
||||
Ok(d) => d,
|
||||
Err(_) => 0,
|
||||
};
|
||||
let hash = v.remove(0);
|
||||
let mediator_msig_make = v.remove(0);
|
||||
let mediator_msig_prepare = v.remove(0);
|
||||
let mediator_kex_1 = v.remove(0);
|
||||
let mediator_kex_2 = v.remove(0);
|
||||
let mediator_kex_3 = v.remove(0);
|
||||
let ship_date = match v.remove(0).parse::<i64>() {
|
||||
Ok(d) => d,
|
||||
Err(_) => 0,
|
||||
};
|
||||
let subaddress = v.remove(0);
|
||||
let status = v.remove(0);
|
||||
let quantity = match v.remove(0).parse::<i64>() {
|
||||
Ok(d) => d,
|
||||
Err(_) => 0,
|
||||
};
|
||||
let vend_kex_1 = v.remove(0);
|
||||
let vend_kex_2 = v.remove(0);
|
||||
let vend_kex_3 = v.remove(0);
|
||||
let vend_msig_make = v.remove(0);
|
||||
let vend_msig_prepare = v.remove(0);
|
||||
let vend_msig_txset = v.remove(0);
|
||||
let xmr_address = v.remove(0);
|
||||
Order {
|
||||
orid,
|
||||
cid,
|
||||
pid,
|
||||
cust_kex_1,
|
||||
cust_kex_2,
|
||||
cust_kex_3,
|
||||
cust_msig_make,
|
||||
cust_msig_prepare,
|
||||
cust_msig_txset,
|
||||
date,
|
||||
deliver_date,
|
||||
hash,
|
||||
mediator_kex_1,
|
||||
mediator_kex_2,
|
||||
mediator_kex_3,
|
||||
mediator_msig_make,
|
||||
mediator_msig_prepare,
|
||||
ship_date,
|
||||
subaddress,
|
||||
status,
|
||||
quantity,
|
||||
vend_kex_1,
|
||||
vend_kex_2,
|
||||
vend_kex_3,
|
||||
vend_msig_make,
|
||||
vend_msig_prepare,
|
||||
vend_msig_txset,
|
||||
xmr_address,
|
||||
}
|
||||
}
|
||||
pub fn update(
|
||||
orid: String,
|
||||
o: Order,
|
||||
) -> Order {
|
||||
Order {
|
||||
orid,
|
||||
cid: String::from(&o.cid),
|
||||
pid: String::from(&o.pid),
|
||||
cust_kex_1: String::from(&o.cust_kex_1),
|
||||
cust_kex_2: String::from(&o.cust_kex_2),
|
||||
cust_kex_3: String::from(&o.cust_kex_3),
|
||||
cust_msig_make: String::from(&o.cust_msig_make),
|
||||
cust_msig_prepare: String::from(&o.cust_msig_make),
|
||||
cust_msig_txset: String::from(&o.cust_msig_txset),
|
||||
date: o.date,
|
||||
deliver_date: o.deliver_date,
|
||||
hash: String::from(&o.hash),
|
||||
mediator_kex_1: String::from(&o.mediator_kex_1),
|
||||
mediator_kex_2: String::from(&o.mediator_kex_2),
|
||||
mediator_kex_3: String::from(&o.mediator_kex_3),
|
||||
mediator_msig_make: String::from(&o.mediator_msig_make),
|
||||
mediator_msig_prepare: String::from(&o.mediator_msig_prepare),
|
||||
ship_date: o.ship_date,
|
||||
subaddress: String::from(&o.subaddress),
|
||||
status: String::from(&o.status),
|
||||
quantity: o.quantity,
|
||||
vend_kex_1: String::from(&o.vend_kex_1),
|
||||
vend_kex_2: String::from(&o.vend_kex_2),
|
||||
vend_kex_3: String::from(&o.vend_kex_3),
|
||||
vend_msig_make: String::from(&o.vend_msig_make),
|
||||
vend_msig_prepare: String::from(&o.vend_msig_prepare),
|
||||
vend_msig_txset: String::from(&o.vend_msig_txset),
|
||||
xmr_address: String::from(&o.xmr_address),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct Dispute {
|
||||
pub did: String,
|
||||
|
|
|
@ -598,39 +598,6 @@ pub async fn make_wallet(info: Vec<String>) -> reqres::XmrRpcMakeResponse {
|
|||
}
|
||||
}
|
||||
|
||||
/// Performs the xmr rpc 'finalize_multisig' method
|
||||
pub async fn finalize_wallet(info: Vec<String>) -> reqres::XmrRpcFinalizeResponse {
|
||||
info!("executing {}", RpcFields::Finalize.value());
|
||||
let client = reqwest::Client::new();
|
||||
let host = get_rpc_host();
|
||||
let params = reqres::XmrRpcFinalizeParams {
|
||||
multisig_info: info,
|
||||
};
|
||||
let req = reqres::XmrRpcFinalizeRequest {
|
||||
jsonrpc: RpcFields::JsonRpcVersion.value(),
|
||||
id: RpcFields::Id.value(),
|
||||
method: RpcFields::Finalize.value(),
|
||||
params,
|
||||
};
|
||||
let login: RpcLogin = get_rpc_creds();
|
||||
match client
|
||||
.post(host)
|
||||
.json(&req)
|
||||
.send_with_digest_auth(&login.username, &login.credential)
|
||||
.await
|
||||
{
|
||||
Ok(response) => {
|
||||
let res = response.json::<reqres::XmrRpcFinalizeResponse>().await;
|
||||
debug!("{} response: {:?}", RpcFields::Finalize.value(), res);
|
||||
match res {
|
||||
Ok(res) => res,
|
||||
_ => Default::default(),
|
||||
}
|
||||
}
|
||||
Err(_) => Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs the xmr rpc 'export_multisig_info' method
|
||||
pub async fn export_multisig_info() -> reqres::XmrRpcExportResponse {
|
||||
info!("executing {}", RpcFields::Export.value());
|
||||
|
@ -725,7 +692,7 @@ pub async fn sign_multisig(tx_data_hex: String) -> reqres::XmrRpcSignMultisigRes
|
|||
/// Performs the xmr rpc 'exchange_multisig_keys' method
|
||||
pub async fn exchange_multisig_keys(
|
||||
force_update_use_with_caution: bool,
|
||||
multisig_info: String,
|
||||
multisig_info: Vec<String>,
|
||||
password: String,
|
||||
) -> reqres::XmrRpcExchangeMultisigKeysResponse {
|
||||
info!("executing: {}", RpcFields::ExchangeMultisigKeys.value());
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{utils, models};
|
||||
use crate::utils;
|
||||
use serde::{
|
||||
Deserialize,
|
||||
Serialize,
|
||||
|
@ -62,7 +62,7 @@ pub struct XmrRpcSignMultisigParams {
|
|||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub struct XmrRpcExchangeMultisigKeysParams {
|
||||
pub force_update_use_with_caution: bool,
|
||||
pub multisig_info: String,
|
||||
pub multisig_info: Vec<String>,
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
|
@ -1080,307 +1080,3 @@ impl Default for ErrorResponse {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct GetCustomerResponse {
|
||||
pub address: String,
|
||||
pub cid: String,
|
||||
pub name: String,
|
||||
pub pgp: String,
|
||||
}
|
||||
|
||||
impl Default for GetCustomerResponse {
|
||||
fn default() -> Self {
|
||||
GetCustomerResponse {
|
||||
address: utils::empty_string(),
|
||||
cid: utils::empty_string(),
|
||||
name: utils::empty_string(),
|
||||
pgp: utils::empty_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct GetVendorResponse {
|
||||
pub vid: String,
|
||||
pub active: bool,
|
||||
pub address: String,
|
||||
pub description: String,
|
||||
pub name: String,
|
||||
pub pgp: String,
|
||||
}
|
||||
|
||||
impl Default for GetVendorResponse {
|
||||
fn default() -> Self {
|
||||
GetVendorResponse {
|
||||
vid: utils::empty_string(),
|
||||
active: false,
|
||||
address: utils::empty_string(),
|
||||
description: utils::empty_string(),
|
||||
name: utils::empty_string(),
|
||||
pgp: utils::empty_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct GetProductResponse {
|
||||
pub pid: String,
|
||||
pub in_stock: bool,
|
||||
pub description: String,
|
||||
pub name: String,
|
||||
pub price: i64,
|
||||
pub qty: i64,
|
||||
}
|
||||
|
||||
impl Default for GetProductResponse {
|
||||
fn default() -> Self {
|
||||
GetProductResponse {
|
||||
pid: utils::empty_string(),
|
||||
in_stock: false,
|
||||
description: utils::empty_string(),
|
||||
name: utils::empty_string(),
|
||||
price: 0,
|
||||
qty: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct GetVendorProductsResponse {
|
||||
pub products: Vec<GetProductResponse>,
|
||||
}
|
||||
|
||||
impl Default for GetVendorProductsResponse {
|
||||
fn default() -> Self {
|
||||
GetVendorProductsResponse {
|
||||
products: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct GetAuthResponse {
|
||||
pub address: String,
|
||||
pub aid: String,
|
||||
pub created: i64,
|
||||
pub cvid: String,
|
||||
pub data: String,
|
||||
pub token: String,
|
||||
}
|
||||
|
||||
impl Default for GetAuthResponse {
|
||||
fn default() -> Self {
|
||||
GetAuthResponse {
|
||||
address: utils::empty_string(),
|
||||
aid: utils::empty_string(),
|
||||
created: 0,
|
||||
cvid: utils::empty_string(),
|
||||
data: utils::empty_string(),
|
||||
token: utils::empty_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct GetDisputeResponse {
|
||||
pub orid: String,
|
||||
pub created: i64,
|
||||
pub tx_set: String,
|
||||
}
|
||||
|
||||
impl Default for GetDisputeResponse {
|
||||
fn default() -> Self {
|
||||
GetDisputeResponse {
|
||||
orid: utils::empty_string(),
|
||||
created: 0,
|
||||
tx_set: utils::empty_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct GetOrderResponse {
|
||||
pub orid: String,
|
||||
pub pid: String,
|
||||
pub xmr_address: String,
|
||||
pub cust_msig_info: String,
|
||||
pub cust_kex_1: String,
|
||||
pub cust_kex_2: String,
|
||||
pub cust_kex_3: String,
|
||||
pub date: i64,
|
||||
pub deliver_date: i64,
|
||||
pub ship_date: i64,
|
||||
pub hash: String,
|
||||
pub msig_prepare: String,
|
||||
pub msig_make: String,
|
||||
pub msig_kex_1: String,
|
||||
pub msig_kex_2: String,
|
||||
pub msig_kex_3: String,
|
||||
pub subaddress: String,
|
||||
pub status: String,
|
||||
pub quantity: i64,
|
||||
pub vend_kex_1: String,
|
||||
pub vend_kex_2: String,
|
||||
pub vend_kex_3: String,
|
||||
pub vend_msig_info: String,
|
||||
}
|
||||
|
||||
impl Default for GetOrderResponse {
|
||||
fn default() -> Self {
|
||||
GetOrderResponse {
|
||||
orid: utils::empty_string(),
|
||||
pid: utils::empty_string(),
|
||||
xmr_address: utils::empty_string(),
|
||||
cust_msig_info: utils::empty_string(),
|
||||
cust_kex_1: utils::empty_string(),
|
||||
cust_kex_2: utils::empty_string(),
|
||||
cust_kex_3: utils::empty_string(),
|
||||
date: 0,
|
||||
deliver_date: 0,
|
||||
ship_date: 0,
|
||||
hash: utils::empty_string(),
|
||||
msig_prepare: utils::empty_string(),
|
||||
msig_make: utils::empty_string(),
|
||||
msig_kex_1: utils::empty_string(),
|
||||
msig_kex_2: utils::empty_string(),
|
||||
msig_kex_3: utils::empty_string(),
|
||||
subaddress: utils::empty_string(),
|
||||
status: utils::empty_string(),
|
||||
quantity: 0,
|
||||
vend_kex_1: utils::empty_string(),
|
||||
vend_kex_2: utils::empty_string(),
|
||||
vend_kex_3: utils::empty_string(),
|
||||
vend_msig_info: utils::empty_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct GetOrdersResponse {
|
||||
pub orders: Vec<GetOrderResponse>,
|
||||
}
|
||||
|
||||
impl Default for GetOrdersResponse {
|
||||
fn default() -> Self {
|
||||
GetOrdersResponse {
|
||||
orders: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// START response builders
|
||||
impl GetDisputeResponse {
|
||||
pub fn build(m_dispute: models::Dispute) -> Self {
|
||||
GetDisputeResponse {
|
||||
orid: m_dispute.orid,
|
||||
created: m_dispute.created,
|
||||
tx_set: m_dispute.tx_set,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetProductResponse {
|
||||
pub fn build(m_product: models::Product) -> Self {
|
||||
GetProductResponse {
|
||||
pid: m_product.pid,
|
||||
in_stock: m_product.in_stock,
|
||||
description: m_product.description,
|
||||
name: m_product.name,
|
||||
price: m_product.price,
|
||||
qty: m_product.qty,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetVendorProductsResponse {
|
||||
pub fn build(m_products: Vec<models::Product>) -> Self {
|
||||
let mut v_res: Vec<GetProductResponse> = Vec::new();
|
||||
for m in m_products {
|
||||
let p_res: GetProductResponse = GetProductResponse {
|
||||
pid: m.pid,
|
||||
in_stock: m.in_stock,
|
||||
description: m.description,
|
||||
name: m.name,
|
||||
price: m.price,
|
||||
qty: m.qty,
|
||||
};
|
||||
v_res.push(p_res);
|
||||
}
|
||||
GetVendorProductsResponse { products: v_res }
|
||||
}
|
||||
}
|
||||
|
||||
impl GetOrderResponse {
|
||||
pub fn build(pid: String, m_order: models::Order) -> Self {
|
||||
GetOrderResponse {
|
||||
orid: m_order.orid,
|
||||
pid,
|
||||
xmr_address: m_order.xmr_address,
|
||||
cust_msig_info: m_order.cust_msig_info,
|
||||
cust_kex_1: m_order.cust_kex_1,
|
||||
cust_kex_2: m_order.cust_kex_2,
|
||||
cust_kex_3: m_order.cust_kex_3,
|
||||
date: m_order.date,
|
||||
deliver_date: m_order.deliver_date,
|
||||
ship_date: m_order.ship_date,
|
||||
hash: m_order.hash,
|
||||
msig_prepare: m_order.msig_prepare,
|
||||
msig_make: m_order.msig_make,
|
||||
msig_kex_1: m_order.msig_kex_1,
|
||||
msig_kex_2: m_order.msig_kex_2,
|
||||
msig_kex_3: m_order.msig_kex_3,
|
||||
subaddress: m_order.subaddress,
|
||||
status: m_order.status,
|
||||
quantity: m_order.quantity,
|
||||
vend_kex_1: m_order.vend_kex_1,
|
||||
vend_kex_2: m_order.vend_kex_2,
|
||||
vend_kex_3: m_order.vend_kex_3,
|
||||
vend_msig_info: m_order.vend_msig_info,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetOrdersResponse {
|
||||
pub fn build(m_orders: Vec<models::Order>) -> Self {
|
||||
let mut v_res: Vec<GetOrderResponse> = Vec::new();
|
||||
for m in m_orders {
|
||||
let o_res: GetOrderResponse = GetOrderResponse {
|
||||
orid: m.orid,
|
||||
pid: m.p_id,
|
||||
xmr_address: m.xmr_address,
|
||||
cust_msig_info: m.cust_msig_info,
|
||||
cust_kex_1: m.cust_kex_1,
|
||||
cust_kex_2: m.cust_kex_2,
|
||||
cust_kex_3: m.cust_kex_3,
|
||||
date: m.date,
|
||||
deliver_date: m.deliver_date,
|
||||
ship_date: m.ship_date,
|
||||
hash: m.hash,
|
||||
msig_prepare: m.msig_prepare,
|
||||
msig_make: m.msig_make,
|
||||
msig_kex_1: m.msig_kex_1,
|
||||
msig_kex_2: m.msig_kex_2,
|
||||
msig_kex_3: m.msig_kex_3,
|
||||
subaddress: m.subaddress,
|
||||
status: m.status,
|
||||
quantity: m.quantity,
|
||||
vend_kex_1: m.vend_kex_1,
|
||||
vend_kex_2: m.vend_kex_2,
|
||||
vend_kex_3: m.vend_kex_3,
|
||||
vend_msig_info: m.vend_msig_info,
|
||||
};
|
||||
v_res.push(o_res);
|
||||
}
|
||||
GetOrdersResponse { orders: v_res }
|
||||
}
|
||||
}
|
||||
// END response builders
|
||||
|
|
|
@ -179,6 +179,12 @@ pub fn get_app_contact_port() -> u16 {
|
|||
args.contact_port
|
||||
}
|
||||
|
||||
/// app message port
|
||||
pub fn get_app_market_port() -> u16 {
|
||||
let args = args::Args::parse();
|
||||
args.marketplace_port
|
||||
}
|
||||
|
||||
/// app message port
|
||||
pub fn get_app_message_port() -> u16 {
|
||||
let args = args::Args::parse();
|
||||
|
@ -355,6 +361,15 @@ fn start_micro_servers() {
|
|||
.spawn()
|
||||
.expect("failed to start contact server");
|
||||
debug!("{:?}", c_output.stdout);
|
||||
info!("starting marketplace admin server");
|
||||
let mut market_path = "nevmes-contact/target/debug/nevmes_market";
|
||||
if env == ReleaseEnvironment::Production {
|
||||
market_path = "nevmes_market";
|
||||
}
|
||||
let market_output = std::process::Command::new(market_path)
|
||||
.spawn()
|
||||
.expect("failed to start marketplace server");
|
||||
debug!("{:?}", market_output.stdout);
|
||||
info!("starting message server");
|
||||
let mut message_path = "nevmes-message/target/debug/nevmes_message";
|
||||
if env == ReleaseEnvironment::Production {
|
||||
|
|
7
nevmes-market/.gitignore
vendored
Executable file
7
nevmes-market/.gitignore
vendored
Executable file
|
@ -0,0 +1,7 @@
|
|||
/target
|
||||
/core
|
||||
/test-lmdb
|
||||
/wallet
|
||||
monero-wallet-rpc.log
|
||||
notes.txt
|
||||
.env
|
2660
nevmes-market/Cargo.lock
generated
Executable file
2660
nevmes-market/Cargo.lock
generated
Executable file
File diff suppressed because it is too large
Load diff
12
nevmes-market/Cargo.toml
Executable file
12
nevmes-market/Cargo.toml
Executable file
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "nevmes_market"
|
||||
version = "0.5.0-alpha"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
chrono = "0.4.23"
|
||||
env_logger = "0.10.0"
|
||||
nevmes_core = { path = "../nevmes-core" }
|
||||
log = "0.4"
|
||||
rocket = { version = "0.5.0-rc.2", features = ["json"] }
|
21
nevmes-market/LICENSE
Normal file
21
nevmes-market/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2023 creating2morrow
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
64
nevmes-market/README.md
Executable file
64
nevmes-market/README.md
Executable file
|
@ -0,0 +1,64 @@
|
|||
# nevmes-market
|
||||
|
||||
## High-Level Order Lifecycle
|
||||
|
||||
* vendor adds a new product with description and price
|
||||
* customer orders product
|
||||
* vendor creates order, multisig wallet and prepares it
|
||||
|
||||
| | prepare | make | exchange |
|
||||
|-- |-- |-- |-- |
|
||||
|vend | X | | |
|
||||
|cust | | | |
|
||||
|med | | | |
|
||||
|
||||
* customer saves prepare info from vendor, creates multisig wallet
|
||||
|
||||
| | prepare | make | exchange |
|
||||
|-- |-- |-- |-- |
|
||||
|vend | X | | |
|
||||
|cust | X | | |
|
||||
|med | | | |
|
||||
|
||||
* customer sends both prepare infos to mediator
|
||||
* mediator creates multisig wallet, prepares and makes it
|
||||
|
||||
| | prepare | make | exchange |
|
||||
|-- |-- |-- |-- |
|
||||
|vend | X | | |
|
||||
|cust | X | | |
|
||||
|med | X | X | |
|
||||
|
||||
* customer makes multisig wallet and sends both outputs to vendor
|
||||
|
||||
| | prepare | make | exchange |
|
||||
|-- |-- |-- |-- |
|
||||
|vend | X | | |
|
||||
|cust | X | X | |
|
||||
|med | X | X | |
|
||||
|
||||
* vendor makes and calls to exchange multisig keys
|
||||
|
||||
| | prepare | make | exchange |
|
||||
|-- |-- |-- |-- |
|
||||
|vend | X | X | X |
|
||||
|cust | X | X | |
|
||||
|med | X | X | |
|
||||
|
||||
* customer sends output to mediator who then exchanges multisig keys
|
||||
|
||||
| | prepare | make | exchange |
|
||||
|-- |-- |-- |-- |
|
||||
|vend | X | X | X |
|
||||
|cust | X | X | X |
|
||||
|med | X | X | X |
|
||||
|
||||
* customer funds wallet and exports to vendor and mediator
|
||||
* vendor and mediator import multisig info
|
||||
* customer signs multisig txset and sends to mediator
|
||||
* mediator requests tracking number from vendor
|
||||
* mediator relase signed txset to vendor
|
||||
* vendor signs and submits signed txset
|
||||
* in case of dispute the mediator can sign multisig txset for customer refund
|
||||
|
||||
Reference: https://resilience365.com/monero-multisig-how-to/
|
75
nevmes-market/curl.md
Normal file
75
nevmes-market/curl.md
Normal file
|
@ -0,0 +1,75 @@
|
|||
# CURL / API docs
|
||||
|
||||
```bash
|
||||
# [GET] get the current monero-wallet-rpc version
|
||||
curl http://127.0.0.1:8000/xmr/version
|
||||
|
||||
# [POST] sign data (monero-wallet-rpc)
|
||||
curl http://127.0.0.1:38083/json_rpc --digest -u user:pass -d '{"jsonrpc":"2.0","id":"0","method":"sign","params":{"data":"some data here"}}' -H 'Content-Type: application/json'
|
||||
|
||||
# [POST] get addresses (monero-wallet-rpc)
|
||||
curl http://127.0.0.1:38083/json_rpc --digest -u user:pass -d '{"jsonrpc":"2.0","id":"0","method":"get_address","params":{"account_index":0,"address_index":[0]}}' -H 'Content-Type: application/json'
|
||||
|
||||
# [GET] login
|
||||
# customer or vendor
|
||||
# xmr address
|
||||
# aid - auth id
|
||||
# cvid - customer or vendor id (2nd api call finalizes login and creates it)
|
||||
# data - random bytes to sign
|
||||
# signature - generate signature with wallet private keys
|
||||
curl http://127.0.0.1:8000/login/<customer|vendor>/<XMR_ADDRESS>/<SIGNATURE>/<AID>/CID
|
||||
|
||||
# [GET] information
|
||||
# customer or vendor
|
||||
# xmr address
|
||||
# customer or vendor id
|
||||
curl http://127.0.0.1:8000/<customer|vendor>/<XMR_ADDRESS>/<ID> -H 'token: <JWT>'
|
||||
|
||||
# [PATCH] update
|
||||
# customer or vendor URI
|
||||
# <id> - i32
|
||||
# <data> - String
|
||||
# <update_type> - Enum => 0 - active, 1 - description, 2 - name, 3 - pgp
|
||||
curl -iv -X PATCH http://127.0.0.1:8000/<customer|vendor>/<XMR_ADDRESS>/update -d '{"cid": "CID", "name": "<name>", "pgp": "<pgp>", "xmr_address": "" }'
|
||||
|
||||
# [GET]
|
||||
# create a new product
|
||||
curl -iv http://127.0.0.1:8000/product/<XMR_ADDRESS>/create -H 'token: <JWT>'
|
||||
|
||||
# [GET]
|
||||
# return all products for a vendor
|
||||
curl -iv http://127.0.0.1:8000/products/<XMR_ADDRESS> -H 'token: <JWT>'
|
||||
|
||||
# [PATCH] update product
|
||||
# <pid> - i32
|
||||
# <data> - String
|
||||
# <update_type> - Enum => 0 - in_stock, 1 - description, 2 - name, 3 - price 4 - qty
|
||||
curl -X PATCH http://127.0.0.1:8000/product/<XMR_ADDRESS>/update/<pid>/<data>/<update_type> -H 'token: <JWT>'
|
||||
|
||||
# [GET]
|
||||
# intialize an order for a customer
|
||||
curl -iv http://127.0.0.1:8000/order/<XMR_ADDRESS>/create/<pid> -H 'token: <JWT>'
|
||||
|
||||
# [GET]
|
||||
# get all orders
|
||||
# xmr address
|
||||
# customer | vendor
|
||||
curl -iv http://127.0.0.1:8000/orders/<XMR_ADDRESS>/<customer | vendor> -H 'token: <JWT>'
|
||||
|
||||
# [PATCH]
|
||||
# modify order
|
||||
# UpdateType::CustomerKex1 => 0, // make output from customer
|
||||
# UpdateType::CustomerKex2 => 1, // use this for funding kex
|
||||
# UpdateType::CustomerKex3 => 2, // might need this later?
|
||||
# UpdateType::CustomerMultisigInfo => 3, // prepare output from customer
|
||||
# UpdateType::Deliver => 4, // customer has received the item, released txset
|
||||
# UpdateType::Hash => 5, // tx hash from funding the wallet order
|
||||
# UpdateType::Ship => 6, // update ship date, app doesn't store tracking numbers
|
||||
# UpdateType::Subaddress => 7, // update address for payout
|
||||
# UpdateType::VendorKex1 => 8, // make output from vendor
|
||||
# UpdateType::VendorKex2 => 9, // use this for funding kex
|
||||
# UpdateType::VendorKex3 => 10, // might need this later?
|
||||
# UpdateType::VendorMultisigInfo => 11, // prepare output from vendor
|
||||
# UpdateType::Quantity => 12, // this can be updated until wallet is funded
|
||||
curl -X PATCH http://127.0.0.1:8000/order/<XMR_ADDRESS>/update/<pid>/<oid>/<data>/<update_type> -H 'token: <JWT>'
|
||||
```
|
110
nevmes-market/src/controller.rs
Normal file
110
nevmes-market/src/controller.rs
Normal file
|
@ -0,0 +1,110 @@
|
|||
use rocket::http::Status;
|
||||
use rocket::response::status::Custom;
|
||||
use rocket::serde::json::Json;
|
||||
use rocket::{get, patch, post};
|
||||
|
||||
use nevmes_core::*;
|
||||
|
||||
use crate::{dispute, product};
|
||||
|
||||
// JSON APIs
|
||||
|
||||
/// Create a product by passing vendor vid
|
||||
#[post("/create", data = "<req_product>")]
|
||||
pub async fn create_product(
|
||||
req_product: Json<models::Product>,
|
||||
_token: auth::BearerToken,
|
||||
) -> Custom<Json<models::Product>> {
|
||||
let m_product: models::Product = product::create(req_product);
|
||||
Custom(
|
||||
Status::Ok,
|
||||
Json(m_product),
|
||||
)
|
||||
}
|
||||
|
||||
/// Update product information
|
||||
#[patch("/<_address>/update", data="<product>")]
|
||||
pub async fn update_product(
|
||||
_address: String,
|
||||
product: Json<models::Product>,
|
||||
_token: auth::BearerToken,
|
||||
) -> Custom<Json<models::Product>> {
|
||||
let m_product: models::Product = product::modify(product);
|
||||
Custom(
|
||||
Status::Ok,
|
||||
Json(m_product),
|
||||
)
|
||||
}
|
||||
|
||||
// /// Initialize order
|
||||
// #[get("/<address>/create/<pid>")]
|
||||
// pub async fn initialize_order(
|
||||
// address: String,
|
||||
// _token: auth::BearerToken,
|
||||
// pid: String,
|
||||
// ) -> Custom<Json<reqres::GetOrderResponse>> {
|
||||
// // get the cid from the address after verification
|
||||
// let m_customer = customer::find(address).await;
|
||||
// let temp_pid = String::from(&pid);
|
||||
// let m_order: models::Order = order::create(m_customer.cid, temp_pid).await;
|
||||
// Custom(
|
||||
// Status::Ok,
|
||||
// Json(reqres::GetOrderResponse::build(pid, m_order)),
|
||||
// )
|
||||
// }
|
||||
|
||||
// /// Update order information from vendor
|
||||
// #[patch("/update/<pid>/<oid>/<data>/vendor")]
|
||||
// pub async fn update_order(
|
||||
// _address: String,
|
||||
// oid: String,
|
||||
// pid: String,
|
||||
// _token: auth::BearerToken,
|
||||
// data: String,
|
||||
// ) -> Custom<Json<reqres::GetOrderResponse>> {
|
||||
// let temp_pid: String = String::from(&pid);
|
||||
// let m_order: models::Order = order::modify(oid, pid, data, update_type).await;
|
||||
// Custom(
|
||||
// Status::Ok,
|
||||
// Json(reqres::GetOrderResponse::build(temp_pid, m_order)),
|
||||
// )
|
||||
// }
|
||||
|
||||
// /// Get all orders
|
||||
// /// by passing auth
|
||||
// #[get("/<address>/<corv>")]
|
||||
// pub async fn get_orders(
|
||||
// address: String,
|
||||
// corv: String,
|
||||
// _token: auth::BearerToken,
|
||||
// ) -> Custom<Json<reqres::GetOrdersResponse>> {
|
||||
// let m_orders: Vec<models::Order> = order::find_all(address, corv).await;
|
||||
// Custom(Status::Ok, Json(reqres::GetOrdersResponse::build(m_orders)))
|
||||
// }
|
||||
|
||||
/// Create a dispute
|
||||
#[post("/create", data = "<dispute>")]
|
||||
pub async fn create_dispute(
|
||||
dispute: Json<models::Dispute>,
|
||||
_token: auth::BearerToken,
|
||||
) -> Custom<Json<models::Dispute>> {
|
||||
let m_dispute: models::Dispute = dispute::create(dispute);
|
||||
Custom(
|
||||
Status::Ok,
|
||||
Json(m_dispute),
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a dispute
|
||||
#[get("/<did>")]
|
||||
pub async fn get_dispute(
|
||||
_token: auth::BearerToken,
|
||||
did: String,
|
||||
) -> Custom<Json<models::Dispute>> {
|
||||
let m_dispute: models::Dispute = dispute::find(&did);
|
||||
Custom(
|
||||
Status::Ok,
|
||||
Json(m_dispute),
|
||||
)
|
||||
}
|
||||
// END JSON APIs
|
31
nevmes-market/src/dispute.rs
Normal file
31
nevmes-market/src/dispute.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
use nevmes_core::{db, models::*, utils};
|
||||
use rocket::serde::json::Json;
|
||||
use log::{debug, error, info};
|
||||
|
||||
/// Create a new dispute
|
||||
pub fn create(d: Json<Dispute>) -> Dispute {
|
||||
let f_did: String = format!("dispute{}", utils::generate_rnd());
|
||||
info!("create dispute: {}", &f_did);
|
||||
let new_dispute = Dispute {
|
||||
did: String::from(&f_did),
|
||||
created: chrono::offset::Utc::now().timestamp(),
|
||||
orid: String::from(&d.orid),
|
||||
tx_set: String::from(&d.tx_set),
|
||||
};
|
||||
debug!("insert dispute: {:?}", &d);
|
||||
let s = db::Interface::open();
|
||||
let k = &d.did;
|
||||
db::Interface::write(&s.env, &s.handle, k, &Dispute::to_db(&new_dispute));
|
||||
new_dispute
|
||||
}
|
||||
|
||||
/// Dispute lookup
|
||||
pub fn find(did: &String) -> Dispute {
|
||||
let s = db::Interface::open();
|
||||
let r = db::Interface::read(&s.env, &s.handle, &String::from(did));
|
||||
if r == utils::empty_string() {
|
||||
error!("dispute not found");
|
||||
return Default::default()
|
||||
}
|
||||
Dispute::from_db(String::from(did), r)
|
||||
}
|
6
nevmes-market/src/lib.rs
Executable file
6
nevmes-market/src/lib.rs
Executable file
|
@ -0,0 +1,6 @@
|
|||
pub mod controller; // HTTP entry point
|
||||
pub mod dispute; // Dispute repo/service layer
|
||||
pub mod order; // Order repo/service layer
|
||||
pub mod product; // Product repo/service layer
|
||||
|
||||
// DO NOT EDIT BELOW THIS LINE
|
22
nevmes-market/src/main.rs
Executable file
22
nevmes-market/src/main.rs
Executable file
|
@ -0,0 +1,22 @@
|
|||
#[macro_use]
|
||||
extern crate rocket;
|
||||
|
||||
use nevmes_core::*;
|
||||
use nevmes_market::*;
|
||||
|
||||
// The only changes in here should be mounting new controller methods
|
||||
|
||||
#[launch]
|
||||
async fn rocket() -> _ {
|
||||
let config = rocket::Config {
|
||||
port: utils::get_app_market_port(),
|
||||
..rocket::Config::debug_default()
|
||||
};
|
||||
env_logger::init();
|
||||
log::info!("nevmes-auth is online");
|
||||
rocket::custom(&config)
|
||||
.mount("/dispute", routes![controller::create_dispute, controller::get_dispute])
|
||||
// .mount("/order", routes![controller::initialize_order, controller::update_order])
|
||||
// .mount("/orders", routes![controller::get_orders])
|
||||
.mount("/product", routes![controller::create_product, controller::update_product])
|
||||
}
|
111
nevmes-market/src/order.rs
Normal file
111
nevmes-market/src/order.rs
Normal file
|
@ -0,0 +1,111 @@
|
|||
// use nevmes_core::*;
|
||||
// use log::{debug, error, info};
|
||||
// use rocket::serde::json::Json;
|
||||
// use crate::product;
|
||||
|
||||
// enum StatusType {
|
||||
// Delivered,
|
||||
// MultisigMissing,
|
||||
// MulitsigComplete,
|
||||
// Shipped,
|
||||
// }
|
||||
|
||||
// impl StatusType {
|
||||
// pub fn value(&self) -> String {
|
||||
// match *self {
|
||||
// StatusType::Delivered => String::from("Delivered"),
|
||||
// StatusType::MultisigMissing => String::from("MultisigMissing"),
|
||||
// StatusType::MulitsigComplete => String::from("MulitsigComplete"),
|
||||
// StatusType::Shipped => String::from("Shipped"),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// /// Create a skeleton for order
|
||||
// pub fn create(cid: String, pid: String) -> models::Order {
|
||||
// let ts = chrono::offset::Utc::now().timestamp();
|
||||
// let orid: String = format!("O{}", utils::generate_rnd());
|
||||
// let m_product: models::Product = product::find(&pid);
|
||||
// let new_order = models::Order {
|
||||
// orid,
|
||||
// cid: String::from(&cid),
|
||||
// pid: String::from(&pid),
|
||||
// cust_kex_1: utils::empty_string(),
|
||||
// cust_kex_2: utils::empty_string(),
|
||||
// cust_kex_3: utils::empty_string(),
|
||||
// cust_msig_make: utils::empty_string(),
|
||||
// cust_msig_prepare: utils::empty_string(),
|
||||
// cust_msig_txset: utils::empty_string(),
|
||||
// date: 0,
|
||||
// deliver_date: 0,
|
||||
// hash: utils::empty_string(),
|
||||
// mediator_kex_1: utils::empty_string(),
|
||||
// mediator_kex_2: utils::empty_string(),
|
||||
// mediator_kex_3: utils::empty_string(),
|
||||
// mediator_msig_make: utils::empty_string(),
|
||||
// mediator_msig_prepare: utils::empty_string(),
|
||||
// ship_date: 0,
|
||||
// subaddress: utils::empty_string(),
|
||||
// status: utils::empty_string(),
|
||||
// quantity: 0,
|
||||
// vend_kex_1: utils::empty_string(),
|
||||
// vend_kex_2: utils::empty_string(),
|
||||
// vend_kex_3: utils::empty_string(),
|
||||
// vend_msig_make: utils::empty_string(),
|
||||
// vend_msig_prepare: utils::empty_string(),
|
||||
// vend_msig_txset: utils::empty_string(),
|
||||
// xmr_address: utils::empty_string(),
|
||||
// };
|
||||
// debug!("insert order: {:?}", new_order);
|
||||
// let m_wallet = monero::create_wallet(String::from(&orid), &utils::empty_string()).await;
|
||||
// if !m_wallet {
|
||||
// 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
|
||||
// pub fn find(oid: String) -> models::Order {
|
||||
// let s = db::Interface::open();
|
||||
// let r = db::Interface::read(&s.env, &s.handle, &String::from(&oid));
|
||||
// if r == utils::empty_string() {
|
||||
// error!("order not found");
|
||||
// return Default::default();
|
||||
// }
|
||||
// models::Order::from_db(String::from(&oid), r)
|
||||
// }
|
||||
|
||||
// /// Lookup all orders for customer
|
||||
// pub async fn find_all_customer_orders(cid: String) -> Vec<models::Order> {
|
||||
// let i_s = db::Interface::open();
|
||||
// let i_list_key = format!("ol");
|
||||
// let i_r = db::Interface::read(&i_s.env, &i_s.handle, &String::from(i_list_key));
|
||||
// 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 mut orders: Vec<models::Order> = Vec::new();
|
||||
// for o in i_v {
|
||||
// let order: models::Order = find(o);
|
||||
// if order.orid != utils::empty_string() && order.cid == cid {
|
||||
// orders.push(order);
|
||||
// }
|
||||
// }
|
||||
// orders
|
||||
// }
|
86
nevmes-market/src/product.rs
Normal file
86
nevmes-market/src/product.rs
Normal file
|
@ -0,0 +1,86 @@
|
|||
// Product repo/service layer
|
||||
use nevmes_core::{db, models::*, utils};
|
||||
use log::{debug, error, info};
|
||||
use rocket::serde::json::Json;
|
||||
|
||||
/// Create a new product
|
||||
pub fn create(d: Json<Product>) -> Product {
|
||||
let pid: String = format!("product{}", utils::generate_rnd());
|
||||
let new_product = Product {
|
||||
pid: String::from(&pid),
|
||||
description: String::from(&d.description),
|
||||
image: d.image.iter().cloned().collect(),
|
||||
in_stock: d.in_stock,
|
||||
name: String::from(&d.name),
|
||||
price: d.price,
|
||||
qty: d.qty,
|
||||
};
|
||||
debug!("insert product: {:?}", &new_product);
|
||||
let s = db::Interface::open();
|
||||
let k = &new_product.pid;
|
||||
db::Interface::write(&s.env, &s.handle, k, &Product::to_db(&new_product));
|
||||
// in order to retrieve all products, write keys to with pl
|
||||
let list_key = format!("pl");
|
||||
let r = db::Interface::read(&s.env, &s.handle, &String::from(&list_key));
|
||||
if r == utils::empty_string() {
|
||||
debug!("creating product index");
|
||||
}
|
||||
let product_list = [r, String::from(&pid)].join(",");
|
||||
debug!("writing product index {} for id: {}", product_list, list_key);
|
||||
db::Interface::write(&s.env, &s.handle, &String::from(list_key), &product_list);
|
||||
new_product
|
||||
}
|
||||
|
||||
/// Single Product lookup
|
||||
pub fn find(pid: &String) -> Product {
|
||||
let s = db::Interface::open();
|
||||
let r = db::Interface::read(&s.env, &s.handle, &String::from(pid));
|
||||
if r == utils::empty_string() {
|
||||
error!("product not found");
|
||||
return Default::default();
|
||||
}
|
||||
Product::from_db(String::from(pid), r)
|
||||
}
|
||||
|
||||
/// Product lookup for all
|
||||
pub fn find_all() -> Vec<Product> {
|
||||
let i_s = db::Interface::open();
|
||||
let i_list_key = format!("pl");
|
||||
let i_r = db::Interface::read(&i_s.env, &i_s.handle, &String::from(i_list_key));
|
||||
if i_r == utils::empty_string() {
|
||||
error!("product index not found");
|
||||
}
|
||||
let i_v_pid = i_r.split(",");
|
||||
let i_v: Vec<String> = i_v_pid.map(|s| String::from(s)).collect();
|
||||
let mut products: Vec<Product> = Vec::new();
|
||||
for p in i_v {
|
||||
let product: Product = find(&p);
|
||||
if product.pid != utils::empty_string() {
|
||||
products.push(product);
|
||||
}
|
||||
}
|
||||
products
|
||||
}
|
||||
|
||||
/// Modify product
|
||||
pub fn modify(p: Json<Product>) -> Product {
|
||||
info!("modify product: {}", &p.pid);
|
||||
let f_prod: Product = find(&p.pid);
|
||||
if f_prod.pid == utils::empty_string() {
|
||||
error!("product not found");
|
||||
return Default::default();
|
||||
}
|
||||
let u_prod = Product::update(
|
||||
f_prod,
|
||||
String::from(&p.description),
|
||||
p.image.iter().cloned().collect(),
|
||||
p.in_stock,
|
||||
String::from(&p.description),
|
||||
p.price,
|
||||
p.qty,
|
||||
);
|
||||
let s = db::Interface::open();
|
||||
db::Interface::delete(&s.env, &s.handle, &u_prod.pid);
|
||||
db::Interface::write(&s.env, &s.handle, &u_prod.pid, &Product::to_db(&u_prod));
|
||||
return u_prod;
|
||||
}
|
|
@ -3,5 +3,6 @@ cd nevmes-auth && cargo build
|
|||
cd ../nevmes-contact && cargo build
|
||||
cd ../nevmes-core && cargo build
|
||||
cd ../nevmes-gui && cargo build
|
||||
cd ../nevmes-market && cargo build
|
||||
cd ../nevmes-message && cargo build
|
||||
cd ../ && RUST_LOG=debug cargo run $1
|
||||
|
|
|
@ -19,6 +19,8 @@ cd nevmes-auth && cargo build --release && cp target/release/nevmes_auth ../$LIN
|
|||
cd ../
|
||||
cd nevmes-contact && cargo build --release && cp target/release/nevmes_contact ../$LINUX_OUTPUT_DIR
|
||||
cd ../
|
||||
cd nevmes-market && cargo build --release && cp target/release/nevmes_market ../$LINUX_OUTPUT_DIR
|
||||
cd ../
|
||||
cd nevmes-message && cargo build --release && cp target/release/nevmes_message ../$LINUX_OUTPUT_DIR
|
||||
cd ../
|
||||
# make the bzip for linux
|
||||
|
|
|
@ -4,6 +4,7 @@ cd nevmes-auth && cargo clean
|
|||
cd ../nevmes-contact && cargo clean
|
||||
cd ../nevmes-core && cargo clean
|
||||
cd ../nevmes-gui && cargo clean
|
||||
cd ../nevmes-market && cargo clean
|
||||
cd ../nevmes-message && cargo clean
|
||||
cd ../ && cargo clean
|
||||
rm -rf .build/
|
||||
|
|
|
@ -4,5 +4,6 @@ cd nevmes-auth && cargo +nightly fmt
|
|||
cd ../nevmes-contact && cargo +nightly fmt
|
||||
cd ../nevmes-core && cargo +nightly fmt
|
||||
cd ../nevmes-gui && cargo +nightly fmt
|
||||
cd ../nevmes-market && cargo +nightly fmt
|
||||
cd ../nevmes-message && cargo +nightly fmt
|
||||
cd ../ && cargo +nightly fmt
|
||||
|
|
|
@ -6,21 +6,14 @@ use rocket::{
|
|||
serde::json::Json,
|
||||
};
|
||||
|
||||
use nevmes_core::{
|
||||
contact,
|
||||
i2p,
|
||||
message,
|
||||
models,
|
||||
monero,
|
||||
proof,
|
||||
reqres,
|
||||
};
|
||||
use nevmes_core::*;
|
||||
use nevmes_market::*;
|
||||
|
||||
// JSON APIs exposed over i2p
|
||||
|
||||
/// Get payment API version
|
||||
///
|
||||
/// Protected: false
|
||||
/// Protected: true
|
||||
///
|
||||
/// This also functions as a health check
|
||||
#[get("/version")]
|
||||
|
@ -28,6 +21,21 @@ pub async fn get_version(_jwp: proof::PaymentProof) -> Custom<Json<reqres::XmrRp
|
|||
Custom(Status::Ok, Json(monero::get_version().await))
|
||||
}
|
||||
|
||||
#[get("/test")]
|
||||
pub async fn test() -> Custom<Json<models::User>> {
|
||||
let mut v: Vec<String> = Vec::new();
|
||||
v.push("t1".to_string());
|
||||
v.push("t2".to_string());
|
||||
v.push("t3".to_string());
|
||||
let u: models::User = models::User {
|
||||
uid: v.remove(0),
|
||||
xmr_address: v.remove(0),
|
||||
name: v.remove(0),
|
||||
};
|
||||
Custom(Status::Ok, Json(u))
|
||||
}
|
||||
|
||||
|
||||
/// If i2p not in the state of rejecting tunnels this will return `open: true`
|
||||
///
|
||||
/// Protected: false
|
||||
|
@ -81,3 +89,20 @@ pub async fn gen_jwp(proof: Json<proof::TxProof>) -> Custom<Json<reqres::Jwp>> {
|
|||
let jwp = proof::create_jwp(&proof).await;
|
||||
Custom(Status::Ok, Json(reqres::Jwp { jwp }))
|
||||
}
|
||||
|
||||
// NEVMES Market APIs
|
||||
//-----------------------------------------------
|
||||
|
||||
/// Get all products by passing vendor address
|
||||
///
|
||||
/// Protected: true
|
||||
#[get("/products")]
|
||||
pub async fn get_products(
|
||||
_jwp: proof::PaymentProof,
|
||||
) -> Custom<Json<Vec<models::Product>>> {
|
||||
let m_products: Vec<models::Product> = product::find_all();
|
||||
Custom(
|
||||
Status::Ok,
|
||||
Json(m_products),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -58,4 +58,6 @@ async fn rocket() -> _ {
|
|||
.mount("/share", routes![controller::share_contact_info])
|
||||
.mount("/i2p", routes![controller::get_i2p_status])
|
||||
.mount("/xmr/rpc", routes![controller::get_version])
|
||||
.mount("/market", routes![controller::get_products])
|
||||
.mount("/test", routes![controller::test])
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue