Push Oracle

Quick Start: Supra Price Feeds

Supra's Push oracle publishes price pairs on-chain regularly and at high frequencies, enabling consumers to get near real-time prices for their smart contracts. The Push oracle functions via partnerships Supra has with respective chains to share, ensuring that frequent feed updates are available for these destination chains without interruption. Both the Push model and Pull model (on demand) have the same number of data pairs offered by Supra.

Integrating with Supra price feeds is quick and easy. The price feed value published by Supra is known as an S-Value (aka Supra Value). In the following sections, we will demonstrate how to retrieve an S-Value using Supra's Push model.

Please refer to the below resources for a better understanding of our price feeds.

  • Data Feeds - This explains how Supra calculates the S-value for an asset.

  • Data Feeds Index - This provides a list of data pairs currently offered by Supra.

  • Available Networks - This is a list of available networks and Supra contract addresses.

Let's begin!

Step 1: Create the S-value interface

Import the interface from the DORA Interface (https://github.com/Entropy-Foundation/dora-interface) Git repository, and add the subdirectory Testnet you to use for integration.

Step 2: Configure the S-value feed dependency

Create your project and add the below dependencies in your Move.toml

Testnet

[dependencies]
core = { git = "https://github.com/Entropy-Foundation/dora-interface", subdir = "supra/testnet/core", rev = "master" }

Mainnet

Coming soon

Step 3: Request S-values for data feeds

Now you can easily request S-values of any supported data pairs.

  • Import : supra_oracle::supra_oracle_storage

use aptos_std::table::{Self, Table};
use supra_oracle::supra_oracle_storage;
  • Add the following structs

struct PriceConfiguration has key {
        feeds: Table<u32, PriceStrategy>,
    }

    struct PriceStrategy has store, copy, drop {
        high: u128,
        low: u128,
        start_time: u64,
        end_time: u64,
    }

PriceConfiguration is the main resource structure for this module. It has a `feeds` map that stores the price strategy feeds. &#xNAN;PriceStrategy represents a strategy feed entry with high, low, start time, and end time.

  • Next, add the `init_module function below:

fun init_module(owner: &signer) {
        move_to(owner, PriceConfiguration{ feeds:table::new<u32, PriceStrategy>()});
    }

This initializes the PriceConfiguration with an empty feeds vector map. Then, it shares this resource.

  • Add the set_high_low function. This function sets the high and low price of a specific pair in the PriceConfiguration. If the pair already exists, it updates the existing PriceStrategy; if not, it inserts a new PriceStrategy.

public entry fun set_high_low(supra_pair_id: u32) acquires PriceConfiguration {
        assert!(supra_oracle_storage::does_pair_exist(supra_pair_id), 0);
        let (current_price, _, _, current_round) = supra_oracle_storage::get_price(supra_pair_id);
        let price_configuration = borrow_global_mut<PriceConfiguration>(@supra_client);
        let price_strategy = table::borrow_mut_with_default(
            &mut price_configuration.feeds,
            supra_pair_id,
            PriceStrategy { high: 0, low: 0, start_time: 0, end_time: 0 }
        );

        if ((price_strategy.high + price_strategy.low) == 0) {
            price_strategy.high = current_price;
            price_strategy.low = current_price;
            price_strategy.start_time = current_round;
            price_strategy.end_time = current_round;
        }
        else {
            if (current_price > price_strategy.high) {
                price_strategy.high = current_price;
            }
            else if (current_price < price_strategy.low) {
                price_strategy.low = current_price;
            };
            price_strategy.end_time = current_round;
        }
    }
  • Add the following check_price_strategy function to retrieve Strategic Price of one pair between an interval. This public view function fetches the strategic price for a single pair thats been updated by the above function set_high_low .

#[view]
    public fun check_price_strategy(supra_pair_id:u32):PriceStrategy acquires PriceConfiguration {
        *table::borrow(& borrow_global<PriceConfiguration>(@supra_client).feeds,supra_pair_id)
    }
  • To retrieve a S-value for multiple pairs you can design a public view function get_pair_price_sum that fetches prices for multiple pairs from the oracle, adds them and returns the sum.

#[view]
    public fun get_pair_price_sum(pairs: vector<u32>):u256 {
        let prices:vector<Price> = supra_oracle_storage::get_prices(pairs);
        let sum:u256 = 0;

        vector::for_each_reverse(prices,|price| {
            let (_,value,_,_,_) = supra_oracle_storage::extract_price(&price);
            sum = sum + (value as u256);
        });
        return sum
    }

Derived Pairs - Convert a data pair to any currency with ease

There have been many requests to provide functionality convert the prices to USD. While we take data directly from exchange quoted pairs mostly in stable coins (USDT/USDC), conversion at our end adds more latency and extra layer of margin for error. (*The oracle services who provide USD prices are already converting the USDT prices at their backend with previously mentioned disadvantages of that method). Still, for those who are in need we provide that as a custom function to convert and derive any pair using operators of Multiplication(parameter=0) or Division(Parameter=1).

  1. Import supra_oracle::supra_oracle_storage dependency:

    use supra_oracle::supra_oracle_storage ;
  2. Next, add the `init_module function below:

    fun init_module(owner_signer: &signer) {
       move_to(owner_signer, EmitDerivePair { derived_pair: account::new_event_handle<DerivedPair>(owner_signer) });
    }

Add the following get_update_derived_price function to retrieve S-value for the derived pair. This public entry function fetches the price for a derived pair from the supra_oracle_storage module and emits an event for the Derived Pair Feed.

public entry fun get_derived_pair_price(
  _signer: &signer,
  pair_id1: u32,
  pair_id2: u32,
  operation: u8
) acquires EmitDerivePair {
    let (value, decimal, round_difference, round_compare) = supra_oracle_storage::get_derived_price(pair_id1, pair_id2, operation);

  let event_handler = borrow_global_mut<EmitDerivePair>(@client_example);
  let derived_pair = DerivedPair { pair_id1, pair_id2, operation, value, decimal, round_difference, round_compare };
  event::emit_event<DerivedPair>(&mut event_handler.derived_pair, derived_pair);
}

From the above code:

  • pair: a pair index number from which you want to retrieve the price value

  • pairs: Index numbers of multiple pairs from which you want to retrieve the price value

Tada! You now have a method in your Smart Contract that you can call at any time to retrieve the price of the selected pair.

\

Last updated