-
-
Save adilanchian/93fbd2e06b3b5d3acb99b5723cebd925 to your computer and use it in GitHub Desktop.
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); | |
wavePortalContract.on("NewWave", (from, timestamp, message) => { | |
console.log("NewWave", from, timestamp, message); | |
setAllWaves(prevState => [...prevState, { | |
address: from, | |
timestamp: new Date(timestamp * 1000), | |
message: message | |
}]); | |
}); | |
} 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); | |
} 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 |
require('@nomiclabs/hardhat-waffle'); | |
require('dotenv').config(); | |
module.exports = { | |
solidity: '0.8.0', | |
networks: { | |
rinkeby: { | |
url: process.env.STAGING_ALCHEMY_KEY, | |
accounts: [process.env.PRIVATE_KEY], | |
}, | |
mainnet: { | |
chainId: 1, | |
url: process.env.PROD_ALCHEMY_KEY, | |
accounts: [process.env.PRIVATE_KEY], | |
}, | |
}, | |
}; |
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 waveTxn = await waveContract.wave('This is wave #1'); | |
await waveTxn.wait(); | |
let waveTxn = await waveContract.wave('This is wave #2'); | |
await waveTxn.wait(); | |
contractBalance = await hre.ethers.provider.getBalance(waveContract.addresss); | |
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(); |
// SPDX-License-Identifier: UNLICENSED | |
pragma solidity ^0.8.0; | |
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; | |
mapping(address => uint256) public lastWavedAt; | |
constructor() payable { | |
console.log("We have been constructed!"); | |
} | |
function wave(string memory _message) public { | |
require( | |
lastWavedAt[msg.sender] + 15 minutes < block.timestamp, | |
"Wait 15m" | |
); | |
lastWavedAt[msg.sender] = block.timestamp; | |
totalWaves += 1; | |
console.log("%s has waved!", msg.sender); | |
waves.push(Wave(msg.sender, _message, block.timestamp)); | |
uint256 randomNumber = (block.difficulty + block.timestamp + seed) % | |
100; | |
console.log("Random # generated: %s", randomNumber); | |
seed = randomNumber; | |
if (randomNumber < 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; | |
} | |
} |
There is a typo error. On line 100 waveportalContract should be wavePortalContract this typo breaks the App.
Also on line 14, const provider = new ethers.providers.Web3Provider is missing "();"
See my fork for the updated version : https://gist.github.com/AymericFerreira/67bb14fe1a73c1b322a54ae28a115c9a
Good catch!
cool
Is this supposed to be the final version? after finishing the 4th step? 🤔
Because i dont see the event listeners for the "NewWave", and also the "getAllWaves" function is not being called anywhere
Same, "getAllWaves" is not called in useEffect in this App.js
Error: missing argument: passed to contract (count=0, expectedCount=1, code=MISSING_ARGUMENT, version=contracts/5.5.0)
at Logger.makeError (index.ts:225:28)
at Logger.throwError (index.ts:237:20)
at Logger.checkArgumentCount (index.ts:296:18)
at index.ts:184:12
at Generator.next ()
at index.ts:1:1
at new Promise ()
at __awaiter5 (index.ts:1:1)
at populateTransaction (index.ts:176:100)
at Contract. (index.ts:422:33)
Error: missing argument: passed to contract (count=0, expectedCount=1, code=MISSING_ARGUMENT, version=contracts/5.5.0) at Logger.makeError (index.ts:225:28) at Logger.throwError (index.ts:237:20) at Logger.checkArgumentCount (index.ts:296:18) at index.ts:184:12 at Generator.next () at index.ts:1:1 at new Promise () at __awaiter5 (index.ts:1:1) at populateTransaction (index.ts:176:100) at Contract. (index.ts:422:33)
check your contract address
Hi, really cool project. For random number I used Chainlink Verifiable Random Function (https://docs.chain.link/docs/get-a-random-number/), check this out if you want to achieve true randomness. Setup is not that complicated
While solving this project I came across this gist page and compared with the project code (while trying testing, etc.).
It seems that this gist page has a different version of implementation of run.js
than the tutorial, and that raises and error that makes it impossible to run it. Also interesting that one of the versions use const
while the other let
.
The tutorial suggests the following:
const waveTxn = await waveContract.wave("This is wave #1");
await waveTxn.wait();
const waveTxn2 = await waveContract.wave("This is wave #2");
await waveTxn2.wait();
While this gist shows the following, with the associated error
let waveTxn = await waveContract.wave('This is wave #1');
await waveTxn.wait();
let waveTxn = await waveContract.wave('This is wave #2'); // Issue is here
await waveTxn.wait(); // and here, see above
error message:
➜ Buildspace-Wave-Portal-Solidity git:(main) ✗ npx hardhat run scripts/run.js
Compiled 1 Solidity file successfully
/Users/xx/Documents/Buildspace-Wave-Portal-Solidity/scripts/run.js:20
let waveTxn = await waveContract.wave('This is wave #2');
^
SyntaxError: Identifier 'waveTxn' has already been declared
This version of the code is different from the one in the lessons.
i.e in App.jsx gaslimit is not applied here with the wave.
This version of the code is different from the one in the lessons. i.e in App.jsx gaslimit is not applied here with the wave.
And also I don't see where the getAllWaves
is being used.
You can call "getAllWaves" after check if has an authorized account. After "setCurrentAccount(...". remember wrapping the "checkIfWalletIsConnected" fn into a callback to avoid looping
Error: call revert exception [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ] (method="getTotalWaves()", data="0x", errorArgs=null, errorName=null, errorSignature=null, reason=null, code=CALL_EXCEPTION, version=abi/5.6.3)
at Logger.makeError (index.ts:261:1)
at Logger.throwError (index.ts:273:1)
at Interface.decodeFunctionResult (interface.ts:427:1)
at Contract. (index.ts:400:1)
at Generator.next ()
at fulfilled (index.ts:1:1)
Also the app doesn't looks like the one shown in the first lesson
hopefully it will be a start for better things
So the getAllWaves
is not used right?
Guys. you are supposed to figure out where to put getAllWaves() by yourselves, that's why its not in the gist.
Great project, I learnt a good deal of new things. Thanks buildspace for the knowledge.
Thanks buildspace.
That's awesome! ✨
Thanks buildspace!
How amazing buildspace made someone with zero experience about developing like me built a blockchain interactive site.
See updates!
https://gist.github.com/letsgitcracking/9b4cafbf04fba420b14918179a5e0745/revisions