Hello,
having some issues with test prooject based on âBuild Your Own Web 3.0 Metaverse using Solidity, Javascript and Moralis - Blockchain Developmentâ from Yoiutube tutorial. Map never showing up.
Logic.js
//Initializing constants
const serverUrl = "xxxxx";
const appId = "xxxxx";
//Graphics constants
// - map management constants
const tiles = 624;
const plots = tiles * 1;
const roads = tiles * 1;
const initialOffsets = plots +roads;
const plotViewOffsets = plots + (2 * roads);
//- canvas and context
const mainCanvas = document.getElementById("mainCanvas");
const mainCtx = mainCanvas.getContext('2d');
const plotCanvas = document.getElementById("plotCanvas");
const plotCtx = plotCanvas.getContext('2d');
const worldImage = new Image();
//- State
const mapView = {mapOffsetX:-1*initialOffsets,mapOffsetY:-1*initialOffsets};
const plotView = {plotX:0, plotY:0, locationX:0,locationY:0};
const unassignables = [
"0x8fa5a0f171f8b06a2006bc8fa5164606fa303f29b43f25438ae585d32f979524",
"0x51335e5c0d362b12bbc4877297443f914f0f9849da3bb43485ce6d96fcc6f9c9",
"0xbb15fe082bb44a75feb18fcb4072d7e1d817f016d24cc1b1205c4f729e0b69ca",
"0x5e2da10292384f87396bd6e706838dcb931f91404f3f01e4ef9538f3e161262e",
"0x760a8a1da896267c45023b0d1c17a5bc42b81d12ab49a4bf1ccfec74c1ebe8ae",
"0xad2572137374014c87d7abe24a591d3d65aee5cdc781ae15c727a971c5637aa7",
"0xc2c26eb9355dec9ceae980da9bb626c7b583fe9af9c779333ea6e19309c2f3a6",
"0xbf8142b3eb80adcbdb8a1c1a146995728a859ab1a1dbf29dcf15ebeb32f4a468",
"0x3c02bccec034096f69ebbaacc075adbf352d2309a6de6b632d7b18b10b60180c",
"0xfaf95d6bec5226ee145a021be8bda12c1062f7817ba6340499023b26d7e7a3f0",
"0x98ce6651c1676f0d20fc0553d96755f2162f97c874ec668be5ebc68c3b2b7b41"
]
//web3 constants
const contractAddress = ""; //your own contract
const contractABI = [{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"tokenURI","type":"string"},{"internalType":"bytes","name":"bytesId","type":"bytes"}],"name":"assign","outputs":[],"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"assignee","type":"address"},{"indexed":false,"internalType":"bytes","name":"bytesId","type":"bytes"}],"name":"Assigned","type":"event"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"bytesId","type":"bytes"}],"name":"exist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}];
const ethers = Moralis.web3Library;
//canvas drawing functions
function drawCanvas(){
mainCanvas.width = 3 * plots + 4 * roads;
mainCanvas.height = 3 * plots + 4 * roads;
plotCanvas.width = plots
plotCanvas.height = plots
worldImage.src = 'static/img/Rainbowland.png';
worldImage.onload = () => {
initializeMap()
}
}
function initializeMap() {
updatePlotLocation()
setPlotData();
drawMapSection(mainCtx,mapView.mapOffsetX,mapView.mapOffsetY);
drawCursor(plotViewOffsets,plotViewOffsets);
drawMapSection(plotCtx,-1 * plotView.locationX,-1 *plotView.locationY);
}
//animate functions
function move(direction) {
const validMove = validateMove(direction);
if (validMove) {
updateView(direction);
updatePlotLocation();
drawMapSection(mainCtx,mapView.mapOffsetX,mapView.mapOffsetY);
drawCursor(plotViewOffsets,plotViewOffsets);
drawMapSection(plotCtx,-1 * plotView.locationX,-1 *plotView.locationY);
setPlotData();
}
}
function validateMove(direction) {
switch(direction){
case 'ArrowRight': return !(plotView.plotX == 5);
case 'ArrowUp': return !(plotView.plotY == 0);
case 'ArrowLeft': return !(plotView.plotX == 0);
case 'ArrowDown': return !(plotView.plotY == 5);
}
}
function updateView(direction) {
switch(direction){
case 'ArrowRight':
plotView.plotX += 1;
mapView.mapOffsetX -= plots + roads;
break
case 'ArrowDown':
plotView.plotY += 1;
mapView.mapOffsetY -= plots + roads;
break
case 'ArrowLeft':
plotView.plotX -= 1;
mapView.mapOffsetX += plots + roads;
break
case 'ArrowUp':
plotView.plotY -= 1;
mapView.mapOffsetY += plots + roads;
break
}
}
function drawMapSection(ctx,originX,originY){
ctx.drawImage(worldImage,originX,originY);
}
function drawCursor(x,y) {
mainCtx.strokeRect(x,y,plots,plots)
}
function updatePlotLocation() {
plotView.locationX = -1 * mapView.mapOffsetX + plotViewOffsets;
plotView.locationY = -1 * mapView.mapOffsetY + plotViewOffsets;
}
//UI Functions
function setPlotData() {
const plotID = ethers.utils.id(JSON.stringify(plotView));
document.getElementById("plotX").value = plotView.plotX
document.getElementById("plotY").value = plotView.plotY
document.getElementById("locationX").value = plotView.locationX
document.getElementById("locationY").value = plotView.locationY
document.getElementById("plotID").value = plotID;
isPlotAssignable(plotID);
}
function isPlotAssignable(plotID) {
const _unassignable = unassignables.includes(plotID);
if (_unassignable) {
document.getElementById("claimButton").setAttribute("disabled",null);
}
else {
document.getElementById("claimButton").removeAttribute("disabled");
}
}
function displayMessage(messageType, message){
const messages = {
"00":`<div class= "alert alert-success"> ${message} </div>`,
"01":`<div class= "alert alert-danger"> ${message} </div>`
}
document.getElementById("notifications").innerHTML = messages[messageType];
}
//web3 Functions
async function login(){
Moralis.Web3.authenticate().then(async function (){
const chainIdHex = await Moralis.switchNetwork("0x13881");
});
}
async function assignPlot() {
const plotID = document.getElementById("plotID").value;
const assigned = await isPlotAssigned(plotID);
if (!assigned) {
const metadata = {
"PlotID":plotID,
"PlotX":document.getElementById("plotX").value,
"PlotY":document.getElementById("plotY").value,
"LocationX":document.getElementById("locationX").value,
"LocationY":document.getElementById("locationX").value,
"image":"https://moralis.io/wp-content/uploads/2021/06/Moralis-Glass-Favicon.svg",
}
const metadataFile = new Moralis.File("metadata.json", {base64 : btoa(JSON.stringify(metadata))});
await metadataFile.saveIPFS();
const metadataURI = metadataFile.ipfs();
await mint(metadataURI);
}
else{
displayMessage("01","Plot is already assigned");
}
}
async function mint(_tokenURI) {
const contractOptions = {
contractAddress: contractAddress,
abi: contractABI,
functionName: "assign",
params: {
tokenURI:_tokenURI,
bytesId:document.getElementById("plotID").value
}
}
try{
const transaction = await Moralis.executeFunction(contractOptions);
await transaction.wait();
displayMessage("00","Transaction confirmed with hash "+transaction.hash);
}
catch(error){
displayMessage("01","Transaction reverted see console for details");
console.log(error)
}
}
async function isPlotAssigned(plotID) {
const contractOptions = {
contractAddress: contractAddress,
abi: contractABI,
functionName: "exist",
params: {
bytesId:plotID
}
}
return await Moralis.executeFunction(contractOptions);
}
Moralis.start({ serverUrl, appId });
login();
drawCanvas();
window.addEventListener('keydown' , (e) => {
move(e.key)
});
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<!--Head Content-->
<title>Land</title>
<!-- Required meta tags -->
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Links -->
<!-- Make It Pretty Import the Bootstrap stylesheet -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">
</head>
<body>
<main>
<div class="container mt-5">
<div class="row">
<h1 class="display-1 text-center text-success" > The Rainbowland</h1>
</div>
<div class="row">
<div class="col-lg-6">
<div class="text-center bg-success text-white">
<h1>Map</h1>
</div>
<div id="MainCanvasDiv" class="text-center">
<canvas id="mainCanvas"></canvas>
</div>
</div>
<div class="col-lg-6">
<div class="text-center bg-success text-white">
<h1>Current Plot</h1>
</div>
<div id="PlotCanvasDiv"class="text-center">
<canvas id="plotCanvas"></canvas>
</div>
<div class="input-group mb-2">
<span class="input-group-text">Plot ID</span>
<input disabled="true" id="plotID" type="text" class="form-control">
</div>
<div class="input-group mb-2">
<span class="input-group-text">Plot Coordinates</span>
<input disabled="true" id="plotX" type="text" class="form-control">
<input disabled="true" id="plotY" type="text" class="form-control">
</div>
<div class="input-group mb-2">
<span class="input-group-text">Location Coordinates</span>
<input disabled="true" id="locationX" type="text" class="form-control">
<input disabled="true" id="locationY" type="text" class="form-control">
</div>
<div class="row">
<button class="btn btn-success btn-block btn-lg" id="claimButton" onclick="assignPlot();">Claim</button>
</div>
</div>
</div>
<hr>
<div class="row">
<div class="text-center bg-success text-white">
<h1>Notifications</h1>
</div>
<div id="notifications" class="container mt-2">
</div>
</div>
</div>
</main>
<!-- Scripts -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-U1DAWAznBHeqEIlVSCgzq+c9gqGAJn5c/t99JyeKa9xxaYpSvHU5awsuZVVFIhvj" crossorigin="anonymous"></script>
<script src="https://unpkg.com/moralis/dist/moralis.js"></script>
<script src="static/js/logic.js"></script>
</body>
</html>
Will appreciate any suggestions. Thank you!