Follow its steps to set up the account and on how to upload assets.
Upload the assets
Upload token-images folder, and then we can fill the image field for token meta data. Do it for all your token meta data. (change to your own ipfs urls)
After filling all the info for token meta data, upload metadata folder.
Finally, upload the logo picture.
Set the metadata, royalty, token config
Make a nft-config.json in the project root folder, we'll use these info for later use. Content below:
{"collectionMeta": {"name":"Aptos Birds", "description": "They're a collection of 10,000 utility-enabled PFPs that feature a richly diverse and unique pool of rarity-powered traits. What's more, each Aptosbird unlocks private club membership and additional benefits the longer you hold them.",
"external_url":"https://aptosbirds.xyz" },"royalty": {"takeRate":5,"feeRecipient":"0xc8c5f00f234b26a7e206d616a9a2063e6b7894651abc94d4b0ace979f53295fa" },"tokenInfo": {"maxSupply":10000 },"assets": {"logo":"./assets/logo.png","collectionImagesPath":"./assets/collection-images/" }}
You can adjust the config according to your need. A few things to be clear:
takeRate: the percent of the royalty, 5 stands for 5%.
feeRecipient: the address that will collect the royalty fees
maxSupply: the maximum supply for this collection
Set up Aptos account
We need an Aptos account to interact with the blockchain. If you don't have an account, you can generate an account using the Petra wallet.
Fund your account with some $APT tokens, 1 $APT tokens should be enough. You can buy on Binance, FTX.
Mint NFT using typescript
Make a src folder in the project root to contain all the source code, also you need a .env file to store PRIV_KEY to prevent you from submitting it to a git repo.
account.ts
Create account.ts under the src folder. Content below:
// account.tsimport dotenv from'dotenv';dotenv.config();import { AptosAccount } from"aptos";// Need to set PRIV_KEY in the .env fileconstPRIV_KEY=process.env.PRIV_KEY;// AptosAccount accepts unit8array as private key, so we need this helper functionconstfromHexStringToUnit8Array= (hexString:string) =>Uint8Array.from(hexString.match(/.{1,2}/g).map((byte) =>parseInt(byte,16)));constPRIV_KEY_ARR=fromHexStringToUnit8Array(PRIV_KEY);exportconstaptosAccount=newAptosAccount(PRIV_KEY_ARR);
Get the private key from .env file
Convert to Unit8Array
Initialize the account, and export for later use.
chain.ts
Create chain.ts under the src folder. Content below:
// chain.tsexportconstAPTOS_NODE_URL_MAIN='https://fullnode.mainnet.aptoslabs.com'import { AptosClient, FaucetClient, MaybeHexString, TokenClient } from"aptos";constAPTOS_NODE_URL_MAIN='https://fullnode.mainnet.aptoslabs.com'constAPTOS_NODE_URL_DEV='https://fullnode.devnet.aptoslabs.com'constAPTOS_FAUCET_URL_DEV='https://faucet.devnet.aptoslabs.com'// For mainnet usage, set CHAIN_NET in .env fileconstCHAIN_NET=process.env.CHAIN_NET;exportconstisMainnet=CHAIN_NET==="Main";// Initialize aptos client// This client is used to interact with aptos blockchainconstaptosNodeUrl= isMainnet ?APTOS_NODE_URL_MAIN:APTOS_NODE_URL_DEV;constaptosClient=newAptosClient(aptosNodeUrl);exportconsttokenClient=newTokenClient(aptosClient);// For dev purpose, we need to fund our account with faucet.exportconstfundAccountForDev= (address:MaybeHexString) => {constfaucetClient=newFaucetClient(APTOS_NODE_URL_DEV,APTOS_FAUCET_URL_DEV);faucetClient.fundAccount(address,100_000_000);}
Here we get the tokenClient to interact with Aptos blockchain, and a helper function fundAccountForDev to get $APT for dev purpose. isMainnet flag is used turn on/off mainnet interaction.
issue_NFT.ts
Create issue_NFT.ts under the src folder. Content below:
// issue_NFT.tsimport collectionConfig from"../collection-config.json";import { aptosAccount } from"./account";import { aptosClient, tokenClient, fundAccountForDev, isMainnet } from"./chain";(async () => {console.log("=== Addresses ===");console.log(`Account address: ${aptosAccount.address()}`);console.log("");// Fund the account if in devif (isMainnet) {awaitfundAccountForDev(aptosAccount.address()); }console.log("=== Creating Collection ===");// Get params from configconstcollectionName=collectionConfig.collectionMeta.name;constcollectionDesc=collectionConfig.collectionMeta.description;constcollectionUri=collectionConfig.assets.logoUri;constcollectionMaxAmount=collectionConfig.tokenInfo.maxSupply;consttokenUri=collectionConfig.assets.tokenMetadataUri;constfeeRecipient=collectionConfig.royalty.feeRecipient;constroyaltyPointsDenominator=100;constroyaltyPointsNumerator=collectionConfig.royalty.takeRate;// Create the collection.constcreateCollectionTxn=awaittokenClient.createCollection( aptosAccount, collectionName, collectionDesc, collectionUri, collectionMaxAmount, );awaitaptosClient.waitForTransaction(createCollectionTxn, { checkSuccess:true });// Log the collection info after creationconstlogCollection=async () => {console.log("Collection info:");constcollectionData=awaittokenClient.getCollectionData(aptosAccount.address(), collectionName);console.log(`${collectionName}: ${JSON.stringify(collectionData,null,4)}`); }awaitlogCollection();console.log("=== Mint Token ===");constmintToken=async (tokenId:number) => {consttxnHash=awaittokenClient.createToken( aptosAccount, collectionName,`${collectionName} #${tokenId}`,// name of token, exp. Monkey #1`${collectionName} #${tokenId}`,// description of token1,// amount to mint, in most cases 1 for ERC721`${tokenUri}/${tokenId}.json`,1,// max supply for this token, set 1 for ERC721 feeRecipient, royaltyPointsDenominator, royaltyPointsNumerator, );awaitaptosClient.waitForTransaction(txnHash, { checkSuccess:true }); }// mint token 1 awaitmintToken(1);// await mintToken(2); // you can do the same with token 2// Log the collection info after token mintlogCollection();})();
The above code created a collection, and mint 1 token under the collection. A few things to konw:
You can only create 1 collection with the same name.
If you set CHAIN_NET=main, you'll need to fund your account with $APT to mint tokens