addressed comments

This commit is contained in:
Marvin Jones 2026-05-28 16:58:03 -04:00
parent bfec9fcc77
commit be4b910a28
16 changed files with 244 additions and 510 deletions

View File

@ -8,7 +8,7 @@ use std::{
use nssa::AccountId; use nssa::AccountId;
use wallet::{ use wallet::{
account::AccountIdWithPrivacy, cli::CliAccountMention, account::AccountIdWithPrivacy, cli::CliAccountMention,
program_facades::native_token_transfer::NativeTokenTransfer, program_facades::native_token_transfer::NativeTokenTransfer, AccountIdentity,
}; };
use crate::{ use crate::{
@ -86,15 +86,10 @@ pub unsafe extern "C" fn wallet_ffi_transfer_public(
let transfer = NativeTokenTransfer(&wallet); let transfer = NativeTokenTransfer(&wallet);
let from_mention = CliAccountMention::Id(AccountIdWithPrivacy::Public(from_id));
let to_mention = CliAccountMention::Id(AccountIdWithPrivacy::Public(to_id));
match block_on(transfer.send_public_transfer( match block_on(transfer.send_public_transfer(
from_id, AccountIdentity::Public(from_id),
to_id, AccountIdentity::Public(to_id),
amount, amount,
&from_mention,
&to_mention,
)) { )) {
Ok(tx_hash) => { Ok(tx_hash) => {
let tx_hash = CString::new(tx_hash.to_string()) let tx_hash = CString::new(tx_hash.to_string())
@ -196,12 +191,11 @@ pub unsafe extern "C" fn wallet_ffi_transfer_shielded(
let transfer = NativeTokenTransfer(&wallet); let transfer = NativeTokenTransfer(&wallet);
match block_on(transfer.send_shielded_transfer_to_outer_account( match block_on(transfer.send_shielded_transfer_to_outer_account(
from_id, from_mention.into_public_identity(from_id),
to_npk, to_npk,
to_vpk, to_vpk,
to_identifier, to_identifier,
amount, amount,
&from_mention,
)) { )) {
Ok((tx_hash, _shared_key)) => { Ok((tx_hash, _shared_key)) => {
let tx_hash = CString::new(tx_hash.to_string()) let tx_hash = CString::new(tx_hash.to_string())
@ -469,7 +463,11 @@ pub unsafe extern "C" fn wallet_ffi_transfer_shielded_owned(
let transfer = NativeTokenTransfer(&wallet); let transfer = NativeTokenTransfer(&wallet);
match block_on(transfer.send_shielded_transfer(from_id, to_id, amount, &from_mention)) { match block_on(transfer.send_shielded_transfer(
from_mention.into_public_identity(from_id),
to_id,
amount,
)) {
Ok((tx_hash, _shared_key)) => { Ok((tx_hash, _shared_key)) => {
let tx_hash = CString::new(tx_hash.to_string()) let tx_hash = CString::new(tx_hash.to_string())
.map_or(ptr::null_mut(), std::ffi::CString::into_raw); .map_or(ptr::null_mut(), std::ffi::CString::into_raw);
@ -622,9 +620,7 @@ pub unsafe extern "C" fn wallet_ffi_register_public_account(
let transfer = NativeTokenTransfer(&wallet); let transfer = NativeTokenTransfer(&wallet);
let mention = CliAccountMention::Id(AccountIdWithPrivacy::Public(account_id)); match block_on(transfer.register_account(AccountIdentity::Public(account_id))) {
match block_on(transfer.register_account(account_id, &mention)) {
Ok(tx_hash) => { Ok(tx_hash) => {
let tx_hash = CString::new(tx_hash.to_string()) let tx_hash = CString::new(tx_hash.to_string())
.map_or(ptr::null_mut(), std::ffi::CString::into_raw); .map_or(ptr::null_mut(), std::ffi::CString::into_raw);

View File

@ -47,6 +47,8 @@ url.workspace = true
derive_more = { workspace = true, features = ["display"] } derive_more = { workspace = true, features = ["display"] }
[features] [features]
# Enables `keycard get-private-keys` command that prints sensitive secret keys to terminal.
# Never enable in production builds.
keycard-debug = [] keycard-debug = []
[dev-dependencies] [dev-dependencies]

View File

@ -11,7 +11,7 @@ use nssa_core::{
use crate::{ExecutionFailureKind, WalletCore}; use crate::{ExecutionFailureKind, WalletCore};
#[derive(Clone)] #[derive(Clone, Debug)]
pub enum AccountIdentity { pub enum AccountIdentity {
Public(AccountId), Public(AccountId),
/// A public account without signing. Would not try to sign, even if account is owned. /// A public account without signing. Would not try to sign, even if account is owned.
@ -69,6 +69,22 @@ impl AccountIdentity {
) )
} }
/// Returns the `AccountId` for public variants. Used by facades that need the raw ID
/// for derived-address computation alongside the identity.
#[must_use]
pub const fn public_account_id(&self) -> Option<nssa::AccountId> {
match self {
Self::Public(id) | Self::PublicNoSign(id) => Some(*id),
Self::PublicKeycard { account_id, .. } => Some(*account_id),
Self::PrivateOwned(_)
| Self::PrivateForeign { .. }
| Self::PrivatePdaOwned(_)
| Self::PrivatePdaForeign { .. }
| Self::PrivateShared { .. }
| Self::PrivatePdaShared { .. } => None,
}
}
#[must_use] #[must_use]
pub const fn is_private(&self) -> bool { pub const fn is_private(&self) -> bool {
matches!( matches!(
@ -384,19 +400,14 @@ impl AccountManager {
}) })
.collect(); .collect();
let keycard_paths = self let keycard_paths: Vec<&str> = self
.states .states
.iter() .iter()
.fold(vec![], |mut acc, state| match state { .filter_map(|state| match state {
State::Private(_) | State::Public { .. } => acc, State::PublicKeycard { key_path, .. } => Some(key_path.as_str()),
State::PublicKeycard { State::Private(_) | State::Public { .. } => None,
account: _, })
key_path, .collect();
} => {
acc.push(key_path.as_str());
acc
}
});
if let Some(pin) = self.pin.clone() { if let Some(pin) = self.pin.clone() {
pyo3::Python::with_gil(|py| -> pyo3::PyResult<()> { pyo3::Python::with_gil(|py| -> pyo3::PyResult<()> {

View File

@ -155,6 +155,17 @@ impl CliAccountMention {
Self::Id(_) | Self::Label(_) => None, Self::Id(_) | Self::Label(_) => None,
} }
} }
#[must_use]
pub fn into_public_identity(self, account_id: nssa::AccountId) -> crate::AccountIdentity {
match self {
Self::KeyPath(key_path) => crate::AccountIdentity::PublicKeycard {
account_id,
key_path,
},
Self::Id(_) | Self::Label(_) => crate::AccountIdentity::Public(account_id),
}
}
} }
impl FromStr for CliAccountMention { impl FromStr for CliAccountMention {

View File

@ -142,14 +142,11 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand {
) => { ) => {
let tx_hash = Amm(wallet_core) let tx_hash = Amm(wallet_core)
.send_new_definition( .send_new_definition(
a, user_holding_a.into_public_identity(a),
b, user_holding_b.into_public_identity(b),
lp, user_holding_lp.into_public_identity(lp),
balance_a, balance_a,
balance_b, balance_b,
&user_holding_a,
&user_holding_b,
&user_holding_lp,
) )
.await?; .await?;
println!("Transaction hash is {tx_hash}"); println!("Transaction hash is {tx_hash}");
@ -177,13 +174,11 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand {
(AccountIdWithPrivacy::Public(a), AccountIdWithPrivacy::Public(b)) => { (AccountIdWithPrivacy::Public(a), AccountIdWithPrivacy::Public(b)) => {
let tx_hash = Amm(wallet_core) let tx_hash = Amm(wallet_core)
.send_swap_exact_input( .send_swap_exact_input(
a, user_holding_a.into_public_identity(a),
b, user_holding_b.into_public_identity(b),
amount_in, amount_in,
min_amount_out, min_amount_out,
token_definition, token_definition,
&user_holding_a,
&user_holding_b,
) )
.await?; .await?;
println!("Transaction hash is {tx_hash}"); println!("Transaction hash is {tx_hash}");
@ -211,13 +206,11 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand {
(AccountIdWithPrivacy::Public(a), AccountIdWithPrivacy::Public(b)) => { (AccountIdWithPrivacy::Public(a), AccountIdWithPrivacy::Public(b)) => {
let tx_hash = Amm(wallet_core) let tx_hash = Amm(wallet_core)
.send_swap_exact_output( .send_swap_exact_output(
a, user_holding_a.into_public_identity(a),
b, user_holding_b.into_public_identity(b),
exact_amount_out, exact_amount_out,
max_amount_in, max_amount_in,
token_definition, token_definition,
&user_holding_a,
&user_holding_b,
) )
.await?; .await?;
println!("Transaction hash is {tx_hash}"); println!("Transaction hash is {tx_hash}");
@ -251,15 +244,12 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand {
) => { ) => {
let tx_hash = Amm(wallet_core) let tx_hash = Amm(wallet_core)
.send_add_liquidity( .send_add_liquidity(
a, user_holding_a.into_public_identity(a),
b, user_holding_b.into_public_identity(b),
lp, user_holding_lp.into_public_identity(lp),
min_amount_lp, min_amount_lp,
max_amount_a, max_amount_a,
max_amount_b, max_amount_b,
&user_holding_a,
&user_holding_b,
&user_holding_lp,
) )
.await?; .await?;
println!("Transaction hash is {tx_hash}"); println!("Transaction hash is {tx_hash}");
@ -295,11 +285,10 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand {
.send_remove_liquidity( .send_remove_liquidity(
a, a,
b, b,
lp, user_holding_lp.into_public_identity(lp),
balance_lp, balance_lp,
min_amount_a, min_amount_a,
min_amount_b, min_amount_b,
&user_holding_lp,
) )
.await?; .await?;
println!("Transaction hash is {tx_hash}"); println!("Transaction hash is {tx_hash}");

View File

@ -97,7 +97,7 @@ impl WalletSubcommand for AtaSubcommand {
match owner_resolved { match owner_resolved {
AccountIdWithPrivacy::Public(owner_id) => { AccountIdWithPrivacy::Public(owner_id) => {
let tx_hash = Ata(wallet_core) let tx_hash = Ata(wallet_core)
.send_create(owner_id, definition_id, &owner) .send_create(owner.into_public_identity(owner_id), definition_id)
.await?; .await?;
println!("Transaction hash is {tx_hash}"); println!("Transaction hash is {tx_hash}");
let transfer_tx = wallet_core.poll_native_token_transfer(tx_hash).await?; let transfer_tx = wallet_core.poll_native_token_transfer(tx_hash).await?;
@ -138,7 +138,12 @@ impl WalletSubcommand for AtaSubcommand {
match from_resolved { match from_resolved {
AccountIdWithPrivacy::Public(from_id) => { AccountIdWithPrivacy::Public(from_id) => {
let tx_hash = Ata(wallet_core) let tx_hash = Ata(wallet_core)
.send_transfer(from_id, definition_id, to_id, amount, &from) .send_transfer(
from.into_public_identity(from_id),
definition_id,
to_id,
amount,
)
.await?; .await?;
println!("Transaction hash is {tx_hash}"); println!("Transaction hash is {tx_hash}");
let transfer_tx = wallet_core.poll_native_token_transfer(tx_hash).await?; let transfer_tx = wallet_core.poll_native_token_transfer(tx_hash).await?;
@ -177,7 +182,11 @@ impl WalletSubcommand for AtaSubcommand {
match holder_resolved { match holder_resolved {
AccountIdWithPrivacy::Public(holder_id) => { AccountIdWithPrivacy::Public(holder_id) => {
let tx_hash = Ata(wallet_core) let tx_hash = Ata(wallet_core)
.send_burn(holder_id, definition_id, amount, &holder) .send_burn(
holder.into_public_identity(holder_id),
definition_id,
amount,
)
.await?; .await?;
println!("Transaction hash is {tx_hash}"); println!("Transaction hash is {tx_hash}");
let transfer_tx = wallet_core.poll_native_token_transfer(tx_hash).await?; let transfer_tx = wallet_core.poll_native_token_transfer(tx_hash).await?;

View File

@ -5,7 +5,7 @@ use nssa::AccountId;
use crate::{ use crate::{
AccDecodeData::Decode, AccDecodeData::Decode,
WalletCore, AccountIdentity, WalletCore,
account::AccountIdWithPrivacy, account::AccountIdWithPrivacy,
cli::{CliAccountMention, SubcommandReturnValue, WalletSubcommand}, cli::{CliAccountMention, SubcommandReturnValue, WalletSubcommand},
program_facades::native_token_transfer::NativeTokenTransfer, program_facades::native_token_transfer::NativeTokenTransfer,
@ -60,7 +60,7 @@ impl WalletSubcommand for AuthTransferSubcommand {
match resolved { match resolved {
AccountIdWithPrivacy::Public(pub_account_id) => { AccountIdWithPrivacy::Public(pub_account_id) => {
let tx_hash = NativeTokenTransfer(wallet_core) let tx_hash = NativeTokenTransfer(wallet_core)
.register_account(pub_account_id, &account_id) .register_account(account_id.into_public_identity(pub_account_id))
.await?; .await?;
println!("Transaction hash is {tx_hash}"); println!("Transaction hash is {tx_hash}");
@ -124,12 +124,11 @@ impl WalletSubcommand for AuthTransferSubcommand {
} }
(Some(to), None, None) => match (from, to) { (Some(to), None, None) => match (from, to) {
(AccountIdWithPrivacy::Public(from), AccountIdWithPrivacy::Public(to)) => { (AccountIdWithPrivacy::Public(from), AccountIdWithPrivacy::Public(to)) => {
let to_mention = to_account.expect("matched Some branch");
NativeTokenTransferProgramSubcommand::Public { NativeTokenTransferProgramSubcommand::Public {
from, from: Some(from_account.into_public_identity(from)),
to, to: Some(to_mention.into_public_identity(to)),
amount, amount,
from_mention: from_account,
to_mention: to_account.expect("matched Some branch"),
} }
} }
( (
@ -148,10 +147,9 @@ impl WalletSubcommand for AuthTransferSubcommand {
(AccountIdWithPrivacy::Public(from), AccountIdWithPrivacy::Private(to)) => { (AccountIdWithPrivacy::Public(from), AccountIdWithPrivacy::Private(to)) => {
NativeTokenTransferProgramSubcommand::Shielded( NativeTokenTransferProgramSubcommand::Shielded(
NativeTokenTransferProgramSubcommandShielded::ShieldedOwned { NativeTokenTransferProgramSubcommandShielded::ShieldedOwned {
from, from: Some(from_account.into_public_identity(from)),
to, to,
amount, amount,
from_mention: from_account,
}, },
) )
} }
@ -171,12 +169,11 @@ impl WalletSubcommand for AuthTransferSubcommand {
AccountIdWithPrivacy::Public(from) => { AccountIdWithPrivacy::Public(from) => {
NativeTokenTransferProgramSubcommand::Shielded( NativeTokenTransferProgramSubcommand::Shielded(
NativeTokenTransferProgramSubcommandShielded::ShieldedForeign { NativeTokenTransferProgramSubcommandShielded::ShieldedForeign {
from, from: Some(from_account.into_public_identity(from)),
to_npk, to_npk,
to_vpk, to_vpk,
to_identifier, to_identifier,
amount, amount,
from_mention: from_account,
}, },
) )
} }
@ -196,19 +193,13 @@ pub enum NativeTokenTransferProgramSubcommand {
/// ///
/// Public operation. /// Public operation.
Public { Public {
/// from - valid 32 byte hex string. #[arg(skip)]
#[arg(long)] from: Option<AccountIdentity>,
from: AccountId, #[arg(skip)]
/// to - valid 32 byte hex string. to: Option<AccountIdentity>,
#[arg(long)]
to: AccountId,
/// amount - amount of balance to move. /// amount - amount of balance to move.
#[arg(long)] #[arg(long)]
amount: u128, amount: u128,
#[arg(skip)]
from_mention: CliAccountMention,
#[arg(skip)]
to_mention: CliAccountMention,
}, },
/// Private execution. /// Private execution.
#[command(subcommand)] #[command(subcommand)]
@ -241,24 +232,21 @@ pub enum NativeTokenTransferProgramSubcommandShielded {
/// Shielded operation. /// Shielded operation.
ShieldedOwned { ShieldedOwned {
/// from - valid 32 byte hex string. /// from - valid 32 byte hex string.
#[arg(long)] #[arg(skip)]
from: AccountId, from: Option<AccountIdentity>,
/// to - valid 32 byte hex string. /// to - valid 32 byte hex string.
#[arg(long)] #[arg(long)]
to: AccountId, to: AccountId,
/// amount - amount of balance to move. /// amount - amount of balance to move.
#[arg(long)] #[arg(long)]
amount: u128, amount: u128,
#[arg(skip)]
from_mention: CliAccountMention,
}, },
/// Send native token transfer from `from` to `to` for `amount`. /// Send native token transfer from `from` to `to` for `amount`.
/// ///
/// Shielded operation. /// Shielded operation.
ShieldedForeign { ShieldedForeign {
/// from - valid 32 byte hex string. #[arg(skip)]
#[arg(long)] from: Option<AccountIdentity>,
from: AccountId,
/// `to_npk` - valid 32 byte hex string. /// `to_npk` - valid 32 byte hex string.
#[arg(long)] #[arg(long)]
to_npk: String, to_npk: String,
@ -271,8 +259,6 @@ pub enum NativeTokenTransferProgramSubcommandShielded {
/// amount - amount of balance to move. /// amount - amount of balance to move.
#[arg(long)] #[arg(long)]
amount: u128, amount: u128,
#[arg(skip)]
from_mention: CliAccountMention,
}, },
} }
@ -399,14 +385,13 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandShielded {
wallet_core: &mut WalletCore, wallet_core: &mut WalletCore,
) -> Result<SubcommandReturnValue> { ) -> Result<SubcommandReturnValue> {
match self { match self {
Self::ShieldedOwned { Self::ShieldedOwned { from, to, amount } => {
from,
to,
amount,
from_mention,
} => {
let (tx_hash, secret) = NativeTokenTransfer(wallet_core) let (tx_hash, secret) = NativeTokenTransfer(wallet_core)
.send_shielded_transfer(from, to, amount, &from_mention) .send_shielded_transfer(
from.expect("from set during Send dispatch"),
to,
amount,
)
.await?; .await?;
println!("Transaction hash is {tx_hash}"); println!("Transaction hash is {tx_hash}");
@ -432,7 +417,6 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandShielded {
to_vpk, to_vpk,
to_identifier, to_identifier,
amount, amount,
from_mention,
} => { } => {
let to_npk_res = hex::decode(to_npk)?; let to_npk_res = hex::decode(to_npk)?;
let mut to_npk = [0; 32]; let mut to_npk = [0; 32];
@ -447,12 +431,11 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandShielded {
let (tx_hash, _) = NativeTokenTransfer(wallet_core) let (tx_hash, _) = NativeTokenTransfer(wallet_core)
.send_shielded_transfer_to_outer_account( .send_shielded_transfer_to_outer_account(
from, from.expect("from set during Send dispatch"),
to_npk, to_npk,
to_vpk, to_vpk,
to_identifier.unwrap_or_else(rand::random), to_identifier.unwrap_or_else(rand::random),
amount, amount,
&from_mention,
) )
.await?; .await?;
@ -500,15 +483,13 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommand {
Ok(SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash }) Ok(SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash })
} }
Self::Public { Self::Public { from, to, amount } => {
from,
to,
amount,
from_mention,
to_mention,
} => {
let tx_hash = NativeTokenTransfer(wallet_core) let tx_hash = NativeTokenTransfer(wallet_core)
.send_public_transfer(from, to, amount, &from_mention, &to_mention) .send_public_transfer(
from.expect("from is set during Send dispatch"),
to.expect("to is set during Send dispatch"),
amount,
)
.await?; .await?;
println!("Transaction hash is {tx_hash}"); println!("Transaction hash is {tx_hash}");

View File

@ -5,7 +5,7 @@ use nssa::AccountId;
use crate::{ use crate::{
AccDecodeData::Decode, AccDecodeData::Decode,
WalletCore, AccountIdentity, WalletCore,
account::AccountIdWithPrivacy, account::AccountIdWithPrivacy,
cli::{CliAccountMention, SubcommandReturnValue, WalletSubcommand}, cli::{CliAccountMention, SubcommandReturnValue, WalletSubcommand},
program_facades::token::Token, program_facades::token::Token,
@ -226,10 +226,9 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
(AccountIdWithPrivacy::Public(from), AccountIdWithPrivacy::Private(to)) => { (AccountIdWithPrivacy::Public(from), AccountIdWithPrivacy::Private(to)) => {
TokenProgramSubcommand::Shielded( TokenProgramSubcommand::Shielded(
TokenProgramSubcommandShielded::TransferTokenShieldedOwned { TokenProgramSubcommandShielded::TransferTokenShieldedOwned {
sender_account_id: from, sender: Some(from_mention.into_public_identity(from)),
recipient_account_id: to, recipient_account_id: to,
balance_to_move: amount, balance_to_move: amount,
sender_mention: from_mention,
}, },
) )
} }
@ -246,12 +245,11 @@ impl WalletSubcommand for TokenProgramAgnosticSubcommand {
), ),
AccountIdWithPrivacy::Public(from) => TokenProgramSubcommand::Shielded( AccountIdWithPrivacy::Public(from) => TokenProgramSubcommand::Shielded(
TokenProgramSubcommandShielded::TransferTokenShieldedForeign { TokenProgramSubcommandShielded::TransferTokenShieldedForeign {
sender_account_id: from, sender: Some(from_mention.into_public_identity(from)),
recipient_npk: to_npk, recipient_npk: to_npk,
recipient_vpk: to_vpk, recipient_vpk: to_vpk,
recipient_identifier: to_identifier, recipient_identifier: to_identifier,
balance_to_move: amount, balance_to_move: amount,
sender_mention: from_mention,
}, },
), ),
}, },
@ -561,19 +559,17 @@ pub enum TokenProgramSubcommandDeshielded {
pub enum TokenProgramSubcommandShielded { pub enum TokenProgramSubcommandShielded {
// Transfer tokens using the token program // Transfer tokens using the token program
TransferTokenShieldedOwned { TransferTokenShieldedOwned {
#[arg(short, long)] #[arg(skip)]
sender_account_id: AccountId, sender: Option<AccountIdentity>,
#[arg(short, long)] #[arg(short, long)]
recipient_account_id: AccountId, recipient_account_id: AccountId,
#[arg(short, long)] #[arg(short, long)]
balance_to_move: u128, balance_to_move: u128,
#[arg(skip)]
sender_mention: CliAccountMention,
}, },
// Transfer tokens using the token program // Transfer tokens using the token program
TransferTokenShieldedForeign { TransferTokenShieldedForeign {
#[arg(short, long)] #[arg(skip)]
sender_account_id: AccountId, sender: Option<AccountIdentity>,
/// `recipient_npk` - valid 32 byte hex string. /// `recipient_npk` - valid 32 byte hex string.
#[arg(long)] #[arg(long)]
recipient_npk: String, recipient_npk: String,
@ -585,8 +581,6 @@ pub enum TokenProgramSubcommandShielded {
recipient_identifier: Option<u128>, recipient_identifier: Option<u128>,
#[arg(short, long)] #[arg(short, long)]
balance_to_move: u128, balance_to_move: u128,
#[arg(skip)]
sender_mention: CliAccountMention,
}, },
// Burn tokens using the token program // Burn tokens using the token program
BurnTokenShielded { BurnTokenShielded {
@ -697,15 +691,15 @@ impl WalletSubcommand for TokenProgramSubcommandPublic {
AccountIdWithPrivacy::Public(recipient_id), AccountIdWithPrivacy::Public(recipient_id),
) = (sender, recipient) ) = (sender, recipient)
else { else {
anyhow::bail!("Only public accounts supported for token transfer"); anyhow::bail!(
"`TokenProgramSubcommandPublic::TransferToken`: Unexpected private account received."
);
}; };
let tx_hash = Token(wallet_core) let tx_hash = Token(wallet_core)
.send_transfer_transaction( .send_transfer_transaction(
sender_id, sender_account_id.into_public_identity(sender_id),
recipient_id, recipient_account_id.into_public_identity(recipient_id),
balance_to_move, balance_to_move,
&sender_account_id,
&recipient_account_id,
) )
.await?; .await?;
println!("Transaction hash is {tx_hash}"); println!("Transaction hash is {tx_hash}");
@ -721,14 +715,15 @@ impl WalletSubcommand for TokenProgramSubcommandPublic {
} => { } => {
let holder = holder_account_id.resolve(wallet_core.storage())?; let holder = holder_account_id.resolve(wallet_core.storage())?;
let AccountIdWithPrivacy::Public(holder_id) = holder else { let AccountIdWithPrivacy::Public(holder_id) = holder else {
anyhow::bail!("Only public holder account supported for token burn"); anyhow::bail!(
"`TokenProgramSubcommandPublic::BurnToken`: holder account must be public."
);
}; };
let tx_hash = Token(wallet_core) let tx_hash = Token(wallet_core)
.send_burn_transaction( .send_burn_transaction(
definition_account_id, definition_account_id,
holder_id, holder_account_id.into_public_identity(holder_id),
amount, amount,
&holder_account_id,
) )
.await?; .await?;
println!("Transaction hash is {tx_hash}"); println!("Transaction hash is {tx_hash}");
@ -747,15 +742,15 @@ impl WalletSubcommand for TokenProgramSubcommandPublic {
let (AccountIdWithPrivacy::Public(def_id), AccountIdWithPrivacy::Public(holder_id)) = let (AccountIdWithPrivacy::Public(def_id), AccountIdWithPrivacy::Public(holder_id)) =
(definition, holder) (definition, holder)
else { else {
anyhow::bail!("Only public accounts supported for token mint"); anyhow::bail!(
"`TokenProgramSubcommandPublic::MintToken`: holder account must be public."
);
}; };
let tx_hash = Token(wallet_core) let tx_hash = Token(wallet_core)
.send_mint_transaction( .send_mint_transaction(
def_id, definition_account_id.into_public_identity(def_id),
holder_id, holder_account_id.into_public_identity(holder_id),
amount, amount,
&definition_account_id,
&holder_account_id,
) )
.await?; .await?;
println!("Transaction hash is {tx_hash}"); println!("Transaction hash is {tx_hash}");
@ -1076,12 +1071,11 @@ impl WalletSubcommand for TokenProgramSubcommandShielded {
) -> Result<SubcommandReturnValue> { ) -> Result<SubcommandReturnValue> {
match self { match self {
Self::TransferTokenShieldedForeign { Self::TransferTokenShieldedForeign {
sender_account_id, sender,
recipient_npk, recipient_npk,
recipient_vpk, recipient_vpk,
recipient_identifier, recipient_identifier,
balance_to_move, balance_to_move,
sender_mention,
} => { } => {
let recipient_npk_res = hex::decode(recipient_npk)?; let recipient_npk_res = hex::decode(recipient_npk)?;
let mut recipient_npk = [0; 32]; let mut recipient_npk = [0; 32];
@ -1097,12 +1091,11 @@ impl WalletSubcommand for TokenProgramSubcommandShielded {
let (tx_hash, _) = Token(wallet_core) let (tx_hash, _) = Token(wallet_core)
.send_transfer_transaction_shielded_foreign_account( .send_transfer_transaction_shielded_foreign_account(
sender_account_id, sender.expect("sender set during Send dispatch"),
recipient_npk, recipient_npk,
recipient_vpk, recipient_vpk,
recipient_identifier.unwrap_or_else(rand::random), recipient_identifier.unwrap_or_else(rand::random),
balance_to_move, balance_to_move,
&sender_mention,
) )
.await?; .await?;
@ -1119,17 +1112,15 @@ impl WalletSubcommand for TokenProgramSubcommandShielded {
Ok(SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash }) Ok(SubcommandReturnValue::PrivacyPreservingTransfer { tx_hash })
} }
Self::TransferTokenShieldedOwned { Self::TransferTokenShieldedOwned {
sender_account_id, sender,
recipient_account_id, recipient_account_id,
balance_to_move, balance_to_move,
sender_mention,
} => { } => {
let (tx_hash, secret_recipient) = Token(wallet_core) let (tx_hash, secret_recipient) = Token(wallet_core)
.send_transfer_transaction_shielded_owned_account( .send_transfer_transaction_shielded_owned_account(
sender_account_id, sender.expect("sender set during Send dispatch"),
recipient_account_id, recipient_account_id,
balance_to_move, balance_to_move,
&sender_mention,
) )
.await?; .await?;
@ -1371,16 +1362,14 @@ impl WalletSubcommand for CreateNewTokenProgramSubcommand {
let (AccountIdWithPrivacy::Public(def_id), AccountIdWithPrivacy::Public(sup_id)) = let (AccountIdWithPrivacy::Public(def_id), AccountIdWithPrivacy::Public(sup_id)) =
(definition, supply) (definition, supply)
else { else {
anyhow::bail!("Only public accounts supported for new token definition"); anyhow::bail!("`NewPublicDefPublicSupp`: unexpected private account received.");
}; };
let tx_hash = Token(wallet_core) let tx_hash = Token(wallet_core)
.send_new_definition( .send_new_definition(
def_id, definition_account_id.into_public_identity(def_id),
sup_id, supply_account_id.into_public_identity(sup_id),
name, name,
total_supply, total_supply,
&definition_account_id,
&supply_account_id,
) )
.await?; .await?;
println!("Transaction hash is {tx_hash}"); println!("Transaction hash is {tx_hash}");

View File

@ -77,24 +77,12 @@ pub enum ExecutionFailureKind {
AccountDataError(AccountId), AccountDataError(AccountId),
#[error("Failed to build transaction: {0}")] #[error("Failed to build transaction: {0}")]
TransactionBuildError(#[from] nssa::error::NssaError), TransactionBuildError(#[from] nssa::error::NssaError),
#[error("Failed to sign transaction: {0}")]
SignError(anyhow::Error),
#[error(transparent)] #[error(transparent)]
KeycardError(#[from] pyo3::PyErr), KeycardError(#[from] pyo3::PyErr),
} }
impl ExecutionFailureKind {
/// Convert an [`anyhow::Error`] (e.g. from [`SigningGroup`]) into a keycard error.
#[must_use]
#[expect(
clippy::needless_pass_by_value,
reason = "used as a method reference in map_err"
)]
pub fn from_anyhow(e: anyhow::Error) -> Self {
Self::KeycardError(pyo3::PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(
e.to_string(),
))
}
}
#[expect(clippy::partial_pub_fields, reason = "TODO: make all fields private")] #[expect(clippy::partial_pub_fields, reason = "TODO: make all fields private")]
pub struct WalletCore { pub struct WalletCore {
config_path: PathBuf, config_path: PathBuf,
@ -606,7 +594,7 @@ impl WalletCore {
let message_hash = message.hash(); let message_hash = message.hash();
let signatures_public_keys = acc_manager let signatures_public_keys = acc_manager
.sign_message(message_hash) .sign_message(message_hash)
.map_err(ExecutionFailureKind::from_anyhow)?; .map_err(ExecutionFailureKind::SignError)?;
let witness_set = let witness_set =
nssa::privacy_preserving_transaction::witness_set::WitnessSet::from_raw_parts( nssa::privacy_preserving_transaction::witness_set::WitnessSet::from_raw_parts(
@ -679,7 +667,7 @@ impl WalletCore {
let message_hash = message.hash(); let message_hash = message.hash();
let signatures_public_keys = acc_manager let signatures_public_keys = acc_manager
.sign_message(message_hash) .sign_message(message_hash)
.map_err(ExecutionFailureKind::from_anyhow)?; .map_err(ExecutionFailureKind::SignError)?;
let witness_set = let witness_set =
nssa::public_transaction::WitnessSet::from_raw_parts(signatures_public_keys); nssa::public_transaction::WitnessSet::from_raw_parts(signatures_public_keys);

View File

@ -3,64 +3,43 @@ use common::HashType;
use nssa::{AccountId, program::Program}; use nssa::{AccountId, program::Program};
use token_core::TokenHolding; use token_core::TokenHolding;
use crate::{AccountIdentity, ExecutionFailureKind, WalletCore, cli::CliAccountMention}; use crate::{AccountIdentity, ExecutionFailureKind, WalletCore};
pub struct Amm<'wallet>(pub &'wallet WalletCore); pub struct Amm<'wallet>(pub &'wallet WalletCore);
impl Amm<'_> { impl Amm<'_> {
#[expect(clippy::too_many_arguments, reason = "each parameter is distinct")]
pub async fn send_new_definition( pub async fn send_new_definition(
&self, &self,
user_holding_a: AccountId, user_holding_a: AccountIdentity,
user_holding_b: AccountId, user_holding_b: AccountIdentity,
user_holding_lp: AccountId, user_holding_lp: AccountIdentity,
balance_a: u128, balance_a: u128,
balance_b: u128, balance_b: u128,
user_holding_a_mention: &CliAccountMention,
user_holding_b_mention: &CliAccountMention,
user_holding_lp_mention: &CliAccountMention,
) -> Result<HashType, ExecutionFailureKind> { ) -> Result<HashType, ExecutionFailureKind> {
let user_holding_a_identity = user_holding_a_mention.key_path().map_or( let a_id = user_holding_a
AccountIdentity::Public(user_holding_a), .public_account_id()
|key_path| AccountIdentity::PublicKeycard { .ok_or(ExecutionFailureKind::KeyNotFoundError)?;
account_id: user_holding_a, let b_id = user_holding_b
key_path: key_path.to_owned(), .public_account_id()
}, .ok_or(ExecutionFailureKind::KeyNotFoundError)?;
);
let user_holding_b_identity = user_holding_b_mention.key_path().map_or(
AccountIdentity::Public(user_holding_b),
|key_path| AccountIdentity::PublicKeycard {
account_id: user_holding_b,
key_path: key_path.to_owned(),
},
);
let user_holding_lp_identity = user_holding_lp_mention.key_path().map_or(
AccountIdentity::Public(user_holding_lp),
|key_path| AccountIdentity::PublicKeycard {
account_id: user_holding_lp,
key_path: key_path.to_owned(),
},
);
let program = Program::amm(); let program = Program::amm();
let amm_program_id = Program::amm().id(); let amm_program_id = Program::amm().id();
let user_a_acc = self let user_a_acc = self
.0 .0
.get_account_public(user_holding_a) .get_account_public(a_id)
.await .await
.map_err(ExecutionFailureKind::SequencerError)?; .map_err(ExecutionFailureKind::SequencerError)?;
let user_b_acc = self let user_b_acc = self
.0 .0
.get_account_public(user_holding_b) .get_account_public(b_id)
.await .await
.map_err(ExecutionFailureKind::SequencerError)?; .map_err(ExecutionFailureKind::SequencerError)?;
let definition_token_a_id = TokenHolding::try_from(&user_a_acc.data) let definition_token_a_id = TokenHolding::try_from(&user_a_acc.data)
.map_err(|_err| ExecutionFailureKind::AccountDataError(user_holding_a))? .map_err(|_err| ExecutionFailureKind::AccountDataError(a_id))?
.definition_id(); .definition_id();
let definition_token_b_id = TokenHolding::try_from(&user_b_acc.data) let definition_token_b_id = TokenHolding::try_from(&user_b_acc.data)
.map_err(|_err| ExecutionFailureKind::AccountDataError(user_holding_b))? .map_err(|_err| ExecutionFailureKind::AccountDataError(b_id))?
.definition_id(); .definition_id();
let amm_pool = let amm_pool =
@ -83,9 +62,9 @@ impl Amm<'_> {
AccountIdentity::PublicNoSign(vault_holding_a), AccountIdentity::PublicNoSign(vault_holding_a),
AccountIdentity::PublicNoSign(vault_holding_b), AccountIdentity::PublicNoSign(vault_holding_b),
AccountIdentity::PublicNoSign(pool_lp), AccountIdentity::PublicNoSign(pool_lp),
user_holding_a_identity, user_holding_a,
user_holding_b_identity, user_holding_b,
user_holding_lp_identity, user_holding_lp,
], ],
instruction_data, instruction_data,
&program.into(), &program.into(),
@ -93,35 +72,39 @@ impl Amm<'_> {
.await .await
} }
#[expect(clippy::too_many_arguments, reason = "each parameter is distinct")]
pub async fn send_swap_exact_input( pub async fn send_swap_exact_input(
&self, &self,
user_holding_a: AccountId, user_holding_a: AccountIdentity,
user_holding_b: AccountId, user_holding_b: AccountIdentity,
swap_amount_in: u128, swap_amount_in: u128,
min_amount_out: u128, min_amount_out: u128,
token_definition_id_in: AccountId, token_definition_id_in: AccountId,
user_holding_a_mention: &CliAccountMention,
user_holding_b_mention: &CliAccountMention,
) -> Result<HashType, ExecutionFailureKind> { ) -> Result<HashType, ExecutionFailureKind> {
let a_id = user_holding_a
.public_account_id()
.ok_or(ExecutionFailureKind::KeyNotFoundError)?;
let b_id = user_holding_b
.public_account_id()
.ok_or(ExecutionFailureKind::KeyNotFoundError)?;
let program = Program::amm(); let program = Program::amm();
let amm_program_id = Program::amm().id(); let amm_program_id = Program::amm().id();
let user_a_acc = self let user_a_acc = self
.0 .0
.get_account_public(user_holding_a) .get_account_public(a_id)
.await .await
.map_err(ExecutionFailureKind::SequencerError)?; .map_err(ExecutionFailureKind::SequencerError)?;
let user_b_acc = self let user_b_acc = self
.0 .0
.get_account_public(user_holding_b) .get_account_public(b_id)
.await .await
.map_err(ExecutionFailureKind::SequencerError)?; .map_err(ExecutionFailureKind::SequencerError)?;
let definition_token_a_id = TokenHolding::try_from(&user_a_acc.data) let definition_token_a_id = TokenHolding::try_from(&user_a_acc.data)
.map_err(|_err| ExecutionFailureKind::AccountDataError(user_holding_a))? .map_err(|_err| ExecutionFailureKind::AccountDataError(a_id))?
.definition_id(); .definition_id();
let definition_token_b_id = TokenHolding::try_from(&user_b_acc.data) let definition_token_b_id = TokenHolding::try_from(&user_b_acc.data)
.map_err(|_err| ExecutionFailureKind::AccountDataError(user_holding_b))? .map_err(|_err| ExecutionFailureKind::AccountDataError(b_id))?
.definition_id(); .definition_id();
let amm_pool = let amm_pool =
@ -145,27 +128,15 @@ impl Amm<'_> {
} }
let user_a_signing_identity = if token_definition_id_in == definition_token_a_id { let user_a_signing_identity = if token_definition_id_in == definition_token_a_id {
user_holding_a_mention.key_path().map_or( user_holding_a
AccountIdentity::Public(user_holding_a),
|key_path| AccountIdentity::PublicKeycard {
account_id: user_holding_a,
key_path: key_path.to_owned(),
},
)
} else { } else {
AccountIdentity::PublicNoSign(user_holding_a) AccountIdentity::PublicNoSign(a_id)
}; };
let user_b_signing_identity = if token_definition_id_in == definition_token_b_id { let user_b_signing_identity = if token_definition_id_in == definition_token_b_id {
user_holding_b_mention.key_path().map_or( user_holding_b
AccountIdentity::Public(user_holding_b),
|key_path| AccountIdentity::PublicKeycard {
account_id: user_holding_b,
key_path: key_path.to_owned(),
},
)
} else { } else {
AccountIdentity::PublicNoSign(user_holding_b) AccountIdentity::PublicNoSign(b_id)
}; };
self.0 self.0
@ -183,35 +154,39 @@ impl Amm<'_> {
.await .await
} }
#[expect(clippy::too_many_arguments, reason = "each parameter is distinct")]
pub async fn send_swap_exact_output( pub async fn send_swap_exact_output(
&self, &self,
user_holding_a: AccountId, user_holding_a: AccountIdentity,
user_holding_b: AccountId, user_holding_b: AccountIdentity,
exact_amount_out: u128, exact_amount_out: u128,
max_amount_in: u128, max_amount_in: u128,
token_definition_id_in: AccountId, token_definition_id_in: AccountId,
user_holding_a_mention: &CliAccountMention,
user_holding_b_mention: &CliAccountMention,
) -> Result<HashType, ExecutionFailureKind> { ) -> Result<HashType, ExecutionFailureKind> {
let a_id = user_holding_a
.public_account_id()
.ok_or(ExecutionFailureKind::KeyNotFoundError)?;
let b_id = user_holding_b
.public_account_id()
.ok_or(ExecutionFailureKind::KeyNotFoundError)?;
let program = Program::amm(); let program = Program::amm();
let amm_program_id = Program::amm().id(); let amm_program_id = Program::amm().id();
let user_a_acc = self let user_a_acc = self
.0 .0
.get_account_public(user_holding_a) .get_account_public(a_id)
.await .await
.map_err(ExecutionFailureKind::SequencerError)?; .map_err(ExecutionFailureKind::SequencerError)?;
let user_b_acc = self let user_b_acc = self
.0 .0
.get_account_public(user_holding_b) .get_account_public(b_id)
.await .await
.map_err(ExecutionFailureKind::SequencerError)?; .map_err(ExecutionFailureKind::SequencerError)?;
let definition_token_a_id = TokenHolding::try_from(&user_a_acc.data) let definition_token_a_id = TokenHolding::try_from(&user_a_acc.data)
.map_err(|_err| ExecutionFailureKind::AccountDataError(user_holding_a))? .map_err(|_err| ExecutionFailureKind::AccountDataError(a_id))?
.definition_id(); .definition_id();
let definition_token_b_id = TokenHolding::try_from(&user_b_acc.data) let definition_token_b_id = TokenHolding::try_from(&user_b_acc.data)
.map_err(|_err| ExecutionFailureKind::AccountDataError(user_holding_b))? .map_err(|_err| ExecutionFailureKind::AccountDataError(b_id))?
.definition_id(); .definition_id();
let amm_pool = let amm_pool =
@ -235,27 +210,15 @@ impl Amm<'_> {
} }
let user_a_signing_identity = if token_definition_id_in == definition_token_a_id { let user_a_signing_identity = if token_definition_id_in == definition_token_a_id {
user_holding_a_mention.key_path().map_or( user_holding_a
AccountIdentity::Public(user_holding_a),
|key_path| AccountIdentity::PublicKeycard {
account_id: user_holding_a,
key_path: key_path.to_owned(),
},
)
} else { } else {
AccountIdentity::PublicNoSign(user_holding_a) AccountIdentity::PublicNoSign(a_id)
}; };
let user_b_signing_identity = if token_definition_id_in == definition_token_b_id { let user_b_signing_identity = if token_definition_id_in == definition_token_b_id {
user_holding_b_mention.key_path().map_or( user_holding_b
AccountIdentity::Public(user_holding_b),
|key_path| AccountIdentity::PublicKeycard {
account_id: user_holding_b,
key_path: key_path.to_owned(),
},
)
} else { } else {
AccountIdentity::PublicNoSign(user_holding_b) AccountIdentity::PublicNoSign(b_id)
}; };
self.0 self.0
@ -273,61 +236,40 @@ impl Amm<'_> {
.await .await
} }
#[expect(clippy::too_many_arguments, reason = "each parameter is distinct")]
pub async fn send_add_liquidity( pub async fn send_add_liquidity(
&self, &self,
user_holding_a: AccountId, user_holding_a: AccountIdentity,
user_holding_b: AccountId, user_holding_b: AccountIdentity,
user_holding_lp: AccountId, user_holding_lp: AccountIdentity,
min_amount_liquidity: u128, min_amount_liquidity: u128,
max_amount_to_add_token_a: u128, max_amount_to_add_token_a: u128,
max_amount_to_add_token_b: u128, max_amount_to_add_token_b: u128,
user_holding_a_mention: &CliAccountMention,
user_holding_b_mention: &CliAccountMention,
user_holding_lp_mention: &CliAccountMention,
) -> Result<HashType, ExecutionFailureKind> { ) -> Result<HashType, ExecutionFailureKind> {
let user_holding_a_identity = user_holding_a_mention.key_path().map_or( let a_id = user_holding_a
AccountIdentity::Public(user_holding_a), .public_account_id()
|key_path| AccountIdentity::PublicKeycard { .ok_or(ExecutionFailureKind::KeyNotFoundError)?;
account_id: user_holding_a, let b_id = user_holding_b
key_path: key_path.to_owned(), .public_account_id()
}, .ok_or(ExecutionFailureKind::KeyNotFoundError)?;
);
let user_holding_b_identity = user_holding_b_mention.key_path().map_or(
AccountIdentity::Public(user_holding_b),
|key_path| AccountIdentity::PublicKeycard {
account_id: user_holding_b,
key_path: key_path.to_owned(),
},
);
let user_holding_lp_identity = user_holding_lp_mention.key_path().map_or(
AccountIdentity::Public(user_holding_lp),
|key_path| AccountIdentity::PublicKeycard {
account_id: user_holding_lp,
key_path: key_path.to_owned(),
},
);
let program = Program::amm(); let program = Program::amm();
let amm_program_id = Program::amm().id(); let amm_program_id = Program::amm().id();
let user_a_acc = self let user_a_acc = self
.0 .0
.get_account_public(user_holding_a) .get_account_public(a_id)
.await .await
.map_err(ExecutionFailureKind::SequencerError)?; .map_err(ExecutionFailureKind::SequencerError)?;
let user_b_acc = self let user_b_acc = self
.0 .0
.get_account_public(user_holding_b) .get_account_public(b_id)
.await .await
.map_err(ExecutionFailureKind::SequencerError)?; .map_err(ExecutionFailureKind::SequencerError)?;
let definition_token_a_id = TokenHolding::try_from(&user_a_acc.data) let definition_token_a_id = TokenHolding::try_from(&user_a_acc.data)
.map_err(|_err| ExecutionFailureKind::AccountDataError(user_holding_a))? .map_err(|_err| ExecutionFailureKind::AccountDataError(a_id))?
.definition_id(); .definition_id();
let definition_token_b_id = TokenHolding::try_from(&user_b_acc.data) let definition_token_b_id = TokenHolding::try_from(&user_b_acc.data)
.map_err(|_err| ExecutionFailureKind::AccountDataError(user_holding_b))? .map_err(|_err| ExecutionFailureKind::AccountDataError(b_id))?
.definition_id(); .definition_id();
let amm_pool = let amm_pool =
@ -350,9 +292,9 @@ impl Amm<'_> {
AccountIdentity::PublicNoSign(vault_holding_a), AccountIdentity::PublicNoSign(vault_holding_a),
AccountIdentity::PublicNoSign(vault_holding_b), AccountIdentity::PublicNoSign(vault_holding_b),
AccountIdentity::PublicNoSign(pool_lp), AccountIdentity::PublicNoSign(pool_lp),
user_holding_a_identity, user_holding_a,
user_holding_b_identity, user_holding_b,
user_holding_lp_identity, user_holding_lp,
], ],
instruction_data, instruction_data,
&program.into(), &program.into(),
@ -360,25 +302,15 @@ impl Amm<'_> {
.await .await
} }
#[expect(clippy::too_many_arguments, reason = "each parameter is distinct")]
pub async fn send_remove_liquidity( pub async fn send_remove_liquidity(
&self, &self,
user_holding_a: AccountId, user_holding_a: AccountId,
user_holding_b: AccountId, user_holding_b: AccountId,
user_holding_lp: AccountId, user_holding_lp: AccountIdentity,
remove_liquidity_amount: u128, remove_liquidity_amount: u128,
min_amount_to_remove_token_a: u128, min_amount_to_remove_token_a: u128,
min_amount_to_remove_token_b: u128, min_amount_to_remove_token_b: u128,
user_holding_lp_mention: &CliAccountMention,
) -> Result<HashType, ExecutionFailureKind> { ) -> Result<HashType, ExecutionFailureKind> {
let user_holding_lp_identity = user_holding_lp_mention.key_path().map_or(
AccountIdentity::Public(user_holding_lp),
|key_path| AccountIdentity::PublicKeycard {
account_id: user_holding_lp,
key_path: key_path.to_owned(),
},
);
let program = Program::amm(); let program = Program::amm();
let amm_program_id = Program::amm().id(); let amm_program_id = Program::amm().id();
let user_a_acc = self let user_a_acc = self
@ -421,7 +353,7 @@ impl Amm<'_> {
AccountIdentity::PublicNoSign(pool_lp), AccountIdentity::PublicNoSign(pool_lp),
AccountIdentity::PublicNoSign(user_holding_a), AccountIdentity::PublicNoSign(user_holding_a),
AccountIdentity::PublicNoSign(user_holding_b), AccountIdentity::PublicNoSign(user_holding_b),
user_holding_lp_identity, user_holding_lp,
], ],
instruction_data, instruction_data,
&program.into(), &program.into(),

View File

@ -7,26 +7,19 @@ use nssa::{
}; };
use nssa_core::SharedSecretKey; use nssa_core::SharedSecretKey;
use crate::{AccountIdentity, ExecutionFailureKind, WalletCore, cli::CliAccountMention}; use crate::{AccountIdentity, ExecutionFailureKind, WalletCore};
pub struct Ata<'wallet>(pub &'wallet WalletCore); pub struct Ata<'wallet>(pub &'wallet WalletCore);
impl Ata<'_> { impl Ata<'_> {
pub async fn send_create( pub async fn send_create(
&self, &self,
owner_id: AccountId, owner: AccountIdentity,
definition_id: AccountId, definition_id: AccountId,
owner_mention: &CliAccountMention,
) -> Result<HashType, ExecutionFailureKind> { ) -> Result<HashType, ExecutionFailureKind> {
let owner_identity = let owner_id = owner
owner_mention .public_account_id()
.key_path() .ok_or(ExecutionFailureKind::KeyNotFoundError)?;
.map_or(AccountIdentity::Public(owner_id), |key_path| {
AccountIdentity::PublicKeycard {
account_id: owner_id,
key_path: key_path.to_owned(),
}
});
let program = Program::ata(); let program = Program::ata();
let ata_program_id = program.id(); let ata_program_id = program.id();
@ -41,7 +34,7 @@ impl Ata<'_> {
self.0 self.0
.send_pub_tx( .send_pub_tx(
vec![ vec![
owner_identity, owner,
AccountIdentity::PublicNoSign(definition_id), AccountIdentity::PublicNoSign(definition_id),
AccountIdentity::PublicNoSign(ata_id), AccountIdentity::PublicNoSign(ata_id),
], ],
@ -53,21 +46,14 @@ impl Ata<'_> {
pub async fn send_transfer( pub async fn send_transfer(
&self, &self,
owner_id: AccountId, owner: AccountIdentity,
definition_id: AccountId, definition_id: AccountId,
recipient_id: AccountId, recipient_id: AccountId,
amount: u128, amount: u128,
owner_mention: &CliAccountMention,
) -> Result<HashType, ExecutionFailureKind> { ) -> Result<HashType, ExecutionFailureKind> {
let owner_identity = let owner_id = owner
owner_mention .public_account_id()
.key_path() .ok_or(ExecutionFailureKind::KeyNotFoundError)?;
.map_or(AccountIdentity::Public(owner_id), |key_path| {
AccountIdentity::PublicKeycard {
account_id: owner_id,
key_path: key_path.to_owned(),
}
});
let program = Program::ata(); let program = Program::ata();
let ata_program_id = program.id(); let ata_program_id = program.id();
@ -85,7 +71,7 @@ impl Ata<'_> {
self.0 self.0
.send_pub_tx( .send_pub_tx(
vec![ vec![
owner_identity, owner,
AccountIdentity::PublicNoSign(sender_ata_id), AccountIdentity::PublicNoSign(sender_ata_id),
AccountIdentity::PublicNoSign(recipient_id), AccountIdentity::PublicNoSign(recipient_id),
], ],
@ -97,20 +83,13 @@ impl Ata<'_> {
pub async fn send_burn( pub async fn send_burn(
&self, &self,
owner_id: AccountId, owner: AccountIdentity,
definition_id: AccountId, definition_id: AccountId,
amount: u128, amount: u128,
owner_mention: &CliAccountMention,
) -> Result<HashType, ExecutionFailureKind> { ) -> Result<HashType, ExecutionFailureKind> {
let owner_identity = let owner_id = owner
owner_mention .public_account_id()
.key_path() .ok_or(ExecutionFailureKind::KeyNotFoundError)?;
.map_or(AccountIdentity::Public(owner_id), |key_path| {
AccountIdentity::PublicKeycard {
account_id: owner_id,
key_path: key_path.to_owned(),
}
});
let program = Program::ata(); let program = Program::ata();
let ata_program_id = program.id(); let ata_program_id = program.id();
@ -128,7 +107,7 @@ impl Ata<'_> {
self.0 self.0
.send_pub_tx( .send_pub_tx(
vec![ vec![
owner_identity, owner,
AccountIdentity::PublicNoSign(holder_ata_id), AccountIdentity::PublicNoSign(holder_ata_id),
AccountIdentity::PublicNoSign(definition_id), AccountIdentity::PublicNoSign(definition_id),
], ],

View File

@ -1,46 +1,25 @@
use authenticated_transfer_core::Instruction as AuthTransferInstruction; use authenticated_transfer_core::Instruction as AuthTransferInstruction;
use common::HashType; use common::HashType;
use nssa::{AccountId, program::Program}; use nssa::program::Program;
use super::NativeTokenTransfer; use super::NativeTokenTransfer;
use crate::{ use crate::{
AccountIdentity, ExecutionFailureKind, cli::CliAccountMention, AccountIdentity, ExecutionFailureKind,
program_facades::native_token_transfer::auth_transfer_preparation, program_facades::native_token_transfer::auth_transfer_preparation,
}; };
impl NativeTokenTransfer<'_> { impl NativeTokenTransfer<'_> {
pub async fn send_public_transfer( pub async fn send_public_transfer(
&self, &self,
from: AccountId, from: AccountIdentity,
to: AccountId, to: AccountIdentity,
balance_to_move: u128, balance_to_move: u128,
from_mention: &CliAccountMention,
to_mention: &CliAccountMention,
) -> Result<HashType, ExecutionFailureKind> { ) -> Result<HashType, ExecutionFailureKind> {
let (instruction_data, program, tx_pre_check) = auth_transfer_preparation(balance_to_move); let (instruction_data, program, tx_pre_check) = auth_transfer_preparation(balance_to_move);
let from_identity =
from_mention
.key_path()
.map_or(AccountIdentity::Public(from), |key_path| {
AccountIdentity::PublicKeycard {
account_id: from,
key_path: key_path.to_owned(),
}
});
let to_identity = to_mention
.key_path()
.map_or(AccountIdentity::Public(to), |key_path| {
AccountIdentity::PublicKeycard {
account_id: to,
key_path: key_path.to_owned(),
}
});
self.0 self.0
.send_pub_tx_with_pre_check( .send_pub_tx_with_pre_check(
vec![from_identity, to_identity], vec![from, to],
instruction_data, instruction_data,
&program.into(), &program.into(),
tx_pre_check, tx_pre_check,
@ -50,24 +29,13 @@ impl NativeTokenTransfer<'_> {
pub async fn register_account( pub async fn register_account(
&self, &self,
from: AccountId, account: AccountIdentity,
account_mention: &CliAccountMention,
) -> Result<HashType, ExecutionFailureKind> { ) -> Result<HashType, ExecutionFailureKind> {
let from_identity =
account_mention
.key_path()
.map_or(AccountIdentity::Public(from), |key_path| {
AccountIdentity::PublicKeycard {
account_id: from,
key_path: key_path.to_owned(),
}
});
let program = Program::authenticated_transfer_program(); let program = Program::authenticated_transfer_program();
let instruction_data = Program::serialize_instruction(AuthTransferInstruction::Initialize)?; let instruction_data = Program::serialize_instruction(AuthTransferInstruction::Initialize)?;
self.0 self.0
.send_pub_tx(vec![from_identity], instruction_data, &program.into()) .send_pub_tx(vec![account], instruction_data, &program.into())
.await .await
} }
} }

View File

@ -3,31 +3,20 @@ use nssa::AccountId;
use nssa_core::{Identifier, NullifierPublicKey, SharedSecretKey, encryption::ViewingPublicKey}; use nssa_core::{Identifier, NullifierPublicKey, SharedSecretKey, encryption::ViewingPublicKey};
use super::{NativeTokenTransfer, auth_transfer_preparation}; use super::{NativeTokenTransfer, auth_transfer_preparation};
use crate::{AccountIdentity, ExecutionFailureKind, cli::CliAccountMention}; use crate::{AccountIdentity, ExecutionFailureKind};
impl NativeTokenTransfer<'_> { impl NativeTokenTransfer<'_> {
pub async fn send_shielded_transfer( pub async fn send_shielded_transfer(
&self, &self,
from: AccountId, from: AccountIdentity,
to: AccountId, to: AccountId,
balance_to_move: u128, balance_to_move: u128,
from_mention: &CliAccountMention,
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> { ) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
let from_identity =
from_mention
.key_path()
.map_or(AccountIdentity::Public(from), |key_path| {
AccountIdentity::PublicKeycard {
account_id: from,
key_path: key_path.to_owned(),
}
});
let (instruction_data, program, tx_pre_check) = auth_transfer_preparation(balance_to_move); let (instruction_data, program, tx_pre_check) = auth_transfer_preparation(balance_to_move);
self.0 self.0
.send_privacy_preserving_tx_with_pre_check( .send_privacy_preserving_tx_with_pre_check(
vec![ vec![
from_identity, from,
self.0 self.0
.resolve_private_account(to) .resolve_private_account(to)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?, .ok_or(ExecutionFailureKind::KeyNotFoundError)?,
@ -48,28 +37,17 @@ impl NativeTokenTransfer<'_> {
pub async fn send_shielded_transfer_to_outer_account( pub async fn send_shielded_transfer_to_outer_account(
&self, &self,
from: AccountId, from: AccountIdentity,
to_npk: NullifierPublicKey, to_npk: NullifierPublicKey,
to_vpk: ViewingPublicKey, to_vpk: ViewingPublicKey,
to_identifier: Identifier, to_identifier: Identifier,
balance_to_move: u128, balance_to_move: u128,
from_mention: &CliAccountMention,
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> { ) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
let from_identity =
from_mention
.key_path()
.map_or(AccountIdentity::Public(from), |key_path| {
AccountIdentity::PublicKeycard {
account_id: from,
key_path: key_path.to_owned(),
}
});
let (instruction_data, program, tx_pre_check) = auth_transfer_preparation(balance_to_move); let (instruction_data, program, tx_pre_check) = auth_transfer_preparation(balance_to_move);
self.0 self.0
.send_privacy_preserving_tx_with_pre_check( .send_privacy_preserving_tx_with_pre_check(
vec![ vec![
from_identity, from,
AccountIdentity::PrivateForeign { AccountIdentity::PrivateForeign {
npk: to_npk, npk: to_npk,
vpk: to_vpk, vpk: to_vpk,

View File

@ -3,47 +3,25 @@ use nssa::{AccountId, program::Program};
use nssa_core::{Identifier, NullifierPublicKey, SharedSecretKey, encryption::ViewingPublicKey}; use nssa_core::{Identifier, NullifierPublicKey, SharedSecretKey, encryption::ViewingPublicKey};
use token_core::Instruction; use token_core::Instruction;
use crate::{AccountIdentity, ExecutionFailureKind, WalletCore, cli::CliAccountMention}; use crate::{AccountIdentity, ExecutionFailureKind, WalletCore};
pub struct Token<'wallet>(pub &'wallet WalletCore); pub struct Token<'wallet>(pub &'wallet WalletCore);
impl Token<'_> { impl Token<'_> {
pub async fn send_new_definition( pub async fn send_new_definition(
&self, &self,
definition_account_id: AccountId, definition: AccountIdentity,
supply_account_id: AccountId, supply: AccountIdentity,
name: String, name: String,
total_supply: u128, total_supply: u128,
definition_mention: &CliAccountMention,
supply_mention: &CliAccountMention,
) -> Result<HashType, ExecutionFailureKind> { ) -> Result<HashType, ExecutionFailureKind> {
let definition_identity = definition_mention.key_path().map_or(
AccountIdentity::Public(definition_account_id),
|key_path| AccountIdentity::PublicKeycard {
account_id: definition_account_id,
key_path: key_path.to_owned(),
},
);
let supply_identity = supply_mention.key_path().map_or(
AccountIdentity::Public(supply_account_id),
|key_path| AccountIdentity::PublicKeycard {
account_id: supply_account_id,
key_path: key_path.to_owned(),
},
);
let program = Program::token(); let program = Program::token();
let instruction = Instruction::NewFungibleDefinition { name, total_supply }; let instruction = Instruction::NewFungibleDefinition { name, total_supply };
let instruction_data = let instruction_data =
Program::serialize_instruction(instruction).expect("Instruction should serialize"); Program::serialize_instruction(instruction).expect("Instruction should serialize");
self.0 self.0
.send_pub_tx( .send_pub_tx(vec![definition, supply], instruction_data, &program.into())
vec![definition_identity, supply_identity],
instruction_data,
&program.into(),
)
.await .await
} }
@ -146,28 +124,10 @@ impl Token<'_> {
pub async fn send_transfer_transaction( pub async fn send_transfer_transaction(
&self, &self,
sender_account_id: AccountId, sender: AccountIdentity,
recipient_account_id: AccountId, recipient: AccountIdentity,
amount: u128, amount: u128,
sender_mention: &CliAccountMention,
recipient_mention: &CliAccountMention,
) -> Result<HashType, ExecutionFailureKind> { ) -> Result<HashType, ExecutionFailureKind> {
let sender_identity = sender_mention.key_path().map_or(
AccountIdentity::Public(sender_account_id),
|key_path| AccountIdentity::PublicKeycard {
account_id: sender_account_id,
key_path: key_path.to_owned(),
},
);
let recipient_identity = recipient_mention.key_path().map_or(
AccountIdentity::Public(recipient_account_id),
|key_path| AccountIdentity::PublicKeycard {
account_id: recipient_account_id,
key_path: key_path.to_owned(),
},
);
let program = Program::token(); let program = Program::token();
let instruction = Instruction::Transfer { let instruction = Instruction::Transfer {
amount_to_transfer: amount, amount_to_transfer: amount,
@ -176,11 +136,7 @@ impl Token<'_> {
Program::serialize_instruction(instruction).expect("Instruction should serialize"); Program::serialize_instruction(instruction).expect("Instruction should serialize");
self.0 self.0
.send_pub_tx( .send_pub_tx(vec![sender, recipient], instruction_data, &program.into())
vec![sender_identity, recipient_identity],
instruction_data,
&program.into(),
)
.await .await
} }
@ -291,19 +247,10 @@ impl Token<'_> {
pub async fn send_transfer_transaction_shielded_owned_account( pub async fn send_transfer_transaction_shielded_owned_account(
&self, &self,
sender_account_id: AccountId, sender: AccountIdentity,
recipient_account_id: AccountId, recipient_account_id: AccountId,
amount: u128, amount: u128,
sender_mention: &CliAccountMention,
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> { ) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
let sender_identity = sender_mention.key_path().map_or(
AccountIdentity::Public(sender_account_id),
|key_path| AccountIdentity::PublicKeycard {
account_id: sender_account_id,
key_path: key_path.to_owned(),
},
);
let instruction = Instruction::Transfer { let instruction = Instruction::Transfer {
amount_to_transfer: amount, amount_to_transfer: amount,
}; };
@ -312,7 +259,7 @@ impl Token<'_> {
self.0 self.0
.send_privacy_preserving_tx( .send_privacy_preserving_tx(
vec![ vec![
sender_identity, sender,
self.0 self.0
.resolve_private_account(recipient_account_id) .resolve_private_account(recipient_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?, .ok_or(ExecutionFailureKind::KeyNotFoundError)?,
@ -332,21 +279,12 @@ impl Token<'_> {
pub async fn send_transfer_transaction_shielded_foreign_account( pub async fn send_transfer_transaction_shielded_foreign_account(
&self, &self,
sender_account_id: AccountId, sender: AccountIdentity,
recipient_npk: NullifierPublicKey, recipient_npk: NullifierPublicKey,
recipient_vpk: ViewingPublicKey, recipient_vpk: ViewingPublicKey,
recipient_identifier: Identifier, recipient_identifier: Identifier,
amount: u128, amount: u128,
sender_mention: &CliAccountMention,
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> { ) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
let sender_identity = sender_mention.key_path().map_or(
AccountIdentity::Public(sender_account_id),
|key_path| AccountIdentity::PublicKeycard {
account_id: sender_account_id,
key_path: key_path.to_owned(),
},
);
let instruction = Instruction::Transfer { let instruction = Instruction::Transfer {
amount_to_transfer: amount, amount_to_transfer: amount,
}; };
@ -355,7 +293,7 @@ impl Token<'_> {
self.0 self.0
.send_privacy_preserving_tx( .send_privacy_preserving_tx(
vec![ vec![
sender_identity, sender,
AccountIdentity::PrivateForeign { AccountIdentity::PrivateForeign {
npk: recipient_npk, npk: recipient_npk,
vpk: recipient_vpk, vpk: recipient_vpk,
@ -378,18 +316,9 @@ impl Token<'_> {
pub async fn send_burn_transaction( pub async fn send_burn_transaction(
&self, &self,
definition_account_id: AccountId, definition_account_id: AccountId,
holder_account_id: AccountId, holder: AccountIdentity,
amount: u128, amount: u128,
holder_mention: &CliAccountMention,
) -> Result<HashType, ExecutionFailureKind> { ) -> Result<HashType, ExecutionFailureKind> {
let holder_identity = holder_mention.key_path().map_or(
AccountIdentity::Public(holder_account_id),
|key_path| AccountIdentity::PublicKeycard {
account_id: holder_account_id,
key_path: key_path.to_owned(),
},
);
let program = Program::token(); let program = Program::token();
let instruction = Instruction::Burn { let instruction = Instruction::Burn {
amount_to_burn: amount, amount_to_burn: amount,
@ -399,10 +328,7 @@ impl Token<'_> {
self.0 self.0
.send_pub_tx( .send_pub_tx(
vec![ vec![AccountIdentity::PublicNoSign(definition_account_id), holder],
AccountIdentity::PublicNoSign(definition_account_id),
holder_identity,
],
instruction_data, instruction_data,
&program.into(), &program.into(),
) )
@ -511,28 +437,10 @@ impl Token<'_> {
pub async fn send_mint_transaction( pub async fn send_mint_transaction(
&self, &self,
definition_account_id: AccountId, definition: AccountIdentity,
holder_account_id: AccountId, holder: AccountIdentity,
amount: u128, amount: u128,
definition_mention: &CliAccountMention,
holder_mention: &CliAccountMention,
) -> Result<HashType, ExecutionFailureKind> { ) -> Result<HashType, ExecutionFailureKind> {
let definition_identity = definition_mention.key_path().map_or(
AccountIdentity::Public(definition_account_id),
|key_path| AccountIdentity::PublicKeycard {
account_id: definition_account_id,
key_path: key_path.to_owned(),
},
);
let holder_identity = holder_mention.key_path().map_or(
AccountIdentity::Public(holder_account_id),
|key_path| AccountIdentity::PublicKeycard {
account_id: holder_account_id,
key_path: key_path.to_owned(),
},
);
let program = Program::token(); let program = Program::token();
let instruction = Instruction::Mint { let instruction = Instruction::Mint {
amount_to_mint: amount, amount_to_mint: amount,
@ -541,11 +449,7 @@ impl Token<'_> {
Program::serialize_instruction(instruction).expect("Instruction should serialize"); Program::serialize_instruction(instruction).expect("Instruction should serialize");
self.0 self.0
.send_pub_tx( .send_pub_tx(vec![definition, holder], instruction_data, &program.into())
vec![definition_identity, holder_identity],
instruction_data,
&program.into(),
)
.await .await
} }

View File

@ -15,17 +15,14 @@ impl KeycardSessionContext {
} }
} }
pub fn get_or_connect<'py>( pub fn get_or_connect(&mut self, py: Python<'_>) -> pyo3::PyResult<&KeycardWallet> {
&'py mut self,
py: Python<'py>,
) -> pyo3::PyResult<&'py KeycardWallet> {
if self.wallet.is_none() { if self.wallet.is_none() {
python_path::add_python_path(py)?; python_path::add_python_path(py)?;
let wallet = KeycardWallet::new(py)?; let wallet = KeycardWallet::new(py)?;
wallet.connect(py, &self.pin)?; wallet.connect(py, &self.pin)?;
self.wallet = Some(wallet); self.wallet = Some(wallet);
} }
Ok(self.wallet.as_ref().unwrap()) Ok(self.wallet.as_ref().expect("wallet was just inserted"))
} }
pub fn close(self, py: Python<'_>) { pub fn close(self, py: Python<'_>) {