Ajoutez le boutton de "Mint NFT" sur votre site web
Tags: blockchain, solidity, nft, nfts
Published: 2022-08-23 17:23:33

---
title: Ajoutez le boutton de "Mint NFT" sur votre site web
published: true
description: 
tags: blockchain, solidity, nft, nfts
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o7tffua00gwx5alfbnvf.png
---

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.

{% youtube EntNhMTBzU4 %}

## Dépendances

Pour ce tutoriel tu vas avoir besoin de [NodeJs](https://nodejs.org/es/), je vous conseille de le télécharger avec [NVM](https://github.com/nvm-sh/nvm#installing-and-updating), aussi on aura besoin d'une RPC URL, je vous conseille d'utiliser [INFURA](https://infura.io/), et puis [Metamask](https://metamask.io/) avec du GoerliETH que to peux trouver dans un [Faucet](https://goerlifaucet.com/).

## 1. Configuration initiale

```bash
mkdir MyNFTCollection
cd MyNFTCollection
npm install --save-dev truffle dotenv @truffle/hdwallet-provider @openzeppelin/contracts
npx truffle init
```

`truffle-config.js`
```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
  }
};
```

## 2. Déployer le contrat

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

`contracts/MyNFT.sol`

```solidity
// 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.");
    }
}
```

`migrations/1_my_deploy.js`
```js
const MyNFT = artifacts.require("MyNFT")

module.exports = async function (deployer) {
  await deployer.deploy(MyNFT)
}
```

`.env`
```js
GOERLI_RPC_URL=YOURRPCKEY
PRIVATE_KEY=YOURPRIVATEKEY
```

```bash
npx truffle migrate --network goerli
```

## 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`
```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>
```

Rapelez vous copypaster l'address du contract en `MY_NFT_CONTRACT_ADDRESS`.

`client/blockchain_stuff.js`
```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)
  });
}
```

## 4. Essayons le site web

```bash
npm install -g lite-server
cd client
lite-server
```

On peut voir le résultat sur [http://localhost:3000](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](https://github.com/FilosofiaCodigo/NFTCollectionTemplate) si vous avez besoin.

**¡Merci pour regarder ce tutoriel!**