Fiducia Oracle Network
It is often necessary we fetch external data in our blockchain applications. For traditional back-end applications this can be done with simple HTTP REST-ful fetch requests, but not the case in blockchain applications. Firstly it is usually not necessary for every nodes in the network to fetch from the remote end to verify the data. Secondly the http request does not return a deterministic result as there maybe network delays or even errors. This potentially cause block production delays and problems and affect the stability of the blockchain application.
Through REI and FCN, Fiducia Network provides smart contracts access to off-chain data from APIs, data sources, and computation processes, including grid nodes running full fledged applications.
The following is an implementation of the FID node and REI to access off-chain data using the Substrate ecosystem components.
This project consists of a Fiducia Interoperable Data blockchain node with a custom module that fetch prices of a few cryptocurrencies, each from two external sources and then aggregate them by simply averaging and recording them back to on-chain storage.
Fiducia Oracle Network Implementation
Fiducia Oracle Network is an interoperable blockchain that is able to fetch price information from data sources. The Development stack of Fiducia Oracle Network consists of: 1) Substrate SDK 2) WebAssembly 3) Grid Computing Node
1. Data Fetch Transaction
Data Fetch Transaction
In this file, in addition to the regular lib setup, we specify a SubmitDFTransaction
type and set it as the associated type for our pallet trait. We then implement the system::offchain::CreateTransaction
trait afterwards as follows. This is necessary for the off-chain worker to send signed or unsigned transactions back on-chain.
2. Data Verification and Block Inclusion
Data Verification and Block Inclusion
Note the necessary included modules at the top for:
system::{ offchain, ...}
, off-chain workers, for submitting transactionsimple_json
, a lightweight json-parsing library that work inno_std
environmentsp_runtime::{...}
, some libraries to handle HTTP requests and sending transactions back on-chain.
The main logic of this pallet goes as:
After a block is produced,
offchain_worker
function is called. This is the main entry point of the Substrate off-chain worker. It checks that for everyBlockFetchDur
blocks (set inlib.rs
), the off-chain worker goes out and fetch the price based on the config data inFETCHED_CRYPTOS
.For each entry of the
FETCHED_CRYPTOS
, it executes thefetch_price
function, and get the JSON response back fromfetch_json
function. The JSON is parsed for a specific format to return the price in (USD dollar * 1000) in integer format.We then submit an unsigned transaction to call the on-chain extrinsics
record_price
function to record the price. All unsigned transactions by default are regarded as invalid transactions, so we explicitly enable them in thevalidate_unsigned
function.On the next block production, the price is stored on-chain. The
SrcPricePoints
stores the actual price + timestamp (price point), andTokenSrcPPMap
andRemoteSrcPPMap
are the indices mapping the cryptocurrency and remote src to some price points. FinallyUpdateAggPP
are incremented by one so later on we know how many new price points have arrived since we last calculated the mean of the crypto price.Once a block is produced,
offchain_worker
function kicks in again, and see thatUpdateAggPP
have mapping value(s) greater than 0, then theaggregate_pp
function is called. This function retrieves the lastUpdateAggPP
mapping value, being passed in to the function asfreq
parameter, of that crypto prices and find the mean of each crypto price. Then we submit an unsigned transaction to call the on-chain extrinsicsrecord_agg_pp
function to record the mean price of the cryptocurrencies, with logic similar to therecord_price
function.
User Interface
Configuration
The User Interface is based on ReactJS library. Configuration is stored in the src/config
directory, with common.json
being loaded first, then the environment-specific json file, and finally environment variables, with precedence.
development.json
affects the development environmenttest.json
affects the test environment, triggered inyarn test
command.production.json
affects the production environment, triggered inyarn build
command.
Some environment variables are read and integrated in the template config
object, including:
REACT_APP_PROVIDER_SOCKET
overridingconfig[PROVIDER_SOCKET]
REACT_APP_DEVELOPMENT_KEYRING
overridingconfig[DEVELOPMENT_KEYRING]
More on React environment variables.
When writing and deploying your own front end, you should configure:
CUSTOM_TYPES
insrc/config/common.json
. See Extending types.PROVIDER_SOCKET
insrc/config/production.json
pointing to your own deployed node.DEVELOPMENT_KEYRING
insrc/config/common.json
be set tofalse
. See Keyring.
Specifying Connecting Node
There are two ways to specify it:
With
PROVIDER_SOCKET
in{common, development, production}.json
.With
rpc=<ws or wss connection>
query parameter after the URL. This overrides the above setting.
Reusable Components
useSubstrate Custom Hook
The custom hook useSubstrate
provides access to the Polkadot js API and thus the keyring and the blockchain itself. Specifically it exposes this API.
socket
- The remote provider socket it is connecting to.types
- The custom types used in the connected node.keyring
- A keyring of accounts available to the user.keyringState
- One of"READY"
or"ERROR"
states.keyring
is valid only whenkeyringState === "READY"
.api
- The remote api to the connected node.apiState
- One of"CONNECTING"
,"READY"
, or"ERROR"
states.api
is valid only whenapiState === "READY"
.
TxButton Component
The TxButton handles basic query and transaction requests to the connected node. You can reuse this component for a wide variety of queries and transactions. See src/Transfer.js for a transaction example and src/ChainState.js for a query example.
Account Selector
The Account Selector provides the user with a unified way to select their account from a keyring. If the Balances module is installed in the runtime, it also displays the user's token balance. It is included in the template already.
Last updated