use crate::oracle::client::OracleClient;
use crate::oracle::error::OracleError;
use cosmwasm_std::{Decimal256, Timestamp};
use serde::{Deserialize, Serialize};
impl OracleClient {
pub async fn get_price(
&self,
base_token: String,
quote_token: String,
) -> Result<Price, OracleError> {
let query = Query {
get_price: GetPriceRequest {
base_asset_symbol: base_token,
quote_asset_symbol: quote_token,
},
};
let response: GetPriceResponse = self
.query_contract(self.oracle_contract_address.to_string(), &query, None)
.await?
.data;
response.pair_data.ok_or_else(|| {
OracleError::PriceNotFound(
query.get_price.base_asset_symbol,
query.get_price.quote_asset_symbol,
)
})
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Price {
pub price: Decimal256,
pub expiry_time: Timestamp,
}
#[derive(Serialize)]
struct Query {
pub get_price: GetPriceRequest,
}
#[derive(Serialize)]
struct GetPriceRequest {
pub base_asset_symbol: String,
pub quote_asset_symbol: String,
}
#[derive(Deserialize)]
struct GetPriceResponse {
pub pair_data: Option<Price>,
}
#[cfg(test)]
mod tests {
use super::*;
use crate::oracle::client::OracleAdminClient;
use crate::test_utils::helpers::{TEST_ASSET_ARCH_SYMBOL, TEST_ASSET_USDT_SYMBOL};
use crate::test_utils::test_scenario::TestScenario;
use serial_test::serial;
use std::ops::Add;
use std::str::FromStr;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
#[tokio::test]
#[serial]
async fn test_get_price() {
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 price_expiry_time = SystemTime::now().add(Duration::from_secs(7200)); let price_expiry_timestamp = price_expiry_time
.duration_since(UNIX_EPOCH)
.expect("Converting to timestamp failed");
let err = client
.public_oracle_client
.get_price(
TEST_ASSET_ARCH_SYMBOL.to_string(),
TEST_ASSET_USDT_SYMBOL.to_string(),
)
.await
.expect_err("Expected error as we haven't set any asset pairs yet");
assert_eq!(
err.to_string(),
OracleError::PriceNotFound(
TEST_ASSET_ARCH_SYMBOL.to_string(),
TEST_ASSET_USDT_SYMBOL.to_string()
)
.to_string()
);
test_scenario.set_default_assets(&client).await;
let err = client
.public_oracle_client
.get_price(
TEST_ASSET_ARCH_SYMBOL.to_string(),
TEST_ASSET_USDT_SYMBOL.to_string(),
)
.await
.expect_err("Expected error as we haven't set any prices yet");
assert!(matches!(err, OracleError::PriceNotFound(_, _)));
test_scenario
.set_default_prices(&client, price_expiry_timestamp, "50000")
.await;
let client = OracleClient::new(
test_scenario.cosmos_client,
oracle_contract_address
.parse()
.expect("Failed to parse account ID"),
)
.expect("Failed to create oracle client");
let result = client
.get_price(
TEST_ASSET_ARCH_SYMBOL.to_string(),
TEST_ASSET_USDT_SYMBOL.to_string(),
)
.await;
assert!(result.is_ok());
let price = result.unwrap();
assert_eq!(price.price, Decimal256::from_str("50000").unwrap());
}
}