Skip to content

hashgraph/hedera-nft-minter

Hedera NFT Minter App

An example web app that demonstrates how you can mint NFTs on the Hedera network using HashPack or Blade wallet and upload metadata with an image to IPFS provider supporting HIP-412 standard. App also included simply My NFT Gallery page, where connected user NFTs are listed.

UI_welcome-screen

Built With

  • Hedera Hashgraph - The enterprise-grade public network
  • Hedera Mirror Node - provides a way to store and cost-effectively query historical data from the public ledger
  • Hedera Hashgraph JavaScript SDK - The easiest way to use Hedera in JavaScript
  • NFT Storage - The long-term storage service designed for off-chain NFT data
  • Node.JS - Node.js is an open-source, cross-platform, back-end JavaScript runtime environment
  • React.JS - A fast, unopinionated web framework for node.js
  • TypeScript - Strongly typed programming language that builds on JavaScript
  • SASS - The most mature, stable, and powerful professional-grade CSS extension language in the world.
  • BabelJS - A real-time client-to-server framework for node.js
  • WebPack - Static module bundler for modern JavaScript applications

Created by

  • Norbert Kulus
  • Patryk Matyjasiak

Prerequisites

This demo assumes that you are familiar with Node.JS based applications and using React.JS UI framework. Also, you need to be familiar with using Hedera Mirror Node, Hedera Hashgraph JavaScript SDK. You will need to generate API key(s) from NFT Storage to store NFTs images and metadata or configure your own IPFS provider (or implement your own IPFS service usage). To use an app, you will also need a Hedera Account connected within HashPack wallet. If you don't have one yet, sign up at portal.hedera.com.

Getting Started

You can clone this repository by running the following command:

git clone https://github.com/hashgraph/hedera-nft-minter

Copy the .env.sample file and rename the copy to .env

Then update the newly renamed .env file with your IPFS URL, Hedera network type, Mirror Node version, and HashPack wallet metadata:

## Minimal setup
APP_NAME=Mintbar

HEDERA_NETWORK=testnet
HEDERA_MIRROR_NODE_API_VERSION=v1

PINATA_API_URL=https://api.nft.storage
PINATA_JWT_KEYS=['key1','key2','key3','key4','key5']
# IPFS_GATEWAYS=['https://gateway.1/{CID}','https://{CID}.gateway.2']

WALLET_CONFIG_NAME=Mintbar.xyz
WALLET_CONFIG_DESCRIPTION=Mint your own NFT.

  • The APP_NAME is used for generating localStorage variable names for holding both wallets' connection data.
  • The HEDERA_NETWORK holds Hedera Network type (testnet, mainnet)
  • The HEDERA_MIRROR_NODE_API_VERSION is a variable for storing the mirror node API version
  • The PINATA_API_URL is your IPFS storage API URL (currently only the https://www.pinata.cloud/ is implemented)
  • The PINATA_JWT_KEYS is an array with API keys generated from NFT Storage
  • The IPFS_GATEWAYS is an array with gateways for fetch IPFS data. {cid} in url is replaced by true metadata CID of NFT.
  • The WALLET_CONFIG_NAME stores name shown in the each Wallet connection modal
  • The WALLET_CONFIG_DESCRIPTION stores description shown in the each Wallet connection modal
  • The WALLET_CONFIG_URL is optional. URL shown in wallet connection modal (only BladeWallet supported).
  • The WALLET_CONFIG_ICON_URL is optional. Stores URL to image shown in each Wallet connection modal. If not provided, the app is looking for ${ window.location.protocol }//${ window.location.host }/logo.svg to serve in the each wallet connection modal

After downloading and setting up our environment, we'll install our packages via npm.

npm install

If installing the dependencies was successful, now try to run the app

npm run start

Application design

Page Components (src/pages)

  1. HomePage Component : This component includes whole MinterWizard used to process minting. The handleFormSubmit method contains all procedures used for minting an NFT.

  2. MyNFTCollection Component: This Component displays the listed NFTs of the connected user. This Component gets its data from a JSON file in the assets folder as well. This Component is the Child Component of the Customers Component

Services (src/services)

HTS
  1. createToken({ accountId: string; tokenName: string; tokenSymbol: string; amount: number; customFees?: Fees[]; keys?: TokenKey[] }): method used for generating TokenCreateTransaction. The public key for a connected account is fetched from MirrorNode.
  2. mintToken(tokenId: string | TokenId, acc1: string, cids: string[]): method used for generating TokenMintTransaction
MirrorNode
  1. async fetchAccountInfo(accountId: string): fetch account info for Hedera account. Mirror Node API - Accounts
  2. async fetchTokenInfo(tokenId: string): fetch Hedera token info. Mirror Node API - Token info
  3. async fetchNFTMetadata(cid: string): method fetches nft metadata from cid. If CID does not contain HTTPS protocol we use https://ipfs.io/ipfs/ to serve metadata
  4. async fetchAllNFTs(idOrAliasOrEvmAddress: string): in this method, all NFTs connected with the Hedera account are returned. Mirror Node API - Account NFTs
  5. async fetchCollectionInfoForGroupedNFTs(groupedNfts: GroupedNFTs): group NFTs fetched from MirrorNode.fetchAllNFTs() by collection ID and fetch additional collection info
IPFS

Both methods are using random IPFS key from .env variable for each request.

  1. uploadFile(file: File | Blob): upload file
  2. createMetadataFile(meta: NFTMetadata): upload metadata.json file

Connection Hooks (src/utils/hooks)

useHashPack

Inside this hook, the HashConnect instance is created and a connection with the HashPack extension is trying to be established. The hook helps handle connection flow. Inside a hook are listeners for HashPack wallet pairing, extension events and iFrame pairing events. Returns saved connection data, clearing connection method, connection method and HashConnect instance.

const {
    hashConnect,
    hashConnectState,
    connectToHashPack,
    disconnectFromHashPack,
} = useHashPack();
useHederaWallets

The connection and sending transaction magic happened here. Hooks under the hood create a context, where the two above hooks are used to provide a connection with each wallet extension. Within useHederaWallets you can send transactions generated from Hedera JS SDK signed by an account connected with any supported Hedera wallet extension.

const {
    userWalletId,
    connectedWalletType,
    connect,
    disconnect,
    sendTransaction,
} = useHederaWallets()

URL (src/routes/base.tsx)

The application has:

  • / which ties to HomePage Component
  • /my-nft-collection which ties to MyNFTCollection Component

HTTP calls

axios library is used to make HTTP Calls. https://axios-http.com/

Hedera calls

UI Resources

Disclaimer

This is just a simple demo application. Please use responsibly.

File an issue if you see problems.

Contributing

Contributions are welcome. Please see the contributing guide to see how you can get involved.

Code of Conduct

This project is governed by the Contributor Covenant Code of Conduct. By participating, you are expected to uphold this code of conduct. Please report unacceptable behavior to [email protected].

LICENSE

Apache 2.0