CosmWasm

This section explains how to read data from Yggdrasil data feeds on Cosmos chains. We’ll cover how to get the data feed address, request data feeds, and handle the responses using callback messages. T

Getting the Data Feed Address

First, you'll need the Data Feed Address for the Cosmos chains you’re working with. You can find the addresses and their respective contract addresses in the relevant section of this documentation.

Using Data Feed Crate in your smart contracts

For sending requests and handling them users need to import Data Feed crate in their contracts , this enables them to use all the type definitions and messages of the data feed contract in their contracts . To plug in the crate simply add the following line of code in the Cargo.toml file of your contract .

price-feeds = "0.1.1"

Requesting the Data Feed or Data Feeds

You have two options for requesting data feeds:

  1. Request a Single Data Feed

  2. Request Multiple Data Feeds

Request a Single Data Feed

To request a single data feed, you can send a request directly to the data feed contract. Each price feed requires a fee in the native token of the blockchain. Below is the example to Request a single price feed

use price_feeds::{RequestPriceFeed , RequestPriceFeeds}; 
use price_feeds::msg::{PriceFeedResponse, PriceFeedsResponse , PriceFeedReq};

pub fn execute_request_single_price(
    deps: DepsMut,
    _info: MessageInfo,
    pair : String,
) -> Result<Response, ContractError> {
    let price_feed_contract = PRICE_FEED_CONTRACT.load(deps.storage)?;
    
    let request_msg = WasmMsg::Execute {
        contract_addr: deps.api.addr_validate(&price_feed_contract)?.to_string(),
        //msg to be called from the Data Feed Contract with the symbol for the required data feed 
        msg: to_json_binary(&RequestPriceFeed { symbol: pair})?,
        funds: vec![Coin{
            denom : "uom".to_string(), 
            amount: Uint128::new(1000)
        }],
    };

    Ok(Response::new()
        .add_message(request_msg)
        .add_attribute("action", "request_single_price")
    )
}

Request Multiple Data Feeds

To request multiple data feeds, use the PriceFeedReq type, which allows you to request an array of data feeds in one go. Here’s an example of how to request multiple price feeds in a smart contract:

pub fn execute_request_multiple_prices(
    deps: DepsMut,
    _info: MessageInfo,
    pairs: Vec<String>,
) -> Result<Response, ContractError> {
    let price_feed_contract = PRICE_FEED_CONTRACT.load(deps.storage)?;
    let length = pairs.clone().len();
    //request to be sent to the blockchain . 
    let request = PriceFeedReq { pairs };
    
    //request msg with specifications for the required data feed 
    let request_msg = WasmMsg::Execute {
        contract_addr: deps.api.addr_validate(&price_feed_contract)?.to_string(),
        msg: to_json_binary(&RequestPriceFeeds { request })?,
        funds: vec![Coin {
	//denom to be set the native token of the target chain 
            denom: "uom".to_string(),
            amount: Uint128::new(1000) * Uint128::new(length as u128),
        }],
    };

    Ok(Response::new()
        .add_message(request_msg)
        .add_attribute("action", "request_multiple_prices"))
}

🌳 Note: The request will fail if you define your own PriceFeedReq struct in the contract. It needs to be imported from the data feed crate.

Handling the Price Feed Response

After sending the request to the data feed contract, you need to specify callback functions to handle the responses. There are two types of callback messages:

  1. ReceivePrice: For handling a single price feed response.

  2. ReceivePrices: For handling multiple price feed responses.

Handling a Single Price Feed Response

To handle a single price feed response, use the ReceivePrice message. Here’s an example:

ExecuteMsg::ReceivePrice { price_response } => execute_receive_price(deps, env, info, price_response),

pub fn execute_receive_price(
    deps: DepsMut,
    _env: Env,
    _info: MessageInfo,
    price_response: PriceFeedResponse,
) -> Result<Response, ContractError> {
    let price_feed = PriceFeed {
        price: price_response.price,
    };

    PRICE_FEEDS.save(deps.storage, price_response.symbol, &price_feed)?;

    Ok(Response::new()
        .add_attribute("action", "receive_price")
        .add_attribute("price", price_response.price.to_string()))
}

Handling Multiple Price Feed Responses

To handle multiple price feed responses, use the ReceivePrices message. Here’s an example:

ExecuteMsg::ReceivePrices { prices_response } => execute_receive_prices(deps, env, info, prices_response),

pub fn execute_receive_prices(
    deps: DepsMut,
    _env: Env,
    _info: MessageInfo,
    prices_response: PriceFeedsResponse,
) -> Result<Response, ContractError> {
    for price_feed in prices_response.price_feeds.iter() {
        let price_feed_data = PriceFeed {
            price: price_feed.price,
        };
        PRICE_FEEDS.save(deps.storage, price_feed.symbol.clone(), &price_feed_data)?;
    }

    Ok(Response::new()
        .add_attribute("action", "receive_prices")
        .add_attribute("count", prices_response.price_feeds.len().to_string()))
}

Note - The logic for ReceivePrice and ReceivePrices messages can be modified according to your use case and requirements. The above given implementation is only for example.

Conclusion

By following the steps outlined above, you can efficiently request and handle data feeds in your smart contracts across all Cosmos chains. Make sure to use the provided data feed crate to avoid request failures and customize the callback logic to fit your specific needs. This process will enable seamless integration of accurate and reliable price feeds into your decentralized applications, ensuring you have up-to-date data for your operations.

Last updated