Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added burn feature to the console wallet #5322

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions applications/tari_console_wallet/src/ui/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use crate::{
ui::{
components::{
base_node::BaseNode,
burn_tab::BurnTab,
contacts_tab::ContactsTab,
events_component::EventsComponent,
log_tab::LogTab,
Expand Down Expand Up @@ -88,6 +89,7 @@ impl<B: Backend> App<B> {
.add("Transactions".into(), Box::new(TransactionsTab::new()))
.add("Send".into(), Box::new(SendTab::new(&app_state)))
.add("Receive".into(), Box::new(ReceiveTab::new()))
.add("Burn".into(), Box::new(BurnTab::new(&app_state)))
.add("Contacts".into(), Box::new(ContactsTab::new()))
.add("Network".into(), Box::new(NetworkTab::new(base_node_selected)))
.add("Events".into(), Box::new(EventsComponent::new()))
Expand Down
691 changes: 691 additions & 0 deletions applications/tari_console_wallet/src/ui/components/burn_tab.rs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ use crate::{
ui::{
components::{Component, KeyHandled},
state::AppState,
ui_contact::UiContact,
widgets::{centered_rect_absolute, draw_dialog, MultiColumnList, WindowedListState},
UiContact,
MAX_WIDTH,
},
utils::formatting::display_compressed_string,
Expand Down
1 change: 1 addition & 0 deletions applications/tari_console_wallet/src/ui/components/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ mod styles;
pub mod tabs_container;
pub mod transactions_tab;
pub use self::component::*;
pub mod burn_tab;
pub mod contacts_tab;
pub mod events_component;

Expand Down
7 changes: 5 additions & 2 deletions applications/tari_console_wallet/src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ use crate::utils::crossterm_events::CrosstermEvents;
mod app;
mod components;
pub mod state;
mod ui_burnt_proof;
mod ui_contact;
mod ui_error;
mod widgets;

use std::io::{stdout, Stdout};

pub use app::*;
Expand All @@ -43,8 +45,7 @@ use crossterm::{
use log::*;
use tokio::runtime::Handle;
use tui::{backend::CrosstermBackend, Terminal};
pub use ui_contact::*;
pub use ui_error::*;
use ui_error::UiError;

use crate::utils::events::{Event, EventStream};

Expand All @@ -58,6 +59,8 @@ pub fn run(app: App<CrosstermBackend<Stdout>>) -> Result<(), ExitError> {
app.app_state.refresh_transaction_state().await?;
trace!(target: LOG_TARGET, "Refreshing contacts state");
app.app_state.refresh_contacts_state().await?;
trace!(target: LOG_TARGET, "Refreshing burnt proofs state");
app.app_state.refresh_burnt_proofs_state().await?;
trace!(target: LOG_TARGET, "Refreshing connected peers state");
app.app_state.refresh_connected_peers_state().await?;
trace!(target: LOG_TARGET, "Checking connectivity");
Expand Down
129 changes: 126 additions & 3 deletions applications/tari_console_wallet/src/ui/state/app_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

use std::{
collections::{HashMap, VecDeque},
path::PathBuf,
sync::Arc,
time::{Duration, Instant},
};
Expand Down Expand Up @@ -73,11 +74,12 @@ use crate::{
ui::{
state::{
debouncer::BalanceEnquiryDebouncer,
tasks::{send_one_sided_transaction_task, send_transaction_task},
tasks::{send_burn_transaction_task, send_one_sided_transaction_task, send_transaction_task},
wallet_event_monitor::WalletEventMonitor,
},
UiContact,
UiError,
ui_burnt_proof::UiBurntProof,
ui_contact::UiContact,
ui_error::UiError,
},
utils::db::{CUSTOM_BASE_NODE_ADDRESS_KEY, CUSTOM_BASE_NODE_PUBLIC_KEY_KEY},
wallet_modes::PeerConfig,
Expand Down Expand Up @@ -164,6 +166,14 @@ impl AppState {
Ok(())
}

pub async fn refresh_burnt_proofs_state(&mut self) -> Result<(), UiError> {
let mut inner = self.inner.write().await;
inner.refresh_burnt_proofs_state().await?;
drop(inner);
self.update_cache().await;
Ok(())
}

pub async fn refresh_connected_peers_state(&mut self) -> Result<(), UiError> {
self.check_connectivity().await;
let mut inner = self.inner.write().await;
Expand Down Expand Up @@ -259,6 +269,22 @@ impl AppState {
Ok(())
}

pub async fn delete_burnt_proof(&mut self, proof_id: u32) -> Result<(), UiError> {
let mut inner = self.inner.write().await;

inner
.wallet
.db
.delete_burnt_proof(proof_id)
.map_err(UiError::WalletStorageError)?;

inner.refresh_burnt_proofs_state().await?;
drop(inner);
self.update_cache().await;

Ok(())
}

pub async fn send_transaction(
&mut self,
address: String,
Expand Down Expand Up @@ -360,6 +386,57 @@ impl AppState {
Ok(())
}

pub async fn send_burn_transaction(
&mut self,
burn_proof_filepath: Option<String>,
claim_public_key: Option<String>,
amount: u64,
selection_criteria: UtxoSelectionCriteria,
fee_per_gram: u64,
message: String,
result_tx: watch::Sender<UiTransactionBurnStatus>,
) -> Result<(), UiError> {
let inner = self.inner.write().await;

let burn_proof_filepath = match burn_proof_filepath {
None => None,
Some(path) => {
let path = PathBuf::from(path);

if path.exists() {
return Err(UiError::BurntProofFileExists);
}

Some(path)
},
};

let fee_per_gram = fee_per_gram * uT;
let tx_service_handle = inner.wallet.transaction_service.clone();
let claim_public_key = match claim_public_key {
None => return Err(UiError::PublicKeyParseError),
Some(claim_public_key) => match PublicKey::from_hex(claim_public_key.as_str()) {
Ok(claim_public_key) => Some(claim_public_key),
Err(_) => return Err(UiError::PublicKeyParseError),
},
};

send_burn_transaction_task(
burn_proof_filepath,
claim_public_key,
MicroTari::from(amount),
selection_criteria,
message,
fee_per_gram,
tx_service_handle,
inner.wallet.db.clone(),
result_tx,
)
.await;

Ok(())
}

pub async fn cancel_transaction(&mut self, tx_id: TxId) -> Result<(), UiError> {
let inner = self.inner.write().await;
let mut tx_service_handle = inner.wallet.transaction_service.clone();
Expand All @@ -385,6 +462,14 @@ impl AppState {
&self.cached_data.my_identity
}

pub fn get_burnt_proofs(&self) -> &[UiBurntProof] {
self.cached_data.burnt_proofs.as_slice()
}

pub fn get_burnt_proof_by_index(&self, idx: usize) -> Option<&UiBurntProof> {
self.cached_data.burnt_proofs.get(idx)
}

pub fn get_contacts(&self) -> &[UiContact] {
self.cached_data.contacts.as_slice()
}
Expand All @@ -405,6 +490,14 @@ impl AppState {
&self.cached_data.contacts[start..end]
}

pub fn get_burnt_proofs_slice(&self, start: usize, end: usize) -> &[UiBurntProof] {
if self.cached_data.burnt_proofs.is_empty() || start >= end {
return &[];
}

&self.cached_data.burnt_proofs[start..end]
}

pub fn get_pending_txs(&self) -> &Vec<CompletedTransactionInfo> {
&self.cached_data.pending_txs
}
Expand Down Expand Up @@ -779,6 +872,27 @@ impl AppStateInner {
Ok(())
}

pub async fn refresh_burnt_proofs_state(&mut self) -> Result<(), UiError> {
// let db_burnt_proofs = self.wallet.db.get_burnt_proofs()?;
let db_burnt_proofs = self.wallet.db.fetch_burnt_proofs()?;
let mut ui_proofs: Vec<UiBurntProof> = vec![];

for proof in db_burnt_proofs {
ui_proofs.push(UiBurntProof {
id: proof.0,
reciprocal_claim_public_key: proof.1,
payload: proof.2,
burned_at: proof.3,
});
}

ui_proofs.sort_by(|a, b| a.burned_at.cmp(&b.burned_at));

self.data.burnt_proofs = ui_proofs;
self.updated = true;
Ok(())
}

pub async fn refresh_connected_peers_state(&mut self) -> Result<(), UiError> {
let connections = self.wallet.comms.connectivity().get_active_connections().await?;
let peer_manager = self.wallet.comms.peer_manager();
Expand Down Expand Up @@ -1063,6 +1177,7 @@ struct AppStateData {
confirmations: HashMap<TxId, u64>,
my_identity: MyIdentity,
contacts: Vec<UiContact>,
burnt_proofs: Vec<UiBurntProof>,
connected_peers: Vec<Peer>,
balance: Balance,
base_node_state: BaseNodeState,
Expand Down Expand Up @@ -1137,6 +1252,7 @@ impl AppStateData {
confirmations: HashMap::new(),
my_identity: identity,
contacts: Vec::new(),
burnt_proofs: vec![],
connected_peers: Vec::new(),
balance: Balance::zero(),
base_node_state: BaseNodeState::default(),
Expand Down Expand Up @@ -1171,6 +1287,13 @@ pub enum UiTransactionSendStatus {
Error(String),
}

#[derive(Clone, Debug)]
pub enum UiTransactionBurnStatus {
Initiated,
TransactionComplete((u32, String, String)),
Error(String),
}

bitflags! {
pub struct TransactionFilter: u8 {
const NONE = 0b0000_0000;
Expand Down
24 changes: 24 additions & 0 deletions applications/tari_console_wallet/src/ui/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,28 @@ mod debouncer;
mod tasks;
mod wallet_event_monitor;

use serde::{Deserialize, Serialize};
use tari_common_types::serializers;

pub use self::app_state::*;

#[derive(Serialize, Deserialize)]
pub struct CommitmentSignatureBase64 {
#[serde(with = "serializers::base64")]
pub public_nonce: Vec<u8>,
#[serde(with = "serializers::base64")]
pub u: Vec<u8>,
#[serde(with = "serializers::base64")]
pub v: Vec<u8>,
}

#[derive(Serialize, Deserialize)]
pub struct BurntProofBase64 {
#[serde(with = "serializers::base64")]
pub reciprocal_claim_public_key: Vec<u8>,
#[serde(with = "serializers::base64")]
pub commitment: Vec<u8>,
pub ownership_proof: Option<CommitmentSignatureBase64>,
#[serde(with = "serializers::base64")]
pub range_proof: Vec<u8>,
}
Loading