bolt-cw-sdk 1.0.0

SDK for the BOLT protocol, providing utilities for interacting with the BOLT contracts.
Documentation
use serde::{Deserialize, Serialize};

use crate::oracle::client::OracleClient;
use crate::oracle::error::OracleError;

impl OracleClient {
    pub async fn asset_pairs(&self) -> Result<Vec<AssetPairs>, OracleError> {
        let query = Query {
            asset_pairs: AssetPairsRequest {},
        };
        let response: AssetPairsResponse = self
            .query_contract(self.oracle_contract_address.to_string(), &query, None)
            .await?
            .data;
        Ok(response.list)
    }
}

#[derive(Serialize, Deserialize, PartialEq, Debug)]
pub struct AssetPairs {
    pub base: Asset,
    pub quote: Asset,
}

#[derive(Serialize, Deserialize, PartialEq, Debug)]
pub struct Asset {
    pub name: String,
    pub symbol: String,
    pub precision: u8,
}

#[derive(Serialize)]
struct Query {
    pub asset_pairs: AssetPairsRequest,
}

#[derive(Serialize)]
struct AssetPairsRequest {}

#[derive(Deserialize)]
struct AssetPairsResponse {
    pub list: Vec<AssetPairs>,
}

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

    use cosmwasm_std::Decimal256;
    use serial_test::serial;

    use super::*;
    use crate::oracle::client::OracleAdminClient;
    use crate::test_utils::helpers::{
        TEST_ASSET_ARCH_NAME, TEST_ASSET_ARCH_PRECISION, TEST_ASSET_ARCH_SYMBOL,
        TEST_ASSET_ETH_NAME, TEST_ASSET_ETH_PRECISION, TEST_ASSET_ETH_SYMBOL, TEST_ASSET_USDT_NAME,
        TEST_ASSET_USDT_PRECISION, TEST_ASSET_USDT_SYMBOL,
    };
    use crate::test_utils::test_scenario::TestScenario;

    #[tokio::test]
    #[serial]
    async fn test_asset_pairs_against_wrong_contract() {
        let test_scenario = TestScenario::new_from_config("config.json".to_string()).await;
        let client = OracleAdminClient::from_scenario(&test_scenario, &test_scenario.admin_address)
            .expect("Failed to create oracle admin client");

        let err = client
            .public_oracle_client
            .asset_pairs()
            .await
            .expect_err("Expected error when querying asset pairs against wrong contract");
        assert!(matches!(err, OracleError::CosmosClientError(_)))
    }

    #[tokio::test]
    #[serial]
    async fn test_asset_pairs() {
        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 asset_pairs = client
            .public_oracle_client
            .asset_pairs()
            .await
            .expect("Failed to get asset pairs");
        assert!(asset_pairs.is_empty()); // We haven't setup any asset pairs yet

        let _ = test_scenario.set_default_assets(&client).await;

        let asset_pairs = client.public_oracle_client.asset_pairs().await.unwrap();

        let expected = vec![
            AssetPairs {
                base: Asset {
                    name: TEST_ASSET_ETH_NAME.to_string(),
                    symbol: TEST_ASSET_ETH_SYMBOL.to_string(),
                    precision: TEST_ASSET_ETH_PRECISION,
                },
                quote: Asset {
                    name: TEST_ASSET_USDT_NAME.to_string(),
                    symbol: TEST_ASSET_USDT_SYMBOL.to_string(),
                    precision: TEST_ASSET_USDT_PRECISION,
                },
            },
            AssetPairs {
                base: Asset {
                    name: TEST_ASSET_ARCH_NAME.to_string(),
                    symbol: TEST_ASSET_ARCH_SYMBOL.to_string(),
                    precision: TEST_ASSET_ARCH_PRECISION,
                },
                quote: Asset {
                    name: TEST_ASSET_USDT_NAME.to_string(),
                    symbol: TEST_ASSET_USDT_SYMBOL.to_string(),
                    precision: TEST_ASSET_USDT_PRECISION,
                },
            },
            AssetPairs {
                base: Asset {
                    name: TEST_ASSET_ARCH_NAME.to_string(),
                    symbol: TEST_ASSET_ARCH_SYMBOL.to_string(),
                    precision: TEST_ASSET_ARCH_PRECISION,
                },
                quote: Asset {
                    name: TEST_ASSET_ETH_NAME.to_string(),
                    symbol: TEST_ASSET_ETH_SYMBOL.to_string(),
                    precision: TEST_ASSET_ETH_PRECISION,
                },
            },
        ];
        assert_eq!(asset_pairs, expected);
    }
}