Do something on smart contract event

Hi, Iā€™d like to make a little script that monitors, at best via websockets a specific smart contract event, when that event occurs, I wanna call the smart contract and do something on it. Of course this could have been done better, but Iā€™m in the situation that I need to do exactly as I explainedā€¦

I donā€™t care to sync past events, I need to monitor from the moment I start my script (itā€™s a nodejs command line program).

Does Moralis offer such a functionality to subcribe to a specific smart contract event, and when that occurs I run the code I want, say a function called doSomething() and if yes, is there some code sample for it? Thank you

1 Like

you can do a combination of synching a smart contract event and running a trigger on afterSave or beforeSave for that event

https://docs.moralis.io/moralis-server/automatic-transaction-sync/smart-contract-events#sync-and-watch-contract-events

https://docs.moralis.io/moralis-server/cloud-code/triggers#aftersave

hey @cryptotester. you dont need moralis fo rthis im sure they probably do provide some functionality as @cryptokid shows above. Yeah you need to use a websocket provider if you want to constantly monitor real time events as they are emitted but in node you can simply just run code such as this

const Web3 = require("Web3")
var web3;

const provider = new Web3.providers.WebsocketProvider("INFURA_ENDPOINT_GOES_HERE")
web3 = new Web3(provider);
contract = new web3.eth.Contract(Contractabi, contractAddress);

async function mainScript() {
    
    contract.events.eventName({}).on("data", (data) => {
      
          try {

                //do stuff each time your script detects the required event


           } catch (err) {

                console.error(err)
           }
    })

}

mainScript()

you just need to make an instance of whatever the contract is that has the event you need to subscribe to. Then subscribe to the particular event by calling contract.events and using specificying th eevent youwant then when yoyr script detects the event execute whatever code you wsnt. The above code is very general and i dont know what your specific use case but if you want more of a specifc example cosider the case where you want to get real time price feeds from uniswap. Uniswap has a sync event that is emitted when the uniwap reserves for some token pair is updates. so if you subscribe to this event each time you can get real time price data. consider the code below

const UniswapV2Pair = require("../build/contracts/IUniswapV2Pair.json");
const Web3 = require('web3');
var web3;

const provider = new Web3.providers.WebsocketProvider("INFURA_ENDPOINT_GOES_HERE")
web3 = new Web3(provider);

module.exports = { web3http, web3ws }
// define address of Pair contract
const DaiWethPairAdd = "0xa478c2975ab1ea89e8196811f51a7b7ade33eb11";

// create web3 contract object
const unisswapPairContract = new web3ws.eth.Contract(UniswapV2Pair.abi,  DaiWethPairAdd );

// reserve state
const state = {
    token0: undefined,
    token1: undefined,
};

const mainWSS = async () => {
    // fetch current state of reserves
    [state.token0, state.token1] = const _reserves = await uniswapPairContract.methods.getReserves().call();

    // subscribe to Sync event of Pair
    uniswapPairContract.events.Sync({}).on("data", (data) => updateState(data));

    // calculate price and print
    console.log(`Price ${DAI WETH} : ${state.token0 / state.token1}`)
};

const updateState = (data) => {
    // update state
    state.token0 = data.returnValues.reserve0) / 10 ** 18; //convert from wei 
    state.token1 = data.returnValues.reserve1 / 10 ** 18; //convert from wei
    state.blockNumber = data.blockNumber;

    // calculate price and print
    console.log(`Price ${DAI WETH} : ${state.token0 / state.token1}`)
}

mainWSS();

when you call main() the prices will update each time the sync event is fired. Again not sure what your specific example is but with the genral example above and this specific one for uniswap price data you should be able oto get some ideas

4 Likes

thanks for helping @mcgrane5!!

1 Like

hahhah no worries, whenever i can my g!! @ivan

This was very helpful.

1 Like

Thank you mcgrane5 I appreciate the answer! I think Iā€™ll give it a try very soon. In my case itā€™s really something much easier than that, but Iā€™ll keep in mind also the uniswap monitoringā€¦ soon or later I may need something like that too who knows :wink:

Is @cryptokid ā€˜s reference to Moralis documentation useful as well? I mean, the advantage of Moralis is (when available/supported) to write less code and to achieve the ā€œsameā€ (but depending on Moralisā€™ server).

As I got a nice boilerplate from mcgrane5 I think Iā€™ll try that first.

If there is a boilerplate to achieve this using moralis, itā€™s very welcome.

Thanks to both for your prompt replies, yo @ivan fun to see you in this thread too, now that I have something to work on, I had my coffee so I guess I can GO GO GO GO GO GO (like the song) :wink:

2 Likes

Hay @cryptotester. Im very sure it is although you will find lots of good tips and trips in there if you take a while to give it a read.

Hey @mcgrane5 I tried to implement your solution only to find out (actually not find) that on Fantom (didnā€™t specify but I was assuming all ethereum clones work kinda similarly) there is no websocket providerā€¦

So in the end I got my thing working with in a rudimentary while loop, like:

while (true)  {
  await myContractCall().then(x => {
    if (myCondition) { doSomething() }
  })
  await sleep(waitSeconds)
}

Not the best, but get what Iā€™m trying to achieve doneā€¦ if by chance you know there is websocket support on fantom, let me know. But I searched and didnā€™t find itā€¦

If you go to infura.io, you will notice (after adding the various add-ons, which are free if you use the free tier with 100k requests/day) that there is no wss also for polygon, nor for arbitrum, nor for optimism. I was quite surprised to discover thisā€¦ looks like they prefer devs to bomb their servers with requests, rather than connecting via wssā€¦ lolā€¦

1 Like

hey @cryptotester. this is something i did not know. as ive neevr used Fantom I could suggest maybe switching provider to alchemy and see if they support Fantom and also have a wss endpoint or even try flashbots to see if they support Fantom. That is annoying its probably because they are a lesser used chain. I would also recomment try useing the regular https endpoint but specificy web3.webSocketProvider. Something like this

const provider = new Web3.providers.WebsocketProvider(put your http endpoint here)
web3 = new Web3(provider);

it could be worth a try.

no this wont work as the node script will finish and not keep listenting i quickily tried it on th code i had above. That is a shame. try google for Fantom providers with WSS. At least you do have something that works albeit it not the most desirable option. yeah i would first check alchemy to see what they have