概览
铸造是在您的收藏中创建新 NFT 代币的过程。CreateKit 提供了一个独特的两阶段铸造系统,优化了燃气效率和用户体验。铸造阶段
阶段 1:部署和首次铸造
首次铸造操作是特殊的 - 它在单个交易中部署集合合约并铸造第一个代币:部署和首次铸造
Copy
Ask AI
import { CollectionManager } from '@b3dotfun/basemint'
const collectionManager = new CollectionManager(publicClient)
// 假设我们有收藏元数据和创建者签名
const predictedAddress = collectionManager.predictCollectionAddress(
collectionMetadata,
creatorSignature
)
// 生成部署者签名
const deployerSignature = await collectionManager.generateDeployerSignature(
walletClient,
predictedAddress
)
// 创建集合实例
const collection = collectionManager.createCollection(
predictedAddress,
collectionMetadata.tokenStandard
)
// 部署并铸造首个 NFT
const mintTx = await collection.mint(
walletClient,
1n, // 数量
undefined, // 元数据 URI(使用 baseURI)
collectionMetadata.mintPrice || 0n,
[], // 白名单证明(公开为空)
creatorSignature, // 首次铸造所需
deployerSignature // 首次铸造所需
)
console.log(`🚀 集合部署并首个代币铸造完成:${mintTx}`)
阶段 2:常规铸造
部署后,后续的铸造更简单,只需要标准参数:常规铸造
Copy
Ask AI
// 对于部署后的后续铸造
const regularMintTx = await collection.mint(
walletClient,
1n, // 数量
undefined, // 元数据 URI
collectionMetadata.mintPrice || 0n,
[] // 白名单证明
// 常规铸造不需要签名
)
console.log(`✨ 代币铸造完成:${regularMintTx}`)
代币标准
CreateKit 支持 ERC721 和 ERC1155 标准,具有不同的铸造行为:ERC721 独特代币
Copy
Ask AI
// ERC721 - 每个代币都是独特的
const erc721Collection = collectionManager.createCollection(
predictedAddress,
"ERC721"
)
// ERC721 总是铸造数量为 1
await erc721Collection.mint(
walletClient,
1n, // 对于 ERC721 总是 1
"https://example.com/metadata/1.json", // 此代币的独特元数据
parseEther("0.01"),
[]
)
// 每次铸造都会创建一个新的独特代币 ID
// 代币 ID 递增:1, 2, 3, 等。
定价和支付
固定定价
固定价格铸造
Copy
Ask AI
import { parseEther } from 'viem'
const fixedPriceCollection = {
name: "固定价格集合",
symbol: "FPC",
creator: account.address,
gameOwner: account.address,
mintPrice: parseEther("0.01"), // 每个代币 0.01 ETH
maxPerWallet: 5n
}
// 以固定价格铸造
await collection.mint(
walletClient,
2n, // 数量
undefined,
parseEther("0.02"), // 2 * 0.01 ETH
[]
)
免费铸造
免费铸造
Copy
Ask AI
const freeCollection = {
name: "免费集合",
symbol: "FREE",
creator: account.address,
gameOwner: account.address,
mintPrice: 0n, // 免费铸造
maxPerWallet: 10n
}
// 免费铸造(只需支付燃气费)
await collection.mint(
walletClient,
1n,
undefined,
0n, // 无需支付
[]
)
动态定价
动态定价逻辑
Copy
Ask AI
// 在您的应用程序中自定义定价逻辑
function calculateMintPrice(totalSupply: bigint, basePrice: bigint): bigint {
// 价格随供应量增加
const priceMultiplier = totalSupply / 1000n + 1n
return basePrice * priceMultiplier
}
// 获取当前供应量并计算价格
const currentSupply = await collection.totalSupply()
const dynamicPrice = calculateMintPrice(currentSupply, parseEther("0.001"))
await collection.mint(
walletClient,
1n,
undefined,
dynamicPrice,
[]
)
白名单铸造
CreateKit 支持基于 Merkle 树的白名单,用于独家铸造:设置白名单
白名单设置
Copy
Ask AI
import { WhitelistManager } from '@b3dotfun/basemint'
// 使用地址创建白名单
const whitelist = new WhitelistManager([
{ address: "0x1234567890123456789012345678901234567890" },
{ address: "0x2345678901234567890123456789012345678901" },
{ address: "0x3456789012345678901234567890123456789012" }
])
// 获取集合部署的 Merkle 根
const merkleRoot = whitelist.getRoot()
const whitelistCollection = {
name: "白名单集合",
symbol: "WLC",
creator: account.address,
gameOwner: account.address,
isWhitelistEnabled: true,
whitelistMerkleRoot: merkleRoot,
mintPrice: parseEther("0.005")
}
白名单铸造
使用白名单证明铸造
Copy
Ask AI
// 获取铸造地址的证明
const userAddress = account.address
const proof = whitelist.getProof(userAddress)
// 验证用户是否在白名单中(可选检查)
const isWhitelisted = whitelist.verify(userAddress, proof)
if (!isWhitelisted) {
throw new Error("地址不在白名单中")
}
// 使用白名单证明铸造
await collection.mint(
walletClient,
1n,
undefined,
parseEther("0.005"),
proof // 提供白名单证明
)
铸造限制和控制
每个钱包的限制
钱包限制
Copy
Ask AI
// 设置每个钱包的最大代币数量
const limitedCollection = {
name: "限量集合",
symbol: "LTD",
creator: account.address,
gameOwner: account.address,
maxPerWallet: 3n, // 每个钱包最多 3 个代币
maxSupply: 1000n
}
// 铸造前检查当前余额
const currentBalance = await collection.balanceOf(account.address)
const maxPerWallet = await collection.maxPerWallet()
if (currentBalance >= maxPerWallet) {
throw new Error("钱包限额已超")
}
await collection.mint(walletClient, 1n, undefined, 0n, [])
基于时间的控制
时间控制
Copy
Ask AI
const timedCollection = {
name: "定时发布",
symbol: "TIME",
creator: account.address,
gameOwner: account.address,
startTime: BigInt(Math.floor(Date.now() / 1000) + 3600), // 1 小时后开始
endTime: BigInt(Math.floor(Date.now() / 1000) + 86400), // 24 小时后结束
}
// 检查铸造是否当前活跃
const currentTime = BigInt(Math.floor(Date.now() / 1000))
const startTime = await collection.startTime()
const endTime = await collection.endTime()
const isMintingActive = currentTime >= startTime && currentTime <= endTime
if (!isMintingActive) {
throw new Error("当前未激活铸造")
}
元数据处理
自动元数据
CreateKit 可以根据集合设置自动生成元数据:自动生成的元数据
Copy
Ask AI
// 使用 baseURI 自动生成元数据
const autoMetadataCollection = {
name: "自动元数据集合",
symbol: "AMC",
creator: account.address,
gameOwner: account.address,
// baseURI 将由 BaseMint CDN 自动生成
}
// 使用自动元数据铸造(对 URI 传递 undefined)
await collection.mint(
walletClient,
1n,
undefined, // 使用 baseURI + tokenId
0n,
[]
)
// 元数据将在:{baseURI}/{tokenId} 处可用
自定义元数据
自定义元数据 URIs
Copy
Ask AI
// 为每个代币提供特定的元数据 URI
const customMetadataURIs = [
"https://myapi.com/metadata/special-sword.json",
"https://myapi.com/metadata/rare-shield.json",
"https://myapi.com/metadata/epic-helmet.json"
]
for (const metadataURI of customMetadataURIs) {
await collection.mint(
walletClient,
1n,
metadataURI, // 此代币的自定义元数据
parseEther("0.01"),
[]
)
}
批量铸造
对于 ERC1155 集合,您可以高效地铸造多个代币:批量铸造
Copy
Ask AI
// 单个交易,多个代币
await erc1155Collection.mint(
walletClient,
10n, // 铸造相同类型的 10 个代币
"https://example.com/metadata/resource.json",
parseEther("0.001") * 10n, // 所有代币的总价格
[]
)
// 对于不同类型的代币,使用单独的交易
const tokenTypes = [
{ uri: "https://example.com/wood.json", quantity: 5n },
{ uri: "https://example.com/stone.json", quantity: 3n },
{ uri: "https://example.com/gold.json", quantity: 1n }
]
for (const tokenType of tokenTypes) {
await erc1155Collection.mint(
walletClient,
tokenType.quantity,
tokenType.uri,
calculatePrice(tokenType.quantity),
[]
)
}
错误处理
全面的错误处理
Copy
Ask AI
async function safeMint(
collection: any,
walletClient: any,
quantity: bigint,
metadataURI: string | undefined,
mintPrice: bigint,
proof: string[]
) {
try {
// 铸造前验证
const isDeployed = await collection.isDeployed()
if (!isDeployed) {
throw new Error("集合尚未部署")
}
const currentSupply = await collection.totalSupply()
const maxSupply = await collection.maxSupply()
if (currentSupply + quantity > maxSupply) {
throw new Error("将超出最大供应量")
}
const userBalance = await collection.balanceOf(walletClient.account.address)
const maxPerWallet = await collection.maxPerWallet()
if (userBalance + quantity > maxPerWallet) {
throw new Error("将超出钱包限额")
}
// 检查支付金额
const requiredPayment = await collection.mintPrice() * quantity
if (mintPrice < requiredPayment) {
throw new Error("支付不足")
}
// 尝试铸造
const tx = await collection.mint(
walletClient,
quantity,
metadataURI,
mintPrice,
proof
)
console.log(`✅ 铸造成功:${tx}`)
return tx
} catch (error: any) {
if (error.message.includes('Invalid merkle proof')) {
console.error('❌ 地址不在白名单中')
} else if (error.message.includes('Insufficient payment')) {
console.error('❌ 铸造价格错误')
} else if (error.message.includes('Max per wallet exceeded')) {
console.error('❌ 钱包限额已达')
} else {
console.error('❌ 铸造失败:', error.message)
}
throw error
}
}
燃气优化
高效铸造模式
燃气效率高的铸造
Copy
Ask AI
// 对于 ERC1155:在一个交易中铸造多个代币
await erc1155Collection.mint(
walletClient,
10n, // 比 10 个单独的交易更节省燃气
metadataURI,
totalPrice,
proof
)
// 对于 ERC721:考虑在应用程序级别进行批量操作
const mintPromises = []
for (let i = 0; i < 5; i++) {
mintPromises.push(
collection.mint(walletClient, 1n, undefined, mintPrice, proof)
)
}
// 并发执行铸造(注意管理 nonce)
const results = await Promise.all(mintPromises)
燃气价格管理
燃气价格优化
Copy
Ask AI
import { createWalletClient, http } from 'viem'
// 自定义燃气配置
const optimizedWalletClient = createWalletClient({
chain: b3Testnet,
transport: http(),
account,
// 燃气配置
gasPrice: parseGwei('20'), // 自定义燃气价格
})
// 或使用动态燃气定价
const gasPrice = await publicClient.getGasPrice()
const adjustedGasPrice = gasPrice * 110n / 100n // 当前价格上 10%
await collection.mint(
optimizedWalletClient,
1n,
undefined,
mintPrice,
proof,
{
gasPrice: adjustedGasPrice
}
)
监控和分析
铸造事件跟踪
事件监控
Copy
Ask AI
import { getCollectionMintEvents } from '@b3dotfun/basemint'
// 跟踪铸造事件
const fromBlock = await publicClient.getBlockNumber() - 1000n
const toBlock = await publicClient.getBlockNumber()
const mintEvents = await getCollectionMintEvents(
publicClient,
collection.address,
"ERC721",
fromBlock,
toBlock
)
console.log("近期铸造:", mintEvents.map(event => ({
minter: event.args.minter,
tokenId: event.args.tokenId?.toString(),
quantity: event.args.quantity?.toString(),
blockNumber: event.blockNumber
})))
实时监控
实时铸造监控
Copy
Ask AI
// 观察新的铸造事件
const unwatch = publicClient.watchContractEvent({
address: collection.address,
abi: collection.abi,
eventName: 'Transfer', // 或 'TransferSingle' 对于 ERC1155
onLogs: (logs) => {
logs.forEach(log => {
console.log('检测到新铸造:', {
from: log.args.from,
to: log.args.to,
tokenId: log.args.tokenId?.toString()
})
})
}
})
// 完成后停止观察
// unwatch()
最佳实践
用户体验
- 在铸造过程中提供清晰的反馈
- 预先显示估计的燃气费用
- 实现适当的加载状态
- 优雅地处理错误,提供用户友好的消息