zera-sdk 0.1.0

Rust SDK for ZERA transactions, validator APIs, and bridge workflows
Documentation
use zera_proto::zera_txn::ContractUpdateTxn;

use crate::contract::shared::{
    validate_key_pair, validate_update_contract_options, UpdateContractOptions,
};
use crate::crypto::address::generate_address_from_public_key;
use crate::error::{Result, ZeraError};
use crate::fees::{FeeConfigHelper, UniversalFeeCalculator};
use crate::grpc::{submit_transaction, UnaryTransport, ValidatorApiClient};
use crate::sign::sign_with_key;
use crate::tx::{
    build_standard_base_txn, get_address_and_nonce_with_client, BuildStandardBaseTxnParams,
};
use crate::types::RpcConfig;

pub async fn build_contract_update_txn(
    options: UpdateContractOptions,
) -> Result<ContractUpdateTxn> {
    let client = ValidatorApiClient::new(options.grpc_config.clone().unwrap_or_default())?;
    build_contract_update_txn_with_client(options, &client).await
}

pub async fn build_contract_update_txn_with_client<T>(
    options: UpdateContractOptions,
    client: &ValidatorApiClient<T>,
) -> Result<ContractUpdateTxn>
where
    T: UnaryTransport,
{
    validate_update_contract_options(&options.contract_id, options.contract_version)?;
    if options.public_key_base58_identifier.is_empty() {
        return Err(ZeraError::Validation(
            "Public key identifier is required".to_string(),
        ));
    }
    generate_address_from_public_key(&options.public_key_base58_identifier)?;

    let nonce = if let Some(nonce) = options.nonce {
        nonce
    } else {
        get_address_and_nonce_with_client(&options.public_key_base58_identifier, client)
            .await?
            .1
    };

    let base = build_standard_base_txn(BuildStandardBaseTxnParams {
        public_key_id: options.public_key_base58_identifier.clone(),
        fee_id: options.fee_id.clone(),
        fee_amount_parts: options.fee_amount_parts.clone(),
        nonce,
        memo: options.memo.clone(),
    })?;

    let mut update_txn = ContractUpdateTxn {
        base: Some(base),
        contract_id: options.contract_id,
        contract_version: options.contract_version,
        name: options.name,
        governance: options.governance,
        restricted_keys: options.restricted_keys,
        contract_fees: options.contract_fees,
        custom_parameters: options.custom_parameters,
        expense_ratio: options.expense_ratio,
        token_compliance: options.token_compliance,
        kyc_status: options.kyc_status,
        immutable_kyc_status: options.immutable_kyc_status,
        quash_threshold: options.quash_threshold,
    };

    update_txn = UniversalFeeCalculator::calculate_fee_with_client(
        FeeConfigHelper {
            contract_id: None,
            proto_object: update_txn,
            token_info_map: std::collections::HashMap::new(),
            base_fee_id: options.fee_id,
            base_fee: options.fee_amount_parts,
            contract_fee_id: None,
            contract_fee: None,
            interface_fee_id: None,
            interface_fee: None,
            interface_address: None,
            overestimate_percent: None,
            gas_fee_in_usd: None,
            grpc_config: None,
            needs_initialization: None,
        },
        client,
    )
    .await?;

    Ok(update_txn)
}

pub async fn update_contract(options: UpdateContractOptions) -> Result<ContractUpdateTxn> {
    validate_key_pair(
        &options.public_key_base58_identifier,
        &options.private_key_base58,
    )?;
    let mut update_txn = build_contract_update_txn(options.clone()).await?;
    sign_with_key(
        &mut update_txn,
        &options.private_key_base58,
        &options.public_key_base58_identifier,
    )?;
    Ok(update_txn)
}

pub async fn send_update_contract(
    update: &ContractUpdateTxn,
    grpc_config: Option<RpcConfig>,
) -> Result<String> {
    submit_transaction(update, grpc_config.unwrap_or_default()).await
}