162 lines
8.1 KiB
Rust
162 lines
8.1 KiB
Rust
// file: crates/ksp-offchain-transport-lib/tests/release_completeness.rs
|
|
// version: 1
|
|
|
|
#![warn(missing_docs)]
|
|
#![deny(unreachable_pub)]
|
|
#![forbid(unsafe_code)]
|
|
|
|
//! Release-level completeness canaries for the eight-provider SOL/USD V1 contract.
|
|
|
|
#[test]
|
|
fn pre_010_exact_eight_provider_inventory_and_semantics_are_stable() -> ksp_core_lib::Result<()> {
|
|
let setups = match all_disabled_setups() {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
};
|
|
let service = match ksp_offchain_transport_lib::MarketPriceService::new(setups) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
};
|
|
let registry = service.registry();
|
|
assert_eq!(registry.len(), 8);
|
|
let expected = [
|
|
(
|
|
"birdeye",
|
|
ksp_offchain_transport_lib::MarketPriceSemantics::SolanaSpot,
|
|
ksp_offchain_transport_lib::MarketPriceProviderAuthMode::RequiredApiKey,
|
|
),
|
|
(
|
|
"coinbase_exchange",
|
|
ksp_offchain_transport_lib::MarketPriceSemantics::ExchangeLastTrade,
|
|
ksp_offchain_transport_lib::MarketPriceProviderAuthMode::None,
|
|
),
|
|
(
|
|
"coingecko",
|
|
ksp_offchain_transport_lib::MarketPriceSemantics::AggregatedMarket,
|
|
ksp_offchain_transport_lib::MarketPriceProviderAuthMode::None,
|
|
),
|
|
(
|
|
"coinmarketcap",
|
|
ksp_offchain_transport_lib::MarketPriceSemantics::AggregatedMarket,
|
|
ksp_offchain_transport_lib::MarketPriceProviderAuthMode::None,
|
|
),
|
|
(
|
|
"coinpaprika",
|
|
ksp_offchain_transport_lib::MarketPriceSemantics::AggregatedMarket,
|
|
ksp_offchain_transport_lib::MarketPriceProviderAuthMode::None,
|
|
),
|
|
("dexscreener", ksp_offchain_transport_lib::MarketPriceSemantics::DexPairUsd, ksp_offchain_transport_lib::MarketPriceProviderAuthMode::None),
|
|
("jupiter", ksp_offchain_transport_lib::MarketPriceSemantics::SolanaHeuristic, ksp_offchain_transport_lib::MarketPriceProviderAuthMode::None),
|
|
("kraken", ksp_offchain_transport_lib::MarketPriceSemantics::ExchangeLastTrade, ksp_offchain_transport_lib::MarketPriceProviderAuthMode::None),
|
|
];
|
|
for (entry, (provider_id, semantics, auth_mode)) in registry.entries().iter().zip(expected) {
|
|
assert_eq!(entry.descriptor().id().as_str(), provider_id);
|
|
assert_eq!(entry.descriptor().semantics(), semantics);
|
|
assert_eq!(entry.descriptor().auth_mode(), auth_mode);
|
|
assert!(entry.descriptor().supports_sol_usd());
|
|
assert_eq!(entry.state().availability(), ksp_offchain_transport_lib::MarketPriceProviderAvailability::Disabled);
|
|
}
|
|
return std::result::Result::Ok(());
|
|
}
|
|
|
|
#[test]
|
|
fn pre_010_evolutive_public_enums_are_non_exhaustive() -> std::io::Result<()> {
|
|
let root = crate_root();
|
|
let provider = match std::fs::read_to_string(root.join("src/market_price_provider.rs")) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
};
|
|
for enum_name in [
|
|
"MarketPricePair",
|
|
"MarketPriceSemantics",
|
|
"MarketPriceProviderAuthMode",
|
|
"MarketPriceProviderRateLimitScope",
|
|
"MarketPriceProviderRateLimitKind",
|
|
"MarketPriceProviderQuotaPeriod",
|
|
"MarketPriceProviderQuotaUnit",
|
|
"MarketPriceProviderAvailability",
|
|
] {
|
|
assert_non_exhaustive(provider.as_str(), enum_name);
|
|
}
|
|
let coingecko = match std::fs::read_to_string(root.join("src/market_price_coingecko.rs")) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
};
|
|
assert_non_exhaustive(coingecko.as_str(), "MarketPriceCoinGeckoAccessMode");
|
|
let coinmarketcap = match std::fs::read_to_string(root.join("src/market_price_coinmarketcap.rs")) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
};
|
|
assert_non_exhaustive(coinmarketcap.as_str(), "MarketPriceCoinMarketCapAccessMode");
|
|
let jupiter = match std::fs::read_to_string(root.join("src/market_price_jupiter.rs")) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
};
|
|
assert_non_exhaustive(jupiter.as_str(), "MarketPriceJupiterAccessMode");
|
|
let service = match std::fs::read_to_string(root.join("src/market_price_service.rs")) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
};
|
|
assert_non_exhaustive(service.as_str(), "MarketPriceProviderSetup");
|
|
return std::result::Result::Ok(());
|
|
}
|
|
|
|
fn all_disabled_setups() -> ksp_core_lib::Result<std::vec::Vec<ksp_offchain_transport_lib::MarketPriceProviderSetup>> {
|
|
let birdeye = match ksp_offchain_transport_lib::MarketPriceBirdeyeSettings::new(false, std::option::Option::None) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
};
|
|
let coinbase = match ksp_offchain_transport_lib::MarketPriceCoinbaseExchangeSettings::new(false) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
};
|
|
let coingecko = match ksp_offchain_transport_lib::MarketPriceCoinGeckoSettings::keyless(false) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
};
|
|
let coinmarketcap = match ksp_offchain_transport_lib::MarketPriceCoinMarketCapSettings::keyless(false) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
};
|
|
let coinpaprika = match ksp_offchain_transport_lib::MarketPriceCoinPaprikaSettings::new(false) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
};
|
|
let dexscreener = match ksp_offchain_transport_lib::MarketPriceDexScreenerSettings::new(false, std::option::Option::None) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
};
|
|
let jupiter = match ksp_offchain_transport_lib::MarketPriceJupiterSettings::keyless(false) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
};
|
|
let kraken = match ksp_offchain_transport_lib::MarketPriceKrakenSettings::new(false) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
};
|
|
return std::result::Result::Ok(std::vec![
|
|
ksp_offchain_transport_lib::MarketPriceProviderSetup::Birdeye(birdeye),
|
|
ksp_offchain_transport_lib::MarketPriceProviderSetup::CoinbaseExchange(coinbase),
|
|
ksp_offchain_transport_lib::MarketPriceProviderSetup::CoinGecko(coingecko),
|
|
ksp_offchain_transport_lib::MarketPriceProviderSetup::CoinMarketCap(coinmarketcap),
|
|
ksp_offchain_transport_lib::MarketPriceProviderSetup::CoinPaprika(coinpaprika),
|
|
ksp_offchain_transport_lib::MarketPriceProviderSetup::DexScreener(dexscreener),
|
|
ksp_offchain_transport_lib::MarketPriceProviderSetup::Jupiter(jupiter),
|
|
ksp_offchain_transport_lib::MarketPriceProviderSetup::Kraken(kraken),
|
|
]);
|
|
}
|
|
|
|
fn assert_non_exhaustive(source: &str, enum_name: &str) {
|
|
let marker = std::format!("pub enum {enum_name}");
|
|
let position = source.find(marker.as_str());
|
|
assert!(position.is_some(), "public enum must remain present: {enum_name}");
|
|
if let std::option::Option::Some(position) = position {
|
|
let start = position.saturating_sub(256);
|
|
assert!(source[start..position].contains("#[non_exhaustive]"), "evolutive public enum must be non_exhaustive: {enum_name}");
|
|
}
|
|
}
|
|
|
|
fn crate_root() -> std::path::PathBuf {
|
|
return std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
|
}
|