zera-sdk 0.1.0

Rust SDK for ZERA transactions, validator APIs, and bridge workflows
Documentation
use std::time::{SystemTime, UNIX_EPOCH};

use prost_types::Timestamp;
use zera_proto::zera_txn::{BaseTxn, PublicKey};

use crate::api::get_nonce_with_client;
use crate::crypto::address::{generate_address_from_public_key, get_public_key_bytes};
use crate::error::{Result, ZeraError};
use crate::grpc::{UnaryTransport, ValidatorApiClient};
use crate::types::RpcConfig;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BuildStandardBaseTxnParams {
    pub public_key_id: String,
    pub fee_id: Option<String>,
    pub fee_amount_parts: Option<String>,
    pub nonce: u64,
    pub memo: Option<String>,
}

pub fn build_standard_base_txn(params: BuildStandardBaseTxnParams) -> Result<BaseTxn> {
    let fee_id = params.fee_id.unwrap_or_else(|| "$ZRA+0000".to_string());
    let fee_amount = params.fee_amount_parts.unwrap_or_else(|| "1".to_string());
    if fee_amount.is_empty() || fee_amount == "0" {
        return Err(ZeraError::Validation(
            "Base fee must be provided and cannot be 0".to_string(),
        ));
    }

    let public_key = PublicKey {
        single: get_public_key_bytes(&params.public_key_id)?,
        ..Default::default()
    };

    let now = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .map_err(|error| ZeraError::Serialization(format!("Invalid system time: {error}")))?;

    Ok(BaseTxn {
        public_key: Some(public_key),
        timestamp: Some(Timestamp {
            seconds: now.as_secs() as i64,
            nanos: now.subsec_nanos() as i32,
        }),
        fee_amount,
        fee_id,
        memo: params.memo.filter(|memo| !memo.trim().is_empty()),
        nonce: params.nonce,
        ..Default::default()
    })
}

pub async fn get_address_and_nonce(
    public_key_id: &str,
    config: RpcConfig,
) -> Result<(String, u64)> {
    let client = ValidatorApiClient::new(config)?;
    get_address_and_nonce_with_client(public_key_id, &client).await
}

pub async fn get_address_and_nonce_with_client<T>(
    public_key_id: &str,
    client: &ValidatorApiClient<T>,
) -> Result<(String, u64)>
where
    T: UnaryTransport,
{
    let address = generate_address_from_public_key(public_key_id)?;
    let nonce = get_nonce_with_client(&address, client).await?;
    Ok((address, nonce))
}