use getset::Getters;
use serde::{Deserialize, Serialize};
use crate::{
client::{api::PreparedTransactionData, secret::SecretManage, ClientError},
types::block::{
address::Bech32Address,
output::{
feature::{IssuerFeature, MetadataFeature, SenderFeature, TagFeature},
unlock_condition::AddressUnlockCondition,
NftId, NftOutputBuilder,
},
},
utils::ConvertTo,
wallet::{
operations::transaction::{TransactionOptions, TransactionWithMetadata},
Wallet, WalletError,
},
};
#[derive(Debug, Clone, Serialize, Deserialize, Default, Getters)]
#[serde(rename_all = "camelCase")]
pub struct MintNftParams {
#[getset(get = "pub")]
address: Option<Bech32Address>,
#[getset(get = "pub")]
sender: Option<Bech32Address>,
#[getset(get = "pub")]
metadata: Option<MetadataFeature>,
#[getset(get = "pub")]
#[serde(default, with = "crate::utils::serde::option_prefix_hex_bytes")]
tag: Option<Vec<u8>>,
#[getset(get = "pub")]
issuer: Option<Bech32Address>,
#[getset(get = "pub")]
immutable_metadata: Option<MetadataFeature>,
}
impl MintNftParams {
pub fn new() -> Self {
Self::default()
}
pub fn try_with_address(mut self, address: impl ConvertTo<Bech32Address>) -> Result<Self, WalletError> {
self.address = Some(address.convert()?);
Ok(self)
}
pub fn with_address(mut self, address: impl Into<Option<Bech32Address>>) -> Self {
self.address = address.into();
self
}
pub fn try_with_sender(mut self, sender: impl ConvertTo<Bech32Address>) -> Result<Self, WalletError> {
self.sender = Some(sender.convert()?);
Ok(self)
}
pub fn with_sender(mut self, sender: impl Into<Option<Bech32Address>>) -> Self {
self.sender = sender.into();
self
}
pub fn with_metadata(mut self, metadata: impl Into<Option<MetadataFeature>>) -> Self {
self.metadata = metadata.into();
self
}
pub fn with_tag(mut self, tag: impl Into<Option<Vec<u8>>>) -> Self {
self.tag = tag.into();
self
}
pub fn try_with_issuer(mut self, issuer: impl ConvertTo<Bech32Address>) -> Result<Self, WalletError> {
self.issuer = Some(issuer.convert()?);
Ok(self)
}
pub fn with_issuer(mut self, issuer: impl Into<Option<Bech32Address>>) -> Self {
self.issuer = issuer.into();
self
}
pub fn with_immutable_metadata(mut self, immutable_metadata: impl Into<Option<MetadataFeature>>) -> Self {
self.immutable_metadata = immutable_metadata.into();
self
}
}
impl<S: 'static + SecretManage> Wallet<S>
where
WalletError: From<S::Error>,
ClientError: From<S::Error>,
{
pub async fn mint_nfts<I: IntoIterator<Item = MintNftParams> + Send>(
&self,
params: I,
options: impl Into<Option<TransactionOptions>> + Send,
) -> Result<TransactionWithMetadata, WalletError>
where
I::IntoIter: Send,
{
let options = options.into();
let prepared_transaction = self.prepare_mint_nfts(params, options.clone()).await?;
self.sign_and_submit_transaction(prepared_transaction, options).await
}
pub async fn prepare_mint_nfts<I: IntoIterator<Item = MintNftParams> + Send>(
&self,
params: I,
options: impl Into<Option<TransactionOptions>> + Send,
) -> Result<PreparedTransactionData, WalletError>
where
I::IntoIter: Send,
{
log::debug!("[TRANSACTION] prepare_mint_nfts");
let storage_score_params = self.client().get_storage_score_parameters().await?;
let wallet_address = self.address().await.into_inner();
let mut outputs = Vec::new();
for MintNftParams {
address,
sender,
metadata,
tag,
issuer,
immutable_metadata,
} in params
{
let address = match address {
Some(address) => {
self.client().bech32_hrp_matches(address.hrp()).await?;
address.inner().clone()
}
None => wallet_address.clone(),
};
let mut nft_builder = NftOutputBuilder::new_with_minimum_amount(storage_score_params, NftId::null())
.add_unlock_condition(AddressUnlockCondition::new(address));
if let Some(sender) = sender {
nft_builder = nft_builder.add_feature(SenderFeature::new(sender));
}
if let Some(metadata) = metadata {
nft_builder = nft_builder.add_feature(metadata);
}
if let Some(tag) = tag {
nft_builder = nft_builder.add_feature(TagFeature::new(tag)?);
}
if let Some(issuer) = issuer {
nft_builder = nft_builder.add_immutable_feature(IssuerFeature::new(issuer));
}
if let Some(immutable_metadata) = immutable_metadata {
nft_builder = nft_builder.add_immutable_feature(immutable_metadata);
}
outputs.push(nft_builder.finish_output()?);
}
self.prepare_send_outputs(outputs, options).await
}
}