bolt-cw-sdk 1.0.0

SDK for the BOLT protocol, providing utilities for interacting with the BOLT contracts.
Documentation
use cosmrs::cosmwasm::MsgExecuteContract;
use cosmrs::tx::Msg;
use cosmwasm_std::Decimal256;
use serde::Serialize;

use crate::oracle::client::OracleAdminClient;
use crate::oracle::error::OracleError;
use crate::tx_builder::TxBuilder;

impl OracleAdminClient {
    pub fn append_update_config_msg(
        &self,
        tx_builder: &mut TxBuilder,
        price_threshold_ratio: Option<Decimal256>,
        price_expire_millis: Option<u64>,
    ) -> Result<(), OracleError> {
        let update_config = UpdateConfig {
            price_threshold_ratio,
            price_expire_millis,
        };
        let contract_msg = ExecuteMsg { update_config };
        let contract_msg =
            serde_json::to_vec(&contract_msg).map_err(OracleError::SerdeJsonError)?;
        let msg = MsgExecuteContract {
            sender: tx_builder.account_id.clone(),
            contract: self.chain_config.oracle_contract_address.clone(),
            msg: contract_msg,
            funds: vec![],
        };
        let msg = msg.to_any().map_err(OracleError::EyreError)?;

        tx_builder.add_msg(msg);
        Ok(())
    }
}

#[derive(Serialize)]
pub struct UpdateConfig {
    pub price_threshold_ratio: Option<Decimal256>,
    pub price_expire_millis: Option<u64>,
}

#[derive(Serialize)]
struct ExecuteMsg {
    pub update_config: UpdateConfig,
}

#[cfg(test)]
mod tests {
    use std::str::FromStr;

    use cosmrs::tendermint::abci::Code;
    use serial_test::serial;

    use super::*;
    use crate::test_utils::helpers::assert_event_attribute;
    use crate::test_utils::test_scenario::TestScenario;

    #[tokio::test]
    #[serial]
    async fn test_update_config() {
        let test_scenario = TestScenario::new_from_config("config.json".to_string()).await;

        let price_threshold_ratio = Decimal256::from_str("0.5").unwrap();
        let price_expire_millis = Some(1000);
        let oracle_contract_address = test_scenario
            .instantiate_oracle_contract(price_threshold_ratio, price_expire_millis)
            .await;

        let client = OracleAdminClient::from_scenario(&test_scenario, &oracle_contract_address)
            .expect("Failed to create oracle admin client");

        let account = client
            .public_oracle_client
            .account(test_scenario.admin_address.clone())
            .await
            .expect("Failed to get account from public oracle client");
        let mut tx_builder = TxBuilder::new(
            test_scenario.admin_mnemonic.clone(),
            test_scenario.chain_prefix.clone(),
            test_scenario.chain_id.clone(),
            test_scenario.derivation_path,
            account.sequence,
            account.account_number,
        )
        .expect("Failed to create tx builder");

        let price_threshold_ratio = Decimal256::one();
        let price_expire_millis = 42;
        client
            .append_update_config_msg(
                &mut tx_builder,
                Some(price_threshold_ratio),
                Some(price_expire_millis),
            )
            .unwrap();

        tx_builder.set_memo("From test_update_config".to_string());
        let gas = 500_000u64;
        tx_builder.set_fee(70_000_000_000_000_000u128, &test_scenario.chain_denom, gas);
        let signed_bytes = tx_builder
            .get_signed_bytes()
            .expect("Failed to get signed bytes");

        let response = client
            .broadcast_tx(signed_bytes)
            .await
            .expect("Failed to broadcast tx");

        match response.tx_result.code {
            Code::Ok => {
                println!("Transaction successful: {:?}", response.hash);
                let update_config_event = response
                    .tx_result
                    .events
                    .iter()
                    .find(|ev| ev.kind == "wasm-update_config")
                    .expect("Failed to find update config event");
                assert_event_attribute(
                    update_config_event,
                    "price_expire_millis",
                    &price_expire_millis.to_string(),
                );
                assert_event_attribute(
                    update_config_event,
                    "price_threshold_ratio",
                    &price_threshold_ratio.to_string(),
                );
            }
            Code::Err(code) => {
                panic!(
                    "Transaction failed with code: {:?} response: {:?}",
                    code, response
                );
            }
        }
    }
}