NFT 项目是Aptos 链上发展迅速的赛道,基于Aptos 链上发布NFT,铸造成本低、速度快,您是否也想在Aptos 发布自己的NFT却不知道从何入手?本文Aptos Global 将带您一步一步地完成在Aptos上发布NFT。方法简单,入门轻松,一起来吧!
本文来自:learn-web3
编译:Aptos Global
源代码
推荐下载源代码,帮助你亲身体验发布NFT。
https://github.com/zengxinhai/issue-NFT-on-Aptos
先决条件
你需要知道一些Typescript就可以开始了,确保你已经安装了node。
创建项目
创建一个空项目并进行一些init操作:
mkdir sample-collection
cd sample-collection
npm init
安装必须的包:
npm install aptos -S
npm install dotenv typescript ts-node -D
创建 typescript 参数:
npm install aptos -S
npm install dotenv typescript ts-node -D
确保启用 resolveJsonModule,
禁用 strictNullChecks。
准备静态文件
制作一个资产文件夹来放置 collection 的logo和图片。在这里,我们有一个logo 图像,在token 图像子文件夹中有两个 token 图像。
Token 元数据
创建一个元数据文件夹,用于放置集合中每个 token 的元数据。下面是 token 元数据的示例。
// 1.json
{
"name": "AptosBirds #1",
"description": "AptosBirds #1",
"image": "",
"external_url": "",
"attributes": [
{
"trait_type": "Specie",
"value": "Owl"
},
{
"trait_type": "Eyes",
"value": "Angry - Yellow"
},
{
"trait_type": "Eyewear",
"value": "None"
},
{
"trait_type": "Outerwear",
"value": "Hoodie Down"
},
{
"trait_type": "Headwear",
"value": "None"
},
{
"trait_type": "Body",
"value": "Tabby"
},
{
"trait_type": "Feathers",
"value": "Gray"
},
{
"trait_type": "Background",
"value": "Green"
},
{
"trait_type": "Beak",
"value": "Small - Orange"
}
]
}
名称:描述将被市场用于在网站上显示信息。
用户将使用属性根据不同的特征进行过滤。
图像将显示给用户。我们将在将图像上传到 IPFS 后填充它。
现在我们有这样的文件夹结构:
在 IPFS 上托管资产
这里我们使用 nft.storage 将文件上传到 IPFS
NFTUp 工具
下载地址:https://nft.storage/docs/how-to/nftup/
按照其步骤设置帐户以及如何上传资产。
上传资产
上传 token-images 文件夹,然后我们可以为 token 元数据填充 image 字段。为您的所有令牌元数据执行此操作。(更改为您自己的 ipfs 网址)
// 1.json
{
"name": "AptosBirds #1",
"description": "AptosBirds #1",
"image": "https://nftstorage.link/ipfs/bafybeibgtdkejt77t4w2fl2kh36cokmj5vipwfsxsn2z2fx35trlvg2kc4/1.png",
"external_url": "https://nftstorage.link/ipfs/bafybeibgtdkejt77t4w2fl2kh36cokmj5vipwfsxsn2z2fx35trlvg2kc4/1.png",
"attributes": [
...
]
}
填写完 token 元数据的所有信息后,上传元数据文件夹。
最后上传logo图片。
设置元数据、版税、token配置
在项目根文件夹中创建一个 nft-config.json,我们将使用这些信息供以后使用。以下内容:
{
"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/"
}
}
您可以根据需要调整配置。有几点需要明确:
takeRate:提成的百分比,5代表5%。
feerreceiver:收取特许权使用费的地址
maxSupply:此集合的最大供应
设置Aptos帐户
我们需要一个Aptos帐户来与区块链交互。如果您没有帐户,您可以使用Petra钱包生成一个帐户。
用一些$APT代币为您的账户提供资金,1 $APT代币应该足够了,你可以在币安上购买。
使用typescript 铸造NFT
在项目根目录中创建一个src文件夹来包含所有的源代码,还需要一个.env文件来存储PRIV_KEY,以防止提交到git repo。
account.ts
在 src 文件夹下创建 account.ts。以下内容:
// account.ts
import dotenv from 'dotenv';
dotenv.config();
import { AptosAccount } from "aptos";
// Need to set PRIV_KEY in the .env file
const PRIV_KEY = process.env.PRIV_KEY;
// AptosAccount accepts unit8array as private key, so we need this helper function
const fromHexStringToUnit8Array = (hexString: string) =>
Uint8Array.from(hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));
const PRIV_KEY_ARR = fromHexStringToUnit8Array(PRIV_KEY);
export const aptosAccount = new AptosAccount(PRIV_KEY_ARR);
从.env文件中获取私钥
转换为Unit8Array
初始化帐户,并导出供以后使用。
chain.ts
创建链。SRC文件夹下的Ts。内容如下:
// chain.ts
export const APTOS_NODE_URL_MAIN = 'https://fullnode.mainnet.aptoslabs.com'
import { AptosClient, FaucetClient, MaybeHexString, TokenClient } from "aptos";
const APTOS_NODE_URL_MAIN = 'https://fullnode.mainnet.aptoslabs.com'
const APTOS_NODE_URL_DEV = 'https://fullnode.devnet.aptoslabs.com'
const APTOS_FAUCET_URL_DEV = 'https://faucet.devnet.aptoslabs.com'
// For mainnet usage, set CHAIN_NET in .env file
const CHAIN_NET = process.env.CHAIN_NET;
export const isMainnet = CHAIN_NET === "Main";
// Initialize aptos client
// This client is used to interact with aptos blockchain
const aptosNodeUrl = isMainnet ? APTOS_NODE_URL_MAIN : APTOS_NODE_URL_DEV;
const aptosClient = new AptosClient(aptosNodeUrl);
export const tokenClient = new TokenClient(aptosClient);
// For dev purpose, we need to fund our account with faucet.
export const fundAccountForDev = (address: MaybeHexString) => {
const faucetClient = new FaucetClient(APTOS_NODE_URL_DEV, APTOS_FAUCET_URL_DEV);
faucetClient.fundAccount(address, 100_000_000);
}
在这里,我们获得tokenClient与Aptos区块链交互,
以及一个帮助函数fundAccountForDev来获得$APT用于开发目的。
isMainnet标志用于打开/关闭主网交互。
issue_NFT.ts
创建issue_NFT.SRC文件夹下的Ts。内容如下:
// issue_NFT.ts
import 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 dev
if (isMainnet) {
await fundAccountForDev(aptosAccount.address());
}
console.log("=== Creating Collection ===");
// Get params from config
const collectionName = collectionConfig.collectionMeta.name;
const collectionDesc = collectionConfig.collectionMeta.description;
const collectionUri = collectionConfig.assets.logoUri;
const collectionMaxAmount = collectionConfig.tokenInfo.maxSupply;
const tokenUri = collectionConfig.assets.tokenMetadataUri;
const feeRecipient = collectionConfig.royalty.feeRecipient;
const royaltyPointsDenominator = 100;
const royaltyPointsNumerator = collectionConfig.royalty.takeRate;
// Create the collection.
const createCollectionTxn = await tokenClient.createCollection(
aptosAccount,
collectionName,
collectionDesc,
collectionUri,
collectionMaxAmount,
);
await aptosClient.waitForTransaction(createCollectionTxn, { checkSuccess: true });
// Log the collection info after creation
const logCollection = async () => {
console.log("Collection info:");
const collectionData = await tokenClient.getCollectionData(aptosAccount.address(), collectionName);
console.log(`${collectionName}: ${JSON.stringify(collectionData, null, 4)}`);
}
await logCollection();
console.log("=== Mint Token ===");
const mintToken = async (tokenId: number) => {
const txnHash = await tokenClient.createToken(
aptosAccount,
collectionName,
`${collectionName} #${tokenId}`, // name of token, exp. Monkey #1
`${collectionName} #${tokenId}`, // description of token
1, // 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,
);
await aptosClient.waitForTransaction(txnHash, { checkSuccess: true });
}
// mint token 1
await mintToken(1);
// await mintToken(2); // you can do the same with token 2
// Log the collection info after token mint
logCollection();
})();
上面的代码创建了一个集合,并在该集合下创建了1个token,以下是需要了解的几点:
您只能创建一个具有相同名称的集合。
如果你设置CHAIN_NET=main,你将需要用$APT为你的账户提供资金来制造token
测试NFT
在package.json中添加一个命令。
// package.json
{
...
"scripts": {
"issueNFT": "ts-node src/issue_NFT.ts"
},
...
}
运行以下命令:
npm run issueNFT
如果没有任何问题,那么你已经发出了NFT
如果你在主网上发布的,你可以去 topaz.so 看看你的NFT 是什么样的。
推荐阅读
关注Aptos Global
发现Web3 时代新机遇