Assignment - Event

hey Pedro, thanks mate, it feels that I still got a lot to learn though :slightly_smiling_face:

I did actually looked at those Truffle docs before, but I donā€™t see anywhere that you can not deploy to test net or main net. Maybe I donā€™t understand or see something but Filip also deploying to test net at the end of Ethereum Smart Contract Programming 201 and there is no mention of Ganache at all. In fact in the entire course there is no mention about Ganache, I would know as I have completed that course :wink: but actually now Iā€™m not sure and maybe Iā€™m missing something. Iā€™m not actually entirely sure how to deploy to main net, well Filip says its same way as test net but havenā€™t done myself or seen anyone doing it.

2 Likes

Then I donā€™t know! I would be pissed to have been wasting time with Ganache if it is not needed anymore! :joy:
Also took both Ethereum201 old and new. In fact, I started using Ganache in the old Ethereum201 course. Iā€™ve just realized that Filip added a video in the new Eth201 where he deploys the dex on Ropsten, without mentioning Ganacheā€¦
Would be nice if @filip or someone knowledgeable could answer!

1 Like

While we are on topic my question would be. Do we deploy to main net by changing truffle-config.js and uncommenting the same code but insetead inserting mainnet details? If so where do we find those details?

    //Useful for deploying to a public network.
    // NB: It's important to wrap the provider as a function.
    // ropsten: {
    // provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/YOUR-PROJECT-ID`),
    // network_id: 3,       // Ropsten's id
    // gas: 5500000,        // Ropsten has a lower block limit than mainnet
    // confirmations: 2,    // # of confs to wait between deployments. (default: 0)
    // timeoutBlocks: 200,  // # of blocks before a deployment times out  (minimum/default: 50)
    // skipDryRun: true     // Skip dry run before migrations? (default: false for public nets )
    // },
1 Like

This I can answer! Yes, you just un-comment the network that you wanna deploy to, then:

  • truffle migrate --network <network name here>

Eg: truffle migrate --network kovan

But first youā€™ve got to install a wallet provider package: @truffle/hdwallet-provider
And to use an Ethereum node of your choice like Infura or Moralis (or your own).

So basically for the mainnet:

  • get infura/moralis endpoint for the mainnet network, and edit truffle-config.js.
  • Replace ropsten with mainnet, and network id with 1.
  • Then truffle migrate --network mainnet

Just check again the video Deploying our contract to a live network (the last one) on the ETH 201 course, itā€™s up to date and well explained. Wasnā€™t there when I took the course!

1 Like

thanks for that, but the only thing that Iā€™m not sure of is what do you mean uncomment network that I want to deploy to? There is only ropsten network details there and there is advanced and private, so where is main net?

1 Like

Another truffle-config from an older project as example:

networks: {
    // Useful for testing. The `development` name is special - truffle uses it by default
    // if it's defined here and no other network is specified at the command line.
    // You should run a client (like ganache-cli, geth or parity) in a separate terminal
    // tab if you use this network and you must also set the `host`, `port` and `network_id`
    // options below to some value.
    //
    // development: {
    //  host: "127.0.0.1",     // Localhost (default: none)
    //  port: 8545,            // Standard Ethereum port (default: none)
    //  network_id: "*",       // Any network (default: none)
    // },

    // Another network with more advanced options...
    // advanced: {
      // port: 8777,             // Custom port
      // network_id: 1342,       // Custom network
      // gas: 8500000,           // Gas sent with each transaction (default: ~6700000)
      // gasPrice: 20000000000,  // 20 gwei (in wei) (default: 100 gwei)
      // from: <address>,        // Account to send txs from (default: accounts[0])
      // websockets: true        // Enable EventEmitter interface for web3 (default: false)
    // },

    // Useful for deploying to a public network.
    // NB: It's important to wrap the provider as a function.
     ropsten: {
       provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/*******`),
       network_id: 3,         // Ropsten's id
       gas: 5500000,          // Ropsten has a lower block limit than mainnet
       confirmations: 2,      // # of confs to wait between deployments. (default: 0)
       timeoutBlocks: 50,     // # of blocks before a deployment times out  (minimum/default: 50)
       skipDryRun: true       // Skip dry run before migrations? (default: false for public nets )
     },

   //rinkeby: {
      //   provider: () => new HDWalletProvider(mnemonic, `https://rinkeby.infura.io/v3/*******`),
      //   network_id: 4,
      //   gasPrice: 20000000000, // 20 GWEI
      //   gas: 5500000,          // Ropsten has a lower block limit than mainnet
      //   confirmations: 2,      // # of confs to wait between deployments. (default: 0)
      //   timeoutBlocks: 50,    // # of blocks before a deployment times out  (minimum/default: 50)
      //   skipDryRun: true       // Skip dry run before migrations? (default: false for public nets )
      // },

    kovan: {
        provider: () => new HDWalletProvider(mnemonic, `https://kovan.infura.io/v3/*******`),
        network_id: 42,
        gas: 5500000,
        confirmations: 2,     // # of confs to wait between deployments. (default: 0)
        timeoutBlocks: 50,    // # of blocks before a deployment times out  (minimum/default: 50)
        skipDryRun: true      // Skip dry run before migrations? (default: false for public nets )       
    },

    // Useful for private networks
    // private: {
      // provider: () => new HDWalletProvider(mnemonic, `https://network.io`),
      // network_id: 2111,   // This network is yours, in the cloud.
      // production: true    // Treats this network as if it was a public net. (default: false)
    // }
  },
1 Like

So which one is mainnet?

You just replace a few thingsā€¦ Double check the value depending of you contract.

 mainnet: {
       provider: () => new HDWalletProvider(mnemonic, `https://MAINNET.infura.io/v3/****`), //given by infura/Moralis
       network_id: 1,           //MAINNET ID
       gas: 100000,             
       gasPrice: 110000000000,  //110 gwei
       networkCheckTimeout: 10000000,
     }
1 Like

This is working for me but uses deprecated properties which show up as warnings in Firefox console:

index.js
var web3 = new Web3(Web3.givenProvider); 
var instance;
var user;
var contractAddress = "0x21AB46BD9d9dead6C83dd7e37458469467c1c533";


$(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);
                alert( "This here cat is ALIVE!!!" );
        })
        .on('error', console.error);
    })
})



function createKitty(){
    var dnaStr = getDna();

    instance.methods.createKittyGen0(dnaStr).send({}, function(error, txHash){
        if(error)
            console.log(error);
        else
            console.log(txHash);
    })
}

createKitty

function createKitty() {
  var dnaStr = getDna();
  i.methods.createKittyGen0(dnaStr).send({}, function (error, txHash) {
    if (error) {
      console.log(error);
    } else {
      console.log(txHash);
      i.events
        .Birth({}, function (error, event) {})
        .on("data", function (event) {
          console.log(event);
          //event.returnValues
          //0: "0x4B165ec77B7f4aF4ff56EEa6cF469A8BCDa27CC9"
          // 1: "0"
          // 2: "0"
          // 3: "0"
          // 4: "8267413912248741"
          // dadId: "0"
          // genes: "8267413912248741"
          // kittenId: "0"
          // mumId: "0"
          // owner: "0x431...CC9"
        })
        .on("error", function (error, receipt) {
          console.log(error, receipt);
        });
    }
  });
}

Problem connecting to Metamask.

Referring to the ā€œWeb3.js Start Codingā€ video, approximately minute 8/9.

Hi guys, I donā€™t know how to fix this one. My website doesnā€™t prompt Metamask to allow access when I refresh the window. I also cannot consol.log the instance. Hereā€™s my code index.js:

var web3js = new Web3(Web3.givenProvider);

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

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

        console.log(instance);
    })
})

Metamask does not have an option anymore for ā€œconnectionsā€ - at least mine doesnā€™t. I had to change the variable name from web3 to web3js, because otherwise VS Code got confused with the instantiation. Also, the word ethereum (after window.) has three dots underneath it indicating a problem and gives the following alert ā€œProperty ā€˜ethereumā€™ does not exist on type ā€˜Window & typeof globalThisā€™.ts(2339)ā€. I havenā€™t found anything useful online.

Help is appreciated.
Greetz
Em

1 Like

are you using the web3 cdn in your index.html file

Ok, I donā€™t know why, I didnā€™t change anything, but all of a sudden everything works today.
Thanks for reaching out to me (btw, yes, I did import the web3 cdn into my index.html file :slight_smile: )
Greetz

1 Like

Trying to do this with the Moralis backend/server. Was a pretty rough road for me to get to this point, but it seems to work fine. Now that itā€™s running on Moralis, I canā€™t seem to get truffle to sync with Ganache anymore, but it still runs so okay for now I guess.

index.js

const serverUrl = "*Moralis SERVER ID*";
const appId = "*Moralis APP ID*";
Moralis.start({ serverUrl, appId});

let contractInstance;

async function login() {

   try {
     let user = await Moralis.User.current();
     if (!user) {
         user = await Moralis.authenticate({ signingMessage: "Hello World!" });
     }
      console.log(user);
      console.log(user.get('ethAddress'));
      alert("User logged in");
      window.web3 = await Moralis.Web3.enable();
      contractInstance = new web3.eth.Contract(window.abi, "*contract address*");
    }
    catch(error) {
     console.log(error)
   }
}

function createKitty() {
    let dna = getDna();

    contractInstance.methods.createKittyGen0(dna).send({from: ethereum.selectedAddress}, function(error, txHash){
        if(error)
          console.log(error);
        else {
            console.log(txHash);
        }
    })
    contractInstance.events.Birth().on('data', function(event){
        console.log(event);
        let owner = event.returnValues.owner;
        let kittenId = event.returnValues.kittenId;
        let matronId = event.returnValues.matronId;
        let sireId = event.returnValues.sireId;
        let genes = event.returnValues.genes;
        alert("Gen 0  kitty created!\n" + "owner: " + owner + "\nKitten ID: "
        + kittenId + "\nMatron ID: " + matronId + "\nSire ID: " + sireId + "\nGenes: " + genes);

    })
}

$(document).ready(function(){
    login();
})

document.getElementById("create_kitty").onclick = function(){createKitty()};

try command+shift+r ~

1 Like

Hey guys,

Everything works fine in terms of creating a cat and displaying a little popup indicating so with the help of the event listener. But for some reason the dna does not get read and displayed properly - only the first two numbers of the dna string get displayed (dnabody and dnaears). Iā€™ve gone over my code as well as Filipā€™s code on GitHub, just to make sure everything is the same, but still I donā€™t know where the bug lies.

Does anyone know whatā€™s going on?

Hereā€™s my code:

This is the document.ready part where I listen for the birth event and console.log the DNA.

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

        //Creating an instance of the contract
        instance = new web3js.eth.Contract(abi, contractAddress, {from: accounts[0]})

        user = accounts[0];

        console.log(instance)

        instance.events.Birth()
        .on('data', function(event) {

            //Here I console the DNA (genes), but only get a partial value.
            console.log(event.returnValues.genes); 

            alert("Congratulations Em!!! Your cat has been created! And here are all the stats:" + JSON.stringify(event.returnValues, null, 4));

            console.log(event.returnValues);
        })
        .on('error', function(error) {
            console.log(error);
        })

    })
})

And here are the getDNA and the createKitty functions found in catSettings.js

catSettings.js
function getDna(){
    var dna = ''
    dna += $('#dnabody').html()
    dna += $('#dnaears').html()
    dna += $('#dnamouth').html()
    dna += $('#dnaeyes').html()
    dna += $('#dnashape').html()
    dna += $('#dnadecoration').html()
    dna += $('#dnadecorationTopBottom').html()
    dna += $('#dnadecorationMiddle').html()
    dna += $('#dnaanimation').html()
    dna += $('#dnaspecial').html()

    return parseInt(dna)
}

function createKitty() {

    var genes = getDna();

    //Again I console.log out the DNA    
    console.log(genes);

    instance.methods.createKittyGen0(genes).send({}, function(error, txHash) {
        if(error) {
            console.log(error);
        }
        else {
            console.log(txHash);
        } 
    })

}

Regards
Em

@kenn.eth

Hi Kenneth,

So Iā€™ve wanted to change the code in the index.js file so that I connect to Metamask via a ā€œconnect buttonā€ instead of automatically when the page loads. That works fine - I load the page, nothing happens; I click on ā€œconnect walletā€ and I get prompted to connect to Metamask. Afterwards I can create kitties to my heartā€™s conntent and everything is peachy.

The problem comes when I switch to another page (or reload the factory page) and then come back again to the factory page. Whenever I then try and create a cat the createKitty function cannot read the methods, which I think means there is some kind of a lost connection.

This is the error I get:
catSettings.js:169 Uncaught TypeError: Cannot read properties of undefined (reading ā€˜methodsā€™)
at createKitty (catSettings.js:169)
at HTMLButtonElement.onclick (factory.html:176)

Is there a way to maintain the contract instance (which includes the methods) in such a way that when I reload the page I can continue creating kitties after Iā€™ve connected using the ā€œconnect buttonā€?

Hereā€™s my code:

creatKitty()
function createKitty() {

    var genes = getDna();

    //BTW, for some reason my genes/DNA only shows the first two values. Any idea why?
    console.log(genes);

    instance.methods.createKittyGen0(genes).send({}, function(error, txHash) {

        if(error) {
            console.log(error);
        }
        else {
            console.log(txHash);
        }
    })
}
index.js
var web3js = new Web3(Web3.givenProvider);

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

$(document).ready(function() {

    //I've temporarily commented out the functionality so as to use the connect button functionality instead
    /*window.ethereum.enable().then(function(accounts) {
        
        //Creating an instance of the contract
        instance = new web3js.eth.Contract(abi, contractAddress, {from: accounts[0]})
        user = accounts[0];
        console.log(instance)        

        instance.events.Birth()
        .on('data', function(event) {

            //Here I console the DNA (genes), but only get a partial value.
            console.log(event.returnValues.genes); 

            alert("Congratulations Em!!! Your cat has been created! And here are all the stats:" +
            JSON.stringify(event.returnValues, null, 4));

            console.log(event.returnValues);
        })
        .on('error', function(error) {
            console.log(error);
        })        
    })*/
})

function connect() {

    window.ethereum.enable().then(function(accounts) {

        //Creating an instance of the contract
        instance = new web3js.eth.Contract(abi, contractAddress, {from: accounts[0]})

        user = accounts[0];

        console.log(instance)

        instance.events.Birth()
        .on('data', function(event) {

            //Here I console the DNA (genes), but only get a partial value.
            console.log(event.returnValues.genes); 

            alert("Congratulations Em!!! Your cat has been created! And here are all the stats:" + 
            JSON.stringify(event.returnValues, null, 4));

            console.log(event.returnValues);
        })
        .on('error', function(error) {
            console.log(error);
        })

    })
}

I hope Iā€™ve made sense.
Regards
Em

2 Likes

@Emmerich i would say when you reload the page metamask connection breaks and and web3 isnt loaded hence thats why your contrtc is undefined. maybe you have to connect everytime you relod. its had to tell becuse you dont have much code ther to goo off. i would say this is the case because you are enabling web3 only in that connect() function so you will need to clock the button each time you refresh.

I have a solution for that im just thinking of now. So you could get thw account o fthe person your currently using the app with. Then make an if check on page load then compares the last last address who was using the app with the current acount logged in in metamask. If they are not the same then require that the user clocks the connect button. Otherwise load web3 as normal on page load. If you want to go with something like this let me know and i will cod eit out im just finishing up college and ill see what i can do. I probably wont use jQuery because i hate using jquery for initing web3 async functions are much better IMO

1 Like

Hey @Emmerich ! In order to check the error in you code I need to have the full version. Can you please upload it to a github repository and share it?

About the connection with metamask, you can use cookies to remember if the user is loggedin before and is the same account, you let metamask connection automatic, otherwise you leave it like manual by displaying the connect button.

@mcgrane5

Hey, thanks for the response. Connecting every time I reload does work, but obviously thatā€™s not what I want. Iā€™ll try the idea you suggested - the if check to see which address is currently connected. If I get stuck Iā€™ll come back to you.

Just in case, hereā€™s my GitHub repository of this: https://github.com/EmmerichS/HelloKitties

Take care Em

1 Like