use ibc_proto::cosmos::tx::v1beta1::Fee;
use ibc_proto::google::protobuf::Any;
use ibc_relayer_types::events::IbcEvent;
use tendermint_rpc::endpoint::broadcast::tx_sync::Response;
use tendermint_rpc::{Client, HttpClient, Url};
use crate::chain::cosmos::encode::sign_and_encode_tx;
use crate::chain::cosmos::estimate::estimate_tx_fees;
use crate::chain::cosmos::query::account::query_account;
use crate::chain::cosmos::query::tx::all_ibc_events_from_tx_search_response;
use crate::chain::cosmos::types::account::Account;
use crate::chain::cosmos::types::config::TxConfig;
use crate::chain::cosmos::wait::wait_tx_succeed;
use crate::config::types::Memo;
use crate::error::Error;
use crate::event::IbcEventWithHeight;
use crate::keyring::{Secp256k1KeyPair, SigningKeyPair};
use super::batch::send_batched_messages_and_wait_commit;
use super::estimate::EstimatedGas;
pub async fn estimate_fee_and_send_tx(
rpc_client: &HttpClient,
config: &TxConfig,
key_pair: &Secp256k1KeyPair,
account: &Account,
tx_memo: &Memo,
messages: &[Any],
) -> Result<(Response, EstimatedGas), Error> {
let (fee, estimated_gas) =
estimate_tx_fees(config, key_pair, account, tx_memo, messages).await?;
let tx_result = send_tx_with_fee(
rpc_client, config, key_pair, account, tx_memo, messages, &fee,
)
.await?;
Ok((tx_result, estimated_gas))
}
async fn send_tx_with_fee(
rpc_client: &HttpClient,
config: &TxConfig,
key_pair: &Secp256k1KeyPair,
account: &Account,
tx_memo: &Memo,
messages: &[Any],
fee: &Fee,
) -> Result<Response, Error> {
let tx_bytes = sign_and_encode_tx(config, key_pair, account, tx_memo, messages, fee)?;
let response = broadcast_tx_sync(rpc_client, &config.rpc_address, tx_bytes).await?;
Ok(response)
}
pub async fn broadcast_tx_sync(
rpc_client: &HttpClient,
rpc_address: &Url,
data: Vec<u8>,
) -> Result<Response, Error> {
let response = rpc_client
.broadcast_tx_sync(data)
.await
.map_err(|e| Error::rpc(rpc_address.clone(), e))?;
Ok(response)
}
pub async fn simple_send_tx(
rpc_client: &HttpClient,
config: &TxConfig,
key_pair: &Secp256k1KeyPair,
messages: Vec<Any>,
) -> Result<Vec<IbcEventWithHeight>, Error> {
let key_account = key_pair.account();
let account = query_account(&config.grpc_address, &key_account)
.await?
.into();
let (response, _) = estimate_fee_and_send_tx(
rpc_client,
config,
key_pair,
&account,
&Memo::default(),
&messages,
)
.await?;
if response.code.is_err() {
return Err(Error::check_tx(response));
}
let response = wait_tx_succeed(
rpc_client,
&config.rpc_address,
&config.rpc_timeout,
&response.hash,
)
.await?;
let events = all_ibc_events_from_tx_search_response(&config.chain_id, response);
Ok(events)
}
pub async fn batched_send_tx(
rpc_client: &HttpClient,
config: &TxConfig,
key_pair: &Secp256k1KeyPair,
messages: Vec<Any>,
) -> Result<Vec<IbcEventWithHeight>, Error> {
let key_account = key_pair.account();
let mut account = query_account(&config.grpc_address, &key_account)
.await?
.into();
let events = send_batched_messages_and_wait_commit(
rpc_client,
config,
key_pair,
&mut account,
&Memo::default(),
messages,
)
.await?;
for event in &events {
if let IbcEvent::ChainError(ref e) = event.event {
return Err(Error::send_tx(e.clone()));
}
}
Ok(events)
}