> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pragma.build/llms.txt
> Use this file to discover all available pages before exploring further.

# Consuming Data

> Full scope of what you can do with Pragma

You can find the list of supported assets [here](./assets).

The current Pragma addresses are:

| Network          | Address                                                           | Explorer                                                                                                                                                                                                                                               |
| ---------------- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Starknet Mainnet | 0x2a85bd616f912537c50a49a4076db02c00b29b2cdc8a197ce92ed1837fa875b | [Starkscan](https://starkscan.co/contract/0x2a85bd616f912537c50a49a4076db02c00b29b2cdc8a197ce92ed1837fa875b) [Voyager](https://voyager.online/contract/0x2a85bd616f912537c50a49a4076db02c00b29b2cdc8a197ce92ed1837fa875b)                              |
| Starknet Sepolia | 0x36031daa264c24520b11d93af622c848b2499b66b41d611bac95e13cfca131a | [Starkscan](https://sepolia.starkscan.co/contract/0x36031daa264c24520b11d93af622c848b2499b66b41d611bac95e13cfca131a) [Voyager](https://sepolia.voyager.online/contract/0x36031daa264c24520b11d93af622c848b2499b66b41d611bac95e13cfca131a#accountCalls) |

## Sample Code

If you are just trying to get started with our price feeds, see the self-contained code snippets below. If you'd like to use more advanced oracle functions please see the further information below. You can find a full sample data feed consumer contract [here](https://github.com/Astraly-Labs/pragma-hack/tree/master) and the full Oracle interface specification is available [here](https://github.com/astraly-labs/pragma-oracle/blob/main/pragma-oracle/src/oracle/oracle.cairo).

## Add Pragma as a dependency to your scarb/snforge project

```shell theme={null}
scarb add pragma_lib --git https://github.com/astraly-labs/pragma-lib
```

### BTC/USD Spot Median Price

<CodeGroup>
  ```rust get_asset_price_median.cairo theme={null}
  use pragma_lib::abi::{IPragmaABIDispatcher, IPragmaABIDispatcherTrait};
  use pragma_lib::types::{AggregationMode, DataType, PragmaPricesResponse};
  use starknet::ContractAddress;
  use starknet::contract_address::contract_address_const;

  const KEY :felt252 = 18669995996566340; // felt252 conversion of "BTC/USD"

  fn get_asset_price_median(oracle_address: ContractAddress, asset : DataType) -> u128  {
      let oracle_dispatcher = IPragmaABIDispatcher{contract_address : oracle_address};
      let output : PragmaPricesResponse= oracle_dispatcher.get_data(asset, AggregationMode::Median(()));
      return output.price;
  }
  ```

  ```rust usage.cairo theme={null}
  let oracle_address : ContractAddress = contract_address_const::<0x06df335982dddce41008e4c03f2546fa27276567b5274c7d0c1262f3c2b5d167>();
  let price = get_asset_price_median(oracle_address, DataType::SpotEntry(KEY));
  ```
</CodeGroup>

#### SOL/USD Spot Average Price, filtered by sources

<CodeGroup>
  ```rust get_asset_price_average.cairo theme={null}

  use pragma_lib::abi::{IPragmaABIDispatcher, IPragmaABIDispatcherTrait};
  use pragma_lib::types::{AggregationMode, DataType, PragmaPricesResponse};
  use starknet::ContractAddress;
  use starknet::contract_address::contract_address_const;
  use array::ArrayTrait;

  const KEY: felt252 = 23449611697214276; // felt252 conversion of "SOL/USD", can also write const KEY : felt252 = 'SOL/USD'
  const OKX: felt252 = 'OKX'; // felt252 conversion of "OKX"
  const BINANCE: felt252 = 'BINANCE'; // felt252 conversion of "BINANCE"

  fn get_asset_price_average(oracle_address: ContractAddress, asset : DataType, sources : Span<felt252>) -> u128  {
      let oracle_dispatcher = IPragmaABIDispatcher{contract_address : oracle_address};
      let output : PragmaPricesResponse= oracle_dispatcher.get_data_for_sources(asset, AggregationMode::Mean(()), sources);

      return output.price;
  }
  ```

  ```rust usage.cairo theme={null}
  let oracle_address : ContractAddress = contract_address_const::<0x06df335982dddce41008e4c03f2546fa27276567b5274c7d0c1262f3c2b5d167>();

  let mut sources = ArrayTrait::<felt252>::new();
  sources.append(OKX);
  sources.append(BINANCE);

  let price = get_asset_price_average(oracle_address, DataType::SpotEntry(KEY), sources.span());
  ```
</CodeGroup>

#### BTC/USD Future Price

<CodeGroup>
  ```rust get_asset_price_median.cairo theme={null}
  use pragma_lib::abi::{IPragmaABIDispatcher, IPragmaABIDispatcherTrait};
  use pragma_lib::types::{AggregationMode, DataType, PragmaPricesResponse};
  use starknet::ContractAddress;
  use starknet::contract_address::contract_address_const;

  const KEY :felt252 = 18669995996566340; // felt252 conversion of "BTC/USD", can write const KEY : felt252 = 'BTC/USD'

  fn get_asset_price_median(oracle_address: ContractAddress, asset : DataType) -> u128  {
      let oracle_dispatcher = IPragmaABIDispatcher{contract_address : oracle_address};
      let output : PragmaPricesResponse= oracle_dispatcher.get_data(asset, AggregationMode::Median(()));

      return output.price;
  }
  ```

  ```rust usage.cairo theme={null}
  let oracle_address : ContractAddress = contract_address_const::<0x06df335982dddce41008e4c03f2546fa27276567b5274c7d0c1262f3c2b5d167>();
  let expiration_timestamp = 1691395615; //in seconds
  let price = get_asset_price_median(oracle_address, DataType::FutureEntry((KEY, expiration_timestamp)));
  ```
</CodeGroup>

## Conversion Rate

<Info>
  For some assets such as liquid staking tokens, it's actually more relevant to use the conversion rate rather than the market price given the liquidity is often poor for these assets.
  To use this special aggregation method, the base token first needs to be associated to a vault address which follows the [ERC4626](https://erc4626.info/) standard.
</Info>

#### Sample code

<CodeGroup>
  ```rust get_asset_conversion_rate.cairo theme={null}
  use pragma_lib::abi::{IPragmaABIDispatcher, IPragmaABIDispatcherTrait};
  use pragma_lib::types::{AggregationMode, DataType, PragmaPricesResponse};
  use starknet::ContractAddress;
  use starknet::contract_address::contract_address_const;

  const KEY :felt252 = 1629317993172502401860; // felt252 conversion of "XSTRK/USD", can write const KEY : felt252 = 'XSTRK/USD'

  fn get_asset_conversion_rate(oracle_address: ContractAddress, asset : DataType) -> u128  {
      let oracle_dispatcher = IPragmaABIDispatcher{contract_address : oracle_address};
      let output : PragmaPricesResponse= oracle_dispatcher.get_data(asset,AggregationMode::ConversionRate);

      return output.price;
  }
  ```

  ```rust usage.cairo theme={null}
  let oracle_address : ContractAddress = contract_address_const::<0x06df335982dddce41008e4c03f2546fa27276567b5274c7d0c1262f3c2b5d167>();
  let price = get_asset_conversion_rate(oracle_address, DataType::SpotEntry((KEY)));
  ```
</CodeGroup>

Alternatively, we implemented a specialized conversion rate feed that automatically calculates the conversion rate for specific feeds. Calling these feeds follows a process similar to retrieving spot BTC/USD prices.

<Info>
  For the list of supported conversion rate feeds, see the [Conversion Rates section](./assets#conversion-rates) in the assets documentation.
</Info>

<CodeGroup>
  ```rust get_asset_conversion_rate.cairo theme={null}
  use pragma_lib::abi::{IPragmaABIDispatcher, IPragmaABIDispatcherTrait};
  use pragma_lib::types::{AggregationMode, DataType, PragmaPricesResponse};
  use starknet::ContractAddress;
  use starknet::contract_address::contract_address_const;

  const KEY :felt252 = 384270964630611589151504336040175440891848512324; // felt252 conversion of "CONVERSION_XSTRK/USD", can write const KEY : felt252 = 'CONVERSION_XSTRK/USD'

  fn get_asset_conversion_rate(oracle_address: ContractAddress, asset : DataType) -> u128  {
      let oracle_dispatcher = IPragmaABIDispatcher{contract_address : oracle_address};
      let output : PragmaPricesResponse = oracle_dispatcher.get_data(asset,AggregationMode::Median);

      return output.price;
  }
  ```

  ```rust usage.cairo theme={null}
  let oracle_address : ContractAddress = contract_address_const::<0x06df335982dddce41008e4c03f2546fa27276567b5274c7d0c1262f3c2b5d167>();
  let price = get_asset_conversion_rate(oracle_address, DataType::SpotEntry((KEY)));
  ```
</CodeGroup>

<Warning>
  It will only work with the `Median` aggregation mode.
</Warning>

## Technical Specification

<AccordionGroup>
  <Accordion title="get_data_median">
    ### Function: `get_data_median`

    The simplest function that aggregates all data into a median for a given data type.

    #### Inputs

    * `data_type`: enum of the data type you are requesting (See DataType structure). By providing the enum data type, you also provide the pair id (for spot entries), or the pair id and the expiration timestamp (for futures).

    #### Returns

    A `PragmaPricesResponse` struct containing:

    * `price`: aggregation result using robust median algorithm (multiplied by `10**decimals`)
    * `decimals`: number of places value has been shifted
    * `last_updated_timestamp`: timestamp of most recent entry
    * `num_sources_aggregated`: number of sources in final answer
    * `expiration_timestamp`: expiration timestamp (futures only)
  </Accordion>

  <Accordion title="get_data_median_for_sources">
    ### Function: `get_data_median_for_sources`

    Aggregates data from specified sources into a median for a given data type.

    #### Inputs

    * `data_type`: enum of data type requested (provides pair id or pair id + expiration timestamp)
    * `sources`: array of sources to aggregate (Span of felt252)

    #### Returns

    A `PragmaPricesResponse` struct containing:

    * `price`: median aggregation result (multiplied by `10**decimals`)
    * `decimals`: decimal places shifted
    * `last_updated_timestamp`: most recent entry timestamp
    * `num_sources_aggregated`: source count in final result
    * `expiration_timestamp`: expiration time (futures only)
  </Accordion>

  <Accordion title="get_data">
    ### Function: `get_data`

    Like get\_data\_median but with custom aggregation logic options.

    #### Inputs

    * `data_type`: enum of requested data type
    * `aggregation_mode`: mode for combining data sources (MEDIAN, MEAN, or CONVERSIONRATE)

    #### Returns

    * `price`: aggregated result using specified mode (multiplied by `10**decimals`)
    * `decimals`: decimal places shifted
    * `last_updated_timestamp`: most recent entry timestamp
    * `num_sources_aggregated`: sources in final answer
    * `expiration_timestamp`: expiration time (futures only)
  </Accordion>

  <Accordion title="get_data_with_USD_hop">
    ### Function: `get_data_with_USD_hop`

    Enables price rebasing with different base currency (e.g., BTC/ETH from BTC/USD and ETH/USD).

    #### Inputs

    * `base_currency_id`: base currency felt252 (e.g., BTC)
    * `quote_currency_id`: quote currency felt252 (e.g., ETH)
    * `aggregation_mode`: combining mode (MEDIAN, MEAN, CONVERSIONRATE)
    * `typeof`: SimpleDataType enum
    * `expiration_timestamp`: expiration time (futures only)

    #### Returns

    * `price`: aggregated result (multiplied by `10**decimals`)
    * `decimals`: decimal shift
    * `last_updated_timestamp`: latest entry time
    * `num_sources_aggregated`: source count
    * `expiration_timestamp`: expiration (futures only)
  </Accordion>

  <Accordion title="get_data_for_sources">
    ### Function: `get_data_for_sources`

    Gets price with specified currency path and sources.

    #### Inputs

    * `data_type`: data type enum
    * `aggregation_mode`: combining mode (MEDIAN, MEAN, CONVERSIONRATE)
    * `sources`: source array (Span of felt252)

    #### Returns

    * `price`: aggregated result (multiplied by `10**decimals`)
    * `decimals`: decimal places
    * `last_updated_timestamp`: latest update time
    * `num_sources_aggregated`: source count
    * `expiration_timestamp`: expiration (futures only)
  </Accordion>

  <Accordion title="get_data_entry">
    ### Function: `get_data_entry`

    Retrieves most recent raw data point for specific asset, source, and publisher.

    #### Inputs

    * `data_type`: data type enum
    * `source`: uppercased UTF8-encoded source (e.g., `str_to_felt("GEMINI")`)
    * `publisher`: publisher to consider (e.g., `str_to_felt("PRAGMA")`)

    #### Returns

    * `possible_entry`: PossibleEntry enum containing base entry (timestamp, source, publisher) and additional data (type, price, volume)
  </Accordion>

  <Accordion title="get_data_entries">
    ### Function: `get_data_entries`

    Gets multiple raw data points for specific asset across all sources.

    #### Inputs

    * `data_type`: data type enum

    #### Returns

    Array of `possible_entry` enums, each containing base entry and additional data
  </Accordion>

  <Accordion title="get_data_entries_for_sources">
    ### Function: `get_data_entries_for_sources`

    Gets recent raw data for specific asset and source list.

    #### Inputs

    * `data_type`: data type enum
    * `sources`: source array (Span of felt252)

    #### Returns

    * Array of `possible_entry` enums
    * `timestamp`: most recent entry time
  </Accordion>

  <Accordion title="get_last_checkpoint_before">
    ### Function: `get_last_checkpoint_before`

    Returns last oracle price snapshot before given timestamp.

    #### Inputs

    * `data_type`: data type enum
    * `timestamp`: target timestamp
    * `aggregation_mode`: combining mode

    #### Returns

    * `checkpoint`: Checkpoint struct (timestamp, value, mode, source count)
    * `idx`: checkpoint index (u64)
  </Accordion>

  <Accordion title="get_latest_checkpoint_index">
    ### Function: `get_latest_checkpoint_index`

    Returns index of latest oracle price snapshot.

    #### Inputs

    * `data_type`: data type enum
    * `aggregation_mode`: combining mode

    #### Returns

    * `idx`: latest checkpoint index (u64)
    * `is_valid`: validity flag
  </Accordion>

  <Accordion title="get_latest_checkpoint">
    ### Function: `get_latest_checkpoint`

    Returns latest oracle price snapshot.

    #### Inputs

    * `data_type`: data type enum
    * `aggregation_mode`: combining mode

    #### Returns

    * `checkpoint`: Checkpoint struct (timestamp, value, mode, source count)
  </Accordion>
</AccordionGroup>
