1

I have the following (very simple) oracle contract. All I want it to do is manage data on the chain that is returned by an open source API - I'll use this data in another contract. I am able to call the methods of my contract without any issue using web3js, but I am unable to listen for events on a socket. I should be seeing console.log('Event firing ', event) output something, but I do not. If helpful, I am running ganache and truffle locally to host the contract

When I hit the http://localhost:3000/api/oracle endpoint, I get the following (source code below the output). Can someone help me understand why I'm not capturing the events correctly?

[0] 9:36:44 AM - Found 0 errors. Watching for file changes.
[1] Running on 3000 ⚡
[1] Endpoint called
[1] Contract response Done
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

contract SnapshotOracle {
  // Contract owner
  address public owner;

  string[] public voters;

  // Callback function
  event CallbackGetVotes(address owner);

  constructor() {
    owner = msg.sender;
  }

  // This is called first, which emits an event
  // that fetches new data
  function updateVotes() public returns (string memory) {
    emit CallbackGetVotes(owner);
    return "Done";
  }

  // Once the data is fatched by the service,
  // setVotes is called to set that data
  function setVotes(string[] memory _voters) public {
    require(msg.sender == owner);
    voters = _voters;
  }

  // Finally, getVotes is called to get the new data
  function getVotes() public view returns (string[] memory) {
    return voters;
  }
}
// Simple Node oracle service to interact with oracle contract
import express, { Express, Request, Response } from 'express';
import bodyParser from 'body-parser';
import helmet from 'helmet';
import dotenv from 'dotenv';

import Web3 from 'web3'
import OracleContract from './contracts/SnapshotOracle.json'
import { AbiItem } from 'web3-utils'

dotenv.config();

const PORT = process.env.PORT || 3000;
const app: Express = express();

app.use(helmet());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

// Web socket to contract
const CHAIN_PORT = '7545' 
const ORACLE_ADDR = '0x05dbB4b1C895C593b66686b5234D3cD80D18E460'
const web3 = new Web3(`ws://127.0.0.1:${CHAIN_PORT}`)
const oracleContract = new web3.eth.Contract(OracleContract.abi as AbiItem[], ORACLE_ADDR)

web3.eth.getAccounts((err, accounts) => {
  const a = oracleContract.events.CallbackGetVotes({owner: accounts[0]})
  .on('data', (event: any) => {
    console.log('Event firing ', event)
    // TODO: Run API Request
    // TODO: Save result of API request to contract state
  })
})

app.get('/api/oracle', (req: Request, res: Response) => {
  const web3 = new Web3(`http://127.0.0.1:${CHAIN_PORT}`)
  const oracleContract = new web3.eth.Contract(OracleContract.abi as AbiItem[], ORACLE_ADDR)
  console.log('Endpoint called')

  web3.eth.getAccounts(async (err, accounts) => {
    const t = await oracleContract.methods.updateVotes().call({owner: accounts[0]})
    console.log('Contract response', t)

    setTimeout(async () => {
      const votes = await oracleContract.methods.getVotes().call()
      res.send(votes)
    }, 3000)
  })
});

app.listen(PORT, () => console.log(`Running on ${PORT} ⚡`));

1 Answer 1

1

The problem is that you aren't creating a transaction oracleContract.methods.updateVotes().call() is calling updateVotes as view function. You have to use .send instead.

const t = await oracleContract.methods.updateVotes().send({owner: accounts[0]})
console.log("Transaction receipt: ", t)
1
  • Got it, makes a ton of sense, thank you Commented Dec 30, 2021 at 16:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.