In Part 1 you learned how to create a fungible token using SDK and a Solidity Smart Contract. Now let’s explore the equivalent but for NFTs. This tutorial is similar to Part 1 but it’s worth practicing a little bit more with token creation especially because of parameter differences between fungible and non-fungible tokens.
As for Part 1, in this example, there is only one Treasury Account. You can use the same function you created in Part 1 to simplify the account creation.
async function accountCreator(pvKey, iBal) { const response = await new AccountCreateTransaction() .sesetInitialBalance(iBal) .setKey(pvKey.publicKey) .setAlias(pvKey.publicKey.toEvmAddress()) .execute(client); const receipt = await response.getReceipt(client); return receipt.accountId; }
And use it like this:
const treasuryId = await accountCreator(privateKey, initialBalance);
Note that you can use the accountCreator function to create other accounts if you need to.
In this example when creating your NFT using the TokenCreateTransaction() function you must specify these parameters:
Name
Symbol
TokenType
Decimals (0 for NFTs)
Token Memo
Initial Supply (0 for NFTs)
Treasury Account
Supply Type
Supply Key
Max Supply
Auto-renew Account ID
Auto-renew period
//Create the NFT const nftCreate = await new TokenCreateTransaction() .setTokenName("Fall Collection") .setTokenSymbol("LEAF") .setTokenType(TokenType.NonFungibleUnique) .setDecimals(0) .setTokenMemo("Just a memo") .setInitialSupply(0) .setTreasuryAccountId(treasuryId) .setSupplyType(TokenSupplyType.Finite) .setSupplyKey(treasuryKey) .setMaxSupply(250) .setAutoRenewAccountId(treasuryId) .setAutoRenewPeriod(7000000) .freezeWith(client); //Sign the transaction with the treasury key const nftCreateTxSign = await nftCreate.sign(treasuryKey); //Submit the transaction to a Hedera network const nftCreateSubmit = await nftCreateTxSign.execute(client);
You just created a non-fungible token with a maximum supply of 250. Make sure you sign the transaction using a treasury Key before execution.
As you did before, to get your token ID you can just get the transaction receipt.
//Get the transaction receipt const nftCreateRx = await nftCreateSubmit.getReceipt(client); //Get the token ID const tokenId = nftCreateRx.tokenId; //Log the token ID console.log(`Created NFT with ID: ${tokenId} \n`);
Console Output:
Perfect! You created an NFT! Now, if you want, you can copy and paste your token ID to HashScan to explore a little more what you just created on testnet.
Now, as you did in Part 1, you need to create your contract. The contract name is TokenCreator.sol, and you must import these files again into your working directory by downloading them from the contracts folder here:
IHederaTokenService.sol
HederaTokenService.sol
HederaResponseCodes.sol
ExpiryHelper.sol
FeeHelper.sol
KeyHelper.sol
Solidity Contract:
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.0 <0.9.0; import './HederaResponseCodes.sol'; import './IHederaTokenService.sol'; import './HederaTokenService.sol'; import './ExpiryHelper.sol'; contract TokenCreator is ExpiryHelper{ function createNonFungible( string memory name, string memory symbol, string memory memo, uint32 maxSupply, uint32 autoRenewPeriod ) external payable returns (address){ // Instantiate the list of keys we'll use for token create IHederaTokenService.TokenKey[] memory keys = new IHederaTokenService.TokenKey[](1); // use the helper methods in KeyHelper to create basic key keys[0] = createSingleKey(HederaTokenService.SUPPLY_KEY_TYPE, KeyHelper.CONTRACT_ID_KEY, address(this)); IHederaTokenService.HederaToken memory token; token.name = name; token.symbol = symbol; token.memo = memo; token.treasury = address(this); token.tokenSupplyType = true; // set supply to FINITE token.tokenKeys = keys; token.maxSupply = maxSupply; token.freezeDefault = false; token.expiry = createAutoRenewExpiry(address(this), autoRenewPeriod); // Contract automatically renew by himself (int responseCode, address createdToken) = HederaTokenService.createNonFungibleToken(token); if(responseCode != HederaResponseCodes.SUCCESS){ revert("Failed to create non-fungible token"); } return createdToken; } }
And then to compile your contract you just run:
solcjs --bin TokenCreator.sol -o binaries
This command will create a new directory called /binaries that contains multiple .bin files. The one you are going to use it’s called TokenCreator_sol_TokenCreator.bin.
You can find the contract bytecode in this Codesandbox. (remember to fork and modify the .env file)
You will store your contract on Hedera using the ContractCreateFlow() method. This single call performs FileCreateTransaction(), FileAppendTransaction(), and ContractCreateTransaction() for you.
Always ensure that the Gas fee you specify as a parameter is enough to execute the transaction, or you'll get an error.
const createContract = new ContractCreateFlow() .setGas(150000) // Increase if revert .setBytecode(bytecode); // Contract bytecode const createContractTx = await createContract.execute(client); const createContractRx = await createContractTx.getReceipt(client); const contractId = createContractRx.contractId; console.log(`Contract created with ID: ${contractId}`);
Now you can execute your contract function by using ContractExecuteTransaction() to create your NFT collection.
Make sure every parameter is correct and the number of parameters you pass is the same as the ones in your contract, or you will get a CONTRACT_REVERT_EXECUTED error.
// Create NFT using precompile function const createToken = new ContractExecuteTransaction() .setContractId(contractId) .setGas(300000) // Increase if revert .setPayableAmount(20) // Increase if revert .setFunction("createNonFungible", new ContractFunctionParameters() .addString("Fall Collection") //NFT name .addString("LEAF") // NFT symbol .addString("Just a memo") // NFT memo .addUint32(250) // NFT max supply .addUint32(7000000)); // auto renew period const createTokenTx = await createToken.execute(client); const createTokenRx = await createTokenTx.getRecord(client); const tokenIdSolidityAddr = createTokenRx.contractFunctionResult.getAddress(0); const tokenId = AccountId.fromSolidityAddress(tokenIdSolidityAddr); console.log(`Token created with ID: ${tokenId} \n`);
Great! Now you know how to create Hedera Tokens using SDKs and Smart Contracts.
For feedback or further explanation on this article, you can contact us on Hedera Discord Server
Check out the Hedera SDK example code on Github
Check out the Smart Contract example code on Github
Hedera Service Solidity Libraries (Hedera Documentation)
Hedera Token Service (Hedera Documentation)
What are Smart Contracts? (Hedera Learning Center)