NFT Minter Tutorial |

One of the biggest challenges for developers coming from a web2 environment is figuring out how to connect their smart contract to a frontend project and interact with it.

By creating an nft minter, a simple user interface where you can enter a link to your digital asset, a title, and a description, you’ll learn how:

Reading: Ethereum development tutorial

  • connect to metamask through your frontend project
  • call smart contract methods from your frontend
  • sign transactions using metamask

In this tutorial, we will use react as our interface framework. Since this tutorial is primarily focused on web3 development, we won’t spend a lot of time breaking down the basics of react. instead, we will focus on adding functionality to our project.

As a prerequisite, you should have a beginner-level understanding of react: knowing how components, props, usestate/useeffect, and basic calling functions work. If you’ve never heard of any of those terms before, you might want to check out this getting started tutorial to get started. For more visual learners, we highly recommend this excellent series of modern and comprehensive reaction tutorial videos from net ninja.

And if you haven’t already, you’ll definitely need an alchemy account to complete this tutorial and build anything on the blockchain. Sign up here for a free account.

without further ado, let’s get started!

doing nfts 101

Before we start looking at any code, it’s important to understand how creating an nft works. involves two steps:

publish an nft smart contract on the ethereum blockchain

the biggest difference between the two nft smart contract standards is that erc-1155 is a multi-token standard and includes batch functionality, while erc-721 is a single-token standard and therefore only supports the transfer of one token at a time. time.

call minting function

This minting function typically requires you to pass two variables as parameters, first the recipient, which specifies the address your newly minted nft will receive, and second the nft tokenuri, a string that resolves to a json document which describes the nft metadata.

The metadata of an nft is really what brings it to life, allowing it to have properties, such as a name, a description, an image (or a different digital asset), and other attributes. here is an example of a tokenuri, which contains the metadata of an nft.

In this tutorial, we will focus on part 2, calling the smart contract minting function of an existing nft using our react UI.

here is a link to the erc-721 nft smart contract that we will call in this tutorial. if you want to know how we did it, we recommend that you check out our other tutorial, “how to create an nft”.

Great, now that we understand how nfting works, let’s clone our startup files!

clone the initial files

First, go to the nft-minter-tutorial github repository to get the starter files for this project. clone this repository in your local environment.=

When you open this cloned nft-minter-tutorial repository, you will notice that it contains two folders: minter-starter-files and nft-minter.

  • minter-starter-files contains the starter files (essentially react UI) for this project. In this tutorial, we will be working on this directory, as you learn how to bring this UI to life by connecting it to your ethereum wallet and an nft smart contract.
  • nft -minter contains the full comprehensive tutorial and is there for you as a reference if you get stuck.

next open your copy of minter-starter-files in your code editor and then navigate to your src folder.

all the code we will write will live in the src folder. we will edit the minter.js component and write additional javascript files to give our project web3 functionality.

step 2: take a look at our startup files

Before we start coding, it’s important to check what we’ve already been given in the startup files.

run your react project

Let’s start by running the react project in our browser. The beauty of react is that once we have our project running in our browser, any changes we save will be updated live in our browser.

To run the project, navigate to the root of the minter-starter-files folder and run npm install in your terminal to install the project dependencies:

once they have finished installing, run npm start in your terminal:

Doing so should open http://localhost:3000/ in your browser, where you’ll see our project’s interface. It should consist of 3 fields: a place to enter a link to your nft asset, enter the name of your nft, and provide a description.

if you try to click the “connect wallet” or “mint nft” buttons, you will notice that they don’t work, that’s because we still have to program their functionality! 🙂

the minter.js component

note: make sure you are in the minter-starter-files folder and not the nft-minter folder!

Let’s go back to the src folder in our editor and open the minter.js file. it is very important that we understand everything in this file, as it is the main react component we will be working on.

At the top of this file, we have our state variables that we will update after specific events.

ever heard of react state variables or state hooks? consult these documents.

This is what each of the variables represents:

  • walletaddress – a string that stores the user’s wallet address
  • status – a string that contains a message to display at the bottom of the UI
  • name – a string that stores the name of nft
  • description – a string that stores the description of nft
  • url – a string that is a link to the digital asset of nft

After the state variables, you will see three unimplemented functions: useeffect, connectwalletpressed, and onmintpressed. you’ll notice that all of these functions are asynchronous, that’s because we’ll be making asynchronous api calls on them! their names are eponymous with their functionalities:

  • useeffect – this is a react hook that is called after the component is rendered. because it was passed an empty prop[] array (see line 3), it will only be called on the first render of the component. here we will call our wallet listener and another wallet function to update our UI to reflect if a wallet is already connected.
  • connectwalletpressed – this function will be called to connect the user’s metamask wallet to our dapp .
  • onmintpressed: This function will be called to mint the user’s nft.

near the end of this file, we have the user interface of our component. If you scan this code carefully, you’ll notice that we update our url, name, and description state variables when the input in their corresponding text fields changes.

You will also see connectwalletpressed and onmintpressed being called when buttons with ids mintbutton and walletbutton are clicked respectively.

Finally, let’s address where this minter component is added.

if you go to the app.js file, which is the main component in react that acts as a container for all the other components, you will see that our minter component is injected on line 7.

In this tutorial, we’ll just edit the minter.js file and add files to our src folder.

Now that we understand what we’re working with, let’s set up our ethereum wallet!

##: configure your ethereum wallet {#configure-your-ethereum-wallet}

In order for users to be able to interact with your smart contract, they will need to connect their ethereum wallet to your dapp.

download metamask

For this tutorial, we will use metamask, an in-browser virtual wallet used to manage your ethereum account address. If you want to learn more about how ethereum transactions work, check out this page.

You can download and create a free metamask account here. when you’re creating an account, or if you already have an account, be sure to switch to the “ropsten test network” at the top right (so we’re not dealing with real money).

add ether from a faucet

To mint our nfts (or sign any transaction on the ethereum blockchain), we’ll need some fake eth. To get eth, you can go to ropsten faucet and enter your ropsten account address, then click “send ropsten eth”. you should see eth in your metamask account soon after!

check your balance

To verify that our balance is there, let’s make an eth_getbalance request using alchemy’s compose tool. this will return the amount of eth in our wallet. after entering your metamask account address and clicking “send request”, you should see a response like this:

note: this result is in wei not eth. wei is used as the smallest name for ether. the conversion from wei to eth is: 1 eth = 10¹⁸ wei. so if we convert 0xde0b6b3a7640000 to decimal, we get 1*10¹⁸ which equals 1 eth.

Phew! Our fake money is all there! 🤑

connect metamask to your UI

Now that our metamask wallet is set up, let’s connect our dapp to it!

Because we want to prescribe the mvc paradigm, we’re going to create a separate file containing our functions to manage our dapp’s logic, data, and rules, and then pass those functions to our interface (our minter .js component ).

the connectwallet function

To do this, create a new folder called utils in your src directory and add a file called interact.js inside, which will contain all of our smart contract and wallet interaction functions.

In our interact.js file, we’ll write a connectwallet function, which we’ll then import and call in our minter.js component.

See also: Crypto bitmart 150m smart theblock –

in your interact.js file, add the following

Let’s break down what this code does:

first, our function checks if window.ethereum is enabled in your browser.

window.ethereum is a global api injected by metamask and other wallet providers that allows websites to request users’ ethereum accounts. if approved, it can read data from the blockchains the user is connected to and suggest that the user sign messages and transactions. see the metamask docs for more information.

if window.ethereum is not present, that means metamask is not installed. this results in a json object being returned, where the returned address is an empty string, and the status jsx object indicates that the user should install metamask.

Most of the functions we write will return json objects that we can use to update our state and ui variables.

now, if window.ethereum is present, then that’s when things get interesting.

Using a try/catch loop, we will try to connect to metamask by calling [window.ethereum.request({ method: “eth_requestaccounts” });]( rpc-api. html#eth-requestaccounts). calling this function will open the metamask in the browser, so the user will be prompted to connect their wallet to your dapp.

  • if the user chooses to connect, the method: “eth_requestaccounts” will return an array containing all of the user’s account addresses that are connected to the dapp. Altogether, our connectwallet function will return a json object containing the first address in this array (see line 9) and a status message that prompts the user to write a message to the smart contract.
  • if the user refuses the connection, the json object will contain an empty string for the returned address and a status message reflecting that the user refused the connection.

add the connectwallet function to your minter.js ui component

Now that we’ve written this connectwallet function, let’s connect it to our minter.js. component.

First, we’ll need to import our function into our minter.js file by adding import { connectwallet } from “./utils/interact.js”; at the top of the minter.js file. your first 11 lines of minter.js should now look like this:

then, inside our connectwalletpressed function, we’ll call our imported connectwallet function, like so:

did you notice how most of our functionality is abstracted from our minter.js component in the interact.js file? this is for us to comply with the m-v-c paradigm!

in connectwalletpressed, we simply make an await call to our imported connectwallet function and, using its response, update our wallet address and state variables via its state hooks.

Now, let’s save both minter.js and interact.js files and test our UI so far.

open your browser at localhost:3000 and press the “connect wallet” button at the top right of the page.

if you have metamask installed, you will be prompted to connect your wallet to your dapp. accept the invitation to connect.

You should see that the wallet button now reflects that your address is connected.

then try to refresh the page… this is weird. our wallet button asks us to connect metamask, even though it is already connected…

but don’t worry! we can easily fix this by implementing a function called getcurrentwalletconnected, which will check if an address is already connected to our dapp and update our UI accordingly.

the getcurrentwalletconnected function

In your interact.js file, add the following getcurrentwalletconnected function:

This code is very similar to the connectwallet function we wrote earlier.

The main difference is that instead of calling the eth_requestaccounts method, which opens the metamask for the user to connect their wallet, here we call the eth_accounts method, which simply returns an array containing the metamask addresses currently connected to our dapp.

To see this function in action, let’s call it in our minter.js component’s useeffect function.

As we did with connectwallet, we need to import this function from our interact.js file to our minter.js file like so:

now, we just call it in our useeffect function:

notice, we use the response from our call to getcurrentwalletconnected to update our wallet address and state variables.

Once you’ve added this code, try refreshing our browser window. the button should say you’re connected and show a preview of your connected wallet address, even after upgrading!

implement addwalletlistener

The last step in configuring our dapp wallet is to implement the wallet listener so that our UI updates when the state of our wallet changes, such as when the user logs out or switches accounts.

In your minter.js file, add an addwalletlistener function similar to the following:

let’s quickly break down what’s going on here:

  • first, our function checks to see if window.ethereum is enabled (i.e. metamask is installed).
    • if it isn’t, we simply set our state variable to a jsx string that prompts the user to install metamask.
    • if enabled, we configure the window.ethereum.on(“accountschanged”) listener on line 3 that listens for state changes in the metamask wallet, including when the user connects an additional account to the dapp, switches accounts or disconnects an account. if there is at least one account connected, the walletaddress state variable is updated as the first account in the array of accounts returned by the listener. otherwise, the wallet address is set to an empty string.

    finally, we need to call it in our useeffect function:

    and voila! we have completed the programming of all our wallet functionality! Now that our wallet is set up, let’s figure out how to mint our nft!

    nft 101 metadata

    so remember the nft metadata we just talked about in step 0 of this tutorial: they bring an nft to life, allowing it to have properties, such as a digital asset, name, description, and other attributes.

    We’ll need to set this metadata as a json object and store it, so we can pass it as the tokenuri parameter when calling our smart contract’s mintnft function.

    the text in the fields “asset link”, “name”, “description” will comprise the different properties of our nft metadata. We’ll format this metadata as a json object, but there are a couple of options for storing this json object:

    • we could store it on the ethereum blockchain; however, doing so would be very expensive.
    • we could store it on a centralized server, like aws or firebase. but that would defeat our spirit of decentralization.
    • we could use ipfs, a decentralized protocol and peer-to-peer network to store and share data in a distributed file system. Since this protocol is decentralized and free, it is our best option!

    To store our metadata in ipfs, we’ll use pinata, a convenient ipfs api and toolkit. in the next step, we’ll explain exactly how to do this!

    use pintata to anchor your metadata to ipfs

    If you don’t have a pinata account, sign up for a free account here and complete the steps to verify your email and account.

    create your piñata api key

    Navigate to the page, then select the “new key” button at the top, set the admin widget to enabled, and name your key.

    then you will be shown a popup with your api information. make sure to keep it in a safe place.

    Now that our key is set up, add it to our project so we can use it.

    create an .env file

    we can safely store our pinata key and secret in an environment file. Let’s install the dotenv package in your project directory.

    open a new tab in your terminal (separate from the one running localhost) and make sure you’re in the minter-starter-files folder, then run the following command in your terminal:

    Next, create an .env file in the root directory of your minter-starter-files by entering the following on your command line:

    this will open your .env file in vim (a text editor). to save it press “esc” + “:” + “q” on your keyboard in that order.

    then in vscode, navigate to your .env file and add your pinata api key and api secret, like so:

    save the file and you’re ready to start writing the function to load your json metadata into ipfs.

    implement pinjsontoipfs

    luckily for us, pinata has a specific api for loading json data into ipfs and a convenient javascript example with axios that we can use, with some slight modifications.

    See also: SEC Emails Highlighting Alleged Conflict of Interest Set to Take Center Stage in Ripple Trial

    in your utils folder, let’s create another file called piñata.js and then import our piñata secret and key from the .env file like so:

    then paste the additional code below into your pinata.js file. don’t worry, we’ll break down what each means!

    so what exactly does this code do?

    first, import axios, a promise-based http client for the browser, and node.js, which we’ll use to make a request to pinata.

    then we have our pinjsontoipfs async function, which takes a jsonbody as input and the pinata api key and secret in its header, all to make a post request to your pinjsontoipfs api.

    • if this post request is successful, then our function returns a json object with the success boolean as true and the pinataurl where our metadata was set. we’ll use this returned pinataurl as the tokenuri input for our smart contract’s mint function.
    • if this post request fails, then our function returns a json object with boolean on success as false and a string of message that transmits our error.

    As with our connectwallet function return types, we’re returning json objects so we can use their parameters to update our state variables and the UI.

    upload your smart contract

    Now that we have a way to load our nft metadata into ipfs via our pinjsontoipfs function, we’re going to need a way to load an instance of our smart contract so we can call its mintnft function.

    As we mentioned before, in this tutorial we will use this existing nft smart contract; however, if you’d like to learn how we did it, or make one yourself, we recommend checking out our other tutorial, “how to create an nft”.

    the abi contract

    If you have examined our files closely, you will have noticed that in our src directory there is a contract-abi.json file. an abi is needed to specify which function will invoke a contract and to ensure that the function will return data in the format it expects.

    We are also going to need an alchemy api key and the alchemy web3 api to connect to the ethereum blockchain and load our smart contract.

    create your alchemy api key

    If you don’t have an alchemy account yet, sign up for free here.

    once you have created an alchemy account, you can generate an api key by creating an app. this will allow us to make requests to the ropsten testnet.

    navigate to the “create app” page in your alchemy dashboard by hovering over “applications” in the navigation bar and clicking “create app”.

    name your app, we choose “my first nft!”, give a short description, select “staging” for the environment used for accounting for your app, and choose “ropsten” for your network.

    click “create app” and you’re good to go. your application should appear in the following table.

    great, so now that we’ve created our http alchemy api url, copy it to your clipboard…

    … and then let’s add it to our .env file. Altogether, your .env file should look like this:

    Now that we have our abi contract and our alchemy api key, we are ready to upload our smart contract using alchemy web3.

    set up your alchemy web3 terminal and contract

    First, if you don’t already have it, you’ll need to install alchemy web3 by navigating to the home directory: nft-minter-tutorial in the terminal:

    Next, let’s go back to our interact.js file. at the top of the file, add the following code to import your alchemy key from your .env file and configure your alchemy web3 terminal:

    alchemy web3 is a wrapper for web3.js, providing improved api methods and other crucial benefits to make your life as a web3 developer easier. it’s designed to require minimal configuration so you can start using it in your application right away.

    Next, let’s add our contract abi and contract address to our file.

    Once we have both, we’re ready to start coding our mint function!

    implement mintnft function

    Inside your interact.js file, let’s define our function, mintnft, which will eponymously mint our nft.

    Because we’ll be making numerous asynchronous calls (to pinata to anchor our metadata to ipfs, alchemy web3 to load our smart contract, and metamask to sign our transactions), our function will also be asynchronous.

    The three inputs to our function will be the url of our digital asset, the name, and the description. add the following function signature below the connectwallet function:

    input error handling

    Naturally, it makes sense to have some kind of input error handling at the beginning of the function, so we exit this function if our input parameters are not correct. Inside our function, let’s add the following code:

    basically, if any of the input parameters is an empty string, we return a json object where the boolean on success is false and the status string indicates that all fields in our UI must be complete.


    upload metadata to ipfs

    once we know our metadata is formatted correctly, the next step is to wrap it in a json object and upload it to ipfs via the pinjsontoipfs we wrote.

    To do this, we first need to import the pinjsontoipfs function in our interact.js file. at the top of interact.js, let’s add:

    remember that pinjsontoipfs accepts a json body. so before we call it, we’ll need to format our url, name, and description parameters into a json object.

    let’s update our code to create a json object called metadata and then call pinjsontoipfs with this metadata parameter:

    Note that we store the response from our call to pinjsontoipfs(metadata) in the pinataresponse object. then we parse this object for errors.

    if there is an error, we return a json object where the success boolean is false and our status string indicates that our call failed. otherwise, we extract the pinataurl from the pinataresponse and store it as our tokenuri variable.

    Now it’s time to load our smart contract using the alchemy web3 api that we initialized at the top of our file. add the following line of code to the end of the mintnft function to set the contract in the global variable window.contract:

    The last thing we need to add in our mintnft function is our ethereum transaction:

    If you are already familiar with ethereum transactions, you will notice that the structure is quite similar to what you have seen.

    • first, we configure our transaction parameters.
      • to specifies the address of the recipient (our smart contract)
      • from specifies the signer of the transaction (the connected address of the user to metamask: window.ethereum.selectedaddress)
      • the data contains the call to our smart contract mintnft method, which receives our tokenuri and the user’s wallet address, window.ethereum.selectedaddress, as tickets
      • if the transaction is successful, the function will return a json object where boolean success is set to true and the status string prompts the user to query etherscan for more information about their transaction.
      • if the transaction fails, the function will return a json object where the success boolean is set to false and the status string passes the error message.

      Together, our mintnft function should look like this:

      That’s a giant feature! now, we just need to connect our mintnft function to our minter.js component…

      connect mintnft to our minter.js interface

      open your minter.js file and update import { connectwallet, getcurrentwalletconnected } from “./utils/interact.js”; line at the top to be:

      Finally, implement the onmintpressed function to make an await call to your imported mintnft function and update the state variable of state to reflect whether our transaction succeeded or failed:

      deploy your nft to a live website

      Are you ready to get your project up and running for users to interact with? check out this tutorial to implement your minter on a live website.

      one last step…

      taking the blockchain world by storm

      just kidding, you made it to the end of the tutorial!

      to recap, by building an nft minter you successfully learned how to:

      • connect to metamask through your frontend project
      • call smart contract methods from your frontend
      • sign transactions using metamask

      Presumably you’d like to be able to display the nft minted via your dapp in your wallet, so be sure to check out our quick tutorial on how to view your nft in your wallet!

      and, as always, if you have any questions, we’re here to help you in the alchemy discord. We can’t wait to see how you apply the concepts in this tutorial to your future projects!

      See also: 7 Ways To Make Money With Ethereum in 2020 – CoinDiligent

Related Articles

Leave a Reply

Your email address will not be published.

Back to top button