Skip to content

Price Oracle and Feeds

Overview

By leveraging oracles, the OpenGradient network provides access to trusted, real-time and historical price data that powers AI model execution and decision-making.

Why We Need Oracle Integration

Oracles are essential for the following reasons:

  • Real-time data feeds: AI models may need external inputs like cryptocurrency prices to execute predictions and decisions in real-time. Oracles allow smart contracts to access this data securely and in a decentralized manner.
  • Verification of inputs: AI models must rely on authentic and untampered inputs, especially when handling off-chain data. Oracles help ensure the security and reliability of these inputs, which are critical for secure AI inference.
  • Dynamic pricing of resources: For running AI models and secure inference, compute resources are priced based on demand. Oracles help provide real-time pricing information for these resources, ensuring that execution costs remain fair and decentralized.

Oracle Integration Overview

We are integrating oracles using Skip's Connect solution. This out-of-process service efficiently fetches price data from multiple sources, aggregates it into a single price feed, and periodically updates our chain using the new values. We are fetching the latest prices for each new block in our chain. Users and dApps can query the most recent prices directly from the blockchain.

In the rest of this document, we will provide two approaches to interact with the oracle and market map modules: API and Smart-contract.

Usage

API Endpoints

1. Get All Currency Pairs

  • Endpoint: /connect/oracle/v2/get_all_tickers
  • Method: GET
  • Description: Retrieve all currency pairs tracked by the oracle module.

2. Get Market Map

  • Endpoint: /connect/marketmap/v2/marketmap
  • Method: GET
  • Description: Retrieves the entire market map, including all markets and configurations.

3. Get price

  • Endpoint: /connect/oracle/v2/get_price
  • Method: GET
  • Description: This endpoint is responsible for fetching the current price of a specific currency pair tracked by the oracle.
bash
curl http://NODE_IP_ADDRESS:1317/connect/oracle/v2/get_price?currency_pair=ETH/USD
Response:
{
  "price": {
    "price": "2610437225",
    "block_timestamp": "2024-10-15T09:27:10.734785284Z",
    "block_height": "5753"
  },
  "nonce": "5480",
  "decimals": "6",
  "id": "25"
}

Querying Real-Time Data

The following Solidity smart contract demonstrates how to interact with the Oracle module to retrieve prices. Latest oracle price data is exposed through the ICosmos interface.

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

// Import the ICosmos interface
import "x/evm/contracts/i_cosmos/ICosmos.sol";

contract OracleTest {
    // The ICosmos contract's address on the EVM module
    ICosmos public cosmosContract;

    // Constructor that sets the address of the ICosmos contract
    constructor() {
        address cosmosContractAddress = 0x00000000000000000000000000000000000000f1;
        cosmosContract = ICosmos(cosmosContractAddress);
    }

    // Function to query the price of a given token pair (e.g., "ETH/USD")
    function queryCosmosPrice(string memory tokenPair) public view returns (uint256) {
        // Path to the oracle module's GetPrices endpoint
        string memory path = "/connect.oracle.v2.Query/GetPrices";
        
        // Create the request body with the token pair
        string memory request = string(abi.encodePacked('{"currency_pair_ids": ["', tokenPair, '"]}'));

        // Call the query_cosmos function to send the request to Cosmos
        string memory result = cosmosContract.query_cosmos(path, request);
    
        // Convert the result string to uint256 (assuming the result is numeric)
        uint256 price = parsePrice(result); // Implement a parsePrice function to extract the numeric value.
        return price;
    }
}

Explanation: queryCosmosPrice: Queries the price of a specific currency pair (e.g., "ETH/USD") and returns the price as a uint256.

Querying Historical Data (OGHistorical)

In addition to real-time data, you can retrieve historical price candles for a given currency pair using the OGHistorical contract. This functionality is useful for AI models that rely on time-series data or need to observe price history for analytics.

Historical Contract Interface

solidity
struct HistoricalInputQuery {
    string currency_pair;
    uint32 total_candles;
    uint32 candle_duration_in_mins; // e.g., 1 for 1 minute, 60 for 1 hour
    CandleOrder order;
    CandleType[] candle_types;
}

interface OGHistorical {
    function queryHistoricalCandles(
        HistoricalInputQuery memory input
    ) external returns (TensorLib.Number[] memory);

    function runInferenceOnPriceFeed(
        string memory model_id,
        string memory input_name,
        HistoricalInputQuery memory input
    ) external returns (ModelOutput memory);
}

Key Methods:

  1. queryHistoricalCandles: retrieves a specified number of candles (e.g., open, high, low, close) for a given currency pair in ascending or descending order.

    • currency_pair: e.g., "ETH/USD".
    • total_candles: Number of candles to fetch (e.g., 100).
    • candle_duration_in_mins: Duration of each candle in minutes.
    • order: Ascending or descending.
    • candle_types: Which candle data you want (e.g., [CandleType.High, CandleType.Low]).
  2. runInferenceOnPriceFeed runs an AI inference job on historical price data. For instance, you can supply a model ID, input name, and HistoricalInputQuery in order to do on-chain predictions or analysis using historical price data.

Example: Getting Historical Candles On-Chain

Suppose you want to get the last 24 hours of hourly candles (24 candles) for ETH/USD in ascending order. You might write a contract function like:

solidity
function fetch24HPriceHistory() external {
    HistoricalInputQuery memory query = HistoricalInputQuery({
        currency_pair: "ETH/USD",
        total_candles: 24,
        candle_duration_in_mins: 60,
        order: CandleOrder.Ascending,
        candle_types: new CandleType[](4)
    });

    // Populate candleTypes with Open, High, Low, Close (or any subset)
    query.candle_types[0] = CandleType.Open;
    query.candle_types[1] = CandleType.High;
    query.candle_types[2] = CandleType.Low;
    query.candle_types[3] = CandleType.Close;

    // Now call the OGHistorical contract
    TensorLib.Number[] memory historicalData = OGHistorical_CONTRACT.queryHistoricalCandles(query);
}

OpenGradient 2025