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.
- 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
- Norbert Kulus
- Patryk Matyjasiak
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.
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
-
HomePage Component : This component includes whole MinterWizard used to process minting. The
handleFormSubmit
method contains all procedures used for minting an NFT. -
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
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.mintToken(tokenId: string | TokenId, acc1: string, cids: string[])
: method used for generating TokenMintTransaction
async fetchAccountInfo(accountId: string)
: fetch account info for Hedera account. Mirror Node API - Accountsasync fetchTokenInfo(tokenId: string)
: fetch Hedera token info. Mirror Node API - Token infoasync fetchNFTMetadata(cid: string)
: method fetches nft metadata from cid. If CID does not contain HTTPS protocol we use https://ipfs.io/ipfs/ to serve metadataasync fetchAllNFTs(idOrAliasOrEvmAddress: string)
: in this method, all NFTs connected with the Hedera account are returned. Mirror Node API - Account NFTsasync fetchCollectionInfoForGroupedNFTs(groupedNfts: GroupedNFTs)
: group NFTs fetched fromMirrorNode.fetchAllNFTs()
by collection ID and fetch additional collection info
Both methods are using random IPFS key from .env
variable for each request.
uploadFile(file: File | Blob)
: upload filecreateMetadataFile(meta: NFTMetadata)
: uploadmetadata.json
file
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();
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()
The application has:
/
which ties to HomePage Component/my-nft-collection
which ties to MyNFTCollection Component
axios library is used to make HTTP Calls. https://axios-http.com/
- @hashgraph/sdk: to generate Hedera transactions. https://github.com/hashgraph/hedera-sdk-js
- hashconnect: for submitting transactions with HashPack wallet. https://www.hashpack.app/hashconnect
- ReactJS : Refer to https://reactjs.org/ to understand the concepts of ReactJS
- classnames: https://github.com/JedWatson/classnames#readme
- lodash: https://lodash.com/
- formik: Reactive forms with https://formik.org/
- yup: Easy form validation https://github.com/jquense/yup
- react-transition-group : https://reactcommunity.org/react-transition-group/
- react-toastify: https://github.com/fkhadra/react-toastify#readme
- react-scrollbars-custom: https://github.com/xobotyi/react-scrollbars-custom
- react-dropzone: https://react-dropzone.js.org/
- body-scroll-lock: https://github.com/willmcpo/body-scroll-lock#readme
This is just a simple demo application. Please use responsibly.
File an issue if you see problems.
Contributions are welcome. Please see the contributing guide to see how you can get involved.
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].