DEV Community

Cover image for Ajoutez le boutton de "Mint NFT" sur votre site web
Ahmed Castro for Filosofía Código FR

Posted on

Ajoutez le boutton de "Mint NFT" sur votre site web

Les projets de NFTs de collections plus célèbres ont commencé avec une website pour minter. On ce vidéo on va créer un smart contract en Goerli déployer une UI avec un bouton de mint.

Dépendances

Pour ce tutoriel tu vas avoir besoin de NodeJs, je vous conseille de le télécharger avec NVM, aussi on aura besoin d'une RPC URL, je vous conseille d'utiliser INFURA, et puis Metamask avec du GoerliETH que to peux trouver dans un Faucet.

1. Configuration initiale

mkdir MyNFTCollection
cd MyNFTCollection
npm install --save-dev truffle dotenv @truffle/hdwallet-provider @openzeppelin/contracts
npx truffle init
Enter fullscreen mode Exit fullscreen mode

truffle-config.js

require('dotenv').config()
const HDWalletProvider = require('@truffle/hdwallet-provider');

const fs = require('fs');

module.exports = {
  networks: {
    development: {
      host: "127.0.0.1",
      port: 8545,
      network_id: "*",
    },
    goerli: {
      provider: function () {
        return new HDWalletProvider(process.env.PRIVATE_KEY, process.env.GOERLI_RPC_URL);
      },
      network_id: 4,
      gas: 4000000,
      networkCheckTimeout: 10000
    }
  },
  mocha: {
  },
  compilers: {
    solc: {
      version: "0.8.16",
    }
  },
  db: {
    enabled: false
  }
};
Enter fullscreen mode Exit fullscreen mode

2. Déployer le contrat

Créez et éditez le contrat suivant a votre convenance.

contracts/MyNFT.sol

// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

contract MyNFT is ERC721Enumerable {
    uint256 public MAX_ELEMENTS = 5;
    uint256 public PRICE = 0.01 ether;
    address public CREATOR = 0x0000000000000000000000000000000000000000;
    uint256 public token_count;
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIdTracker;

    constructor() ERC721("My NFT", "MNFT") {}

    function _baseURI() internal view virtual override returns (string memory) {
        return "MIURL";
    }

    function _totalSupply() internal view returns (uint) {
        return _tokenIdTracker.current();
    }

    function totalMint() public view returns (uint256) {
        return _totalSupply();
    }

    function mint(address _to, uint256 _count) public payable {
        uint256 total = _totalSupply();
        require(total + _count <= MAX_ELEMENTS, "Max limit");
        require(total <= MAX_ELEMENTS, "Sale end");
        require(msg.value >= PRICE*_count, "Value below price");

        for (uint256 i = 0; i < _count; i++) {
            _mintAnElement(_to);
        }
    }

    function _mintAnElement(address _to) private {
        uint id = _totalSupply();
        _tokenIdTracker.increment();
        _safeMint(_to, id);
    }

    function withdrawAll() public {
        (bool success, ) = CREATOR.call{value:address(this).balance}("");
        require(success, "Transfer failed.");
    }
}
Enter fullscreen mode Exit fullscreen mode

migrations/1_my_deploy.js

const MyNFT = artifacts.require("MyNFT")

module.exports = async function (deployer) {
  await deployer.deploy(MyNFT)
}
Enter fullscreen mode Exit fullscreen mode

.env

GOERLI_RPC_URL=YOURRPCKEY
PRIVATE_KEY=YOURPRIVATEKEY
Enter fullscreen mode Exit fullscreen mode
npx truffle migrate --network goerli
Enter fullscreen mode Exit fullscreen mode

3. Le frontend

Créez le dossier client/contracts, créez dedans le fichier MyNFTABI.json et copypastez dedans l'atribut abi dans le fichier build/contracts/MyNFT.json. De plus, modifiez le HTML et le JS a votre convenance.

client/index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
</head>
<body>
  <input id="connect_button" type="button" value="Connect" onclick="connectWallet()" style="display: none"></input>
  <p id="account_address" style="display: none"></p>
  <p id="web3_message"></p>
  <p id="contract_state"></p>
  <select id="mint_amount">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
    <option value="4">4</option>
  </select>
  <input type="button" value="mint!" onclick="_mint()">
  <p id="nft_price"></p>
  <p id="nft_balance"></p>
  <br>
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/web3/1.3.5/web3.min.js"></script>
  <script type="text/javascript" src="blockchain_stuff.js"></script>
</body>
</html>

<script>
  function _mint()
  {
    mint_amount = document.getElementById("mint_amount").value
    mint(mint_amount)
  }
</script>
Enter fullscreen mode Exit fullscreen mode

Rapelez vous copypaster l'address du contract en MY_NFT_CONTRACT_ADDRESS.

client/blockchain_stuff.js

const NETWORK_ID = 5

const MY_NFT_CONTRACT_ADDRESS = "0xc7c463b90B393b4A0d3650Aa70a08211a6D5fB79"
const MY_NFT_CONTRACT_ABI_PATH = "./MyNFTABI.json"
var my_nft_contract
var price

var accounts
var web3

function metamaskReloadCallback() {
  window.ethereum.on('accountsChanged', (accounts) => {
    document.getElementById("web3_message").textContent="Network changed, refreshing...";
    window.location.reload()
  })
  window.ethereum.on('networkChanged', (accounts) => {
    document.getElementById("web3_message").textContent="Network chainged, refreshing...";
    window.location.reload()
  })
}

const getWeb3 = async () => {
  return new Promise((resolve, reject) => {
    if(document.readyState=="complete")
    {
      if (window.ethereum) {
        const web3 = new Web3(window.ethereum)
        window.location.reload()
        resolve(web3)
      } else {
        reject("must install MetaMask")
        document.getElementById("web3_message").textContent="Error: Connect to Metamask";
      }
    }else
    {
      window.addEventListener("load", async () => {
        if (window.ethereum) {
          const web3 = new Web3(window.ethereum)
          resolve(web3)
        } else {
          reject("must install MetaMask")
          document.getElementById("web3_message").textContent="Error: Please install Metamask";
        }
      });
    }
  });
};

const getContract = async (web3, address, abi_path) => {
  const response = await fetch(abi_path);
  const data = await response.json();

  const netId = await web3.eth.net.getId();
  contract = new web3.eth.Contract(
    data,
    address
    );
  return contract
}

async function loadDapp() {
  metamaskReloadCallback()
  document.getElementById("web3_message").textContent="Please connect to Metamask"
  var awaitWeb3 = async function () {
    web3 = await getWeb3()
    web3.eth.net.getId((err, netId) => {
      if (netId == NETWORK_ID) {
        var awaitContract = async function () {
          my_nft_contract = await getContract(web3, MY_NFT_CONTRACT_ADDRESS, MY_NFT_CONTRACT_ABI_PATH)
          document.getElementById("web3_message").textContent="You are connected to Metamask"
          onContractInitCallback()
          web3.eth.getAccounts(function(err, _accounts){
            accounts = _accounts
            if (err != null)
            {
              console.error("An error occurred: "+err)
            } else if (accounts.length > 0)
            {
              onWalletConnectedCallback()
              document.getElementById("account_address").style.display = "block"
            } else
            {
              document.getElementById("connect_button").style.display = "block"
            }
          });
        };
        awaitContract();
      } else {
        document.getElementById("web3_message").textContent="Please connect to Goerli";
      }
    });
  };
  awaitWeb3();
}

async function connectWallet() {
  await window.ethereum.request({ method: "eth_requestAccounts" })
  accounts = await web3.eth.getAccounts()
  onWalletConnectedCallback()
}

loadDapp()

const onContractInitCallback = async () => {
  price = await my_nft_contract.methods.PRICE().call()
  document.getElementById("nft_price").textContent = "NFT Price: " + web3.utils.fromWei(price) + " ETH";
}

const onWalletConnectedCallback = async () => {
  balance = await my_nft_contract.methods.balanceOf(accounts[0]).call()
  document.getElementById("nft_balance").textContent= "Your balance: " + balance;
}


//// Functions ////

const mint = async (amount) => {
  const result = await my_nft_contract.methods.mint(accounts[0], amount)
  .send({ from: accounts[0], gas: 0, value: price * amount })
  .on('transactionHash', function(hash){
    document.getElementById("web3_message").textContent="Executing...";
  })
  .on('receipt', function(receipt){
    document.getElementById("web3_message").textContent="Success.";    })
  .catch((revertReason) => {
    console.log("ERROR! Transaction reverted: " + revertReason.receipt.transactionHash)
  });
}
Enter fullscreen mode Exit fullscreen mode

4. Essayons le site web

npm install -g lite-server
cd client
lite-server
Enter fullscreen mode Exit fullscreen mode

On peut voir le résultat sur http://localhost:3000.

Maintenant on peut changer le smart contract et adapter l'UI du site web. Je vous conseille d'utiliser Netlify pour déployer, c'est gratuit et simple. De plus, utilisez le répo sur Github si vous avez besoin.

¡Merci pour regarder ce tutoriel!

Top comments (0)