This repo contains a couple of simple implementations of a demo Consumer smart contract, which implements the xFUND Router & Data Provision suite.
It contains everything required to get started, including a skeleton, simple smart contract (DemoConsumer.sol) which can be modified, deployed and tested.
Additionally, DemoConsumerCustom.sol contains more sophisticated custom data request and receive functions to give an example of how the base contract can be extended to suite your needs.
The interaction guide below focuses on the simpler DemoConsumer
smart contract, but
both are deployed during the process, and can be interacted with.
Copy the custom_networks.example.js
to custom_networks.js
and modify as required. It will then be possible to
pass the network using the --network
flag with any truffle
command.
Open a Terminal and clone this repo:
git clone https://github.com/unification-com/data-consumer-demo
cd data-consumer-demo
NodeJS
is required to use this software. We recommend using
nvm to manage NodeJS installations, and currently.
recommend NodeJS v12.18.3.
We also recommend Yarn for npm
package management.
Install the dependencies with either yarn
yarn install
or npm
npm install
Compile the contracts using truffle
:
npx truffle compile
Using Metamask, or similar Wallet manager create a new wallet address (or use an existing one).
Grab some test ETH from the Sepolia faucet for this wallet address.
You will also need to make a note of the Private Key and Wallet address for the next steps.
This wallet will be used to deploy the smart contract, and interact with it.
Copy the example.env
to .env
:
cp example.env .env
Open the new .env
file in a text editor and edit the variables, adding the private
key for the wallet you intend to use to deploy the smart contract (the one from step 3)
for the ETH_PKEY
variable. You aill also need an [Infura])(https://infura.io) API key,
and optionally an Etherscan API key.
The Sepolia values for ROUTER_ADDRESS
and XFUND_ADDRESS
can be found at
https://docs.finchains.io/contracts.html.
The Sepolia values for PROVIDER_ADDRESS
and FEE
can be found at
https://docs.finchains.io/guide/ooo_api.html.
At the date of commit, for Sepolia these values are:
ROUTER_ADDRESS=0xf6b5d6eafE402d22609e685DE3394c8b359CaD31
XFUND_ADDRESS=0xb07C72acF3D7A5E9dA28C56af6F93862f8cc8196
PROVIDER_ADDRESS=0x611661f4B5D82079E924AcE2A6D113fAbd214b14
FEE=100000
Once your .env
is configured, deploy the smart contract on Sepolia testnet:
npx truffle deploy --network=sepolia
Optionally, you can upload the source code and verify the contract on Etherscan, so that
you can interact with it via Etherscan. You will need an
Etherscan API key, and to add the value to your .env
by setting the ETHERSCAN_API
value. Once that's done, run:
npx truffle run verify DemoConsumer --network=sepolia
npx truffle run verify DemoConsumerCustom --network=sepolia
Note: Both demo contracts DemoConsumer.sol
and DemoConsumerCustom.sol
should now have been
deployed. The following interaction overview covers the simpler DemoConsumer
smart
contract. With the exceptions of calling the requestData
and getting the price data from
DemoConsumer
contract, the following steps are the same for both demo contracts.
See the customRequestData
and getPrice
functions in the
DemoConsumerCustom.sol contract
for examples on how to interact with the customised version.
Run the truffle
development console, and connect to the Sepolia testnet:
npx truffle console --network=sepolia
The following steps need only be done periodically, to ensure all parties have the correct amount of tokens and gas to pay for data.
Go to xFUNDMOCK
on Etherscan, and connect MetaMask with the account used to deploy the DemoConsumer
smart contract, then run the gimme()
function. This is a faucet function, and will
supply your wallet with 10 xFUNDMOCK
tokens. You may do this once per hour.
Within the truffle
console, load the contract instances, and set some variables
ready for interaction
truffle(sepolia)> let provider = process.env.PROVIDER_ADDRESS
truffle(sepolia)> let demoConsumer = await DemoConsumer.deployed()
Get the deployed address for your DemoConsumer
smart contract:
truffle(sepolia)> demoConsumer.address
Next, using either Etherscan, or MetaMask, transfer 5 xFUNDMOCK
tokens to your
DemoConsumer
contract address.
Wait for the transaction to succeed, then get the current account information
truffle(sepolia)> let accounts = await web3.eth.getAccounts()
truffle(sepolia)> let consumerOwner = accounts[0]
Then we need to allow the Router
smart contract to pay fees on the DemoConsumer
contract's
behalf:
truffle(sepolia)> demoConsumer.increaseRouterAllowance("115792089237316195423570985008687907853269984665640564039457584007913129639935", {from: consumerOwner})
Now that the DemoConsumer
smart contract is fully initialised, we can request data
to be sent to the smart contract. You will need to top up the Consumer contract's
tokens every so often.
First, check the current price
in your DemoConsumer
contract. Run:
truffle(sepolia)> let priceBefore = await demoConsumer.getPrice()
truffle(sepolia)> priceBefore.toString()
The result should be 0.
Next, request some data from the provider. Run:
truffle(sepolia)> let endpoint = web3.utils.asciiToHex("BTC.GBP.PR.AVC.24H")
truffle(sepolia)> demoConsumer.requestData(endpoint, {from: consumerOwner})
The first command encodes the data endpoint (the data we want to get) into a bytes32
value. We are requesting the mean US dollar (USD
) price of Bitcoin (BTC
), with
outliers (very high or very low) values removed (PR.AVI
) from the final mean calculation.
A full list of supported API endpoints is available from the Finchains OoO API Docs
It may take a block or two for the request to be fully processed - the provider will listen for
the request, then submit a Tx with the data to the Router
, which will forward it to
your smart contract.
After 30 seconds or so, run:
truffle(sepolia)> let priceAfter = await demoConsumer.getPrice()
truffle(sepolia)> priceAfter.toString()
If the price is still 0, simply run the following a couple more times:
truffle(sepolia)> priceAfter = await demoConsumer.price()
truffle(sepolia)> priceAfter.toString()
The price should now be a non-zero value.
To convert to the actual price:
truffle(sepolia)> let realPrice = web3.utils.fromWei(priceAfter)
truffle(sepolia)> realPrice.toString()
Note: the Oracle sends all price data converted to actualPrice * (10 ** 18)
in
order to remove any decimals.
There are a couple of helper scripts in dev_scripts
which can be run via Truffle
to automate requesting and cancelling data requests on Sepolia Testnet for your contract.
Request data and check fulfilment with:
npx truffle exec dev_scripts/consumer_xfund.js --network=sepolia
npx truffle exec dev_scripts/request-data.js --network=sepolia