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!: add payment id #6340

Merged
merged 13 commits into from
Jun 3, 2024
Merged
1 change: 1 addition & 0 deletions applications/minotari_app_grpc/proto/wallet.proto
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ message PaymentRecipient {
ONE_SIDED_TO_STEALTH_ADDRESS = 2;
}
PaymentType payment_type = 5;
bytes payment_id = 6;
}

message TransferResponse {
Expand Down
10 changes: 9 additions & 1 deletion applications/minotari_console_wallet/src/automation/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ use tari_comms::{
use tari_comms_dht::{envelope::NodeDestination, DhtDiscoveryRequester};
use tari_core::transactions::{
tari_amount::{uT, MicroMinotari, Minotari},
transaction_components::{OutputFeatures, TransactionOutput, WalletOutput},
transaction_components::{encrypted_data::PaymentId, OutputFeatures, TransactionOutput, WalletOutput},
};
use tari_crypto::ristretto::RistrettoSecretKey;
use tari_utilities::{hex::Hex, ByteArray};
Expand Down Expand Up @@ -232,6 +232,7 @@ pub async fn send_one_sided(
selection_criteria: UtxoSelectionCriteria,
dest_address: TariAddress,
message: String,
payment_id: PaymentId,
) -> Result<TxId, CommandError> {
wallet_transaction_service
.send_one_sided_transaction(
Expand All @@ -241,6 +242,7 @@ pub async fn send_one_sided(
OutputFeatures::default(),
fee_per_gram * uT,
message,
payment_id,
)
.await
.map_err(CommandError::TransactionServiceError)
Expand All @@ -253,6 +255,7 @@ pub async fn send_one_sided_to_stealth_address(
selection_criteria: UtxoSelectionCriteria,
dest_address: TariAddress,
message: String,
payment_id: PaymentId,
) -> Result<TxId, CommandError> {
wallet_transaction_service
.send_one_sided_to_stealth_address_transaction(
Expand All @@ -262,6 +265,7 @@ pub async fn send_one_sided_to_stealth_address(
OutputFeatures::default(),
fee_per_gram * uT,
message,
payment_id,
)
.await
.map_err(CommandError::TransactionServiceError)
Expand Down Expand Up @@ -452,6 +456,7 @@ pub async fn make_it_rain(
UtxoSelectionCriteria::default(),
address.clone(),
msg.clone(),
PaymentId::Empty,
)
.await
},
Expand All @@ -463,6 +468,7 @@ pub async fn make_it_rain(
UtxoSelectionCriteria::default(),
address.clone(),
msg.clone(),
PaymentId::Empty,
)
.await
},
Expand Down Expand Up @@ -725,6 +731,7 @@ pub async fn command_runner(
UtxoSelectionCriteria::default(),
args.destination,
args.message,
PaymentId::Empty,
)
.await
{
Expand All @@ -743,6 +750,7 @@ pub async fn command_runner(
UtxoSelectionCriteria::default(),
args.destination,
args.message,
PaymentId::Empty,
)
.await
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ use tari_core::{
transactions::{
tari_amount::{MicroMinotari, T},
transaction_components::{
encrypted_data::PaymentId,
CodeTemplateRegistration,
OutputFeatures,
OutputType,
Expand Down Expand Up @@ -503,13 +504,17 @@ impl wallet_server::Wallet for WalletGrpcServer {
dest.fee_per_gram,
dest.message,
dest.payment_type,
dest.payment_id,
))
})
.collect::<Result<Vec<_>, _>>()
.map_err(Status::invalid_argument)?;

let mut transfers = Vec::new();
for (hex_address, address, amount, fee_per_gram, message, payment_type) in recipients {
for (hex_address, address, amount, fee_per_gram, message, payment_type, payment_id) in recipients {
let payment_id = PaymentId::from_bytes(&payment_id)
.map_err(|_| "Invalid payment id".to_string())
.map_err(Status::invalid_argument)?;
let mut transaction_service = self.get_transaction_service();
transfers.push(async move {
(
Expand All @@ -534,6 +539,7 @@ impl wallet_server::Wallet for WalletGrpcServer {
OutputFeatures::default(),
fee_per_gram.into(),
message,
payment_id,
)
.await
} else {
Expand All @@ -545,6 +551,7 @@ impl wallet_server::Wallet for WalletGrpcServer {
OutputFeatures::default(),
fee_per_gram.into(),
message,
payment_id,
)
.await
},
Expand Down
38 changes: 36 additions & 2 deletions applications/minotari_console_wallet/src/ui/components/send_tab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub struct SendTab {
send_input_mode: SendInputMode,
show_contacts: bool,
to_field: String,
payment_id_field: String,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it might be good in future to include a drop down for "Custom Text", "Custom binary", "Sender Address"

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as well as some other options in future. Exchanges might want a specific field in here.

amount_field: String,
fee_field: String,
message_field: String,
Expand All @@ -49,6 +50,7 @@ impl SendTab {
send_input_mode: SendInputMode::None,
show_contacts: false,
to_field: String::new(),
payment_id_field: String::new(),
amount_field: String::new(),
fee_field: app_state.get_default_fee_per_gram().as_u64().to_string(),
message_field: String::new(),
Expand Down Expand Up @@ -104,6 +106,9 @@ impl SendTab {
Span::raw(" field, "),
Span::styled("C", Style::default().add_modifier(Modifier::BOLD)),
Span::raw(" to select a contact."),
Span::styled("P", Style::default().add_modifier(Modifier::BOLD)),
Span::raw(" to edit "),
Span::styled("Payment-id", Style::default().add_modifier(Modifier::BOLD)),
]),
Spans::from(vec![
Span::raw("Press "),
Expand Down Expand Up @@ -167,6 +172,14 @@ impl SendTab {
.block(Block::default().borders(Borders::ALL).title("(M)essage:"));
f.render_widget(message_input, vert_chunks[3]);

let payment_id_input = Paragraph::new(self.payment_id_field.as_ref())
.style(match self.send_input_mode {
SendInputMode::PaymentId => Style::default().fg(Color::Magenta),
_ => Style::default(),
})
.block(Block::default().borders(Borders::ALL).title("(P)ayment-id:"));
f.render_widget(payment_id_input, vert_chunks[4]);

match self.send_input_mode {
SendInputMode::None => (),
SendInputMode::To => f.set_cursor(
Expand Down Expand Up @@ -197,6 +210,12 @@ impl SendTab {
// Move one line down, from the border to the input line
vert_chunks[3].y + 1,
),
SendInputMode::PaymentId => f.set_cursor(
// Put cursor past the end of the input text
vert_chunks[4].x + self.payment_id_field.width() as u16 + 1,
// Move one line down, from the border to the input line
vert_chunks[4].y + 1,
),
}
}

Expand Down Expand Up @@ -275,6 +294,7 @@ impl SendTab {
UtxoSelectionCriteria::default(),
fee_per_gram,
self.message_field.clone(),
self.payment_id_field.clone(),
tx,
)) {
Err(e) => {
Expand All @@ -294,6 +314,7 @@ impl SendTab {
UtxoSelectionCriteria::default(),
fee_per_gram,
self.message_field.clone(),
self.payment_id_field.clone(),
tx,
),
) {
Expand Down Expand Up @@ -332,6 +353,7 @@ impl SendTab {
self.selected_unique_id = None;
self.fee_field = app_state.get_default_fee_per_gram().as_u64().to_string();
self.message_field = "".to_string();
self.payment_id_field = "".to_string();
self.send_input_mode = SendInputMode::None;
self.send_result_watch = Some(rx);
}
Expand Down Expand Up @@ -386,12 +408,19 @@ impl SendTab {
},
},
SendInputMode::Message => match c {
'\n' => self.send_input_mode = SendInputMode::None,
'\n' => self.send_input_mode = SendInputMode::PaymentId,
c => {
self.message_field.push(c);
return KeyHandled::Handled;
},
},
SendInputMode::PaymentId => match c {
'\n' => self.send_input_mode = SendInputMode::None,
c => {
self.payment_id_field.push(c);
return KeyHandled::Handled;
},
},
}
}

Expand Down Expand Up @@ -424,7 +453,7 @@ impl<B: Backend> Component<B> for SendTab {
.constraints(
[
Constraint::Length(3),
Constraint::Length(14),
Constraint::Length(17),
Constraint::Min(42),
Constraint::Length(1),
]
Expand Down Expand Up @@ -579,6 +608,7 @@ impl<B: Backend> Component<B> for SendTab {
},
'f' => self.send_input_mode = SendInputMode::Fee,
'm' => self.send_input_mode = SendInputMode::Message,
'p' => self.send_input_mode = SendInputMode::PaymentId,
's' | 'o' | 'x' => {
if self.to_field.is_empty() {
self.error_message =
Expand Down Expand Up @@ -651,6 +681,9 @@ impl<B: Backend> Component<B> for SendTab {
SendInputMode::Message => {
let _ = self.message_field.pop();
},
SendInputMode::PaymentId => {
let _ = self.payment_id_field.pop();
},
SendInputMode::None => {},
}
}
Expand All @@ -663,6 +696,7 @@ pub enum SendInputMode {
Amount,
Message,
Fee,
PaymentId,
}

#[derive(PartialEq, Debug)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use chrono::{DateTime, Local};
use log::*;
use minotari_wallet::transaction_service::storage::models::TxCancellationReason;
use tari_common_types::transaction::{TransactionDirection, TransactionStatus};
use tari_core::transactions::transaction_components::encrypted_data::PaymentId;
use tokio::runtime::Handle;
use tui::{
backend::Backend,
Expand Down Expand Up @@ -288,7 +289,7 @@ impl TransactionsTab {
.split(area);

// Labels
let constraints = [Constraint::Length(1); 14];
let constraints = [Constraint::Length(1); 15];
let label_layout = Layout::default().constraints(constraints).split(columns[0]);

let tx_id = Span::styled("TxID:", Style::default().fg(Color::Magenta));
Expand All @@ -305,6 +306,7 @@ impl TransactionsTab {
let confirmations = Span::styled("Confirmations:", Style::default().fg(Color::Magenta));
let mined_height = Span::styled("Mined Height:", Style::default().fg(Color::Magenta));
let maturity = Span::styled("Maturity:", Style::default().fg(Color::Magenta));
let payment_id = Span::styled("Payment Id:", Style::default().fg(Color::Magenta));

let trim = Wrap { trim: true };
let paragraph = Paragraph::new(tx_id).wrap(trim);
Expand Down Expand Up @@ -335,11 +337,13 @@ impl TransactionsTab {
f.render_widget(paragraph, label_layout[12]);
let paragraph = Paragraph::new(maturity).wrap(trim);
f.render_widget(paragraph, label_layout[13]);
let paragraph = Paragraph::new(payment_id).wrap(trim);
f.render_widget(paragraph, label_layout[14]);

// Content
let required_confirmations = app_state.get_required_confirmations();
if let Some(tx) = self.detailed_transaction.as_ref() {
let constraints = [Constraint::Length(1); 14];
let constraints = [Constraint::Length(1); 15];
let content_layout = Layout::default().constraints(constraints).split(columns[1]);
let tx_id = Span::styled(format!("{}", tx.tx_id), Style::default().fg(Color::White));

Expand Down Expand Up @@ -429,6 +433,20 @@ impl TransactionsTab {
};
let maturity = Span::styled(maturity, Style::default().fg(Color::White));

let payment_id = match tx.payment_id.clone() {
Some(v) => {
if let PaymentId::Open(bytes) = v {
String::from_utf8(bytes)
.unwrap_or_else(|_| "Invalid".to_string())
.to_string()
} else {
format!("#{}", v)
}
},
None => "None".to_string(),
};
let payment_id = Span::styled(payment_id, Style::default().fg(Color::White));

let paragraph = Paragraph::new(tx_id).wrap(trim);
f.render_widget(paragraph, content_layout[0]);
let paragraph = Paragraph::new(source_address).wrap(trim);
Expand Down Expand Up @@ -457,6 +475,8 @@ impl TransactionsTab {
f.render_widget(paragraph, content_layout[12]);
let paragraph = Paragraph::new(maturity).wrap(trim);
f.render_widget(paragraph, content_layout[13]);
let paragraph = Paragraph::new(payment_id).wrap(trim);
f.render_widget(paragraph, content_layout[14]);
}
}
}
Expand All @@ -469,7 +489,7 @@ impl<B: Backend> Component<B> for TransactionsTab {
Constraint::Length(3),
Constraint::Length(1),
Constraint::Min(9),
Constraint::Length(16),
Constraint::Length(17),
]
.as_ref(),
)
Expand Down
Loading
Loading