Assignment - Event

Tried this a bunch of times, but maybe my computer is just slow in updating. I’ll wait for a while and hope it does update. Thank you

Hey man, it still doesn’t work after a few hours (issue with python server).

Left: Python
Right: Live server (VS code)

image

1 Like

It’s only with python server? :face_with_monocle:

If the Live Server from VS code is working, i might advice to use that one instead, hope it does not show any issue in the future.

Carlos Z

1 Like

Yup, it’s only on the python server. I’m using the live server right now so I can follow through with the course lessons, Thanks, man!

1 Like

Please see my code below:

$( document ).ready(function() {
  $('#NewKitty').on('click', function() {
      instance.methods.createKittyGen0(getDna()).send({},function(error, txHash){
      if (error){
        console.log(error);
      }
      else {
        console.log(txHash);
      }
    });
  })
});

hey @vili any error on this code?

@kenn.eth @Samuel1 @Mariano_Collarte @ol_frank

Error: Uncaught TypeError: Cannot read property ‘enable’ of undefined

Solution: Just access the frontend web page (index.html) through the python server(1) http://localhost:8000/ instead of opening the html file directly.

(1) To start the python server, run python3 -m http.server 8000 inside the client folder.

I hope this will help some people :slightly_smiling_face:

3 Likes

my code is not generating an error, however, when I run this not getting any txHash output

function CreateNewKiddy() {

  //using call contract function enabled by web3 call setup in index.js
  instance.methods.createKittyGen0(getDna()).send({},function(error, txHash) {
       if (error)
           console.log(error);
       else {
           console.log(txHash);
       }
   })
  console.log(instance.methods.ownerOf(0));
  console.log(instance.methods.totalSupply());
}


//if someone clicks the 'Create Cat' button, creates new cat
$('#create_cat').click(function(){
  console.log("creating kiddy");
  CreateNewKiddy();
})

everything works except ‘instance.methods.totalSupply().call()’ is returning NaN!

function CreateNewKiddy() {

    var theDNA = getDna();
  
    //using call contract function enabled by web3 call setup in index.js
    instance.methods.createKittyGen0(theDNA).send({},function(error, txHash) {
         if (error)
             console.log(error);
         else {
             console.log(txHash);
           instance.events.Birth(user,instance.methods.totalSupply().call() - 1,0,0,theDNA);
           console.log(instance.methods.ownerOf(0).call());
           console.log(instance.methods.totalSupply().call());
           alert("new birth! id " + instance.methods.totalSupply().call() - 1 + " owner: " + user + " DNA: " + theDNA);
  ;       }
     })
  
  }

Hello, this is my code:

$(document).ready(function(){
   window.ethereum.enable().then(function(accounts){
    instance = new web3.eth.Contract(abi, contractAddress, {from: accounts[0]})   
    user = accounts[0];

    console.log(instance);

    instance.events.Birth()
      .on("data", event => console.log(event))
      .on("error", console.error);
   })
})
1 Like

I’ve created a button which calls connectMetamask(). This function also sets up the event listeners for on-chain events.

Code

index.js
const web3 = new Web3(Web3.givenProvider);

const KITTIES_CONTRACT_ADDRESS = "0xc6A42C7dfbB9BF8eD2F86b59117Bb550eE65160C";

let userAddress;
let kittiesContract;

$(document).ready(function () {
  if (typeof window.ethereum !== "undefined") {
    console.log("MetaMask is installed.");
  } else {
    console.error("MetaMask is inaccessible.");
    return;
  }

  // set up MetaMask event listeners
  ethereum.on("accountsChanged", function (accounts) {
    userAddress = undefined;
    console.warn(
      "MetaMask account has been changed. Please reconnect MetaMask."
    );
    $("#connect-metamask-btn").show();
  });
});

async function connectMetamask() {
  if (typeof window.ethereum == "undefined") {
    alert("MetaMask is inaccessible.");
    return;
  }

  $("#onchain-alert").empty();

  // will start the MetaMask extension
  const accounts = await window.ethereum.request({
    method: "eth_requestAccounts",
  });
  userAddress = accounts[0];

  if (accounts.length > 0) {
    console.log("Connected MetaMask.");
    $("#connect-metamask-btn").hide();
  } else {
    // user canceled connection request
    return;
  }

  // load contracts
  kittiesContract = new web3.eth.Contract(
    abiKitties,
    KITTIES_CONTRACT_ADDRESS,
    { from: userAddress }
  );

  // set up contract event listeners
  kittiesContract.events
    .Birth()
    .on("connected", function (subscriptionId) {
      console.log("connected!", subscriptionId);
    })
    .on("data", function (event) {
      console.log("data!", event);
      const kittyId = event.returnValues.kittyId;
      const mumId = event.returnValues.mumId;
      const dadId = event.returnValues.dadId;
      const genes = event.returnValues.genes;
      const owner = event.returnValues.owner;
      const transactionHash = event.transactionHash;
      onchainAlertMsgSuccess(
        `<strong>Birth Event!</strong>
        kittyId: ${kittyId}, mumId: ${mumId}, dadId: ${dadId}, genes: ${genes}, owner: ${owner},
        transactionHash: ${transactionHash}`
      );
    })
    .on("changed", function (event) {
      console.log("changed!", event);
    })
    .on("error", function (error, receipt) {
      console.error("error!", error);
    });
}

async function createKitty() {
  $("#onchain-alert").empty();
  try {
    const res = await kittiesContract.methods
      .createKittyGen0(getDNAString())
      .send();
    return res;
  } catch (err) {
    console.error(err);
    onchainAlertMsgWarning(
      `<strong>createKitty:</strong> Failed. ${
        userAddress === undefined
          ? "Please connect MetaMask!"
          : "See console for details!"
      }`
    );
  }
}

function onchainAlertMsgSuccess(msg) {
  onchainAlertMsg("success", msg);
}

function onchainAlertMsgWarning(msg) {
  onchainAlertMsg("warning", msg);
}

function onchainAlertMsg(type, msg) {
  const alertHtml = `
    <div
    class="alert alert-${type} alert-dismissible fade show text-start"
    role="alert"
    >
    ${msg}
    <button
      type="button"
      class="btn-close"
      data-bs-dismiss="alert"
    ></button>
    </div>
  `;

  $("#onchain-alert").html(alertHtml);
}

HTML part
<!-- Buttons -->
<div class="row justify-content-center">
  <div class="col-lg-4 m-2 d-flex justify-content-between">
    <button
      type="button"
      class="btn btn-primary light-b-shadow"
      onclick="defaultKitty()"
    >
      <b>Default Kitty</b>
    </button>
    <button
      type="button"
      class="btn btn-primary light-b-shadow"
      onclick="randomKitty()"
    >
      <b>Random Kitty</b>
    </button>
  </div>
  <div class="col-lg-6 m-2 d-flex justify-content-end">
    <button
      type="button"
      class="btn btn-success light-b-shadow"
      onclick="createKitty()"
    >
      <b>Create Kitty</b>
    </button>
  </div>
</div>
<!-- On-chain Alert Message -->
<div class="row justify-content-center">
  <div id="onchain-alert" class="col-lg-10 m-2"></div>
</div>

Hey @apmfree make sure that your totalSupply function is public in other to call it. If is declare as private in the contract it will only be accessible from the contract.

Thank you for posting this :slight_smile:
This helped unstuck me.

2 Likes

hey community ,I can not show genes function , is there something wrong with my smart contract ? I could not get gene number when I created first item with truffle console either that’s why I thought maybe something wrong with contract.Thank you so much

/// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

import "./IERC721.sol";
import "../node_modules/@openzeppelin/contracts/access/Ownable.sol";

contract Kittycontract is IERC721, Ownable{
    
    uint256 public constant CREATION_LIMIT_GEN0 = 10;
    string constant _tokenName = "CryptoKitties";
    string constant _tokenSymbol = "NFCaT";

    event Birth(
        address owner,
        uint256 kittenId,
        uint256 mumId,
        uint256 dadId,
        uint256 genes
    );

    struct Kitty{
        uint256 genes;
        uint64 birthTime;
        uint32 mumId;
        uint32 dadId;
        uint16 generation;
    }

    Kitty[] kitties;

    mapping(address => uint256) ownershipTokenCount;
    mapping(uint256 => address) public kittyindexToOwner;

    uint256 public gen0Counter;



    function createKittyGen0(uint256 _genes) public onlyOwner returns (uint256) {
        require(gen0Counter < CREATION_LIMIT_GEN0);

        gen0Counter++;
        
        return _createKitty(0, 0, 0, _genes, msg.sender);
    }

    function _createKitty(
        uint256 _genes,
        uint256 _mumId,
        uint256 _dadId,
        uint256 _generation,
        address _owner
    ) internal returns (uint256){

        Kitty memory _kitty = Kitty({
            genes: _genes,
            birthTime: uint64(block.timestamp),
            mumId: uint32(_mumId),
            dadId: uint32(_dadId),
            generation:  uint16(_generation)
        });
    
       kitties.push(_kitty);

       uint256 newKittenId = kitties.length - 1;

       emit Birth(_owner, newKittenId, _mumId, _dadId, _genes);

       _transfer(address(0), _owner, newKittenId);

       return newKittenId;
    }

    function getKitty(uint256 _id) external view returns (
        uint256 genes,
        uint256 birthTime,
        uint256 mumId,
        uint256 dadId,
        uint256 generation
    )
    {
        Kitty storage kitty = kitties[_id];

        birthTime = uint256(kitty.birthTime);
        mumId = uint256(kitty.mumId);
        dadId = uint256(kitty.dadId);
        generation = uint256(kitty.generation);
        genes = kitty.genes;
    } 
        

    function balanceOf(address owner) external override view returns (uint256 balance){
        return ownershipTokenCount[owner];
    }

    function totalSupply() public override view  returns (uint256 total){
        return kitties.length;
    }

    function name() external override pure returns (string memory){return _tokenName;}

    function symbol() external override pure returns (string memory){return _tokenSymbol;}

    function ownerOf(uint256 tokenId) external view override returns (address){
        return kittyindexToOwner[tokenId];
    }

    function transfer(address _to, uint256 _tokenId) external override{
        require(_to != address(0), "Cannot send tokens to this address");
        require(ownershipTokenCount[msg.sender]>0, "Not enough tokens");
        require(kittyindexToOwner[_tokenId]==msg.sender, "You must own the token");
    
        _transfer(msg.sender, _to, _tokenId);
    }

    function _transfer(address _from, address _to, uint256 _tokenId) internal {

        ownershipTokenCount[_to]++;
        kittyindexToOwner[_tokenId] = _to;
        
        if(_from !=address(0)){
        ownershipTokenCount[_from]--;

        }
        emit Transfer(_from, _to, _tokenId);
    }
}

gene problem

Hi,
I am experiencing some weird caching issue with ‘python3 -m http.server 8000’.
Cannot see the changes made from the code in the browser.

Does anyone know how to clear cache for python3 server?

UPDATE:
clearing browser cache solves the issue. But this is really not an optimal solution. There needs to be a way to force python to not write to cache in the first place.

Many thanks

1 Like

as you can see here by returnvalues does not matter which DNA I have , it shows always zero

gene problem1

Another trick is also to refresh the page + cleaning cache, in chrome for example you do it through ctrl + F5 , sometimes the changes are not visible through the cache issue between the browser and webserver (python), cleaning cache or restarting the webserver does the trick most of the times.

Carlos Z

Hey @aliekber1976, hope you are ok.

Please share your project through a github repository so i can review it and replicate the issue from my side, a suggestion i can do is to review if your createKitty function from your contract does receive the genes, also check the function that sent the arguments to the contract (Create button probably calls this web3 function to sent the data to the contract).

Carlos Z

Hey Thank you so much for responding fast.

here is my codes on github

https://github.com/aliekber1976/CloneCryptoKitties

Check the order of the parameters in your createKittyGen0 function, it might be that you are sending them in the wrong way.

image

Carlos Z

2 Likes