use zera_proto::zera_guardian::ZeraPayload;
use zera_proto::zera_txn::SmartContractExecuteTxn;
use crate::contract::shared::validate_key_pair;
use crate::error::{Result, ZeraError};
use crate::grpc::{UnaryTransport, ValidatorApiClient};
use crate::sign::sign_with_key;
use crate::smart_contracts::execute::{
build_smart_contract_execute_txn, build_smart_contract_execute_txn_with_client,
BuildSmartContractExecuteOptions, ExecuteParameter, ParameterType,
};
use super::types::BridgeZeraOptions;
pub const BRIDGE_CONTRACT_NAME: &str = "zera_bridge_proxy";
pub const BRIDGE_INSTANCE: u32 = 1;
pub fn format_guardian_signatures(payload: &ZeraPayload) -> String {
let sig_pairs = payload
.signatures
.iter()
.enumerate()
.map(|(index, signature)| {
let public_key = payload.public_keys.get(index).map_or("", String::as_str);
format!("{signature},{public_key}")
})
.collect::<Vec<_>>()
.join("|");
format!("{}|{}", payload.signed_hash, sig_pairs)
}
pub async fn create_bridge_transaction(
function_name: &str,
parameter_value: &str,
public_key_base58_identifier: &str,
private_key_base58: &str,
fee_id: &str,
options: BridgeZeraOptions,
) -> Result<SmartContractExecuteTxn> {
if private_key_base58.is_empty() {
return Err(ZeraError::Validation(
"privateKeyBase58 is required".to_string(),
));
}
validate_key_pair(public_key_base58_identifier, private_key_base58)?;
let mut transaction = build_smart_contract_execute_txn(
BRIDGE_CONTRACT_NAME,
BRIDGE_INSTANCE,
"execute",
&bridge_parameters(function_name, parameter_value),
public_key_base58_identifier,
BuildSmartContractExecuteOptions {
memo: options.memo,
grpc_config: options.grpc_config,
gas_fee_in_usd: options.gas_fee_in_usd,
overestimate_percent: options.overestimate_percent,
nonce: options.nonce,
fee_id: Some(fee_id.to_string()),
fee_amount_parts: options.fee_amount_usd,
},
)
.await?;
sign_with_key(
&mut transaction,
private_key_base58,
public_key_base58_identifier,
)?;
Ok(transaction)
}
pub async fn create_bridge_transaction_with_client<T>(
function_name: &str,
parameter_value: &str,
public_key_base58_identifier: &str,
private_key_base58: &str,
fee_id: &str,
options: BridgeZeraOptions,
client: &ValidatorApiClient<T>,
) -> Result<SmartContractExecuteTxn>
where
T: UnaryTransport,
{
if private_key_base58.is_empty() {
return Err(ZeraError::Validation(
"privateKeyBase58 is required".to_string(),
));
}
validate_key_pair(public_key_base58_identifier, private_key_base58)?;
let mut transaction = build_smart_contract_execute_txn_with_client(
BRIDGE_CONTRACT_NAME,
BRIDGE_INSTANCE,
"execute",
&bridge_parameters(function_name, parameter_value),
public_key_base58_identifier,
BuildSmartContractExecuteOptions {
memo: options.memo,
grpc_config: None,
gas_fee_in_usd: options.gas_fee_in_usd,
overestimate_percent: options.overestimate_percent,
nonce: options.nonce,
fee_id: Some(fee_id.to_string()),
fee_amount_parts: options.fee_amount_usd,
},
client,
)
.await?;
sign_with_key(
&mut transaction,
private_key_base58,
public_key_base58_identifier,
)?;
Ok(transaction)
}
fn bridge_parameters(function_name: &str, parameter_value: &str) -> [ExecuteParameter; 2] {
[
ExecuteParameter {
parameter_type: ParameterType::String.as_str().to_string(),
value: function_name.as_bytes().to_vec(),
},
ExecuteParameter {
parameter_type: ParameterType::String.as_str().to_string(),
value: parameter_value.as_bytes().to_vec(),
},
]
}