This tutorial using Bahasa Indonesia, if you still wanna know, just translate it and good luck!
PC / Laptop / Komputer dengan OS Windows
Discord Buildspace :
Kopi dan ayang, kalo ada
Command prompt (sudah ada di komputer kalian)
Visual Studio Code, download disini :
NodeJS versi 16, download disini :
Buka website ini kemudian klik βStart Buildβ dan login pakai akun Google-mu.
Klik βAdd to Calendarβ dan hubungkan akun Discord-mu, lalu klik βLets go!β
Pada fase βWelcome, let's get you the details!β, isi alasan atau motivasi kamu dalam mengikuti event ini. Gunakan bahasa inggris ya.
Siapkan command prompt (CMD) kamu, lalu lanjut ke fase βGet your local Ethereum networking running - 1β dan pastikan sudah menginstall NodeJS versi 16.
Ketik :
node -vdi CMD, apabila sudah versi 16 maka lanjut ke step berikutnya.ketik ini :
mkdir my-wave-portal
cd my-wave-portal
npm init -y
npm install --save-dev hardhat@latest
Kalo hasilnya seperti berikut, maka lanjut ke step berikutnya ya.


Ketik
npx hardhatlalu pilih βCreate javascriptβ, untuk folder biarkan default saja, kemudian tekanydan enter.setelah selesai, jalankan code berikut :
npm install --save-dev "hardhat@^2.12.2" "@nomicfoundation/hardhat-toolbox@^2.0.0"
maka hasilnya akan kurang lebih seperti ini :

Buka aplikasi VS Code > File > Open Folder > Pilih folder βmy-wave-portalβ yang udah kamu install sebelumnya.
Buat/edit file
hardhat.config.jsdan isi code berikut :
require("@nomicfoundation/hardhat-toolbox");
// This is a sample Hardhat task. To learn how to create your own go to
// https://hardhat.org/guides/create-task.html
task("accounts", "Prints the list of accounts", async (taskArgs, hre) => {
const accounts = await hre.ethers.getSigners();
for (const account of accounts) {
console.log(account.address);
}
});
// You need to export an object to set up your config
// Go to https://hardhat.org/config/ to learn more
/**
* @type import('hardhat/config').HardhatUserConfig
*/
module.exports = {
solidity: "0.8.17",
};
Save, lalu run
npx hardhat nodedi CMD kamu. Nanti disana akan muncul 15 address, TOLONG JANGAN DI CLOSE.Buka CMD baru, lalu ketik code berikut :
cd my-wave-portal
npx hardhat compile
npx hardhat test
hasilnya akan seperti ini, kalo iya silakan lanjut.

Kemudian kembali ke aplikasi VS Code dan silakan hapus file lock.js di folder test, deploy.js di folder scripts, dan lock.sol di folder contracts.
Setelah itu, submit screenshot dari CMD kamu yang berisi 15 alamat di step sebelumnya ke Discord official Buildspace di channel #progress (link Discord ada diatas ya)
Submit juga screenshot tersebut di website Buildspace dengan cara klik βSubmit Requirementβ.

Buka aplikasi VS Code, buat file
WavePortal.soldi dalam foldercontractsisi dengan code berikut :
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;
import "hardhat/console.sol";
contract WavePortal {
constructor() {
console.log("Yo yo, I am a contract and I am smart");
}
}
Download extension Solidity di link berikut :
Screenshot code kamu di
WavePortal.soldan upload di website + Discord Buildspace.
Kembali ke aplikasi VS Code, buat file dengan nama
run.jsdan taruh didalam folderscriptskemudian isi dengan code berikut :
const main = async () => {
const waveContractFactory = await hre.ethers.getContractFactory("WavePortal");
const waveContract = await waveContractFactory.deploy();
await waveContract.deployed();
console.log("Contract deployed to:", waveContract.address);
};
const runMain = async () => {
try {
await main();
process.exit(0); // exit Node process without error
} catch (error) {
console.log(error);
process.exit(1); // exit Node process while indicating 'Uncaught Fatal Exception' error
}
// Read more about Node exit ('process.exit(num)') status codes here: https://stackoverflow.com/a/47163396/7974948
};
runMain();
Buka CMD kamu yang ke-2 (yang sedang nganggur), kemudian tulis command ini
npx hardhat run scripts/run.jsdan screenshot + submit hasil dari command tersebut di Discord + website Buildspace.

Edit file
WavePortal.solyang ada didalam foldercontractsdan isi dengan code berikut :
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;
import "hardhat/console.sol";
contract WavePortal {
uint256 totalWaves;
constructor() {
console.log("Yo yo, I am a contract and I am smart");
}
function wave() public {
totalWaves += 1;
console.log("%s has waved!", msg.sender);
}
function getTotalWaves() public view returns (uint256) {
console.log("We have %d total waves!", totalWaves);
return totalWaves;
}
}
Edit file
run.jsdan isi dengan code berikut :
const main = async () => {
const [owner, randomPerson] = await hre.ethers.getSigners();
const waveContractFactory = await hre.ethers.getContractFactory("WavePortal");
const waveContract = await waveContractFactory.deploy();
await waveContract.deployed();
console.log("Contract deployed to:", waveContract.address);
console.log("Contract deployed by:", owner.address);
await waveContract.getTotalWaves();
const waveTxn = await waveContract.wave();
await waveTxn.wait();
await waveContract.getTotalWaves();
};
const runMain = async () => {
try {
await main();
process.exit(0);
} catch (error) {
console.log(error);
process.exit(1);
}
};
runMain();
Kemudian buka CMD kamu lagi, dan run command ini
npx hardhat run scripts/run.jsdan hasilnya sebagai berikut :

Setelah selesai, buka website Buildspace dan submit kembali. Untuk kata-katanya, isi dengan
Create my first eth contract.
Kembali ke aplikasi VS Code kemudian tambahkan/edit file
deploy.jsdidalam folderscriptsdengan code berikut :
const main = async () => {
const [deployer] = await hre.ethers.getSigners();
const accountBalance = await deployer.getBalance();
console.log("Deploying contracts with account: ", deployer.address);
console.log("Account balance: ", accountBalance.toString());
const waveContractFactory = await hre.ethers.getContractFactory("WavePortal");
const waveContract = await waveContractFactory.deploy();
await waveContract.deployed();
console.log("WavePortal address: ", waveContract.address);
};
const runMain = async () => {
try {
await main();
process.exit(0);
} catch (error) {
console.log(error);
process.exit(1);
}
};
runMain();
kemudian run command berikut (dengan catatan, posisi folder di CMD kamu sekarang berada didalam folder my-wave-portal) :
npx hardhat run scripts/deploy.js --network localhostCopy WavePortal address, dan simpan di tempat terbaik.
Screenshot hasilnya, dan submit di website Buildspace.

Buat akun di Replit, kemudian buka link berikut dan klik βFork Replβ dan langsung tekan enter saja (nama proyek tidak usah dirubah) :

Setelah berhasil, silakan tekan RUN.

Kemudian copy link seperti yang saya tunjuk, lalu submit di website Buildspace.

Buat akun di website QuickNode, kemudian klik βCreate endpointβ :

Step 1 > Pilih Ethereum
Step 2 > Pilih Goerli
Step 3 > Tidak usah di edit, langsung tekan βContinueβ saja.
Pada bagian βPlanβ, pilih yang βDiscoverβ
Create!

Setelah jadi, back-up link kamu di bagian βHTTP Providerβ

Kembali ke CMD kamu yang nganggur, ketik
npm install --save dotenvKembali ke aplikasi VS Code, edit file
hardhat.config.jsdan isi dengan code berikut :
require("@nomicfoundation/hardhat-toolbox");
// Import and configure dotenv
require("dotenv").config();
module.exports = {
solidity: "0.8.17",
networks: {
goerli: {
// This value will be replaced on runtime
url: process.env.STAGING_QUICKNODE_KEY,
accounts: [process.env.PRIVATE_KEY],
},
},
};
Setelah itu, kembali ke CMD dan ketik
echo test>.env, hasilnya seperti berikut :

Kemudian cek di aplikasi VS Code, nanti akan ada muncul file baru dengan nama
.env, edit file tersebut dan isi ini :
STAGING_QUICKNODE_KEY=isi_dengan_https_dari_QuickNode_tadi
PRIVATE_KEY=isi_dengan_private_key_metamask_kamu
Save, kemudian run command
npx hardhat run scripts/deploy.js --network goerlidi CMD dan hasilnya seperti :

Silakan buka website berikut dan ambil LINK TRANSAKSI HASH kamu disana :
Submit link tersebut di website Buildspace
Kembali buka akun Replit kamu, buka folder
srcdan edit fileApp.jsxdan replace code tersebut dengan ini ya ges ya :
import React, { useEffect, useState } from "react";
import "./App.css";
const getEthereumObject = () => window.ethereum;
/*
* This function returns the first linked account found.
* If there is no account linked, it will return null.
*/
const findMetaMaskAccount = async () => {
try {
const ethereum = getEthereumObject();
/*
* First make sure we have access to the Ethereum object.
*/
if (!ethereum) {
console.error("Make sure you have Metamask!");
return null;
}
console.log("We have the Ethereum object", ethereum);
const accounts = await ethereum.request({ method: "eth_accounts" });
if (accounts.length !== 0) {
const account = accounts[0];
console.log("Found an authorized account:", account);
return account;
} else {
console.error("No authorized account found");
return null;
}
} catch (error) {
console.error(error);
return null;
}
};
const App = () => {
const [currentAccount, setCurrentAccount] = useState("");
const connectWallet = async () => {
try {
const ethereum = getEthereumObject();
if (!ethereum) {
alert("Get MetaMask!");
return;
}
const accounts = await ethereum.request({
method: "eth_requestAccounts",
});
console.log("Connected", accounts[0]);
setCurrentAccount(accounts[0]);
} catch (error) {
console.error(error);
}
};
/*
* This runs our function when the page loads.
* More technically, when the App component "mounts".
*/
useEffect(async () => {
const account = await findMetaMaskAccount();
if (account !== null) {
setCurrentAccount(account);
}
}, []);
return (
<div className="mainContainer">
<div className="dataContainer">
<div className="header">
π Hey there!
</div>
<div className="bio">
I am Farza and I worked on self-driving cars so that's pretty cool
right? Connect your Ethereum wallet and wave at me!
</div>
<button className="waveButton" onClick={null}>
Wave at Me
</button>
{/*
* If there is no currentAccount render this button
*/}
{!currentAccount && (
<button className="waveButton" onClick={connectWallet}>
Connect Wallet
</button>
)}
</div>
</div>
);
};
export default App;
Tekan βRUNβ kembali, seperti di step sebelumnya.
Nanti hasilnya seperti ini :

Silakan koneksikan wallet yang private-key nya sudah kamu submit tadi di website tersebut.
Buka website Buildspace kembali, klik βSubmit Requirementβ dan isi form tersebut dengan kalimat indahmu ;)
Kembali ke Replit lagi, kita edit file
App.jsxlagi dan isi dengan code berikut :
import React, { useEffect, useState } from "react";
import { ethers } from "ethers";
import './App.css';
import abi from './utils/WavePortal.json';
const App = () => {
const [currentAccount, setCurrentAccount] = useState("");
/**
* Create a varaible here that holds the contract address after you deploy!
*/
const contractAddress = "0xd5f08a0ae197482FA808cE84E00E97d940dBD26E";
const contractABI = abi.abi;
const checkIfWalletIsConnected = async () => {
try {
const { ethereum } = window;
if (!ethereum) {
console.log("Make sure you have metamask!");
return;
} else {
console.log("We have the ethereum object", ethereum);
}
const accounts = await ethereum.request({ method: 'eth_accounts' });
if (accounts.length !== 0) {
const account = accounts[0];
console.log("Found an authorized account:", account);
setCurrentAccount(account)
} else {
console.log("No authorized account found")
}
} catch (error) {
console.log(error);
}
}
const connectWallet = async () => {
try {
const { ethereum } = window;
if (!ethereum) {
alert("Get MetaMask!");
return;
}
const accounts = await ethereum.request({ method: "eth_requestAccounts" });
console.log("Connected", accounts[0]);
setCurrentAccount(accounts[0]);
} catch (error) {
console.log(error)
}
}
const wave = async () => {
try {
const { ethereum } = window;
if (ethereum) {
const provider = new ethers.providers.Web3Provider(ethereum);
const signer = provider.getSigner();
const wavePortalContract = new ethers.Contract(contractAddress, contractABI, signer);
let count = await wavePortalContract.getTotalWaves();
console.log("Retrieved total wave count...", count.toNumber());
const waveTxn = await wavePortalContract.wave();
console.log("Mining...", waveTxn.hash);
await waveTxn.wait();
console.log("Mined -- ", waveTxn.hash);
count = await wavePortalContract.getTotalWaves();
console.log("Retrieved total wave count...", count.toNumber());
} else {
console.log("Ethereum object doesn't exist!");
}
} catch (error) {
console.log(error)
}
}
useEffect(() => {
checkIfWalletIsConnected();
}, [])
return (
<div className="mainContainer">
<div className="dataContainer">
<div className="header">
π Hey there!
</div>
<div className="bio">
I am farza and I worked on self-driving cars so that's pretty cool right? Connect your Ethereum wallet and wave at me!
</div>
<button className="waveButton" onClick={wave}>
Wave at Me
</button>
{!currentAccount && (
<button className="waveButton" onClick={connectWallet}>
Connect Wallet
</button>
)}
</div>
</div>
);
}
export default App
Pada bagian
const contractAddress, silakan ganti0xblablabladengan address WavePortal yang kita dapat dari step tutorial 5.Kembali ke Replit lagi, silakan buat folder dengan nama
srcdidalam folderutils, dan buat file dengan nama `WavePortal.json`.

Kembali ke VS Code lalu buka file ini
artifacts/contracts/WavePortal.sol/WavePortal.json, kemudian ambil isinya dan paste ke file di Replit yang baru kita buat tadi.Setelah itu, buka website yang kamu generate di Replit, klik βConnectβ, dan klik βWave at Meβ.
Terima approval yang muncul di Metamask jaringan GOERLI.
Screenshot website kamu, dan upload di website Buildspace <3

Kembali ke VS Code, dan edit file
WavePortal.solyang kita buat diawal tadi.
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;
import "hardhat/console.sol";
contract WavePortal {
uint256 totalWaves;
/*
* A little magic, Google what events are in Solidity!
*/
event NewWave(address indexed from, uint256 timestamp, string message);
/*
* I created a struct here named Wave.
* A struct is basically a custom datatype where we can customize what we want to hold inside it.
*/
struct Wave {
address waver; // The address of the user who waved.
string message; // The message the user sent.
uint256 timestamp; // The timestamp when the user waved.
}
/*
* I declare a variable waves that lets me store an array of structs.
* This is what lets me hold all the waves anyone ever sends to me!
*/
Wave[] waves;
constructor() {
console.log("I AM SMART CONTRACT. POG.");
}
/*
* You'll notice I changed the wave function a little here as well and
* now it requires a string called _message. This is the message our user
* sends us from the frontend!
*/
function wave(string memory _message) public {
totalWaves += 1;
console.log("%s waved w/ message %s", msg.sender, _message);
/*
* This is where I actually store the wave data in the array.
*/
waves.push(Wave(msg.sender, _message, block.timestamp));
/*
* I added some fanciness here, Google it and try to figure out what it is!
* Let me know what you learn in #general-chill-chat
*/
emit NewWave(msg.sender, block.timestamp, _message);
}
/*
* I added a function getAllWaves which will return the struct array, waves, to us.
* This will make it easy to retrieve the waves from our website!
*/
function getAllWaves() public view returns (Wave[] memory) {
return waves;
}
function getTotalWaves() public view returns (uint256) {
// Optional: Add this line if you want to see the contract print the value!
// We'll also print it over in run.js as well.
console.log("We have %d total waves!", totalWaves);
return totalWaves;
}
}
Edit file
run.jsdengan ini :
const main = async () => {
const waveContractFactory = await hre.ethers.getContractFactory("WavePortal");
const waveContract = await waveContractFactory.deploy();
await waveContract.deployed();
console.log("Contract addy:", waveContract.address);
let waveCount;
waveCount = await waveContract.getTotalWaves();
console.log(waveCount.toNumber());
/**
* Let's send a few waves!
*/
let waveTxn = await waveContract.wave("A message!");
await waveTxn.wait(); // Wait for the transaction to be mined
const [_, randomPerson] = await hre.ethers.getSigners();
waveTxn = await waveContract.connect(randomPerson).wave("Another message!");
await waveTxn.wait(); // Wait for the transaction to be mined
let allWaves = await waveContract.getAllWaves();
console.log(allWaves);
};
const runMain = async () => {
try {
await main();
process.exit(0);
} catch (error) {
console.log(error);
process.exit(1);
}
};
runMain();
Buka CMD kamu yang nganggur, dan ketik command ini
npx hardhat run scripts/run.jsdan liat hasilnya.

Kita run ulang command berikut dan SAVE WavePortal address kamu :
npx hardhat run scripts/deploy.js --network goerliBuka Replit lagi, dan edit contractAddress di file
App.jsdan replace dengan WavePortal yang baru kamu generate.(OPSIONAL) kamu bisa pakai code lain di
App.js, semisal ingin membuat tampilannya lebih baik ~ Berikut codenya (INGAT, INI OPSIONAL) :
import React,{useEffect,useState} from "react";
import { ethers } from "ethers";
import './App.css';
import abi from './utils/WavePortal.json';
export default function App() {
const [currentAccount,setCurrentAccount]=useState("");
const [totalWaves,setTotalWaves]=useState();
const [allwaves,setAllwaves]=useState([]);
const [inputValue,setInputValue]= useState('');
const contractAddress = "0xD014C8260bbF382D2ecCf0eb832c20A38c070F3b";
const contractABI = abi.abi;
const chainId = `0x5`;
const rpcURL = 'https://rpc.ankr.com/eth_goerli';
const networkName = 'Goerli Network';
const currencyName = 'ETH';
const currencySymbol = 'ETH';
const explorerURL = 'https://goerli.etherscan.io/';
const addNetwork = async () => {
await window.ethereum.request({
method: 'wallet_addEthereumChain',
params: [
{
chainId: chainId,
chainName: networkName,
rpcUrls: [rpcURL],
blockExplorerUrls: [explorerURL],
nativeCurrency: {
name: currencyName,
symbol: currencySymbol, // 2-6 characters long
decimals: 18,
},
},
],
});
// refresh
window.location.reload();
};
const checkIfWalletIsConnected = async ()=>{
try {
const {ethereum} = window;
if(!ethereum){
console.log("make sure you have metamask");
return;
}else{
console.log("we have the etherum object")
}
const accounts = await ethereum.request({method: "eth_accounts"})
if(accounts.length!==0){
const account = accounts[0];
await getAllWaves();
setCurrentAccount(account);
}else{
console.log("No authorized account found")
}
} catch (error) {
console.log(error);
}
}
const wave = async () => {
try {
const {ethereum} = window;
if(ethereum){
const provider = new ethers.providers.Web3Provider(ethereum);
const signer = provider.getSigner();
const wavePortalContract = new ethers.Contract(contractAddress, contractABI, signer);
let count = await wavePortalContract.getTotalWaves();
console.log("Retrieved total wave count...", count.toNumber());
const waveTxn = await wavePortalContract.wave(inputValue,{gasLimit: 300000});
console.log("Mining...", waveTxn.hash);
await waveTxn.wait();
console.log("Mined -- ", waveTxn.hash);
count = await wavePortalContract.getTotalWaves();
// await getAllWaves();
setTotalWaves(count.toNumber());
console.log("Retrieved total wave count...", count.toNumber());
}else{
console.log("ethereum object doesn't exist")
}
} catch (error) {
console.log(error);
}
}
const connectWallet = async () => {
try {
const { ethereum } = window;
if (!ethereum) {
alert("Get MetaMask!");
return;
}
const accounts = await ethereum.request({ method: "eth_requestAccounts" });
console.log("Connected", accounts[0]);
setCurrentAccount(accounts[0]);
} catch (error) {
console.log(error)
}
}
useEffect(()=>{
checkIfWalletIsConnected();
},[currentAccount])
const fetchTotal = async ()=>{
const {ethereum} = window;
if(ethereum){
const provider = new ethers.providers.Web3Provider(ethereum);
const signer = provider.getSigner();
const wavePortalContract = new ethers.Contract(contractAddress, contractABI, signer);
let count = await wavePortalContract.getTotalWaves();
setTotalWaves(count.toNumber());
console.log("Retrieved total wave count...", count.toNumber());
}else{
console.log("ethereum object doesn't exist")
}
}
useEffect(async ()=>{
await fetchTotal();
},[totalWaves])
const getAllWaves=async ()=>{
try {
if(ethereum){
const provider = new ethers.providers.Web3Provider(ethereum);
const signer = provider.getSigner();
const wavePortalContract = new ethers.Contract(contractAddress, contractABI, signer);
const waves = await wavePortalContract.getAllWaves();
console.log(waves);
let wavesArr = [];
waves.forEach(wave => {
wavesArr.push({
address: wave.waver,
timestamp: new Date(wave.timestamp * 1000),
message: wave.message
});
});
setAllwaves(wavesArr);
}
} catch (error) {
console.log(error);
}
}
useEffect(()=>{
let wavePortalContract;
const onNewWave = (from, timestamp, message) => {
console.log('NewWave', from, timestamp, message);
setAllwaves(prevState => [
...prevState,
{
address: from,
timestamp: new Date(timestamp * 1000),
message: message,
},
]);
};
if (window.ethereum) {
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
wavePortalContract = new ethers.Contract(contractAddress, contractABI, signer);
wavePortalContract.on('NewWave', onNewWave);
}
return () => {
if (wavePortalContract) {
wavePortalContract.off('NewWave', onNewWave);
}
};
},[])
return (
<div className="mainContainer">
<div className="dataContainer">
<div className="header">
<div>π Hey there!</div>
<div className="add" onClick={addNetwork}>Add Goerli to Wallet</div>
</div>
<div className="bio">
I am farza and I worked on self-driving cars so that's pretty cool right? Connect your Ethereum wallet and wave at me!
</div>
<div className="inputWrapper">
<input className="messageBox" placeholder="Please input wave message" onChange={(e)=>{
setInputValue(e.target.value);
}}></input>
<button className="waveButton" onClick={wave}>
Wave at Me
</button>
</div>
{!currentAccount&&(
<button className="connectButton" onClick={connectWallet}>Connect Wallet</button>
)}
<div>
TotalWaves: {totalWaves}
</div>
{allwaves.map((wave,index)=>{
return (
<div key={index} className="messageCard">
<div>Address: {wave.address}</div>
<div>Timestamp: {wave.timestamp.toString()}</div>
<div>Message: {wave.message}</div>
</div>
)
})}
</div>
</div>
);
}
Buka website hasil generate di Replit, dan liat tampilannya sekarang.
Silakan screenshot dan submit di Discord dan website Buildspace.

Kembali ke Replit, edit file
App.jsdengan code berikut :
import React, { useEffect, useState } from "react";
import { ethers } from "ethers";
import './App.css';
import wavePortal from './utils/WavePortal.json';
const App = () => {
const [currentAccount, setCurrentAccount] = useState("");
const [allWaves, setAllWaves] = useState([]);
const contractAddress = "0xd5f08a0ae197482FA808cE84E00E97d940dBD26E";
const getAllWaves = async () => {
try {
if (window.ethereum) {
const provider = new ethers.providers.Web3Provider
const signer = provider.getSigner();
const wavePortalContract = new ethers.Contract(contractAddress, wavePortal.abi, signer);
const waves = await wavePortalContract.getAllWaves();
let wavesCleaned = [];
waves.forEach(wave => {
wavesCleaned.push({
address: wave.waver,
timestamp: new Date(wave.timestamp * 1000),
message: wave.message
});
});
setAllWaves(wavesCleaned);
} else {
console.log("Ethereum object doesn't exist!")
}
} catch (error) {
console.log(error);
}
}
const checkIfWalletIsConnected = async () => {
try {
const { ethereum } = window;
if (!ethereum) {
console.log("Make sure you have metamask!");
return;
} else {
console.log("We have the ethereum object", ethereum);
}
const accounts = await ethereum.request({ method: 'eth_accounts' });
if (accounts.length !== 0) {
const account = accounts[0];
console.log("Found an authorized account:", account);
setCurrentAccount(account)
} else {
console.log("No authorized account found")
}
} catch (error) {
console.log(error);
}
}
const connectWallet = async () => {
try {
const { ethereum } = window;
if (!ethereum) {
alert("Get MetaMask!");
return;
}
const accounts = await ethereum.request({ method: "eth_requestAccounts" });
console.log("Connected", accounts[0]);
setCurrentAccount(accounts[0]);
} catch (error) {
console.log(error)
}
}
const wave = async () => {
try {
const { ethereum } = window;
if (ethereum) {
const provider = new ethers.providers.Web3Provider(ethereum);
const signer = provider.getSigner();
const wavePortalContract = new ethers.Contract(contractAddress, wavePortal.abi, signer);
let count = await wavePortalContract.getTotalWaves();
console.log("Retrieved total wave count...", count.toNumber());
const waveTxn = await wavePortalContract.wave();
console.log("Mining...", waveTxn.hash);
await waveTxn.wait();
console.log("Mined -- ", waveTxn.hash);
count = await wavePortalContract.getTotalWaves();
console.log("Retrieved total wave count...", count.toNumber());
} else {
console.log("Ethereum object doesn't exist!");
}
} catch (error) {
console.log(error)
}
}
useEffect(() => {
checkIfWalletIsConnected();
}, [])
return (
<div className="mainContainer">
<div className="dataContainer">
<div className="header">
π Hey there!
</div>
<div className="bio">
I am farza and I worked on self-driving cars so that's pretty cool right? Connect your Ethereum wallet and wave at me!
</div>
<button className="waveButton" onClick={wave}>
Wave at Me
</button>
{!currentAccount && (
<button className="waveButton" onClick={connectWallet}>
Connect Wallet
</button>
)}
{allWaves.map((wave, index) => {
return (
<div style={{ backgroundColor: "OldLace", marginTop: "16px", padding: "8px" }}>
<div>Address: {wave.address}</div>
<div>Time: {wave.timestamp.toString()}</div>
<div>Message: {wave.message}</div>
</div>)
})}
</div>
</div>
);
}
export default App
Buka aplikasi VS Code di komputermu, dan edit
deploy.jsjadi begini :
const main = async () => {
const waveContractFactory = await hre.ethers.getContractFactory('WavePortal');
const waveContract = await waveContractFactory.deploy({
value: hre.ethers.utils.parseEther('0.001'),
});
await waveContract.deployed();
console.log('WavePortal address: ', waveContract.address);
};
const runMain = async () => {
try {
await main();
process.exit(0);
} catch (error) {
console.error(error);
process.exit(1);
}
};
runMain();
Masih di VS Code, edit file
run.jsjadi begini :
const main = async () => {
const waveContractFactory = await hre.ethers.getContractFactory('WavePortal');
const waveContract = await waveContractFactory.deploy({
value: hre.ethers.utils.parseEther('0.01'),
});
await waveContract.deployed();
console.log('Contract addy:', waveContract.address);
let contractBalance = await hre.ethers.provider.getBalance(
waveContract.address
);
console.log(
'Contract balance:',
hre.ethers.utils.formatEther(contractBalance)
);
let waveTxn = await waveContract.wave('A message!');
await waveTxn.wait();
contractBalance = await hre.ethers.provider.getBalance(waveContract.address);
console.log(
'Contract balance:',
hre.ethers.utils.formatEther(contractBalance)
);
let allWaves = await waveContract.getAllWaves();
console.log(allWaves);
};
const runMain = async () => {
try {
await main();
process.exit(0);
} catch (error) {
console.log(error);
process.exit(1);
}
};
runMain();
Masih di VS Code ya ges ya, edit file
WavePortal.soldengan code :
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import "hardhat/console.sol";
contract WavePortal {
uint256 totalWaves;
event NewWave(address indexed from, uint256 timestamp, string message);
struct Wave {
address waver;
string message;
uint256 timestamp;
}
Wave[] waves;
constructor() payable {
console.log("We have been constructed!");
}
function wave(string memory _message) public {
totalWaves += 1;
console.log("%s has waved!", msg.sender);
waves.push(Wave(msg.sender, _message, block.timestamp));
emit NewWave(msg.sender, block.timestamp, _message);
uint256 prizeAmount = 0.0001 ether;
require(
prizeAmount <= address(this).balance,
"Trying to withdraw more money than they contract has."
);
(bool success, ) = (msg.sender).call{value: prizeAmount}("");
require(success, "Failed to withdraw money from contract.");
}
function getAllWaves() public view returns (Wave[] memory) {
return waves;
}
function getTotalWaves() public view returns (uint256) {
return totalWaves;
}
}
Run command berikut di CMD, untuk ngecek hasil dari code-code diatas :
npx hardhat run scripts/run.jsHasilnya seperti ini :

Kemudian, kita coba deploy kontrak baru dengan cara
npx hardhat run scripts/deploy.js --network goerlidi CMD kamu.Setelah itu, cek hasilnya di :
https://goerli.etherscan.io/?utm_source=buildspace.so&utm_medium=buildspace_project
Submit hasilnya di website Buildspace.
Kembali ke VSC, edit file
WavePortal.soldengan ini :
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import "hardhat/console.sol";
contract WavePortal {
uint256 totalWaves;
/*
* We will be using this below to help generate a random number
*/
uint256 private seed;
event NewWave(address indexed from, uint256 timestamp, string message);
struct Wave {
address waver;
string message;
uint256 timestamp;
}
Wave[] waves;
constructor() payable {
console.log("We have been constructed!");
/*
* Set the initial seed
*/
seed = (block.timestamp + block.difficulty) % 100;
}
function wave(string memory _message) public {
totalWaves += 1;
console.log("%s has waved!", msg.sender);
waves.push(Wave(msg.sender, _message, block.timestamp));
/*
* Generate a new seed for the next user that sends a wave
*/
seed = (block.difficulty + block.timestamp + seed) % 100;
console.log("Random # generated: %d", seed);
/*
* Give a 50% chance that the user wins the prize.
*/
if (seed < 50) {
console.log("%s won!", msg.sender);
/*
* The same code we had before to send the prize.
*/
uint256 prizeAmount = 0.0001 ether;
require(
prizeAmount <= address(this).balance,
"Trying to withdraw more money than the contract has."
);
(bool success, ) = (msg.sender).call{value: prizeAmount}("");
require(success, "Failed to withdraw money from contract.");
}
emit NewWave(msg.sender, block.timestamp, _message);
}
function getAllWaves() public view returns (Wave[] memory) {
return waves;
}
function getTotalWaves() public view returns (uint256) {
return totalWaves;
}
}
Edit
run.jsdengan ini :
const main = async () => {
const waveContractFactory = await hre.ethers.getContractFactory("WavePortal");
const waveContract = await waveContractFactory.deploy({
value: hre.ethers.utils.parseEther("0.1"),
});
await waveContract.deployed();
console.log("Contract addy:", waveContract.address);
let contractBalance = await hre.ethers.provider.getBalance(
waveContract.address
);
console.log(
"Contract balance:",
hre.ethers.utils.formatEther(contractBalance)
);
/*
* Let's try two waves now
*/
const waveTxn = await waveContract.wave("This is wave #1");
await waveTxn.wait();
const waveTxn2 = await waveContract.wave("This is wave #2");
await waveTxn2.wait();
contractBalance = await hre.ethers.provider.getBalance(waveContract.address);
console.log(
"Contract balance:",
hre.ethers.utils.formatEther(contractBalance)
);
let allWaves = await waveContract.getAllWaves();
console.log(allWaves);
};
const runMain = async () => {
try {
await main();
process.exit(0);
} catch (error) {
console.log(error);
process.exit(1);
}
};
runMain();
Kemudian run command berikut di CMD kamu yang nganggur :
npx hardhat run scripts/run.jsHasilnya :

Kita edit kembali file
WavePortal.soldan isi dengan ini :
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;
import "hardhat/console.sol";
contract WavePortal {
uint256 totalWaves;
uint256 private seed;
event NewWave(address indexed from, uint256 timestamp, string message);
struct Wave {
address waver;
string message;
uint256 timestamp;
}
Wave[] waves;
/*
* This is an address => uint mapping, meaning I can associate an address with a number!
* In this case, I'll be storing the address with the last time the user waved at us.
*/
mapping(address => uint256) public lastWavedAt;
constructor() payable {
console.log("We have been constructed!");
/*
* Set the initial seed
*/
seed = (block.timestamp + block.difficulty) % 100;
}
function wave(string memory _message) public {
/*
* We need to make sure the current timestamp is at least 15-minutes bigger than the last timestamp we stored
*/
require(
lastWavedAt[msg.sender] + 15 minutes < block.timestamp,
"Wait 15m"
);
/*
* Update the current timestamp we have for the user
*/
lastWavedAt[msg.sender] = block.timestamp;
totalWaves += 1;
console.log("%s has waved!", msg.sender);
waves.push(Wave(msg.sender, _message, block.timestamp));
/*
* Generate a new seed for the next user that sends a wave
*/
seed = (block.difficulty + block.timestamp + seed) % 100;
if (seed <= 50) {
console.log("%s won!", msg.sender);
uint256 prizeAmount = 0.0001 ether;
require(
prizeAmount <= address(this).balance,
"Trying to withdraw more money than they contract has."
);
(bool success, ) = (msg.sender).call{value: prizeAmount}("");
require(success, "Failed to withdraw money from contract.");
}
emit NewWave(msg.sender, block.timestamp, _message);
}
function getAllWaves() public view returns (Wave[] memory) {
return waves;
}
function getTotalWaves() public view returns (uint256) {
return totalWaves;
}
}
Setelah itu, buka CMD dan run ini :
npx hardhat run scripts/run.jsNanti disana akan ada error, silakan tunggu 15 menit kemudian RUN lagi. Contoh bisa diliat sebagai berikut :

Setelah kamu run lagi dan hash-nya muncul, silakan ke explorer Goerli dan copy link-nya. Kemudian, submit di website Buildspace.
Buka website hasil generate di Replit, kemudian edit sesuka hati.
Screenshot, submit di website Buildspace.

Done!
Jadi kalian perlu ngebuka setidaknya 2-3 command prompt, 1 untuk yg idle atau standby, sisanya untuk ngegarap semua command yang ada.
Pengiriman hadiah NFT dilakukan dalam 7 hari.
Jika ada pertanyaan, silakan tanyakan di grup Telegram :
Credits :

