mirror of
https://github.com/creating2morrow/neveko.git
synced 2024-12-22 19:49:24 +00:00
fix prove payment zero conf retry logic
This commit is contained in:
parent
c75ff4e4f1
commit
39827212f6
9 changed files with 178 additions and 87 deletions
|
@ -165,7 +165,6 @@ pub fn trust_gpg(key: String) {
|
||||||
|
|
||||||
/// Get invoice for jwp creation
|
/// Get invoice for jwp creation
|
||||||
pub async fn request_invoice(contact: String) -> Result<reqres::Invoice, Box<dyn Error>> {
|
pub async fn request_invoice(contact: String) -> Result<reqres::Invoice, Box<dyn Error>> {
|
||||||
// TODO(c2m): Error handling for http 402 status
|
|
||||||
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();
|
||||||
|
@ -193,7 +192,6 @@ pub async fn request_invoice(contact: String) -> Result<reqres::Invoice, Box<dyn
|
||||||
///
|
///
|
||||||
/// for gpg key removal.
|
/// for gpg key removal.
|
||||||
pub async fn add_contact_request(contact: String, prune: u32) -> Result<Contact, Box<dyn Error>> {
|
pub async fn add_contact_request(contact: String, prune: u32) -> Result<Contact, Box<dyn Error>> {
|
||||||
// TODO(c2m): Error handling for http 402 status
|
|
||||||
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();
|
||||||
|
|
|
@ -19,7 +19,6 @@ pub const APP_NAME: &str = "neveko";
|
||||||
pub const NEVEKO_JWP_SECRET_KEY: &str = "NEVEKO_JWP_SECRET_KEY";
|
pub const NEVEKO_JWP_SECRET_KEY: &str = "NEVEKO_JWP_SECRET_KEY";
|
||||||
pub const NEVEKO_JWT_SECRET_KEY: &str = "NEVEKO_JWT_SECRET_KEY";
|
pub const NEVEKO_JWT_SECRET_KEY: &str = "NEVEKO_JWT_SECRET_KEY";
|
||||||
|
|
||||||
// TODO(c2m): better handling of setting initial wallet password
|
|
||||||
/// Environment variable for injecting wallet password
|
/// Environment variable for injecting wallet password
|
||||||
pub const MONERO_WALLET_PASSWORD: &str = "MONERO_WALLET_PASSWORD";
|
pub const MONERO_WALLET_PASSWORD: &str = "MONERO_WALLET_PASSWORD";
|
||||||
|
|
||||||
|
|
|
@ -45,10 +45,10 @@ impl TransactionType {
|
||||||
pub fn value(&self) -> String {
|
pub fn value(&self) -> String {
|
||||||
match *self {
|
match *self {
|
||||||
Self::Failed => String::from("failed"),
|
Self::Failed => String::from("failed"),
|
||||||
Self::In => String::from("In"),
|
Self::In => String::from("in"),
|
||||||
Self::Out => String::from("Out"),
|
Self::Out => String::from("out"),
|
||||||
Self::Pending => String::from("Pending"),
|
Self::Pending => String::from("pending"),
|
||||||
Self::Pool => String::from("Pool"),
|
Self::Pool => String::from("pool"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn propogated(tx_type: String) -> bool {
|
pub fn propogated(tx_type: String) -> bool {
|
||||||
|
|
|
@ -117,7 +117,6 @@ pub async fn create_jwp(proof: &TxProof) -> String {
|
||||||
|
|
||||||
/// Send transaction proof to contact for JWP generation
|
/// Send transaction proof to contact for JWP generation
|
||||||
pub async fn prove_payment(contact: String, txp: &TxProof) -> Result<reqres::Jwp, Box<dyn Error>> {
|
pub async fn prove_payment(contact: String, txp: &TxProof) -> Result<reqres::Jwp, Box<dyn Error>> {
|
||||||
// TODO(c2m): Error handling for http 402 status
|
|
||||||
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();
|
||||||
|
|
|
@ -112,6 +112,15 @@ pub struct Destination {
|
||||||
pub amount: u128,
|
pub amount: u128,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Destination {
|
||||||
|
fn default() -> Self {
|
||||||
|
Destination {
|
||||||
|
address: utils::empty_string(),
|
||||||
|
amount: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
pub struct XmrRpcTransferParams {
|
pub struct XmrRpcTransferParams {
|
||||||
pub destinations: Vec<Destination>,
|
pub destinations: Vec<Destination>,
|
||||||
|
@ -438,7 +447,8 @@ pub struct Transfer {
|
||||||
pub address: String,
|
pub address: String,
|
||||||
pub amount: u128,
|
pub amount: u128,
|
||||||
pub amounts: Vec<u128>,
|
pub amounts: Vec<u128>,
|
||||||
pub confirmations: u64,
|
/// On zero conf this field is missing
|
||||||
|
pub confirmations: Option<u64>,
|
||||||
pub double_spend_seen: bool,
|
pub double_spend_seen: bool,
|
||||||
pub fee: u128,
|
pub fee: u128,
|
||||||
pub height: u64,
|
pub height: u64,
|
||||||
|
@ -984,7 +994,7 @@ impl Default for XmrRpcGetTxByIdResponse {
|
||||||
address: utils::empty_string(),
|
address: utils::empty_string(),
|
||||||
amount: 0,
|
amount: 0,
|
||||||
amounts: Vec::new(),
|
amounts: Vec::new(),
|
||||||
confirmations: 0,
|
confirmations: None,
|
||||||
double_spend_seen: false,
|
double_spend_seen: false,
|
||||||
fee: 0,
|
fee: 0,
|
||||||
height: 0,
|
height: 0,
|
||||||
|
|
|
@ -716,6 +716,7 @@ pub async fn can_transfer(invoice: u128) -> bool {
|
||||||
|
|
||||||
/// Gui toggle for vendor mode
|
/// Gui toggle for vendor mode
|
||||||
pub fn toggle_vendor_enabled() -> bool {
|
pub fn toggle_vendor_enabled() -> bool {
|
||||||
|
// TODO(c2m): Dont toggle vendors with orders status != Delivered
|
||||||
let s = db::Interface::open();
|
let s = db::Interface::open();
|
||||||
let r = db::Interface::read(&s.env, &s.handle, contact::NEVEKO_VENDOR_ENABLED);
|
let r = db::Interface::read(&s.env, &s.handle, contact::NEVEKO_VENDOR_ENABLED);
|
||||||
if r != contact::NEVEKO_VENDOR_MODE_ON {
|
if r != contact::NEVEKO_VENDOR_MODE_ON {
|
||||||
|
|
|
@ -61,6 +61,7 @@ pub struct AddressBookApp {
|
||||||
invoice_rx: Receiver<reqres::Invoice>,
|
invoice_rx: Receiver<reqres::Invoice>,
|
||||||
is_adding: bool,
|
is_adding: bool,
|
||||||
is_composing: bool,
|
is_composing: bool,
|
||||||
|
is_approving_jwp: bool,
|
||||||
is_estimating_fee: bool,
|
is_estimating_fee: bool,
|
||||||
is_pinging: bool,
|
is_pinging: bool,
|
||||||
is_loading: bool,
|
is_loading: bool,
|
||||||
|
@ -110,6 +111,7 @@ impl Default for AddressBookApp {
|
||||||
invoice_rx,
|
invoice_rx,
|
||||||
is_adding: false,
|
is_adding: false,
|
||||||
is_composing: false,
|
is_composing: false,
|
||||||
|
is_approving_jwp: false,
|
||||||
is_estimating_fee: false,
|
is_estimating_fee: false,
|
||||||
is_loading: false,
|
is_loading: false,
|
||||||
is_message_sent: false,
|
is_message_sent: false,
|
||||||
|
@ -275,8 +277,10 @@ impl eframe::App for AddressBookApp {
|
||||||
d,
|
d,
|
||||||
self.status.i2p.clone(),
|
self.status.i2p.clone(),
|
||||||
expire,
|
expire,
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
self.is_loading = true;
|
self.is_loading = true;
|
||||||
|
self.is_approving_jwp = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ui.button("Exit").clicked() {
|
if ui.button("Exit").clicked() {
|
||||||
|
@ -295,9 +299,14 @@ impl eframe::App for AddressBookApp {
|
||||||
.title_bar(false)
|
.title_bar(false)
|
||||||
.id(egui::Id::new(self.status.i2p.clone()))
|
.id(egui::Id::new(self.status.i2p.clone()))
|
||||||
.show(&ctx, |ui| {
|
.show(&ctx, |ui| {
|
||||||
if self.is_pinging {
|
if self.is_pinging || self.is_loading {
|
||||||
|
let spinner_text = if self.is_loading {
|
||||||
|
"retrying payment proof... "
|
||||||
|
} else {
|
||||||
|
"pinging..."
|
||||||
|
};
|
||||||
ui.add(egui::Spinner::new());
|
ui.add(egui::Spinner::new());
|
||||||
ui.label("pinging...");
|
ui.label(spinner_text);
|
||||||
}
|
}
|
||||||
let status = if self.s_contact.xmr_address != utils::empty_string() {
|
let status = if self.s_contact.xmr_address != utils::empty_string() {
|
||||||
"online"
|
"online"
|
||||||
|
@ -323,6 +332,7 @@ impl eframe::App for AddressBookApp {
|
||||||
);
|
);
|
||||||
self.approve_payment = true;
|
self.approve_payment = true;
|
||||||
self.showing_status = false;
|
self.showing_status = false;
|
||||||
|
self.is_approving_jwp = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !self.status.signed_key {
|
if !self.status.signed_key {
|
||||||
|
@ -346,6 +356,21 @@ impl eframe::App for AddressBookApp {
|
||||||
self.showing_status = false;
|
self.showing_status = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if self.status.txp != utils::empty_string()
|
||||||
|
&& self.status.jwp == utils::empty_string()
|
||||||
|
&& status == "online" {
|
||||||
|
if ui.button("Prove Retry").clicked() {
|
||||||
|
send_payment_req(
|
||||||
|
self.payment_tx.clone(),
|
||||||
|
ctx.clone(),
|
||||||
|
Default::default(),
|
||||||
|
self.status.i2p.clone(),
|
||||||
|
expire as u64,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
self.is_loading = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
let nick_label = ui.label("nick: ");
|
let nick_label = ui.label("nick: ");
|
||||||
ui.text_edit_singleline(&mut self.add_nick)
|
ui.text_edit_singleline(&mut self.add_nick)
|
||||||
|
@ -357,12 +382,16 @@ impl eframe::App for AddressBookApp {
|
||||||
}
|
}
|
||||||
if ui.button("Exit").clicked() {
|
if ui.button("Exit").clicked() {
|
||||||
self.showing_status = false;
|
self.showing_status = false;
|
||||||
|
self.is_loading = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Main panel for adding contacts
|
// Main panel for adding contacts
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
if self.is_approving_jwp {
|
||||||
|
ui.add(egui::Spinner::new());
|
||||||
|
}
|
||||||
ui.heading("Add Contact");
|
ui.heading("Add Contact");
|
||||||
ui.label(
|
ui.label(
|
||||||
"____________________________________________________________________________\n",
|
"____________________________________________________________________________\n",
|
||||||
|
@ -643,13 +672,15 @@ fn send_payment_req(
|
||||||
d: reqres::Destination,
|
d: reqres::Destination,
|
||||||
contact: String,
|
contact: String,
|
||||||
expire: u64,
|
expire: u64,
|
||||||
|
retry: bool,
|
||||||
) {
|
) {
|
||||||
log::debug!("async send_payment_req");
|
log::debug!("async send_payment_req");
|
||||||
log::debug!("cleaning stale jwp values");
|
log::debug!("cleaning stale jwp values");
|
||||||
|
tokio::spawn(async move {
|
||||||
|
if !retry {
|
||||||
utils::clear_gui_db(String::from("gui-txp"), String::from(&contact));
|
utils::clear_gui_db(String::from("gui-txp"), String::from(&contact));
|
||||||
utils::clear_gui_db(String::from("gui-jwp"), String::from(&contact));
|
utils::clear_gui_db(String::from("gui-jwp"), String::from(&contact));
|
||||||
utils::clear_gui_db(String::from("gui-exp"), String::from(&contact));
|
utils::clear_gui_db(String::from("gui-exp"), String::from(&contact));
|
||||||
tokio::spawn(async move {
|
|
||||||
let ptxp_address = String::from(&d.address);
|
let ptxp_address = String::from(&d.address);
|
||||||
let ftxp_address = String::from(&d.address);
|
let ftxp_address = String::from(&d.address);
|
||||||
log::debug!("sending {} piconero(s) to: {}", &d.amount, &d.address);
|
log::debug!("sending {} piconero(s) to: {}", &d.amount, &d.address);
|
||||||
|
@ -686,18 +717,26 @@ fn send_payment_req(
|
||||||
String::from(&contact),
|
String::from(&contact),
|
||||||
String::from(&ftxp.signature),
|
String::from(&ftxp.signature),
|
||||||
);
|
);
|
||||||
|
utils::write_gui_db(
|
||||||
|
String::from("gui-txp-hash"),
|
||||||
|
String::from(&contact),
|
||||||
|
String::from(&ftxp.hash),
|
||||||
|
);
|
||||||
|
utils::write_gui_db(
|
||||||
|
String::from("gui-txp-sig"),
|
||||||
|
String::from(&contact),
|
||||||
|
String::from(&ftxp.signature),
|
||||||
|
);
|
||||||
|
utils::write_gui_db(
|
||||||
|
String::from("gui-txp-subaddress"),
|
||||||
|
String::from(&contact),
|
||||||
|
String::from(&ftxp.subaddress),
|
||||||
|
);
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"proving payment to {} for: {}",
|
"proving payment to {} for: {}",
|
||||||
String::from(&contact),
|
String::from(&contact),
|
||||||
&ftxp.hash
|
&ftxp.hash
|
||||||
);
|
);
|
||||||
monero::close_wallet(&wallet_name, &wallet_password).await;
|
|
||||||
// if we made it this far we can now request a JWP from our friend
|
|
||||||
// wait a bit for the tx to propogate
|
|
||||||
tokio::time::sleep(std::time::Duration::from_secs(
|
|
||||||
crate::BLOCK_TIME_IN_SECS_EST,
|
|
||||||
))
|
|
||||||
.await;
|
|
||||||
match proof::prove_payment(String::from(&contact), &ftxp).await {
|
match proof::prove_payment(String::from(&contact), &ftxp).await {
|
||||||
Ok(result) => {
|
Ok(result) => {
|
||||||
utils::write_gui_db(
|
utils::write_gui_db(
|
||||||
|
@ -721,6 +760,55 @@ fn send_payment_req(
|
||||||
}
|
}
|
||||||
_ => log::error!("failed to obtain jwp"),
|
_ => log::error!("failed to obtain jwp"),
|
||||||
}
|
}
|
||||||
|
monero::close_wallet(&wallet_name, &wallet_password).await;
|
||||||
|
// if we made it this far we can now request a JWP from our friend
|
||||||
|
// wait a bit for the tx to propogate
|
||||||
|
tokio::time::sleep(std::time::Duration::from_secs(
|
||||||
|
crate::BLOCK_TIME_IN_SECS_EST,
|
||||||
|
))
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
if retry {
|
||||||
|
let k_hash = String::from("gui-txp-hash");
|
||||||
|
let k_sig = String::from("gui-txp-sig");
|
||||||
|
let k_subaddress = String::from("gui-txp-subaddress");
|
||||||
|
let hash = utils::search_gui_db(k_hash, String::from(&contact));
|
||||||
|
let signature = utils::search_gui_db(k_sig, String::from(&contact));
|
||||||
|
let subaddress = utils::search_gui_db(k_subaddress, String::from(&contact));
|
||||||
|
let ftxp: proof::TxProof = proof::TxProof {
|
||||||
|
subaddress,
|
||||||
|
confirmations: 0,
|
||||||
|
hash: String::from(&hash),
|
||||||
|
message: utils::empty_string(),
|
||||||
|
signature,
|
||||||
|
};
|
||||||
|
log::debug!(
|
||||||
|
"proving payment to {} for: {}",
|
||||||
|
String::from(&contact),
|
||||||
|
&ftxp.hash
|
||||||
|
);
|
||||||
|
match proof::prove_payment(String::from(&contact), &ftxp).await {
|
||||||
|
Ok(result) => {
|
||||||
|
utils::write_gui_db(
|
||||||
|
String::from("gui-jwp"),
|
||||||
|
String::from(&contact),
|
||||||
|
String::from(&result.jwp),
|
||||||
|
);
|
||||||
|
// this is just an estimate expiration but should suffice
|
||||||
|
let seconds: i64 = expire as i64 * 2 * 60;
|
||||||
|
// subtract 120 seconds since we had to wait for one confirmation
|
||||||
|
let grace: i64 = seconds - BLOCK_TIME_IN_SECS_EST as i64;
|
||||||
|
let unix: i64 = chrono::offset::Utc::now().timestamp() + grace;
|
||||||
|
utils::write_gui_db(
|
||||||
|
String::from("gui-exp"),
|
||||||
|
String::from(&contact),
|
||||||
|
format!("{}", unix),
|
||||||
|
);
|
||||||
|
ctx.request_repaint();
|
||||||
|
}
|
||||||
|
_ => log::error!("failed to obtain jwp"),
|
||||||
|
}
|
||||||
|
}
|
||||||
let _ = tx.send(true);
|
let _ = tx.send(true);
|
||||||
ctx.request_repaint();
|
ctx.request_repaint();
|
||||||
});
|
});
|
||||||
|
|
|
@ -365,7 +365,6 @@ impl eframe::App for HomeApp {
|
||||||
self.s_xmr_rpc_ver.result.version, address, unlocked_balance, locked_balance,
|
self.s_xmr_rpc_ver.result.version, address, unlocked_balance, locked_balance,
|
||||||
unlock_time, xmrd_info.nettype, xmrd_info.top_block_hash, xmrd_info.height, xmrd_info.synchronized,
|
unlock_time, xmrd_info.nettype, xmrd_info.top_block_hash, xmrd_info.height, xmrd_info.synchronized,
|
||||||
db_size, free_space, xmrd_info.version));
|
db_size, free_space, xmrd_info.version));
|
||||||
// TODO(c2m): pull in more xmr blockchain information?
|
|
||||||
});
|
});
|
||||||
ui.label("____________________________________________________________________\n");
|
ui.label("____________________________________________________________________\n");
|
||||||
ui.label("\n");
|
ui.label("\n");
|
||||||
|
|
|
@ -5,9 +5,6 @@ use sha2::{
|
||||||
Sha512,
|
Sha512,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// TODO(c2m): Create a more secure locking mechanism
|
|
||||||
///
|
|
||||||
/// is there a way to trigger system screen lock on the machine???
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[cfg_attr(feature = "serde", serde(default))]
|
#[cfg_attr(feature = "serde", serde(default))]
|
||||||
|
|
Loading…
Reference in a new issue