wallet + ui: sending and receiving rework, ability to use dandelion on broadcast, remove node restart modal, fix txs statuses

This commit is contained in:
ardocrat
2024-04-18 05:20:49 +03:00
parent fa71dc2ada
commit 7e2e08530b
15 changed files with 469 additions and 392 deletions
+5 -2
View File
@@ -36,7 +36,9 @@ pub struct WalletConfig {
/// External connection identifier.
pub ext_conn_id: Option<i64>,
/// Minimal amount of confirmations.
pub min_confirmations: u64
pub min_confirmations: u64,
/// Flag to use Dandelion to broadcast transactions.
pub use_dandelion: Option<bool>
}
/// Base wallets directory name.
@@ -69,7 +71,8 @@ impl WalletConfig {
ConnectionMethod::Integrated => None,
ConnectionMethod::External(id) => Some(*id)
},
min_confirmations: MIN_CONFIRMATIONS_DEFAULT
min_confirmations: MIN_CONFIRMATIONS_DEFAULT,
use_dandelion: Some(true),
};
Settings::write_to_file(&config, config_path);
config
+98 -64
View File
@@ -22,8 +22,8 @@ use std::sync::{Arc, mpsc, RwLock};
use std::sync::atomic::{AtomicBool, AtomicI64, AtomicU8, Ordering};
use std::thread::Thread;
use std::time::Duration;
use futures::channel::oneshot;
use grin_api::{ApiServer, Router};
use grin_chain::SyncStatus;
use grin_core::global;
@@ -35,7 +35,7 @@ use grin_wallet_controller::command::parse_slatepack;
use grin_wallet_controller::controller;
use grin_wallet_controller::controller::ForeignAPIHandlerV2;
use grin_wallet_impls::{DefaultLCProvider, DefaultWalletImpl, HTTPNodeClient};
use grin_wallet_libwallet::{Error, InitTxArgs, IssueInvoiceTxArgs, NodeClient, RetrieveTxQueryArgs, Slate, StatusMessage, TxLogEntry, TxLogEntryType, WalletInst, WalletLCProvider};
use grin_wallet_libwallet::{Error, InitTxArgs, IssueInvoiceTxArgs, NodeClient, Slate, SlatepackAddress, StatusMessage, TxLogEntry, TxLogEntryType, WalletInst, WalletLCProvider};
use grin_wallet_libwallet::api_impl::owner::{cancel_tx, retrieve_summary_info, retrieve_txs};
use crate::node::{Node, NodeConfig};
@@ -226,6 +226,13 @@ impl Wallet {
w_config.save();
}
/// Update usage of Dandelion to broadcast transactions.
pub fn update_use_dandelion(&self, use_dandelion: bool) {
let mut w_config = self.config.write().unwrap();
w_config.use_dandelion = Some(use_dandelion);
w_config.save();
}
/// Update minimal amount of confirmations.
pub fn update_min_confirmations(&self, min_confirmations: u64) {
let mut w_config = self.config.write().unwrap();
@@ -460,6 +467,19 @@ impl Wallet {
}
}
/// Parse Slatepack message into [`Slate`].
pub fn parse_slatepack(&self, message: String) -> Result<Slate, Error> {
let mut api = Owner::new(self.instance.clone().unwrap(), None);
return match parse_slatepack(&mut api, None, None, Some(message.clone())) {
Ok((slate, _)) => {
Ok(slate)
}
Err(_) => {
Err(Error::SlatepackDeser("Slatepack parse error".to_string()))
}
}
}
/// Create Slatepack message from provided slate.
fn create_slatepack_message(&self, slate: Slate) -> Result<String, Error> {
let mut message = "".to_string();
@@ -481,60 +501,33 @@ impl Wallet {
Ok(message)
}
/// Receive transaction via Slatepack message, return response to sender.
pub fn receive(&self, message: String) -> Result<String, Error> {
/// Initialize a transaction to send amount, return request for funds receiver.
pub fn send(&self, amount: u64) -> Result<String, Error> {
let config = self.get_config();
let args = InitTxArgs {
src_acct_name: Some(config.account),
amount,
minimum_confirmations: config.min_confirmations,
num_change_outputs: 1,
selection_strategy_is_use_all: false,
..Default::default()
};
let mut api = Owner::new(self.instance.clone().unwrap(), None);
match parse_slatepack(&mut api, None, None, Some(message.clone())) {
Ok((mut slate, _)) => {
let config = self.get_config();
controller::foreign_single_use(api.wallet_inst.clone(), None, |api| {
slate = api.receive_tx(&slate, Some(config.account.as_str()), None)?;
Ok(())
})?;
// Create Slatepack message response.
let response = self.create_slatepack_message(slate)?;
let slate = api.init_send_tx(None, args)?;
// Sync wallet info.
self.sync();
Ok(response)
}
Err(_) => {
Err(Error::GenericError("Parsing error".to_string()))
}
}
// Lock outputs to for this transaction.
api.tx_lock_outputs(None, &slate)?;
// Create Slatepack message response.
let response = self.create_slatepack_message(slate)?;
// Sync wallet info.
self.sync();
Ok(response)
}
/// S transaction via Slatepack message and return response to sender.
pub fn pay(&self, message: String) -> Result<String, Error> {
let mut api = Owner::new(self.instance.clone().unwrap(), None);
match parse_slatepack(&mut api, None, None, Some(message.clone())) {
Ok((mut slate, _)) => {
let config = self.get_config();
let args = InitTxArgs {
src_acct_name: None,
amount: slate.amount,
minimum_confirmations: config.min_confirmations,
selection_strategy_is_use_all: false,
..Default::default()
};
let mut api = Owner::new(self.instance.clone().unwrap(), None);
let slate = api.process_invoice_tx(None, &slate, args)?;
// Create Slatepack message response.
let response = self.create_slatepack_message(slate)?;
// Sync wallet info.
self.sync();
Ok(response)
}
Err(_) => {
Err(Error::GenericError("Parsing error".to_string()))
}
}
}
/// Initialize an invoice transaction.
/// Initialize an invoice transaction to receive amount, return request for funds sender.
pub fn issue_invoice(&self, amount: u64) -> Result<String, Error> {
let args = IssueInvoiceTxArgs {
dest_acct_name: None,
@@ -553,8 +546,57 @@ impl Wallet {
Ok(response)
}
pub fn send(&self) {
/// Handle message from the invoice issuer to send founds, return response for funds receiver.
pub fn pay(&self, message: String) -> Result<String, Error> {
let slate = self.parse_slatepack(message)?;
let config = self.get_config();
let args = InitTxArgs {
src_acct_name: None,
amount: slate.amount,
minimum_confirmations: config.min_confirmations,
selection_strategy_is_use_all: false,
..Default::default()
};
let mut api = Owner::new(self.instance.clone().unwrap(), None);
let slate = api.process_invoice_tx(None, &slate, args)?;
api.tx_lock_outputs(None, &slate)?;
// Create Slatepack message response.
let response = self.create_slatepack_message(slate)?;
// Sync wallet info.
self.sync();
Ok(response)
}
/// Handle message to receive funds, return response to sender.
pub fn receive(&self, message: String) -> Result<String, Error> {
let mut slate = self.parse_slatepack(message)?;
let mut api = Owner::new(self.instance.clone().unwrap(), None);
controller::foreign_single_use(api.wallet_inst.clone(), None, |api| {
slate = api.receive_tx(&slate, Some(self.get_config().account.as_str()), None)?;
Ok(())
})?;
// Create Slatepack message response.
let response = self.create_slatepack_message(slate)?;
// Sync wallet info.
self.sync();
Ok(response)
}
/// Finalize transaction from provided message as sender or invoice issuer with Dandelion.
pub fn finalize(&self, message: String, dandelion: bool) -> Result<Slate, Error> {
let mut slate = self.parse_slatepack(message)?;
let mut api = Owner::new(self.instance.clone().unwrap(), None);
slate = api.finalize_tx(None, &slate)?;
api.post_tx(None, &slate, dandelion)?;
// Sync wallet info.
self.sync();
Ok(slate)
}
/// Cancel transaction.
@@ -581,11 +623,6 @@ impl Wallet {
cancelling_r.contains(id)
}
/// Finalize transaction from provided Slatepack message.
pub fn finalize(&self) {
}
/// Change wallet password.
pub fn change_password(&self, old: String, new: String) -> Result<(), Error> {
let instance = self.instance.clone().unwrap();
@@ -889,6 +926,7 @@ fn sync_wallet_data(wallet: &Wallet) {
}).collect::<Vec<TxLogEntry>>();
// Update txs statuses.
for tx in &txs {
println!("{}", serde_json::to_string(tx).unwrap());
if tx.tx_type == TxLogEntryType::TxSentCancelled
|| tx.tx_type == TxLogEntryType::TxReceivedCancelled {
// Remove cancelling status.
@@ -903,15 +941,11 @@ fn sync_wallet_data(wallet: &Wallet) {
return;
}
}
Err(e) => {
println!("error on retrieve_txs {}", e);
}
Err(e) => println!("error on retrieve_txs {}", e),
}
}
}
Err(e) => {
println!("error on retrieve_summary_info {}", e);
}
Err(e) => println!("error on retrieve_summary_info {}", e),
}
}