use prost::Message;
use zera_proto::zera_txn::{CoinTxn, TransferAuthentication};
use crate::error::{Result, ZeraError};
use crate::sign::signer::{create_transaction_hash, sign_transaction_data, ZeraSigner};
use crate::tx::BaseTxnAccess;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CoinTxnKeyPair {
pub public_key: String,
pub private_key: String,
}
pub async fn sign_and_finalize<T>(txn: &mut T, signer: &dyn ZeraSigner) -> Result<()>
where
T: Message + BaseTxnAccess,
{
let bytes = txn.encode_to_vec();
let signature = signer.sign(&bytes).await?;
{
let base = txn
.base_mut()
.ok_or_else(|| ZeraError::Validation("Transaction is missing base data".to_string()))?;
base.signature = Some(signature);
}
let signed_bytes = txn.encode_to_vec();
let hash = create_transaction_hash(&signed_bytes);
let base = txn
.base_mut()
.ok_or_else(|| ZeraError::Validation("Transaction is missing base data".to_string()))?;
base.hash = Some(hash);
Ok(())
}
pub fn sign_with_key<T>(txn: &mut T, private_key: &str, public_key_id: &str) -> Result<()>
where
T: Message + BaseTxnAccess,
{
let bytes = txn.encode_to_vec();
let signature = sign_transaction_data(&bytes, private_key, public_key_id)?;
{
let base = txn
.base_mut()
.ok_or_else(|| ZeraError::Validation("Transaction is missing base data".to_string()))?;
base.signature = Some(signature);
}
let signed_bytes = txn.encode_to_vec();
let hash = create_transaction_hash(&signed_bytes);
let base = txn
.base_mut()
.ok_or_else(|| ZeraError::Validation("Transaction is missing base data".to_string()))?;
base.hash = Some(hash);
Ok(())
}
pub async fn sign_coin_txn(txn: &mut CoinTxn, signers: &[&dyn ZeraSigner]) -> Result<()> {
if signers.is_empty() {
return Err(ZeraError::Validation(
"At least one signer is required".to_string(),
));
}
let txn_bytes = txn.encode_to_vec();
let auth = txn.auth.get_or_insert_with(TransferAuthentication::default);
for signer in signers {
auth.signature.push(signer.sign(&txn_bytes).await?);
}
let signed_bytes = txn.encode_to_vec();
let hash = create_transaction_hash(&signed_bytes);
let base = txn
.base
.as_mut()
.ok_or_else(|| ZeraError::Validation("CoinTXN is missing base data".to_string()))?;
base.hash = Some(hash);
Ok(())
}
pub fn sign_coin_txn_with_keys(txn: &mut CoinTxn, keys: &[CoinTxnKeyPair]) -> Result<()> {
if keys.is_empty() {
return Err(ZeraError::Validation(
"At least one key pair is required".to_string(),
));
}
let txn_bytes = txn.encode_to_vec();
let auth = txn.auth.get_or_insert_with(TransferAuthentication::default);
for key in keys {
if key.public_key.is_empty() || key.private_key.is_empty() {
return Err(ZeraError::Validation(
"Key pair is missing privateKey or publicKey".to_string(),
));
}
auth.signature.push(sign_transaction_data(
&txn_bytes,
&key.private_key,
&key.public_key,
)?);
}
let signed_bytes = txn.encode_to_vec();
let hash = create_transaction_hash(&signed_bytes);
let base = txn
.base
.as_mut()
.ok_or_else(|| ZeraError::Validation("CoinTXN is missing base data".to_string()))?;
base.hash = Some(hash);
Ok(())
}