Skip to content

Commit

Permalink
enable the Display command to display confidential transfer mint ex…
Browse files Browse the repository at this point in the history
…tension
  • Loading branch information
samkim-crypto committed Sep 24, 2023
1 parent 1cf22b9 commit f616231
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 13 deletions.
4 changes: 4 additions & 0 deletions token/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2162,6 +2162,9 @@ async fn command_display(config: &Config<'_>, address: Pubkey) -> CommandResult

let token_data = parse_token(&account_data.data, decimals);

// remove on next `solana-account-decoder` upgrade
let ui_confidential_transfer_extension = has_confidential_transfer(&account_data.data);

match token_data {
Ok(TokenAccountType::Account(account)) => {
let mint_address = Pubkey::from_str(&account.mint)?;
Expand Down Expand Up @@ -2189,6 +2192,7 @@ async fn command_display(config: &Config<'_>, address: Pubkey) -> CommandResult
epoch: epoch_info.epoch,
program_id: config.program_id.to_string(),
mint,
ui_confidential_transfer_extension,
};

Ok(config.output_format.formatted_string(&cli_output))
Expand Down
104 changes: 91 additions & 13 deletions token/cli/src/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ use solana_account_decoder::{
},
};
use solana_cli_output::{display::writeln_name_value, OutputFormat, QuietDisplay, VerboseDisplay};
use spl_token_2022::{
extension::{
confidential_transfer::ConfidentialTransferMint, BaseStateWithExtensions,
StateWithExtensions,
},
solana_program::pubkey::Pubkey,
solana_zk_token_sdk::zk_token_elgamal::pod::ElGamalPubkey,
state::Mint,
};
use std::fmt::{self, Display};

pub(crate) trait Output: Serialize + fmt::Display + QuietDisplay + VerboseDisplay {}
Expand Down Expand Up @@ -250,7 +259,7 @@ impl fmt::Display for CliTokenAccount {
if !self.account.extensions.is_empty() {
writeln!(f, "{}", style("Extensions:").bold())?;
for extension in &self.account.extensions {
display_ui_extension(f, 0, extension)?;
display_ui_extension(f, 0, extension, None)?;
}
}

Expand Down Expand Up @@ -288,6 +297,7 @@ pub(crate) struct CliMint {
pub(crate) epoch: u64,
#[serde(flatten)]
pub(crate) mint: UiMint,
pub(crate) ui_confidential_transfer_extension: Option<UiConfidentialTransferExtension>,
}

impl QuietDisplay for CliMint {}
Expand Down Expand Up @@ -319,7 +329,12 @@ impl fmt::Display for CliMint {
if !self.mint.extensions.is_empty() {
writeln!(f, "{}", style("Extensions").bold())?;
for extension in &self.mint.extensions {
display_ui_extension(f, self.epoch, extension)?;
display_ui_extension(
f,
self.epoch,
extension,
self.ui_confidential_transfer_extension.as_ref(),
)?;
}
}

Expand Down Expand Up @@ -547,6 +562,7 @@ fn display_ui_extension(
f: &mut fmt::Formatter,
epoch: u64,
ui_extension: &UiExtension,
ui_confidential_transfer_extension: Option<&UiConfidentialTransferExtension>,
) -> fmt::Result {
match ui_extension {
UiExtension::TransferFeeConfig(UiTransferFeeConfig {
Expand Down Expand Up @@ -683,21 +699,47 @@ fn display_ui_extension(
}
// ExtensionType::Uninitialized is a hack to ensure a mint/account is never the same length as a multisig
UiExtension::Uninitialized => Ok(()),
UiExtension::ConfidentialTransferMint(_) => writeln_name_value(
f,
" Unparseable extension:",
"ConfidentialTransferMint is not presently supported",
),
UiExtension::ConfidentialTransferAccount(_) => writeln_name_value(
f,
" Unparseable extension:",
" Confidential transfer:",
"ConfidentialTransferAccount is not presently supported",
),
_ => writeln_name_value(
f,
" Unparseable extension:",
"Consider upgrading to a newer version of spl-token",
),
_ => {
if let Some(ui_confidential_transfer_extension) = ui_confidential_transfer_extension {
match ui_confidential_transfer_extension {
UiConfidentialTransferExtension::ConfidentialTransferMint(ui_mint) => {
writeln!(f, " {}", style("Confidential transfer:").bold())?;
writeln!(
f,
" {}: {}",
style("Account approve policy").bold(),
if ui_mint.auto_approve_new_accounts {
"auto"
} else {
"manual"
},
)?;
writeln!(
f,
" {}: {}",
style("Audit key:").bold(),
if let Some(auditor_pubkey) = ui_mint.auditor_encryption_pubkey.as_ref()
{
auditor_pubkey
} else {
"audits are not enabled"
}
)
}
}
} else {
writeln_name_value(
f,
" Unparseable extension:",
"Consider upgrading to a newer version of spl-token",
)
}
}
}
}

Expand All @@ -708,3 +750,39 @@ fn flattened<S: Serializer>(
let flattened: Vec<_> = vec.iter().flatten().collect();
flattened.serialize(serializer)
}

#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
pub(crate) enum UiConfidentialTransferExtension {
ConfidentialTransferMint(UiConfidentialTransferMint),
// TODO: add `ConfidentialTransferAccount`
}

#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
pub(crate) struct UiConfidentialTransferMint {
pub authority: Option<String>,
pub auto_approve_new_accounts: bool,
pub auditor_encryption_pubkey: Option<String>,
}

pub(crate) fn has_confidential_transfer(data: &[u8]) -> Option<UiConfidentialTransferExtension> {
if let Ok(mint) = StateWithExtensions::<Mint>::unpack(data) {
if let Some(confidential_transfer_mint) =
mint.get_extension::<ConfidentialTransferMint>().ok()
{
let authority: Option<Pubkey> = confidential_transfer_mint.authority.into();
let auditor_encryption_pubkey: Option<ElGamalPubkey> =
confidential_transfer_mint.auditor_elgamal_pubkey.into();
return Some(UiConfidentialTransferExtension::ConfidentialTransferMint(
UiConfidentialTransferMint {
authority: authority.map(|pubkey| pubkey.to_string()),
auto_approve_new_accounts: confidential_transfer_mint
.auto_approve_new_accounts
.into(),
auditor_encryption_pubkey: auditor_encryption_pubkey
.map(|pubkey| pubkey.to_string()),
},
));
}
}
None
}

0 comments on commit f616231

Please sign in to comment.