use std::str::FromStr;
use secp256k1::SecretKey;
use super::ContractCallPayload;
use crate::clarity;
use crate::clarity::Clarity;
use crate::clarity::FnArguments;
use crate::crypto::c32::Address;
use crate::crypto::c32::Mode;
use crate::transaction::AnchorMode;
use crate::transaction::Auth;
use crate::transaction::Network;
use crate::transaction::PostConditionMode;
use crate::transaction::PostConditions;
use crate::transaction::SpendingConditionStandard;
use crate::transaction::TokenTransferPayload;
use crate::transaction::Transaction;
#[derive(Debug, Clone, PartialEq, Eq, typed_builder::TypedBuilder)]
pub struct STXTokenTransfer<T, N>
where
T: Clarity,
N: Network,
{
pub recipient: T,
pub amount: u64,
pub sender: SecretKey,
pub network: N,
#[builder(default = 0)]
pub fee: u64,
#[builder(default = 0)]
pub nonce: u64,
#[builder(default = AnchorMode::Any)]
pub anchor_mode: AnchorMode,
#[builder(setter(into), default = String::new())]
pub memo: String,
#[builder(default = PostConditionMode::Allow)]
pub post_condition_mode: PostConditionMode,
#[builder(default = PostConditions::default())]
pub post_conditions: PostConditions,
#[builder(default = false)]
pub sponsored: bool,
}
impl<T, N> STXTokenTransfer<T, N>
where
T: Clarity,
N: Network,
{
pub fn transaction(self) -> Transaction {
let pk = self.sender.public_key(&secp256k1::Secp256k1::new());
let payload = TokenTransferPayload::new(self.recipient, self.amount, self.memo);
let condition = SpendingConditionStandard::new(pk, self.fee, self.nonce, Mode::P2PKH);
let auth = if self.sponsored {
unimplemented!("Sponsored transactions are not yet supported")
} else {
Auth::Standard(Box::new(condition))
};
Transaction::new(
self.network.version(),
self.network.chain_id(),
auth,
self.anchor_mode,
self.post_condition_mode,
self.post_conditions,
Box::new(payload),
)
}
}
#[derive(Debug, Clone, PartialEq, Eq, typed_builder::TypedBuilder)]
pub struct STXContractCall<N>
where
N: Network,
{
#[builder(setter(into))]
pub address: String,
#[builder(setter(into))]
pub contract: String,
#[builder(setter(into))]
pub fn_name: String,
pub fn_args: FnArguments,
pub sender: SecretKey,
pub network: N,
#[builder(default = 0)]
pub fee: u64,
#[builder(default = 0)]
pub nonce: u64,
#[builder(default = AnchorMode::Any)]
pub anchor_mode: AnchorMode,
#[builder(default = PostConditionMode::Allow)]
pub post_condition_mode: PostConditionMode,
#[builder(default = PostConditions::default())]
pub post_conditions: PostConditions,
#[builder(default = false)]
pub sponsored: bool,
}
impl<N> STXContractCall<N>
where
N: Network,
{
pub fn transaction(self) -> Result<Transaction, clarity::Error> {
let pk = self.sender.public_key(&secp256k1::Secp256k1::new());
let address = Address::from_str(&self.address)?;
let payload = ContractCallPayload::new(address, self.contract, self.fn_name, self.fn_args);
let condition = SpendingConditionStandard::new(pk, self.fee, self.nonce, Mode::P2PKH);
let auth = if self.sponsored {
unimplemented!("Sponsored transactions are not yet supported")
} else {
Auth::Standard(Box::new(condition))
};
let transaction = Transaction::new(
self.network.version(),
self.network.chain_id(),
auth,
self.anchor_mode,
self.post_condition_mode,
self.post_conditions,
Box::new(payload),
);
Ok(transaction)
}
}