Creating a Decentralized Mortgage Platform Using CELO

Introduction

A mortgage platform is an internet-based system or service that simplifies the process of obtaining a mortgage for borrowers, lenders, and other participants in real estate deals. It acts as a centralized platform where borrowers can submit mortgage applications, lenders can assess and authorize applications, and all parties can work together on the required paperwork and procedures. The platform usually includes automated underwriting, document organization, electronic signature capabilities, and communication channels to make the mortgage application and approval process more efficient.

Introduce CELO as a Platform for Building Decentralized Applications

CELO is a platform that enables developers to easily construct decentralized applications (DApps). It offers a secure and expandable environment for developing and implementing solutions based on blockchain technology. By using CELO, developers can take advantage of the advantages offered by blockchain, such as transparency and decentralization, to create innovative and inclusive applications.

To ensure scalability and compatibility, CELO utilizes a distinctive consensus mechanism called Proof-of-Stake with Threshold Encryption (PoS-TEE). This mechanism enables fast transaction processing, minimal delays, and smooth interaction with other blockchain networks. In summary, CELO provides a strong foundation for constructing decentralized applications that have the potential to revolutionize industries and empower communities.

Understanding Mortgage Platforms

Mortgage platforms are digital platforms that streamline the process of mortgage lending by bringing together borrowers, lenders, and other relevant parties. These platforms create an online marketplace where borrowers can submit their loan applications, and lenders can assess and consider these applications. By utilizing technology, mortgage platforms enhance the efficiency and convenience of the mortgage process for everyone involved.

Prerequisites

During this tutorial, we will guide you through creating the mortgage system on Celo. It is essential that you have a solid grasp of both react.js and solidity fundamentals. Rest assured, we will provide explanations for the solidity and react code we employ in the process.

Requirements

In this article, we will utilize the following components to develop the Mortgage DApp:

  • React-Celo
  • Celo contractkit
  • Solidity + Web3js
  • Remix EVN
  • Node.js version 10 or higher
  • MetaMask wallet

After reading this article, you will acquire a thorough comprehension and mastery of utilizing the Celo ContractKit. This software package simplifies the creation of applications on the Celo blockchain by providing convenient methods to interact with smart contracts and enabling the development of decentralized applications (dApps).

In this tutorial, we will utilize React-Celo, a framework specifically designed for constructing Celo blockchain dApps using ReactJs. It offers pre-built components and tools that streamline the development workflow and simplify integration with wallet connectivity.

Building a Mortgage Platform with Solidity

In this section, we will examine the Mortgage Dapp that was developed for this article. Our implementation relies on React-celo and Celo ContractKit. Prior to delving into the details, let us first explore the solidity code, which holds great significance in this context.

Solidity code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

contract MortgageContract {
    address admin;
    uint256 publicArrayIndex;
    struct MortgageData {
        address ownerAddress;
        string lenderName;
        string lenderDescription;
        uint256 minimumAmount;
        uint256 maximumAmount;
        uint256 loanTerms;
        string products;
        string startDate;
        uint256 interestRate;
        uint256 balance;
    }
    MortgageData[] internal MortgageDataArray;

    // Create Morgage array
    function createMortgage(
        address ownerAddress,
        string memory lenderName,
        string memory lenderDescription,
        uint256 minimumAmount,
        uint256 maximumAmount,
        uint256 loanTerms,
        string memory products,
        string memory startDate,
        uint256 interestRate
    ) public {
        uint256 _balance;
        MortgageData memory newData = MortgageData(
            ownerAddress,
            lenderName,
            lenderDescription,
            minimumAmount,
            maximumAmount,
            loanTerms,
            products,
            startDate,
            interestRate,
            _balance
        );
        MortgageDataArray.push(newData);
    }

    // Viwing created mortgages
    function viewMortgages() public view returns (MortgageData[] memory) {
        return MortgageDataArray;
    }

    // Lender Deposit
    function depositFunctionForLender(uint256 _index) external payable {
        require(
            _index < MortgageDataArray.length,
            "Your index is greater than the array length"
        );
        uint256 oldBlance = MortgageDataArray[_index].balance;
        MortgageDataArray[_index].balance = oldBlance += msg.value;
    }

    // Lender withdraw
    function withdrawFunctionForLender(
        uint256 _amount,
        uint256 _index,
        address payable _address
    ) public {
        uint256 oldBlance = MortgageDataArray[_index].balance;
        MortgageDataArray[_index].balance = oldBlance -= _amount;
        _address.transfer(_amount);
    }

    // MortgagorsData *******************************************************************************************
    struct MortgagorsData {
        string fullName;
        string homePrice;
        string downPayment;
        uint256 loanAmount;
        uint256 loanTerm;
        string startDate;
        string status;
        string interestRate;
        address mortgagorAddress;
        string lenderAddress;
        uint256 scorePoint;
    }
    MortgagorsData[] internal MorgagorsDataArray;

    // Create Mortgagors
    function createMortgagor(
        string memory fullName,
        string memory homePrice,
        string memory downPayment,
        uint256 loanAmount,
        uint256 loanTerm,
        string memory startDate,
        string memory interestRate,
        string memory lenderAddress,
        uint256 scorePoint
    ) public {
        MortgagorsData memory newMortgagor = MortgagorsData(
            fullName,
            homePrice,
            downPayment,
            loanAmount,
            loanTerm,
            startDate,
            interestRate,
            "pending",
            msg.sender,
            lenderAddress,
            scorePoint
        );
        MorgagorsDataArray.push(newMortgagor);
    }

    function viewMortgagors() public view returns (MortgagorsData[] memory) {
        return MorgagorsDataArray;
    }

    // Approve or reject
    function loanUnderWaitingFunction(
        string memory _status,
        uint256 _index
    ) public {
        require(
            _index < MorgagorsDataArray.length,
            "Morgagors not found. Index is freater than morgagors array"
        );
        MorgagorsDataArray[_index].status = _status;
    }

    function viewMyMortgagors() public {
        // Will be implement in the front end
        // Viewing mortaggors that has a lender addres of user
    }

    //  Get contract balance
    function contractBalance() public view returns (uint256) {
        return address(this).balance;
    }

    function withdrawAllFunds() public payable {
        payable(admin).transfer(contractBalance());
    }

    function test() public pure returns (string memory) {
        return "Everything is working";
    }

    function getAddress() public view returns (address) {
        return msg.sender;
    }
}

Code structure
The code provided is a Solidity smart contract called “MortgageContract” that implements functionality related to mortgages. Let’s break down the code and explain each part:

  1. Contract Declaration:
    • pragma solidity ^0.8.17;: This line specifies the version of the Solidity compiler required for the contract.
    • contract MortgageContract { ... }: This defines the main contract named MortgageContract.
  2. State Variables:
    • address admin: Declares a state variable to store the address of the contract administrator.
    • uint256 publicArrayIndex: Declares a state variable to track the array index of the public data.
    • struct MortgageData { ... }: Defines a struct named MortgageData to store mortgage-related information.
    • MortgageData[] internal MortgageDataArray: Declares an internal array to store instances of MortgageData structs.
  3. Mortgage Creation:
    • function createMortgage(...) public { ... }: This function allows creating a new mortgage by providing various details. It creates a new MortgageData struct with the provided values and adds it to the MortgageDataArray array.
  4. Viewing Mortgages:
    • function viewMortgages() public view returns (MortgageData[] memory) { ... }: This function returns the entire MortgageDataArray array, allowing anyone to view the created mortgages.
  5. Lender Deposit and Withdrawal:
    • function depositFunctionForLender(uint256 _index) external payable { ... }: This function allows a lender to deposit funds to a specific mortgage identified by the _index parameter. It updates the balance of the mortgage by adding the deposited amount.
    • function withdrawFunctionForLender(...) public { ... }: This function allows a lender to withdraw funds from a specific mortgage identified by the _index parameter. It deducts the specified amount from the mortgage’s balance and transfers it to the specified _address.
  6. Mortgagor Creation and Approval:
    • struct MortgagorsData { ... }: Defines a struct named MortgagorsData to store mortgagor-related information.
    • MortgagorsData[] internal MorgagorsDataArray;: Declares an internal array to store instances of MortgagorsData structs.
    • function createMortgagor(...) public { ... }: This function allows creating a new mortgagor by providing various details. It creates a new MortgagorsData struct with the provided values and adds it to the MorgagorsDataArray array.
    • function loanUnderWaitingFunction(...) public { ... }: This function allows approving or rejecting a mortgagor’s loan request by updating the status field of the corresponding MorgagorsData struct in the MorgagorsDataArray.
  7. Viewing Mortgagors:
    • function viewMortgagors() public view returns (MortgagorsData[] memory) { ... }: This function returns the entire MorgagorsDataArray array, allowing anyone to view the created mortgagors.
  8. Contract Balance and Fund Withdrawal:
    • function contractBalance() public view returns (uint256) { ... }: This function returns the balance (in wei) of the contract.
    • function withdrawAllFunds() public payable { ... }: This function allows the contract administrator to withdraw all the funds (if any) from the contract by transferring the balance to the admin address.
  9. Additional Helper Functions:
    • function test() public pure returns (string memory) { ... }: A simple test function that returns a hardcoded string.
    • function getAddress() public view returns (address) { ... }: This function returns the address of the caller (sender).

Please note that some parts of the code, such as error handling and security checks, may require further improvements depending on the specific use case and deployment requirements.

Deploying The Code

Deploying the Solidity Mortgage code through Remix is a simple procedure. Remix is an online integrated development environment (IDE) that enables you to write, compile, and deploy smart contracts. To deploy your Solidity code using Remix, follow these steps:

  1. Open Remix: Visit the Remix website (remix.ethereum.org) and launch the Remix IDE.
  2. Compose or import your Solidity code: Write your Solidity code directly in the Remix editor or import an existing Solidity file.
  3. Compile the contract: Access the “Solidity Compiler” tab in the Remix sidebar. Select the appropriate compiler version and click the “Compile” button to compile your contract.
  4. Choose the deployment environment: Within the Remix sidebar, go to the “Deploy & Run Transactions” tab. Select the desired deployment environment, such as the Alfajores testnet.
  5. Select the injected provider: Under the deployment environment, choose the “Injected Web3” option from the dropdown menu. This option enables you to connect to your web3 provider, such as MetaMask, and interact with the test network.
  6. Deploy the contract: Click the “Deploy” button to deploy your contract to the selected network using the injected provider. This action will generate a transaction, and you will be prompted to confirm the transaction via your web3 provider. Ensure that you choose the Alfajores test network, as that is the one we will be utilizing, and you can easily fund it by visiting https://faucet.celo.org/alfajores.
  7. Verify and interact with the contract: After the contract is deployed, Remix will provide you with the contract’s address and other relevant details. You can utilize this address to interact with the deployed contract through Remix’s interface. Remember to save the address in a notepad because we will be using it in the ContractHook.js file when we clone the project’s GitHub repository.

Exploring the Front End DApp of the Project

In this section, we will examine the front-end decentralized application (Dapp) of the mortgage system. Each line of code will be explained, along with its functionality. We will delve into the wallet connection system, the creation of mortgages, and the creation of mortgagors. Additionally, we will explore the deployment process of the smart contract that connects the Dapp with the solidity code.

Cloning the Project file on GitHub

To obtain a copy of the project’s GitHub repository, you can execute the following code within your terminal.

 git clone https://github.com/GabrielDelight/Creating-a-Decentralized-Mortgage-Platform-Using-CELO-.git

Once you have cloned the project folder, just go to the project directory and execute the command yarn install to install all the required yarn packages for the mortgage system project.

After the installation of all packages, you can start the package by running yarn start. Once the packages are successfully installed, you will be able to see the following output in your browser.

In the provided code, the displayed balance in metamask is equivalent to the balance in our metaMask account. I will elaborate on the implementation details in this article.

Implementing Wallet Connect

We incorporated React-Celo, which enabled us to integrate the wallet connect system and include the alfajores test network in our Metamask wallet. Please ensure that you have a Metamask Wallet installed by downloading it from the official website. The code for integrating the wallet connect functionality can be found in the index.js file. Here is the code snippet:

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { CeloProvider, Alfajores, NetworkNames } from "@celo/react-celo";
import "@celo/react-celo/lib/styles.css";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <CeloProvider
      dapp
      connectModal={{
        // This options changes the title of the modal and can be either a string or a react element
        title: <span>Connect your Wallet</span>,
        providersOptions: {
          // This option toggles on and off the searchbar
          searchable: true,
        },
      }}
      networks={[Alfajores]}
      network={{
        name: NetworkNames.Alfajores,
        rpcUrl: "https://alfajores-forno.celo-testnet.org",
        graphQl: "https://alfajores-blockscout.celo-testnet.org/graphiql",
        explorer: "https://alfajores-blockscout.celo-testnet.org",
        chainId: 44787,
      }}
    >
      <App />
    </CeloProvider>
  </React.StrictMode>
);
reportWebVitals();

To access a wallet, simply click the “Wallet Connect” button located at the top header of your DApp. You will then receive the following output:

Code structure:
The provided code is a React-based implementation for the front-end of a DApp (Decentralized Application). React is a JavaScript library used for building user interfaces.

In the code, various dependencies are imported, including React and ReactDOM, which are essential for rendering the application in the browser. Additionally, the code imports styles from an “index.css” file to apply custom styling to the DApp. The main component of the application, “App”, is also imported.

The code then sets up the CeloProvider component from the “@celo/react-celo” library, which provides functionality related to the Celo blockchain. It configures the connection modal for wallet integration, specifying options such as the modal title and search bar visibility. The CeloProvider is also configured with the network information for Alfajores, including the RPC URL, GraphQL endpoint, explorer, and chain ID. Finally, the main component, “App”, is rendered within the CeloProvider component, and web vitals are reported using the “reportWebVitals” function.

Lastly, this code establishes the foundation for a front-end DApp by integrating wallet functionality and connecting to the Celo blockchain network. It sets up the necessary dependencies, renders the application, and provides the required configuration for seamless interaction with the Celo blockchain.

Exploring the Contract Hook file

The central component of this project is the contractHook file, situated within the Hook directory in our project’s main folder. The following image depicts the folder structure.

The code in the ContractHook file is provided below:

import React, { useState, useEffect } from "react";
import { useCelo } from "@celo/react-celo";
import Web3 from "web3";
import { newKitFromWeb3 } from "@celo/contractkit";
import { abiData } from "../data/abi";
import BigNumber from "bignumber.js";
import Swal from "sweetalert2";
const ContractHook = () => {
  const { address } = useCelo();
  const [depositBalance, setDepositBalance] = useState("");
  const [contractBalance, setContractBalance] = useState("");
  const [metamaskWallet, setMetamaskWallet] = useState("");
  const [mortgages, setMortgages] = useState([]);
  const [mortgagors, setMortgors] = useState([]);
  const [getAddressFromContract, setGetAddressFromContract] = useState();
  const web3 = new Web3("https://alfajores-forno.celo-testnet.org");
  const kit = newKitFromWeb3(web3);
  kit.addAccount(
    "ec4aa7efc0f434dc888bbafd1655d0837afa73d706b5e9ae6e266bdf2b9ce9e5"
  );
  let contractInstance = new kit.web3.eth.Contract(
    abiData,
    "0xB4eCC0602D082E718B1011B43ac3b71b8EC7b96b"
  );
  // console.log("address,", address)
  useEffect(() => {
    async function isConnectedToContract() {
      try {
        const result = await contractInstance.methods.test().call();
        console.log("Test result:", result);
        const getAddressFrpmCOntract = await contractInstance.methods
          .getAddress()
          .call();
        setGetAddressFromContract(getAddressFrpmCOntract);
        // Get metamask balance
        let balance = await kit.web3.eth.getBalance(address);
        setMetamaskWallet(new BigNumber(balance).dividedBy(1e18).toString());
        const contractBalance = await contractInstance.methods
          .contractBalance()
          .call();
        setContractBalance(
          new BigNumber(contractBalance).dividedBy(1e18).toString()
        );
        const getMortgages = await contractInstance.methods
          .viewMortgages()
          .call();
        setMortgages(getMortgages);

        const getMortgagors = await contractInstance.methods
          .viewMortgagors()
          .call();

        setMortgors(getMortgagors);
      } catch (error) {
        console.log(error);
      }
    }
    isConnectedToContract();
    let intervalId = setInterval(() => {
      isConnectedToContract();
    }, 2000);
    return () => clearInterval(intervalId);
  }, []);

  return {
    contractInstance,
    metamaskWallet,
    contractBalance,
    depositBalance,
    kit,
    address,
    mortgages,
    mortgagors,
  };
};
export default ContractHook;

Code structure:
The code defines a React custom hook called ContractHook. This hook is responsible for connecting to a Celo-based smart contract, retrieving data from the contract, and managing the state of various variables.
Here’s a summary of the code:

  1. The hook imports necessary dependencies including React, useCelo from @celo/react-celo, Web3, newKitFromWeb3 from @celo/contractkit, abiData, BigNumber from "bignumber.js", and Swal from "sweetalert2".
  2. Inside the ContractHook component, several state variables are declared using the useState hook to store different data related to the contract, such as deposit balance, contract balance, metamask wallet balance, mortgages, mortgagors, and the contract address.
  3. The web3 object is created with the URL of the Celo testnet.
  4. A kit instance is created using newKitFromWeb3 and the web3 object.
  5. An account is added to the kit using kit.addAccount.
  6. A contract instance is created using kit.web3.eth.Contract and the abiData and contract address.
  7. The useEffect hook is used to connect to the contract and retrieve data. This effect runs once when the component mounts and sets up an interval to update the data every 2 seconds. It also cleans up the interval when the component unmounts.
  8. Inside the isConnectedToContract function, the following tasks are performed:
    • The test function of the contract is called to check the connection.
    • The getAddress function of the contract is called to retrieve the contract address.
    • The metamask wallet balance is fetched using kit.web3.eth.getBalance.
    • The contract balance is fetched using the contractBalance function of the contract.
    • The viewMortgages function of the contract is called to retrieve the list of mortgages.
    • The viewMortgagors function of the contract is called to retrieve the list of mortgagors.
  9. The retrieved data is stored in the respective state variables using the set functions.
  10. The hook returns an object containing the contract instance, metamask wallet balance, contract balance, deposit balance, kit instance, user address, mortgages, and mortgagors.

This custom hook can be used in a React component to access and display the data retrieved from the Celo-based smart contract. The component can destructure the returned object from the hook and use the data as needed.

Creating Mortgages

To generate a Mortgage, select the Create Mortgage button located in the header of the Dapp. Upon clicking, a form will appear where you can fill in the necessary information. The outcome of this action will be a list displaying the newly created Mortgages.

The following code snippet demonstrates the creation of a Mortgage component, which can be found in src/components/CreateMortgage/CreateMortgage.js enables users to apply for a loan. A detailed explanation of the code will be provided.

import React, { useState } from "react";
import ContractHook from "../../Hooks/ContractHook";
import classes from "./CreateMortgage.module.css";
import Swal from "sweetalert2";
import Loading from "../LoadingIcon/Loading";
const CreateMortgage = (props) => {
  const [formData, setFormData] = useState({});
  const [isLoading, setIsLoading] = useState(false);
  const onHandleClick = (el) => {
    if (el.target.id === "parent-div") {
      props.onCloseModal();
      console.log("Closibng");
    }
  };
  const onChnageHandler = (e) => {
    setFormData((prevState) => {
      return {
        ...prevState,
        [e.target.name]: e.target.value,
      };
    });
  };
  const { contractInstance, address } = ContractHook();
  const onSubmithandler = () => {
    try {
      setIsLoading(true);
      const {
        lenderName,
        lenderDescription,
        minimumAmount,
        maximumAmount,
        loanTerms,
        products,
        startDate,
        interestRate,
      } = formData;
      contractInstance.methods
        .createMortgage(
          address,
          lenderName,
          lenderDescription,
          parseInt(minimumAmount),
          parseInt(maximumAmount),
          parseInt(loanTerms),
          products,
          new Date().toISOString(),
          parseInt(interestRate)
        )
        .send({
          from: address,
          gas: 3000000,
        })
        .on("transactionHash", (hash) => {
          console.log("Transaction hash:", hash);
        })
        .on("receipt", (receipt) => {
          console.log("Receipt:", receipt);
          Swal.fire(
            "Successful!",
            `You were successful in creating a mortgage.`,
            "success"
          );
          setIsLoading(false);
        })
        .on("error", (error) => {
          console.error("Error: occured", error);
          Swal.fire(
            "Transaction failed!",
            `Attempt to create a mortgage failed.`,
            "error"
          );
          setIsLoading(false);
        });
    } catch (error) {
      console.log(error);
    }
  };
  return (
    <div className={classes.container} id="parent-div" onClick={onHandleClick}>
      <div className={classes.wrapper}>
        <div>
          <input
            onChange={onChnageHandler}
            name="lenderName"
            type="text"
            placeholder="Lender name"
          />
          <input
            onChange={onChnageHandler}
            name="lenderDescription"
            type="text"
            placeholder="Lender description"
          />
          <input
            onChange={onChnageHandler}
            name="minimumAmount"
            type={"number"}
            placeholder="Maximim: 2 CELO"
          />
          <input
            onChange={onChnageHandler}
            name="maximumAmount"
            type={"number"}
            placeholder="Minimum: 5 CELO"
          />
          <input
            onChange={onChnageHandler}
            name="loanTerms"
            type={"number"}
            placeholder="Loan terms: eg 2, 3, 5 years"
          />
          <input
            onChange={onChnageHandler}
            name="interestRate"
            type={"number"}
            placeholder="Integrest rate: 4, 5. 7"
          />
          <input
            onChange={onChnageHandler}
            name="products"
            type={"text"}
            placeholder="Products: Student, Parent, Business loan "
          />
          {!isLoading ? (
            <input
              onClick={onSubmithandler}
              type={"button"}
              value={"Create Mortgage"}
            />
          ) : (
            <Loading />
          )}{" "}
        </div>
      </div>
    </div>
  );
};
export default CreateMortgage; 

Code structure
This code represents a React component called CreateMortgage, which is responsible for creating a mortgage using a smart contract on the blockchain. Let’s go through the code step-by-step to understand what it does:

  1. The component imports required modules and hooks:
    • React: The core React library.
    • useState: A React hook that enables functional components to have state.
    • ContractHook: A custom hook that likely handles the interaction with the smart contract.
    • classes: A CSS module used for styling the component.
    • Swal: A library for displaying beautiful alert messages (SweetAlert2).
    • Loading: A custom component for showing a loading icon.
  2. Inside the component, two states are defined using the useState hook:
    • formData: An object that stores the data entered in the form inputs by the user.
    • isLoading: A boolean state used to track whether the component is in a loading state (i.e., during the contract creation process).
  3. There are two functions defined within the component:
    • onHandleClick: This function is triggered when the user clicks on the container element with the id “parent-div.” Its purpose is to close the modal (by calling props.onCloseModal()) when the user clicks outside the form area.
    • onChnageHandler: This function is triggered when the user types in any of the input fields. It updates the formData state with the latest value entered by the user, using the setFormData function.
  4. A custom hook ContractHook() is used to retrieve the contractInstance and address variables. It’s likely that this hook is implemented to handle the interaction with the smart contract, returning the instance of the contract and the address associated with the current user.
  5. The main function of the component, onSubmithandler, is triggered when the user clicks the “Create Mortgage” button. This function does the following:
    • Sets isLoading to true, indicating that the component is now in the loading state.
    • Extracts the necessary data from formData.
    • Calls the createMortgage function of the smart contract with the extracted data.
    • Attaches event handlers to the transaction:
      • "transactionHash": Called when the transaction hash is generated. It logs the hash to the console.
      • "receipt": Called when the transaction is successfully mined and added to the blockchain. It shows a success message using Swal.fire and sets isLoading to false.
      • "error": Called if an error occurs during the transaction. It displays an error message using Swal.fire and sets isLoading to false.
  6. The render function returns the JSX markup for the component. It consists of a form with several input fields for the user to enter mortgage details and a “Create Mortgage” button. When the button is clicked, the onSubmithandler function is executed.
  7. If isLoading is true, the component renders the Loading component instead of the “Create Mortgage” button.

In summary, the CreateMortgage component is responsible for rendering a form where the user can input mortgage details. When the user submits the form, it calls a smart contract method to create a mortgage on the blockchain. The component handles transaction-related events and displays loading indicators and messages using SweetAlert2 during the process.

Depositing to Mortgage

In order to enhance the security of the system, all that is required is to add funds to a newly generated mortgage account, following the steps explained earlier. This action will activate the “apply” button in the mortgage list. To enable users to apply, all you have to do is click on the deposit button within the mortgage list. The accompanying video demonstrates the process of making a deposit.

https://youtu.be/X5GT9zSU2A4

Once a deposit is made successfully, users will be able to see the apply button appearing. There will be an illustration below indicating that the apply button is now activated.

The Mortgagors Component

To initiate the loan application process, users can easily access our application designed specifically for applying for loans within the mortgage system. To apply, all you have to do is click the “apply” button and complete the form. Once you have filled out the form and successfully submitted it, you will have completed the application process. Here is a step-by-step guide on how to apply for a loan.

https://youtu.be/OaAk394Y2WI

Below is a code for applying for a loan located in /src/components/LoanApplicationForm:

import React, { useState } from "react";
import ContractHook from "../../Hooks/ContractHook";
import classes from "./LoanApplicationFormComponent.module.css";
import Swal from "sweetalert2";
import Loading from "../LoadingIcon/Loading";
const LoanApplicationFormComponent = (props) => {
  const [formData, setFormData] = useState({});
  const [isLoading, setIsLoading] = useState(false);
  const onHandleClick = (el) => {
    if (el.target.id === "parent--div") {
      props.closeModal();
      console.log("Closibng");
    }
  };
  const onChnageHandler = (e) => {
    setFormData((prevState) => {
      return {
        ...prevState,
        [e.target.name]: e.target.value,
      };
    });
  };
  const { contractInstance, address } = ContractHook();
  const onSubmithandler = () => {
    try {
      const {
        homePrice,
        fullName,
        downPayment,
        scorePoint,
        loanAmount,
        loanTerm,
      } = formData;
      let startData = new Date().toISOString();
      setIsLoading(true);
      contractInstance.methods
        .createMortgagor(
          fullName,
          homePrice,
          downPayment,
          loanAmount,
          loanTerm,
          startData,
          props.data.interestRate,
          props.data.ownerAddress,
          scorePoint
        )
        .send({
          from: address,
          gas: 3000000,
        })
        .on("transactionHash", (hash) => {
          console.log("Transaction hash:", hash);
        })
        .on("receipt", (receipt) => {
          console.log("Receipt:", receipt);
          Swal.fire(
            "Application successful!",
            `You were successful in applying fot a loan.`,
            "success"
          );
          setIsLoading(false);
        })
        .on("error", (error) => {
          console.error("Error: occured", error);
          Swal.fire(
            "Transaction failed!",
            `Attempt to apply for  a mortgage failed.`,
            "error"
          );
          setIsLoading(false);
        });
    } catch (error) {
      console.log(error);
    }
    console.log(formData);
  };
  return (
    <div className={classes.container} id="parent--div" onClick={onHandleClick}>
      <div className={classes.wrapper}>
        <div>
          <input
            onChange={onChnageHandler}
            name="fullName"
            type="text"
            placeholder="Full name"
          />
          <input
            onChange={onChnageHandler}
            name="homePrice"
            type="number"
            placeholder="Home Price in CELO"
          />
          <input
            onChange={onChnageHandler}
            name="downPayment"
            type="number"
            placeholder="Down payment (initial house deposit) in CELO"
          />
          <input
            onChange={onChnageHandler}
            name="loanAmount"
            type={"number"}
            placeholder="Loan amount: eg 2 CELO"
          />
          <input
            onChange={onChnageHandler}
            name="scorePoint"
            type="number"
            placeholder="Score point"
          />
          <input
            onChange={onChnageHandler}
            name="loanTerm"
            type={"number"}
            placeholder="Loan term: eg 2, 3, 5 years"
          />
          <input onClick={onSubmithandler} type={"button"} value={"Apply"} />
        </div>
      </div>
    </div>
  );
};
export default LoanApplicationFormComponent;

Code structure
The code provided is a React component for a loan application form. It uses state variables to store form data and manage the loading state. It interacts with a contract using a custom hook. On form submission, it calls a contract method, displays success or error messages, and resets the loading state. The component renders input fields and an “Apply” button.

Importance of testing and ensuring platform security.

Testing and ensuring platform security are vital when creating a decentralized mortgage platform using CELO. Thorough testing, including security audits and rigorous testing methodologies, helps identify vulnerabilities and ensures the platform functions as intended. Adhering to best practices and implementing proper access control mechanisms further enhances platform security.

Conclusion

Thank you for reading this enjoyable article. It discusses React-Celo and Celo ContractKit, covering a wide range of topics. I encourage you to apply the knowledge to create advanced Dapps, enhancing your understanding and facilitating collaboration with other developers. The code discussed in the article is accessible in a GitHub repository, which you can find by clicking here. Your time and attention are appreciated.

Next Steps

Your next step should be to create additional options for the Mortgage system and transform it into a practical project. To expand its impact, you can consider partnering with other developers. To further enhance your skills in utilizing the Celo blockchain for your projects, I invite you to click here and read my article about constructing a Travel Booking DApp on Celo that I have created.

About the Author

Gabriel Delight is a highly experienced Blockchain Engineer and Web developer. He possesses a strong skill set and expertise in technical writing. His goal is to utilize his wide range of skills and knowledge to make valuable contributions to a dynamic organization’s success. He has a genuine passion for crafting top-notch web applications and producing technical content that is precise, easily understandable, and filled with valuable information. You can connect with him via his social media profile: LinkedIn and Twitter.

References

2 Likes

Hi @Celo_Academy
I have successfully created an account, I humbly request that the article be assigned to me, as I was kindly informed on the Trello Board. Thank you very much for your consideration.

1 Like

Hi @Gabriel I made you owner so you can manage the proposal now. Welcome to the Academy :seedling:

2 Likes

Hi @Gabriel, I’ll be reviewing this.

1 Like

Thank you very much. I appreciate a lot. :rocket: