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 . . .👉