March 28, 2023
Velocity Sales
#Nextjs
#TypeScript
#Ethers.js
For one of my classes in my blockchain semester I needed to make a second hand car dealership that would communicate and store data on the ethereum blockchain. So I decided to use NextJS and Ethers.js to handle the website and communication with the blockchain.
Welcome to "Velocity Sales", a second-hand car dealership website built on the Ethereum blockchain. As part of my blockchain semester, I developed this project to create a decentralized platform for buying and selling used cars. Leveraging technologies such as Next.js, TypeScript, and Ethers.js. Velocity Sales enables secure communication and data storage on the Ethereum blockchain.
Implementation
To establish the connection between the website and the Ethereum blockchain, I utilized Next.js and Ethers.js. The project's architecture involved creating a React Context that handles all the communication between the blockchain and the website.
Connecting to the contract
Upon starting the website, a function called connectToContract
is invoked to establish a connection with the deployed smart contract on the Ethereum blockchain. Here is how it works:
1async function connectToContract(): Promise<void> { 2 try { 3 // Check if MetaMask is installed 4 if (typeof (window as any) === 'undefined') { 5 throw new Error('Please install MetaMask first.') 6 } 7 8 // Connect to Web3Provider using MetaMask 9 const _provider = new ethers.providers.Web3Provider( 10 (window as any).ethereum 11 ) 12 13 const _signer = _provider.getSigner() 14 const _contract = new ethers.Contract(contractAddress, abi.abi, _signer) 15 16 const _address = await _provider.listAccounts() 17 18 if (_address.length > 0) { 19 setAddress(_address[0]) 20 } 21 22 // Set the provider, signer, and contract 23 setProvider(_provider) 24 setSigner(_signer) 25 setContract(_contract) 26 27 const ethereuem = (window as any).ethereum 28 29 // Add event listener for account changes 30 ethereuem.on('accountsChanged', (_accounts: any) => { 31 setAddress(_accounts.length > 0 ? _accounts[0] : null) 32 }) 33 34 setIsConnected(true) 35 } catch (err) { 36 console.error(err) 37 } 38}
This function checks if the MetaMask extension is installed and then establishes a connection using the Web3Provider provided by MetaMask. It sets the provider, signer, and contract for further interactions with the blockchain.
Interacting with the Contract
To communicate with the functions on the smart contract, I created the callContractFunction
function. Here is how it works:
1async function callContractFunction( 2 functionName: string, 3 ...args: any[] 4): Promise<any> { 5 try { 6 if (!contract) { 7 console.error('Contract not initialized') 8 return null 9 } 10 11 const result = await contract[functionName](...args) 12 return result 13 } catch (error) { 14 console.error(`Error calling function ${functionName}: ${error}`) 15 return null 16 } 17}
This function takes the name of the contract function and any required arguments. It then calls the corresponding function on the contract and returns the result. This simplifies the process of interacting with the smart contract from the website.
Detail
The detail page provides comprehensive information about a specific car, including its license plate, brand, type, and mileage. Each car is represented as a non-fungible token (NFT) on the blockchain, with an owner identified by a wallet address. If the wallet address connected to the website matches the owner's address, additional options such as deleting, modifying, canceling, and unlisting the car are available. These options directly communicate with the blockchain to update the token's data.
For visitors who are potential buyers and do not own the car, purchasing options are displayed. If the buyer has sufficient Ethereum in their wallet (including the car's price and gas fees), they can initiate the purchase process. The payment process involves transferring the funds from the buyer's wallet to the contract and updating the car's status as "sold". The buyer and seller can then arrange the physical transfer of the car.
After the buyer collects the car, they can press a button to transfer the funds from the contract to the seller's wallet. Simultaneously, the NFT token ownership is transferred to the new owner, completing the purchase.
Empty handling
The user's garage page displays all the cars they have entered int he application or purchased. However, if the user has no cars associated with their account, the application gracefully handles the situation by displaying an image indicating that there are no cars available.
Unauthorized
To make sure that no user would be able to view pages without connecting his or her wallet I made a route guard that wraps around all pages and checks on every URL change which URL it's on and throw the user out if he or she isn't connected.
To ensure that users cannot access pages without connecting their wallets, I implemented a route guard that wraps around all pages. This guard checks the URL on every change and redirects users if they are not connected. Here's an example of how it works:
1const authCheck = async (url: string): Promise<void> => { 2 // Redirect to login page if accessing a private page and not logged in 3 const restrictedPaths: string[] = ['profile', 'cars'] 4 5 if (restrictedPaths.includes(url) && !address) { 6 setAuthorized(false) 7 router.push({ 8 pathname: '/unauthorized', 9 query: { returnUrl: router.pathname }, 10 }) 11 } else { 12 setAuthorized(true) 13 } 14}
The function checks the current URL against the restricted paths array. If the user is not connected and tries to access a private page, they are redirected to the unauthorized page (/unauthorized)
. This ensures that only authorized users can access certain parts of the website.
Conclusion
This project demonstrates the potential of using blockchain technology, specifically the Ethereum network, for creating decentralized applications. By leveraging Next.JS, TypeScript, and Ethers.js, I build a secure and reliable platform for second-hand car sales.
The integration of smart contracts allows for transparent and immutable transactions, providing users with a trustworthy environment. I am excited about the possibilities of blockchain technology brings and look forward to exploring further innovative applications in the future.