Last active
July 17, 2023 18:42
-
-
Save farzaa/5015532446dfdb267711592107a285a9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import './styles/App.css'; | |
import twitterLogo from './assets/twitter-logo.svg'; | |
import { ethers } from "ethers"; | |
import React, { useEffect, useState } from "react"; | |
import myEpicNft from './utils/MyEpicNFT.json'; | |
const TWITTER_HANDLE = '_buildspace'; | |
const TWITTER_LINK = `https://twitter.com/${TWITTER_HANDLE}`; | |
const OPENSEA_LINK = ''; | |
const TOTAL_MINT_COUNT = 50; | |
// I moved the contract address to the top for easy access. | |
const CONTRACT_ADDRESS = "0xF1aD06077E05ebD0e0c0e8eBC104fE436c560D6F"; | |
const App = () => { | |
const [currentAccount, setCurrentAccount] = useState(""); | |
const checkIfWalletIsConnected = async () => { | |
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) | |
// Setup listener! This is for the case where a user comes to our site | |
// and ALREADY had their wallet connected + authorized. | |
setupEventListener() | |
} else { | |
console.log("No authorized account found") | |
} | |
} | |
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]); | |
// Setup listener! This is for the case where a user comes to our site | |
// and connected their wallet for the first time. | |
setupEventListener() | |
} catch (error) { | |
console.log(error) | |
} | |
} | |
// Setup our listener. | |
const setupEventListener = async () => { | |
// Most of this looks the same as our function askContractToMintNft | |
try { | |
const { ethereum } = window; | |
if (ethereum) { | |
// Same stuff again | |
const provider = new ethers.providers.Web3Provider(ethereum); | |
const signer = provider.getSigner(); | |
const connectedContract = new ethers.Contract(CONTRACT_ADDRESS, myEpicNft.abi, signer); | |
// THIS IS THE MAGIC SAUCE. | |
// This will essentially "capture" our event when our contract throws it. | |
// If you're familiar with webhooks, it's very similar to that! | |
connectedContract.on("NewEpicNFTMinted", (from, tokenId) => { | |
console.log(from, tokenId.toNumber()) | |
alert(`Hey there! We've minted your NFT and sent it to your wallet. It may be blank right now. It can take a max of 10 min to show up on OpenSea. Here's the link: https://testnets.opensea.io/assets/${CONTRACT_ADDRESS}/${tokenId.toNumber()}`) | |
}); | |
console.log("Setup event listener!") | |
} else { | |
console.log("Ethereum object doesn't exist!"); | |
} | |
} catch (error) { | |
console.log(error) | |
} | |
} | |
const askContractToMintNft = async () => { | |
try { | |
const { ethereum } = window; | |
if (ethereum) { | |
const provider = new ethers.providers.Web3Provider(ethereum); | |
const signer = provider.getSigner(); | |
const connectedContract = new ethers.Contract(CONTRACT_ADDRESS, myEpicNft.abi, signer); | |
console.log("Going to pop wallet now to pay gas...") | |
let nftTxn = await connectedContract.makeAnEpicNFT(); | |
console.log("Mining...please wait.") | |
await nftTxn.wait(); | |
console.log(nftTxn); | |
console.log(`Mined, see transaction: https://rinkeby.etherscan.io/tx/${nftTxn.hash}`); | |
} else { | |
console.log("Ethereum object doesn't exist!"); | |
} | |
} catch (error) { | |
console.log(error) | |
} | |
} | |
useEffect(() => { | |
checkIfWalletIsConnected(); | |
}, []) | |
const renderNotConnectedContainer = () => ( | |
<button onClick={connectWallet} className="cta-button connect-wallet-button"> | |
Connect to Wallet | |
</button> | |
); | |
const renderMintUI = () => ( | |
<button onClick={askContractToMintNft} className="cta-button connect-wallet-button"> | |
Mint NFT | |
</button> | |
) | |
return ( | |
<div className="App"> | |
<div className="container"> | |
<div className="header-container"> | |
<p className="header gradient-text">My NFT Collection</p> | |
<p className="sub-text"> | |
Each unique. Each beautiful. Discover your NFT today. | |
</p> | |
{currentAccount === "" ? renderNotConnectedContainer() : renderMintUI()} | |
</div> | |
<div className="footer-container"> | |
<img alt="Twitter Logo" className="twitter-logo" src={twitterLogo} /> | |
<a | |
className="footer-text" | |
href={TWITTER_LINK} | |
target="_blank" | |
rel="noreferrer" | |
>{`built on @${TWITTER_HANDLE}`}</a> | |
</div> | |
</div> | |
</div> | |
); | |
}; | |
export default App; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity 0.8.0; | |
import "@openzeppelin/contracts/utils/Strings.sol"; | |
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; | |
import "@openzeppelin/contracts/utils/Counters.sol"; | |
import "hardhat/console.sol"; | |
import { Base64 } from "./libraries/Base64.sol"; | |
contract MyEpicNFT is ERC721URIStorage { | |
using Counters for Counters.Counter; | |
Counters.Counter private _tokenIds; | |
string baseSvg = "<svg xmlns='http://www.w3.org/2000/svg' preserveAspectRatio='xMinYMin meet' viewBox='0 0 350 350'><style>.base { fill: white; font-family: serif; font-size: 24px; }</style><rect width='100%' height='100%' fill='black' /><text x='50%' y='50%' class='base' dominant-baseline='middle' text-anchor='middle'>"; | |
string[] firstWords = ["BLAH", "BLAH", "BLAH"]; | |
string[] secondWords = ["BLAH", "BLAH", "BLAH"]; | |
string[] thirdWords = ["BLAH", "BLAH", "BLAH"]; | |
// MAGICAL EVENTS. | |
event NewEpicNFTMinted(address sender, uint256 tokenId); | |
constructor() ERC721 ("SquareNFT", "SQUARE") { | |
console.log("This is my NFT contract. Woah!"); | |
} | |
function pickRandomFirstWord(uint256 tokenId) public view returns (string memory) { | |
uint256 rand = random(string(abi.encodePacked("FIRST_WORD", Strings.toString(tokenId)))); | |
rand = rand % firstWords.length; | |
return firstWords[rand]; | |
} | |
function pickRandomSecondWord(uint256 tokenId) public view returns (string memory) { | |
uint256 rand = random(string(abi.encodePacked("SECOND_WORD", Strings.toString(tokenId)))); | |
rand = rand % secondWords.length; | |
return secondWords[rand]; | |
} | |
function pickRandomThirdWord(uint256 tokenId) public view returns (string memory) { | |
uint256 rand = random(string(abi.encodePacked("THIRD_WORD", Strings.toString(tokenId)))); | |
rand = rand % thirdWords.length; | |
return thirdWords[rand]; | |
} | |
function random(string memory input) internal pure returns (uint256) { | |
return uint256(keccak256(abi.encodePacked(input))); | |
} | |
function makeAnEpicNFT() public { | |
uint256 newItemId = _tokenIds.current(); | |
string memory first = pickRandomFirstWord(newItemId); | |
string memory second = pickRandomSecondWord(newItemId); | |
string memory third = pickRandomThirdWord(newItemId); | |
string memory combinedWord = string(abi.encodePacked(first, second, third)); | |
string memory finalSvg = string(abi.encodePacked(baseSvg, combinedWord, "</text></svg>")); | |
string memory json = Base64.encode( | |
bytes( | |
string( | |
abi.encodePacked( | |
'{"name": "', | |
combinedWord, | |
'", "description": "A highly acclaimed collection of squares.", "image": "data:image/svg+xml;base64,', | |
Base64.encode(bytes(finalSvg)), | |
'"}' | |
) | |
) | |
) | |
); | |
string memory finalTokenUri = string( | |
abi.encodePacked("data:application/json;base64,", json) | |
); | |
console.log("\n--------------------"); | |
console.log(finalTokenUri); | |
console.log("--------------------\n"); | |
_safeMint(msg.sender, newItemId); | |
_setTokenURI(newItemId, finalTokenUri); | |
_tokenIds.increment(); | |
console.log("An NFT w/ ID %s has been minted to %s", newItemId, msg.sender); | |
// EMIT MAGICAL EVENTS. | |
emit NewEpicNFTMinted(msg.sender, newItemId); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
dont forget to add
// SPDX-License-Identifier: UNLICENSED
at start