slatepacks: better error handling and messages on parsing

This commit is contained in:
ardocrat 2024-04-20 23:49:19 +03:00
parent 95be986e0f
commit 10d184fab2
6 changed files with 112 additions and 64 deletions

View file

@ -77,8 +77,8 @@ wallets:
parse_s1_slatepack_desc: 'To receive %{amount} ツ send this message to the sender:' parse_s1_slatepack_desc: 'To receive %{amount} ツ send this message to the sender:'
parse_s2_slatepack_desc: 'Finalize transaction to send %{amount} ツ' parse_s2_slatepack_desc: 'Finalize transaction to send %{amount} ツ'
parse_s3_slatepack_desc: 'Post transaction to finalize sending of %{amount} ツ' parse_s3_slatepack_desc: 'Post transaction to finalize sending of %{amount} ツ'
response_slatepack_err: 'An error occurred during creation of the response, check input data:' resp_slatepack_err: 'An error occurred during creation of the response, check input data:'
response_exists_err: 'Such transaction already exists:' resp_exists_err: 'Such transaction already exists.'
create_request_desc: 'Create request to send or receive the funds:' create_request_desc: 'Create request to send or receive the funds:'
send_request_desc: 'You have created a request to send %{amount} ツ. Send this message to the receiver of funds:' send_request_desc: 'You have created a request to send %{amount} ツ. Send this message to the receiver of funds:'
send_slatepack_err: An error occurred during creation of request to send funds, check input data. send_slatepack_err: An error occurred during creation of request to send funds, check input data.

View file

@ -77,8 +77,8 @@ wallets:
parse_s1_slatepack_desc: 'Для получения %{amount} ツ отправьте это сообщение отправителю:' parse_s1_slatepack_desc: 'Для получения %{amount} ツ отправьте это сообщение отправителю:'
parse_s2_slatepack_desc: 'Завершите транзакцию для отправки %{amount} ツ' parse_s2_slatepack_desc: 'Завершите транзакцию для отправки %{amount} ツ'
parse_s3_slatepack_desc: 'Опубликуйте транзакцию для завершения отправки %{amount} ツ' parse_s3_slatepack_desc: 'Опубликуйте транзакцию для завершения отправки %{amount} ツ'
response_slatepack_err: 'Во время создания ответа произошла ошибка, проверьте входные данные:' resp_slatepack_err: 'Во время создания ответа произошла ошибка, проверьте входные данные:'
response_exists_err: 'Такая транзакция уже существует:' resp_exists_err: 'Такая транзакция уже существует.'
create_request_desc: 'Cоздать запрос на получение или отправку средств:' create_request_desc: 'Cоздать запрос на получение или отправку средств:'
send_request_desc: 'Вы создали запрос на отправку %{amount} ツ. Отправьте это сообщение получателю средств:' send_request_desc: 'Вы создали запрос на отправку %{amount} ツ. Отправьте это сообщение получателю средств:'
send_slatepack_err: Во время создания запроса на отправку средств произошла ошибка, проверьте входные данные. send_slatepack_err: Во время создания запроса на отправку средств произошла ошибка, проверьте входные данные.

View file

@ -191,10 +191,10 @@ impl WalletMessages {
if let Some(err) = &self.message_error { if let Some(err) = &self.message_error {
ui.label(RichText::new(err.text()).size(16.0).color(Colors::RED)); ui.label(RichText::new(err.text()).size(16.0).color(Colors::RED));
} else { } else {
let desc_text = if response_empty && self.message_slate.is_none() { let desc_text = if self.message_slate.is_none() {
t!("wallets.input_slatepack_desc") t!("wallets.input_slatepack_desc")
} else { } else {
let slate = self.message_slate.as_ref().unwrap(); let mut slate = self.message_slate.clone().unwrap();
let amount = amount_to_hr_string(slate.amount, true); let amount = amount_to_hr_string(slate.amount, true);
match slate.state { match slate.state {
SlateState::Standard1 => { SlateState::Standard1 => {
@ -386,51 +386,8 @@ impl WalletMessages {
} }
if let Ok(mut slate) = wallet.parse_slatepack(self.message_edit.clone()) { if let Ok(mut slate) = wallet.parse_slatepack(self.message_edit.clone()) {
println!("parse_message: {}", slate); println!("parse_message: {}", slate);
// Make operation based on incoming state status.
match slate.state {
SlateState::Standard1 => {
if let Ok(resp) = wallet.receive(self.message_edit.clone()) {
self.response_edit = resp;
} else {
// Check if tx with same slate id already exists.
let exists_tx = wallet.tx_by_slate(&slate).is_some();
if exists_tx {
return;
}
// Set default response error message. // Try to setup empty amount from transaction by id.
self.message_error = Some(
MessageError::Response(t!("wallets.response_slatepack_err"))
);
}
}
SlateState::Invoice1 => {
match wallet.pay(self.message_edit.clone()) {
Ok(resp) => {
self.response_edit = resp;
}
Err(err) => {
match err {
grin_wallet_libwallet::Error::NotEnoughFunds {..} => {
let amount = amount_to_hr_string(slate.amount, true);
let a_t = t!("wallets.pay_balance_error", "amount" => amount);
self.message_error = Some(MessageError::Other(a_t));
}
_ => {
self.message_error = Some(
MessageError::Response(t!("wallets.response_slatepack_err"))
);
}
}
}
}
}
_ => {
self.response_edit = "".to_string();
}
}
// Try to get amount from transaction by id.
if slate.amount == 0 { if slate.amount == 0 {
let _ = wallet.get_data().unwrap().txs.clone().iter().map(|tx| { let _ = wallet.get_data().unwrap().txs.clone().iter().map(|tx| {
if tx.data.tx_slate_id == Some(slate.id) { if tx.data.tx_slate_id == Some(slate.id) {
@ -441,10 +398,91 @@ impl WalletMessages {
tx tx
}).collect::<Vec<&WalletTransaction>>(); }).collect::<Vec<&WalletTransaction>>();
} }
self.message_slate = Some(slate.clone());
if slate.amount == 0 {
self.message_error = Some(
MessageError::Response(t!("wallets.resp_slatepack_err"))
);
return;
}
// Make operation based on incoming state status.
match slate.state {
SlateState::Standard1 | SlateState::Invoice1 => {
let resp = if slate.state == SlateState::Standard1 {
wallet.receive(self.message_edit.clone())
} else {
wallet.pay(self.message_edit.clone())
};
if resp.is_ok() {
self.response_edit = resp.unwrap();
} else {
// Check if tx with same slate id already exists.
let exists_tx = wallet.tx_by_slate(&slate).is_some();
if exists_tx {
let mut sl = slate.clone();
sl.state = if sl.state == SlateState::Standard1 {
SlateState::Standard2
} else {
SlateState::Invoice2
};
match wallet.read_slatepack(&sl) {
None => {
self.message_error = Some(
MessageError::Response(t!("wallets.resp_slatepack_err"))
);
}
Some(sp) => {
self.message_slate = Some(slate);
self.response_edit = sp;
}
}
return;
}
// Set default response error message.
self.message_error = Some(
MessageError::Response(t!("wallets.resp_slatepack_err"))
);
}
}
SlateState::Standard2 | SlateState::Invoice2 => {
// Check if slatepack with same id and state already exists.
let mut sl = slate.clone();
sl.state = if sl.state == SlateState::Standard2 {
SlateState::Standard1
} else {
SlateState::Invoice1
};
match wallet.read_slatepack(&sl) {
None => {
match wallet.read_slatepack(&slate) {
None => {
self.message_error = Some(
MessageError::Response(t!("wallets.resp_slatepack_err"))
);
}
Some(sp) => {
self.message_slate = Some(sl);
self.response_edit = sp;
return;
}
}
}
Some(_) => {
self.message_slate = Some(slate.clone());
return;
}
}
}
_ => {
self.response_edit = "".to_string();
}
}
self.message_slate = Some(slate);
} else { } else {
self.message_slate = None; self.message_slate = None;
self.message_error = Some(MessageError::Parse(t!("wallets.response_slatepack_err"))); self.message_error = Some(MessageError::Parse(t!("wallets.resp_slatepack_err")));
} }
} }

View file

@ -230,8 +230,9 @@ fn tx_item_ui(ui: &mut egui::Ui,
|| tx.data.tx_type == TxLogEntryType::TxReceivedCancelled; || tx.data.tx_type == TxLogEntryType::TxReceivedCancelled;
if is_canceled { if is_canceled {
format!("{} {}", X_CIRCLE, t!("wallets.tx_canceled")) format!("{} {}", X_CIRCLE, t!("wallets.tx_canceled"))
} else if tx.data.kernel_excess.is_some() && } else if tx.posting || (tx.data.kernel_excess.is_some() &&
tx.data.tx_type == TxLogEntryType::TxReceived { (tx.data.tx_type == TxLogEntryType::TxReceived ||
tx.data.tx_type == TxLogEntryType::TxSent)) {
format!("{} {}", DOTS_THREE_CIRCLE, t!("wallets.tx_finalizing")) format!("{} {}", DOTS_THREE_CIRCLE, t!("wallets.tx_finalizing"))
} else { } else {
match tx.data.tx_type { match tx.data.tx_type {
@ -253,7 +254,7 @@ fn tx_item_ui(ui: &mut egui::Ui,
format!("{} {}", CHECK_CIRCLE, t!("wallets.tx_confirmed")) format!("{} {}", CHECK_CIRCLE, t!("wallets.tx_confirmed"))
}, },
TxLogEntryType::TxSent | TxLogEntryType::TxReceived => { TxLogEntryType::TxSent | TxLogEntryType::TxReceived => {
if data.info.last_confirmed_height - tx_height > min_conf { if data.info.last_confirmed_height - tx_height > min_conf + 1 {
let text = if tx.data.tx_type == TxLogEntryType::TxSent { let text = if tx.data.tx_type == TxLogEntryType::TxSent {
t!("wallets.tx_sent") t!("wallets.tx_sent")
} else { } else {

View file

@ -17,7 +17,7 @@ use std::path::PathBuf;
use std::string::ToString; use std::string::ToString;
use grin_core::global::ChainTypes; use grin_core::global::ChainTypes;
use grin_wallet_libwallet::{SlateState}; use grin_wallet_libwallet::{Slate};
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use crate::{AppConfig, Settings}; use crate::{AppConfig, Settings};
@ -122,13 +122,13 @@ impl WalletConfig {
} }
/// Get Slatepacks data path for current wallet. /// Get Slatepacks data path for current wallet.
pub fn get_slatepack_path(&self, id: String, state: &SlateState) -> PathBuf { pub fn get_slatepack_path(&self, slate: &Slate) -> PathBuf {
let mut slatepack_dir = PathBuf::from(self.get_data_path()); let mut slatepack_dir = PathBuf::from(self.get_data_path());
slatepack_dir.push(SLATEPACKS_DIR_NAME); slatepack_dir.push(SLATEPACKS_DIR_NAME);
if !slatepack_dir.exists() { if !slatepack_dir.exists() {
let _ = fs::create_dir_all(slatepack_dir.clone()); let _ = fs::create_dir_all(slatepack_dir.clone());
} }
let slatepack_file_name = format!("{}.{}.slatepack", id, state); let slatepack_file_name = format!("{}.{}.slatepack", slate.id, slate.state);
slatepack_dir.push(slatepack_file_name); slatepack_dir.push(slatepack_file_name);
slatepack_dir slatepack_dir
} }

View file

@ -479,13 +479,22 @@ impl Wallet {
})?; })?;
// Save slatepack. // Save slatepack.
let slatepack_dir = self.get_config().get_slatepack_path(slate.id.to_string(), &slate.state); let slatepack_dir = self.get_config().get_slatepack_path(&slate);
let mut output = File::create(slatepack_dir)?; let mut output = File::create(slatepack_dir)?;
output.write_all(message.as_bytes())?; output.write_all(message.as_bytes())?;
output.sync_all()?; output.sync_all()?;
Ok(message) Ok(message)
} }
/// Read slatepack from file.
pub fn read_slatepack(&self, slate: &Slate) -> Option<String> {
let slatepack_path = self.get_config().get_slatepack_path(slate);
match fs::read_to_string(slatepack_path) {
Ok(s) => Some(s),
Err(_) => None
}
}
/// Get transaction by slate id. /// Get transaction by slate id.
pub fn tx_by_slate(&self, slate: &Slate) -> Option<WalletTransaction> { pub fn tx_by_slate(&self, slate: &Slate) -> Option<WalletTransaction> {
if let Some(data) = self.get_data() { if let Some(data) = self.get_data() {
@ -956,17 +965,17 @@ fn sync_wallet_data(wallet: &Wallet) {
tx.amount_credited - tx.amount_debited tx.amount_credited - tx.amount_debited
}; };
// Setup transaction broadcasting flag based on slate state. // Setup transaction posting flag based on slate state.
let posting = if (tx.tx_type == TxLogEntryType::TxSent || let posting = if (tx.tx_type == TxLogEntryType::TxSent ||
tx.tx_type == TxLogEntryType::TxReceived) && tx.tx_type == TxLogEntryType::TxReceived) &&
!tx.confirmed && tx.tx_slate_id.is_some() { !tx.confirmed && tx.tx_slate_id.is_some() {
let sl_id = tx.tx_slate_id.unwrap().to_string(); let mut slate = Slate::blank(1, false);
let state = match tx.tx_type { slate.id = tx.tx_slate_id.unwrap();
slate.state = match tx.tx_type {
TxLogEntryType::TxReceived => SlateState::Invoice3, TxLogEntryType::TxReceived => SlateState::Invoice3,
_ => SlateState::Standard3 _ => SlateState::Standard3
}; };
let slatepack_path = config.get_slatepack_path(sl_id, &state); wallet.read_slatepack(&slate).is_some()
fs::read_to_string(slatepack_path).is_ok()
} else { } else {
false false
}; };