Create a simple NFT minting website | BlockTrain
Créer un site Web de frappe NFT simple
Qu'allons-nous construire ?đ€
Nous allons créer un DAPP qui permet aux utilisateurs de connecter leur portefeuille et de créer des NFT à partir de notre contrat, cela semble incroyable, n'est-ce pas ?
Nous rédigerons un petit contrat ERC721 que nous déploierons sur un testnet et créerons des NFT à partir de celui-ci. Pour l'interface, nous utiliserons l'application React , et pour l'intégration du portefeuille, nous utiliserons RainbowKit , qui est un portefeuille, mais dispose également d'un SDK qui permet aux développeurs d'intégrer les connexions de portefeuille de maniÚre transparente. Ensuite, nous utiliserons Wagmi pour utiliser notre contrat (récupérer notre contrat) et l'utiliser dans notre interface, wagmi est une bibliothÚque qui est une collection de crochets de réaction contenant tout ce dont vous avez besoin pour commencer à travailler avec Ethereum.
Si cela ne semble pas excitant, je ne sais pas ce qui se passe :)
đ PrĂ©requis
- Compréhension de base de ce que sont les NFT
- Connaissances de base en HTML, CSS, JS
- Petite curiosité :)
đ RĂ©diger un contrat ERC721
Avant de crĂ©er notre DAPP de frappe, nous aurons besoin d'un contrat Ă partir duquel nous frapperons nos NFT, ne vous inquiĂ©tez pas si vous ne savez pas comment rĂ©diger des contrats intelligents, nous avons dĂ©jĂ des projets dĂ©taillĂ©s sur les NFT comme DĂ©marrer avec DĂ©veloppement NFT et comment crĂ©er un contrat NFT avec des mĂ©tadonnĂ©es en chaĂźne, cela pourrait ĂȘtre un bon point de dĂ©part si vous cherchez Ă comprendre les contrats intelligents NFT, restez Ă©galement Ă l'Ă©coute car nous allons bientĂŽt abandonner beaucoup de projetsđ
Passons Ă Openzeppelin Wizard et obtenons un contrat passe-partout
Ici, nous ajoutons d'abord le nom et le symbole du contrat, cela sera utilisé comme identifiant sur les places de marché etherscan et NFT
Vient ensuite l'URI de base, ne vous inquiĂ©tez pas pour cela, nous allons bientĂŽt dĂ©poser un projet sur les NFT musicaux oĂč je vais couvrir cela en dĂ©tail, pour l'instant vous pouvez utiliser mon lien ipfs hĂ©bergĂ© :
ipfs://bafybeidt5boy4ousc3jl7v6v5xvle6ybiteqduek7moil6gtzajazfxq2y/
mais rappelez-vous simplement que cela est une référence à nos NFT, il contient nos métadonnées NFT et ressemble à ceci lorsqu'il est ouvertet le fichier individuel est un fichier json qui contient des métadonnées pour NFT, qui ressemble à ceci
{ "image": "ipfs://bafybeihqsmqlnd7ifiwuaso6petbaxkux5s2bs7rzncpzepw2kvy5w4vfu/0.png", "name": "DAPE #0", "description": "Demo using a small collection of Degenerate Apes.", "external_url": "https://twitter.com/Deveshb15", "attributes": [ { "trait_type": "Background", "value": "Magic Mint" }, { "trait_type": "Skin", "value": "Camo Coral" }, { "trait_type": "Expression", "value": "Excited" } ] }
Il s'agit de la norme de métadonnées pour ERC721
Viennent ensuite les fonctionnalités et nous sélectionnerons Mintable qui permettra aux utilisateurs de créer, des identifiants d'auto-incrémentation qui seront utilisés pour incrémenter les tokenIds des NFT à chaque fois qu'un nouveau est créé, et le stockage d'URI pour s'assurer que notre baseURI est ajouté avec
/${tokenId}.json
cause c'est comme ça nos métadonnées NFT individuelles seront accessibles.
Ouvrons maintenant cela dans Remix , qui est une idée en ligne pour compiler et déployer des contrats intelligents.
Nous allons juste apporter quelques modifications au contrat, le contrat final devrait ressembler Ă ceci :
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts@4.7.3/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts@4.7.3/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts@4.7.3/access/Ownable.sol";
import "@openzeppelin/contracts@4.7.3/utils/Counters.sol";
contract Blocktrain is ERC721, ERC721URIStorage, Ownable {
using Counters for Counters.Counter;
Counters.Counter private _tokenIdCounter;
uint256 public mintRate = 0.00069 ether;
constructor() ERC721("Blocktrain", "BNT") {}
function _baseURI() internal pure override returns (string memory) {
return "ipfs://bafybeidt5boy4ousc3jl7v6v5xvle6ybiteqduek7moil6gtzajazfxq2y/";
}
function safeMint() public payable {
require(msg.value >= mintRate, "Not enough ether");
uint256 tokenId = _tokenIdCounter.current();
_tokenIdCounter.increment();
_safeMint(msg.sender, tokenId);
}
// The following functions are overrides required by Solidity.
function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {
super._burn(tokenId);
}
function tokenURI(uint256 tokenId)
public
view
override(ERC721, ERC721URIStorage)
returns (string memory)
{
require(_exists(tokenId), "Token doesn't exists");
return string(abi.encodePacked(_baseURI(), Strings.toString(tokenId), '.json'));
}
}
Ici, nous avons changé safeMint()
la fonction pour frapper NFT à la personne qui frappe (msg.sender) et avons supprimé le onlyOwner
modificateur afin que n'importe qui puisse frapper le NFT, j'ai Ă©galement rendu la safeMint()
fonction payante et ajouté un mintRate
pour définir le taux de frappe NFT que l'utilisateur devra payer frapper le NFT c'est ainsi que le créateur gagne généralement en dehors de la redevance secondaire, ensuite j'ai changé la tokenURI()
fonction pour ajouter le /${tokenId}.json
Ă la fin du baseURI
.
Compilons maintenant notre contrat et déployons-le sur Goerli Testnet , si vous ne savez pas comment obtenir gratuitement testnet ETH, je l'ai expliqué dans Créer un contrat NFT avec des métadonnées en chaßne
Une fois que vous obtenez du testnet ETH, laissez aller Ă Remix et appuyez sur Ctrl+S
ceci pour compiler le contrat :
Une fois le contrat compilĂ©, dĂ©ployons-le sur Goerli Testnet , changeons l'environnement en Injected Metamask et assurons-nous que vous ĂȘtes sur Goerli Network dans Metamask et Deploy .
Il ouvrira une fenĂȘtre contextuelle Metamask, confirmez simplement et votre contrat sera dĂ©ployĂ©, vous pouvez Ă©galement consulter votre contrat sur goerli.etherscan.io , copiez simplement l' adresse du contrat Ă l'aide de ce bouton
et collez-le sur goerli.etherscan.io
Maintenant que notre contrat est prĂȘt, revenons Ă notre DAPP de frappe.
đ Explication : Que signifie frapper un NFT ?
Frapper signifie littĂ©ralement crĂ©er quelque chose ou quelque chose qui est produit Ă ce moment-lĂ Ă partir de zĂ©ro. Fondamentalement, cela signifie simplement que vous venez de donner naissance Ă un NFT hehe, c'est peut-ĂȘtre l'analogie la plus simple que vous comprendrez.
En termes de blockchain, cela signifie que NFT est né/produit à ce moment-là , c'est la raison pour laquelle il est transféré 0x0000000000000000000000000000000000000000
(que vous pouvez considérer comme le trou noir de la blockchain, c'est une abréviation de l'adresse de genÚse) à votre adresse, vous peut le voir magnifiquement sur Opensea
Une fois que l'actif est frappĂ©, il s'agit officiellement d'un NFT et il peut ĂȘtre vendu sur n'importe quel marchĂ© NFT.
✍️ CrĂ©ez une application React pour frapper nos NFT
Installons et configurons une application de réaction à l'aide du package cra(create-react-app).
Ouvrez votre terminal et cd dans le dossier oĂč vous souhaitez crĂ©er le DAPP de frappe NFT .
Exécutez cette commande pour installer et configurer React :
npx create-react-app nft-minting-dapp
Cela peut prendre quelques minutes, selon votre machine, mais une fois qu'il est installé, il suffit de le cd dans le projet et nous installerons le CSS tailwind pour notre CSS. J'utilise tailwind mais n'hésitez pas à utiliser ce que vous voulez.
cd nft-minting-dapp
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
Une fois que vous avez exécuté ces commandes, ouvrons le dossier dans un éditeur de code, j'utilise personnellement VS Code.
Ouvrez-le tailwind.config.js
et remplacez-le par :
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
Ajoutons maintenant les @tailwind
directives ** ** pour chacune des couches de Tailwind Ă votre ./src/index.css
fichier.
@tailwind base;
@tailwind components;
@tailwind utilities;
Nous avons maintenant terminé l'installation de react-app et tailwindCSS
Exécutez cette commande et vous devriez avoir votre application en cours d'exécution
npm start
Vous devriez voir quelque chose comme ceci :
Maintenant, nettoyons les choses et créons simplement un bouton de menthe de base
Supprimez les fichiers marqués en rouge dans la barre latérale gauche et supprimez les éléments marqués deApp.js
Maintenant, App.js
cela devrait ressembler Ă ceci :
function App() {
return (
<div className="flex items-center justify-center min-h-screen">
<div className="flex flex-col items-center justify-center gap-4">
<h1 className="text-4xl font-extrabold">Mint an NFT</h1>
<button className="bg-black text-white py-2 px-4 rounded-xl transform hover:scale-105">
Mint
</button>
</div>
</div>
);
}
export default App;
Et la sortie [localhost:3000](http://localhost:3000)
devrait ĂȘtre :
Ceci n'est qu'un aperçu de base de l'application, nous le remplirons progressivement avec les données.
Passons Ă l'ajout d'un adaptateur de portefeuille.
⚙️ Configurer les adaptateurs de portefeuille
Nous allons utiliser RainbowKit pour cela, vous pouvez lire les docs ici → RainbowKit
Pour installer RainbowKit, nous aurons besoin de quelques packages
npm install @rainbow-me/rainbowkit wagmi ethers
wagmi et ethers sont des dépendances homologues pour rainbowkit.
Vous pouvez accéder à la documentation d'installation de RainbowKit ou suivre les étapes ci-dessous.
Importons ensuite RainbowKit, wagmi et ethers , danssrc/index.js
import '@rainbow-me/rainbowkit/styles.css';
import {
getDefaultWallets,
RainbowKitProvider,
} from '@rainbow-me/rainbowkit';
import {
chain,
configureChains,
createClient,
WagmiConfig,
} from 'wagmi';
import { alchemyProvider } from 'wagmi/providers/alchemy';
import { publicProvider } from 'wagmi/providers/public';
Configurons maintenant les chaßnes souhaitées et générons les connecteurs requis. Vous devrez également configurer un wagmi
client.
...
const { chains, provider } = configureChains(
[chain.mainnet, chain.polygon, chain.goerli, chain.polygonMumbai],
[
alchemyProvider({ apiKey: process.env.ALCHEMY_ID }),
publicProvider()
]
);
const { connectors } = getDefaultWallets({
appName: 'My NFT Minting DAPP',
chains
});
const wagmiClient = createClient({
autoConnect: true,
connectors,
provider
})
Pour obtenir un ALCHEMY_ID, vous devrez crĂ©er un compte sur Alchemy et crĂ©er une nouvelle application sur Goerli pour obtenir un ALCHEMY_ID, si vous n'avez pas compris cela, allez-y et lisez la section DĂ©ployons le contrat de ce projet oĂč je 'ai expliquĂ© cela en dĂ©tail
Copiez la clé API et collez-la comme variable ALCHEMY_ID
Vous vous demandez probablement pourquoi je montre ma clé API, eh bien j'ai créé cette application uniquement dans le cadre de ce projet et je la supprimerai probablement une fois utilisée.
Enveloppez ensuite votre application avec RainbowKitProvider
et [WagmiConfig](https://wagmi.sh/docs/provider)
.
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<WagmiConfig client={wagmiClient}>
<RainbowKitProvider chains={chains}>
<App />
</RainbowKitProvider>
</WagmiConfig>
</React.StrictMode>
);
Une fois cela fait, nous devrions pouvoir utiliser ConnectWallet
le crochet de rainbowkit pour permettre aux utilisateurs de se connecter au portefeuille et d'utiliser notre application
L'application ressemblera Ă ceci :
import { ConnectButton } from '@rainbow-me/rainbowkit';
import { useAccount } from 'wagmi'
function App() {
const { address } = useAccount()
return (
<div>
<div className='flex items-center justify-end p-2'>
<ConnectButton />
</div>
<div className="flex flex-col items-center justify-center min-h-[90vh] gap-4">
<h1 className="text-4xl font-extrabold">Mint an NFT</h1>
{
address ? (
<button className="bg-black text-white py-2 px-4 rounded-xl transform hover:scale-105">
Mint
</button>
) : (
<ConnectButton />
)
}
</div>
</div>
);
}
export default App;
Ici, nous vérifions si le address
est connecté à l'aide de wagmi
, si l'adresse est connectée, affichez le bouton Mint ou affichez le bouton de connexion , il devrait ressembler à ceci :
Allez-y et stylisez-le comme vous le souhaitez, j'irai avec un design simpliste.
Maintenant que nous avons configuré nos portefeuilles, allons-y et récupérons le contrat dans notre interface
đ„š Obtenons notre adresse de contrat et notre contrat ABI
Pour obtenir l'adresse du contrat que nous avons déployé précédemment sur remix, cliquez sur cette icÎne
Stockez maintenant CONTRACT_ADDRESS
en tant que variable dansApp.js
const CONTRACT_ADDRESS = '0x0c7EB3349E3B13fc0E6D0Fb405eEf42Cd5FC7bf4'
function App() {
const { address } = useAccount()
...
Passons maintenant Ă notre CONTRACT_ABI
, allez dans remix et cliquez sur l'onglet du compilateur de solidité dans la barre latérale gauche et copiez l'ABI en cliquant sur cette icÎne
Créez maintenant un dossier dans src/ABI.js
et exportez abi
la variable avec l'ABI copié à partir du remix, quelque chose comme ceci :
Et utilisez-le dans App.js
quelque chose comme ceci:
import { abi as CONTRACT_ABI } from './ABI';
const CONTRACT_ADDRESS = '0x0c7EB3349E3B13fc0E6D0Fb405eEf42Cd5FC7bf4'
function App() {
const { address } = useAccount()
...
đ€ș RĂ©cupĂ©rer notre contrat avec Wagmi
Maintenant que nous avons les CONTRACT_ADDRESS et CONTRACT_ABI , récupérons notre contrat en utilisant useContract fourni par wagmi
Importons d'abord le crochet useContract :
import { useAccount, useContract, useSigner } from 'wagmi'
Maintenant que nous avons importé useContract , utilisons dans notreApp
function App() {
const { address } = useAccount()
const { data: signer } = useSigner()
const contract = useContract({
addressOrName: CONTRACT_ADDRESS,
contractInterface: CONTRACT_ABI,
signerOrProvider: signer
})
console.log(contract)
...
Nous avons Ă©galement besoin useSigner
d'un crochet qui sera nécessaire pour effectuer une transaction comme la frappe d'un NFT.
Vous devriez voir les fonctions de contrat dans l'onglet de la console, quelque chose comme ça
C'est ainsi que nous allons interagir avec notre contrat, vous pouvez voir notre safeMint()
fonction dans la console, nous l'utiliserons pour frapper notre NFT
Essayons d'obtenir le mintRate de notre NFT une fois, pour cela nous devrons créer une fonction car mintRate()
la fonction renverra une promesse et nous utiliserons async/wait, la fonction devrait ressembler Ă ceci :
// console.log(contract)
const getMint = async() => {
const price = await contract.mintRate()
console.log(price.toString())
}
useEffect(() => {
if(contract?.signer) {
getMint()
}
}, [contract])
...
Vous devriez voir quelque chose comme ceci dans votre console :
N'oubliez pas que le mintRate ici est dans WEI , vous pouvez en savoir plus sur wei ici
N'hésitez pas à explorer toutes les fonctions du contrat, pas nécessaire mais bien si vous voulez comprendre et pratiquer.
đŸ CrĂ©ation de notre fonction Mint
Maintenant que nous avons notre contrat et que nous sommes capables d'interagir avec notre contrat intelligent, commençons à travailler sur le contrat intelligent.
function safeMint() public payable {
require(msg.value >= mintRate, "Not enough ether");
uint256 tokenId = _tokenIdCounter.current();
_tokenIdCounter.increment();
_safeMint(msg.sender, tokenId);
}
Si vous vous souvenez bien, nous avions notre safeMint()
dĂ» et nous facturons un petit montant Ă l'utilisateur pour frapper le NFT, nous devrons donc l'envoyer comme argument Ă la fonction
Voyons Ă quoi ressemble la fonction mint :
const mintNft = async() => {
try {
const mint = await contract.safeMint({ value: mintRate })
console.log(mint)
contract.on("Transfer", (to, from, token) => {
console.log(to, from, token)
})
} catch(err) {
console.log(err)
}
}
Ici, nous essayons d'abord de créer la fonction en utilisant la safeMint()
fonction du contrat intelligent, et d'envoyer la valeur en tant qu'argument avec le mintRate que nous avons récupéré auparavant, rappelez-vous que nous ajoutons un bloc try-catch pour détecter si une erreur se produit et montrer cela à l'utilisateur.
Vous vous demandez peut-ĂȘtre qu'est-ce contract.on
qu'il surveille la prochaine transaction et vérifie si l'événement portant le nom Transfer
se produit et si console ses arguments, nous l'utiliserons pour afficher les données de celui-ci.
Il s'agit d'un aperçu à vol d'oiseau de toutes les fonctions et de tous les états du code, je partagerai également un repl (code entier) à la fin, mais c'est l'intégralité du flux :
const [mintRate, setMintRate] = useState("0")
const [error, setError] = useState(false)
const [tokenId, setTokenId] = useState(null)
const [loading, setLoading] = useState(false)
const getMint = async() => {
const price = await contract.mintRate()
setMintRate(price.toString())
}
useEffect(() => {
if(contract?.signer) {
getMint()
}
}, [contract])
const mintNft = async() => {
setLoading(true)
try {
const mint = await contract.safeMint({ value: mintRate })
console.log(mint)
contract.on("Transfer", (to, from, token) => {
console.log(to, from, token)
setTokenId(token.toString())
setLoading(false)
})
} catch(err) {
console.log(err)
setError(err)
setLoading(false)
}
}
console.log("MINT ", mintRate)
console.log("TOKEN ", tokenId)
console.log("ERROR ", error)
console.log("LOADING ", loading)
Nous définissons 4 états, mintRate
, tokenId
, error
, et loading
, nous utiliserons mintRate pour frapper le NFT et envoyer la valeur comme argument, nous utiliserons error pour attraper l'erreur et l'afficher dans l'interface utilisateur, nous utiliserons loading pour créer un chargement lors de la création du NFT, et tokenId est essentiellement le jeton NFT qui a été créé en ce moment, nous l'utiliserons pour diriger les utilisateurs vers la page opensea de leur jeton.
Maintenant, lions-le Ă notre fonction mint :
<button onClick={mintNft} className="bg-black text-white py-2 px-4 rounded-xl transform hover:scale-105">
Mint
</button>
et essayez-le dans le navigateur :
Cela devrait déclencher une transaction comme ceci :
Cliquez sur confirmer et surveillez les logs de votre console
C'est tout le flux du processus de frappe.
Violađ, nous avons maintenant notre NFT, utilisons maintenant les Ă©tats donnĂ©s dans l'interface utilisateur pour crĂ©er une bonne expĂ©rience utilisateur
đ€ CrĂ©ez un flux pour permettre aux utilisateurs de le visualiser sur une place de marchĂ©
Nous allons maintenant utiliser nos états actuels pour créer une bonne expérience utilisateur :
....
<div className="flex flex-col items-center justify-center min-h-[90vh] gap-4">
<h1 className="text-4xl font-extrabold">Mint an NFT</h1>
{address ? (
loading ? (
<h3 className="text-xl">Minting your NFT...</h3>
) : (
<button
onClick={mintNft}
className="bg-black text-white py-2 px-4 rounded-xl transform hover:scale-105"
>
Mint
</button>
)
) : (
<ConnectButton />
)}
{error && (
<div>
<p>Something went wrong!</p>
</div>
)}
{tokenId && (
<div className="flex flex-col">
<p className="font-bold">Token with id {tokenId} minted</p>
<p>
Check it over here:{" "}
<a
href={`https://testnets.opensea.io/assets/goerli/${CONTRACT_ADDRESS}/${tokenId}`}
target="_blank"
rel="noreferrer"
>
Opensea
</a>
</p>
</div>
)}
</div>
....
Ici, nous vĂ©rifions si le jeton est en train d'ĂȘtre frappĂ© et s'il est en train d'ĂȘtre frappĂ©, nous montrons un Ă©cran de chargement, soyez sincĂšre ici et crĂ©ez une animation de chargement incroyable, j'adorerais voir vos tags sur Twitter ;)
Ensuite, nous vĂ©rifions si l'erreur est vraie et si c'est vrai que nous leur montrons un message d'erreur, rappelez-vous que nous consoleons l'erreur consignĂ©e dans le bloc try-catch, vous pouvez mĂȘme enregistrer le message d'erreur en tant qu'Ă©tat et le montrer ici, comme je l'ai dit ĂȘtre curieux et essayer diffĂ©rentes choses.
Enfin, nous utiliserons le tokenId créé pour afficher un lien vers la page Opensea.
Essayons maintenant :
Une fois qu'il est frappé, nous pouvons le voir sur l'écran
Cliquons sur Opensea :
Et voilĂ , il y a votre NFTđ€
Vous vous demandez peut-ĂȘtre pourquoi j'ai un singe dĂ©gĂ©nĂ©rĂ© comme mon NFT, c'est parce que j'ai utilisĂ© le baseURI de la collection Degenrate Ape parce que c'est juste pour les tests et que je l'ai dĂ©ployĂ© sur le testnet.
đŸ Tout est fait !
Génial maintenant que nous avons créé un DAPP qui permet à l'utilisateur de créer NFT, déployons-le sur Vercel ou Netlify , ce qui vous permet de déployer des sites Web gratuitement, j'adorerais aussi créer vos NFT, n'oubliez pas de nous taguer sur Twitter alors que nous connaissons et monnayons vos NFT.
Soyez curieux ici et allez au contenu de votre cĆur et concevez magnifiquement la page de menthe j'aimerais voir votre crĂ©ativitĂ© ici.
Lien Replit du code source : https://replit.com/@deveshB1/NFTMintDapp
C'est un enveloppement, tapotez-vous dans le dos et construisez de la merde cool !
Commentaires
Enregistrer un commentaire
đ Hello,
N'hĂ©sitez pas Ă commenter ou vous exprimer si vous avez des trucs Ă dire . . .đ