Quex Data Oracle Tutorial
Here we present a step-by-step illustration of Quex data oracle usage. This tutorial passes through all the actions needed to create your own data feed on Quex Data Oracle query and use the data.
For the sake of example, we consider the part of dApp that collects and stores five best bids and five best asks on BTC-USDT pair on Binance together with their lastUpdateId
. Normally you would not need the persistent storage of this data due to high gas consumption and corresponding transaction fees. You would rather make some aggregation and implement some decision logic with as few persistent storage as possible. However, this example is good in demonstrating most of Quex capabilities. Namely
Complex HTTP query to a third-party API
Non-trivial result post-processing, including arithmetics, array mapping, and selecting fields of JSON
Ability to receive the data on-chain as a ready-to-use user-defined structure without the hassle of reencoding, repacking, or introducing large argument lists
Register the request on-chain
Clone the interfaces repository with the helper script to register the new request
Cd to the directory with the helper script
Edit the data feed description (quex_feed.json
) to meet your desired request. In our case, it will look like
The details on how these fields are constructed can be found here. Briefly, request
has the structure of an HTTP request to be made by an oracle, patch
is designated to contain the encrypted private fields of the request, schema
is the type of the structure which is to be ABI-encoded and passed on-chain, filter
is a jq
filter, used to convert response JSON to schema
. Quex uses the subset of jq language for post-processing. The list of supported operations can be found here.
In config.json
provide your RPC URL, the address of Quex FeedRegistry
contract, and the path to the file with your data feed description (quex_feed.json
)
The address of the FeedRegistry
contract together with other user-facing contracts can be found here.
Prepare Python virtual environment and install dependencies
Run the script to register the request. It will send corresponding transactions to the configured chain. Hence, it requires the private key of the account you use for on-chain request registration
The output will look like
The most important field here is feed ID. Take a note of it
You can see the corresponding transactions in the explorer. The parts of the data feed description are reusable. So, in case you will be registering new data feeds manually, you can reuse request_id
, patch_id
, schema_id
, and filter_id
for new data feeds without sending already recorded data on-chain.
Create a Smart-Contract
Create your contract which utilizes the data from the oracle. Here is an example for our particular case. Note that FEED_ID
is taken as in the output of create_feed.py
.
Deploy your contract to the network where Quex data oracles exist. This particular contract can be compiled with "viaIR": true
option to allow structure array copying.
Query Data
Every time we wish to query the data, we can use the request
method of the contract above. It will pass the request to QuexRequestRegistry
contract, and after the data is fetched and post-processed it will be returned to processResponse
method. As processResponse
can contain arbitrary logic, the callbackGasLimit
must be passed to request
which must account for the gas used by processResponse
. Additionally, the amount of native coins not less than tx.gasprice*callbackGasLimit
must be paid in the request
call to cover these gas expenses.
Do not worry about guessing the precise value of the gas price. The QuexRequestRegistry
contract calculates the exact price and returns the change within the same transaction, so you can safely transfer a bit more than needed.
In our example the callback has to store large structures of OrderBook
, and a gas consumption is a bit less than 600k per call. So when trying out this contract in the test network, you can set callbackGasLimit
to 600000, and set the transaction value to cover this gas (at the time of writing, 0.5 RBNT on Redbelly testnet will suffice for all this logic).
After you trigger request
, and receive the response, you can check it with the getters provided.
Last updated