755 lines
28 KiB
Rust
Raw Normal View History

use common::{HashType, transaction::NSSATransaction};
2026-05-15 18:15:54 -04:00
use nssa::{AccountId, 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;
use sequencer_service_rpc::RpcClient as _;
use token_core::Instruction;
2026-05-15 18:15:54 -04:00
use crate::{
ExecutionFailureKind, PrivacyPreservingAccount, WalletCore,
cli::CliAccountMention,
helperfunctions::read_pin,
signing::SigningGroups,
};
2026-03-04 18:42:33 +03:00
pub struct Token<'wallet>(pub &'wallet WalletCore);
impl Token<'_> {
2026-05-15 18:15:54 -04:00
#[expect(clippy::too_many_arguments, reason = "each parameter is distinct")]
pub async fn send_new_definition(
&self,
definition_account_id: AccountId,
supply_account_id: AccountId,
name: String,
total_supply: u128,
2026-05-15 18:15:54 -04:00
definition_mention: &CliAccountMention,
supply_mention: &CliAccountMention,
) -> 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 };
2026-05-01 02:44:36 -04:00
2026-05-15 18:15:54 -04:00
let mut groups = SigningGroups::new();
groups
.add_sender(definition_mention, definition_account_id, self.0)
.and_then(|()| groups.add_sender(supply_mention, supply_account_id, self.0))
.map_err(|e| ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<PyRuntimeError, _>(e.to_string())))?;
let nonces = self.0.get_accounts_nonces(groups.signing_ids()).await
.map_err(ExecutionFailureKind::SequencerError)?;
let message = nssa::public_transaction::Message::try_new(program_id, account_ids, nonces, instruction).unwrap();
2026-05-15 18:15:54 -04:00
let pin = if groups.needs_pin() {
read_pin()
.map_err(|e| ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<PyRuntimeError, _>(e.to_string())))?
.as_str()
.to_owned()
2026-05-01 02:44:36 -04:00
} else {
2026-05-15 18:15:54 -04:00
String::new()
2026-05-01 02:44:36 -04:00
};
2026-05-15 18:15:54 -04:00
let sigs = groups.sign_all(&message.hash(), &pin)
.map_err(|e| ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<PyRuntimeError, _>(e.to_string())))?;
2026-05-01 02:44:36 -04:00
2026-05-15 18:15:54 -04:00
let tx = nssa::PublicTransaction::new(message, WitnessSet::from_raw_parts(sigs));
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),
2026-05-15 18:15:54 -04:00
self.0
.resolve_private_account(supply_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?,
],
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![
2026-05-15 18:15:54 -04:00
self.0
.resolve_private_account(definition_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?,
2025-12-02 15:27:20 +02:00
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![
2026-05-15 18:15:54 -04:00
self.0
.resolve_private_account(definition_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?,
self.0
.resolve_private_account(supply_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?,
2025-12-02 15:27:20 +02:00
],
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-05-15 18:15:54 -04:00
sender_mention: &CliAccountMention,
recipient_mention: &CliAccountMention,
) -> Result<HashType, ExecutionFailureKind> {
let account_ids = vec![sender_account_id, recipient_account_id];
let program_id = nssa::program::Program::token().id();
2026-05-15 18:15:54 -04:00
let instruction = Instruction::Transfer { amount_to_transfer: amount };
2026-05-06 20:35:46 -04:00
2026-05-15 18:15:54 -04:00
let mut groups = SigningGroups::new();
groups
.add_sender(sender_mention, sender_account_id, self.0)
.and_then(|()| groups.add_recipient(recipient_mention, recipient_account_id, self.0))
.map_err(|e| ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<PyRuntimeError, _>(e.to_string())))?;
let nonces = self.0.get_accounts_nonces(groups.signing_ids()).await
2026-03-04 18:42:33 +03:00
.map_err(ExecutionFailureKind::SequencerError)?;
2026-05-15 18:15:54 -04:00
let message = nssa::public_transaction::Message::try_new(program_id, account_ids, nonces, instruction).unwrap();
2026-05-06 20:35:46 -04:00
2026-05-15 18:15:54 -04:00
let pin = if groups.needs_pin() {
read_pin()
.map_err(|e| ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<PyRuntimeError, _>(e.to_string())))?
.as_str()
.to_owned()
2026-04-29 07:52:15 -04:00
} else {
2026-05-15 18:15:54 -04:00
String::new()
2026-04-27 20:16:39 -04:00
};
2026-05-15 18:15:54 -04:00
let sigs = groups.sign_all(&message.hash(), &pin)
.map_err(|e| ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<PyRuntimeError, _>(e.to_string())))?;
2026-05-15 18:15:54 -04:00
let tx = nssa::PublicTransaction::new(message, WitnessSet::from_raw_parts(sigs));
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![
2026-05-15 18:15:54 -04:00
self.0
.resolve_private_account(sender_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?,
self.0
.resolve_private_account(recipient_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?,
],
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![
2026-05-15 18:15:54 -04:00
self.0
.resolve_private_account(sender_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?,
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![
2026-05-15 18:15:54 -04:00
self.0
.resolve_private_account(sender_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?,
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),
2026-05-15 18:15:54 -04:00
self.0
.resolve_private_account(recipient_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?,
],
instruction_data,
&Program::token().into(),
2026-05-15 18:15:54 -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
pub async fn send_burn_transaction(
&self,
definition_account_id: AccountId,
holder_account_id: AccountId,
amount: u128,
2026-05-15 18:15:54 -04:00
holder_mention: &CliAccountMention,
) -> 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-05-15 18:15:54 -04:00
let mut groups = SigningGroups::new();
groups
.add_sender(holder_mention, holder_account_id, self.0)
.map_err(|e| ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<PyRuntimeError, _>(e.to_string())))?;
let nonces = self.0.get_accounts_nonces(groups.signing_ids()).await
2026-03-04 18:42:33 +03:00
.map_err(ExecutionFailureKind::SequencerError)?;
2026-05-15 18:15:54 -04:00
let message = nssa::public_transaction::Message::try_new(Program::token().id(), account_ids, nonces, instruction)
.expect("Instruction should serialize");
let pin = if groups.needs_pin() {
read_pin()
.map_err(|e| ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<PyRuntimeError, _>(e.to_string())))?
.as_str()
.to_owned()
2026-05-01 02:44:36 -04:00
} else {
2026-05-15 18:15:54 -04:00
String::new()
2026-05-01 02:44:36 -04:00
};
2026-05-15 18:15:54 -04:00
let sigs = groups.sign_all(&message.hash(), &pin)
.map_err(|e| ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<PyRuntimeError, _>(e.to_string())))?;
2025-12-11 14:46:16 +02:00
2026-05-15 18:15:54 -04:00
let tx = nssa::PublicTransaction::new(message, WitnessSet::from_raw_parts(sigs));
2025-12-11 14:46:16 +02: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,
) -> 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![
2026-05-15 18:15:54 -04:00
self.0
.resolve_private_account(definition_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?,
self.0
.resolve_private_account(holder_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?,
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_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![
2026-05-15 18:15:54 -04:00
self.0
.resolve_private_account(definition_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?,
2025-12-11 14:46:16 +02:00
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),
2026-05-15 18:15:54 -04:00
self.0
.resolve_private_account(holder_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?,
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)
})
}
pub async fn send_mint_transaction(
&self,
definition_account_id: AccountId,
holder_account_id: AccountId,
amount: u128,
2026-05-15 18:15:54 -04:00
definition_mention: &CliAccountMention,
holder_mention: &CliAccountMention,
) -> 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
2026-05-15 18:15:54 -04:00
let mut groups = SigningGroups::new();
groups
.add_sender(definition_mention, definition_account_id, self.0)
.and_then(|()| groups.add_recipient(holder_mention, holder_account_id, self.0))
.map_err(|e| ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<PyRuntimeError, _>(e.to_string())))?;
let nonces = self.0.get_accounts_nonces(groups.signing_ids()).await
2026-03-04 18:42:33 +03:00
.map_err(ExecutionFailureKind::SequencerError)?;
2026-05-15 18:15:54 -04:00
let message = nssa::public_transaction::Message::try_new(Program::token().id(), account_ids, nonces, instruction).unwrap();
2026-05-15 18:15:54 -04:00
let pin = if groups.needs_pin() {
read_pin()
.map_err(|e| ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<PyRuntimeError, _>(e.to_string())))?
.as_str()
.to_owned()
2026-05-01 02:44:36 -04:00
} else {
2026-05-15 18:15:54 -04:00
String::new()
2026-05-01 02:44:36 -04:00
};
2026-05-15 18:15:54 -04:00
let sigs = groups.sign_all(&message.hash(), &pin)
.map_err(|e| ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<PyRuntimeError, _>(e.to_string())))?;
2025-12-11 14:46:16 +02:00
2026-05-15 18:15:54 -04:00
let tx = nssa::PublicTransaction::new(message, WitnessSet::from_raw_parts(sigs));
2025-12-11 14:46:16 +02: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,
) -> 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![
2026-05-15 18:15:54 -04:00
self.0
.resolve_private_account(definition_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?,
self.0
.resolve_private_account(holder_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?,
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_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![
2026-05-15 18:15:54 -04:00
self.0
.resolve_private_account(definition_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?,
2025-12-11 14:46:16 +02:00
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![
2026-05-15 18:15:54 -04:00
self.0
.resolve_private_account(definition_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?,
2025-12-11 14:46:16 +02:00
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),
2026-05-15 18:15:54 -04:00
self.0
.resolve_private_account(holder_account_id)
.ok_or(ExecutionFailureKind::KeyNotFoundError)?,
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)
})
}
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)
})
}
2026-05-15 18:15:54 -04:00
}