DEV Community

Cover image for Blockchain in practice with Land Registry System in Laravel
Abdur Rahman
Abdur Rahman

Posted on • Updated on

Blockchain in practice with Land Registry System in Laravel

In this article, I will summarize how to build a blockchain-based land registry application. This should help you to grasp the basics of blockchain application and make your hand dirty with building a practical application with Laravel and Ethereum.

What is Blockchain?

According to Wikipedia
"A blockchain, originally blockchain is a growing list of records, called blocks, that are linked using cryptography."
Sounds a little complex? No problem, Same happened to me when I read this definition first time.

Let's make our life easier. Break it down. Blockchain consists of two words 'Block' and 'Chain'. In easier language, Blockchain is a chain of blocks one after another where blocks keep information. So, it just a chain of information. An example makes it even easier.
Let's say you and your friend Jhon have two bank accounts with no balance

  • You deposit $100 to your account
  • You transfer $20 to John's account
  • After a few days, Jhon return the $20 to your account

Imagine each of these transactions is stored in a single block and formed a chain sequentially. So, we have three blocks in our blockchain which are not altered by anyone. If you understand this, you've understood the tough definition we start with.

Why build a Land Registry System in blockchain?

When it comes to decide why we blockchain, there are a lot of resources available on the internet. To make it simple, I would put a few points on why we decided to build the system in the blockchain.

  • The system needs assurance of no data alteration once a land registration, ownership transfer, etc are recorded to system.
  • Security of the system
  • Decentralized. Hence, multiple copies of the same data exist to everyone.

Tools we need

  • Ganache
  • Truffle
  • Metamask
  • Solidity js
  • Knowledge of basic Javascript etc.

What is Smart Contract?

In general, a contract is an agreement between parties with some rules and penalties. Both parties should obliged and abide by the rules or accept penalties.
A smart contract is the digital version of this agreement. It controls digital assets or currencies transfer according to an agreement. We will use solidity.js to write our smart contract for the land registry system. So, our smart contract will say what we can do with the blockchain application.

What is solidity?

Solidity is an object-oriented, high-level language for implementing smart contracts. We will use solidity to build our smart contract. You shouldn't find it difficult if you have a basic idea of Javascript.

What is Truffle?

Truffle is a development environment, testing framework and asset pipeline for Ethereum, aiming to make life as an Ethereum developer easier. With truffle, you can compile, test and deploy your smart contract to a test network.

What is Ganache?

Ganache is a personal blockchain. This is a great tool to test your Etherum smart contract without spending a penny. Using ganache you can test the application with having to interact with public blockchain which would cost you money to deploy the smart contract.

What is MetaMask?

MetaMask is a chrome extension for accessing Ethereum enabled distributed applications or "Dapps" in your browser! This will enable us to use our application from the browser.

Before we move on,
This blog is inspired from here.
I will just summarize the main points here. If you require further clarification on the smart contract you may have a look at this.

Ok, cool!
Lots of what is questions.

Now let's have a look at our smart contract code

pragma solidity ^0.5.0;

contract LandRegistry {
  uint public totalRegistered = 0;
  struct Township {
    uint id;
    uint townshipId;
    uint owner_nid;
    string owner_name;
    string owner_address;
    string owner_father_name;
    string owner_mother_name;
  }

  mapping(uint => Township) public townShips;

  constructor() public {

  }

  function registerTownShip(
    uint townshipId,
    uint owner_nid,
    string memory owner_name,
    string memory owner_address,
    string memory owner_father_name,
    string memory owner_mother_name
  ) public {
    totalRegistered++;
    townShips[totalRegistered] = Township(
      totalRegistered,
      townshipId,
      owner_nid,
      owner_name,
      owner_address,
      owner_father_name,
      owner_mother_name
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Now compile the above code with Truffle.

truffle compile
Enter fullscreen mode Exit fullscreen mode

if everything goes well, you shouldn't see any compilation error.

"Ok, my code compiled without any error.
I understand this is a class containing methods. And created a structure that will hold a single land registry entry and an array that holding all the registered array in it."

But, what is townshipId here?

Well, the township is a piece of land that uniquely identified with a code. We will pass this townshipId to specify the land to be registered which stored in our centralized database. Although I prefer the list of townships to be in the smart contract, for simplicity I just stored them in our central database.

Time to connect to the test network.
Now, we want to connect with the ganache personal blockchain and see all blockchain transactions, wallet addresses and so on.

Have a look at this tutorial for more details

We need to deploy the smart contract to blockchain to use it.

truffle migrate
Enter fullscreen mode Exit fullscreen mode

this will deploy the smart contract to the test network. if you open ganache, you will see a few addresses open on the network along with some test coins.

I have created the application on Laravel. All the code of this application including the smart contract will be found here
I am not gonna give every detail of building Laravel application as you may go through the github repository to look at everything.
Rather, I will focus on how the application communicates with blockchain.

To understand how our application will interact with blockchain we should know a little about ABI(Application Binary Interface)
When you compile smart contract, bytecode generated and which pushed to Ethereum storage. This is what smart contract representation on Ethereum. Now, the problem is, how would we interact with bytecode and call the smart contract functions from there which is next to impossible?

this is where the ABI comes into play.
The ABI is a .json file that describes the deployed contract and its functions. This will allow us to communicate with the smart contract as this has all the definitions of smart contract functions, data types, variables, etc. When we compile the smart contract, respective ABI files(.json) are generated inside the build folder.
Now, this the file we work within our Laravel application. We call the smart contract functions like register land, total registration, etc. through the ABI file.

We will put the ABI file in our Laravel application.

Let's move forward to understand the javascript functions which connect to meta mask, ABI and interact with the smart contract to solve the purpose.

loadWeb3: async () => {
        if (typeof web3 !== 'undefined') {
            App.web3Provider = web3.currentProvider
            web3 = new Web3(web3.currentProvider)
        } else {
            window.alert("Please connect to Metamask.")
        }
        // Modern dapp browsers...
        if (window.ethereum) {
            window.web3 = new Web3(ethereum);
            try {
                // Request account access if needed
                await ethereum.enable();
                // Acccounts now exposed
                web3.eth.sendTransaction({/* ... */})
            } catch (error) {
                // User denied account access...
            }
        }
        // Legacy dapp browsers...
        else if (window.web3) {
            App.web3Provider = web3.currentProvider
            window.web3 = new Web3(web3.currentProvider)
            // Acccounts always exposed
            web3.eth.sendTransaction({/* ... */})
        }
        // Non-dapp browsers...
        else {
            console.log('Non-Ethereum browser detected. You should consider trying MetaMask!')
        }
    }
Enter fullscreen mode Exit fullscreen mode

The loadweb3 function assigns the appropriate provider to communicate to the blockchain. Please make sure you have installed MetaMask extension in your chrome browser.

loadAccount: async () => {
        // Set the current blockchain account
        App.account = web3.eth.accounts[0];
    }
Enter fullscreen mode Exit fullscreen mode

This loadAccount function sets the default account for the blockchain.

loadContract: async () => {
        // Create a JavaScript version of the smart contract
        const landRegistry = await $.getJSON('contract/LandRegistry.json')
        App.contracts.LandRegistry = TruffleContract(landRegistry)
        App.contracts.LandRegistry.setProvider(App.web3Provider)

        // Hydrate the smart contract with values from the blockchain
        App.landRegistry = await App.contracts.LandRegistry.deployed()
    }
Enter fullscreen mode Exit fullscreen mode

This function loads the smart contract JSON file and enables js to interact with all smart contract functions. So, this will mainly help us to access functions for registering land, getting total registrations, get a list of registered lands, etc.

render: async () => {
        await App.renderAllTransactions();
        await App.renderRecentTransactions();
    },
    renderRecentTransactions: async () => {
        const townships = await fetch('/api/townships')
            .then((resp) => resp.json())
            .then(function(data) {
                return data;
            });

        const totalRegistered = await App.landRegistry.totalRegistered();
        const townShipTemplate = $('#recentTransactions');

        for (var  i = totalRegistered.toNumber(); i >= 1; i--) {
            // Fetch the task data from the blockchain
            const townShip = await App.landRegistry.townShips(i);
            let townshipId = await townShip[1].toNumber();
            let owner_name = await townShip[3];
            let owner_address = await townShip[4];
            let owner_father_name = await townShip[5];
            let owner_mother_name = await townShip[6];
            let created_at = await townShip[7].toNumber();
            let townShipData = App.getTownshipByCode(townships, townshipId);

            // Create the html for the task
            let townShipItem =
                `<div class="col-md-4">
                <div class="card mt-4">
                    <div class="card-body">
                        <h4 class="card-title"><strong><i class="fa fa-calendar text-muted" aria-hidden="true"></i> ` + moment.unix(created_at).format("DD-MM-YYYY h:mm:ss") + `</strong></h4>
                        <h5 class="card-title">#`+ townShipData.code +`</h5>
                        <p>
                            <i class="fa fa-area-chart text-muted" aria-hidden="true"></i> `+ townShipData.area +` sqft <br>
                            <i class="fa fa-map-marker text-muted" aria-hidden="true"></i>  ` + townShipData.location + `
                        </p>

                        <hr>

                        <h6 class="card-subtitle mb-2"><span class="text-muted">Owner:</span> `+ owner_name +`</h6>
                        <h6 class="card-subtitle"><span class="text-muted"><i class="fa fa-map-marker" aria-hidden="true"></i> </span> ` + owner_address + `</h6>
                    </div>
                </div>
            </div>`;

            // Show the task
            townShipTemplate.append(townShipItem)
        }
    },

    renderAllTransactions: async() =>  {
        const townships = await fetch('/api/townships')
        .then((resp) => resp.json())
        .then(function(data) {
            return data;
        });

        const totalRegistered = await App.landRegistry.totalRegistered();
        const townShipTemplate = $('#allTransactions > .row');

        for (var  i = totalRegistered.toNumber(); i >= 1; i--) {
            // Fetch the task data from the blockchain
            const townShip = await App.landRegistry.townShips(i);
            let townshipId = await townShip[1].toNumber();
            let owner_name = await townShip[3];
            let owner_address = await townShip[4];
            let owner_father_name = await townShip[5];
            let owner_mother_name = await townShip[6];
            let created_at = await townShip[7].toNumber();
            let townShipData = App.getTownshipByCode(townships, townshipId);

            // Create the html for the task
            let townShipItem =
            `<div class="col-md-4">
                <div class="card mt-4">
                    <div class="card-body">
                        <h4 class="card-title"><strong><i class="fa fa-calendar text-muted" aria-hidden="true"></i> ` + moment.unix(created_at).format("DD-MM-YYYY h:mm:ss") + `</strong></h4>
                        <h5 class="card-title">#`+ townShipData.code +`</h5>
                        <p>
                            <i class="fa fa-area-chart text-muted" aria-hidden="true"></i> `+ townShipData.area +` sqft <br>
                            <i class="fa fa-map-marker text-muted" aria-hidden="true"></i>  ` + townShipData.location + `
                        </p>

                        <hr>

                        <h6 class="card-subtitle mb-2"><span class="text-muted">Owner:</span> `+ owner_name +`</h6>
                        <h6 class="card-subtitle"><span class="text-muted"><i class="fa fa-map-marker" aria-hidden="true"></i> </span> ` + owner_address + `</h6>
                    </div>
                </div>
            </div>`;

            // Show the task
            townShipTemplate.append(townShipItem)
        }
    },

    registerLand: async (data) => {
        let townshipId = $('[name="townshipId"]').val();
        let owner_nid = $('[name="owner_nid"]').val();
        let owner_name = $('[name="owner_name"]').val();
        let owner_address = $('[name="owner_address"]').val();
        let owner_father_name = $('[name="owner_father_name"]').val();
        let owner_mother_name = $('[name="owner_mother_name"]').val();

        // await App.landRegistry.registerTownShip(Number(townshipId), Number(owner_nid), owner_name, owner_address, owner_father_name, owner_mother_name)
        await App.landRegistry.registerTownShip(Number(townshipId), Number(owner_nid), owner_name, owner_address, owner_father_name, owner_mother_name);
        alert('Successfully registered the land.')
    },

    getTownshipByCode: (townships, id) => {
        return townships.find(function (townShip) {
            return townShip.id === id;
        })
    }
Enter fullscreen mode Exit fullscreen mode

And finally, the above code is all about rendering registered lands, register land, etc on our webpages.

Ok, so far we have gone through basics of blockchain stuff and two main things of our land registry application.

I have this github repository which has all the codes for smart contract and the Laravel application.
You are free to make a pull request, play around with the files and learn things.

Note: This is a pet project, the purpose of this project to learn the basics of a blockchain application and put it in practice. So, I didn't focus on best practices, proper naming, performance, etc.

Thank you.

Top comments (20)

Collapse
 
muhaimenul profile image
Muhaimenul Islam • Edited

Thanks for this beginner friendly article. It really helped me a lot to quick start hands on blockchain development. I highly appreciate it. The guideline and references are really useful for me. Finally, I got some clear idea regarding blockchain development.

Collapse
 
abdurrahmanriyad profile image
Abdur Rahman

Thank you

Collapse
 
sanika28 profile image
Sanika Tomar

There is a problem when I register the Land details, It does not show any Option to select the Id. On inspecting I get this "LandRegistry has not(truffle-contract.js:456) been deployed to a detected network (network/artifact mismatch)". What should I do in order to solve this?

Collapse
 
cricspass profile image
cricspass

Yes Can you guide! I am getting the same problem as well!

Collapse
 
ryanarcel profile image
Ryan Arcel Galendez

Good day. Sorry for being such a noob but how can I run this application? I tried "php artisan serve" but it does not run. Thank you.

Collapse
 
abdurrahmanriyad profile image
Abdur Rahman

Ryan Arcel Galendez, thanks for reaching out.

You need to set up MetaMask and Ganache and all the tools mentioned on the blog.
Also, please let me know what error you see.
If you still face any problem, I am here to help you.
Thank you.

Collapse
 
ryanarcel profile image
Ryan Arcel Galendez

I have already set up Metamask and Ganache. When I "php artisan serve" it, I got an error. Apparently it is looking for a /vendor/autoload.php file.

Thread Thread
 
abdurrahmanriyad profile image
Abdur Rahman

Then you might not run "composer install"

Collapse
 
yeshigyelts profile image
Yeshi

Hello Abdur, I have downloaded your project and everything is working well. I would like to know if it is possible to build a blockchain app without requiring metamask i.e. signing the transactions by backend. I do not want my end-users to go through the process of downloading the extension and configuring it.

Collapse
 
henober profile image
Henober

Hello dear friend thanks for your explanation. I have installed every tools and compiled and migrate the smart contract into ganache and view new address transaction! however after i browse and login the Laravel application on browser with metamask. when i try to insert data on land registry form and i click submit nothing doesn't come . i think its the Laravel application is not inserting data to the blockchain network ? what should i do

Collapse
 
abdurrahmanriyad profile image
Abdur Rahman

Not sure.
There could be multiple reasons.
May be your metamask wallet doesn't have enough gas to make a transaction.
Or may be you are not properly connected with Ganache.
Please play more with it, it should be working.
If you still fail, do let me know I will try to help you.
Thanks

Collapse
 
paulchase profile image
Paul Ajonye

Is there video format for this tutorial?

Collapse
 
abdurrahmanriyad profile image
Abdur Rahman

Sorry.
No.

Collapse
 
francimaina profile image
francimaina

I have installed and set up all the required apps but when i try to truffle compile and migrate it does not work what could be the challenge

Collapse
 
maccladder profile image
maccladder

Hi i have this error when i try to register a land. i see it in the console. please enlighten me!
Image description

Collapse
 
agilulfo1820 profile image
Dan Rusnac

Hi, I'm looking at your code but don't see where are you using the ABI and how you are using Laravel to interact with the smart contract (eg: taking the new data)

Collapse
 
abdurrahmanriyad profile image
Abdur Rahman

Please refer to js files in the public/js folder.
The following is responsible for communicating with ABI and Laravel view file to do the mentioned functionalities.

github.com/abdurrahmanriyad/blockc...

Collapse
 
rakib09 profile image
Rakibul Hasan

Very nice article.
I appreciate it. After reading this blog my confusion about smart contact is much clear.
thanks for this post.

Collapse
 
abdurrahmanriyad profile image
Abdur Rahman

Thank you very much.
This will inspire me to write on in the future.

Collapse
 
emmatosin profile image
emmatosin

Help. It's not running here