Skip to content

Commit

Permalink
Add sending to stealth address (command, GRPC, gui).
Browse files Browse the repository at this point in the history
  • Loading branch information
Cifko committed Jul 18, 2022
1 parent c75d224 commit 8f76414
Show file tree
Hide file tree
Showing 11 changed files with 443 additions and 51 deletions.
1 change: 1 addition & 0 deletions applications/tari_app_grpc/proto/wallet.proto
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ message PaymentRecipient {
enum PaymentType {
STANDARD_MIMBLEWIMBLE = 0;
ONE_SIDED = 1;
ONE_SIDED_TO_STEALTH_ADDRESS = 2;
}
PaymentType payment_type = 5;
}
Expand Down
31 changes: 31 additions & 0 deletions applications/tari_console_wallet/src/automation/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,25 @@ pub async fn send_one_sided(
.map_err(CommandError::TransactionServiceError)
}

pub async fn send_one_sided_to_stealth_address(
mut wallet_transaction_service: TransactionServiceHandle,
fee_per_gram: u64,
amount: MicroTari,
dest_pubkey: PublicKey,
message: String,
) -> Result<TxId, CommandError> {
wallet_transaction_service
.send_one_sided_to_stealth_address_transaction(
dest_pubkey,
amount,
OutputFeatures::default(),
fee_per_gram * uT,
message,
)
.await
.map_err(CommandError::TransactionServiceError)
}

pub async fn coin_split(
amount_per_split: MicroTari,
num_splits: usize,
Expand Down Expand Up @@ -605,6 +624,18 @@ pub async fn command_runner(
debug!(target: LOG_TARGET, "send-one-sided tx_id {}", tx_id);
tx_ids.push(tx_id);
},
SendOneSidedToStealthAddress(args) => {
let tx_id = send_one_sided_to_stealth_address(
transaction_service.clone(),
config.fee_per_gram,
args.amount,
args.destination.into(),
args.message,
)
.await?;
debug!(target: LOG_TARGET, "send-one-sided-to-stealth-address tx_id {}", tx_id);
tx_ids.push(tx_id);
},
MakeItRain(args) => {
make_it_rain(
transaction_service.clone(),
Expand Down
1 change: 1 addition & 0 deletions applications/tari_console_wallet/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ pub enum CliCommands {
GetBalance,
SendTari(SendTariArgs),
SendOneSided(SendTariArgs),
SendOneSidedToStealthAddress(SendTariArgs),
MakeItRain(MakeItRainArgs),
CoinSplit(CoinSplitArgs),
DiscoverPeer(DiscoverPeerArgs),
Expand Down
19 changes: 19 additions & 0 deletions applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ impl wallet_server::Wallet for WalletGrpcServer {

let mut standard_transfers = Vec::new();
let mut one_sided_transfers = Vec::new();
let mut one_sided_transfers_to_stealth_address = Vec::new();
for (address, pk, amount, fee_per_gram, message, payment_type) in recipients {
let mut transaction_service = self.get_transaction_service();
if payment_type == PaymentType::StandardMimblewimble as i32 {
Expand Down Expand Up @@ -483,16 +484,34 @@ impl wallet_server::Wallet for WalletGrpcServer {
.await,
)
});
} else if payment_type == PaymentType::OneSidedToStealthAddress as i32 {
one_sided_transfers_to_stealth_address.push(async move {
(
address,
transaction_service
.send_one_sided_to_stealth_address_transaction(
pk,
amount.into(),
OutputFeatures::default(),
fee_per_gram.into(),
message,
)
.await,
)
});
} else {
}
}

let standard_results = future::join_all(standard_transfers).await;
let one_sided_results = future::join_all(one_sided_transfers).await;
let one_sided_transfers_to_stealth_address_results =
future::join_all(one_sided_transfers_to_stealth_address).await;

let results = standard_results
.into_iter()
.chain(one_sided_results.into_iter())
.chain(one_sided_transfers_to_stealth_address_results.into_iter())
.map(|(address, result)| match result {
Ok(tx_id) => TransferResult {
address,
Expand Down
140 changes: 90 additions & 50 deletions applications/tari_console_wallet/src/ui/components/send_tab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ impl SendTab {
Span::styled("S", Style::default().add_modifier(Modifier::BOLD)),
Span::raw(" to send a normal transaction, "),
Span::styled("O", Style::default().add_modifier(Modifier::BOLD)),
Span::raw(" to send a one-sided transaction."),
Span::raw(" to send a one-sided transaction, "),
Span::styled("X", Style::default().add_modifier(Modifier::BOLD)),
Span::raw(" to send a one-sided transaction to a stealth address."),
]),
])
.wrap(Wrap { trim: false })
Expand Down Expand Up @@ -276,11 +278,11 @@ impl SendTab {
self.confirmation_dialog = None;
return KeyHandled::Handled;
} else if 'y' == c {
let one_sided_transaction =
matches!(self.confirmation_dialog, Some(ConfirmationDialogType::OneSidedSend));
match self.confirmation_dialog {
None => (),
Some(ConfirmationDialogType::NormalSend) | Some(ConfirmationDialogType::OneSidedSend) => {
Some(ConfirmationDialogType::Normal) |
Some(ConfirmationDialogType::OneSided) |
Some(ConfirmationDialogType::StealthAddress) => {
if 'y' == c {
let amount = if let Ok(v) = self.amount_field.parse::<MicroTari>() {
v
Expand All @@ -304,42 +306,67 @@ impl SendTab {
let (tx, rx) = watch::channel(UiTransactionSendStatus::Initiated);

let mut reset_fields = false;
if one_sided_transaction {
match Handle::current().block_on(app_state.send_one_sided_transaction(
self.to_field.clone(),
amount.into(),
self.selected_unique_id.clone(),
None,
fee_per_gram,
self.message_field.clone(),
tx,
)) {
Err(e) => {
self.error_message = Some(format!(
"Error sending one-sided transaction:\n{}\nPress Enter to continue.",
e
))
},
Ok(_) => reset_fields = true,
}
} else {
match Handle::current().block_on(app_state.send_transaction(
self.to_field.clone(),
amount.into(),
self.selected_unique_id.clone(),
None,
fee_per_gram,
self.message_field.clone(),
tx,
)) {
Err(e) => {
self.error_message = Some(format!(
"Error sending normal transaction:\n{}\nPress Enter to continue.",
e
))
},
Ok(_) => reset_fields = true,
}
match self.confirmation_dialog {
Some(ConfirmationDialogType::OneSided) => {
match Handle::current().block_on(app_state.send_one_sided_transaction(
self.to_field.clone(),
amount.into(),
self.selected_unique_id.clone(),
None,
fee_per_gram,
self.message_field.clone(),
tx,
)) {
Err(e) => {
self.error_message = Some(format!(
"Error sending one-sided transaction:\n{}\nPress Enter to continue.",
e
))
},
Ok(_) => reset_fields = true,
}
},
Some(ConfirmationDialogType::StealthAddress) => {
match Handle::current().block_on(
app_state.send_one_sided_to_stealth_address_transaction(
self.to_field.clone(),
amount.into(),
self.selected_unique_id.clone(),
None,
fee_per_gram,
self.message_field.clone(),
tx,
),
) {
Err(e) => {
self.error_message = Some(format!(
"Error sending one-sided transaction to stealth address:\n{}\nPress \
Enter to continue.",
e
))
},
Ok(_) => reset_fields = true,
}
},
_ => {
match Handle::current().block_on(app_state.send_transaction(
self.to_field.clone(),
amount.into(),
self.selected_unique_id.clone(),
None,
fee_per_gram,
self.message_field.clone(),
tx,
)) {
Err(e) => {
self.error_message = Some(format!(
"Error sending normal transaction:\n{}\nPress Enter to continue.",
e
))
},
Ok(_) => reset_fields = true,
}
},
}
if reset_fields {
self.to_field = "".to_string();
Expand Down Expand Up @@ -511,7 +538,7 @@ impl<B: Backend> Component<B> for SendTab {

match self.confirmation_dialog {
None => (),
Some(ConfirmationDialogType::NormalSend) => {
Some(ConfirmationDialogType::Normal) => {
draw_dialog(
f,
area,
Expand All @@ -522,7 +549,7 @@ impl<B: Backend> Component<B> for SendTab {
9,
);
},
Some(ConfirmationDialogType::OneSidedSend) => {
Some(ConfirmationDialogType::OneSided) => {
draw_dialog(
f,
area,
Expand All @@ -533,6 +560,18 @@ impl<B: Backend> Component<B> for SendTab {
9,
);
},
Some(ConfirmationDialogType::StealthAddress) => {
draw_dialog(
f,
area,
"Confirm Sending Transaction".to_string(),
"Are you sure you want to send this one-sided transaction to a stealth address?\n(Y)es / (N)o"
.to_string(),
Color::Red,
120,
9,
);
},
}
}

Expand Down Expand Up @@ -584,7 +623,7 @@ impl<B: Backend> Component<B> for SendTab {
},
'f' => self.send_input_mode = SendInputMode::Fee,
'm' => self.send_input_mode = SendInputMode::Message,
's' | 'o' => {
's' | 'o' | 'x' => {
if self.to_field.is_empty() {
self.error_message = Some("Destination Public Key/Emoji ID\nPress Enter to continue.".to_string());
return;
Expand All @@ -599,11 +638,11 @@ impl<B: Backend> Component<B> for SendTab {
return;
}

if matches!(c, 'o') {
self.confirmation_dialog = Some(ConfirmationDialogType::OneSidedSend);
} else {
self.confirmation_dialog = Some(ConfirmationDialogType::NormalSend);
}
self.confirmation_dialog = Some(match c {
'o' => ConfirmationDialogType::OneSided,
'x' => ConfirmationDialogType::StealthAddress,
_ => ConfirmationDialogType::Normal,
});
},
_ => {},
}
Expand Down Expand Up @@ -690,6 +729,7 @@ pub enum SendInputMode {

#[derive(PartialEq, Debug)]
pub enum ConfirmationDialogType {
NormalSend,
OneSidedSend,
Normal,
OneSided,
StealthAddress,
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::collections::HashMap;
use chrono::{DateTime, Local};
use log::*;
use tari_common_types::transaction::{TransactionDirection, TransactionStatus};
use tari_comms::types::CommsPublicKey;
use tari_wallet::transaction_service::storage::models::TxCancellationReason;
use tokio::runtime::Handle;
use tui::{
Expand Down Expand Up @@ -224,7 +225,11 @@ impl TransactionsTab {
column1_items.push(ListItem::new(Span::styled(amount, amount_style)));
} else {
column0_items.push(ListItem::new(Span::styled(
app_state.get_alias(&t.source_public_key),
if t.source_public_key == CommsPublicKey::default() {
"Imported one sided Tx".to_string()
} else {
app_state.get_alias(&t.source_public_key)
},
Style::default().fg(text_color),
)));
let color = match (t.cancelled.is_some(), chain_height) {
Expand Down
38 changes: 38 additions & 0 deletions applications/tari_console_wallet/src/ui/state/app_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ use tokio::{
task,
};

use super::tasks::send_one_sided_to_stealth_address_transaction;
use crate::{
notifier::Notifier,
ui::{
Expand Down Expand Up @@ -367,6 +368,43 @@ impl AppState {
Ok(())
}

pub async fn send_one_sided_to_stealth_address_transaction(
&mut self,
dest_pubkey: String,
amount: u64,
unique_id: Option<Vec<u8>>,
parent_public_key: Option<PublicKey>,
fee_per_gram: u64,
message: String,
result_tx: watch::Sender<UiTransactionSendStatus>,
) -> Result<(), UiError> {
let inner = self.inner.write().await;
let dest_pubkey = match CommsPublicKey::from_hex(dest_pubkey.as_str()) {
Ok(pk) => pk,
Err(_) => EmojiId::str_to_pubkey(dest_pubkey.as_str()).map_err(|_| UiError::PublicKeyParseError)?,
};

let output_features = OutputFeatures {
unique_id,
parent_public_key,
..Default::default()
};

let fee_per_gram = fee_per_gram * uT;
let tx_service_handle = inner.wallet.transaction_service.clone();
tokio::spawn(send_one_sided_to_stealth_address_transaction(
dest_pubkey,
MicroTari::from(amount),
output_features,
message,
fee_per_gram,
tx_service_handle,
result_tx,
));

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 Down
Loading

0 comments on commit 8f76414

Please sign in to comment.