905 lines
32 KiB
Rust
Raw Normal View History

use common::{HashType, transaction::NSSATransaction};
2026-04-27 20:16:39 -04:00
use keycard_wallet::KeycardWallet;
2026-05-01 02:44:36 -04:00
use nssa::{AccountId, Signature, PublicKey, program::Program, public_transaction::WitnessSet};
use nssa_core::{Identifier, NullifierPublicKey, SharedSecretKey, encryption::ViewingPublicKey};
use pyo3::exceptions::PyRuntimeError;
use sequencer_service_rpc::RpcClient as _;
use token_core::Instruction;
use crate::{ExecutionFailureKind, PrivacyPreservingAccount, WalletCore};
2026-03-04 18:42:33 +03:00
pub struct Token<'wallet>(pub &'wallet WalletCore);
impl Token<'_> {
pub async fn send_new_definition(
&self,
definition_account_id: AccountId,
supply_account_id: AccountId,
name: String,
total_supply: u128,
2026-05-01 02:44:36 -04:00
definition_key_path: Option<&str>,
supply_key_path: Option<&str>,
) -> Result<HashType, ExecutionFailureKind> {
let account_ids = vec![definition_account_id, supply_account_id];
let program_id = nssa::program::Program::token().id();
let instruction = Instruction::NewFungibleDefinition { name, total_supply };
let nonces = self
.0
.get_accounts_nonces(account_ids.clone())
.await
.map_err(ExecutionFailureKind::SequencerError)?;
let message = nssa::public_transaction::Message::try_new(
program_id,
account_ids,
nonces,
instruction,
)
.unwrap();
2026-05-01 02:44:36 -04:00
let msg_hash = message.hash();
let pin = if definition_key_path.is_some() || supply_key_path.is_some() {
Some(crate::helperfunctions::read_pin().map_err(|e| {
ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<PyRuntimeError, _>(
e.to_string(),
))
})?)
} else {
None
};
let (sig_def, pk_def) = if let Some(kp) = definition_key_path {
KeycardWallet::sign_message_for_path_with_connect(pin.as_ref().unwrap(), kp, &msg_hash)?
} else {
let sk = self
.0
.storage
.user_data
.get_pub_account_signing_key(definition_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?;
(Signature::new(&sk, &msg_hash), PublicKey::new_from_private_key(&sk))
};
2026-05-01 02:44:36 -04:00
let (sig_sup, pk_sup) = if let Some(kp) = supply_key_path {
KeycardWallet::sign_message_for_path_with_connect(pin.as_ref().unwrap(), kp, &msg_hash)?
} else {
let sk = self
.0
.storage
.user_data
.get_pub_account_signing_key(supply_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?;
(Signature::new(&sk, &msg_hash), PublicKey::new_from_private_key(&sk))
};
let witness_set = nssa::public_transaction::WitnessSet::from_list(
&message,
2026-05-01 02:44:36 -04:00
&[sig_def, sig_sup],
&[pk_def, pk_sup],
)
.map_err(ExecutionFailureKind::TransactionBuildError)?;
let tx = nssa::PublicTransaction::new(message, witness_set);
Ok(self
.0
.sequencer_client
.send_transaction(NSSATransaction::Public(tx))
.await?)
}
2025-12-02 15:27:20 +02:00
pub async fn send_new_definition_private_owned_supply(
&self,
definition_account_id: AccountId,
supply_account_id: AccountId,
name: String,
total_supply: u128,
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
let instruction = Instruction::NewFungibleDefinition { name, total_supply };
let instruction_data =
Program::serialize_instruction(instruction).expect("Instruction should serialize");
self.0
.send_privacy_preserving_tx(
vec![
PrivacyPreservingAccount::Public(definition_account_id),
PrivacyPreservingAccount::PrivateOwned(supply_account_id),
],
instruction_data,
&Program::token().into(),
2026-04-27 20:16:39 -04:00
&None,
)
.await
.map(|(resp, secrets)| {
let first = secrets
.into_iter()
.next()
2025-12-02 15:27:20 +02:00
.expect("expected supply's secret");
(resp, first)
})
}
2025-12-02 15:27:20 +02:00
pub async fn send_new_definition_private_owned_definiton(
&self,
definition_account_id: AccountId,
supply_account_id: AccountId,
name: String,
2025-12-02 15:27:20 +02:00
total_supply: u128,
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
let instruction = Instruction::NewFungibleDefinition { name, total_supply };
let instruction_data =
Program::serialize_instruction(instruction).expect("Instruction should serialize");
2025-12-02 15:27:20 +02:00
self.0
.send_privacy_preserving_tx(
vec![
PrivacyPreservingAccount::PrivateOwned(definition_account_id),
PrivacyPreservingAccount::Public(supply_account_id),
],
instruction_data,
&Program::token().into(),
2026-04-27 20:16:39 -04:00
&None,
2025-12-02 15:27:20 +02:00
)
.await
.map(|(resp, secrets)| {
let first = secrets
.into_iter()
.next()
.expect("expected definition's secret");
(resp, first)
})
}
pub async fn send_new_definition_private_owned_definiton_and_supply(
&self,
definition_account_id: AccountId,
supply_account_id: AccountId,
name: String,
2025-12-02 15:27:20 +02:00
total_supply: u128,
) -> Result<(HashType, [SharedSecretKey; 2]), ExecutionFailureKind> {
let instruction = Instruction::NewFungibleDefinition { name, total_supply };
let instruction_data =
Program::serialize_instruction(instruction).expect("Instruction should serialize");
2025-12-02 15:27:20 +02:00
self.0
.send_privacy_preserving_tx(
vec![
PrivacyPreservingAccount::PrivateOwned(definition_account_id),
PrivacyPreservingAccount::PrivateOwned(supply_account_id),
],
instruction_data,
&Program::token().into(),
2026-04-27 20:16:39 -04:00
&None,
2025-12-02 15:27:20 +02:00
)
.await
.map(|(resp, secrets)| {
let mut iter = secrets.into_iter();
let first = iter.next().expect("expected definition's secret");
let second = iter.next().expect("expected supply's secret");
(resp, [first, second])
})
}
pub async fn send_transfer_transaction(
&self,
sender_account_id: AccountId,
recipient_account_id: AccountId,
amount: u128,
2026-04-27 20:16:39 -04:00
sender_key_path: Option<String>,
) -> Result<HashType, ExecutionFailureKind> {
let account_ids = vec![sender_account_id, recipient_account_id];
let program_id = nssa::program::Program::token().id();
let instruction = Instruction::Transfer {
amount_to_transfer: amount,
};
let mut nonces = self
2026-03-04 18:42:33 +03:00
.0
.get_accounts_nonces(vec![sender_account_id])
.await
.map_err(ExecutionFailureKind::SequencerError)?;
2026-04-27 20:16:39 -04:00
let recipient_nonces = self
2026-04-27 20:12:57 -04:00
.0
2026-04-27 20:16:39 -04:00
.get_accounts_nonces(vec![recipient_account_id])
.await
.map_err(ExecutionFailureKind::SequencerError)?;
nonces.extend(recipient_nonces);
let message = nssa::public_transaction::Message::try_new(
program_id,
account_ids,
nonces,
instruction,
)
.unwrap();
2026-05-01 02:44:36 -04:00
let witness_set = if let Some(sender_key_path) = sender_key_path {
let pin = crate::helperfunctions::read_pin().map_err(|e| {
ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<PyRuntimeError, _>(
e.to_string(),
))
})?;
let (signature, public_key) = KeycardWallet::sign_message_for_path_with_connect(
2026-04-29 07:52:15 -04:00
&pin,
2026-05-01 02:44:36 -04:00
&sender_key_path,
&message.hash(),
2026-04-29 07:52:15 -04:00
)
.expect("Expect a valid signature");
2026-05-01 02:44:36 -04:00
WitnessSet::from_list(&message, &[signature], &[public_key])
2026-04-29 07:52:15 -04:00
} else {
2026-04-27 20:16:39 -04:00
let mut private_keys = Vec::new();
let sender_sk = self
.0
.storage
.user_data
.get_pub_account_signing_key(sender_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?;
private_keys.push(sender_sk);
if let Some(recipient_sk) = self
.0
.storage
.user_data
.get_pub_account_signing_key(recipient_account_id)
{
private_keys.push(recipient_sk);
} else {
println!(
"Receiver's account ({recipient_account_id}) private key not found in wallet. Proceeding with only sender's key."
);
}
2026-05-01 02:44:36 -04:00
Ok(nssa::public_transaction::WitnessSet::for_message(
&message,
&private_keys,
))
2026-04-27 20:16:39 -04:00
};
2026-05-01 02:44:36 -04:00
let tx = nssa::PublicTransaction::new(message, witness_set.unwrap()); //TODO: Marvin
Ok(self
.0
.sequencer_client
.send_transaction(NSSATransaction::Public(tx))
.await?)
}
pub async fn send_transfer_transaction_private_owned_account(
&self,
sender_account_id: AccountId,
recipient_account_id: AccountId,
amount: u128,
) -> Result<(HashType, [SharedSecretKey; 2]), ExecutionFailureKind> {
let instruction = Instruction::Transfer {
amount_to_transfer: amount,
};
let instruction_data =
Program::serialize_instruction(instruction).expect("Instruction should serialize");
self.0
.send_privacy_preserving_tx(
vec![
PrivacyPreservingAccount::PrivateOwned(sender_account_id),
PrivacyPreservingAccount::PrivateOwned(recipient_account_id),
],
instruction_data,
&Program::token().into(),
2026-04-27 20:16:39 -04:00
&None,
)
.await
.map(|(resp, secrets)| {
let mut iter = secrets.into_iter();
let first = iter.next().expect("expected sender's secret");
let second = iter.next().expect("expected recipient's secret");
(resp, [first, second])
})
}
pub async fn send_transfer_transaction_private_foreign_account(
&self,
sender_account_id: AccountId,
recipient_npk: NullifierPublicKey,
2026-01-21 17:27:23 -05:00
recipient_vpk: ViewingPublicKey,
2026-04-15 17:21:16 -03:00
recipient_identifier: Identifier,
amount: u128,
) -> Result<(HashType, [SharedSecretKey; 2]), ExecutionFailureKind> {
let instruction = Instruction::Transfer {
amount_to_transfer: amount,
};
let instruction_data =
Program::serialize_instruction(instruction).expect("Instruction should serialize");
self.0
.send_privacy_preserving_tx(
vec![
PrivacyPreservingAccount::PrivateOwned(sender_account_id),
PrivacyPreservingAccount::PrivateForeign {
npk: recipient_npk,
2026-01-21 17:27:23 -05:00
vpk: recipient_vpk,
2026-04-15 17:21:16 -03:00
identifier: recipient_identifier,
},
],
instruction_data,
&Program::token().into(),
2026-04-27 20:16:39 -04:00
&None,
)
.await
.map(|(resp, secrets)| {
let mut iter = secrets.into_iter();
let first = iter.next().expect("expected sender's secret");
let second = iter.next().expect("expected recipient's secret");
(resp, [first, second])
})
}
pub async fn send_transfer_transaction_deshielded(
&self,
sender_account_id: AccountId,
recipient_account_id: AccountId,
amount: u128,
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
let instruction = Instruction::Transfer {
amount_to_transfer: amount,
};
let instruction_data =
Program::serialize_instruction(instruction).expect("Instruction should serialize");
self.0
.send_privacy_preserving_tx(
vec![
PrivacyPreservingAccount::PrivateOwned(sender_account_id),
PrivacyPreservingAccount::Public(recipient_account_id),
],
instruction_data,
&Program::token().into(),
2026-04-27 20:16:39 -04:00
&None,
)
.await
.map(|(resp, secrets)| {
let first = secrets
.into_iter()
.next()
.expect("expected sender's secret");
(resp, first)
})
}
pub async fn send_transfer_transaction_shielded_owned_account(
&self,
sender_account_id: AccountId,
recipient_account_id: AccountId,
amount: u128,
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
let instruction = Instruction::Transfer {
amount_to_transfer: amount,
};
let instruction_data =
Program::serialize_instruction(instruction).expect("Instruction should serialize");
self.0
.send_privacy_preserving_tx(
vec![
PrivacyPreservingAccount::Public(sender_account_id),
PrivacyPreservingAccount::PrivateOwned(recipient_account_id),
],
instruction_data,
&Program::token().into(),
2026-04-27 20:16:39 -04:00
&None,
)
.await
.map(|(resp, secrets)| {
let first = secrets
.into_iter()
.next()
.expect("expected recipient's secret");
(resp, first)
})
}
pub async fn send_transfer_transaction_shielded_foreign_account(
&self,
sender_account_id: AccountId,
recipient_npk: NullifierPublicKey,
2026-01-21 17:27:23 -05:00
recipient_vpk: ViewingPublicKey,
2026-04-15 17:21:16 -03:00
recipient_identifier: Identifier,
amount: u128,
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
let instruction = Instruction::Transfer {
amount_to_transfer: amount,
};
let instruction_data =
Program::serialize_instruction(instruction).expect("Instruction should serialize");
self.0
.send_privacy_preserving_tx(
vec![
PrivacyPreservingAccount::Public(sender_account_id),
PrivacyPreservingAccount::PrivateForeign {
npk: recipient_npk,
2026-01-21 17:27:23 -05:00
vpk: recipient_vpk,
2026-04-15 17:21:16 -03:00
identifier: recipient_identifier,
},
],
instruction_data,
&Program::token().into(),
2026-04-27 20:16:39 -04:00
&None,
)
.await
.map(|(resp, secrets)| {
let first = secrets
.into_iter()
.next()
.expect("expected recipient's secret");
(resp, first)
})
}
2025-12-11 14:46:16 +02:00
2026-05-01 02:44:36 -04:00
pub async fn send_initialize_account(
&self,
definition_account: PrivacyPreservingAccount,
holder_account: PrivacyPreservingAccount,
key_path: &Option<String>,
) -> Result<(HashType, Vec<SharedSecretKey>), ExecutionFailureKind> {
let instruction = Instruction::InitializeAccount;
if definition_account.is_public() && holder_account.is_public() {
let PrivacyPreservingAccount::Public(definition_account_id) = definition_account else {
unreachable!()
};
let PrivacyPreservingAccount::Public(holder_account_id) = holder_account else {
unreachable!()
};
let nonces = self
.0
.get_accounts_nonces(vec![holder_account_id])
.await
.map_err(ExecutionFailureKind::SequencerError)?;
let message = nssa::public_transaction::Message::try_new(
Program::token().id(),
vec![definition_account_id, holder_account_id],
nonces,
instruction,
)
.expect("Instruction should serialize");
let witness_set = if let Some(key_path) = key_path {
let pin = crate::helperfunctions::read_pin().map_err(|e| {
ExecutionFailureKind::KeycardError(
pyo3::PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(e.to_string()),
)
})?;
let (signature, pub_key) = keycard_wallet::KeycardWallet::sign_message_for_path_with_connect(
&pin,
key_path,
&message.hash(),
)?;
nssa::public_transaction::WitnessSet::from_list(&message, &[signature], &[pub_key])
.map_err(ExecutionFailureKind::TransactionBuildError)?
} else {
let signing_key = self
.0
.storage
.user_data
.get_pub_account_signing_key(holder_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?;
nssa::public_transaction::WitnessSet::for_message(&message, &[signing_key])
};
let tx = nssa::PublicTransaction::new(message, witness_set);
let hash = self
.0
.sequencer_client
.send_transaction(NSSATransaction::Public(tx))
.await?;
Ok((hash, vec![]))
} else {
let instruction_data =
Program::serialize_instruction(instruction).expect("Instruction should serialize");
self.0
.send_privacy_preserving_tx(
vec![definition_account, holder_account],
instruction_data,
&Program::token().into(),
key_path,
)
.await
.map(|(resp, secrets)| (resp, secrets))
}
}
2025-12-11 14:46:16 +02:00
pub async fn send_burn_transaction(
&self,
definition_account_id: AccountId,
holder_account_id: AccountId,
amount: u128,
2026-05-01 02:44:36 -04:00
holder_key_path: Option<&str>,
) -> Result<HashType, ExecutionFailureKind> {
2025-12-11 14:46:16 +02:00
let account_ids = vec![definition_account_id, holder_account_id];
let instruction = Instruction::Burn {
amount_to_burn: amount,
};
2025-12-11 14:46:16 +02:00
2026-03-04 18:42:33 +03:00
let nonces = self
.0
.get_accounts_nonces(vec![holder_account_id])
.await
.map_err(ExecutionFailureKind::SequencerError)?;
2025-12-11 14:46:16 +02:00
let message = nssa::public_transaction::Message::try_new(
Program::token().id(),
2025-12-11 14:46:16 +02:00
account_ids,
nonces,
2025-12-11 14:46:16 +02:00
instruction,
)
2025-12-22 04:02:12 +02:00
.expect("Instruction should serialize");
2025-12-11 14:46:16 +02:00
2026-05-01 02:44:36 -04:00
let msg_hash = message.hash();
let witness_set = if let Some(kp) = holder_key_path {
let pin = crate::helperfunctions::read_pin().map_err(|e| {
ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<PyRuntimeError, _>(
e.to_string(),
))
})?;
let (sig, pk) =
KeycardWallet::sign_message_for_path_with_connect(&pin, kp, &msg_hash)?;
nssa::public_transaction::WitnessSet::from_list(&message, &[sig], &[pk])
.map_err(ExecutionFailureKind::TransactionBuildError)?
} else {
let signing_key = self
.0
.storage
.user_data
.get_pub_account_signing_key(holder_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?;
nssa::public_transaction::WitnessSet::for_message(&message, &[signing_key])
};
2025-12-11 14:46:16 +02:00
let tx = nssa::PublicTransaction::new(message, witness_set);
Ok(self
.0
.sequencer_client
.send_transaction(NSSATransaction::Public(tx))
.await?)
2025-12-11 14:46:16 +02:00
}
pub async fn send_burn_transaction_private_owned_account(
&self,
definition_account_id: AccountId,
holder_account_id: AccountId,
amount: u128,
) -> Result<(HashType, [SharedSecretKey; 2]), ExecutionFailureKind> {
let instruction = Instruction::Burn {
amount_to_burn: amount,
};
let instruction_data =
Program::serialize_instruction(instruction).expect("Instruction should serialize");
2025-12-11 14:46:16 +02:00
self.0
.send_privacy_preserving_tx(
vec![
PrivacyPreservingAccount::PrivateOwned(definition_account_id),
PrivacyPreservingAccount::PrivateOwned(holder_account_id),
],
instruction_data,
&Program::token().into(),
2026-04-27 20:16:39 -04:00
&None,
2025-12-11 14:46:16 +02:00
)
.await
.map(|(resp, secrets)| {
let mut iter = secrets.into_iter();
let first = iter.next().expect("expected definition's secret");
let second = iter.next().expect("expected holder's secret");
(resp, [first, second])
})
}
pub async fn send_burn_transaction_deshielded_owned_account(
&self,
definition_account_id: AccountId,
holder_account_id: AccountId,
amount: u128,
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
let instruction = Instruction::Burn {
amount_to_burn: amount,
};
let instruction_data =
Program::serialize_instruction(instruction).expect("Instruction should serialize");
2025-12-11 14:46:16 +02:00
self.0
.send_privacy_preserving_tx(
vec![
PrivacyPreservingAccount::PrivateOwned(definition_account_id),
PrivacyPreservingAccount::Public(holder_account_id),
],
instruction_data,
&Program::token().into(),
2026-04-27 20:16:39 -04:00
&None,
2025-12-11 14:46:16 +02:00
)
.await
.map(|(resp, secrets)| {
let first = secrets
.into_iter()
.next()
.expect("expected definition's secret");
(resp, first)
})
}
pub async fn send_burn_transaction_shielded(
&self,
definition_account_id: AccountId,
holder_account_id: AccountId,
amount: u128,
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
let instruction = Instruction::Burn {
amount_to_burn: amount,
};
let instruction_data =
Program::serialize_instruction(instruction).expect("Instruction should serialize");
2025-12-11 14:46:16 +02:00
self.0
.send_privacy_preserving_tx(
vec![
PrivacyPreservingAccount::Public(definition_account_id),
PrivacyPreservingAccount::PrivateOwned(holder_account_id),
],
instruction_data,
&Program::token().into(),
2026-04-27 20:16:39 -04:00
&None,
2025-12-11 14:46:16 +02:00
)
.await
.map(|(resp, secrets)| {
let first = secrets
.into_iter()
.next()
.expect("expected holder's secret");
(resp, first)
})
}
pub async fn send_mint_transaction(
&self,
definition_account_id: AccountId,
holder_account_id: AccountId,
amount: u128,
2026-05-01 02:44:36 -04:00
definition_key_path: Option<&str>,
) -> Result<HashType, ExecutionFailureKind> {
2025-12-11 14:46:16 +02:00
let account_ids = vec![definition_account_id, holder_account_id];
let instruction = Instruction::Mint {
amount_to_mint: amount,
};
2025-12-11 14:46:16 +02:00
let mut nonces = self
2025-12-11 14:46:16 +02:00
.0
.get_accounts_nonces(vec![definition_account_id])
.await
2026-03-04 18:42:33 +03:00
.map_err(ExecutionFailureKind::SequencerError)?;
2026-05-01 02:44:36 -04:00
if self
.0
.storage
.user_data
.get_pub_account_signing_key(holder_account_id)
2026-05-01 02:44:36 -04:00
.is_some()
{
let recipient_nonces = self
.0
.get_accounts_nonces(vec![holder_account_id])
.await
.map_err(ExecutionFailureKind::SequencerError)?;
nonces.extend(recipient_nonces);
} else {
println!(
"Holder's account ({holder_account_id}) private key not found in wallet. Proceeding with only definition's key."
);
}
2025-12-11 14:46:16 +02:00
let message = nssa::public_transaction::Message::try_new(
Program::token().id(),
2025-12-11 14:46:16 +02:00
account_ids,
nonces,
2025-12-11 14:46:16 +02:00
instruction,
)
.unwrap();
2026-05-01 02:44:36 -04:00
let msg_hash = message.hash();
let witness_set = if let Some(kp) = definition_key_path {
let pin = crate::helperfunctions::read_pin().map_err(|e| {
ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<PyRuntimeError, _>(
e.to_string(),
))
})?;
let (sig, pk) =
KeycardWallet::sign_message_for_path_with_connect(&pin, kp, &msg_hash)?;
nssa::public_transaction::WitnessSet::from_list(&message, &[sig], &[pk])
.map_err(ExecutionFailureKind::TransactionBuildError)?
} else {
let signing_key = self
.0
.storage
.user_data
.get_pub_account_signing_key(definition_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?;
nssa::public_transaction::WitnessSet::for_message(&message, &[signing_key])
};
2025-12-11 14:46:16 +02:00
let tx = nssa::PublicTransaction::new(message, witness_set);
Ok(self
.0
.sequencer_client
.send_transaction(NSSATransaction::Public(tx))
.await?)
2025-12-11 14:46:16 +02:00
}
pub async fn send_mint_transaction_private_owned_account(
&self,
definition_account_id: AccountId,
holder_account_id: AccountId,
amount: u128,
) -> Result<(HashType, [SharedSecretKey; 2]), ExecutionFailureKind> {
let instruction = Instruction::Mint {
amount_to_mint: amount,
};
let instruction_data =
Program::serialize_instruction(instruction).expect("Instruction should serialize");
2025-12-11 14:46:16 +02:00
self.0
.send_privacy_preserving_tx(
vec![
PrivacyPreservingAccount::PrivateOwned(definition_account_id),
PrivacyPreservingAccount::PrivateOwned(holder_account_id),
],
instruction_data,
&Program::token().into(),
2026-04-27 20:16:39 -04:00
&None,
2025-12-11 14:46:16 +02:00
)
.await
.map(|(resp, secrets)| {
let mut iter = secrets.into_iter();
let first = iter.next().expect("expected definition's secret");
let second = iter.next().expect("expected holder's secret");
(resp, [first, second])
})
}
pub async fn send_mint_transaction_private_foreign_account(
&self,
definition_account_id: AccountId,
holder_npk: NullifierPublicKey,
2026-01-21 17:27:23 -05:00
holder_vpk: ViewingPublicKey,
2026-04-15 17:21:16 -03:00
holder_identifier: Identifier,
2025-12-11 14:46:16 +02:00
amount: u128,
) -> Result<(HashType, [SharedSecretKey; 2]), ExecutionFailureKind> {
let instruction = Instruction::Mint {
amount_to_mint: amount,
};
let instruction_data =
Program::serialize_instruction(instruction).expect("Instruction should serialize");
2025-12-11 14:46:16 +02:00
self.0
.send_privacy_preserving_tx(
vec![
PrivacyPreservingAccount::PrivateOwned(definition_account_id),
PrivacyPreservingAccount::PrivateForeign {
npk: holder_npk,
2026-01-21 17:27:23 -05:00
vpk: holder_vpk,
2026-04-15 17:21:16 -03:00
identifier: holder_identifier,
2025-12-11 14:46:16 +02:00
},
],
instruction_data,
&Program::token().into(),
2026-04-27 20:16:39 -04:00
&None,
2025-12-11 14:46:16 +02:00
)
.await
.map(|(resp, secrets)| {
let mut iter = secrets.into_iter();
let first = iter.next().expect("expected definition's secret");
let second = iter.next().expect("expected holder's secret");
(resp, [first, second])
})
}
pub async fn send_mint_transaction_deshielded(
&self,
definition_account_id: AccountId,
holder_account_id: AccountId,
amount: u128,
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
let instruction = Instruction::Mint {
amount_to_mint: amount,
};
let instruction_data =
Program::serialize_instruction(instruction).expect("Instruction should serialize");
2025-12-11 14:46:16 +02:00
self.0
.send_privacy_preserving_tx(
vec![
PrivacyPreservingAccount::PrivateOwned(definition_account_id),
PrivacyPreservingAccount::Public(holder_account_id),
],
instruction_data,
&Program::token().into(),
2026-04-27 20:16:39 -04:00
&None,
2025-12-11 14:46:16 +02:00
)
.await
.map(|(resp, secrets)| {
let first = secrets
.into_iter()
.next()
.expect("expected definition's secret");
(resp, first)
})
}
pub async fn send_mint_transaction_shielded_owned_account(
&self,
definition_account_id: AccountId,
holder_account_id: AccountId,
amount: u128,
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
let instruction = Instruction::Mint {
amount_to_mint: amount,
};
let instruction_data =
Program::serialize_instruction(instruction).expect("Instruction should serialize");
2025-12-11 14:46:16 +02:00
self.0
.send_privacy_preserving_tx(
vec![
PrivacyPreservingAccount::Public(definition_account_id),
PrivacyPreservingAccount::PrivateOwned(holder_account_id),
],
instruction_data,
&Program::token().into(),
2026-04-27 20:16:39 -04:00
&None,
2025-12-11 14:46:16 +02:00
)
.await
.map(|(resp, secrets)| {
let first = secrets
.into_iter()
.next()
.expect("expected holder's secret");
(resp, first)
})
}
pub async fn send_mint_transaction_shielded_foreign_account(
&self,
definition_account_id: AccountId,
holder_npk: NullifierPublicKey,
2026-01-21 17:27:23 -05:00
holder_vpk: ViewingPublicKey,
2026-04-15 17:21:16 -03:00
holder_identifier: Identifier,
2025-12-11 14:46:16 +02:00
amount: u128,
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
let instruction = Instruction::Mint {
amount_to_mint: amount,
};
let instruction_data =
Program::serialize_instruction(instruction).expect("Instruction should serialize");
2025-12-11 14:46:16 +02:00
self.0
.send_privacy_preserving_tx(
vec![
PrivacyPreservingAccount::Public(definition_account_id),
PrivacyPreservingAccount::PrivateForeign {
npk: holder_npk,
2026-01-21 17:27:23 -05:00
vpk: holder_vpk,
2026-04-15 17:21:16 -03:00
identifier: holder_identifier,
2025-12-11 14:46:16 +02:00
},
],
instruction_data,
&Program::token().into(),
2026-04-27 20:16:39 -04:00
&None,
2025-12-11 14:46:16 +02:00
)
.await
.map(|(resp, secrets)| {
let first = secrets
.into_iter()
.next()
.expect("expected holder's secret");
(resp, first)
})
}
}