v0.2.11-pre.006
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
// file: crates/ksp-offchain-transport-lib/unit_tests/market_price_dexscreener.rs
|
||||
// version: 1
|
||||
|
||||
const TEST_PAIR: &str = "Czfq3xZZDmsdGdUyrNLtRhGc47cXcZtLG4crryfu44zE";
|
||||
|
||||
#[test]
|
||||
fn dexscreener_fixture_validates_chain_pair_and_sol_identity_and_maps_exact_pair_usd() -> ksp_core_lib::Result<()> {
|
||||
let provider_id = match crate::MarketPriceProviderId::new(super::DEXSCREENER_PROVIDER_ID) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let pair_address = match TEST_PAIR.parse::<ksp_core_lib::Pubkey>() {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(super::provider_settings_error("test_pair")),
|
||||
};
|
||||
let fixture = concat!(
|
||||
r#"{"schemaVersion":"1.0.0","pairs":[{"chainId":"solana","dexId":"orca","pairAddress":"Czfq3xZZDmsdGdUyrNLtRhGc47cXcZtLG4crryfu44zE","#,
|
||||
r#""baseToken":{"address":"So11111111111111111111111111111111111111112","name":"Wrapped SOL","symbol":"SOL"},"#,
|
||||
r#""quoteToken":{"address":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v","name":"USD Coin","symbol":"USDC"},"#,
|
||||
r#""priceNative":"151.987654321012345678","priceUsd":"151.987654321012345678"}]}"#
|
||||
)
|
||||
.as_bytes();
|
||||
let started = crate::MarketPriceTimestamp::from_unix_millis(10);
|
||||
let received = crate::MarketPriceTimestamp::from_unix_millis(20);
|
||||
let observation = match super::parse_response(fixture, provider_id, &pair_address, started, received) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
assert_eq!(observation.price().to_canonical_string(), "151.987654321012345678");
|
||||
assert_eq!(observation.semantics(), crate::MarketPriceSemantics::DexPairUsd);
|
||||
assert_eq!(observation.provider_timestamp(), std::option::Option::None);
|
||||
assert_eq!(observation.provenance().as_str(), "dexscreener:solana:Czfq3xZZDmsdGdUyrNLtRhGc47cXcZtLG4crryfu44zE:priceUsd");
|
||||
return std::result::Result::Ok(());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dexscreener_settings_and_descriptor_keep_pair_explicit_and_pair_endpoint_rate_limited() -> ksp_core_lib::Result<()> {
|
||||
assert!(crate::MarketPriceDexScreenerSettings::new(true, "not-a-pubkey").is_err());
|
||||
let settings = match crate::MarketPriceDexScreenerSettings::new(true, TEST_PAIR) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
assert_eq!(settings.pair_address().to_string(), TEST_PAIR);
|
||||
let request = match super::build_request(settings.pair_address()) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
assert_eq!(request.url_for_test().as_str(), "https://api.dexscreener.com/latest/dex/pairs/solana/Czfq3xZZDmsdGdUyrNLtRhGc47cXcZtLG4crryfu44zE");
|
||||
let provider = match crate::MarketPriceDexScreenerProvider::new(settings) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
assert_eq!(provider.descriptor().auth_mode(), crate::MarketPriceProviderAuthMode::None);
|
||||
assert_eq!(provider.descriptor().semantics(), crate::MarketPriceSemantics::DexPairUsd);
|
||||
assert_eq!(provider.descriptor().rate_limit().requests(), std::option::Option::Some(300));
|
||||
assert_eq!(provider.descriptor().rate_limit().window_seconds(), std::option::Option::Some(60));
|
||||
assert_eq!(provider.descriptor().rate_limit().scope(), crate::MarketPriceProviderRateLimitScope::Unspecified);
|
||||
return std::result::Result::Ok(());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dexscreener_rejects_wrong_chain_pair_base_identity_multiple_pairs_and_missing_price() -> ksp_core_lib::Result<()> {
|
||||
let provider_id = match crate::MarketPriceProviderId::new(super::DEXSCREENER_PROVIDER_ID) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let pair_address = match TEST_PAIR.parse::<ksp_core_lib::Pubkey>() {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return std::result::Result::Err(super::provider_settings_error("test_pair")),
|
||||
};
|
||||
let timestamp = crate::MarketPriceTimestamp::from_unix_millis(10);
|
||||
let wrong_chain = concat!(
|
||||
r#"{"pairs":[{"chainId":"ethereum","pairAddress":"Czfq3xZZDmsdGdUyrNLtRhGc47cXcZtLG4crryfu44zE","#,
|
||||
r#""baseToken":{"address":"So11111111111111111111111111111111111111112"},"priceUsd":"151.98"}]}"#
|
||||
)
|
||||
.as_bytes();
|
||||
assert!(super::parse_response(wrong_chain, provider_id.clone(), &pair_address, timestamp, timestamp).is_err());
|
||||
let wrong_pair = concat!(
|
||||
r#"{"pairs":[{"chainId":"solana","pairAddress":"58oQChx4yWmvKdwLLZzBi4ChoCc2fqCUWBkwMihLYQo2","#,
|
||||
r#""baseToken":{"address":"So11111111111111111111111111111111111111112"},"priceUsd":"151.98"}]}"#
|
||||
)
|
||||
.as_bytes();
|
||||
assert!(super::parse_response(wrong_pair, provider_id.clone(), &pair_address, timestamp, timestamp).is_err());
|
||||
let wrong_base = concat!(
|
||||
r#"{"pairs":[{"chainId":"solana","pairAddress":"Czfq3xZZDmsdGdUyrNLtRhGc47cXcZtLG4crryfu44zE","#,
|
||||
r#""baseToken":{"address":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"},"priceUsd":"1.00"}]}"#
|
||||
)
|
||||
.as_bytes();
|
||||
assert!(super::parse_response(wrong_base, provider_id.clone(), &pair_address, timestamp, timestamp).is_err());
|
||||
let multiple = concat!(
|
||||
r#"{"pairs":[{"chainId":"solana","pairAddress":"Czfq3xZZDmsdGdUyrNLtRhGc47cXcZtLG4crryfu44zE","#,
|
||||
r#""baseToken":{"address":"So11111111111111111111111111111111111111112"},"priceUsd":"151.98"},{"#,
|
||||
r#""chainId":"solana","pairAddress":"Czfq3xZZDmsdGdUyrNLtRhGc47cXcZtLG4crryfu44zE","#,
|
||||
r#""baseToken":{"address":"So11111111111111111111111111111111111111112"},"priceUsd":"151.98"}]}"#
|
||||
)
|
||||
.as_bytes();
|
||||
assert!(super::parse_response(multiple, provider_id.clone(), &pair_address, timestamp, timestamp).is_err());
|
||||
let missing_price = concat!(
|
||||
r#"{"pairs":[{"chainId":"solana","pairAddress":"Czfq3xZZDmsdGdUyrNLtRhGc47cXcZtLG4crryfu44zE","#,
|
||||
r#""baseToken":{"address":"So11111111111111111111111111111111111111112"},"priceUsd":null}]}"#
|
||||
)
|
||||
.as_bytes();
|
||||
assert!(super::parse_response(missing_price, provider_id, &pair_address, timestamp, timestamp).is_err());
|
||||
return std::result::Result::Ok(());
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
// file: crates/ksp-offchain-transport-lib/unit_tests/market_price_jupiter.rs
|
||||
// version: 1
|
||||
|
||||
#[test]
|
||||
fn jupiter_fixture_maps_exact_heuristic_price_and_block_provenance_without_fake_timestamp() -> ksp_core_lib::Result<()> {
|
||||
let provider_id = match crate::MarketPriceProviderId::new(super::JUPITER_PROVIDER_ID) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let fixture = concat!(
|
||||
r#"{"So11111111111111111111111111111111111111112":{"createdAt":"2024-06-05T08:55:25.527Z","liquidity":621679197.67,"#,
|
||||
r#""usdPrice":151.987654321012345678,"blockId":348004023,"decimals":9,"priceChange24h":1.29}}"#
|
||||
)
|
||||
.as_bytes();
|
||||
let started = crate::MarketPriceTimestamp::from_unix_millis(10);
|
||||
let received = crate::MarketPriceTimestamp::from_unix_millis(20);
|
||||
let observation = match super::parse_response(fixture, provider_id, started, received) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
assert_eq!(observation.price().to_canonical_string(), "151.987654321012345678");
|
||||
assert_eq!(observation.semantics(), crate::MarketPriceSemantics::SolanaHeuristic);
|
||||
assert_eq!(observation.provider_timestamp(), std::option::Option::None);
|
||||
assert_eq!(observation.provenance().as_str(), "jupiter:price_v3:So11111111111111111111111111111111111111112:block:348004023");
|
||||
return std::result::Result::Ok(());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn jupiter_modes_match_current_keyless_and_free_rate_limits_and_redact_key() -> ksp_core_lib::Result<()> {
|
||||
let keyless = match crate::MarketPriceJupiterSettings::keyless(true) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let keyless_provider = match crate::MarketPriceJupiterProvider::new(keyless) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
assert_eq!(keyless_provider.descriptor().auth_mode(), crate::MarketPriceProviderAuthMode::None);
|
||||
assert_eq!(keyless_provider.descriptor().semantics(), crate::MarketPriceSemantics::SolanaHeuristic);
|
||||
assert_eq!(keyless_provider.descriptor().rate_limit().requests(), std::option::Option::Some(1));
|
||||
assert_eq!(keyless_provider.descriptor().rate_limit().window_seconds(), std::option::Option::Some(2));
|
||||
assert_eq!(keyless_provider.descriptor().rate_limit().scope(), crate::MarketPriceProviderRateLimitScope::Unspecified);
|
||||
let free = match crate::MarketPriceJupiterSettings::free(true, std::option::Option::Some("jup-free-canary-secret".to_owned())) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
assert!(!std::format!("{free:?}").contains("jup-free-canary-secret"));
|
||||
let request = match super::build_request(&free) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
assert!(request.has_header_for_test(super::JUPITER_API_KEY_HEADER));
|
||||
assert_eq!(request.url_for_test().query(), std::option::Option::Some("ids=So11111111111111111111111111111111111111112"));
|
||||
let free_provider = match crate::MarketPriceJupiterProvider::new(free) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
assert_eq!(free_provider.descriptor().auth_mode(), crate::MarketPriceProviderAuthMode::RequiredApiKey);
|
||||
assert_eq!(free_provider.descriptor().rate_limit().requests(), std::option::Option::Some(1));
|
||||
assert_eq!(free_provider.descriptor().rate_limit().window_seconds(), std::option::Option::Some(1));
|
||||
assert_eq!(free_provider.descriptor().rate_limit().scope(), crate::MarketPriceProviderRateLimitScope::Account);
|
||||
return std::result::Result::Ok(());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn jupiter_rejects_keyless_credential_missing_price_wrong_identity_and_wrong_decimals() -> ksp_core_lib::Result<()> {
|
||||
assert!(crate::MarketPriceJupiterSettings::free(true, std::option::Option::None).is_err());
|
||||
assert!(crate::MarketPriceJupiterSettings::keyless(true).is_ok());
|
||||
let provider_id = match crate::MarketPriceProviderId::new(super::JUPITER_PROVIDER_ID) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let timestamp = crate::MarketPriceTimestamp::from_unix_millis(10);
|
||||
let missing_price = br#"{"So11111111111111111111111111111111111111112":{"usdPrice":null,"blockId":348004023,"decimals":9}}"#;
|
||||
assert!(super::parse_response(missing_price, provider_id.clone(), timestamp, timestamp).is_err());
|
||||
let wrong_identity = br#"{"JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN":{"usdPrice":1.0,"blockId":348004023,"decimals":6}}"#;
|
||||
assert!(super::parse_response(wrong_identity, provider_id.clone(), timestamp, timestamp).is_err());
|
||||
let wrong_decimals = br#"{"So11111111111111111111111111111111111111112":{"usdPrice":151.98,"blockId":348004023,"decimals":8}}"#;
|
||||
assert!(super::parse_response(wrong_decimals, provider_id, timestamp, timestamp).is_err());
|
||||
return std::result::Result::Ok(());
|
||||
}
|
||||
Reference in New Issue
Block a user