Web3.js Discussion

Welcome to the thread about Web3.js. Here you can discuss everything about the Ethereum api and potential problems that you might stumble upon.

2 Likes

Hi there,

In this lesson I couldn’t understand the basics of web3.js properly.
Is there anyone who can explain the app.js file line by line ? How can we initiate the web3.js and how do we create a conection with our contract?

I would be appreciated if you help me.
Thanks in advance.

(function (Contract) {
    var web3;
    var instance;

function init(cb) {
    web3 = new Web3(
        (window.web3 && window.web3.currentProvider) ||
        new Web3.providers.HttpProvider(Contract.endpoint));

    var contract_interface = web3.eth.contract(Contract.abi);
    instance = contract_interface.at(Contract.address);
    cb();
}

function getMessage(cb) {
    instance.message(function (error, result) {
        cb(error, result);
    });
}

$(document).ready(function () {
    init(function () {
        getMessage(function (error, result) {
            if (error) {
                console.error("Could not get article:", error);
                return;
            }
            $('#message').append(result);
        });
    });
});
`})(Contracts['HelloWorld']);`
1 Like

I can walk you through the init function, which is where we initiate web3.

function init(cb) {
    //This instantiates the web3 object. In it's constructor it takes a web3 provider. A provider is a connection the 
    //ethereum network. Could be a local node or for example metamask.  
    web3 = new Web3(
        (window.web3 && window.web3.currentProvider) ||
        new Web3.providers.HttpProvider(Contract.endpoint));

    //Here we create an interface which contains all the functions and events of our contract. We need the abi 
    //string in order for web3 to know the interface of the contract. 
    var contract_interface = web3.eth.contract(Contract.abi);

    //Here we instantiate the contract to a contract running at an actual ethereum address. We use this instance 
    //object to interact with our contract.
    instance = contract_interface.at(Contract.address);
    
    cb();
}
3 Likes

why is cb in the getMessage(cb) ??

function getMessage(cb) {
instance.message(function (error, result) {
cb(error, result);
});
}

I’m not sure if I understand you question. The cb (callback function) is there so that we can call the callback function when we have received the message from our contract. The callback function that is passed in is this. It can be found on row 23 to 28 in the app.js in the video. Let me know if you need any further explanation.

function(error, result) {
    if(error){
        console.log("Could not get article", error);
        return;
    }
    $('#message').append(result);
}
1 Like

Hi Filip,

Is getMessage a promise? How will the function know if there’s an error or result? I don’t see any declaration or expression of what error or result is.

No, instead we are working with callback functions that are passed into the function. Error and results are objects that are returned by the smart contract. If we have a successful execution, error will be null and result will contain the result from the contract.

Hi. I notice in the app.js line 1 writes (function (Contract){
line 32 writes (Contracts[‘HelloWorld’]).
There is a difference of one “s”, does it not matter, when we try to relate these 2 lines together? Thank you. Reference : Superblocks

It is correct. Line 32 is the input that we reference on line 1. Contracts is an array and we input a specific contract in that array into the function starting on line 1. We select the HelloWorld contract as our input by typing Contracts[HelloWorld].

Then on line 1 we have created the function that takes that contract as an input and makes it available to us in the js code. It’s a little bit complicated but I hope you understand it better now. Either way it’s not necessary to understand it 100% since that code is generated automatically by superblocks anyway.

1 Like

Thank you, Filip.:cocktail:

1 Like

So I was reading the code this whole time as if “cb” wasn’t already a defined variable/function. From a quick Google search, it has a built in definition of being a function of saying error or result?

Can you explain how “cb” works, both from a general sense and also how it’s being applied here?

Not really, “cb” is just what we name the input to the function. The input in this case is a function. You can name it whatever you want. You could name it “myFunction” or whatever you want. As long as when you call the function you change cb() to myFunction().

It’s a little bit complicated. But google and research more about callback functions in javascript if you want to learn more.

Filip

I have a question about the getMessage function

function getMessage(cb) {
      instance.message(function (error, result) {
            cb(error, result);
      });
});

My understanding is that instance.message holds the contents of the variable message in the HelloWorld contract. I think that essentially instance.message is just a variable. So I don’t understand why we have a ‘( function (error, result) {
cb(error, result);
})’ following instance.message.Are we saying that instance.message is actually a function that has another function as argument ?
I would think that the getMessage function would look like:

function getMessage(cb) {
      instance.message;
            cb();
}

Thanks

Yes, exactly your first assumption. The instance.message is a function that takes a function (callback function) as an argument.

We can’t access variables in the contract straight away, since the contract and the javascript code is completely separate. So we need so called getter functions to access the variables of the contract. Those will have same name as the variable itself in web3.js, for simplicity reasons.

So when we call the instance.message function, we will make a request to the blockchain to fetch the message variable from the contract. When the blockchain responds back to our contract, which can take a short while, we will execute the callback function. That’s when we know the blockchain has responded to our request and then we can continue our execution.

Why are we using callbacks in the coinflip example instead of promises or observables? Wouldn’t the coinflip app be synchronize due to using callbacks? If it is asynchronous (which means I am misunderstanding something), is it because the web3 methods that expect a cb parameter have async built into that cb parameter?

Cheers

It is asynchronous because we need to make calls to the blockchain, we don’t know how long that will take. So we need to use either callbacks. I think we could use promises as well with web3.js, if you prefer that.

1 Like

Hello, Filip!
After most of the ETH, Solidiy section was passed, I decided to make the homework but encountered some technical difficulties.
The problem was posted on StackOverflow.
I’ll appreciate any help to find the solution.

Which version of web3.js are you running? In my answer here I will assume you are running 1.x.x. Try to replace the line

  window.web3 = new Web3(web3.currentProvider.enable())

with

  web3 = new Web3(web3.currentProvider);

I’m running the web3 version from github I assume it’s the last one.
I’ve already changed this line but got the different type of error

index.html:90 Uncaught TypeError: contractInstance.owner is not a function

it means something wrong with the line Contract instance

window.contractInstance = new web3.eth.contract(abi, myContractAddress)

contractInstance.owner((err, ownerValue) => {
    document.querySelector('#owner-address').innerHTML(ownerValue)
})

and I have no idea what it might be.

Ok, great.

Good, at least we are moving forward :wink: Now I see some errors in your function calling as well. When you call a getter function you need to call it with the call function. You also shouldn’t declare your contract instance in window. And you need to have a capital C when you create the contract instance. Try this:

var contractInstance = new web3.eth.Contract(abi, myContractAddress)

contractInstance.owner.call((err, ownerValue) => {
    document.querySelector('#owner-address').innerHTML(ownerValue)
})

Try this and let me know how it goes. All of this is available in the documentation: https://web3js.readthedocs.io/en/1.0/web3-eth-contract.html#methods-mymethod-call