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
}