2026-03-13 22:38:23 +03:00
|
|
|
use common::{HashType, transaction::NSSATransaction};
|
2026-04-27 20:16:39 -04:00
|
|
|
use keycard_wallet::KeycardWallet;
|
2026-05-04 10:03:44 -04:00
|
|
|
use nssa::{AccountId, PublicKey, Signature, program::Program, public_transaction::WitnessSet};
|
2026-05-01 02:44:36 -04:00
|
|
|
use nssa_core::{Identifier, NullifierPublicKey, SharedSecretKey, encryption::ViewingPublicKey};
|
|
|
|
|
use pyo3::exceptions::PyRuntimeError;
|
2026-03-13 22:38:23 +03:00
|
|
|
use sequencer_service_rpc::RpcClient as _;
|
2026-01-16 04:11:33 +03:00
|
|
|
use token_core::Instruction;
|
2025-11-30 01:57:59 +03:00
|
|
|
|
2026-03-13 22:38:23 +03:00
|
|
|
use crate::{ExecutionFailureKind, PrivacyPreservingAccount, WalletCore};
|
2025-11-30 01:57:59 +03:00
|
|
|
|
2026-03-04 18:42:33 +03:00
|
|
|
pub struct Token<'wallet>(pub &'wallet WalletCore);
|
2025-11-30 01:57:59 +03:00
|
|
|
|
|
|
|
|
impl Token<'_> {
|
|
|
|
|
pub async fn send_new_definition(
|
|
|
|
|
&self,
|
|
|
|
|
definition_account_id: AccountId,
|
|
|
|
|
supply_account_id: AccountId,
|
2026-01-16 04:11:33 +03:00
|
|
|
name: String,
|
2025-11-30 01:57:59 +03:00
|
|
|
total_supply: u128,
|
2026-05-01 02:44:36 -04:00
|
|
|
definition_key_path: Option<&str>,
|
|
|
|
|
supply_key_path: Option<&str>,
|
2026-03-13 22:38:23 +03:00
|
|
|
) -> Result<HashType, ExecutionFailureKind> {
|
2025-11-30 01:57:59 +03:00
|
|
|
let account_ids = vec![definition_account_id, supply_account_id];
|
|
|
|
|
let program_id = nssa::program::Program::token().id();
|
2026-01-16 04:11:33 +03:00
|
|
|
let instruction = Instruction::NewFungibleDefinition { name, total_supply };
|
2026-03-27 21:43:28 +03:00
|
|
|
let nonces = self
|
|
|
|
|
.0
|
|
|
|
|
.get_accounts_nonces(account_ids.clone())
|
|
|
|
|
.await
|
|
|
|
|
.map_err(ExecutionFailureKind::SequencerError)?;
|
2025-11-30 01:57:59 +03:00
|
|
|
let message = nssa::public_transaction::Message::try_new(
|
|
|
|
|
program_id,
|
|
|
|
|
account_ids,
|
2026-03-27 21:43:28 +03:00
|
|
|
nonces,
|
2025-11-30 01:57:59 +03:00
|
|
|
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)?;
|
2026-05-04 10:03:44 -04:00
|
|
|
(
|
|
|
|
|
Signature::new(sk, &msg_hash),
|
|
|
|
|
PublicKey::new_from_private_key(sk),
|
|
|
|
|
)
|
2026-05-01 02:44:36 -04:00
|
|
|
};
|
2026-03-27 21:43:28 +03:00
|
|
|
|
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)?;
|
2026-05-04 10:03:44 -04:00
|
|
|
(
|
|
|
|
|
Signature::new(sk, &msg_hash),
|
|
|
|
|
PublicKey::new_from_private_key(sk),
|
|
|
|
|
)
|
2026-05-01 02:44:36 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let witness_set = nssa::public_transaction::WitnessSet::from_list(
|
2026-03-27 21:43:28 +03:00
|
|
|
&message,
|
2026-05-01 02:44:36 -04:00
|
|
|
&[sig_def, sig_sup],
|
|
|
|
|
&[pk_def, pk_sup],
|
|
|
|
|
)
|
|
|
|
|
.map_err(ExecutionFailureKind::TransactionBuildError)?;
|
2025-11-30 01:57:59 +03:00
|
|
|
|
|
|
|
|
let tx = nssa::PublicTransaction::new(message, witness_set);
|
|
|
|
|
|
2026-03-13 22:38:23 +03:00
|
|
|
Ok(self
|
|
|
|
|
.0
|
|
|
|
|
.sequencer_client
|
|
|
|
|
.send_transaction(NSSATransaction::Public(tx))
|
|
|
|
|
.await?)
|
2025-11-30 01:57:59 +03:00
|
|
|
}
|
|
|
|
|
|
2025-12-02 15:27:20 +02:00
|
|
|
pub async fn send_new_definition_private_owned_supply(
|
2025-11-30 01:57:59 +03:00
|
|
|
&self,
|
|
|
|
|
definition_account_id: AccountId,
|
|
|
|
|
supply_account_id: AccountId,
|
2026-01-16 04:11:33 +03:00
|
|
|
name: String,
|
2025-11-30 01:57:59 +03:00
|
|
|
total_supply: u128,
|
2026-03-13 22:38:23 +03:00
|
|
|
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
|
2026-01-16 04:11:33 +03:00
|
|
|
let instruction = Instruction::NewFungibleDefinition { name, total_supply };
|
2025-12-26 14:58:41 +03:00
|
|
|
let instruction_data =
|
|
|
|
|
Program::serialize_instruction(instruction).expect("Instruction should serialize");
|
2025-11-30 01:57:59 +03:00
|
|
|
|
|
|
|
|
self.0
|
|
|
|
|
.send_privacy_preserving_tx(
|
|
|
|
|
vec![
|
|
|
|
|
PrivacyPreservingAccount::Public(definition_account_id),
|
|
|
|
|
PrivacyPreservingAccount::PrivateOwned(supply_account_id),
|
|
|
|
|
],
|
2025-12-25 01:49:34 +03:00
|
|
|
instruction_data,
|
2025-12-26 14:58:41 +03:00
|
|
|
&Program::token().into(),
|
2026-04-27 20:16:39 -04:00
|
|
|
&None,
|
2025-11-30 01:57:59 +03:00
|
|
|
)
|
|
|
|
|
.await
|
|
|
|
|
.map(|(resp, secrets)| {
|
|
|
|
|
let first = secrets
|
|
|
|
|
.into_iter()
|
|
|
|
|
.next()
|
2025-12-02 15:27:20 +02:00
|
|
|
.expect("expected supply's secret");
|
2025-11-30 01:57:59 +03:00
|
|
|
(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,
|
2026-01-16 04:11:33 +03:00
|
|
|
name: String,
|
2025-12-02 15:27:20 +02:00
|
|
|
total_supply: u128,
|
2026-03-13 22:38:23 +03:00
|
|
|
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
|
2026-01-16 04:11:33 +03:00
|
|
|
let instruction = Instruction::NewFungibleDefinition { name, total_supply };
|
2025-12-26 14:58:41 +03:00
|
|
|
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),
|
|
|
|
|
],
|
2025-12-25 01:49:34 +03:00
|
|
|
instruction_data,
|
2025-12-26 14:58:41 +03:00
|
|
|
&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,
|
2026-01-16 04:11:33 +03:00
|
|
|
name: String,
|
2025-12-02 15:27:20 +02:00
|
|
|
total_supply: u128,
|
2026-03-13 22:38:23 +03:00
|
|
|
) -> Result<(HashType, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
2026-01-16 04:11:33 +03:00
|
|
|
let instruction = Instruction::NewFungibleDefinition { name, total_supply };
|
2025-12-26 14:58:41 +03:00
|
|
|
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),
|
|
|
|
|
],
|
2025-12-25 01:49:34 +03:00
|
|
|
instruction_data,
|
2025-12-26 14:58:41 +03:00
|
|
|
&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])
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-30 01:57:59 +03:00
|
|
|
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>,
|
2026-03-13 22:38:23 +03:00
|
|
|
) -> Result<HashType, ExecutionFailureKind> {
|
2025-11-30 01:57:59 +03:00
|
|
|
let account_ids = vec![sender_account_id, recipient_account_id];
|
|
|
|
|
let program_id = nssa::program::Program::token().id();
|
2026-01-16 04:11:33 +03:00
|
|
|
let instruction = Instruction::Transfer {
|
|
|
|
|
amount_to_transfer: amount,
|
|
|
|
|
};
|
2026-05-06 20:35:46 -04:00
|
|
|
|
|
|
|
|
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-03-27 21:43:28 +03:00
|
|
|
|
2026-05-06 20:35:46 -04:00
|
|
|
let private_keys = if sender_key_path.is_none() {
|
|
|
|
|
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);
|
|
|
|
|
let recipient_nonces = self
|
|
|
|
|
.0
|
|
|
|
|
.get_accounts_nonces(vec![recipient_account_id])
|
|
|
|
|
.await
|
|
|
|
|
.map_err(ExecutionFailureKind::SequencerError)?;
|
|
|
|
|
nonces.extend(recipient_nonces);
|
|
|
|
|
} else {
|
|
|
|
|
println!(
|
|
|
|
|
"Receiver's account ({recipient_account_id}) private key not found in wallet. Proceeding with only sender's key."
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
private_keys
|
|
|
|
|
} else {
|
|
|
|
|
Vec::new()
|
|
|
|
|
};
|
|
|
|
|
|
2025-11-30 01:57:59 +03:00
|
|
|
let message = nssa::public_transaction::Message::try_new(
|
|
|
|
|
program_id,
|
|
|
|
|
account_ids,
|
2026-03-18 21:58:36 +03:00
|
|
|
nonces,
|
2025-11-30 01:57:59 +03:00
|
|
|
instruction,
|
|
|
|
|
)
|
|
|
|
|
.unwrap();
|
2026-05-01 19:35:57 -04:00
|
|
|
|
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-05-01 19:35:57 -04:00
|
|
|
)?;
|
2026-05-01 02:44:36 -04:00
|
|
|
WitnessSet::from_list(&message, &[signature], &[public_key])
|
2026-05-01 19:35:57 -04:00
|
|
|
.map_err(ExecutionFailureKind::TransactionBuildError)?
|
2026-04-29 07:52:15 -04:00
|
|
|
} else {
|
2026-05-06 20:35:46 -04:00
|
|
|
nssa::public_transaction::WitnessSet::for_message(&message, &private_keys)
|
2026-04-27 20:16:39 -04:00
|
|
|
};
|
2025-11-30 01:57:59 +03:00
|
|
|
|
2026-05-01 19:35:57 -04:00
|
|
|
let tx = nssa::PublicTransaction::new(message, witness_set);
|
2025-11-30 01:57:59 +03:00
|
|
|
|
2026-03-13 22:38:23 +03:00
|
|
|
Ok(self
|
|
|
|
|
.0
|
|
|
|
|
.sequencer_client
|
|
|
|
|
.send_transaction(NSSATransaction::Public(tx))
|
|
|
|
|
.await?)
|
2025-11-30 01:57:59 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub async fn send_transfer_transaction_private_owned_account(
|
|
|
|
|
&self,
|
|
|
|
|
sender_account_id: AccountId,
|
|
|
|
|
recipient_account_id: AccountId,
|
|
|
|
|
amount: u128,
|
2026-03-13 22:38:23 +03:00
|
|
|
) -> Result<(HashType, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
2026-01-16 04:11:33 +03:00
|
|
|
let instruction = Instruction::Transfer {
|
|
|
|
|
amount_to_transfer: amount,
|
|
|
|
|
};
|
2025-12-26 14:58:41 +03:00
|
|
|
let instruction_data =
|
|
|
|
|
Program::serialize_instruction(instruction).expect("Instruction should serialize");
|
2025-11-30 01:57:59 +03:00
|
|
|
|
|
|
|
|
self.0
|
|
|
|
|
.send_privacy_preserving_tx(
|
|
|
|
|
vec![
|
|
|
|
|
PrivacyPreservingAccount::PrivateOwned(sender_account_id),
|
|
|
|
|
PrivacyPreservingAccount::PrivateOwned(recipient_account_id),
|
|
|
|
|
],
|
2025-12-25 01:49:34 +03:00
|
|
|
instruction_data,
|
2025-12-26 14:58:41 +03:00
|
|
|
&Program::token().into(),
|
2026-04-27 20:16:39 -04:00
|
|
|
&None,
|
2025-11-30 01:57:59 +03:00
|
|
|
)
|
|
|
|
|
.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,
|
2025-11-30 01:57:59 +03:00
|
|
|
amount: u128,
|
2026-03-13 22:38:23 +03:00
|
|
|
) -> Result<(HashType, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
2026-01-16 04:11:33 +03:00
|
|
|
let instruction = Instruction::Transfer {
|
|
|
|
|
amount_to_transfer: amount,
|
|
|
|
|
};
|
2025-12-26 14:58:41 +03:00
|
|
|
let instruction_data =
|
|
|
|
|
Program::serialize_instruction(instruction).expect("Instruction should serialize");
|
2025-11-30 01:57:59 +03:00
|
|
|
|
|
|
|
|
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,
|
2025-11-30 01:57:59 +03:00
|
|
|
},
|
|
|
|
|
],
|
2025-12-25 01:49:34 +03:00
|
|
|
instruction_data,
|
2025-12-26 14:58:41 +03:00
|
|
|
&Program::token().into(),
|
2026-04-27 20:16:39 -04:00
|
|
|
&None,
|
2025-11-30 01:57:59 +03:00
|
|
|
)
|
|
|
|
|
.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,
|
2026-03-13 22:38:23 +03:00
|
|
|
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
|
2026-01-16 04:11:33 +03:00
|
|
|
let instruction = Instruction::Transfer {
|
|
|
|
|
amount_to_transfer: amount,
|
|
|
|
|
};
|
2025-12-26 14:58:41 +03:00
|
|
|
let instruction_data =
|
|
|
|
|
Program::serialize_instruction(instruction).expect("Instruction should serialize");
|
2025-11-30 01:57:59 +03:00
|
|
|
|
|
|
|
|
self.0
|
|
|
|
|
.send_privacy_preserving_tx(
|
|
|
|
|
vec![
|
|
|
|
|
PrivacyPreservingAccount::PrivateOwned(sender_account_id),
|
|
|
|
|
PrivacyPreservingAccount::Public(recipient_account_id),
|
|
|
|
|
],
|
2025-12-25 01:49:34 +03:00
|
|
|
instruction_data,
|
2025-12-26 14:58:41 +03:00
|
|
|
&Program::token().into(),
|
2026-04-27 20:16:39 -04:00
|
|
|
&None,
|
2025-11-30 01:57:59 +03:00
|
|
|
)
|
|
|
|
|
.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,
|
2026-05-01 19:35:57 -04:00
|
|
|
sender_key_path: Option<String>,
|
2026-03-13 22:38:23 +03:00
|
|
|
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
|
2026-01-16 04:11:33 +03:00
|
|
|
let instruction = Instruction::Transfer {
|
|
|
|
|
amount_to_transfer: amount,
|
|
|
|
|
};
|
2025-12-26 14:58:41 +03:00
|
|
|
let instruction_data =
|
|
|
|
|
Program::serialize_instruction(instruction).expect("Instruction should serialize");
|
2025-11-30 01:57:59 +03:00
|
|
|
|
|
|
|
|
self.0
|
|
|
|
|
.send_privacy_preserving_tx(
|
|
|
|
|
vec![
|
|
|
|
|
PrivacyPreservingAccount::Public(sender_account_id),
|
|
|
|
|
PrivacyPreservingAccount::PrivateOwned(recipient_account_id),
|
|
|
|
|
],
|
2025-12-25 01:49:34 +03:00
|
|
|
instruction_data,
|
2025-12-26 14:58:41 +03:00
|
|
|
&Program::token().into(),
|
2026-05-01 19:35:57 -04:00
|
|
|
&sender_key_path,
|
2025-11-30 01:57:59 +03:00
|
|
|
)
|
|
|
|
|
.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,
|
2025-11-30 01:57:59 +03:00
|
|
|
amount: u128,
|
2026-03-13 22:38:23 +03:00
|
|
|
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
|
2026-01-16 04:11:33 +03:00
|
|
|
let instruction = Instruction::Transfer {
|
|
|
|
|
amount_to_transfer: amount,
|
|
|
|
|
};
|
2025-12-26 14:58:41 +03:00
|
|
|
let instruction_data =
|
|
|
|
|
Program::serialize_instruction(instruction).expect("Instruction should serialize");
|
2025-11-30 01:57:59 +03:00
|
|
|
|
|
|
|
|
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,
|
2025-11-30 01:57:59 +03:00
|
|
|
},
|
|
|
|
|
],
|
2025-12-25 01:49:34 +03:00
|
|
|
instruction_data,
|
2025-12-26 14:58:41 +03:00
|
|
|
&Program::token().into(),
|
2026-04-27 20:16:39 -04:00
|
|
|
&None,
|
2025-11-30 01:57:59 +03:00
|
|
|
)
|
|
|
|
|
.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| {
|
2026-05-04 10:03:44 -04:00
|
|
|
ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<
|
|
|
|
|
pyo3::exceptions::PyRuntimeError,
|
|
|
|
|
_,
|
|
|
|
|
>(e.to_string()))
|
2026-05-01 02:44:36 -04:00
|
|
|
})?;
|
2026-05-04 10:03:44 -04:00
|
|
|
let (signature, pub_key) =
|
|
|
|
|
keycard_wallet::KeycardWallet::sign_message_for_path_with_connect(
|
|
|
|
|
&pin,
|
|
|
|
|
key_path,
|
|
|
|
|
&message.hash(),
|
|
|
|
|
)?;
|
2026-05-01 02:44:36 -04:00
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
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>,
|
2026-03-13 22:38:23 +03:00
|
|
|
) -> Result<HashType, ExecutionFailureKind> {
|
2025-12-11 14:46:16 +02:00
|
|
|
let account_ids = vec![definition_account_id, holder_account_id];
|
2026-01-16 04:11:33 +03:00
|
|
|
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(
|
2025-12-26 14:58:41 +03:00
|
|
|
Program::token().id(),
|
2025-12-11 14:46:16 +02:00
|
|
|
account_ids,
|
2026-03-18 21:58:36 +03:00
|
|
|
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(),
|
|
|
|
|
))
|
|
|
|
|
})?;
|
2026-05-04 10:03:44 -04:00
|
|
|
let (sig, pk) = KeycardWallet::sign_message_for_path_with_connect(&pin, kp, &msg_hash)?;
|
2026-05-01 02:44:36 -04:00
|
|
|
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);
|
|
|
|
|
|
2026-03-13 22:38:23 +03:00
|
|
|
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,
|
2026-03-13 22:38:23 +03:00
|
|
|
) -> Result<(HashType, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
2026-01-16 04:11:33 +03:00
|
|
|
let instruction = Instruction::Burn {
|
|
|
|
|
amount_to_burn: amount,
|
|
|
|
|
};
|
2025-12-26 14:58:41 +03:00
|
|
|
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),
|
|
|
|
|
],
|
2025-12-25 01:49:34 +03:00
|
|
|
instruction_data,
|
2025-12-26 14:58:41 +03:00
|
|
|
&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,
|
2026-03-13 22:38:23 +03:00
|
|
|
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
|
2026-01-16 04:11:33 +03:00
|
|
|
let instruction = Instruction::Burn {
|
|
|
|
|
amount_to_burn: amount,
|
|
|
|
|
};
|
2025-12-26 14:58:41 +03:00
|
|
|
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),
|
|
|
|
|
],
|
2025-12-25 01:49:34 +03:00
|
|
|
instruction_data,
|
2025-12-26 14:58:41 +03:00
|
|
|
&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,
|
2026-03-13 22:38:23 +03:00
|
|
|
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
|
2026-01-16 04:11:33 +03:00
|
|
|
let instruction = Instruction::Burn {
|
|
|
|
|
amount_to_burn: amount,
|
|
|
|
|
};
|
2025-12-26 14:58:41 +03:00
|
|
|
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),
|
|
|
|
|
],
|
2025-12-25 01:49:34 +03:00
|
|
|
instruction_data,
|
2025-12-26 14:58:41 +03:00
|
|
|
&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>,
|
2026-03-13 22:38:23 +03:00
|
|
|
) -> Result<HashType, ExecutionFailureKind> {
|
2025-12-11 14:46:16 +02:00
|
|
|
let account_ids = vec![definition_account_id, holder_account_id];
|
2026-01-16 04:11:33 +03:00
|
|
|
let instruction = Instruction::Mint {
|
|
|
|
|
amount_to_mint: amount,
|
|
|
|
|
};
|
2025-12-11 14:46:16 +02:00
|
|
|
|
2026-03-27 21:43:28 +03: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-03-27 21:43:28 +03:00
|
|
|
|
2026-05-06 20:35:46 -04:00
|
|
|
let private_keys = if definition_key_path.is_none() {
|
|
|
|
|
let mut private_keys = Vec::new();
|
|
|
|
|
let definition_sk = self
|
2026-03-27 21:43:28 +03:00
|
|
|
.0
|
2026-05-06 20:35:46 -04:00
|
|
|
.storage
|
|
|
|
|
.user_data
|
|
|
|
|
.get_pub_account_signing_key(definition_account_id)
|
|
|
|
|
.ok_or(ExecutionFailureKind::KeyNotFoundError)?;
|
|
|
|
|
private_keys.push(definition_sk);
|
|
|
|
|
|
|
|
|
|
if let Some(holder_sk) = self
|
|
|
|
|
.0
|
|
|
|
|
.storage
|
|
|
|
|
.user_data
|
|
|
|
|
.get_pub_account_signing_key(holder_account_id)
|
|
|
|
|
{
|
|
|
|
|
private_keys.push(holder_sk);
|
|
|
|
|
let holder_nonce: Vec<nssa_core::account::Nonce> = self
|
|
|
|
|
.0
|
|
|
|
|
.get_accounts_nonces(vec![holder_account_id])
|
|
|
|
|
.await
|
|
|
|
|
.map_err(ExecutionFailureKind::SequencerError)?;
|
|
|
|
|
nonces.extend(holder_nonce);
|
|
|
|
|
} else {
|
|
|
|
|
println!(
|
|
|
|
|
"Holder's account ({holder_account_id}) private key not found in wallet. Proceeding with only definition's key."
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
private_keys
|
2026-03-27 21:43:28 +03:00
|
|
|
} else {
|
2026-05-06 20:35:46 -04:00
|
|
|
Vec::new()
|
|
|
|
|
};
|
2026-03-27 21:43:28 +03:00
|
|
|
|
2025-12-11 14:46:16 +02:00
|
|
|
let message = nssa::public_transaction::Message::try_new(
|
2025-12-26 14:58:41 +03:00
|
|
|
Program::token().id(),
|
2025-12-11 14:46:16 +02:00
|
|
|
account_ids,
|
2026-03-18 21:58:36 +03:00
|
|
|
nonces,
|
2025-12-11 14:46:16 +02:00
|
|
|
instruction,
|
|
|
|
|
)
|
|
|
|
|
.unwrap();
|
2026-05-01 02:44:36 -04:00
|
|
|
|
2026-05-06 20:35:46 -04:00
|
|
|
let witness_set = if let Some(definition_key_path) = definition_key_path {
|
2026-05-01 02:44:36 -04:00
|
|
|
let pin = crate::helperfunctions::read_pin().map_err(|e| {
|
|
|
|
|
ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<PyRuntimeError, _>(
|
|
|
|
|
e.to_string(),
|
|
|
|
|
))
|
|
|
|
|
})?;
|
2026-05-06 20:35:46 -04:00
|
|
|
let (signature, public_key) = KeycardWallet::sign_message_for_path_with_connect(
|
|
|
|
|
&pin,
|
|
|
|
|
definition_key_path,
|
|
|
|
|
&message.hash(),
|
|
|
|
|
)?;
|
|
|
|
|
WitnessSet::from_list(&message, &[signature], &[public_key])
|
2026-05-01 02:44:36 -04:00
|
|
|
.map_err(ExecutionFailureKind::TransactionBuildError)?
|
|
|
|
|
} else {
|
2026-05-06 20:35:46 -04:00
|
|
|
nssa::public_transaction::WitnessSet::for_message(&message, &private_keys)
|
2026-05-01 02:44:36 -04:00
|
|
|
};
|
2025-12-11 14:46:16 +02:00
|
|
|
|
|
|
|
|
let tx = nssa::PublicTransaction::new(message, witness_set);
|
|
|
|
|
|
2026-03-13 22:38:23 +03:00
|
|
|
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,
|
2026-03-13 22:38:23 +03:00
|
|
|
) -> Result<(HashType, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
2026-01-16 04:11:33 +03:00
|
|
|
let instruction = Instruction::Mint {
|
|
|
|
|
amount_to_mint: amount,
|
|
|
|
|
};
|
2025-12-26 14:58:41 +03:00
|
|
|
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),
|
|
|
|
|
],
|
2025-12-25 01:49:34 +03:00
|
|
|
instruction_data,
|
2025-12-26 14:58:41 +03:00
|
|
|
&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,
|
2026-03-13 22:38:23 +03:00
|
|
|
) -> Result<(HashType, [SharedSecretKey; 2]), ExecutionFailureKind> {
|
2026-01-16 04:11:33 +03:00
|
|
|
let instruction = Instruction::Mint {
|
|
|
|
|
amount_to_mint: amount,
|
|
|
|
|
};
|
2025-12-26 14:58:41 +03:00
|
|
|
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
|
|
|
},
|
|
|
|
|
],
|
2025-12-25 01:49:34 +03:00
|
|
|
instruction_data,
|
2025-12-26 14:58:41 +03:00
|
|
|
&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,
|
2026-03-13 22:38:23 +03:00
|
|
|
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
|
2026-01-16 04:11:33 +03:00
|
|
|
let instruction = Instruction::Mint {
|
|
|
|
|
amount_to_mint: amount,
|
|
|
|
|
};
|
2025-12-26 14:58:41 +03:00
|
|
|
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),
|
|
|
|
|
],
|
2025-12-25 01:49:34 +03:00
|
|
|
instruction_data,
|
2025-12-26 14:58:41 +03:00
|
|
|
&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,
|
2026-03-13 22:38:23 +03:00
|
|
|
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
|
2026-01-16 04:11:33 +03:00
|
|
|
let instruction = Instruction::Mint {
|
|
|
|
|
amount_to_mint: amount,
|
|
|
|
|
};
|
2025-12-26 14:58:41 +03:00
|
|
|
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),
|
|
|
|
|
],
|
2025-12-25 01:49:34 +03:00
|
|
|
instruction_data,
|
2025-12-26 14:58:41 +03:00
|
|
|
&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,
|
2026-03-13 22:38:23 +03:00
|
|
|
) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> {
|
2026-01-16 04:11:33 +03:00
|
|
|
let instruction = Instruction::Mint {
|
|
|
|
|
amount_to_mint: amount,
|
|
|
|
|
};
|
2025-12-26 14:58:41 +03:00
|
|
|
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
|
|
|
},
|
|
|
|
|
],
|
2025-12-25 01:49:34 +03:00
|
|
|
instruction_data,
|
2025-12-26 14:58:41 +03:00
|
|
|
&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)
|
|
|
|
|
})
|
|
|
|
|
}
|
2025-11-30 01:57:59 +03:00
|
|
|
}
|