Skip to main content

Polling Cycles

What are smart contract events?

Smart contract events broadcast new data coming from a contract.

Why are smart contract events important?

Smart contract event listening notifies applications and users in real time that something new has happened in a smart contract.

Where are events used in smart contract applications?

Frontend

If you swap tokens on a website using a AMM DEX smart contract, the token balances will know when to be updated on the frontend almost instantly using events.

Backend

Trading bots can listen to AMM DEX swap contracts events and find potential arbitrage opportunities. IoT robotics applications in the physical world connected to a smart contract can be controlled with events. Chainlink oracle nodes also depend on smart contract events to know when to communicate between the real world and blockchains.

How to listen to smart contract events on Shardeum?

Websockets

We are planning to add websocket RPC URL support in the future to subscribe to smart contract events. This way, users will be able to save API calls instead of polling for new data every new block/bundle/cycle.

Polling

Reading smart contract events can also be done using Shardeum cycles (we listen to blocks/bundles to do this).

Reading events with Shardeum Cycles:

  1. To get the current cycle: get latest block, then divide by 10, and round down.

  2. Build the JSON URL with:

Example with:

startCycle = endCycle = 49
address = 0x23FF65f07cAbAd1643440a0114d71260F2Bb6352

https://explorer-liberty10.shardeum.org/api/transaction?startCycle=49&endCycle=49&address=0x23FF65f07cAbAd1643440a0114d71260F2Bb6352

  1. Filter for transactions per page [note, 10 transactions per page]:

https://explorer-liberty10.shardeum.org/api/transaction?startCycle=49&endCycle=49&address=0x23FF65f07cAbAd1643440a0114d71260F2Bb6352&page=1

JSON URL Filter Variables

?startCycle=lastestCycle
&endCycle=lastestCycle
&address=addressToListenTo
&page=1

Event Listening With Polling Examples:

Reading transaction events from the null address (address(0)) from cycle 0 to 1000:

const axios = require('axios');

let baseUrl = "https://explorer-sphinx.shardeum.org/api/transaction?startCycle=49330&endCycle=49330&address=0x6bd9e67bf927da1935b6eaea9bf22500c4e1f53a"

getTransactionsToAddressCycleRange(baseUrl)

async function readJSONLoop(totalTransactions) {

let total = totalTransactions;
let pageIndex = 1

while ( total > 0 ) {

let filterUrl = baseUrl + "&page=" + pageIndex
console.log(filterUrl)

let responseRawJSON = await axios.get(filterUrl);
responseRawJSON = responseRawJSON.data;
console.log(responseRawJSON);

total -= 10;
pageIndex++;
}

}

async function getTransactionsToAddressCycleRange(baseUrl) {

let responseRawJSON = await axios.get(baseUrl);
let responseDataJSON = responseRawJSON.data;
let totalTransactions = responseDataJSON.totalTransactions
console.log(totalTransactions);

readJSONLoop(totalTransactions)

}

Listening for the latest cycle, which might contain transaction events from an address:

const axios = require('axios');
const ethers = require('ethers')

const rpcURL = "https://liberty20.shardeum.org/"

const provider = new ethers.providers.JsonRpcProvider(rpcURL)

const timeMilliSec = 1000;

listenForCycle()

function timeout(ms) {
return new Promise(resolve => setTimeout(resolve,ms));
}

async function listenForCycle() {
while (true){

console.log("Current cycle (1 cycle = 10 blocks [bundles]) ")
let cycle = await provider.getBlockNumber();
console.log(Math.floor(cycle/10))

let baseUrlCycleAddress = "https://explorer-liberty20.shardeum.org/api/transaction?startCycle=" + cycle + "&endCycle=" + cycle + "&address=0x0000000000000000000000000000000000000000"
console.log(baseUrlCycleAddress)

let responseRawJSON = await axios.get(baseUrlCycleAddress);
let responseDataJSON = responseRawJSON.data;
let totalTransactions = responseDataJSON.totalTransactions
console.log(totalTransactions);

readJSONLoopLatestCycle(totalTransactions,baseUrlCycleAddress)

await timeout(60*timeMilliSec)

}
}

async function readJSONLoopLatestCycle(totalTransactions,baseUrl) {

let total = totalTransactions;
let pageIndex = 1

while ( total > 0 ) {

let filterUrl = baseUrl + "&page=" + pageIndex
console.log(filterUrl)

let responseRawJSON = await axios.get(filterUrl);
responseRawJSON = responseRawJSON.data;
console.log(responseRawJSON);

total -= 10;
pageIndex++;
}

}