Offchain Subscriber Example

Example of off chain subscriber to listen to data received from Oracles

What's off-chain Subscriber

Off-chain subscriber is non-contract method to query Endpoints and receive data through events from Oracle. It can be a script to query and react on the response received from Oracles through Ethereum blockchain events or users can manually query and wait to see responses using zap-term cli tool

Template

Following script includes calling query and waiting for response events

import {ZapSubscriber} from "@zapjs/subscriber"
import {ZapBondage} from "@zapjs/bondage"
import {ZapToken} from "@zapjs/zaptoken"
import {Config} from "./Config";
const Web3 = require('web3');
const HDWalletProviderMem = require("truffle-hdwallet-provider");
export class SimpleSubscriber{
zapSubscriber: ZapSubscriber|null
constructor(){
this.zapSubscriber = null
}
/**
Decide what oracle and endpoint you want to interact with,
Approve, Bond dots to be ready to query (if there is not enough dots bound)
*/
async setup(){
//setup subscriber, for demo reason, we use same wallet as provider's
let web3 = new Web3(new HDWalletProviderMem(Config.mnemonic,Config.NODE_URL,1))
let accounts = await web3.eth.getAccounts();
let subscriberOwner = accounts[0]
let zapSubscriber = new ZapSubscriber(subscriberOwner, {networkProvider: web3, networkId: await web3.eth.net.getId()})
let zapToken = new ZapToken({networkProvider: web3, networkId: await web3.eth.net.getId()})
let zapBondage = new ZapBondage({networkProvider: web3, networkId: await web3.eth.net.getId()})
// will skip approve and bond if there is enough dots already bound
const boundDots = await zapSubscriber.getBoundDots({provider:Config.Oracle,endpoint:Config.Endpoint})
if(boundDots<Config.dots){
let allowance = await zapToken.contract.methods.allowance(subscriberOwner,zapBondage.contract._address).call()
let zapRequired = await zapBondage.calcZapForDots({provider:Config.Oracle,endpoint:Config.Endpoint,dots:Config.dots})
if(allowance<zapRequired){
let txid = await zapSubscriber.approveToBond({provider:Config.Oracle,zapNum:zapRequired})
}
let txid = await zapSubscriber.bond({provider:Config.Oracle,endpoint:Config.Endpoint,dots:Config.dots})
}
//start listening to incoming reponses
zapSubscriber.listenToOffchainResponse({},(err:any,logs:any)=>{
console.log("Response event from provider : ",logs)
this.processResponse(logs)
})
}
processResponse(response:string){
// implement your custom logic here
console.log("Process response from Oracle : ",response)
}
async queryProvider(query:string,params:string[]){
if(this.zapSubscriber){
return await this.zapSubscriber.queryData({
provider: Config.Oracle,
query: query,
endpoint: Config.Endpoint,
endpointParams: params
})
}
else{
return "No subscriber found"
}
}
}

Subscriber template provide a class that you can setup the function processResponse much as on-chain subscriber implementing callback function. That will be all you need to do to have fully functional off-chain subscriber

Using Template

Setup environment and create off-chain subscriber

  1. cd subscriber-template

  2. cd Offchai_Subscriber_Example

  3. Fill out config file variables such as mnemonic, oracle address, endpoint, query, dots ...

  4. In Simplesubscriber.ts, fill out the body of function processMessage

  5. Make sure you have ZAP and ETH balances in your mnemonic's address

  6. yarn

  7. yarn build

  8. yarn start-offchain

You can modify the index.ts file to include logic when to trigger the query to Oracle

That's it, now you have a Zap Subscriber that interact with Zap contracts and Oracles to receive data you need.