mirror of
https://github.com/creating2morrow/neveko.git
synced 2024-12-22 19:49:24 +00:00
start order multisig wallet funding flow
This commit is contained in:
parent
b44e03725c
commit
573c0ec36c
5 changed files with 274 additions and 58 deletions
|
@ -538,7 +538,12 @@ pub async fn send_make_info(orid: &String, contact: &String, info: Vec<String>)
|
||||||
/// Encrypts and sends the output from the monero-rpc
|
/// Encrypts and sends the output from the monero-rpc
|
||||||
///
|
///
|
||||||
/// `exchange_multisig_keys` method.
|
/// `exchange_multisig_keys` method.
|
||||||
pub async fn send_exchange_info(orid: &String, contact: &String, info: Vec<String>, kex_init: bool) {
|
pub async fn send_exchange_info(
|
||||||
|
orid: &String,
|
||||||
|
contact: &String,
|
||||||
|
info: Vec<String>,
|
||||||
|
kex_init: bool,
|
||||||
|
) {
|
||||||
let s = db::Interface::open();
|
let s = db::Interface::open();
|
||||||
let wallet_name = String::from(orid);
|
let wallet_name = String::from(orid);
|
||||||
let wallet_password = utils::empty_string();
|
let wallet_password = utils::empty_string();
|
||||||
|
@ -594,9 +599,9 @@ pub async fn send_export_info(orid: &String, contact: &String) {
|
||||||
///
|
///
|
||||||
/// from the mediator and the vendor. In response they create an encrypted
|
/// from the mediator and the vendor. In response they create an encrypted
|
||||||
///
|
///
|
||||||
/// multisig message with the requested data. Cusomter manages multisig by
|
/// multisig message with the requested data. Customer manages multisig by
|
||||||
///
|
///
|
||||||
/// injecting
|
/// injecting...
|
||||||
async fn trigger_msig_info_request(
|
async fn trigger_msig_info_request(
|
||||||
contact: String,
|
contact: String,
|
||||||
jwp: String,
|
jwp: String,
|
||||||
|
|
|
@ -14,9 +14,12 @@ use log::{
|
||||||
warn,
|
warn,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
io::Write,
|
|
||||||
error::Error,
|
error::Error,
|
||||||
process::{Command, Stdio}
|
io::Write,
|
||||||
|
process::{
|
||||||
|
Command,
|
||||||
|
Stdio,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
@ -76,6 +79,7 @@ enum RpcFields {
|
||||||
GetVersion,
|
GetVersion,
|
||||||
Id,
|
Id,
|
||||||
Import,
|
Import,
|
||||||
|
IsMultisig,
|
||||||
JsonRpcVersion,
|
JsonRpcVersion,
|
||||||
Make,
|
Make,
|
||||||
Open,
|
Open,
|
||||||
|
@ -106,6 +110,7 @@ impl RpcFields {
|
||||||
RpcFields::GetVersion => String::from("get_version"),
|
RpcFields::GetVersion => String::from("get_version"),
|
||||||
RpcFields::Id => String::from("0"),
|
RpcFields::Id => String::from("0"),
|
||||||
RpcFields::Import => String::from("import_multisig_info"),
|
RpcFields::Import => String::from("import_multisig_info"),
|
||||||
|
RpcFields::IsMultisig => String::from("is_multisig"),
|
||||||
RpcFields::JsonRpcVersion => String::from("2.0"),
|
RpcFields::JsonRpcVersion => String::from("2.0"),
|
||||||
RpcFields::Make => String::from("make_multisig"),
|
RpcFields::Make => String::from("make_multisig"),
|
||||||
RpcFields::Open => String::from("open_wallet"),
|
RpcFields::Open => String::from("open_wallet"),
|
||||||
|
@ -635,9 +640,13 @@ pub async fn get_address() -> reqres::XmrRpcAddressResponse {
|
||||||
let res = response.json::<reqres::XmrRpcAddressResponse>().await;
|
let res = response.json::<reqres::XmrRpcAddressResponse>().await;
|
||||||
match res {
|
match res {
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
debug!("{} count: {}", RpcFields::Address.value(), &res.result.addresses.len());
|
debug!(
|
||||||
|
"{} count: {}",
|
||||||
|
RpcFields::Address.value(),
|
||||||
|
&res.result.addresses.len()
|
||||||
|
);
|
||||||
res
|
res
|
||||||
},
|
}
|
||||||
_ => Default::default(),
|
_ => Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1191,6 +1200,35 @@ pub async fn refresh() -> reqres::XmrRpcRefreshResponse {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Performs the xmr rpc 'is_multisig' method
|
||||||
|
pub async fn is_multisig() -> reqres::XmrRpcIsMultisigResponse {
|
||||||
|
info!("executing {}", RpcFields::IsMultisig.value());
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
let host = get_rpc_host();
|
||||||
|
let req = reqres::XmrRpcRequest {
|
||||||
|
jsonrpc: RpcFields::JsonRpcVersion.value(),
|
||||||
|
id: RpcFields::Id.value(),
|
||||||
|
method: RpcFields::IsMultisig.value(),
|
||||||
|
};
|
||||||
|
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::XmrRpcIsMultisigResponse>().await;
|
||||||
|
debug!("{} response: {:?}", RpcFields::IsMultisig.value(), res);
|
||||||
|
match res {
|
||||||
|
Ok(res) => res,
|
||||||
|
_ => Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Daemon requests
|
// Daemon requests
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -1388,38 +1426,54 @@ pub async fn p_get_transactions(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// enable multisig - `monero-wallet-cli --password <> --wallet-file <> set enable-multisig-experimental 1`
|
/// enable multisig - `monero-wallet-cli --password <> --wallet-file <> set
|
||||||
|
/// enable-multisig-experimental 1`
|
||||||
pub fn enable_experimental_multisig(wallet_file: &String) {
|
pub fn enable_experimental_multisig(wallet_file: &String) {
|
||||||
warn!("Enabling experimental multisig...");
|
warn!("Enabling experimental multisig...");
|
||||||
let bin_dir = get_monero_location();
|
let bin_dir = get_monero_location();
|
||||||
let user = std::env::var("USER").unwrap_or(utils::empty_string());
|
let user = std::env::var("USER").unwrap_or(utils::empty_string());
|
||||||
let file_path = format!("/home/{}/.{}/stagenet/wallet/{}", &user, crate::APP_NAME, &wallet_file);
|
let file_path = format!(
|
||||||
|
"/home/{}/.{}/stagenet/wallet/{}",
|
||||||
|
&user,
|
||||||
|
crate::APP_NAME,
|
||||||
|
&wallet_file
|
||||||
|
);
|
||||||
let wallet_password = utils::empty_string();
|
let wallet_password = utils::empty_string();
|
||||||
let release_env = utils::get_release_env();
|
let release_env = utils::get_release_env();
|
||||||
let args = if release_env == utils::ReleaseEnvironment::Production {
|
let args = if release_env == utils::ReleaseEnvironment::Production {
|
||||||
vec![
|
vec![
|
||||||
"--password", &wallet_password,
|
"--password",
|
||||||
"--wallet-file", &file_path,
|
&wallet_password,
|
||||||
"set", "enable-multisig-experimental", "1"
|
"--wallet-file",
|
||||||
|
&file_path,
|
||||||
|
"set",
|
||||||
|
"enable-multisig-experimental",
|
||||||
|
"1",
|
||||||
]
|
]
|
||||||
} else {
|
} else {
|
||||||
vec![
|
vec![
|
||||||
"--stagenet",
|
"--stagenet",
|
||||||
"--password", &wallet_password,
|
"--password",
|
||||||
"--wallet-file", &file_path,
|
&wallet_password,
|
||||||
"set", "enable-multisig-experimental", "1"
|
"--wallet-file",
|
||||||
|
&file_path,
|
||||||
|
"set",
|
||||||
|
"enable-multisig-experimental",
|
||||||
|
"1",
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
let mut output = Command::new(format!("{}/monero-wallet-cli", bin_dir))
|
let mut output = Command::new(format!("{}/monero-wallet-cli", bin_dir))
|
||||||
.stdin(Stdio::piped())
|
.stdin(Stdio::piped())
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
.args(args)
|
.args(args)
|
||||||
.spawn()
|
.spawn()
|
||||||
.expect("failed to enable experimental msig");
|
.expect("failed to enable experimental msig");
|
||||||
let _ = std::io::stdout().flush();
|
let _ = std::io::stdout().flush();
|
||||||
let mut stdin = output.stdin.take().expect("Failed to open stdin");
|
let mut stdin = output.stdin.take().expect("Failed to open stdin");
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
stdin.write_all(&wallet_password.as_bytes()).expect("Failed to write to stdin");
|
stdin
|
||||||
|
.write_all(&wallet_password.as_bytes())
|
||||||
|
.expect("Failed to write to stdin");
|
||||||
});
|
});
|
||||||
let d_output = output.wait_with_output().expect("Failed to read stdout");
|
let d_output = output.wait_with_output().expect("Failed to read stdout");
|
||||||
debug!("{:?}", d_output);
|
debug!("{:?}", d_output);
|
||||||
|
|
|
@ -513,6 +513,14 @@ pub struct XmrRpcRefreshResult {
|
||||||
pub received_money: bool,
|
pub received_money: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct XmrRpcIsMultisigResult {
|
||||||
|
pub multisig: bool,
|
||||||
|
pub ready: bool,
|
||||||
|
pub threshold: u16,
|
||||||
|
pub total: u16,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub struct XmrDaemonGetInfoResult {
|
pub struct XmrDaemonGetInfoResult {
|
||||||
pub adjusted_time: u64,
|
pub adjusted_time: u64,
|
||||||
|
@ -1078,6 +1086,24 @@ impl Default for XmrRpcRefreshResponse {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct XmrRpcIsMultisigResponse {
|
||||||
|
pub result: XmrRpcIsMultisigResult,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for XmrRpcIsMultisigResponse {
|
||||||
|
fn default() -> Self {
|
||||||
|
XmrRpcIsMultisigResponse {
|
||||||
|
result: XmrRpcIsMultisigResult {
|
||||||
|
multisig: false,
|
||||||
|
ready: false,
|
||||||
|
threshold: 0,
|
||||||
|
total: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// END XMR Structs
|
// END XMR Structs
|
||||||
|
|
||||||
/// Container for the message decryption
|
/// Container for the message decryption
|
||||||
|
|
|
@ -309,6 +309,7 @@ impl eframe::App for HomeApp {
|
||||||
self.connections.is_i2p_advanced = !self.connections.is_i2p_advanced;
|
self.connections.is_i2p_advanced = !self.connections.is_i2p_advanced;
|
||||||
log::debug!("is i2p advanced mode: {}", self.connections.is_i2p_advanced);
|
log::debug!("is i2p advanced mode: {}", self.connections.is_i2p_advanced);
|
||||||
}
|
}
|
||||||
|
// TODO: mainnet
|
||||||
// let mut is_mainnet = self.connections.mainnet;
|
// let mut is_mainnet = self.connections.mainnet;
|
||||||
// if ui.checkbox(&mut is_mainnet, "mainnet").changed() {
|
// if ui.checkbox(&mut is_mainnet, "mainnet").changed() {
|
||||||
// self.connections.mainnet = !self.connections.mainnet;
|
// self.connections.mainnet = !self.connections.mainnet;
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
use image::Luma;
|
||||||
use neveko_core::*;
|
use neveko_core::*;
|
||||||
|
use qrcode::QrCode;
|
||||||
use std::sync::mpsc::{
|
use std::sync::mpsc::{
|
||||||
Receiver,
|
Receiver,
|
||||||
Sender,
|
Sender,
|
||||||
|
@ -7,6 +9,7 @@ use std::sync::mpsc::{
|
||||||
pub struct MultisigManagement {
|
pub struct MultisigManagement {
|
||||||
pub completed_kex_init: bool,
|
pub completed_kex_init: bool,
|
||||||
pub completed_kex_final: bool,
|
pub completed_kex_final: bool,
|
||||||
|
pub completed_funding: bool,
|
||||||
pub completed_prepare: bool,
|
pub completed_prepare: bool,
|
||||||
pub completed_make: bool,
|
pub completed_make: bool,
|
||||||
pub exchange_multisig_keys: String,
|
pub exchange_multisig_keys: String,
|
||||||
|
@ -25,6 +28,7 @@ impl Default for MultisigManagement {
|
||||||
MultisigManagement {
|
MultisigManagement {
|
||||||
completed_kex_init: false,
|
completed_kex_init: false,
|
||||||
completed_kex_final: false,
|
completed_kex_final: false,
|
||||||
|
completed_funding: false,
|
||||||
completed_prepare: false,
|
completed_prepare: false,
|
||||||
completed_make: false,
|
completed_make: false,
|
||||||
exchange_multisig_keys: utils::empty_string(),
|
exchange_multisig_keys: utils::empty_string(),
|
||||||
|
@ -53,6 +57,7 @@ pub struct MarketApp {
|
||||||
get_vendor_product_rx: Receiver<models::Product>,
|
get_vendor_product_rx: Receiver<models::Product>,
|
||||||
is_loading: bool,
|
is_loading: bool,
|
||||||
is_ordering: bool,
|
is_ordering: bool,
|
||||||
|
is_order_qr_set: bool,
|
||||||
is_pinging: bool,
|
is_pinging: bool,
|
||||||
is_customer_viewing_orders: bool,
|
is_customer_viewing_orders: bool,
|
||||||
is_managing_multisig: bool,
|
is_managing_multisig: bool,
|
||||||
|
@ -61,6 +66,7 @@ pub struct MarketApp {
|
||||||
is_showing_product_image: bool,
|
is_showing_product_image: bool,
|
||||||
is_showing_product_update: bool,
|
is_showing_product_update: bool,
|
||||||
is_showing_orders: bool,
|
is_showing_orders: bool,
|
||||||
|
is_showing_order_qr: bool,
|
||||||
is_showing_vendor_status: bool,
|
is_showing_vendor_status: bool,
|
||||||
is_showing_vendors: bool,
|
is_showing_vendors: bool,
|
||||||
is_timeout: bool,
|
is_timeout: bool,
|
||||||
|
@ -70,6 +76,9 @@ pub struct MarketApp {
|
||||||
/// order currently being acted on
|
/// order currently being acted on
|
||||||
m_order: models::Order,
|
m_order: models::Order,
|
||||||
orders: Vec<models::Order>,
|
orders: Vec<models::Order>,
|
||||||
|
order_xmr_address: String,
|
||||||
|
order_qr: egui_extras::RetainedImage,
|
||||||
|
order_qr_init: bool,
|
||||||
our_make_info_tx: Sender<String>,
|
our_make_info_tx: Sender<String>,
|
||||||
our_make_info_rx: Receiver<String>,
|
our_make_info_rx: Receiver<String>,
|
||||||
our_prepare_info_tx: Sender<String>,
|
our_prepare_info_tx: Sender<String>,
|
||||||
|
@ -95,6 +104,8 @@ pub struct MarketApp {
|
||||||
s_order: models::Order,
|
s_order: models::Order,
|
||||||
vendor_status: utils::ContactStatus,
|
vendor_status: utils::ContactStatus,
|
||||||
vendors: Vec<models::Contact>,
|
vendors: Vec<models::Contact>,
|
||||||
|
order_xmr_address_tx: Sender<reqres::XmrRpcAddressResponse>,
|
||||||
|
order_xmr_address_rx: Receiver<reqres::XmrRpcAddressResponse>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for MarketApp {
|
impl Default for MarketApp {
|
||||||
|
@ -112,6 +123,8 @@ impl Default for MarketApp {
|
||||||
let (submit_order_tx, submit_order_rx) = std::sync::mpsc::channel();
|
let (submit_order_tx, submit_order_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 contents = std::fs::read("./assets/qr.png").unwrap_or(Vec::new());
|
||||||
MarketApp {
|
MarketApp {
|
||||||
contact_info_rx,
|
contact_info_rx,
|
||||||
contact_info_tx,
|
contact_info_tx,
|
||||||
|
@ -127,9 +140,11 @@ impl Default for MarketApp {
|
||||||
is_loading: false,
|
is_loading: false,
|
||||||
is_managing_multisig: false,
|
is_managing_multisig: false,
|
||||||
is_ordering: false,
|
is_ordering: false,
|
||||||
|
is_order_qr_set: false,
|
||||||
is_pinging: false,
|
is_pinging: false,
|
||||||
is_product_image_set: false,
|
is_product_image_set: false,
|
||||||
is_showing_orders: false,
|
is_showing_orders: false,
|
||||||
|
is_showing_order_qr: false,
|
||||||
is_showing_products: false,
|
is_showing_products: false,
|
||||||
is_showing_product_image: false,
|
is_showing_product_image: false,
|
||||||
is_showing_product_update: false,
|
is_showing_product_update: false,
|
||||||
|
@ -140,6 +155,11 @@ impl Default for MarketApp {
|
||||||
is_window_shopping: false,
|
is_window_shopping: false,
|
||||||
msig: Default::default(),
|
msig: Default::default(),
|
||||||
m_order: Default::default(),
|
m_order: Default::default(),
|
||||||
|
order_xmr_address: utils::empty_string(),
|
||||||
|
order_xmr_address_rx,
|
||||||
|
order_xmr_address_tx,
|
||||||
|
order_qr: egui_extras::RetainedImage::from_image_bytes("qr.png", &contents).unwrap(),
|
||||||
|
order_qr_init: false,
|
||||||
our_make_info_rx,
|
our_make_info_rx,
|
||||||
our_make_info_tx,
|
our_make_info_tx,
|
||||||
our_prepare_info_rx,
|
our_prepare_info_rx,
|
||||||
|
@ -252,6 +272,12 @@ impl eframe::App for MarketApp {
|
||||||
self.is_loading = false;
|
self.is_loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Ok(a) = self.order_xmr_address_rx.try_recv() {
|
||||||
|
self.order_xmr_address = a.result.address;
|
||||||
|
if self.order_xmr_address != utils::empty_string() {
|
||||||
|
self.is_showing_order_qr = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
// Vendor status window
|
// Vendor status window
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
let mut is_showing_vendor_status = self.is_showing_vendor_status;
|
let mut is_showing_vendor_status = self.is_showing_vendor_status;
|
||||||
|
@ -383,8 +409,12 @@ impl eframe::App for MarketApp {
|
||||||
let vendor =
|
let vendor =
|
||||||
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone());
|
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone());
|
||||||
let sub_type = String::from(message::PREPARE_MSIG);
|
let sub_type = String::from(message::PREPARE_MSIG);
|
||||||
let is_prepared =
|
let is_prepared = validate_msig_step(
|
||||||
validate_msig_step(&mediator, &self.m_order.orid, &vendor, &sub_type);
|
&mediator,
|
||||||
|
&self.m_order.orid,
|
||||||
|
&vendor,
|
||||||
|
&sub_type,
|
||||||
|
);
|
||||||
self.msig.completed_prepare = is_prepared;
|
self.msig.completed_prepare = is_prepared;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -418,8 +448,12 @@ impl eframe::App for MarketApp {
|
||||||
let vendor =
|
let vendor =
|
||||||
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone());
|
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone());
|
||||||
let sub_type = String::from(message::MAKE_MSIG);
|
let sub_type = String::from(message::MAKE_MSIG);
|
||||||
let is_made =
|
let is_made = validate_msig_step(
|
||||||
validate_msig_step(&mediator, &self.m_order.orid, &vendor, &sub_type);
|
&mediator,
|
||||||
|
&self.m_order.orid,
|
||||||
|
&vendor,
|
||||||
|
&sub_type,
|
||||||
|
);
|
||||||
self.msig.completed_make = is_made;
|
self.msig.completed_make = is_made;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -453,8 +487,12 @@ impl eframe::App for MarketApp {
|
||||||
let vendor =
|
let vendor =
|
||||||
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone());
|
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone());
|
||||||
let sub_type = String::from(message::KEX_ONE_MSIG);
|
let sub_type = String::from(message::KEX_ONE_MSIG);
|
||||||
let is_made =
|
let is_made = validate_msig_step(
|
||||||
validate_msig_step(&mediator, &self.m_order.orid, &vendor, &sub_type);
|
&mediator,
|
||||||
|
&self.m_order.orid,
|
||||||
|
&vendor,
|
||||||
|
&sub_type,
|
||||||
|
);
|
||||||
self.msig.completed_kex_init = is_made;
|
self.msig.completed_kex_init = is_made;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -488,16 +526,33 @@ impl eframe::App for MarketApp {
|
||||||
let vendor =
|
let vendor =
|
||||||
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone());
|
utils::search_gui_db(vendor_prefix, self.m_order.orid.clone());
|
||||||
let sub_type = String::from(message::KEX_TWO_MSIG);
|
let sub_type = String::from(message::KEX_TWO_MSIG);
|
||||||
let is_made =
|
let is_made = validate_msig_step(
|
||||||
validate_msig_step(&mediator, &self.m_order.orid, &vendor, &sub_type);
|
&mediator,
|
||||||
|
&self.m_order.orid,
|
||||||
|
&vendor,
|
||||||
|
&sub_type,
|
||||||
|
);
|
||||||
self.msig.completed_kex_final = is_made;
|
self.msig.completed_kex_final = is_made;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// ui.horizontal(|ui| {
|
if self.msig.completed_kex_final && !self.msig.completed_funding {
|
||||||
// ui.label("Fund:\t\t\t\t\t\t\t");
|
ui.horizontal(|ui| {
|
||||||
// if ui.button("Fund").clicked() {}
|
ui.label("Fund:\t\t\t\t\t\t\t");
|
||||||
// });
|
if ui.button("Fund").clicked() {
|
||||||
|
set_order_address(
|
||||||
|
&self.m_order.orid,
|
||||||
|
self.order_xmr_address_tx.clone(),
|
||||||
|
ctx.clone(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ui.button("Check").clicked() {
|
||||||
|
// is the wallet multisig completed?
|
||||||
|
// the customer doesn't pay fees on orders
|
||||||
|
// ensure the balance of the order wallet matches the order total
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
// ui.horizontal(|ui| {
|
// ui.horizontal(|ui| {
|
||||||
// ui.label("Export Info: \t\t\t\t");
|
// ui.label("Export Info: \t\t\t\t");
|
||||||
// if ui.button("Export").clicked() {}
|
// if ui.button("Export").clicked() {}
|
||||||
|
@ -517,6 +572,39 @@ impl eframe::App for MarketApp {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Order Wallet QR
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
let mut is_showing_order_qr = self.is_showing_order_qr;
|
||||||
|
egui::Window::new("order wallet qr")
|
||||||
|
.open(&mut is_showing_order_qr)
|
||||||
|
.title_bar(false)
|
||||||
|
.vscroll(true)
|
||||||
|
.show(ctx, |ui| {
|
||||||
|
if !self.is_order_qr_set && self.order_xmr_address != utils::empty_string() {
|
||||||
|
let code = QrCode::new(&self.order_xmr_address.clone()).unwrap();
|
||||||
|
let image = code.render::<Luma<u8>>().build();
|
||||||
|
let file_path = format!(
|
||||||
|
"/home/{}/.neveko/qr.png",
|
||||||
|
std::env::var("USER").unwrap_or(String::from("user"))
|
||||||
|
);
|
||||||
|
image.save(&file_path).unwrap();
|
||||||
|
self.order_qr_init = true;
|
||||||
|
self.is_order_qr_set = true;
|
||||||
|
let contents = std::fs::read(&file_path).unwrap_or(Vec::new());
|
||||||
|
self.order_qr =
|
||||||
|
egui_extras::RetainedImage::from_image_bytes("qr.png", &contents).unwrap();
|
||||||
|
ctx.request_repaint();
|
||||||
|
}
|
||||||
|
self.order_qr.show(ui);
|
||||||
|
let address_label = ui.label("copy: \t");
|
||||||
|
ui.text_edit_singleline(&mut self.order_xmr_address)
|
||||||
|
.labelled_by(address_label.id);
|
||||||
|
ui.label("\n");
|
||||||
|
if ui.button("Exit").clicked() {
|
||||||
|
self.is_showing_order_qr = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// View orders - Customer Order Flow Management
|
// View orders - Customer Order Flow Management
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
let mut is_customer_viewing_orders = self.is_customer_viewing_orders;
|
let mut is_customer_viewing_orders = self.is_customer_viewing_orders;
|
||||||
|
@ -1510,13 +1598,23 @@ fn send_make_info_req(
|
||||||
let mut v_prepare_info_send = Vec::new();
|
let mut v_prepare_info_send = Vec::new();
|
||||||
// we need to send our info to mediator and vendor so they can perform
|
// we need to send our info to mediator and vendor so they can perform
|
||||||
// make_multisig and send the reponse (String) back
|
// make_multisig and send the reponse (String) back
|
||||||
let c_prepare= utils::search_gui_db(
|
let c_prepare = utils::search_gui_db(
|
||||||
String::from(crate::GUI_MSIG_PREPARE_DB_KEY),
|
String::from(crate::GUI_MSIG_PREPARE_DB_KEY),
|
||||||
String::from(&w_orid),
|
String::from(&w_orid),
|
||||||
);
|
);
|
||||||
let s = db::Interface::async_open().await;
|
let s = db::Interface::async_open().await;
|
||||||
let m_msig_key = format!("{}-{}-{}", message::PREPARE_MSIG, String::from(&m_orid), mediator);
|
let m_msig_key = format!(
|
||||||
let v_msig_key = format!("{}-{}-{}", message::PREPARE_MSIG, String::from(&v_orid), vendor);
|
"{}-{}-{}",
|
||||||
|
message::PREPARE_MSIG,
|
||||||
|
String::from(&m_orid),
|
||||||
|
mediator
|
||||||
|
);
|
||||||
|
let v_msig_key = format!(
|
||||||
|
"{}-{}-{}",
|
||||||
|
message::PREPARE_MSIG,
|
||||||
|
String::from(&v_orid),
|
||||||
|
vendor
|
||||||
|
);
|
||||||
let m_prepare = db::Interface::async_read(&s.env, &s.handle, &m_msig_key).await;
|
let m_prepare = db::Interface::async_read(&s.env, &s.handle, &m_msig_key).await;
|
||||||
let v_prepare = db::Interface::async_read(&s.env, &s.handle, &v_msig_key).await;
|
let v_prepare = db::Interface::async_read(&s.env, &s.handle, &v_msig_key).await;
|
||||||
prepare_info_prep.push(String::from(&m_prepare));
|
prepare_info_prep.push(String::from(&m_prepare));
|
||||||
|
@ -1560,25 +1658,19 @@ fn send_make_info_req(
|
||||||
let m_make = db::Interface::async_read(&s.env, &s.handle, &m_msig_key).await;
|
let m_make = db::Interface::async_read(&s.env, &s.handle, &m_msig_key).await;
|
||||||
let v_make = db::Interface::async_read(&s.env, &s.handle, &v_msig_key).await;
|
let v_make = db::Interface::async_read(&s.env, &s.handle, &v_msig_key).await;
|
||||||
if v_make == utils::empty_string() {
|
if v_make == utils::empty_string() {
|
||||||
log::debug!(
|
log::debug!("constructing vendor {} msig messages", message::MAKE_MSIG);
|
||||||
"constructing vendor {} msig messages",
|
|
||||||
message::MAKE_MSIG
|
|
||||||
);
|
|
||||||
let v_msig_request: reqres::MultisigInfoRequest = reqres::MultisigInfoRequest {
|
let v_msig_request: reqres::MultisigInfoRequest = reqres::MultisigInfoRequest {
|
||||||
contact: i2p::get_destination(None),
|
contact: i2p::get_destination(None),
|
||||||
info: v_prepare_info_send,
|
info: v_prepare_info_send,
|
||||||
init_mediator: false,
|
init_mediator: false,
|
||||||
kex_init:false,
|
kex_init: false,
|
||||||
msig_type: String::from(message::MAKE_MSIG),
|
msig_type: String::from(message::MAKE_MSIG),
|
||||||
orid: String::from(v_orid),
|
orid: String::from(v_orid),
|
||||||
};
|
};
|
||||||
let _v_result = message::d_trigger_msig_info(&vendor, &v_jwp, &v_msig_request).await;
|
let _v_result = message::d_trigger_msig_info(&vendor, &v_jwp, &v_msig_request).await;
|
||||||
}
|
}
|
||||||
if m_make == utils::empty_string() {
|
if m_make == utils::empty_string() {
|
||||||
log::debug!(
|
log::debug!("constructing mediator {} msig messages", message::MAKE_MSIG);
|
||||||
"constructing mediator {} msig messages",
|
|
||||||
message::MAKE_MSIG
|
|
||||||
);
|
|
||||||
let m_msig_request: reqres::MultisigInfoRequest = reqres::MultisigInfoRequest {
|
let m_msig_request: reqres::MultisigInfoRequest = reqres::MultisigInfoRequest {
|
||||||
contact: i2p::get_destination(None),
|
contact: i2p::get_destination(None),
|
||||||
info: m_prepare_info_send,
|
info: m_prepare_info_send,
|
||||||
|
@ -1627,8 +1719,18 @@ fn send_kex_initial_req(
|
||||||
String::from(&w_orid),
|
String::from(&w_orid),
|
||||||
);
|
);
|
||||||
let s = db::Interface::async_open().await;
|
let s = db::Interface::async_open().await;
|
||||||
let m_msig_key = format!("{}-{}-{}", message::MAKE_MSIG, String::from(&m_orid), mediator);
|
let m_msig_key = format!(
|
||||||
let v_msig_key = format!("{}-{}-{}", message::MAKE_MSIG, String::from(&v_orid), vendor);
|
"{}-{}-{}",
|
||||||
|
message::MAKE_MSIG,
|
||||||
|
String::from(&m_orid),
|
||||||
|
mediator
|
||||||
|
);
|
||||||
|
let v_msig_key = format!(
|
||||||
|
"{}-{}-{}",
|
||||||
|
message::MAKE_MSIG,
|
||||||
|
String::from(&v_orid),
|
||||||
|
vendor
|
||||||
|
);
|
||||||
let m_kex_init = db::Interface::async_read(&s.env, &s.handle, &m_msig_key).await;
|
let m_kex_init = db::Interface::async_read(&s.env, &s.handle, &m_msig_key).await;
|
||||||
let v_kex_init = db::Interface::async_read(&s.env, &s.handle, &v_msig_key).await;
|
let v_kex_init = db::Interface::async_read(&s.env, &s.handle, &v_msig_key).await;
|
||||||
kex_init_prep.push(String::from(&m_kex_init));
|
kex_init_prep.push(String::from(&m_kex_init));
|
||||||
|
@ -1642,7 +1744,8 @@ fn send_kex_initial_req(
|
||||||
String::from(&w_orid),
|
String::from(&w_orid),
|
||||||
);
|
);
|
||||||
if local_kex_init == utils::empty_string() {
|
if local_kex_init == utils::empty_string() {
|
||||||
let kex_out = monero::exchange_multisig_keys(false, kex_init_prep, &wallet_password).await;
|
let kex_out =
|
||||||
|
monero::exchange_multisig_keys(false, kex_init_prep, &wallet_password).await;
|
||||||
monero::close_wallet(&w_orid, &wallet_password).await;
|
monero::close_wallet(&w_orid, &wallet_password).await;
|
||||||
let ref_kex_info: &String = &kex_out.result.multisig_info;
|
let ref_kex_info: &String = &kex_out.result.multisig_info;
|
||||||
if String::from(ref_kex_info) != utils::empty_string() {
|
if String::from(ref_kex_info) != utils::empty_string() {
|
||||||
|
@ -1736,8 +1839,18 @@ fn send_kex_final_req(
|
||||||
String::from(&w_orid),
|
String::from(&w_orid),
|
||||||
);
|
);
|
||||||
let s = db::Interface::async_open().await;
|
let s = db::Interface::async_open().await;
|
||||||
let m_msig_key = format!("{}-{}-{}", message::KEX_ONE_MSIG, String::from(&m_orid), mediator);
|
let m_msig_key = format!(
|
||||||
let v_msig_key = format!("{}-{}-{}", message::KEX_ONE_MSIG, String::from(&v_orid), vendor);
|
"{}-{}-{}",
|
||||||
|
message::KEX_ONE_MSIG,
|
||||||
|
String::from(&m_orid),
|
||||||
|
mediator
|
||||||
|
);
|
||||||
|
let v_msig_key = format!(
|
||||||
|
"{}-{}-{}",
|
||||||
|
message::KEX_ONE_MSIG,
|
||||||
|
String::from(&v_orid),
|
||||||
|
vendor
|
||||||
|
);
|
||||||
let m_kex_final = db::Interface::async_read(&s.env, &s.handle, &m_msig_key).await;
|
let m_kex_final = db::Interface::async_read(&s.env, &s.handle, &m_msig_key).await;
|
||||||
let v_kex_final = db::Interface::async_read(&s.env, &s.handle, &v_msig_key).await;
|
let v_kex_final = db::Interface::async_read(&s.env, &s.handle, &v_msig_key).await;
|
||||||
kex_final_prep.push(String::from(&m_kex_final));
|
kex_final_prep.push(String::from(&m_kex_final));
|
||||||
|
@ -1751,7 +1864,8 @@ fn send_kex_final_req(
|
||||||
String::from(&w_orid),
|
String::from(&w_orid),
|
||||||
);
|
);
|
||||||
if local_kex_final == utils::empty_string() {
|
if local_kex_final == utils::empty_string() {
|
||||||
let kex_out = monero::exchange_multisig_keys(false, kex_final_prep, &wallet_password).await;
|
let kex_out =
|
||||||
|
monero::exchange_multisig_keys(false, kex_final_prep, &wallet_password).await;
|
||||||
monero::close_wallet(&w_orid, &wallet_password).await;
|
monero::close_wallet(&w_orid, &wallet_password).await;
|
||||||
let ref_kex_info: &String = &kex_out.result.address;
|
let ref_kex_info: &String = &kex_out.result.address;
|
||||||
if String::from(ref_kex_info) != utils::empty_string() {
|
if String::from(ref_kex_info) != utils::empty_string() {
|
||||||
|
@ -1781,14 +1895,14 @@ fn send_kex_final_req(
|
||||||
if v_kex_final == utils::empty_string() {
|
if v_kex_final == utils::empty_string() {
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"constructing vendor {} msig messages",
|
"constructing vendor {} msig messages",
|
||||||
message::KEX_ONE_MSIG
|
message::KEX_TWO_MSIG
|
||||||
);
|
);
|
||||||
let v_msig_request: reqres::MultisigInfoRequest = reqres::MultisigInfoRequest {
|
let v_msig_request: reqres::MultisigInfoRequest = reqres::MultisigInfoRequest {
|
||||||
contact: i2p::get_destination(None),
|
contact: i2p::get_destination(None),
|
||||||
info: v_kex_final_send,
|
info: v_kex_final_send,
|
||||||
init_mediator: false,
|
init_mediator: false,
|
||||||
kex_init: false,
|
kex_init: false,
|
||||||
msig_type: String::from(message::KEX_ONE_MSIG),
|
msig_type: String::from(message::KEX_TWO_MSIG),
|
||||||
orid: String::from(v_orid),
|
orid: String::from(v_orid),
|
||||||
};
|
};
|
||||||
let _v_result = message::d_trigger_msig_info(&vendor, &v_jwp, &v_msig_request).await;
|
let _v_result = message::d_trigger_msig_info(&vendor, &v_jwp, &v_msig_request).await;
|
||||||
|
@ -1796,14 +1910,14 @@ fn send_kex_final_req(
|
||||||
if m_kex_final == utils::empty_string() {
|
if m_kex_final == utils::empty_string() {
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"constructing mediator {} msig messages",
|
"constructing mediator {} msig messages",
|
||||||
message::KEX_ONE_MSIG
|
message::KEX_TWO_MSIG
|
||||||
);
|
);
|
||||||
let m_msig_request: reqres::MultisigInfoRequest = reqres::MultisigInfoRequest {
|
let m_msig_request: reqres::MultisigInfoRequest = reqres::MultisigInfoRequest {
|
||||||
contact: i2p::get_destination(None),
|
contact: i2p::get_destination(None),
|
||||||
info: m_kex_final_send,
|
info: m_kex_final_send,
|
||||||
init_mediator: false,
|
init_mediator: false,
|
||||||
kex_init: true,
|
kex_init: false,
|
||||||
msig_type: String::from(message::KEX_ONE_MSIG),
|
msig_type: String::from(message::KEX_TWO_MSIG),
|
||||||
orid: String::from(m_orid),
|
orid: String::from(m_orid),
|
||||||
};
|
};
|
||||||
let _m_result = message::d_trigger_msig_info(&mediator, &m_jwp, &m_msig_request).await;
|
let _m_result = message::d_trigger_msig_info(&mediator, &m_jwp, &m_msig_request).await;
|
||||||
|
@ -1813,9 +1927,25 @@ fn send_kex_final_req(
|
||||||
ctx.request_repaint();
|
ctx.request_repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_order_address(orid: &String, tx: Sender<reqres::XmrRpcAddressResponse>, ctx: egui::Context) {
|
||||||
|
let order_id = String::from(orid);
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let wallet_password = utils::empty_string();
|
||||||
|
monero::open_wallet(&order_id, &wallet_password).await;
|
||||||
|
let address: reqres::XmrRpcAddressResponse = monero::get_address().await;
|
||||||
|
monero::close_wallet(&order_id, &wallet_password).await;
|
||||||
|
let _ = tx.send(address);
|
||||||
|
ctx.request_repaint();
|
||||||
|
});
|
||||||
|
}
|
||||||
// End Async fn requests
|
// End Async fn requests
|
||||||
|
|
||||||
fn validate_msig_step(mediator: &String, orid: &String, vendor: &String, sub_type: &String) -> bool {
|
fn validate_msig_step(
|
||||||
|
mediator: &String,
|
||||||
|
orid: &String,
|
||||||
|
vendor: &String,
|
||||||
|
sub_type: &String,
|
||||||
|
) -> bool {
|
||||||
let s = db::Interface::open();
|
let s = db::Interface::open();
|
||||||
let m_msig_key = format!("{}-{}-{}", sub_type, orid, mediator);
|
let m_msig_key = format!("{}-{}-{}", sub_type, orid, mediator);
|
||||||
let v_msig_key = format!("{}-{}-{}", sub_type, orid, vendor);
|
let v_msig_key = format!("{}-{}-{}", sub_type, orid, vendor);
|
||||||
|
|
Loading…
Reference in a new issue