Building on top of Ethereum has never been easier.Frameworks such as the ever popular Truffle-suite and Embark make it very easy for developers to quickly deploy contracts and interact with them.
These frameworks unfortunately is best suited for testing and experimentation. What happen’s if we want to have a server connect to a blockchain, and then have it interact with Smart Contracts?
Enter Web3. Web3 is a wrapper for Ethereum’s JSON-RPC API. Despite being an abstraction library, it still offers great flexibility and a large deal of complexity.
In this tutorial, we’ll be developing on top of the Quorum network. Quorum is extremely similar to Ethereum, so you’ll find that this guide will work perfectly well with Ethereum as well. I choose Quorum specifically because transactions are near instant, and i don’t need to refill my wallet with test ethers. All transactions are free, so we do not need to get test Ethers.
We’ll split this guide into two sections: Contract Deployment and Contract Interaction.
At Chainstack, you can create your own Quorum Node easily. We have a free trial for 14 days, so hop on over to our console to get started.
If you don’t want to use Quorum, you can connect to your own Ethereum node via Geth or Parity, but you can deploy your own node on Chainstack as well for free :)
Disclaimer (I work for Chainstack)
Let’s prepare a simple Smart Contract called Hello.sol
pragma solidity 0.5.0;
contract Hello {
string text;
event received(
address _received
);
constructor(string memory _text) public {
text = _text;
}
function getText() public view returns(string memory) {
return text;
}
function changeText(string memory _newText) public {
text = _newText;
}
function pay() public payable {
emit received(msg.sender);
}
}
The Hello contract accepts String argument to deploy it. You can also call getText() to get back the string that you set during deployment. To change the text, call changeText() and supply it with your new string :)
Finally, the contract has a payable function called pay(). A payable function is a function that can be sent Ethers to, and then the function is executed. We’ll see how all of this is done using Web3js.
We’ll also assume that you know how to compile and get the bytecode and ABI of the contract. An easy way to do so if to use REMIX, and copy the bytecode and ABI that it provides.
Let’s start by creating a contract instance:
const Contract = web3.eth.Contract(abi)
You have to supply the ABI so Web3 knows the specifications of each function in the Contract.
Next, deploy the contract.
.deploy({
data: contractData.bytecode,
arguments:[title],
})
The deploy function accepts an object. This object contains two things, the bytecode of the contract (which you obtained via REMIX) and the arguments for the constructor.
While this function is called .deploy(), it actually doesn’t deploy the contract to the blockchain. We’ll have to use .send() to finalize this process:
.send({
from: address,
gas: 470000000, //9000000 for Ethereum
gasPrice: 0, // 3000 for Ethereum (3000 wei)
})
.send() also takes in three key objects:
1. From Address
2. Gas Limit (or just Gas)
3. Gas Price
Let’s chain .deploy() and .send() of this together:
contract.deploy({
data: contractData.bytecode,
arguments:[title],
})
.send({
from: address,
gas: 470000000,
gasPrice: 0,
})
This will return a promise, which contains the transaction receipt for the deployment of the Hello contract.
In summary, to deploy a contract you need to:
1. Get the bytecode and ABI of the contract
2. Create a contract instance
3. Include the bytecode and constructor arguments in .deploy()
4. Send it to the blockchain using .send()
Once deployed, the transaction receipt contains the address of the Smart Contract. We’ll need this in the next section.
Contract Interaction is slightly more complicated. The contract has three functions, getText() , changeText() and pay()
Let’s get an instance of the smart contract so your javascript file can interact with it.
const contract = Web3.eth.Contract(ABI,contractAddress)
We’ll have to supply the ABI so web3 knows how to interact with the contract. This time, we supply the contractAddress, so Web3 knows where to send our calls to.
With the contract instance, we can now access the getText() function:
const text = await Contract.methods.getText().call({})
The important thing here is the .methods object. The contract Object exists as a nested Object in javascript, and the function calls are stored in the methods object.
Since getText() is a view function, it does not make any changes to the blockchain. Thus, we chain the the function with .call({}).call() also returns the value in the returns() argument of the function in the Smart Contract, and not the transaction receipt.
How about the changeText() function? Take a look:
Contract.methods.changeText('New Text').send({
from: accounts,
gas: 470000,
gasPrice:0
})
For non-view functions, or rather functions which changes the state of the blockchain, we have to chain it with .send(). Recall how we used .send() during contract deployment. This makes sense because deploying the contract is also changing the state of the blockchain. You’ll get the transaction receipt as the response.
The final function pay() is a function that accepts ether. Let’s see how we can do this using Web3.
Contract.methods.pay().send({
from: accounts,
gas: 470000,
value:1000000000000000000 // in WEI, which is equivalent to 1 ether
gasPrice:0
})
We still chain it with the send() function, but this time we include the value parameter in the object to be sent. This value has to be in wei, and not Ether. So do your conversions accordingly.
But wait, what about payable functions that returns a value? How do we return value but also send it some Ether?
The answer is to use .send() first, and then .call().
That’s it! You’re now an expert in Web3 :P Don’t hesitate to drop me a message.
Website: www.chainstack.com
Console: console.chainstack.com