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 ?