What you will be building, see the live demo at sepolia test net and the git repo.
Are you a blockchain enthusiast looking to explore the exciting world of non-fungible tokens (NFTs) and their unique capabilities? Are you interested in building a web3 application that allows users to cross-breed NFTs and create new, one-of-a-kind digital assets? If so, you've come to the right place.
In this tutorial, we will walk you through the process of building a web3 NFT cross-breeding DApp using React, Solidity, and CometChat. React will serve as our front-end framework, providing a robust and interactive user interface. Solidity, the programming language for Ethereum smart contracts, will enable us to define the logic and behavior of our NFT cross-breeding functionality.
Lastly, CometChat will empower us to integrate real-time chat functionality into our DApp, allowing users to interact and communicate with each other seamlessly.
By the end of this tutorial, you will have gained valuable insights into:
Whether you are an experienced developer or just starting your journey into web3 development, this tutorial will equip you with the knowledge and skills to create your very own NFT cross-breeding DApp. So, let's embark on this exciting journey together and unlock the potential of NFT cross-breeding in the blockchain realm. Get ready to dive into the fascinating intersection of React, Solidity, and CometChat – let's begin!
You will need the following tools installed to build along with me:
I recommend watching the video below to learn how to set up your MetaMask for this project.
Clone the starter kit and open it in VS Code using the command below:
git clone https://github.com/Daltonic/tailwind_ethers_starter_kit dappBreeds
cd dappBreeds
Next, update the package.json with the snippet below.
Please run the command yarn install
in your terminal to install the dependencies for this project.
To configure the CometChat SDK, please follow the steps provided below. Once completed, make sure to save the generated keys as environment variables for future use.
STEP 1: Head to CometChat Dashboard and create an account.
STEP 2: Log in to the CometChat dashboard, only after registering.
STEP 3: From the dashboard, add a new app called DappBreeds.
STEP 4: Select the app you just created from the list.
STEP 5:
From the Quick Start copy the APP_ID
, REGION
, and AUTH_KEY
, to your .env
file. See the image and code snippet.
Replace the REACT_COMET_CHAT
placeholder keys with their appropriate values.
REACT_APP_COMETCHAT_APP_ID=****************
REACT_APP_COMETCHAT_AUTH_KEY=******************************
REACT_APP_COMETCHAT_REGION=**
The .env
file should be created at the root of your project.
Navigate to the root directory of the project and open the "hardhat.config.js
" file. Replace the existing content of the file with the provided settings.
This code configures Hardhat for your project. It includes importing necessary plugins, setting up networks (with localhost as the default), specifying the Solidity compiler version, defining paths for contracts and artifacts, and setting a timeout for Mocha tests.
The following steps will guide you through the process of creating the smart contract file for this project:
contracts
inside the src
folder.DappBreeds.sol
and Base64.sol
inside the contracts
folder.
By following these steps, you will have successfully set up the necessary directory structure and created the DappBreeds.sol
and Base64.sol
files, which will serve as the foundation for implementing the logic of the smart contract.
The DappBreed smart contract is designed to facilitate the creation and breeding of AI-generated artworks as non-fungible tokens (NFTs). Let's provide an overview of its key components and functions:
DappBreed inherits from several other contracts, including ERC721, ERC721URIStorage, Ownable, and ReentrancyGuard.
It also imports libraries such as Counters and Base64, as well as contracts from the OpenZeppelin library.
TraitStruct: Represents the traits of an AI-generated artwork, including name, description, weapon, image URI, environment, rarity, breeding status, and parent tokens.
MintStruct: Contains information about a minted NFT, such as its ID, owner, minting cost, timestamp, and associated TraitStruct.
baseURI: Stores the base URI for the metadata of NFTs.
maxSupply: Indicates the maximum number of NFTs that can be minted.
baseExtension and imageExtension: Define the file extensions for the metadata and image files.
mintCost: Specifies the cost in Ether for minting an NFT.
totalBalance: Tracks the total balance (in Ether) accumulated from minting fees.
minted: Maps the token ID to its associated MintStruct, storing information about each minted NFT.
tokenIdExist: Tracks the existence of a token ID.
weapons: Contains a predefined list of weapon names used for generating AI artwork traits.
environments: Holds a predefined list of environment names for AI artwork traits.
rarities: An array to represent the rarity levels of AI artworks.
mintNft: Allows users to mint a new NFT by paying the required mintCost.
breedNft: Enables users to breed two existing NFTs to create a new one, paying the mintCost.
_performMinting: Internal function to perform the minting process, creating the NFT and updating relevant data.
getAllNfts: Returns an array of all minted NFTs.
getMintedNfts: Retrieves an array of NFTs that have not been bred.
getBreededNfts: Returns an array of NFTs that have been bred.
getMyNfts: Retrieves an array of NFTs owned by the caller.
getParentsOf: Returns an array of parent NFTs for a given token ID.
getNft: Retrieves the MintStruct information for a specific token ID.
buildMetadata: Internal function to build the metadata URI for a given token ID.
setBaseURI: Allows the contract owner to update the baseURI for NFT metadata.
_baseURI: Overrides the baseURI function from ERC721URIStorage to return the contract's baseURI.
_burn: Overrides the _burn function from ERC721URIStorage to call the parent implementation.
randomNum: Generates a random number based on input parameters.
currentTime: Retrieves the current timestamp.
payTo: Sends Ether to a specified address.
nonReentrant: Prevents reentrancy attacks by enforcing a non-reentrant execution context.
The contract inherits various functions from the imported contracts, such as _safeMint, _setTokenURI, and supportsInterface.
The DappBreed smart contract combines the functionalities of ERC721, ERC721URIStorage, and Ownable contracts to provide a platform for minting, breeding, and managing AI-generated artworks as NFTs.
Want to get a deeper understanding of NFT developments? Purchase the "Fullstack NFT Marketplace (Course)" today! This comprehensive course will teach you what you need to know about building and deploying NFT marketplaces on Ethereum.
The DappBreed test script is designed to test the functionalities and behaviors of the DappBreed smart contract. Here's an overview of the key tests and functions present in the script:
The script initializes variables such as _maxSupply
, _name
, _symbol
, and _baseUri
for the contract deployment.
It sets up the deployer and two user addresses as signers for testing purposes.
The script deploys the DappBreed contract using the specified parameters.
It uses the mintNft
function to mint an NFT with a value of 0.005 Ether.
The test checks the successful minting of the NFT and verifies the retrieved minted NFT and its ID.
The script includes tests to confirm the successful minting of multiple NFTs.
It mints a second NFT using a different user address and checks the total number of minted NFTs.
The script sets up a scenario for NFT breeding by minting another NFT with a different user address.
It verifies the presence of both minted NFTs and the absence of any breeded NFTs.
The test then uses the breedNft
function to breed the previously minted NFTs.
It checks the successful breeding of the NFT, the total number of owned NFTs, and the presence of breeded NFTs.
Additionally, the test verifies the correctness of the parents and traits of the breeded child NFT.
The DappBreed test script covers crucial aspects of the contract's functionality, including minting and breeding NFTs. It ensures that the contract behaves as expected and that the NFTs are generated and managed correctly.
At the root of the project, create a folder if not existing called “test”, copy and paste the code below inside of it.
By running **yarn hardhat test**
on the terminal will test out all the essential function of this smart contract.
The DappBreed deployment script is responsible for deploying the DappBreed smart contract to the Ethereum network using the Hardhat development environment. Here's an overview of the script:
The script imports the required dependencies, including ethers and the fs module for file system operations.
The main()
function is an asynchronous function that serves as the entry point for the deployment script.
The script defines the deployment parameters, including the contract_name
, name
, symbol
, baseURI
, and maxSupply
.
These parameters specify the name, symbol, base URI, and maximum supply of the NFTs to be deployed.
The script uses the ethers.getContractFactory()
method to obtain the contract factory for the DappBreed
contract.
It deploys the contract by invoking the deploy()
method on the contract factory with the specified parameters.
The deployed contract instance is stored in the contract
variable.
The script waits for the deployment to be confirmed by awaiting the deployed()
function on the contract instance.
The script creates a JSON object containing the deployed contract address.
It writes this JSON object to a file named contractAddress.json
in the specified path: ./src/abis/contractAddress.json
.
If any error occurs during the file writing process, it is logged to the console.
If the contract deployment and file writing processes are successful, the deployed contract address is logged to the console.
Any errors that occur during the deployment or file writing process are caught and logged to the console.
The process exit code is set to 1 to indicate an error occurred.
The DappBreed deployment script allows for the easy deployment of the DappBreed smart contract, and it generates a JSON file containing the deployed contract address for further usage within the project.
In the root of the project, create a folder called “scripts” and another file inside of it called deploy.js
if it doesn’t yet exist. Copy and paste the code below inside of it.
Next, run the yarn hardhat run scripts/deploy.js
to deploy the smart contract into the network on a terminal.
If you require additional assistance with setting up Hardhat or deploying your Fullstack DApp, I recommend watching this informative video that provides guidance and instructions.
To start developing the frontend of our application, we will create a new folder called components
inside the src
directory. This folder will hold all the components needed for our project.
For each of the components listed below, you will need to create a corresponding file inside the src/components
folder and paste its codes inside it.
The Navbar
and MobileMenu
components represent the user interface elements of the DappBreeds application's navigation bar. They display the website's logo, menu items, and a connect wallet button.
The Navbar
component adjusts its layout based on screen size, while the MobileMenu
component is specifically designed for mobile devices. The ConnectButton
component handles the logic for connecting the user's wallet. See code below:
The Hero
component represents a section of the DappBreeds application's homepage. It consists of two sub-components, HeroActions
and HeroImage
, and it arranges them in a responsive layout.
The HeroActions
component contains buttons for minting and breeding NFTs, along with associated logic for interacting with the blockchain.
The HeroImage
component displays an image related to the hero section. The Hero
component aims to engage users by showcasing the possibilities of creating and breeding NFTs, along with statistics related to artworks, artists, and breeds. See the code below:
The Sponsors
component is responsible for displaying a list of sponsor logos on the DappBreeds website. It renders a list (ul
) element with each sponsor's logo represented by an img
element. The logos are sourced from local image files (coinbase.png
, dropbox.png
, slack.png
, webflow.png
) and displayed with a fixed width of 200 pixels while maintaining their aspect ratios.
The component utilizes flexbox and responsive design (md:flex-row
) to align the logos horizontally on larger screens and vertically on smaller screens. The Sponsors
component enhances the visual appeal of the website and showcases the support of notable sponsors.
Please ensure that you have the copies of all the images found in this link inside assets
folder in the src
directory of your project.
Use the code below to form the Sponsors
component.
The Trending
component displays a section on the DappBreeds website that showcases trending NFTs. It dynamically renders a heading based on the length of the nfts
collection, showing either "Trending" or "No minted NFTs yet...". It also includes the TrendingCards
component to display a grid of NFT cards based on the provided nfts
collection.
The component manages the number of displayed cards and handles loading more cards when available. It allows users to add or remove NFTs from the lab and provides truncate functionality for displaying NFT information.
The Trending
component is a central element for showcasing popular NFTs, providing interactivity, and enabling users to explore and engage with the NFT collection.
The TrendingCards
component receives a collection
prop and renders a grid of NFT cards based on the provided collection. It dynamically updates the displayed cards using the **useState**
and useEffect
hooks.
Each card contains an image, name, description, mint cost, owner, and an action button. The component allows users to add or remove NFTs from the lab and offers a "Load more" button to fetch additional cards from the collection.
With its grid layout and interactive features, TrendingCards
enhances the visual representation of NFTs, promotes engagement, and enables users to explore and interact with the trending NFTs featured in the DappBreeds application.
Use the codes below for creating each components, ensure they are in different files.
The Collection
component displays a collection of NFTs in a grid layout. It receives a collection
prop containing the NFT data and an optional title
prop for the collection title.
The component manages the number of displayed NFTs using the useState
and useEffect
hooks. It renders the CollectionCard
component for each NFT in the nfts
state. The component also provides a "Load more" button to fetch additional NFTs from the collection when available.
The CollectionCard
component represents an individual NFT card within the Collection
component. It receives an nft
prop containing the NFT data and renders the card's image, name, description, and breeding information.
The component dynamically displays whether the NFT was bred or minted based on the nft
data. It also includes a link to the detailed view of the NFT. CollectionCard
enhances the visual representation of NFTs within the collection, providing concise information about each NFT and enabling users to navigate to specific NFT details for further exploration.
Use the codes below to create their individual files.
The Footer
component represents the footer section of the application. It is a static component that displays relevant information and links. See the code below.
The Spacer
component is a simple utility component that creates vertical spacing in a layout by rendering empty div
elements. See the codes below.
The ChatButton
component is a menu component that provides chat-related functionalities. It renders a button with an "Add" icon and displays a dropdown menu when clicked.
The dropdown menu options change based on the user's authentication status. If the user is not logged in, the menu displays options for signing up and logging in. If the user is logged in, the menu shows options for recent chats and logging out.
Each menu item triggers a specific action, such as signing up, logging in, opening the list of recent chats, or logging out. The actions are asynchronous and utilize the toast.promise
function to display informative toast messages during the operations.
The component utilizes CometChat SDK and Tailwind CSS to offers a user-friendly way to interact with chat-related functionality in a concise and intuitive manner. See the code below.
The ChatList
component displays a modal dialog that contains a list of conversations. It is triggered by the chatListModal
state variable.
The modal dialog appears as an overlay on top of the page content, providing a darkened background to focus on the conversation list. The component retrieves the user's conversations using the getConversations
function and displays them in the list.
Each conversation is rendered as a Conversation
component, showing the conversation participant's avatar, truncated username, and last message.
Clicking on a conversation triggers navigation to the chat room associated with that conversation, updates the global state accordingly, and retrieves the chat messages using the getMessages
function.
The component utilizes react-identicons
to generate unique avatars based on the conversation participant's username. The chat list modal can be closed by clicking the "X" button. See the codes for it below.
Want to learn how to build an Answer-To-Earn DApp with Next.js, TypeScript, Tailwind CSS, and Solidity?
This video is a great resource for anyone who wants to learn how to build decentralized applications and earn ethers.
Now that we have covered all the components in this application, it is time to start coupling the various pages together. Let's start with the homepage.
To begin developing the pages of our application, we will create a new folder called pages
inside the src
directory. This folder will hold all the pages needed for our project.
For each of the pages listed below, you will need to create a corresponding file inside the src/pages
folder, just as you did before with the components.
The Home
page component represents the home page of the application. It includes several components to provide the main features and content of the page.
The components used in the Home
page are:
Hero
: This component displays a hero section with a catchy title and description, inviting users to explore the features of the application.
Sponsors
: This component showcases the logos of sponsors or partner companies, adding credibility and promoting collaboration.
Trending
: This component displays a section for trending items or NFTs. It receives the minted
array as a prop, which represents the collection of recently minted NFTs.
Collection
: This component represents a collection section, showing a grid of NFTs. It is conditionally rendered based on the length of the breeded
array, which contains NFTs that have been created through breeding.
By combining these components, the Hom
page provides a comprehensive overview of the application, including a hero section, sponsor logos, trending NFTs, and a collection of bred NFTs if any exist. See the codes below.
The Details
page component represents a page that displays the details of a specific NFT. It fetches the NFT data using the getAnNft
function and renders the information once the data is loaded.
The components used in the Details
page are:
NFTImage
: This component displays the image of the NFT. It receives the nft
object as a prop and renders the image using the traits.image
property.
NFTInfo
: This component displays the detailed information of the NFT, including the NFT's name, owner, description, mint cost, weapon, environment, and a button to initiate a chat with the owner. It receives the nft
object as a prop and renders the information accordingly.
CollectionCard
: This component is used to display NFT cards. It is utilized within the Details
page to showcase the inherited NFTs from parents if they exist.
The Details
page also conditionally renders the inherited NFTs section if the parents
array has a length greater than zero. It displays the cards of the inherited NFTs using the CollectionCard
component.
Overall, the Details
page provides a comprehensive view of a specific NFT, including its image, detailed information, and any inherited NFTs. See the codes below.
The Collections
component represents a page that displays the user's collection of NFTs. It fetches the user's NFT collection using the getMyNfts
function and renders the collection if it contains any NFTs.
The components used in the Collections
page are:
Collection
: This component displays a collection of NFT cards. It receives the collection
array as a prop and renders the collection using the CollectionCard
component.
The Collections
page fetches the user's NFT collection when the component mounts using the useEffect
hook.
If the collection
array has a length greater than zero, the page renders the Collection
component with the user's collection and provides a title of "Your Collection". If the collection
array is empty, it displays a message indicating that the user has no collection yet.
Overall, the Collections
page provides a user-specific view of their NFT collection, showcasing the NFT cards using the Collection
component if the collection is not empty, or displaying a message if the collection is empty. See the code below.
The Lab
component represents a page where users can interact with the breeding feature of the application. Users can select NFTs from their collection, breed them, and perform related actions.
The Lab
page allows users to breed NFTs by selecting two NFTs from their collection as father and mother. It features three important buttons:
"Randomly Select": This button randomly selects two NFTs from the platform’s collection as father and mother, facilitating a quick breeding process.
"Breed Now": This button initiates the breeding process with the selected father and mother NFTs. It triggers the breedNft
function, which performs the necessary blockchain transactions for breeding. Success and error messages are displayed using the toast
component.
"Clear Selection": This button clears the current selection of father and mother NFTs, allowing users to choose different NFTs for breeding.
The page also displays visual representations of the selected NFTs and checks the user's wallet connection before breeding. If the wallet is not connected, a warning message is displayed using the toast
component. See the codes below.
The Chat
page allows users to engage in a chat conversation with another user. It features a chat interface with the following components:
Chat Messages: Messages exchanged between the users are displayed in a scrollable container. Each message is represented by the Message
component, which shows the sender's avatar, username (truncated if necessary), message content, and the timestamp of the message.
Message Input: Users can enter their messages in the input field at the bottom of the chat interface. When they submit the message, it is sent using the sendMessage
function and displayed in the chat conversation. The input field supports placeholder text and automatically adjusts its height as the user types.
Scroll to End: The chat interface automatically scrolls to the latest message, ensuring that the most recent content is always visible to the users.
The Chat
page initializes the chat conversation by fetching existing messages using the getMessages
function. It also listens for real-time updates using the listenForMessage
function, allowing for a dynamic chat experience. Messages are stored in the global state using the setGlobalState
function. See the codes below.
Great work! We have now completed all of the components and pages for this project. Let's now connect them to their respective services. We will start with the App component.
The App
component is the entry point of the application and sets up the routing and main structure of the app. It includes the following components and functionality:
Navigation: The Navbar
component is displayed at the top of the app, providing navigation links to different pages.
Routing: The Routes
component from react-router-dom
is used to define the routes and their corresponding components. Each route is associated with a specific URL path and renders the appropriate component when the path is matched.
Pages: The Home
, Details
, Collections
, Lab
, and Chat
components are defined as routes and rendered based on the current URL path. These components represent the different pages of the application, such as the home page, details page, collections page, lab page, and chat page.
Data Loading: The useEffect
hook is used to trigger data loading functions when the component mounts. It checks if a wallet is connected using isWalletConnected
, loads data using loadData
, and checks the authentication state using checkAuthState
. This ensures that necessary data and authentication are available before rendering the app.
Chat Functionality: The ChatButton
component is conditionally rendered if there is a connected account. It provides a button to open the chat interface. The ChatList
component is also rendered, displaying the list of chat conversations.
Styling and Toasts: The Spacer
component is used to create vertical spacing within the app layout. The Footer
component is displayed at the bottom of the app. The ToastContainer
component from react-toastify
is used to display toast notifications for user feedback.
Replace the existing App.jsx
component with the code below.
The blockchain service script provides various functions and utilities to interact with the blockchain and manage NFT-related operations. Here's an overview of the key functionalities:
Wallet Connection: isWalletConnected
checks if the user's wallet (e.g., MetaMask) is connected and manages changes in the connected account. connectWallet
triggers the wallet connection process.
NFT Operations: mintNft
and breedNft
are used to mint and breed NFTs, respectively. They interact with the blockchain contract, handle transactions, and update the corresponding NFT collections.
NFT Data Retrieval: Functions such as getAllNfts
, getMintedNfts
, getBreededNfts
, getMyNfts
, getAnNft
, and getParentsNft
fetch different types of NFT data from the blockchain contract. The retrieved data is structured and stored in the global state.
Data Loading: loadData
loads various NFT collections and related data, such as mint costs, when the application initializes.
Utility Functions: toWei
and fromWei
convert between Wei and Ether units. structuredMint
transforms raw contract data into a structured format for easier consumption and sorting.
Error Handling: reportError
logs any errors encountered during blockchain interactions.
Overall, the script facilitates wallet connection, NFT minting and breeding, data retrieval, and error handling for the blockchain-based NFT application.
To use this code, you will need to create a new folder called services
inside the src
directory of your project. Inside the services
folder, you will need to create a new file called blockchain.jsx
. Once you have created the file, you can copy and paste the code below into it.
Please ensure that you update the environment variables to look like this:
REACT_APP_COMETCHAT_APP_ID=****************
REACT_APP_COMETCHAT_AUTH_KEY=******************************
REACT_APP_COMETCHAT_REGION=**
REACT_APP_RPC_URL=http://127.0.0.1:8545
The CometChat service script provides various functions and utilities for integrating CometChat into the application. Here's an overview of the key functionalities:
Initialization: initCometChat
initializes the CometChat SDK with the provided app ID and region.
User Authentication: loginWithCometChat
and signUpWithCometChat
handle user authentication with CometChat using the provided user ID (UID) and authentication key. They log in or sign up the user respectively and return a Promise with the user object.
User Logout: logOutWithCometChat
logs out the currently logged-in user from CometChat and clears the current user state in the global state.
User Authentication State: checkAuthState
checks the authentication state of the user by fetching the currently logged-in user from CometChat and updates the current user state in the global state.
Messaging: getMessages
fetches the previous messages for a specific user, sendMessage
sends a text message to a specified receiver ID, and listenForMessage
listens for incoming text messages.
Conversations: getConversations
retrieves the conversations for the current user.
The service script provides a set of functions to initialize CometChat, handle user authentication and logout, fetch and send messages, and manage conversation data. These functionalities enable real-time messaging and chat features in the application using the CometChat SDK.
Continuing inside the services
folder, create a new file called chat.jsx
. Once you have created the file, you can copy and paste the code below into it.
Excellent! Now, let's work on the store
file, which serves as a state management library.
The store
service provides a centralized state management solution using the react-hooks-global-state
library. It offers functions for setting, getting, and using global state variables within the application.
The available global state variables include connectedAccount
, chatListModal
, conversations
, messages
, nfts
, minted
, breeded
, collection
, breeds
, parents
, nft
, currentUser
, and mintCost
.
The service also includes a truncate
function, which truncates text to a specified length, allowing for the display of shortened text while maintaining readability.
Additionally, there are utility functions such as addToLab
and remFromLab
that modify the breeds
global state variable, allowing the addition and removal of items in the "Lab" section of the application.
To use this service, you will need to create a new folder called store
inside the src
directory of your project. Inside the store
folder, you will need to create a new file called index.jsx
.
Once you have created the file, you can copy and paste the code below into it.
The index.jsx
file is the entry point for the application. It initializes the CometChat service, sets up dependencies, and renders the React application using the App
component within a BrowserRouter
. It creates a root element for rendering and sets up the necessary configurations for the application to start running.
To use this code, you will need to replace the code below inside of the index.jsx
and index.css
files in the src
folder of your project.
Now you are officially done with the build, just execute yarn start
to have the application running on the browser.
Congratulations on building a Web3 NFT Cross-Breeding Dapp with real-time chat functionality using the CometChat SDK! If you are looking for a powerful and versatile chat SDK that can be used to add chat functionality to any application, I highly recommend trying out CometChat.
CometChat offers a wide range of chat features, including 1-on-1 chat, group chat, file sharing, and more. It is also very easy to integrate with other platforms, making it a great choice for developers of all skill levels.
For more web3 resources, check out this video that teaches how to create a decentralized app by building a web3 lottery dapp, I recommend that you it.
The video provides a hands-on tutorial on how to build a lottery dapp using NextJs, Tailwind CSS, and Solidity.
How to Build a web3 NFT Cross-Breeding Dapp with React, Solidity, and CometChat" is a transformative guide showcasing the fusion of blockchain, React, and real-time chat in creating an innovative NFT cross-breeding Dapp. The project leverages smart contracts for secure operations and offers an intuitive front-end interface. By incorporating CometChat, it enhances user engagement through real-time communication.
This tutorial demonstrates the potential of web3 development in revolutionizing the NFT space, providing transparency and secure transactions. Through comprehensive testing, the smart contracts ensure reliability. Developers are encouraged to explore the vast possibilities of blockchain technology.
For further learning, we recommends subscribing to our YouTube channel and visiting our website for additional resources.
Till next time all the best!
I am a web3 developer and the founder of Dapp Mentors, a company that helps businesses and individuals build and launch decentralized applications. I have over 7 years of experience in the software industry, and I am passionate about using blockchain technology to create new and innovative applications. I run a YouTube channel called Dapp Mentors where I share tutorials and tips on web3 development, and I regularly post articles online about the latest trends in the blockchain space.
Stay connected with us, join communities on Discord: Join Twitter: Follow LinkedIn: Connect GitHub: Explore Website: Visit