# Welcome to Fetch

Your guide to using Fetch Oracle.

### Getting Started

Fetch is an immutable decentralized oracle protocol that incentivizes an open, permissionless network of data reporting and data validation.

It's a system designed to ensure that data can be provided by **anyone** and checked by *everyone*.

This documentation will guide you through everything you need to know, from the basics of how Fetch Oracle improves blockchain networks to insights into the functions of the ecosystem and information for anyone looking to work under the hood.

Let's dive in.

<div align="center"><figure><img src="https://2715759442-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuaWlV2rnUpdykVKTSfXx%2Fuploads%2FvZUPcIRTRgm9OyltIZze%2FFetch%20Oracle%20Logo%20FINAL.jpg?alt=media&amp;token=e74fb396-f611-40ce-8f6d-1417933e6872" alt=""><figcaption></figcaption></figure></div>

### Fetch Oracle Explained (in 3-Minutes)

{% hint style="success" %}
**Don't miss this!**  Watch this easy-to-follow animated Fetch explainer:
{% endhint %}

{% embed url="<https://www.youtube.com/watch?v=dt04rfCARMI>" %}

{% hint style="info" %}
**Quick Links**

* [Watch the Explainer](https://youtu.be/6mm8ezGVGo8)
* [Read the Whitepaper](https://fetchoracle.com/whitepaper.pdf)
* [Read the Audit Report](https://fetchoracle.com/audit.pdf)
  {% endhint %}

## Get Direct Help

[Ask a question in the Fetch Oracle Telegram](https://t.me/fetchoracle).


# What Problem Does Fetch Solve?

Learn how Fetch Oracle benefits PulseChain users and projects.

### Why Do Blockchains Need Oracles?

A blockchain like PulseChain, at its core, is a type of database. It function as a permanent and immutable ledger that can easily store a full record of every transaction that has ever taken place on the chain.

However, these databases do not inherently have access to real world (off-chain) information. The PulseChain network — for instance — natively knows how much PLS is sitting in your wallet. But the chain doesn't know how much that PLS is worth relative to other assets like the US dollar.

<figure><img src="https://2715759442-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuaWlV2rnUpdykVKTSfXx%2Fuploads%2FAmaj9DcuGM06WsOudLDu%2FFetchDoc4.jpg?alt=media&amp;token=8b572503-b7c3-44a3-8c72-d7faff010c32" alt="" width="563"><figcaption><p>Blockchain networks are isolated from real-world events and information.</p></figcaption></figure>

These blockchains also don't know the weather, the results of sporting events, how many cartons of milk you have in your fridge, or any other information they haven't been explicitly given access to.

This means that, if you want your PulseChain project or smart contract to be able to execute based on real-world pricing or outcomes, you need to find a way to feed off-chain information into the blockchain.

Oracles are the tool that allow you to do just that.&#x20;

<figure><img src="https://2715759442-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuaWlV2rnUpdykVKTSfXx%2Fuploads%2Fkc4LN1l4zbBgZvECW1k9%2FFetchDoc5.jpg?alt=media&amp;token=842d842f-d0d3-4e25-86aa-fbc384a935cd" alt="" width="563"><figcaption><p>Oracles enable blockchains to access off-chain data.</p></figcaption></figure>

{% hint style="success" %}
**Oracles** are pieces of software that connect insulated blockchians to the real world, by electing a feed or set of feeds that can communicate off-chain information to the blockchain.
{% endhint %}

But which feeds can you trust?&#x20;

How does a network stay decentralized if it relies on centralized information?&#x20;

And how do you stop bad actors from manipulating the data they enter to their own advantage?

Addressing these challenges requires thinking outside the box... it requires Fetch Oracle.

### Introducing Fetch Oracle

Fetch Oracle is built for any type of data, and the protocol's decentralized network of [reporters](/reporting-data/requirements) supports everything from your basic spot prices, to more sophisticated pricing specs (TWAP/VWAP), Snapshot Vote Results, and just about any custom data needs you have.&#x20;

Fetch Oracle incentivizes an open and permissionless network of data reporting and data validation. It's a system that ensures that data can be provided by anyone and checked by everyone.

If your data can be verified, Fetch Oracle can [bring it on-chain](https://testnet.fetchoracle.com/#/reporter-logs) without compromising your decentralization.

{% hint style="success" %}
Fetch Oracle is an **immutable** and **decentralized** protocol that incentivizes the open and permissionless sharing of data while prioritizing the accuracy of reported information.
{% endhint %}


# What Can You Do With Fetch?

Discover the different ways you can use Fetch Oracle.

### The Fetch Oracle Ecosystem

Fetch Oracle works by aligning the interests of data reporters, data consumers, and FETCH token holders.&#x20;

Virtually anyone can deposit a stake and report data.  At the same time, anyone can pay a dispute fee to challenge any piece of data they believe to be inaccurate.&#x20;

The entire network of users then vote to determine the outcome of the dispute. If the data reporter loses the dispute, the reporter's stake goes to the disputing party.

In this system, users are financially incentivized to report accurate information and dispute inaccurate reports. This allows the ecosystem to remain decentralized, since no single user has the final say. Rather, a weighted voting process prevents incorrect data from corrupting the integrity of the network.

### Types of Users

The Fetch Oracle ecosystem is made up of multiple types of users:

**Reporters:** Anyone with a stake in the network has the ability to manually or automatically provide up-to-date information, allowing them to earn both timed-based rewards and the [tips](/getting-data/tipping) provided by users who are seeking accurate data.

{% hint style="success" %}
Anyone can become a **reporter** as a way to earn yield, both in the form of time-based rewards and tips.
{% endhint %}

**Data Seekers:** In this system, users are able to leverage Fetch Oracle as a way to receive information. These users have the ability to tip for information they're seeking as a way to incentivize reporters to provide timely and accurate information.

{% hint style="success" %}
Someone may become a **data seeker** because they want their project or smart contract to be able to access a piece of real-world information without having to undergo the hassle of building their own solution.
{% endhint %}

Through Fetch Oracle's user incentive structure, these two types of users work together to create a system where everyone wins and mutually-beneficial outcomes are reached.

<figure><img src="https://2715759442-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuaWlV2rnUpdykVKTSfXx%2Fuploads%2Fo9puizIGY5MibLF5qkuW%2FFetch%20Ecosystem.png?alt=media&amp;token=7372542e-f18c-46c7-943c-fa4738913320" alt=""><figcaption><p>The Fetch Oracle Ecosystem</p></figcaption></figure>

### Using Fetch Oracle

There are four core actions a user can take in the Fetch Oracle ecosystem:

1. [**Staking**](/the-basics/staking)**:**  Anyone can earn yield by staking [FETCH tokens](/the-basics/the-fetch-token).
2. [**Reporting**](/reporting-data/how-to-report-data)**:** The key way to use Fetch Oracle is to provide information. As a reporter, you'll receive time-based rewards and [tips](/getting-data/tipping) for providing live and accurate data.
3. [**Disputing**](/votes-and-disputes/disputing)**:** Everyone has the option to dispute information they believe is inaccurate. This triggers a voting process, in which the network has to reach a consensus on whether or not a piece of submitted information is correct.
4. [**Voting**](/votes-and-disputes/voting)**:** Both stakers and reporters are tasked with taking part in votes in order to earn their full rewards. This process helps ensure the integrity of Fetch Oracle, as incorrectly-submitted information will be shot down by system participants.


# The FETCH Token

Find everything you need to know about FETCH.

Fetch Oracle has its own native PRC-20 token known as the **FETCH** token.&#x20;

FETCH plays a key role in the Fetch Oracle ecosystem, as the token is used as an incentive to financially reward users who:

* [Stake](/the-basics/staking) their existing FETCH tokens.
* [Report ](/reporting-data/how-to-report-data)accurate information.
* [Dispute](/votes-and-disputes/disputing) incorrect information.

The FETCH token was built and deployed on immutable code, with an initial supply of 5 billion tokens followed by a fixed 5% annual inflation rate.

In order to maintain this inflation rate, the number of tokens added to the total supply is increased slightly each year.&#x20;

This inflation is distributed to active participants in the network:

* **60% is allocated to data reporters** who provide accurate data.
* **40% is distributed to all stakers**. Since all reporters must stake FETCH to participate, they also receive a share of this allocation.

This dual incentive structure ensures that reporters benefit from both submitting data and securing the protocol through staking.

The exact release schedule can be viewed on line 30 of the [FETCH token smart contract](https://scan.v4.testnet.pulsechain.com/#/address/0xC0573e2Fc47B26fb05097a553BBfcf0166bada0A?tab=contract).


# Staking

Learn how to earn easy yield with Fetch Oracle.

### Fetch Staking Explained (in 3-Minutes)

Users of Fetch Oracle can earn yield by staking FETCH tokens.&#x20;

Staking is an incentive system that ensures the integrity of the network and financially rewards active contributors who are tasked with participating in voting rounds.

{% hint style="success" %}
**Ready for a shortcut?** Check out this animated guide to staking:
{% endhint %}

{% embed url="<https://www.youtube.com/watch?v=UlcBNAj7J2I>" %}

### What Are the Rewards for Staking?

As a reward for staking, you'll earn FETCH tokens — giving you the opportunity to earn yield with very little effort.&#x20;

Your staking rewards are accrued as soon as you start staking, and you’ll keep earning rewards as long as you keep participating in voting rounds.&#x20;

### What Are the Requirements for Staking?

There is no minimum staking amount. However, there is a 7 day wait period required for unstaking FETCH. Therefore, if you stake and then unstake FETCH, you will need to wait 7 days before being able to withdraw the tokens from the contract back to your wallet.

{% hint style="success" %}
As a staker, it's crucial that you actively participate in the voting process for disputes. &#x20;

Doing so allows you to reach your **full earning potential** while helping maintain Fetch's status as the go-to oracle for accurate and timely decentralized information.&#x20;
{% endhint %}

{% hint style="warning" %}
Note that claiming staking rewards or doing any action that does it (like staking, un-staking) during a vote period and *BEFORE* casting your vote in all current open disputes will make you forfeit extra possible rewards.

Make sure to cast your votes before doing so.
{% endhint %}

You can easily stake, unstake, and withdraw FETCH through the [Fetch Dashboard](https://testnet.fetchoracle.com/#/staking) or, alternatively through Telliot CLI.

**Adding to Your Stake and Compounding Rewards**

After your initial stake, you can add additional FETCH tokens to your existing stake in **any amount, with no minimum or maximum limit**. This flexibility allows you to compound your staking rewards by reinvesting them, enhancing your earning potential over time.

Each additional stake is **subject to its own 7-day unstaking period**, meaning you will need to wait 7 days from the time of each deposit before you can withdraw that specific portion of your stake.

{% hint style="info" %}
Everytime tokens in locked balance are moved, by unstaking or staking/re-staking, the 7 days reset!

Be mindful of that and only unstake the amount you actually won't need for the next 7 days and when you are sure you won't need to stake any more tokens during the unstake period.&#x20;

Also, tokens you stake while having tokens in 'locked balance' are deducted from 'locked balance' prior to your actual wallet balance.
{% endhint %}


# Contracts Overview

An overview of the different contracts that work together to create Fetch Oracle.

The Fetch contracts are modular, each serving their own functions. Together, they comprise the core functionality of the Fetch Oracle system.

### Oracle <a href="#oracle" id="oracle"></a>

The **Oracle** contract handles staking, reporting, and reading data. Accounts stake FETCH to the Oracle to become data reporters. Users then read data feeds from this contract.

This contract also handles slashing reporter stakes and removing data when called by the Governance contract.

### AutoPay <a href="#autopay" id="autopay"></a>

The **AutoPay** contract handles payments to reporters for submitting data. Users can set up and fund a schedule for reporting rewards (tips) using this contract, or just add a one time tip.

### Governance

The **Governance** contract handles creating, voting on, and executing disputes on the Oracle contract.

After a dispute is resolved, this contract sends the dispute fee and slashed stake to the appropriate parties.

### Token

The **Token** contract is tasked with handling the functionality of the FETCH token and also handles minting time-based rewards to the Oracle contract on PulseChain.


# Contract Addresses

View Fetch Oracle's contract addresses.

{% hint style="info" %}
&#x20;For upgradable contracts, you need to make calls via the Proxy address.
{% endhint %}

## PulseChain **Mainnet**

For details on each contract copy and paste the desired contract address below into the search bar of the [**PulseChain Mainnet Block Explorer**](https://scan.pulsechain.com/)**.**

**Token**

* FETCH:[ ](https://scan.v4.testnet.pulsechain.com/#/address/0xe5284f722a509659ec70aa236BA08E10B263bCB2)`0xe39B70c9978E4232140d148Ad3C0b08f4A42220D`

**Oracle**

* &#x20;Proxy:`0xCe9DEa26eB6bEaEc73CFf3BACdF3F9e42BB89951`

**Governace**

* Proxy: `0xC0da79edcb7b23a213003BC75f431EbBba624604`

**AutoPay**

* Proxy: `0x828C91405bB7d66949Ee24431625eb57fbe591f4`&#x20;

## PulseChain **Testnet (V4)**

**Token**

* [FETCH](https://scan.v4.testnet.pulsechain.com/#/address/0xC0573e2Fc47B26fb05097a553BBfcf0166bada0A?tab=contract):[ ](https://scan.v4.testnet.pulsechain.com/#/address/0xe5284f722a509659ec70aa236BA08E10B263bCB2)`0xC0573e2Fc47B26fb05097a553BBfcf0166bada0A`

**Oracle**

* [Proxy](https://scan.v4.testnet.pulsechain.com/#/address/0xe5284f722a509659ec70aa236BA08E10B263bCB2): `0xe5284f722a509659ec70aa236BA08E10B263bCB2`&#x20;

**Governace**

* [Proxy](https://scan.v4.testnet.pulsechain.com/#/address/0x0E0a138BF9B4C222Fdab75CC928EF8755DE79B06): `0x0E0a138BF9B4C222Fdab75CC928EF8755DE79B06`

**AutoPay**

* [Proxy](https://scan.v4.testnet.pulsechain.com/#/address/0xa2B568c4C101522DB20C4B2BAa2E6eD55b9Df6DF): `0xa2B568c4C101522DB20C4B2BAa2E6eD55b9Df6DF`


# Contributing

This page describes how to setup a local environment to contribute updates to Tellliot or DVM.

## Development Environment Setup

*These instructions assume that a working Python interpreter (version >=3.9 & <3.10) is already installed on the system.*

Clone telliot repositories to a local working directory:

```
git clone https://github.com/fetchoracle/telliot-feeds.git
```

Change directories:

```
cd telliot-feeds
```

Create and activate a [virtual environment](https://docs.python.org/3/library/venv.html). In this example, the virtual environment is located in a subfolder called `tenv`:

On Mac or Linux run

```bash
python3.9 -m venv tenv
source tenv/bin/activate
```

On Windows run

```bash
py3.9 -m venv tenv
tenv\Scripts\activate
```

Install the project using using an [editable installation](https://pip.pypa.io/en/stable/cli/pip_install/).

```bash
pip install -e .
pip install -r requirements.txt 
```

Making Contributions

Once your dev environment is set up, make desired changes, create new tests for those changes, and conform to the style & typing format of the project. To do so, in the project home directory:

Run all unit tests:

```
pytest
```

Check code typing:

```
tox -e typing
```

Check style (you may need run this step several times):

```
tox -e style
```

Once all those pass, you're ready to make a pull request to the project's main branch. For example you might want to [add support for reporting a new spot price](/reporting-data/add-support-for-a-new-spot-price).


# Audits

The Fetch Oracle protocol on PulseChain is an enhanced fork of the Tellor protocol on Ethereum, and inherits all risks of that protocol.

Fetch Oracle has been professionally reviewed and audited by leading international blockchain security firm, Halborn. The latest report is publicly available for you to [read and download here](https://www.fetchoracle.com/audit.pdf).

<figure><img src="https://2715759442-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuaWlV2rnUpdykVKTSfXx%2Fuploads%2Fy1cCZXHXqLrDblScmlZR%2FFetch%20Oracle%20Audit.png?alt=media&amp;token=251e5007-c7cc-483c-804a-12c2da919b27" alt="" width="375"><figcaption></figcaption></figure>

We also strongly recommend you review the Tellor audits and performance dashboard by Certik [here](https://skynet.certik.com/projects/tellor).


# How to Report Data

Everything you need to know about submitting informaiton.

### What Is Reporting?

Granting live, decentralized access to information is the principal purpose of Fetch Oracle. This is made possible thanks to a global network of users known as reporters — who submit information to the network.\
\
Virtually *anyone* from anywhere in the world can easily learn how to be a Fetch Oracle data reporter and begin earning yield by submitting data through Fetch Oracle.&#x20;

As a reporter, you’ll earn yield in multiple ways:

* You’ll earn **time-based rewards** for using the system.
* You can also earn [**tips**](/getting-data/tipping) from data seekers, in exchange for providing fast and accurate live information.
* In the event that someone files a dispute against you that the community decides was incorrect, you’ll also be **awarded their dispute fee**.

There are two ways that you can report information:

* **Automatically**, by using a command line tool called Telliot — which you can learn more about by visiting the next section: [Automatic Reporting With Telliot](/reporting-data/requirements).
* You also have the option to report **manually**, which you easily can do by entering relevant information into the [Fetch Dashboard](https://testnet.fetchoracle.com/#/submit-value/spotPrice).

{% hint style="success" %}
Want to learn **how to report manually** through the Fetch Oracle Dapp? Watch this short animated video!
{% endhint %}

{% embed url="<https://www.youtube.com/watch?v=0APpIWx38vc>" %}

### Setting Up Automatic Reporting With Telliot

While the most beginner-friendly way to report information is to do so manually through the [Fetch Dashboard](https://testnet.fetchoracle.com/#/submit-value/spotPrice), users also have the option to consistently and automatically report information by using an open source command line tool known as Telliot.\
\
The following set of pages in this section detail how to install, configure, run, and maintain your own reporter with Telliot.


# Requirements

Understand the requirements for reporting data.

### What Are the Requirements for Reporting?

To report data, you'll need to have a stake in the Fetch Oracle network. This ensures that you're incentivised to provide accurate information and are ready to begin earning rewards.

Before we dive into setting up automatic reporting with Telliot, let's break down Fetch's reporting requirements.

### How Much FETCH Must You Stake?

To ensure that the Fetch Oracle data is always secured by a minimum amount, the `stakeAmount` is a function of the price of FETCH, the stake amount dollar target, and the minimum stake amount.

This can be understood as:

`stakeAmount = maxUSD(stakeAmountDollarTarget, minStakeAmount)`

For PulseChain's mainnet, the `stakeAmount` is determined as follows:

`stakeAmount = maxUSD($500, 500,000 FETCH)`

{% hint style="success" %}
When the price of FETCH is **greater than $0.001 (launch price)**, the minimum staking requirement is always **500,000 FETCH**.
{% endhint %}

{% hint style="success" %}
When the price of FETCH is **less than $0.001 (launch price)**, the minimum staking requirement is **$500 USD worth of FETCH**.
{% endhint %}

The stake amount only changes when someone calls the function `updateStakeAmount` in the  `FetchFlex` contract. This can be called by *anyone*, and is dependent on the latest 12+ hour old reported price of FETCH.&#x20;

In the [Fetch Dashboard](https://testnet.fetchoracle.com/#/update-minimum-stake), the `updateStakeAmount` can easily be called as required.

To participate in Fetch Oracle, reporters must stake FETCH tokens. This ensures security and prevents malicious activity. As a result, all reporters are also stakers, meaning they earn rewards from both parts of the inflation allocation:

* **60%** of inflation is distributed to active reporters who provide accurate data.
* **40%** of inflation is given to all stakers, including reporters.

This dual reward system means that reporters not only earn for submitting data but also benefit from the broader staking incentives.

### Understanding the Reporter Lock Period

Once data is submitted to the network by a reporter, the reporter is then locked from submitting again for a time period known as the `reporterLock` — which is usually 12 hours divided by the number of full stakes.&#x20;

Therefore, the amount of times a reporter can submit data to Fetch Oracle is determined by the following equation:

```
reporter_lock = 12 hours / number_of_stakes
```

{% hint style="info" %}
As an example: if the minimum stake amount is 10 FETCH and you have 120 FETCH staked, you can report every hour. But if that minimum amount were updated to 20 FETCH, you would only be able to report every two hours.
{% endhint %}

*


# (Optional) Using Cloud Hosting

While you're free to host your reporter on your own, cloud hosting makes it easy to have 24/7 uptime.

### Step 1: Sign up for Digital Ocean <a href="#docs-internal-guid-38df86cd-7fff-314c-c8c1-fdcb9386a5a4" id="docs-internal-guid-38df86cd-7fff-314c-c8c1-fdcb9386a5a4"></a>

The easiest and most reliable way to run your reporter is to use a service like Digital Ocean to host your reporters for you.

Digital Ocean is an incredibly affordable and user friendly-option, and new users may be eligible for a 2-month free trial.

Plans start as low as $4 USD per month, which is enough to allow you to run multiple Fetch reporters.

While we’ve kept things simple by using Digital Ocean for this guide, you can use whichever solution or self-hosted option you choose.

### Step 2: Create Your Droplet

On Digital Ocean, we can set up a virtual machine known as a “Droplet”. This is essentially a remote device that will run the Telliot code for your reporter.

1. On the dashboard, select ‘**deploy a virtual machine**’ to set up our Droplet.

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXflX6aFhgyZNCF8YynAr530uzFBeH3bd7WnQlcSF1T5gew_MGeskZ23rSEc1bwsLrFPrNcEA11hwk3e8J7W5Rb80t3Ss4qvFiCuypxUEJSF9AzM680pRmKj7y9FFwZGNfjj5XZ1KQ?key=5CcRo7jM0cpYSAYqVD4KefE3" alt=""><figcaption></figcaption></figure>

2. Now, select the region that’s closest to you in order to maximize your connection speed. Leave the datacenter option as **default**.

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdaoYZxgONEHiwB3S8kraQdywuLI_dJA15GNbt8ooGzzQ0_Kx2YIu6Do1QTLsBHcOTcd6viC97Z0Ov9zQQM-CJ-8ar2xLDHCwdRnPslm86Vqg33jeld555rrMN8yXjfJKoSScleTg?key=5CcRo7jM0cpYSAYqVD4KefE3" alt=""><figcaption></figcaption></figure>

3. Make sure to select either **Ubuntu 22.04 (LTS)** or **24.04. (LTS)** for the installation.

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXe0aWxU5OH5GlCX8aXErUMQX2GzKviTfnLxqjZX3XWQNxI5TrehdjGoVyOsARZH3K4N4fFkfxmd8GQbxJlQ1RWpzgVj_-nq-D9-laGpVubr0ZFfGsTlat8kiqyx5_EjMUJd_Atj?key=5CcRo7jM0cpYSAYqVD4KefE3" alt=""><figcaption></figcaption></figure>

4. Choose your Droplet size

Running a reporter isn’t very intensive. At the lowest tier (which is currently the $4 USD per month, regular VM plan) you can run 4 reporters at the same time without any issues.

Feel free to select the best option according to the amount of reporters you’d like to run.&#x20;

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcgsRQzxjm_3zmpGTqN6Ognj3BkCFTKPZWG0kOhuvVZ4NdYnXKzuu3wHXOUFsgF14KovUmu8BFqUcTlFp0mhrZwxc2UCEFe5JEIYIRw72pH3ZmP9t11iEIE-WL5WbuM7sZB8rSiMg?key=5CcRo7jM0cpYSAYqVD4KefE3" alt=""><figcaption><p>Here we’re selecting the $7 per month Premium AMD CPU option.</p></figcaption></figure>

5. Set Your Password&#x20;

Select the ‘**password**’ option and create a unique, strong password according to the requirements. This is the password you are going to use to access your Droplet from other devices.

{% hint style="danger" %}
Make sure to store your password, preferably offline, somewhere safe. You will not receive any emails containing the Droplet's details or password!
{% endhint %}

6. Now, it's just a matter of renaming your Hostname (optional) and double checking you are creating only one droplet (under ‘Quantity’).&#x20;

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfAl3Fuy4kfzJJnpxSwCcu5HGWNhJSFm-fOFw7II4_OpW-acWFnjAxbO964RJbkZGNv7tbVezwmPhWH5EMnf_qN2fF6vQMcZZja-dxH3s6HOcW9UAP0BfHEEmH7IlseaZcGjGCK?key=5CcRo7jM0cpYSAYqVD4KefE3" alt=""><figcaption></figcaption></figure>

After you’re done with your final checks, click **Create Droplet** and wait for it to be created.


# Installing Telliot

How to install the Reporter (Telliot) and a Disputable Values Monitor (DVM) .

{% hint style="info" %}
If you experience ANY issues during the installation and setup please do not hesitate to reach out via the [Fetch Telegram Support](https://t.me/fetchoracle) group!
{% endhint %}

## Prerequisites:

* Some `tPLS` (if you're testing it on <mark style="color:green;">Testnet</mark>) for paying gas fees. If you need `tPLS,` you can obtain some via the [PulseChain Faucet](https://faucet.v4.testnet.pulsechain.com/).
  * If you are reporting to <mark style="color:green;">Mainnet</mark>, you'll need regular PLS.
* A Linux distribution or macOS on your machine, as they are both Unix-based (Ubuntu 22.04 / 24.04 and MAC M1 Ubuntu VM were tested). **Windows is not currently supported.**
* **To install in a mac we recommend using a virtual machine to make sure everything is aligned with this tutorial. Check** [**here**](/reporting-data/installing-telliot/mac-virtual-machine-with-utm) **for quick steps on how to set up one.**
* Running Telliot and a DVM is fairly lightweight and does not require significant computing power. A single core machine with 1 GB RAM should be enough to get started. It's also highly recommended to run this software on a Virtual Machine, fresh cloud server instance from AWS, Digital Ocean, or other providers.

## Install Script

Helper to install telliot and get up and running in no time.

{% hint style="info" %}
Script is supposed to run in linux bash, like, Ubuntu.
{% endhint %}

{% code overflow="wrap" %}

```bash
curl -O https://raw.githubusercontent.com/fetchoracle/telliot-install-script/refs/heads/main/install.sh && chmod +x install.sh && ./install.sh && cd && cd telliot-feeds && source venv/bin/activate
```

{% endcode %}

You can check the full script [here](https://github.com/fetchoracle/telliot-install-script)

### Running the install script

{% hint style="warning" %}
If you are [updating/reinstalling](#upgrade) you need to **remove**/rename the `telliot-feeds` and `telliot` folder that is created in /Home, before running this script.
{% endhint %}

Simply copy and run the full line above in your terminal to clone the repositories and install telliot-feeds, telliot-core and, optionally, disputable-values-monitor.

Follow the on screen instructions carefully and give permission for needed dependencies.

'Mainnet' is the default option to choose for a stable version.

{% hint style="info" %}
During installation you may be asked permission to install python and update the system.
{% endhint %}

<mark style="color:green;">That's it! Everything should be installed and ready to go!</mark>

Check here how to [upgrade](#upgrade) and make sure to edit your desired [endpoints](#configure-endpoints) to use.

### Confirming installation was successful&#x20;

After installing, the command you pasted will try to enter `telliot-feeds` folder and activate the venv environment with\
`source venv/bin/activate` automatically.

Confirm you are in it by checking for (venv) in the cli:

<figure><img src="https://2715759442-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuaWlV2rnUpdykVKTSfXx%2Fuploads%2FQ5pna4Zl8OHW99pR48bF%2Fimage.png?alt=media&amp;token=23a9c7b7-3adf-4aef-b367-f633fae11f7c" alt=""><figcaption><p>(venv) displayed at the beginning of the line and inside telliot-feeds folder</p></figcaption></figure>

{% hint style="danger" %}
Everytime you run Telliot or DVM you need to enter this virtual environment. To enter it, go to `telliot-feeds` folder and run `source venv/bin/activate`. To exit it, run `deactivate`.

Through the command line you can use `cd <name of folder>` to enter a folder and `cd ..` to move one folder up (go back).
{% endhint %}

Now, inside the folder, run `telliot --help`. If you see the help instructions for Telliot, its installation was successful.

<figure><img src="https://2715759442-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuaWlV2rnUpdykVKTSfXx%2Fuploads%2FeOThHzUyNyM32ufa4LPn%2Fimage.png?alt=media&amp;token=f72a182c-109b-4be7-b3fd-96807c28a4d3" alt=""><figcaption><p>Successful Telliot install</p></figcaption></figure>

If you installed DVM, to check it, `cd disputable-values-monitor` from the `telliot-feeds` folder.

Inside DVM folder, run `cli --help`. If you see the help page for the DVM, installation was successful.

<figure><img src="https://2715759442-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuaWlV2rnUpdykVKTSfXx%2Fuploads%2FdtTnQcqXA80Lps2PKcHd%2Fimage.png?alt=media&amp;token=4947a73a-3020-4d06-a2c2-55167b80fe54" alt=""><figcaption><p>Successful DVM install</p></figcaption></figure>

## Upgrade

Delete `telliot-feeds` and `telliot` folder inside your `Home` directory and just run the install script again to update Telliot. Your accounts will remain saved in the `chained_accounts` folder, in /home, so no need to add them after installation.

If you are a more advanced user and has made changes locally to Telliot, you can upgrade it with regular `git pull` to fetch the latest changes from the branches you're using and install the packages with `pip install -e .`. Repeat this process in `telliot-feeds`, `telliot-core` and `disputable-values-monitor` folders.

To run both versions, you may change the name of `telliot-feeds` and `telliot` folders in /home, although this it not recommended.

{% hint style="info" %}
Make sure to check your `.env` and `.env.example` file after an upgrade if you have made previous changes to it!

There may be new variables to set up in `.env.example`
{% endhint %}

## Configure Endpoints <a href="#configure-endpoints" id="configure-endpoints"></a>

You can check your endpoints config running `telliot config show.`

The default configuration for the endpoints can be found in `~/telliot/endpoints.yaml`:

{% hint style="success" %}
Tip: DVM will monitor **all** chains in this folder. Comment out or remove the ones you don't want it to be listening for new events.

It's recommended to run a single DVM per instance for monitoring on the same chain you are reporting.

If you plan to use DVM or Telliot to monitor/report to different chains, we advise to run each service on different instances for better compatibility.
{% endhint %}

```yaml
type: EndpointList
endpoints:
- type: RPCEndpoint
  chain_id: 943
  network: Pulsechain Testnet
  provider: Pulsechain
  url: https://rpc.v4.testnet.pulsechain.com
  explorer: https://scan.v4.testnet.pulsechain.com/
- type: RPCEndpoint
  chain_id: 369
  network: Pulsechain Mainnet
  provider: Pulsechain
  url: https://rpc.pulsechain.com
  explorer: https://scan.pulsechain.com/
```

Below is an example with PulseChain testnet commented (removed):

```
type: EndpointList
endpoints:
#- type: RPCEndpoint
#  chain_id: 943
#  network: Pulsechain Testnet
#  provider: Pulsechain
#  url: https://rpc.v4.testnet.pulsechain.com
#  explorer: https://scan.v4.testnet.pulsechain.com/
- type: RPCEndpoint
  chain_id: 369
  network: Pulsechain Mainnet
  provider: Pulsechain
  url: https://rpc.pulsechain.com
  explorer: https://scan.pulsechain.com/
```

You can add your RPC endpoints by editing the `endpoints.yaml` file. Here's an example command using the [nano](https://www.nano-editor.org/) text editor to edit the YAML file directly:

```
nano ~/telliot/endpoints.yaml
```


# Adding Accounts

Adding your first account after installing Telliot

## Add Reporting Accounts <a href="#add-reporting-accounts" id="add-reporting-accounts"></a>

The reporter (Telliot) needs to know which accounts (wallet addresses) are available for submitting values to the oracle. Use the command line to add necessary reporting accounts/private keys.

Make sure you're in python's virtual environment `(venv)`:

{% hint style="warning" %}
Everytime you run Telliot or DVM you need to enter this virtual environment. To enter it, go to `telliot-feeds` folder and run `source venv/bin/activate`. To exit it, run `deactivate`.

Through the command line you can use `cd <name of folder>` to enter a folder and `cd ..` to move one folder up (go back).
{% endhint %}

First decide where you want to report: \
**PulseChain Mainnet (369)** or  **PulseChain Testnet (943)**.\
\
To add an account for reporting on **PulseChain Mainnet (369)** run the following:

```
telliot account add myacc yourPrivateKey 369
```

{% hint style="info" %}
Remember to replace `myacc` and `yourPrivateKey` in this example with the private key that holds your FETCH for reporting and an account's name to save it locally.
{% endhint %}

You'll be asked to type a password. The characters are *not visible* while you type. Then you re-type the password to confirm it.

**OPTIONAL**: if you want to add another wallet address (or the same one) to ***another*** ***chain***, for example testnet (943), repeat the process but type 943 at the end.

<figure><img src="https://2715759442-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuaWlV2rnUpdykVKTSfXx%2Fuploads%2Fx7j58CRzDmJWmeD4ffoF%2Fimage.png?alt=media&amp;token=b6b21c4b-eeb2-4ccb-b49c-595892bc463c" alt=""><figcaption><p>Confirm the password twice and check the wallet address and chain ID are correct</p></figcaption></figure>

<mark style="color:green;">Done! Your account should be ready to submit reports!</mark>

{% hint style="info" %}
Remeber: if you want to report to other chains *using the same address* just follow the same process but change the name of the account and chain ID. Below is an example using the same wallet address, but to report to Pulsechain **mainnet**:
{% endhint %}

<figure><img src="https://2715759442-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuaWlV2rnUpdykVKTSfXx%2Fuploads%2F0rWhCqDvbZy3MPssOOEH%2Fimage.png?alt=media&amp;token=749b7981-476b-42d5-8966-77eec62401f1" alt=""><figcaption><p>Account name and chain ID changed. Same private key, same wallet.</p></figcaption></figure>

To check the wallets you have added, run `telliot account find`

<figure><img src="https://2715759442-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuaWlV2rnUpdykVKTSfXx%2Fuploads%2FXui9JJhW4qitwvhpxuGt%2Fimage.png?alt=media&amp;token=a2eaf3a3-bae7-4f50-af1c-cb8e7797d362" alt=""><figcaption></figcaption></figure>

To view other options for managing accounts with Telliot, use the command:

```
telliot account --help
```


# MAC Virtual Machine with UTM

Quick tutorial to set up a Ubuntu virtual machine to run Telliot seamlessly

To ensure compatibility it's recommended to install Ubuntu as a virtual machine on your Mac. Using UTM you can do it in quick easy steps and then continue to follow the tutorials [here](/reporting-data/installing-telliot#install-script).

## Downloading UTM

Head to UTM official [download page](https://mac.getutm.app/) and click the download button on the center of the page. It will download a .dmg file of around \~200mb.

Once downloaded, install it by double clicking on it and following the on screen instructions.

{% hint style="info" %}
There's a paid version in the APP Store which is essentially the same program. You can check more details from UTM on this at the bottom of the page [here](https://mac.getutm.app/#:~:text=What%27s%20the%20difference%20in%20the%20Mac%20App%20Store%20version%3F).

Any version should work fine.
{% endhint %}

## Installing Ubuntu

1. Open UTM and click '`create a new virtual machine`' button in the center of the app.
2. Select '`download pre-built from UTM gallery...`'
3. In the website, scroll down, find the `Ubuntu version 22.+` and click on it. Make sure to use <mark style="color:green;">LTS versions</mark>, as those are the ones stable.
   1. This page contains the login and password together with extra guides and info if needed
4. Now select '`open in UTM`'
   1. When it opens, click 'cancel' to close the 'start' screen at the front and reveal the 'download' option behind it
   2. Click on 'download' to start downloading the VM from the link
5. it will start the download and you can follow the process on the sidebar of UTM
6. Once the download is done, you'll see the ubuntu logo and a play button. click on it
7. Wait \~1m for it to boot and you'll be inside Ubuntu
8. Password and login are `ubuntu`&#x20;
9. Once logged in, continue the [installation](/reporting-data/installing-telliot#install-script) process as usual
   1. It's good to wait a few minutes for system updates, though. You can also manually run `sudo apt update` and `sudo apt-get update` from the terminal to make sure Ubuntu is ready to go.


# Reporting With Telliot

Learn how to automatically report data using the command line tool.

## Reporting a Price <a href="#telliot-feeds-reporting-a-price" id="telliot-feeds-reporting-a-price"></a>

It's really simple to report data with Telliot.

First, make sure you're in python's virtual environment `(venv)`:

{% hint style="warning" %}
Everytime you run Telliot or DVM you need to enter this virtual environment. To enter it, go to `telliot-feeds` folder and run `source venv/bin/activate`. To exit it, run `deactivate`.

Through the command line you can use `cd <name of folder>` to enter a folder and `cd ..` to move one folder up (go back).
{% endhint %}

Now, confirm you have at least the minimum current stake amount of FETCH in your reporter's wallet address and run the command below to report a median spot price for PLS/USD.

<mark style="color:blue;">You can check the current minimum stake amount in</mark> [Fetch Dashboard](https://testnet.fetchoracle.com/#/), <mark style="color:blue;">top left of the page!</mark>

```sh
telliot report -a <yourAccName> -qt pls-usd-spot
```

{% hint style="success" %}
`telliot report` is the base command to submit reports. `-a` is the option where you declare the acc name for the wallet you want to use. `-qt` is the query tag you want to report.
{% endhint %}

After running the above, Telliot will: Display some detailed info about contracts and where it is going to try to report, ask for your acc password, try to stake if you don't have the minimum stake amount and try to submit the report. That's it!

{% hint style="warning" %} <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 for what sources they are using! (Submitting data to Testnet first is a great way to get familiar with Reporting 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 %}

<mark style="color:green;">Congratulations you submitted your first report!</mark> :tada:

Below are the detailed information of what happens in the process:

<figure><img src="https://2715759442-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuaWlV2rnUpdykVKTSfXx%2Fuploads%2FWMETde9bL5ejsnsnhedQ%2Fimage.png?alt=media&amp;token=a5d743df-d5a3-4f47-848f-f56753f69d0b" alt=""><figcaption><p>Detailed info about wallet address and chain it will try to report after confirming password</p></figcaption></figure>

Telliot will automatically calculate the current min stake amount and try to stake it by asking you to confirm your password again to submit a deposit transaction.

After that it will calculate the PLS/USD price using its sources and submit the median price.

<figure><img src="https://2715759442-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuaWlV2rnUpdykVKTSfXx%2Fuploads%2F3V7qXqEzqpDDOXUlVd64%2Fimage.png?alt=media&amp;token=b17dc097-ee0b-42e8-aae8-79c217f60600" alt=""><figcaption><p>If the FETCH price being used has changed, it can calculate the current stake amount for a new stake</p></figcaption></figure>

<figure><img src="https://2715759442-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuaWlV2rnUpdykVKTSfXx%2Fuploads%2FxYWkEESFzHl2GVI7zRND%2Fimage.png?alt=media&amp;token=063fe773-01dc-4740-b933-1e647f68840f" alt=""><figcaption><p>Details about staking and asking for password to confirm the deposit of the min stake amount</p></figcaption></figure>

<figure><img src="https://2715759442-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuaWlV2rnUpdykVKTSfXx%2Fuploads%2F8r6249bxlYAzTN5VHb5r%2Fimage.png?alt=media&amp;token=1d5ac09c-c2cd-4e77-af19-4641db8c1db4" alt=""><figcaption><p>Stake deposited and it will continue to submit the price</p></figcaption></figure>

After staking it calculates the PLS/USD price and submits it on chain. It will keep trying to report again after 7 seconds by default.&#x20;

To stop it, press `ctrl + c`.

It will also display an approximate time for when you'll be able to submit a report again, based on the current min stake amount in the contract and your deposited stake amount.

<figure><img src="https://2715759442-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuaWlV2rnUpdykVKTSfXx%2Fuploads%2FLKP3yt4Ehzx9lBAL2A8C%2Fimage.png?alt=media&amp;token=f3bc7384-c705-4f29-a12e-368d38fa1b2a" alt=""><figcaption><p>It has reported and tried again to report after 7 seconds. It's in 'reporter lock' period and the time left for a possible new report is displayed.</p></figcaption></figure>

{% hint style="info" %}
Remember: It will keep trying to report to the same query tag unless you stop Telliot by pressing `ctrl + c`.
{% endhint %}

## Reporting a Random Number using RNG <a href="#telliot-feeds-reporting-a-price" id="telliot-feeds-reporting-a-price"></a>

{% hint style="warning" %}
This is **an example** demonstrating how Fetch can be used to generate a ‘random’ number, based on the original Tellor RNG example feed.

Before using this example in Mainnet, **where disputes may arise**, proper due diligence is required. The primary goal is to showcase additional potential use cases for Fetch.

We encourage others to build upon this idea, improve it, or create new RNG feeds and data sources. If you would like to contribute, consider submitting a review on [GitHub](https://github.com/tellor-io/telliot-feeds) to enable broader participation in data provision.
{% endhint %}

### Process Overview

1\. **User Input:** The user provides a timestamp.

2\. **Fetching Blocks**: Telliot retrieves the next Bitcoin (BTC) and PulseChain (PLS) blocks based on the given timestamp.

3\. **Random Number Generation**: A random number is generated using data from the retrieved blocks.

4\. **Reporting**: The generated number is encoded and submitted for reporting.

### Detailed steps

To report a random number using Telliot RNG use the query tag `tellor-rng-example`

The process begins by prompting the user to input a timestamp:\
From this timestamp, it will fetch the next BTC and PLS block.

```
Enter timestamp for generating a random number:
1742466660
```

Telliot confirms the generation process:

```
Generating random number from timestamp: 1742466660
Press [ENTER] to confirm.
```

Telliot retrieves the latest BTC block:

```
INFO | telliot_feeds.sources.blockhash_aggregator | Using BTC block number 888619
```

Next, it fetches the corresponding block from PulseChain (chain ID: 369):

```
INFO | telliot_feeds.sources.blockhash_aggregator | Trying to fetch block from chain: 369
INFO | telliot_feeds.sources.blockhash_aggregator | Block api data: {'blockNumber': '22996631'}
INFO | telliot_feeds.sources.blockhash_aggregator | Block received: 22996631
INFO | telliot_feeds.sources.blockhash_aggregator | Using block number 22996631
```

The random number is derived from the two retrieved blocks and stored:

```
INFO    | telliot_feeds.sources.blockhash_aggregator | Stored random number for timestamp 1742466660: 0x1989faad8a133a7ce5da64eddd6679a9dd3ef61f893da049895dc92c0f31663f
DEBUG   | telliot_feeds.reporters.tellor_360 | Current query: {"type":"TellorRNG","timestamp":0}
```

The random number is encoded for reporting:

```
DEBUG   | telliot_feeds.reporters.tellor_360 | Reporter Encoded value: 1989faad8a133a7ce5da64eddd6679a9dd3ef61f893da049895dc92c0f31663f
```

### RNG on Fetch Dashboard

Currently, the Fetch Dashboard *does* not display the query or the generated random number. However, the reported data can be seen in the Discord notifications. Below is an example RNG notification in Discord;

```
Query: {"type":"TellorRNG","timestamp":0}
Price Submitted: 11,551,609,377,654,775,654,021,618,183,836,409,979,244,170,088,532,462,796,800
```


# Reporting Options

Options to report or manage your reporter with Telliot

{% hint style="info" %}
You can check Telliot options running `telliot --help`.&#x20;
{% endhint %}

<figure><img src="https://2715759442-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuaWlV2rnUpdykVKTSfXx%2Fuploads%2FKagy3nV09kmwi6ZagFc9%2Fimage.png?alt=media&amp;token=35f07ab3-0910-45e4-b72f-1f4c067512d0" alt=""><figcaption><p>You can also dive in options, like this: <code>telliot report --help</code> and it will explain more details about 'report' option</p></figcaption></figure>

## Staking and Unstaking

<mark style="color:blue;">We reccomend to quickly do this from Fetch Dashbord's</mark> [Staking section](https://testnet.fetchoracle.com/#/staking-rewards)<mark style="color:blue;">, but Telliot also has built in functions you can use.</mark>

### Staking

Using `telliot stake` you can stake additional tokens to your current stake. Select your account with `-a` and `--amount`, like this:

`telliot stake -a <yourAccName> --amount 600000`

It will ask you to confirm your password and it will deposit the extra amount you typed on top of your current stake amount. For example, if your previous amount was 500,000 and you use `--amount 600000` you'll end up with 1,100,000 tokens deposited.

After staking you get a successful deposit transaction URL and telliot stops.

{% hint style="info" %}
You can also stake using the `-s` option while running the usual `telliot report` command. Notice, though, that this option will only top up the amount you chose according to your current stake amount. If you type `-s 600000` and have 500000 already staked, it will stake an additional 100000 only, topping up 500000 to the 600000 desired.

For this function to work correctly, you need to have the `--password` flag enabled and enter it at least once OR just set the PASSWORD= variable in .env file for automatically unlocking your account when password is needed.
{% endhint %}

{% hint style="warning" %}
**NOTE:** If the reporter account's actual stake is reduced after a dispute, the reporter will attempt to stake the difference in FETCH to return to the original desired stake amount if the `-s` is present.

To avoid this, run it without the `-s` flag. It may stop reporting when there's deduction in stake amount depending on your total stake.
{% endhint %}

### Requesting Withdraw

To start the unstake process we use `telliot request-withdraw` to put the tokens in the 7 days lock period state before actually withdrawing them. Process is similar to staking.

`telliot request-withdraw -a <yourAccName> --amount 200000`

After confirming the password you get a requestStakingWithdraw transaction URL if successful and Telliot stops.

### Withdrawing Locked Balance

<mark style="color:blue;">Remember you can check Fetch Dashboard's</mark> [Staking section](https://testnet.fetchoracle.com/#/staking-rewards) <mark style="color:blue;">for detailed info on the state of your locked balance and withdrawal.</mark>

To use Telliot to withdraw we need `telliot withdraw` and the acc name. After the 7 days have passed, calling this function withdraws ALL the tokens in Locked Balance.&#x20;

{% hint style="danger" %}
Everytime tokens in locked balance are moved, by unstaking or staking/re-staking, the 7 days reset!

Be mindful of that and only unstake the amount you actually won't need for the next 7 days and when you are sure you won't need to stake any more tokens to that reporter during the unstake period.&#x20;

Also, tokens you stake while having tokens in 'locked balance' are deducted from 'locked balance' prior to your actual wallet balance.
{% endhint %}

`telliot withdraw -a <yourAccName>`

If the 7 days are gone since you requested the withdraw, you'll get a transaction URL confirming the withdrawal. Otherwise, you'll get a revert saying the 7 days haven't passed yet.

## Submitting Once

To submit a simple single report, add the `--submit-once` option, like this:

```
telliot report -a <yourAccName> -qt pls-usd-spot --submit-once
```

After one value is submitted to Fetch Oracle, the Telliot process will terminate.

## Reporting in Intervals

To stop trying to report every 7 seconds, we can use the `-wp` option and specify what interval, in seconds, we want Telliot to *try* to submit a report. Here' how:

```
telliot report -a <yourAccName> -qt pls-usd-spot -wp 3600
```

Here, Telliot will submit the first report and then wait 3,600 seconds (1 hour) to try to submit the next one. If you are out of report lock period it will succeed, otherwise, it will try again 3,600 seconds later.

## Stop reporting based on Native token balance

```
telliot report -a <yourAccName> -qt pls-usd-spot -mnb 40000
```

You can use the -mnb option to stop Telliot when it detects your native token balance (PLS in PulseChain) reached the threshold you set.

The example above would have stopped Telliot from submitting when reaching <40,000 PLS balance. If you send more PLS to the account it will resume reporting.

## Reporting When Profitable

Telliot can submit when there's a percentage profit or USD profit from time based rewards and tips.

Using the `-p` option we set 2 parameters: % and USD thresholds. If we don't want to check for profits and just submit we can use `-p YOLO 0` which would report straight away and not check for profits at all.

By default Telliot checks for at least 100% profit above 0 USD. The profit is calculated using the FETCH price of fetch-usd-spot source against the gas cost to submit the transaction.

Example:

`-p 1000 2` would only submit a report if the profit after calculating the gas price is above *1000% or 2 Dollars* (based on the FETCH price at the time of reporting).

If you want to use only percentage profit or only USD, set the un-desired value to something really high, so it never passes the validation and only the desired one is checked, example:

`-p 200 999` would only submit with a 200% profit, since 999 USD will very unlikely ever happen.

{% hint style="info" %}
Check the .env file inside `telliot-feeds` folder.&#x20;

In Testnet, the FETCH price is usually mocked to the launch price of 0.001. If you want to use the actual price from tfetch-usd-spot source in Testnet, remove the 0.001 value of the variable and leave it empty.

This is important for calculating profit and reporting tfetch-usd-spot prices in Testnet.

*In Mainnet, it will use the spot price from fetch-usd-spot for profit calculations.*
{% endhint %}

Here are more examples:

`telliot report -a <yourAccName> -qt pls-usd-spot -p 300 5`

Here we're going to submit a report if the percentage profit is above 300% or $5 dollars. If one of these two conditions are met, it reports.

<figure><img src="https://2715759442-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuaWlV2rnUpdykVKTSfXx%2Fuploads%2FRxiWE7KjEMPrwXthsurJ%2Fimage.png?alt=media&amp;token=0bafa354-25cd-42e6-b05f-0efac5c56c8b" alt=""><figcaption><p>You can see your parameters in the details after confirming password</p></figcaption></figure>

<figure><img src="https://2715759442-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuaWlV2rnUpdykVKTSfXx%2Fuploads%2FSA77Mx0qOnyFg5hSgW3B%2Fimage.png?alt=media&amp;token=e119330a-1c15-4f2b-8e2b-5bf66a9c1385" alt=""><figcaption><p>Profit is less than $5 dollars, but way above 300%, so it submits the report. If -<code>p</code> was <code>200000</code> and <code>5</code> it would not submit, since both parameters would be above the actual profit.</p></figcaption></figure>

#### Enforcing *no profit* checks:

`telliot report -a <yourAccName> -qt pls-usd-spot -p YOLO 0`

<figure><img src="https://2715759442-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuaWlV2rnUpdykVKTSfXx%2Fuploads%2FNK9rJpePSFNZajKRqOPz%2Fimage.png?alt=media&amp;token=e6d1a44d-d8ba-42f8-8f2f-8e15e77a80fb" alt=""><figcaption><p>It will not check for profit and just report. You still receive available time based rewards, though.</p></figcaption></figure>

## Reporting for tips

If you leave the `-qt`  option out of the command, Telliot will try to report only when someone tips for an already existing tag. If the tip value matches your profit settings, it will try to submit. Here you'll receive the TBRs + Tips.&#x20;

Tips can be claimed after 12h of submission. This period is to confirm the data submitted is valid.

```
telliot report -a <yourAccName>
```

## Reporting Random Feeds

To support the ecosystem and have a larger chance of getting time based rewards (by not clashing with another reporter submitting the same `QueryID` as you at the same timestamp) you may want to report to multiple random feeds.

Use the `-rf` option to report to a random feed from the list found in `~/telliot-feeds/src/telliot_feeds/feeds` directory. Open the file `__init__.py` to check and edit the queries.

{% hint style="danger" %}
Always check what you're randomly reporting before starting Telliot, to make sure you're comfortable with the queries in there and their sources!

Only report for feeds you have previously tested and checked within the community what they are considering as truth for data submitted.

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

Look for the line containing RANDOM\_FEEDS and the feeds listed there are the ones you'll be submitting, randomly, when using `-rf`.

Comment out the ones you don't want to report to (by adding a `#` in the start of the line) or copy and paste new ones, following the same pattern of the list, from the CATALOG\_FEEDS below it. Remember to save the file when you're done.

To report, the command line will look like this:

```
telliot report -a <yourAccName> -rf
```

## Conditional Reporting

Telliot can report when some conditions are met, like a percent price change or when a price has become stale.

### Reporting when there's a % change

Enables reporting if there’s a percent change in the query tag selected.

Used with ‘conditional’ option, like this:

```
telliot conditional -a <yourAccName> -qt btc-usd-spot --percent-change 0.1
```

Above, if there’s a 10% change in price reported, it will try to report a new one:

<figure><img src="https://2715759442-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuaWlV2rnUpdykVKTSfXx%2Fuploads%2FWoRJu2MXsTxMW9Vtuezs%2Fimage.png?alt=media&amp;token=d7f2bf67-fd0d-4369-8a2c-4062ffb478af" alt=""><figcaption><p>Didn't report since the price change has not met the threshold of 10%</p></figcaption></figure>

### Reporting when the price is Stale

If the feed is stale by X amount of seconds, it will trigger a report on the query tag selected. By default in the 'conditional' option it will consider a price stale after \~24h of no new reports.

Used with ‘conditional’ option, like this:

```
telliot conditional -a myacc_ts -qt btc-usd-spot -st 6400
```

<figure><img src="https://2715759442-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuaWlV2rnUpdykVKTSfXx%2Fuploads%2FPVYA7HT3xABZ0MKrLzZt%2Fimage.png?alt=media&amp;token=5af6a247-94f8-4291-8d38-3c41a98195df" alt=""><figcaption><p>The last price reported was above the threshold desired of 3600 seconds (1h), so Telliot tried to report</p></figcaption></figure>

## Build Feed Flag (advanced) <a href="#build-feed-flag" id="build-feed-flag"></a>

Use the `build-a-feed` flag (`--build-feed`) to build a DataFeed of a `QueryType` with one or more `QueryParameters`.&#x20;

When reporting, the CLI will list the `QueryTypes` this flag supports. To select a `QueryType`, enter a number from the list provided. Then, enter the corresponding `QueryParameters` for the `QueryType` you have selected.

This way you'll be submitting a manual value to Fetch Oracle. Be mindful of submitting thrustful values, otherwise you may get disputed by others!

```
telliot report -a <yourAccName> --build-feed
```


# Discord Notifications

Trigger notifications for Telliot, for example, when submitting a report or having your stake amount reduced (which may mean you got disputed).

Inside telliot-feeds folder, in the .env file, you can set a Discord Webhook for Telliot to send you notifications about Data submitted and other useful information.

{% hint style="success" %}
If you don't have a Discord webhook, here's Discord's [official tutorial](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks#:~:text=%C2%A0%20Facebook-,Making%20A%20Webhook,-With%20that%20in) on how to get one, following quick easy steps.
{% endhint %}

You just need to paste your discord webhook there and telliot will always try to send you a notification when needed.

You can choose a name (default 'Telliot') or leave the webhook variable empty ("") for no notifications.

More info on how to use notifications can be found inside the `.env.example` file.

{% hint style="info" %}
[DVM](/votes-and-disputes/introduction-to-dvm/installing-dvm#usage-1) has its own Discord notifications, too.
{% endhint %}


# Gas Fees

Telliot has flags you can use to manipulate the Gas values used in the transactions

## Estimating Gas Fees <a href="#fees-estimation" id="fees-estimation"></a>

Run `telliot report --help` (top of the instructions) for the options related to gas.

{% hint style="warning" %}
These values should be expressed in BEATS (GWEI). For example, if you want to use 1500000000 IMPULSE (WEI) as maxPriorityFeePerGas, you need to pass -mf 1.5 BEATS (GWEI).

Gas calculations are complex and should be done carefully.&#x20;

Test it first and do diligent research on how Gas and transaction fees work before running any settings in Mainnet, risking losing PLS by having the transaction revert due to bad configuration.
{% endhint %}

## **Gas Setting Flags:**

### **-gl, --gas-limit INTEGER**

**What it does:** Sets the maximum computational units (gas) the transaction is allowed to use. Think of it as a "fuel tank size" limit for your transaction.

**Purpose:** Acts as a safety measure to prevent a transaction from accidentally consuming huge amounts of gas.

**Example:** -gl 300000 (Allow the transaction to use up to 300,000 gas units).

### **-mf, --max-fee FLOAT**

**What it does:** (EIP-1559 / Type 2 Only) Sets the absolute maximum total fee (base fee + priority fee/tip) you are willing to pay per gas unit, specified in Gwei.

**Purpose:** Your total budget cap per unit of gas. The transaction will never cost more per gas unit than this value.

**Example:** -mf 50.5 (Willing to pay up to 50.5 Gwei total per gas unit).

### **-pf, --priority-fee FLOAT**

**What it does:** (EIP-1559 / Type 2 Only) Sets the specific "tip" (maxPriorityFeePerGas) paid directly to the validator per gas unit, specified in Gwei.

**Purpose:** Incentivizes validators to include your transaction faster, especially during busy times. Using this overrides any automatic tip calculation and the -mpfr cap.

**Example:** -pf 4.5 (Offer a 4.5 Gwei tip per gas unit to the validator).

### **-bf, --base-fee FLOAT**

**What it does:** (EIP-1559 / Type 2 Only) Manually sets the base fee part of the gas cost, specified in Gwei.

**Purpose:** Overrides the current base fee dictated by the network. Make sure you know what you're doing before using this, since it may revert the transaction or not even submit.

**Example:** -bf 40 (Force the transaction to use a base fee of 40 Gwei, ignoring the network's current base fee).

### **-tx, --tx-type TEXT**

**What it does:** Explicitly chooses the transaction format. Use 0 for Legacy or 2 for EIP-1559. (PulseChain uses tx 2)

**Purpose:** Ensures the correct fee parameters.

**Example:** -tx 2 (Submit this transaction using the modern EIP-1559 format).

### **-mpfr, --max-priority-fee-range INTEGER**

**What it does:** (EIP-1559 / Type 2 Only) Sets a maximum limit or ceiling (in Gwei) on the automatically calculated priority fee/tip (-pf). Only used if you don't provide -pf manually. The default is 3 Gwei.

**Purpose:** Acts as a safety cap to prevent paying extremely high tips during automatic calculation, especially during network volatility.

**Example:** -mpfr 5 (Allow the automatic tip calculation to go up to 5 Gwei, but no higher).


# Add support for a new spot price

This page outlines the steps to add support for reporting a new spot price to your Telliot reporter.

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))

## 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 %}


# Tipping

Reward reporters for providing the data you need.

### What Are Tips?

Tipping is a core component of Fetch Oracle’s user-incentive structure. It's a great way to introduce accurate real-world data to your project or smart contract without having to find a way to source the information yourself.

{% hint style="success" %}
Ready to learn more about tipping? **Watch this short animated explainer!**
{% endhint %}

{% embed url="<https://www.youtube.com/watch?v=03-eh6bZdfI>" %}

Using the "**Fund a Feed**" feature, data seekers can offer tips as a way to incentivize users to provide live up-to-date data feeds.

{% hint style="info" %}
Use the [Fetch Dashboard](https://testnet.fetchoracle.com/#/how-to-tip) to fund a feed and/or claim tips.&#x20;
{% endhint %}

Fund a Feed works well for anyone who needs access to the price of an asset in a decentralized environment, but does not wish to go through the process of setting up a reporter of their own.

This gives users extra incentive to report timely and accurate information, as reporters have the opportunity to earn tips through this process.&#x20;

As a reporter, you’ll be paid out the full amount if you're the first reporting to it and the information you provide is undisputed by the community.

### How Tipping Works

The payments for Fetch Oracle feeds are not held in the main Fetch Oracle contract. Technically you can pay for Fetch Oracle feeds however you want (off-chain, recurring, handshake agreements, etc.), but the trustless way to do so is on-chain via the [AutoPay contract.](https://github.com/fetchoracle/autoPay)

This AutoPay contract allows parties to schedule and fund recurring data feeds or submit one-time tips to Fetch Oracle `QueryIDs`.

For most Fetch Oracle `QueryIDs`, the FETCH token on the network will be the tipped token.

### Funding a Feed

For easy tipping, you can use the Fetch Dashboard [Fund a Feed](https://testnet.fetchoracle.com/#/fund-a-feed) frontend to setup a one time spot price feed.

For automated tipping, you can use the [AutoPay](https://github.com/fetchoracle/autoPay) contract to pay for data.&#x20;

Whether you just need one data report now, or you need recurring information, AutoPay has you covered.

The timestamp array allows you to submit many one-time tips and claim all of your tip rewards at once.

### Claiming Tips

There is a 12 hour waiting period after reporting data before tips can be claimed. This helps ensure that, if a value gets disputed, another reporter will be incentivized to submit the data and the user can still retrieve their requested data.

Tips are 'attached' to the first reporter that successfully submits to the queryID tipped. They also accumulate until data is submitted for it, making it more attractive. For example:

Let's say someone Tips for PLS/USD query multiple times, one after the other: 10, 15, 20. \
Assuming no one has reported for PLS/USD during the time those tips were submitted, the next reporter to submit will attach all tips to itself: 45 FETCH as Tips.

After 12h they can claim them.

{% hint style="danger" %}
**Tips must be claimed within 3 months of the original data submission**.
{% endhint %}


# Receiving Data From Fetch

This page is about consuming data from Fetch Oracle in your own smart contract.

### Querying Information

The Fetch Oracle system allows users to request specific pieces of data. Meanwhile, reporters can then submit those values.&#x20;

Every piece of data that is requested, reported, and retrieved within the Fetch system is associated with a Query Type, Query Data, and a specific identifier known as the Query ID.

{% tabs %}
{% tab title="Query Type" %}
A Query Type is a specification for custom data you want to receive from the oracle. It defines the parameters of a Query that users can input for their specific requests. For example:

**Query Type - `SpotPrice`**

1. asset
   * description: Asset ID (e.g. PLS)
   * value type: string
2. currency
   * description: Selected currency (e.g. USD)
   * value type: string

{% hint style="info" %}
To generate a new SpotPrice Query ID, use the [Query ID Builder](https://tellor.io/queryidstation/).
{% endhint %}
{% endtab %}

{% tab title="Query Data" %}
Query Data is used to form your new Query's unique identifier, or Query ID.&#x20;

It's also emitted in data submission and payment contract events, allowing Fetch users and reporters can programmatically construct query objects.

[Creating a Query](/getting-data/creating-a-query#example-querydata-and-queryid)
{% endtab %}

{% tab title="Query ID" %}
The Query ID is your Query's unique identifier and the hash of the Query Data. It's required for submitting, retrieving, and paying for all data in the ecosystem.

**To generate a query ID, use this simple tool:**

{% embed url="<https://queryidbuilder.herokuapp.com/>" %}
Query ID Builder
{% endembed %}
{% endtab %}
{% endtabs %}


# Solidity

Learn how to set up solidity integration with Fetch Oracle.

## Connecting to the Oracle

To use Fetch Oracle data, you can use the [UsingFetch](https://github.com/fetchoracle/usingfetch) helper contract. After connecting it to the oracle, you can read a value using your `QueryId`. This guide uses the `PLS/USD SpotPrice` as an example query.

{% hint style="success" %}
Check out this [sample project using Fetch Oracle](https://github.com/fetchoracle/sampleUsingFetch).
{% endhint %}

### Installation

To install `usingfetch`, run the following command:

```bash
npm install usingfetch
```

### Importing

To import the UsingFetch contract into your Solidity file, pass the desired Fetch Oracle address (which can be found on the [references page](/the-basics/contract-addresses)) as a parameter:

```solidity
pragma solidity ^0.8.3;

import "usingfetch/contracts/UsingFetch.sol";

contract MyContract is UsingFetch {

  constructor(address payable _fetchAddress) UsingFetch(_fetchAddress) {

  }

  // ...

}
```

{% hint style="info" %}
**Note:** In the constructor, you need to specify the Fetch Oracle [contract address](/the-basics/contract-addresses). For testing, you can use a Fetch Oracle Playground address.&#x20;

When working with live data, make sure to use the Fetch Oracle address on the PulseChain network.
{% endhint %}

### Reading data

You can either use the [QueryID builder](https://go.fetchoracle.com/#/generate-query-id) to create a QueryID and hardcode it, or use Solidity to generate it.&#x20;

Once you have created a `QueryID`, you can add the Fetch Oracle data feed to your contract code.&#x20;

{% hint style="danger" %}
**The best practice** for reading Fetch Oracle data is to use the `getDataBefore` function with a buffer time that allows time for bad values to be disputed:

`getDataBefore(_queryId,`` `**`block.timestamp - 20 minutes`**`);`

It's also best practice to require/check that the data is not too old. For example:&#x20;

`require(block.timestamp - _timestampRetrieved < 24 hours);`
{% endhint %}

In the example below, we add a function getPlsSpotPrice that reads the PLS/USD price feed from the oracle:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.3;

import "usingfetch/contracts/UsingFetch.sol";

contract ExampleContract is UsingFetch {

    constructor(address payable _fetchAddress) UsingFetch(_fetchAddress) {}

    function getBtcSpotPrice() external view returns(uint256) {
    
      bytes memory _queryData = abi.encode("SpotPrice", abi.encode("btc", "usd"));
      bytes32 _queryId = keccak256(_queryData);
      
      (bytes memory _value, uint256 _timestampRetrieved) =
          getDataBefore(_queryId, block.timestamp - 20 minutes);
      if (_timestampRetrieved == 0) return 0;
      require(block.timestamp - _timestampRetrieved < 24 hours, "Data timestamp is more than 24 hours.");
      return abi.decode(_value, (uint256));
    }
}
```


# User Checklists

Make sure you'e ready to handle live data with Fetch Oracle.

On this page, you'll find two checklists:

* **Development:** actions for the security of your code and integration.
* **Maintenance:** actions to help make sure the data flowing into your contracts is properly checked and monitored.

### Development Checklist <a href="#development-checklist" id="development-checklist"></a>

<details>

<summary><strong>Communicate What Oracle Data is Needed, the Desired Frequency, and How the Feeds Will Be Funded.</strong></summary>

This helps the Fetch community and reporters better understand your needs.

Feel free to ask for help and advice by making an issue in the [dataSpecs repo](https://github.com/fetchoracle/dataSpecs) or by reaching out in the [Fetch Telegram group](https://t.me/fetchoracle).

</details>

<details>

<summary>Review Best Practices.</summary>

[This repository](https://github.com/fetchoracle/sampleUsingFetch) is a reference implementation for integrating Fetch price feed data into your protocol.&#x20;

It demonstrates the best practices for using Fetch, including implementing a dispute time buffer and a data staleness check. It also mitigates back-in-time dispute attacks by caching the most recent value and timestamp.

</details>

<details>

<summary><strong>Build in a Delay to Allow Time for Disputes on Bad Data.</strong></summary>

A reporter can submit any value at any time if they are willing to forfeit their staked FETCH tokens. By delaying use of a value, or by delaying the finality of functions that use the latest Fetch value, you can prevent the use of inaccurate data.

**The best practice for reading Fetch data** is to use the`_getDataBefore` function with a buffer time that allows time for bad values to be disputed:

`_getDataBefore(_queryId,`**`block.timestamp - 20 minutes`**`);`&#x20;

[This repo](https://github.com/fetchoracle/sampleUsingFetch) is a great reference for integrating Fetch.

</details>

<details>

<summary>Add a Staleness Check.</summary>

It's also best practice to require/check that the data is not too old for your use-case. For example:

`require(block.timestamp -`**`_timestampRetrieved < 24 hours`**`);`

</details>

<details>

<summary><strong>Prevent a "Back-in-Time" Attack.</strong></summary>

In the event where a Fetch value is disputed, the disputed value is removed and previous values remain. You can prevent potential attackers from going back in time to find a desired value by including a specific check in your contracts.

</details>

### Maintenance Checklist <a href="#maintenance-checklist" id="maintenance-checklist"></a>

<details>

<summary><strong>Hold FETCH for Disputes.</strong></summary>

This ensures that you are ready to dispute any incorrect values that may occur in the oracle data feed.

</details>

<details>

<summary><strong>Hold FETCH for Staking Reporters (as Insurance).</strong></summary>

In the event of a critical situation, this allows you to act as the reporter of last resort for your protocol.

</details>

<details>

<summary><strong>Monitor the Data.</strong></summary>

Monitoring clients like the Disputable Values Monitor  (DVM) can be found in the Fetch GitHub repos. (Installed by default if you used the install script provided [here](https://app.gitbook.com/o/L4kKvU7jlEjab8TB9Lag/s/uaWlV2rnUpdykVKTSfXx/~/changes/80/reporting-data/installing-telliot))

</details>

<details>

<summary><strong>Become Familiar With Telliot.</strong></summary>

Telliot is currently the standard open-source tool for reporting and interacting with the Fetch oracle network.

</details>

<details>

<summary><strong>Communicate Questions/Concerns</strong></summary>

To address your specific monitoring needs, it is important to communicate any questions or concerns that arise with the Fetch community.

</details>

{% hint style="info" %}
**Remember:** Communication and careful planning are key to a successful integration!
{% endhint %}


# Testnet

Using Fetch Oracle on the PulseChain testnet.

{% hint style="info" %}
**Need Testnet FETCH?**

Reach out to the Fetch team on [Telegram](https://t.me/fetchoracle).
{% endhint %}

For `testnet`, you'll need to use the Fetch Oracle addresses corresponding to the `testnet` deployment.  These can be found on the [Contracts Reference](/the-basics/contract-addresses) page.

### Reference Example:

```solidity
pragma solidity >=0.8.0;

import "usingfetch/contracts/UsingFetch.sol";

contract MyContract is UsingFetch {

  constructor(address payable _fetchAddress) UsingFetch(_fetchAddress) {

  }

  // ...

}
```

`Testnet` is a good place to simulate production use of Fetch Oracle. This requires the user to specify the data they want and incentivize Fetch Oracle's network of reporters to *fetch* it.  You can even run your own reporter if desired. &#x20;

Next steps:

* [Create a query](/getting-data/creating-a-query) (or use an [existing query](https://github.com/fetchoracle/dataSpecs/tree/main/types))


# Creating a Query

Tell the ecosystem what data you're seeking.

All data reported to Fetch Oracle is associated with a unique `QueryId` and a `timestamp`.&#x20;

When a user requests data using a [`tip`](/getting-data/tipping) and when a reporter submits data using `submitValue`, they have to input both the `queryId` and `queryData`.&#x20;

The `queryData` tells reporters how to fulfill the data query, while also informing voters how to verify the data in a dispute. The `queryId` is defined as the keccak256 hash of the `queryData` field.

In order to query the Fetch oracle you'll need to first generate `queryData` and its hash, the `queryId`.

### Getting a Query ID and Query Data

Use the tools below to generate a `queryId` and `queryData:`

{% embed url="<https://queryidbuilder.herokuapp.com/>" %}

{% embed url="<https://www.youtube.com/watch?index=2&list=PLuJHbmh0kCXVPHDA2Q3J3TfatBRGrOsm-&v=thjXi7FGLpU>" %}

{% hint style="info" %}
If the [existing Query Types](https://github.com/fetchoracle/dataSpecs/tree/main/types) don't fit your needs, you can define a new one.
{% endhint %}

## Creating a new Query Type

To add a new data type to Fetch Oracle, you'll just need to define a new queryType. This is how you form a question so that Fetch Oracle reporters know exactly what data is being requested.&#x20;

To create a new Query Type or specification for custom data you need from Fetch oracles, there are two options:

* Fork the Fetch [DataSpecs repository](https://github.com/fetchoracle/dataSpecs) and make a pull request for a new Query type in `./types` using [this template](https://github.com/fetchoracle/dataSpecs/blob/main/types/_NewQueryTypeTemplate.md).
* [Fill out this New Data Request Form ](https://github.com/fetchoracle/dataSpecs/issues/new?assignees=\&labels=\&projects=\&template=new_query_type.yaml\&title=%5BNew+Data+Request+Form%5D%3A+)

You'll need to determine three things: a unique `queryType` *name*, *inputs*, and *outputs*. So let's say you want a query for getting the price of any asset in any currency. In human-readable form, your question could look like this:

*What is the price of PLS/USD?*

You might formally define your query like this:

**Name**: `SpotPrice`

**Inputs**:

1\. *asset* (string): Asset ID (e.g. `PLS`)

2\. *currency* (string): Selected currency (e.g. `USD`)

**Outputs**:

1\. *price* (uint256)

\- `abi_type`: ufixed256x18 (18 decimals of precision)

\- `packed`: false

Next, you may need to incentivize reporters to fetch the answer to your question.  Check out the [tipping ](/getting-data/tipping)page to learn more.

Once Fetch Oracle reporters are submitting your new `queryType` on chain, you can retrieve your desired data with the help of [UsingFetch](https://github.com/fetchoracle/usingfetch), which is a helper contract that provides various Fetch Oracle data getters.&#x20;

First, put your question in `queryData` format, which means encoding your `queryType` name and arguments into bytes (see below). You'll then need to get a `queryId`, which is the `bytes32` unique identifier for each Fetch Oracle data feed. The `queryId` is defined as the `keccak256` hash of `queryData`. Once you know the `queryId` you'll be able to retrieve your data.

In Solidity, your contract can get data like [this](/getting-data/solidity).

### Example QueryData and QueryID

If you input `pls` and `usd`, respectively, the `queryData` would be:

> 0x00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000953706f745072696365000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000003706c73000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037573640000000000000000000000000000000000000000000000000000000000

and the `queryId` would be

> 0x83245f6a6a2f6458558a706270fbcc35ac3a81917602c1313d3bfa998dcc2d4b

### Next Steps

You're free to build a query at any time and start integrating it into your project.&#x20;

When you reach the later stages of building your project, [add an issue](https://github.com/fetchoracle/dataSpecs/issues/new?assignees=\&labels=\&projects=\&template=new_query_type.yaml\&title=%5BNew+Data+Request+Form%5D%3A+) to Fetch Oracle's `dataSpecs` repository so that data reporters know how to fulfill your query. &#x20;

For the best chance of success, it's a good idea to tip reporters by [funding a feed](/getting-data/tipping).


# Voting

How to vote for, or against, a dispute.

In the Fetch ecosystem, **anyone** can dispute information that they believe is incorrect. It is then up to everyone to vote on whether or not the dispute is correct.

{% hint style="success" %}
Watch this **animated explainer** to learn more about disputing in just **3 minutes**!
{% endhint %}

{% embed url="<https://www.youtube.com/watch?v=oZD4bRTSM08>" %}

A dispute must be initiated within 12 hours of a report being submitted, and the community then has a minimum of 24 hours to accept or challenge the dispute.

These disputes are managed through voting, and voting power is determined by the amount of FETCH tokens each user holds.

Both [stakers](/the-basics/staking) and [reporters](/reporting-data/how-to-report-data-managed-feeds) are incentivized to participate in as many votes as possible in order to earn their participation rewards.

When these users vote, they can select one of three options:

* **Accept** the submitted dispute information as accurate. Accepting a dispute confirms that you agree a dispute should proceed.
* **Reject** the submitted dispute information. Rejecting suggests that you feel the dispute is invalid and should be rejected.
* **Void**, dismissing the dispute altogether without penalty for reporter or disputer. Void suggests an error has occurred and will cancel the dispute.

**Note: After a dispute is initiated, there is a minimum voting period of 24 hours times the number of voting rounds.**

There are four steps required for resolving disputes. Each step corresponds to a function called from the appropriate governance contract. &#x20;

{% hint style="info" %}
All steps can be performed easily via the [Fetch Dashboard](https://testnet.fetchoracle.com/#/).
{% endhint %}

<details>

<summary>Step 1: Determine the Disputed Value You Want to Vote On.</summary>

Use the Fetch Dashboard [Vote On A Dispute](https://testnet.fetchoracle.com/#/vote) page to find the report that you want to vote on.

</details>

<details>

<summary>Step 2: Vote.</summary>

Select one of the options from the drop down in the corresponding row for the disputed value and click the **vote** button.

</details>

<details>

<summary>Step 3: Tally Votes.</summary>

Use the Fetch Dashboard [Tally Votes](https://testnet.fetchoracle.com/#/tally) page to tally the votes report that you want to dispute.

</details>

<details>

<summary>Step 4: Execute Vote.</summary>

Use the Fetch Dashboard [Finalize Dispute](https://testnet.fetchoracle.com/#/finalize-dispute) page to complete the round and execute the vote.

</details>


# Disputing

Learn about disputing data.

{% hint style="success" %}
The easiest way to dispute data submitted to Fetch Oracle is to use the [Fetch Dashboard](https://testnet.fetchoracle.com/#/how-to-dispute).&#x20;
{% endhint %}

{% hint style="warning" %}
Before beginning a dispute, the proper amount of FETCH **tokens must be approved** to the contract to cover the dispute fee.  If you use the Fetch Dashboard for the dispute, the token approval is preformed as part of the in-app process.
{% endhint %}

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

Make sure to check FIRST, especially using the DVM, which feed you are disputing and what sources you are using as truth!

Disputing data that is later deemed it was VALID by the community may lose you your dispute fee.

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 %}

For the DVM to dispute, you need to use the `-d` option. You also need to specify an account that will be used to pay the dispute fee and initiate the dispute.

```bash
cli -d -w 120 -a myacct1
```

The command above would start the DVM in dispute mode, with the specified account monitoring the chain every 120s.\
\
If you don't specify an account with the `-a` option, type 'n' when asked if you want to '*run alerts only*?' and select one of your accounts from the list.

{% hint style="warning" %}
You can not dispute if you have not set an account to use when starting the DVM
{% endhint %}

DVM will start with the message *"...Now with auto-disputing!..."* when in dispute mode.

{% hint style="info" %}
There will be no changes appearing in the terminal window until there's a new report submitted to Fetch. After that, some calculations may appear and a table with detailed info on the report will take place.
{% endhint %}

### Dispute Mechanism <a href="#dispute-mechanism" id="dispute-mechanism"></a>

Any party can challenge data submissions of any reporters when a value is placed on-chain. A challenger must submit a dispute fee to each challenge. Once a challenge is submitted, 1 stake of the reporter challenged is set aside for the duration of the dispute period.

FETCH holders vote on the validity of the reported value. All FETCH holders have an incentive to maintain an honest Oracle and can vote on the dispute.&#x20;

A proper submission is one that corresponds to a valid query around the time of the submission of the value. The subjectivity of the validity is a feature and corresponds to “correct” being up to the interpretation of the Fetch community.

<https://t.me/fetchoracle>

### Why Disputing Is Important <a href="#why-its-important" id="why-its-important"></a>

The security of Fetch comes through a minimum deposit of FETCH tokens that acts as a bond or stake in order for reporters to participate in providing data.&#x20;

The reporters risk losing these stakes if they submit data that is successfully disputed.

### What This Means For Getting Data <a href="#what-this-means-for-getting-data" id="what-this-means-for-getting-data"></a>

On a blockchain, security and time can not be separated. You can't have instant finality and still be secure. This is particularly true for oracle data.

Fetch Oracle data values can be used as soon as the data is placed on-chain, however *the longer a user waits once the data is submitted on chain, the more probable it is to remain,* and therefore be secure thanks to the economic incentives to dispute invalid information.&#x20;

Values are able to be disputed and taken off-chain for the same time frame as the reporter lock (12 hours).

## Dispute Using the Fetch Dashboard

The easiest way to dispute data submitted to the Fetch Oracle is to use the [Dispute](https://testnet.fetchoracle.com/#/how-to-dispute) feature in the Fetch Dashboard. &#x20;

This will manage approving the tokens for the governance contract to spend to cover the fees, transfer the correct fee, and call the required function appropriate for the current state of the dispute.

## Dispute Fees

The dispute fee amount is variable depending on the current minimum stake amount. The `getDisputeFee` function can be read from the Fetch governance contract.&#x20;

{% hint style="info" %}
The `disputeFee` starts at 1/10th of the `stakeAmount`, and doubles with each voting round or with each open dispute on a given QueryID. The dispute fee is capped at the stakeAmount.
{% endhint %}


# Introduction to DVM

Monitoring and disputing values in Fetch Oracle.

### Background

In order for the Fetch Oracle to provide accurate, quality data, the data submitted to the Oracle must be monitored, validated and — when the legitimacy of data is in question — disputed.

### How to Dispute a Value Submitted to Fetch

The easiest way to dispute a value submitted to the Fetch Oracle is to use the [Fetch Dashboard](https://testnet.fetchoracle.com/#/how-to-dispute).&#x20;

{% hint style="warning" %} <mark style="color:red;">**Each Disputer is responsible for the action they're taking**</mark><mark style="color:red;">.</mark>

Make sure to check FIRST, especially using the DVM, which feeds you are disputing and what sources you are using as truth!

Disputing data that is later deemed it was VALID by the community may lose you your dispute fee.

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 %}

### How to Run an Automated Monitoring and Disputing Tool (DVM)

A DVM will automatically monitor values submitted to the Fetch Oracle.

## **The Disputable Values Monitor (DVM)**

The DVM is a CLI dashboard and text alerts app for disputable values reported to Fetch oracles.  The DVM constantly monitors Fetch data submissions and compares them to the data available in Telliot-feeds feeds. &#x20;

By default, DVM will monitor for PLS prices and dispute them if the percentage difference against its source is greater than 10%. (if initialized with `-d` flag)

{% hint style="success" %}
Installation instructions can be found on the [install page](/votes-and-disputes/introduction-to-dvm/installing-dvm).
{% endhint %}

Once a disputable value is picked up by the DVM, it sends an alert to a specified Discord webhook.

The next set of pages in this section detail how to install, configure, run and maintain your own DVM.

### Auto Disputer

The DVM has an Auto-Disputer. The Auto-Disputer is a complex event listener for any EVM chain, and it specifically listens for `NewReport` events from Fetch Oracle that the user wants to monitor.

When the Auto-Disputer receives new `NewReport` events, it parses the reported value from the log, then compares the reported value to the trusted value from the Fetch reporter reference implementation (which is Telliot).

In order to auto-dispute, users need to define what a "disputable value" is. To do this, users can set "thresholds" for feeds they want to monitor. Thresholds in the Auto-Disputer serve to set cutoffs between a healthy value and a disputable value. Users can pick from three types of thresholds: **range, percentage, and equality**.

#### Range <a href="#range" id="range"></a>

**Range:** if  the difference between the reported value and the Telliot value is greater than or equal to a set amount, dispute!

For example, if the reported value is 250, and the Telliot value is 1000, and the monitoring threshold is a range of 500, then the difference is 750 (it is >= to the range amount of 500). This means the value is disputable!&#x20;

Therefore, a reported value of 501, in this case, would **not** be disputable.&#x20;

The smaller the range, the more strict the threshold.

#### Percentage <a href="#percentage" id="percentage"></a>

**Percentage:** if the difference between the Telliot value and the reported value is greater than or equal to a set percentage of the Telliot value, dispute!&#x20;

For example, if the reported value is 250, and the Telliot value is 1,000, and the percentage threshold is 0.50 (50%), then the percent difference is 75% of the Telliot value (1,000), and the value is disputable! Therefore, a reported value of 750, in this case, would **not** be disputable.

The smaller the percentage, the more strict the threshold.

#### Equality <a href="#equality" id="equality"></a>

**Equality:** if there is any difference between the reported value and the Telliot value, send a dispute!

For example, if the reported value is "0xabc123", and the Telliot value is "0xabc1234", then the value is disputable!&#x20;

However, to prevent false disputes due to checksummed addresses, the equality threshold sees "0xABC" and "0xabc" as equal.

### Considerations <a href="#considerations" id="considerations"></a>

{% hint style="info" %}
**Range** thresholds best monitor high variance price feeds where the percent difference in price between sources is an unreliable indicator of a bad value. They are incompatibale, however, with non-numeric data feeds.
{% endhint %}

{% hint style="info" %}
**Percentage** thresholds best monitor standard price feeds. The percentage is measured relative to the Telliot value, not the reported value. In other words, if the Telliot value is 1,000, a 25% difference is 25% of 1,000. Like range thresholds, percentage thresholds are incompatibable with non-numeric data feeds.
{% endhint %}

{% hint style="info" %}
**Equality** thresholds best monitor data feeds where there is only one right answer. For example, `EVMCall` requests should be exactly equal to their expected Telliot response. They aren't very useful for price feeds, though.
{% endhint %}


# Installing DVM

How to install, configue, and run a DVM

### Prerequisites:

Follow the install instructions from [Installing Telliot](/reporting-data/installing-telliot) and choose the option to install DVM when running the script. \
\[If you are a more advanced user, you can clone the [DVM repo](https://github.com/fetchoracle/disputable-values-monitor/tree/testnet) inside `telliot-feeds` folder, enter `venv` environment, cd into dvm folder and install it with `pip install -e .`]

Once installed, make sure you're in python's virtual environment `(venv)`:

{% hint style="warning" %}
Everytime you run Telliot or DVM you need to enter this virtual environment. To enter it, go to `telliot-feeds` folder and run `source venv/bin/activate`. To exit it, run `deactivate`.
{% endhint %}

Navigate to the `disputable-values-monitor` directory installed on your machine, under `telliot-feeds` folder:&#x20;

```bash
cd ~/telliot-feeds/disputable-values-monitor/
```

### .env file

Before running the DVM check the `.env` file inside `telliot-feeds`. That's where the variables for DVM are stored and where you'll set your Discord Webhook for alerts.

You may do this later, but DVM won't send alerts for disputes or extra features.

### Endpoints.yaml file

{% hint style="danger" %}
It's also important to check your `telliot` folder in /Home. Open the `endpoints.yaml` file and comment out the endpoints you're not going to use.&#x20;

For example, if you're going to be reporting and monitoring only pulsechain Mainnet, comment out (with a '#') the endpoints for Testnet or any other ones that may be present.

Remember DVM will be scanning all chains in this folder for events.

```yaml
type: EndpointList
endpoints:
#- type: RPCEndpoint
 # chain_id: 943
  #network: Pulsechain Testnet
  #provider: Pulsechain
  #url: https://rpc.v4.testnet.pulsechain.com
  #explorer: https://scan.v4.testnet.pulsechain.com/
- type: RPCEndpoint
  chain_id: 369
  network: Pulsechain Mainnet
  provider: Pulsechain
  url: https://rpc.pulsechain.com
  explorer: https://scan.pulsechain.com/
```

{% endhint %}

{% hint style="warning" %}
Always stop all services if editing .env files or parameters for DVM or Telliot, in case you have both running.

It's recommended, if possible, to run each service on different machines.
{% endhint %}

### Dispute Mode <a href="#usage" id="usage"></a>

To start the DVM in dispute mode, run the following command:

```
cli -d -a <yourAccName>
```

### Alerts <a href="#usage" id="usage"></a>

To enable Discord alerts you need to set up the `.env` file inside `telliot-feeds` with your discord webhook. &#x20;

If you don't have a Discord webhook, here's Discord's [official tutorial](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks#:~:text=%C2%A0%20Facebook-,Making%20A%20Webhook,-With%20that%20in) on how to get one following quick easy steps.

### Alerts Only

To send alerts only and monitor events, start the DVM running:

```bash
cli
```

The console will ask if you want to run alerts only. Type "y" and press enter.

{% hint style="warning" %}
The DVM will then monitor the queries you set in the `telliot-feeds/disputable-values-monitor/disputer-config.yaml` file, inside the dvm folder, and will **NOT** dispute them if they meet their thresholds. It will **only send alerts** according to your specification.

You can generate queryIDs at <https://go.fetchoracle.com/#/generate-query-id>
{% endhint %}

The console screen doesn't change until there's a new report submitted. After that, a table with detailed info on the reports will take place.

Run cli `--help` for a help guide on DVM options available.


# Monitoring

Options to monitor on chain reports and extra features

## Network ID

```
NETWORK_ID=369
```

Set this variable inside the .env file to match the network you're monitoring. \
DVM uses this variable for settings, but you still need to double check the [endpoints.yaml](https://docs.fetchoracle.com/votes-and-disputes/introduction-to-dvm/pages/OdTzxGgpsY1IblTiKFCH#endpoints.yaml-file) file.

## Confidence Threshold

{% hint style="warning" %}
Use `-c` or `--confidence-threshold` to specify a universal percentage confidence threshold for monitoring **only**.
{% endhint %}

Use `-a` or `--account-name` to specify a `chained` account to use for disputing:

```bash
cli -a <your account name without quotes>
```

## Alert All NewReports

Use `-av` to get an alert for all `NewReport` events (regardless of whether they are disputable or not):

```bash
cli -av
```

## Wait Between Checks

If you leave it as default, your DVM will scan the chain every few seconds for new reports.&#x20;

Use the `-w` (wait) option to set how often DVM will check for new reports:

```bash
cli -w 120
```

## Configuring QueryIDs and Thresholds to Monitor. <a href="#configuring-tresholds" id="configuring-tresholds"></a>

Monitored Feeds and their Thresholds are defined in the `disputer-config.yaml` file.

Generate queryIDs here: <https://go.fetchoracle.com/#/generate-query-id>

By default, the Auto-Disputer will monitor the PLS/USD feed with a threshold percentage of 10%. In the default `disputer-config.yaml`  in `disputable-values-monitor/disputer-config.yaml` this is represented as:

```yaml
# AutoDisputer configuration file
feeds:
  - query_id: "0x83245f6a6a2f6458558a706270fbcc35ac3a81917602c1313d3bfa998dcc2d4b"
    threshold:
      type: Percentage
      amount: 0.1 # 10%

```

Where `0x83245f6a6a2f6458558a706270fbcc35ac3a81917602c1313d3bfa998dcc2d4b` represents the `queryId` of the PLS/USD feed on Fetch Oracle.&#x20;

{% hint style="info" %}
It's recommended to monitor two 'simple' queries at once per DVM instance, although more is also possible.&#x20;
{% endhint %}

To change the query being monitored, simply add the new QueryID in the `query_id` field, using quotes.

To change the percentage threshold to dispute or send alerts, change the amount field where:

0.1 = 10%

1 = 100%

For example, to monitor a second query in the form of a `newQueryId`, follow the same pattern while respecting the file indentation, like so:

```yaml
- query_id: "0x83245f6a6a2f6458558a706270fbcc35ac3a81917602c1313d3bfa998dcc2d4b"
    threshold:
      type: Percentage
      amount: 0.1 # 10%
 - query_id: "newQueryID"
    threshold:
      type: Percentage
      amount: 0.75 # 75%

```

## Token Balance Alerts

### Reporters

Inside `telliot-feeds` folder there's a `.env` file which contains variables for DVM.

You can set `REPORTERS=` with the addresses of reporters to monitor their FETCH and PLS balance on chain. If these balances thresholds are met, DVM will send an alert to your Discord channel.

Instructions are present in the file, just remember to separate wallet addresses in REPORTERS= with a comma and to match the thresholds values with the same number of reporters.

For example, if you have 3 wallets, you need 3 thresholds, one for each wallet, in their respective order:

REPORTERS= "0x1...,0x2...,0x3"\
Threshold values= "100,150,200"

Above, wallet 0x1 will trigger with 100, wallet 2 with 150 and wallet 3 with 200.

### Disputer

You can also monitor FETCH and PLS balances for the disputer wallet selected for disputing (when starting DVM with the `-d` option). Set the thresholds for the tokens and it will send an alert when they're met.

## Stale Reporters

You can set a threshold, in seconds, to get notified if the reporters in REPORTERS= have not submitted

```
NO_REPORTING_THRESHOLD="43200, 43200"
```

The length and order or values should match REPORTERS=

## Stale queryIDs

You can set queryIDs to be monitored for stale submissions. If a queryID doesn't receive a submission in a X amount of seconds, you'll receive an alert.

{% code overflow="wrap" %}

```
#QueryIDs to monitor when was the last time they were reported, separated by commas.
#use "0x00000000000000000000000000000000000000000000000000000000000000000" as default if not using it.

QUERY_IDS="0x00000000000000000000000000000000000000000000000000000000000000000,0x00000000000000000000000000000000000000000000000000000000000000000"

#Thresholds, separated by commas, to send alerts if no report is submitted within threshold for queryIDs above.
#Must follow the length and order of QUERY_IDS=.

QUERYID_LAST_REPORT_THRESHOLD="43200, 43200" #Value in seconds. 43200 is for a 12h check.
```

{% endcode %}

Generate queryIDs here: <https://go.fetchoracle.com/#/generate-query-id>


# Claim Tip Script ENV Config

{% hint style="info" %}
This page contains a more advanced CLI version of the easier-to-use 'claim tips' section present in the [Fetch Dashboard](https://dashboard-staging.fetchoracle.com/#/).
{% endhint %}

`ACCT_PUBLIC_KEY=0x0000000000000000000000000000000000000000`

The public address of the account you're scanning tips for.

\
`ACCT_PRIVATE_KEY=0000000000000000000000000000000000000000000000000000000000000000`

The private key of the same account above.

\
REACT\_APP\_DATAFEED\_FLEX\_SUBGRAPH\_BASEURL=[https://graphqlhost/subgraphs/name/fetch-oracle/fetchflex](http://localhost:8000/subgraphs/name/fetch-oracle/fetchflex)

Fetch Flex subgraph URL for the environment you're scanning tips for.

\
REACT\_APP\_DATAFEED\_AUTOPAY\_SUBGRAPH\_BASEURL=[https://graphqlhost](http://localhost:8000/subgraphs/name/fetch-oracle/fetchflex)/[subgraphs/name/fetch-oracle/autopay-pulse](http://localhost:8000/subgraphs/name/fetch-oracle/autopay-pulse)

AutoPay subgraph URL for the environment you're scanning tips for.

\
`AUTOPAY_ADDRESS=0x0000000000000000000000000000000000000000`

Auto Pay contract address for the environment you're scanning tips for.

\
PULSE\_NETWORK\_URL=<https://rpc.v4.testnet.pulsechain.com>

RPC URL for mainnet or testnet, according to the environment you're scanning.

\
`LISTENER_TIMEOUT_DURATION=120 # 120 seconds`

Time out for the tip listener. Can leave as is.

\
`BUFFER_TIME=43200 # 12 hours in seconds`

Buffer time to call the 'claim' function. Leave as is, as 12h is the minimum you need to wait to actually claim an available tip.

\
`REPORT_TIMESTAMP_TIMEOUT=2419200 # 4 weeks in seconds`

You can change this or leave as is, just keep in mind that you have to claim your tips within three months.

If this variable is met, it won't try to submit the 'claim' function when the threshold is set.

If the parameters to claim a tip are not met anyway, you'll just get a revert from the contract.<br>


