clp-feed-interface 0.1.1

Interface package for querying the CLP Feed oracle contract
Documentation

clp-feed-interface

Interface package for querying the Coreum Lending Protocol (CLP) Feed oracle contract. This package provides type-safe bindings for interacting with the CLP Feed price oracle, which aggregates validator-signed price data for various assets.

Installation

Add this to your Cargo.toml:

[dependencies]
clp-feed-interface = "0.1.0"
cosmwasm-std = "2.2"

Quick Start

Using the Helper Querier (Recommended)

use cosmwasm_std::{Deps, Addr, StdResult};
use clp_feed_interface::ClpFeedQuerier;

// In your contract's execute or query function
pub fn get_price(deps: Deps, oracle_addr: Addr, denom: String) -> StdResult<String> {
    let oracle = ClpFeedQuerier::new(&deps.querier, oracle_addr);
    
    let response = oracle.query_price_by_denom(denom)?;
    
    match response.price {
        Some(price_data) => Ok(price_data.price),
        None => Err(cosmwasm_std::StdError::generic_err("Price not found")),
    }
}

Direct Query

use cosmwasm_std::{Deps, Addr, StdResult};
use clp_feed_interface::{QueryMsg, AggregatedPriceResponse};

pub fn query_price(deps: Deps, oracle_addr: Addr, asset: String) -> StdResult<AggregatedPriceResponse> {
    deps.querier.query_wasm_smart(
        oracle_addr.to_string(),
        &QueryMsg::GetPrice { asset },
    )
}

Available Queries

Price Queries

GetPrice

Get the current aggregated price for an asset by name.

use clp_feed_interface::QueryMsg;

let query = QueryMsg::GetPrice { 
    asset: "ATOM".to_string() 
};

GetPriceByDenom

Get the current aggregated price for a denom (e.g., "uatom").

let query = QueryMsg::GetPriceByDenom { 
    denom: "uatom".to_string() 
};

GetAllPrices

Get all current aggregated prices.

let query = QueryMsg::GetAllPrices {};

Validator Queries

GetValidator

Get information about a specific validator.

let query = QueryMsg::GetValidator { 
    validator_id: "validator1".to_string() 
};

GetAllValidators

Get all registered validators.

let query = QueryMsg::GetAllValidators {};

Configuration Queries

GetConfig

Get contract configuration (min signatures, max price age).

let query = QueryMsg::GetConfig {};

GetAdmin

Get the admin address.

let query = QueryMsg::GetAdmin {};

GetOperators

Get all operator addresses.

let query = QueryMsg::GetOperators {};

GetDenomExists

Check if a denom is configured.

let query = QueryMsg::GetDenomExists { 
    denom: "uatom".to_string() 
};

GetRecentSubmission

Get a recent price submission from a specific validator.

let query = QueryMsg::GetRecentSubmission {
    asset: "ATOM".to_string(),
    validator_id: "validator1".to_string(),
};

Type Definitions

AggregatedPrice

The main price data structure returned by the oracle:

pub struct AggregatedPrice {
    pub asset: String,                    // Asset symbol (e.g., "ATOM")
    pub price: String,                    // Price as string
    pub timestamp: Timestamp,              // Last update timestamp
    pub deviation: Option<String>,         // Standard deviation (optional)
    pub submissions: Vec<PriceSubmission>, // Individual validator submissions
    pub feed_block_height: u64,            // Oracle feed block height
    pub chain_block_height: Option<u64>,   // Chain block height (optional)
}

PriceSubmission

Individual validator price submission:

pub struct PriceSubmission {
    pub validator_id: String,
    pub asset: String,
    pub price: String,
    pub timestamp: u64,        // Unix timestamp in seconds
    pub sources: Vec<String>,  // Price data sources
    pub signature: String,    // Ed25519 signature (hex-encoded)
}

ValidatorInfo

Validator information:

pub struct ValidatorInfo {
    pub public_key: String,  // Ed25519 public key (hex-encoded)
    pub active: bool,        // Whether validator is active
}

Complete Example

use cosmwasm_std::{Deps, DepsMut, Env, MessageInfo, Response, StdResult, Uint128};
use clp_feed_interface::{ClpFeedQuerier, AggregatedPriceResponse};

pub fn execute_trade(
    deps: DepsMut,
    env: Env,
    info: MessageInfo,
    collateral_denom: String,
    amount: Uint128,
) -> StdResult<Response> {
    // Load your contract's config (which should store the oracle address)
    let config = CONFIG.load(deps.storage)?;
    
    // Query the oracle for collateral price
    let oracle = ClpFeedQuerier::new(&deps.querier, config.oracle_address);
    let price_response = oracle.query_price_by_denom(collateral_denom.clone())?;
    
    // Extract price data
    let price_data = price_response.price
        .ok_or_else(|| cosmwasm_std::StdError::generic_err("Price not available"))?;
    
    // Validate price freshness (optional)
    let price_age = env.block.time.seconds() - price_data.timestamp.seconds();
    if price_age > 300 {
        return Err(cosmwasm_std::StdError::generic_err("Price data too old"));
    }
    
    // Use the price in your logic
    let price_value = price_data.price.parse::<f64>()
        .map_err(|_| cosmwasm_std::StdError::generic_err("Invalid price format"))?;
    
    // Your trading logic here...
    
    Ok(Response::new()
        .add_attribute("action", "trade")
        .add_attribute("price_used", price_data.price)
        .add_attribute("price_timestamp", price_data.timestamp.seconds().to_string()))
}

Response Types

All query responses are strongly typed:

  • AggregatedPriceResponse - Contains Option<AggregatedPrice>
  • AllPricesResponse - Contains Vec<AggregatedPrice>
  • ValidatorInfoResponse - Contains validator ID and Option<ValidatorInfo>
  • AllValidatorsResponse - Contains Vec<(String, ValidatorInfo)>
  • PriceSubmissionResponse - Contains Option<PriceSubmission>
  • ConfigResponse - Contains min_signatures: u32 and max_price_age: u64
  • AdminResponse - Contains admin: Addr
  • OperatorsResponse - Contains operators: Vec<Addr>
  • DenomExistsResponse - Contains exists: bool and asset: Option<AssetInfo>

Deployed Contracts

Mainnet

  • Contract Address: TBD (Update after deployment)

Testnet

  • Contract Address: TBD (Update after deployment)

Version Compatibility

clp-feed-interface clp-feed Contract Status
0.1.0 0.1.0 ✅ Compatible

Features

  • Type-safe - Full Rust type definitions for all queries and responses
  • Lightweight - Minimal dependencies (only CosmWasm standard libraries)
  • Helper functions - Convenient ClpFeedQuerier wrapper
  • Well-documented - Comprehensive inline documentation
  • Schema support - Compatible with CosmWasm schema generation

Error Handling

The oracle may return None for prices in certain cases:

  • Asset/denom not configured
  • No price data available yet
  • Price data expired

Always check for None values:

let response = oracle.query_price_by_denom("uatom".to_string())?;

match response.price {
    Some(price) => {
        // Use price
    },
    None => {
        // Handle missing price
        return Err(cosmwasm_std::StdError::generic_err("Price not available"));
    }
}

License

MIT

Links