# Add support for a new spot price

When creating a new feed, it is highly incentivised to share it with the community via the Fetch open source [Github](https://github.com/fetchoracle/telliot-feeds/compare). This ensures all the reporters are aligned on new feeds requirements so that the safety of the network can be validated by DVMs and the whole community of reporters.

{% hint style="danger" %} <mark style="color:red;">**Each reporter is responsible for the data they're submitting**</mark><mark style="color:red;">.</mark>

Make sure to check FIRST which feed you are reporting and what sources they are using! (Submitting data to *Testnet first* is a great way to test your new feed without risking real money)

Submitting data that is deemed incorrect may be challenged by *anyone* in the community and you risk losing at least 1 stake per report disputed!

It's highly beneficial and recommended to check within the community of reporters which feeds and sources are being accepted as truth **and** what are the thresholds of tolerance for monitoring data submitted.

You can get more info on all the above at the official telegram group:

<https://t.me/fetchoracle>
{% endhint %}

## Prerequisites

* Python >= 3.9, < 3.10
* Setup environment (see [here](/the-basics/contributing.md))

## Steps

1. Add spot price to catalog. See `src/telliot_feeds/queries/query_catalog.py`. For example let's add a query called `btctest-usd-spot` for testing, adding `BTCTEST/USD`:

```python
query_catalog.add_entry(
    tag="btctest-usd-spot",
    title="BTCTEST/USD spot price",
    q=SpotPrice(asset="btc", currency="usd"),
)
```

2. Add data feed in `src/telliot_feeds/feeds/`. For example, for adding `BTCTEST/USD`, create file `src/telliot_feeds/feeds/btctest_usd_feed.py`:

```python
from telliot_feeds.datafeed import DataFeed
from telliot_feeds.queries.price.spot_price import SpotPrice
from telliot_feeds.sources.price.spot.binance import BinanceSpotPriceSource
from telliot_feeds.sources.price.spot.coinbase import CoinbaseSpotPriceSource
from telliot_feeds.sources.price.spot.coingecko import CoinGeckoSpotPriceSource
from telliot_feeds.sources.price.spot.gemini import GeminiSpotPriceSource
from telliot_feeds.sources.price.spot.kraken import KrakenSpotPriceSource
from telliot_feeds.sources.price_aggregator import PriceAggregator

btctest_usd_median_feed = DataFeed(
    query=SpotPrice(asset="BTCTEST", currency="USD"),
    source=PriceAggregator(
        asset="btctest",
        currency="usd",
        algorithm="median",
        sources=[
            CoinGeckoSpotPriceSource(asset="btc", currency="usd"),
            BinanceSpotPriceSource(asset="btc", currency="usdt"),
            CoinbaseSpotPriceSource(asset="btc", currency="usd"),
            GeminiSpotPriceSource(asset="btc", currency="usd"),
            KrakenSpotPriceSource(asset="btc", currency="usd"),
        ],
    ),
)
```

In the above example, we use the `PriceAggregator` to aggregate the price from multiple sources (automatic API fetches, not sources that require manual entry). The `algorithm` can be `median` or `mean`. The `sources` can be any combination of those found in `src/telliot_feeds/sources/price/spot/` directory or you can add your own, of course.

You're limited by what asset and currency pairs are supported by the underlying APIs (data providers). For example, if you want to add `BTC/JPY`, you might use the `CoinGeckoSpotPriceSource` and `BinanceSpotPriceSource` (which support `BTC/JPY`), but not the `CoinbaseSpotPriceSource` (which does **not** support `BTC/JPY`).&#x20;

{% hint style="warning" %}
You will need to check the documentation of the underlying APIs for which pairs they support or how to parse their values correctly.
{% endhint %}

3\. Add feed to `CATALOG_FEEDS` constant in `src/telliot_feeds/feeds/__init__.py`:

```python
from telliot_feeds.feeds.btctest_usd_feed import btctest_usd_median_feed

CATALOG_FEEDS = {
    ...
    "btctest-usd-spot": btctest_usd_median_feed,
}
```

4. Add currency/asset to supported lists in `src/telliot_feeds/queries/price/spot_price.py`. For example, for adding `BTCTEST/USD`:

```python
CURRENCIES = ["usd", "jpy", "eth", "btc"]
SPOT_PRICE_PAIRS = [
    ...
    "BTCTEST/USD",
]
```

4. Test your new feed in `tests/feeds/`. For example, once you've created a data feed for an `BTCTEST/USD` spot price using an aggregate of a few price sources, create file `tests/feeds/test_btctest_usd_feed.py`:

```python
import statistics

import pytest

from telliot_feeds.feeds.btctest_usd_feed import btctest_usd_median_feed


@pytest.mark.asyncio
async def test_btctest_usd_median_feed(caplog):
    """Retrieve median BTC/USD price."""
    v, _ = await btctest_usd_median_feed.source.fetch_new_datapoint()

    assert v is not None
    assert v > 0
    assert (
        "sources used in aggregate: 4" in caplog.text.lower() or "sources used in aggregate: 5" in caplog.text.lower()
    )
    print(f"BTC/USD Price: {v}")

    # Get list of data sources from sources dict
    source_prices = [source.latest[0] for source in btctest_usd_median_feed.source.sources if source.latest[0]]

    # Make sure error is less than decimal tolerance
    assert (v - statistics.median(source_prices)) < 10**-6
```

5. Create a pull request to merge your changes into the `main` branch [here](https://github.com/fetchoracle/telliot-feeds/compare).

{% hint style="warning" %}
It's recommend to alway share with the community the sources you're using.

This provides alignment on what the current sources are being used as truth for monitoring.

Submitting the feed or edits *first* to Fetch's [Github](https://github.com/fetchoracle/telliot-feeds/compare) is also recommended.\
This way everyone can update accordingly and keep the network safe and you won't risk being disputed when submitting new or edited data to Mainnet.
{% endhint %}

## Using pulseX as source

{% hint style="success" %}
There's a V1 and V2 versions for pulseX source in /source/spot/price.

Make sure to use the one where your token address, for the feed you're creating, is available.

to import from `pulsex_subgraph` or `pulsex_subgraph_v2` sources, just use:

```python
PulseXSubgraphSource
```

```python
PulseXSubgraphv2Source
```

{% endhint %}

Adding pulseX v1 as a source example:

```
sources=[PulseXSubgraphSource(asset="btc", currency="usd"),
```

&#x20;import the function:

```
from telliot_feeds.sources.price.spot.pulsex_subgraph import PulseXSubgraphSource
```

in the feed file, like this:

```python
from telliot_feeds.datafeed import DataFeed
from telliot_feeds.queries.price.spot_price import SpotPrice
from telliot_feeds.sources.price.spot.binance import BinanceSpotPriceSource
from telliot_feeds.sources.price.spot.coingecko import CoinGeckoSpotPriceSource
from telliot_feeds.sources.price_aggregator import PriceAggregator
from telliot_feeds.sources.price.spot.pulsex_subgraph import PulseXSubgraphSource

btctest_usd_median_feed = DataFeed(
    query=SpotPrice(asset="BTCTEST", currency="USD"),
    source=PriceAggregator(
        asset="btctest",
        currency="usd",
        algorithm="median",
        sources=[
            CoinGeckoSpotPriceSource(asset="btc", currency="usd"),
            BinanceSpotPriceSource(asset="btc", currency="usdt"),
            PulseXSubgraphSource(asset="btc", currency="usd"),
        ],
    ),
)
```

In the example, we're using Coingecko, Binance and PulseX to get the price for BTC now.

After that, search the token address in pulseX v1 website (to confirm it is available) and add support for it in Telliot inside this file:

`~telliot-feeds/src/telliot_feeds/sources/price/spot/pulsex_subgraph.py`

```
"wbtc": "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599", #wbtc test
```

like this:

````python
```python
pulsex_subgraph_supporten_tokens = {
#mainnet tokens
    "wpls": "0xa1077a294dde1b09bb078844df40758a5d0f9a27",
    "dai": "0xefd766ccb38eaf1dfd701853bfce31359239f305",
    "usdc": "0x15d38573d2feeb82e7ad5187ab8c1d52810b1f07",
    "plsx": "0x95b303987a60c71504d99aa1b13b4da07b0790ab",
    "fetch": "0xe39B70c9978E4232140d148Ad3C0b08f4A42220D",
    "hex": "0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39",
    "wbtc": "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599", #wbtc test example
    "inc": "0x2fa878ab3f87cc1c9737fc071108f904c0b0c95d",
    "loan": "0x9159f1d2a9f51998fc9ab03fbd8f265ab14a1b3b",
#Testnet Tokens
    "t*dai": "0x826e4e896cc2f5b371cd7bb0bd929db3e3db67c0",
    "t*usdc": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
    "t*plsx": "0x8a810ea8b121d08342e9e7696f4a9915cbe494b7",
    "t*fetch": "0xC0573e2Fc47B26fb05097a553BBfcf0166bada0A",
    "t*wpls": "0x70499adebb11efd915e3b69e700c331778628707",
    "t*hex": "0x2b591e99afE9f32eAA6214f7B7629768c40Eeb39",
    "t*inc": "0x6eFAfcb715F385c71d8AF763E8478FeEA6faDF63",
    "t*loan": "0x2720F69787cE6ba408fB6e2282d7640E805DF367",
}
```
````

If you want to create a <mark style="color:green;">Testnet token feed</mark> (using the testnet RPC) set the token key to start with `t*` when fetching the source. This will tell the program to use Testnet RPC to fetch the price.

If the token is for <mark style="color:green;">Mainnet</mark>, just set it under `#mainnet tokens` . The program will use the Mainnet RPC for the token keys not starting with `t*` .

Now, if we report with `btctest-usd-spot` it should use the sources we created, including pulseX v1 for this example.

To use pulseX v2, follow the same process but pay attention to the name of the sources.

{% hint style="warning" %}
It's recommend to alway share with the community the sources you're using.

This provides alignment on what the current sources are being used as truth for monitoring.

Submitting the feed or edits *first* to Fetch's [Github](https://github.com/fetchoracle/telliot-feeds/compare) is also recommended.\
This way everyone can update accordingly and keep the network safe and you won't risk being disputed when submitting new or edited data to Mainnet.
{% endhint %}

## Dex Screener API

We can use the Dex Screener API source to fetch prices from specific pools the API supports.

Check the basic [steps](#steps) to add a new feed.

Check the current supported pools and chains inside the `telliot_feeds/sources/price/spot/dexscreener_api.py` file.

If the pool or chain you want is not listed, add it, following the same pattern as the current ones.

Double check pool addresses match the asset you desire.

```
dexscreener_supported_pools = {

#pulsechain exchanges:

"9inch":{
    "fetch/usdl": "0xf3dA9A1FF38c6D774e6aA583302A5aB7646b7025",
},
"9mm":{
    "fetch/wpls": "0x547998b2119dB28a62Ff91FDD64032f6176e9060",
},
"pulsex":{
    "fetch/wpls": "0xDFB503E2da6D58eFFfB1710AaDf7A97f21EA76ad",
},

#BASE exchanges:

"aerodrome":{
    "aero/usdc": "0x6cDcb1C4A4D1C3C6d054b27AC5B77e89eAFb971d",
},

}

dexscreener_supported_chains = {
    "369": "pulsechain",
    "8453": "base",

}
MAINNET_API_URL = "https://api.dexscreener.com"
```

Add the source to the feed you're creating or editing in the file:

```
from telliot_feeds.sources.price.spot.dexscreener_api import DexScreenerApiSource
```

Add the *chain, pool, asset and currency*. For example, for PulseChain mainnet, in 9inch exchange, FETCH/USDL pool.

```
DexScreenerApiSource(asset="369,9inch,fetch", currency="usdl"),
```

The API gets the *price in USD* from the pool.

Test your feed in Testnet to make sure it works as expected.

{% hint style="warning" %}
It's recommend to alway share with the community the sources you're using.

This provides alignment on what the current sources are being used as truth for monitoring.

Submitting the feed or edits *first* to Fetch's [Github](https://github.com/fetchoracle/telliot-feeds/compare) is also recommended.\
This way everyone can update accordingly and keep the network safe and you won't risk being disputed when submitting new or edited data to Mainnet.
{% endhint %}

## 9inch V3 RPC source

This source works only with V3 pools (forks of PancakeSwap, like 9inch).\
Using stable coin pools we can get an asset USD price, like FETCH/USDL, for example.

Check the basic [steps](#steps) to add a new feed.

Currently the source works for FETCH/USDL pool, but you want to use it, copy the file and change the name of the source to match your requirement.\
You can also upgrade the file to accept multiple pools and submit it for further review to be included in the [main](https://github.com/fetchoracle/telliot-feeds/compare) repo.

Here's how to copy the file and use it with a different pool

Copy and rename the file in `telliot_feeds/sources/price/spot/nineinch_v3_rpc.py`&#x20;

Edit the pool in this line (fetch/usd in example), which will be the pool to fetch the assets for:

{% code overflow="wrap" %}

```
self.pair_address = Web3.toChecksumAddress("0xf3dA9A1FF38c6D774e6aA583302A5aB7646b7025")
```

{% endcode %}

Add support for the source in your feed:

```
from telliot_feeds.sources.price.spot.nineinch_v3_rpc import NineInchV3Source
```

```
NineInchV3Source(asset="fetch", currency="usdl"),
```

Try to submit a test report to check on data in Testnet.&#x20;

This is important because you need to confirm the order of the assets. By default the source tries to match the 'asset' and 'currency' order you set in the Feed file.

So, even if the pool has the order inverted, like, usdl/fetch, setting asset as 'fetch' and currency as 'usdl' will put the assets in order and then calculate their respective values.

Since the pool is paired with a stable coin, the fetched price can be used as a FETCH/USD price. Note this price is a straight balance price from the pool token amounts. It is representative for that pool balance amounts only.

The names for 'asset' and 'currency' must match the names in the pool.\
So, although you're reporting to FETCH/USD query (again, because it's a stable usd pool) the assets in the pool are FETCH and USDL and they match in feed's file 'asset' and 'currency' fields.

{% hint style="warning" %}
It's recommend to alway share with the community the sources you're using.

This provides alignment on what the current sources are being used as truth for monitoring.

Submitting the feed or edits *first* to Fetch's [Github](https://github.com/fetchoracle/telliot-feeds/compare) is also recommended.\
This way everyone can update accordingly and keep the network safe and you won't risk being disputed when submitting new or edited data to Mainnet.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.fetchoracle.com/reporting-data/add-support-for-a-new-spot-price.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
