Deploying the smart contract

At this point we’ve successfully implemented and tested our smart contract so we’re ready for going live. You may still want to test your contract on a real blockchain or maybe your application is a proof of concept and you want to stay cost free, so we’re going to deploy our application on a testnet.

I have picked Ropsten, but Rinkeby or any other should be fine too. Feel free to drop me a line with your experiences with testnets on the comments.

Our first step is getting some ether on our Metamask account so we can afford deploying and invoking our contract. In order to avoid being attacked or flooded by malicious users, testnets funds are sent to accounts on request and they’re usually capped after a few requests a day. You can request ether from any faucet, but I’ve personally tested the following:

Faucets will basically send ether to your account on request up to a limit. Limits and transferred amounts usually depend on the faucet.

The next step is adding a new network on Truffle so we can easily access it using Truffle commands. In order to add the Ropsten network, simply modify the base truffle.js file and add the new network there. Keep in mind we’ll be attaching an HDWalletProvider in order to allocate funds from our Metamask account and the Infura API as target in order to avoid deploying a local testnet node to deploy our contract.

Note: There’s a known bug that causes Metamask to only be able to use the first wallet under the account. Keep it in mind in case you’re handling multiple wallets with your account.

Multiple wallets under the same Metamask account

Now that we’ve added the network to Truffle, we can deploy our contract by running truffle migrate — network ropsten.

As you can see on the logs above, you’ll be provided with a contract hash that will be your contract’s identity within the blockchain — you can see it on the line Chat: 0xff36b43Cc46e8726dbefA3A03102259ec7D90552. Do not forget this hash, as you’ll need it in order to use your contract. On another hand, Truffle will also build your contract locally, generating the interface’s ABI JSON file — do not loose this file as you’ll need it to invoke the contract via Web3js.

You can also see our deployed contract using Ropsten’s block explorer and our contract hash here.

On the next sections we’ll use the deployed contract via Truffle queries and we’ll implement a very simple Web3js client.

Querying the contract from Truffle

Now that we’ve successfully deployed our smart contract on the Ropsten testnet, we may want to validate that everything is working properly, or we might just want to check the data stored on our contract or execute some transaction.

Again, we’ll be using Truffle in order to create the requests and submit them to the testnet. Let’s take a loot at the example:

On the example, we export a function with the requests to execute. We’ve implemented a room creation function, a find rooms function and a find room details function, and we’ll be calling those just to validate everything works as expected.

As an important note, pay attention to the callback function that’s being passed into our function; we must invoke this function to let Truffle know we’re done the Node process will get stuck.

Finally, we will use Truffle exec to run our queries file pointing at the Ropsten network:

truffle exec queries\queries.js --network ropsten

Query execution logs

Implementing a NodeJS client for the contract

Last but not least we’ll be using Web3js to implement an Ethereum client based on NodeJS.

We’ll begin by creating a smart contract utils function that will create a Web3js connector instance we can share across our application. Said connector looks like this:

As in the previous example, we’ll need the contract hash, but we’ll also need the contract’s ABI interface in order to invoke it — as a reminder, the ABI JSON file is generated during the contract compilation. Remember not to loose it!

A really important method to take a look at on the smart contract util implementation is sendSignedTransaction. This method will replace the send method used in our tests since invoking a real Ethereum network will have us sign our transactions. Since we’re using Infura to avoid creating our local network node as an entry to the network, we have to manually sign our transaction.

In order to sign our transaction, we’ll allocate the gas prices from Eth Gas Station and we’ll generate a nonce which will be used as the unique transaction number for a given wallet. Once we’ve allocated both values, we’ll generate the transaction parameters, containing gas limit, gas price, target network identifier (chainId), destination contract, eth value transferred (if any, this can be used to pay for payable functions or simply to transfer eth between accounts) and the transaction data. Finally, we’ll sign the transaction with our account’s private key and send the transaction using Web3js.

We can find our Metamask account private key on the plugin, by clicking on “Details” and then on “Export private key”.

Metamask private key export feature

Once we’re set with our smart contract connector, we’ll start implementing our service. We want to be able to expose every use case provided by the smart contract to any NodeJS process — this may range from some sort of maintenance CLI tool to a REST API powered by anything ranging from Express to Koa.

Just like during the tests, we can use either call or sendSignedTransaction to invoke the smart contract; also just like before, call will not persist changes on the blockchain — and we won’t have to pay for said transactions — while sendSignedTransaction will persist changes — and we will have to pay for those, so choose wisely!

There’s also a difference on the return objects since call will return the data specified on the smart contract while send will return a transaction receipt with the submitted transaction data. There’s parse methods on the client that will transform the data into our expected data models that we can persist or return as an API response.

It’s also worth noting that we must provide a caller— which basically happens to be our account — when we use call, while the sendSignedTransaction method will deal with generating the caller, gas price and gas limit values to be used as we previously saw.