Unable to listen to Solidity event in Vue app

Viewed 203

I'm trying to reproduce the ethereum.org's Cryptozombie tutorial using a local environment composed of a local Hardhat node and a Vue.js application.

In my Solidity contract, I defined an event and emitted it when creating a new Zombie.

I was able to link my ethereum wallet and exchange some ETH between accounts using Metamask, but in my Vue app, when I try to listen to my event, nothing is showed in console.

Here is the Solidity code of my contract ...

//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

import "hardhat/console.sol";

contract ZombieFactory {
    
    event NewZombie(uint256 zombieId, string name, uint256 dna);

    struct Zombie {
        string name;
        uint256 dna;
    }

    uint256 dnaDigits = 16;
    uint256 dnaModulus = 10 ** dnaDigits;
    
    Zombie[] public zombies;

    function createRandomZombie(string memory _name) public {
        uint256 dna = _generateRandomDna(_name);
        _createZombie(_name, dna);
    }

    function _createZombie(string memory _name, uint256 _dna) private {
        zombies.push(Zombie(_name, _dna));
        uint256 zombieId = zombies.length - 1;
        emit NewZombie(zombieId, _name, _dna);
    }

    function _generateRandomDna(string memory _str) private view returns (uint256) {
        uint256 rand = uint256(keccak256(abi.encodePacked(_str)));
        return rand % dnaModulus;
    }
}

... and here is the code of my Vue app made of two components : App.vue ...

<template>
  <img alt="Vue logo" src="./assets/images/logo.png">
  <CryptoZombie v-if="ethereum" />
</template>

<script>
import CryptoZombie from './components/CryptoZombie.vue'

export default {
  name: 'App',
  components: {
    CryptoZombie
  },
  data() {
    return {
      ethereum: undefined,
    }
  },
  mounted() {
    const { ethereum } = window
    
    if (typeof ethereum !== 'undefined') {
      this.ethereum = ethereum
    }
  }
}
</script>

... and CryptoZombie.vue :

<template>
  <div class="hello">
    <h1 style="text-align: center">Welcome to CryptoZombie</h1>
    <button v-if="typeof account === 'undefined'" @click="connectWallet">Connect your wallet</button>

    <div v-if="account">
      <p class="text-align: center">Now connected with account <code>{{ account }}</code></p>

      <div>
        <input type="text" v-model="zombieName">
        <button @click="createZombie(zombieName)">Mint zombie !</button>
      </div>
    </div>
  </div>
</template>

<script>
import Web3 from 'web3'
import { abi as ZombieFactoryAbi } from '../assets/utils/ZombieFactory.json'

export default {
  name: 'CryptoZombie',
  data: () => {
    return {
      zombieName: undefined,
      account: undefined,
      contract: undefined
    }
  },
  methods: {
    async createZombie(_zombieName) {
      await this.contract.methods.createRandomZombie(_zombieName).call()
    },
    async connectWallet() {
      let accounts = await this.$parent.ethereum.request({method: 'eth_requestAccounts'})
      this.account = accounts[0]
    }
  },
  async mounted() {
    const web3 = new Web3(this.$parent.ethereum)
    
    if (this.$parent.ethereum.isConnected()) {
      await this.connectWallet()
    }

    let zombieFactoryContract = new web3.eth.Contract(ZombieFactoryAbi, '0x5fbdb2315678afecb367f032d93f642f64180aa3')

    zombieFactoryContract.events.NewZombie()
      .on('data', console.log)
      .on('error', console.error) 
    
    this.contract = zombieFactoryContract

    this.$parent.ethereum.on('accountsChanged', (accounts) => {
      this.account = accounts[0]
    })
  }
}
</script>

Event listener is defined in the mount() method of the CryptoZombie component. When I click the button to call createZombie method, I see in hardhat console that the contract have been called, but I can't see anything in firefox console :/

Anyone could help me here ?

0 Answers
Related