Assignment - Event

Got issues running your code. You are importing interface contract without all functions I think.
It is compiling good to you?
2021-04-29_17h05_34

1 Like

indeed, you should try to start the python webserver and check it :nerd_face:

Carlos Z

Hi guys, kinda hitting a wall here :frowning:. I canā€™t get the whole metamask/web3 dealiou to work.

Full project files : https://github.com/KilianZumFelde/kitties/tree/main/academy-kitties-template-master

My troubleshoot:
Ganache seems to be set up right: The contract address from within the truffle console is the same as in ganache, and assigned to variable ā€œcontractaddressā€.
image
image

Address accounts [0] is also getting charged with ETH correctly:
image

And also within metamask:
image
image
Now, it says there ā€œnot connectedā€, and when I click on it, it tells me to ā€œclick on the connect button of the siteā€, which doesnā€™t exist.
image
To understand, metamask has to be connected both to the ā€œfront end siteā€, and to the ganache test blockchain right?

I can connect manually from within metamask, but that doesnā€™t make much of a difference.
image
Python server running:
image
Some ā€œcode 404ā€ problem, which Iā€™m happily ignoring :blush:.
image
Pasting the code here, maybe if there is something obvious:

var web3 = new Web3(Web3.givenProvider);
var contractaddress ="0x10bBA64aa4Cbe4a2819E18eda4477aeF3b975378";
var instance ;
var user ;


$(document).ready(function(){
  
window.ethereum.enable().then(function(accounts){

    instance = new.web3.eth.Contract(abi, contractaddress, {from: accounts[0]});
    user = accounts[0];


}).then( function(){
    instance.events.catbirth().on('data', function(event){
        alertstring = "Kitten born with following properties: id: " + event.returnValues.id +
        ", mumId: " + event.returnValues.motherID + ", dadId: " + event.returnValues.fatherID + ", genes: " +
        event.returnValues.DNA + ", Generation: " + event.returnValues.Generation + "birthtime;"+ event.returnValues.birthtime;
        console.log(alertstring);
        alert(alertstring);
    })
    })
})

$('#createCatButton').click(() =>{
  var DNA = getDna();
    //account[1] as input to send the cat, just for testing
    instance.methods.createKittyGen0(DNA, accounts[1]).send({}, function(error, txHash){
    if (error){
      alert("Cat creation failed!")
    }
    else{
      alert("Cat creation data sent with dna :" + DNA.toString())
    }
  })
})

It seems whatever I do, metamask/web3 couldnā€™t care less :frowning:. Help much appreciated!!

Hey @KZF, the connection is : Metamask with your contract, and you pull this connection using web3.
You always need ganache testnet up and running and if in metasmask looks like connected, thats it. If you can query contract information using .call() functions, means it is working.

Let me know if you could solve it and if not, send me a screen shoot of error.

I simply used js alert this time.

index.js

//initialize web3 library, connect to Ethereum blockchain
var web3 = new Web3(Web3.givenProvider);

//contract instance
var instance;
var user;
var contractAddress = "0x67A44d76Ef018047CC778773bf6AA550e3040f99";

//after page loads
$(document).ready(()=>{
  window.ethereum.enable().then((accounts)=>{ //after login
    //contract instance
    instance = new web3.eth.Contract(abi, contractAddress, {from: accounts[0]}); 
    //almost always accounts[0]
    user = accounts[0]; 

    console.log(instance);
  })
})

//.send is required when state variables are modified
function createKitty(){
  dnaStr = getDna();
  console.log(dnaStr);
  instance.methods.createDoraemonGen0(dnaStr).send({}, (error, txHash)=>{
    if(error){
      console.log(error);
    }else{
      console.log(txHash);
      instance.once('Birth', (error, event) => {
        if(error){
          alert("Error");
        }else{
          console.log(JSON.stringify(event, null, "    ")); 
          alert(`
            Successfully created Doraemon \n
            owner: ${event.returnValues.owner} \n
            genes: ${event.returnValues.genes} \n
            ID: ${event.returnValues.doraemonId} \n
            mumID: ${event.returnValues.mumId} \n
            dadID: ${event.returnValues.dadId} 
          `);
        }
      });
    }
  });
}

1 Like

Iā€™m getting a transaction error every time I try to call the create method. I donā€™t see much details about the error, I only see an error in the metamask when it opens after I click the create button. No errors in the console of dev tools. I think it should be related to web3, at least when I use truffle console I can use the create method without any issues. Anyone knows why Iā€™m seeing this error?

web3_error

index.js

var web3 = new Web3(Web3.givenProvider); // url for the network. givenProvider will use the provider metamask sends

var instance;
var user;
var contractAddress = "0x61FB7AEd5350F3C9EF43CB087C6dcb6ABedA57e8";

$(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);
    })
})

function createPig() {
    var dnaStr = getDna();
    instance.methods.createPiggyGen0(dnaStr).send({}, function(error, txHash) {
        if(error)
            console.log(error);
        else
            console.log(txHash);
    })
}

PiggyContract.sol

pragma solidity ^0.8.4;

import "./IERC721.sol";

contract PiggyContract is IERC721 {

    string public override constant name = "Piggy";
    string public override constant symbol = "PGY";
    uint256 public constant CREATION_LIMIT_GEN0 = 10;

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

    Piggy[] private piggies;

    uint256 public gen0Counter;
    
    mapping(uint256 => address) private piggyIndexOwner;
    mapping(address => uint256) private ownershipTokenCount;

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

    function createPiggyGen0(uint256 _genes) public {
        require(gen0Counter < CREATION_LIMIT_GEN0);

        gen0Counter++;

        // Gen0 have no owners they are own by the contract
        _createPiggy(uint32(0), uint32(0), uint16(0),  _genes, msg.sender);
    }

    function _createPiggy(
        uint256 _mumId,
        uint256 _dadId,
        uint256 _generation,
        uint256 _genes,
        address _owner
    ) private returns (uint256) {
        Piggy memory _piggy = Piggy ({
            genes: _genes,
            birthTime: uint64(block.timestamp),
            mumId: uint32(_mumId),
            dadId: uint32(_dadId),
            generation: uint16(_generation)
        });

        piggies.push(_piggy);
        uint256 newPiggyId = piggies.length -1;

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

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

        return newPiggyId;
    }

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

    function totalSupply() external override view returns (uint256 total) {
        return piggies.length;
    }

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

    function transfer(address to, uint256 tokenId) external override {
        require(to != address(0)); // non zero address
        require(to != address(this)); // not sending to the owner
        require(_ows(msg.sender, tokenId)); // currenct address is the owner of the token

        _transfer(msg.sender, to, tokenId);
    }

    function _transfer(address _from, address _to, uint256 _tokenId) internal {
        ownershipTokenCount[_to]++;
        piggyIndexOwner[_tokenId] = _to;

        if (_from != address(0)) {
            ownershipTokenCount[_from]--;
        }
        
        emit Transfer(_from, _to, _tokenId);
    }

    function _ows(address _claimant, uint256 _tokenId) internal view returns (bool) {
        return piggyIndexOwner[_tokenId] == _claimant;
    }

    function getPiggy(uint256 piggyId) external view returns (
        uint256 genes,
        uint256 birthTime, // use uint265 because is easier to read in the frontend than smaller values
        uint256 mumId,
        uint256 dadId,
        uint256 generation,
        address owner
    )
    {
        Piggy storage _piggy = piggies[piggyId]; // user storage instead memory to use a pointer, instead copy everything to memory

        genes = _piggy.genes;
        birthTime = uint256(_piggy.birthTime);
        mumId = uint256(_piggy.mumId);
        dadId = uint256(_piggy.dadId);
        generation = uint256(_piggy.generation);
        owner = piggyIndexOwner[piggyId];
    }

}

I have the full code here

This error mostly happen because not using the owner account of the contract. Please make sure that you are using the same account that you use to deploy. Let me know if is that, otherwise try to deploy and test in Remix because will get a better explination of the error.

Iā€™ve tried on remix, but it works

remix_create

Iā€™ve deployed everything again. here are the logs from truffle migrate:

2_token__migration.js
=====================

   Replacing 'Migrations'
   ----------------------
   > transaction hash:    0x54de0695f8aab4a5112f055395cf6d4a1d5a55bdd9231e8d1826219eeca18558
   > Blocks: 0            Seconds: 0
   > contract address:    0xB472D658d3c95dE49B351949ee4240435c867dE7
   > block number:        7
   > block timestamp:     1621182473
   > account:             0x5861750ffd1Ad89CfF25699b04FC1668e1dD3918
   > balance:             99.95117052
   > gas used:            288100 (0x46564)
   > gas price:           20 gwei
   > value sent:          0 ETH
   > total cost:          0.005762 ETH


   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:            0.005762 ETH


Summary
=======
> Total deployments:   2
> Final cost:          0.02350664 ETH

Iā€™ve updated the contract address in the index.js:

var contractAddress = "0xB472D658d3c95dE49B351949ee4240435c867dE7";

And Iā€™ve added the wallet address 0x5861750ffd1Ad89CfF25699b04FC1668e1dD3918 on metamask:

metamask

I still get the same error:

metamask_error

Iā€™ve discovered what was the issue. I was using the wrong contract address in the index.js. When I was copying the migrations deploy file to a new file to deploy the contract, by mistake I replaced the contract name in the original migrations file instead of replacing it in the new file, so I was copying and pasting to the index.js the address from migration contract instead my contract

2 Likes

I think is on this way
My code

image

main.js

var web3 = new Web3(Web3.givenProvider);
var contractInstance;

$(document).ready(function() {
    window.ethereum.enable().then(function(accounts){
      contractInstance = new web3.eth.Contract(window.abi, "0xc7E8420a2715fB2474963279AD91e57fcE2998e3", {from: accounts[0]});
      console.log(contractInstance);
      console.log("Its working");
    });  
});


function createCat() {
  var configDeposit = {value: web3.utils.toWei('0.1', "ether")}
  var DNA = getDna();
  contractInstance.methods.createKittyGen0(DNA).send(configDeposit, function(error, txHash) {
        if(error)
            console.log(error)
        else 
            console.log(txHash)
            
  }); 
  contractInstance.once('Birth', function(error, event){ //listener
        if(event) {
            console.log(event)
            alert("kitty Created")
        }
        else
            console.log(error)
    
  });

}

1 Like

Here is the error I am getting. MetaMask is prompting me to connect to the side, I definitly added the correct account from my Ganache into metamask because it says i have 200000 ether. When I click generate Token it DOES NOT prompt my metamask. all it does it give me the error shown.

image

let web3 = new Web3( Web3.currentProvider|| "HTTP://127.0.0.1:9545");

var instance;
var user;
var contractAddress = "0xe8Df0487839eD64b8F4e64602c576C822bFaF539";

$(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', function(event){
            console.log(event);
            let owner = event.returnValues.owner;
            let kittenId = event.returnValues.kittenId;
            let mumId = event.returnValues.mumId;
            let dadId = event.returnValues.dadId;
            let genes = event.returnValues.genes;
            $('#kittyCreation').css("display", 'block');
            $('#kittyCreation').text(
                "owner: "+ owner + "KittyId " + kittenId + "momId: "+ momId + "dadId: "+ dadId + "Genes:" + genes
            )

        })
            .on('error', console.error); 
    })
})

$('#genToken').click(()=>{
    createKitty()
    console.log("gen button pressed")
 })

 function createKitty(){
    var dnaStr = getDna();
    console.log(dnaStr);
    instance.methods.createKittyGen0(dnaStr).send({}, function(err, txHash){
        if (err){
            console.log(err)
        } else {
            console.log("Kitty create msg sent with txHash: " + txHash)
        }
        //console.log("owner: "+ owner + "KittyId " + kittenId + "momId: "+ momId + "dadId: "+ dadId + "Genes:" + genes)

    });
 }

My computer will not let me download the Zip file. Stating that I have to pay a $50 subscription, is there any other way to get web3.min.js???

Hai
The other way to download web3 file is to use npm
npm install web3
Then simply link web3.min.js to your HTML file like this
<script src="../node_modules/web3/dist/web3.min.js"></script>

2 Likes

I got it. Now I keep getting an enable error.

Can someone help?
image



var web3 = new Web3(Web3.givenProvider);
var instance;
var user;
var contractAddress= "0x2B8E03da2969DEe2133111118f1eB884539c7b6e";

$(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);
  })  
})
async function _createOrder() {
    var getOrder = getOrder();
    console.log(getOrder);
    await instance.methods._createOrder(getOrder).send({}, function(error, txHash){
        if(error){
            console.log(error);
        } else {
            console.log(txHash);
            alert("Order Request sent!");
            instance.event.OrderMade({}, function(error, event){
                if(error){
                    alert("Failure in Order Process!");
                } else {
                    console.log(event);
                    alert("Order successful!");
                }
            });
        }

    })
}

1 Like

I think the enable method is deprecated in the latest version.
You can do like this:

const accounts = await window.ethereum.request({method: "eth_requestAccounts"});
const instance = new web3.eth.Contract(abi, contractAddress, { from: accounts[0] });

Note: in order to use await, the function must be async.

2 Likes

So when now I am getting an error that I cannot use document.request or document.ready



var web3 = new Web3(Web3.givenProvider);
var instance;
var user;
var contractAddress= "0x2B8E03da2969DEe2133111118f1eB884539c7b6e";

$(document).request(async function() {
const accounts = await window.ethereum.request({method: "eth_requestAccounts"});
    const instance = new web3.eth.Contract(abi, contractAddress, {from: accounts[0]});
    user = accounts[0];

    console.log(instance);
  });  

async function _createOrder() {
    var getOrder = getOrder();
    console.log(getOrder);
    await instance.methods._createOrder(getOrder).send({}, function(error, txHash){
        if(error){
            console.log(error);
        } else {
            console.log(txHash);
            alert("Order Request sent!");
            instance.event.OrderMade({}, function(error, event){
                if(error){
                    alert("Failure in Order Process!");
                } else {
                    console.log(event);
                    alert("Order successful!");
                }
            });
        }

    })
}
![image|403x125](upload://97BmNpUBGL3QKbiaJkmp6scBsuc.png) 
1 Like

I keep getting this error for the linking of my MetaMask
image



let web3 = new Web3(Web3.givenProvider);
let instance;
let user;
let contractAddress= "0x2B8E03da2969DEe2133111118f1eB884539c7b6e";

$(async function() {
const accounts = await ethereum.request({method: "eth_requestAccounts"});
    instance = new web3.eth.Contract(abi, contractAddress, {from: accounts[0]});
    user = accounts[0];

    console.log(instance);
  });  

async function _createOrder() {
    
    var getOrder = getOrder();
    console.log(getOrder);
    await instance.methods._createOrder(getOrder).send({}, function(error, txHash){
        if(error){
            console.log(error);
        } else {
            console.log(txHash);
            instance.once('OrderMade',(error, event) => {
                if(error){
                    alert("Failure in Order Process!");
                } else {
                    console.log(JSON.stringify(event, null, " "));
                    alert(`Creation Successful \n
                    owner: ${event.returnValues.owner} \n
                    id:${event.returnValues.orderVolumeId}\n
                    cost:${event.returnValues.cost} \n
                    productName:${event.returnValues.productName} \n
                    description:${event.returnValues.description} \n
                    leadTime_in_days${event.returnValues.leadTime_in_days}\n
                    `);
                }
            });
        }

    });
}

Update here is the proof of update on MetaMask:
image
image

So update, the warning is still there. My MetaMask is connected and the an instance is created in MetaMask once I create an order but there is no instance for the contract. My question is does there have to be an instance of the entire contract? If so, is the problem I am having related to deprecation warning?

Code:



let web3 = new Web3(Web3.givenProvider);

let order;

let accounts;

let instance;

let user;

let contractAddress= "0x2B8E03da2969DEe2133111118f1eB884539c7b6e";

$(async function() {    

    accounts = await window.ethereum.request({method: "eth_requestAccounts"}).catch((err)=> {

        console.log(err.code);

    })

    instance = new web3.eth.Contract(abi, contractAddress, {from: accounts[0]});

    user = accounts[0];

    instance.message.OrderMade();

    console.log(instance);

  });  

const _createOrder = async () => {

    order = await window.ethereum.request({method: 'eth_requestAccounts'}).catch((err) => {

        console.log(err.code);

    })

    console.log(order);

}

Instance

you can download it directly from https://github.com/ChainSafe/web3.js/tree/v1.3.4
There is the code and can also use CDN.