在你的网站上铸造
使用你自己的 EVM 钱包连接器和公开 ABI。KurvDrop 的铸造是一个 ERC-20 操作,而不是用 ETH 支付的 payable 铸造。ETH 用于支付网络 Gas。免费铸造阶段仍可能收取合集的服务费,所以请使用报价,不要假定费用为零。
本示例处理的是一个没有拍卖模块的公开阶段,并把付款上限设为精确的报价。它使用访问者自己提供的浏览器钱包,绝不使用服务器私钥。在执行授权和铸造写入之前,请向买家展示总价、额外的代币费用和所在的链,并获得他们的确认。
import { createPublicClient, createWalletClient, custom, erc20Abi, http, zeroAddress, zeroHash,} from 'viem';import { baseSepolia } from 'viem/chains';
const api = 'https://testnet.kurv.fun';const { abi } = await fetch(`${api}/api/v1/contracts/kurvdrop`).then(r => r.json());const publicClient = createPublicClient({ chain: baseSepolia, transport: http() });const walletClient = createWalletClient({ chain: baseSepolia, transport: custom(window.ethereum) });const [account] = await walletClient.requestAddresses();await walletClient.switchChain({ id: baseSepolia.id });
// Woof Pack, verified in KURV's Base Sepolia catalog.const address = '0x8354d02d8022f455db9acb235c6f6655c8adabd3';const { collection: live } = await fetch( `${api}/api/v1/collections/84532/${address}`).then(r => r.json());if (live.contract_type !== 'KurvDrop' || live.mint.active_phase_id === null) { throw new Error('No public mint phase is available.');}const phaseId = BigInt(live.mint.active_phase_id);const quantity = 1n;const phase = await publicClient.readContract({ address, abi, functionName: 'getPhase', args: [phaseId] });if (phase.module !== zeroAddress || phase.merkleRoot !== zeroHash) { throw new Error('This example supports only public phases without an auction module.');}const paymentToken = await publicClient.readContract({ address, abi, functionName: 'paymentToken' });const [maxTotalCost] = await publicClient.readContract({ address, abi, functionName: 'quoteMint', args: [phaseId, quantity] });
// Display these amounts using each token's on-chain decimals and symbol.const required = new Map([[paymentToken.toLowerCase(), maxTotalCost]]);if (phase.token !== zeroAddress && phase.tokenPrice > 0n) { const token = phase.token.toLowerCase(); required.set(token, (required.get(token) ?? 0n) + phase.tokenPrice * quantity);}
// Run only after the buyer reviews and confirms the displayed amounts.for (const [token, amount] of required) { const allowance = await publicClient.readContract({ address: token, abi: erc20Abi, functionName: 'allowance', args: [account, address] }); if (allowance >= amount) continue; // Reset an existing allowance for tokens requiring zero before a new approval. if (allowance > 0n) { const reset = await walletClient.writeContract({ account, address: token, abi: erc20Abi, functionName: 'approve', args: [address, 0n] }); await publicClient.waitForTransactionReceipt({ hash: reset }); } const approved = await walletClient.writeContract({ account, address: token, abi: erc20Abi, functionName: 'approve', args: [address, amount] }); await publicClient.waitForTransactionReceipt({ hash: approved });}
// Exact quote ceiling: if the required price increased, simulation/mint refuses.const { request } = await publicClient.simulateContract({ account, address, abi, functionName: 'mint', args: [phaseId, quantity, 0n, [], maxTotalCost, zeroAddress],});const hash = await walletClient.writeContract(request);const receipt = await publicClient.waitForTransactionReceipt({ hash });if (receipt.status !== 'success') throw new Error('Mint did not complete.');对于白名单阶段,请通过 KURV 现有的证明流程获取买家钱包的额度和 Merkle 证明,并把它们作为铸造的第三个和第四个参数传入。对于私有阶段,绝不能用空证明代替。钱包上限、阶段总量、暂停、拍卖保留和总费用都由合约强制执行;发送之前,模拟必须成功。降价拍卖和单件拍卖使用它们自己的发售模块,不是普通的内嵌 mint 阶段;在你集成并验证该模块的 ABI 和结算流程之前,请使用官方页面。
最后一个铸造参数是一个推荐人钱包地址,而不是追踪字符串。在你有意集成已部署合集的推荐条款之前,默认使用 zeroAddress。实际的费用分配由合约决定;仅仅添加一个链接代码,本身并不会产生佣金。市场上的转售使用市场合约和签名订单,而不是这里展示的一级铸造调用。
关于合集响应的结构,参见公开 API。如需现成的小组件,请使用合集嵌入。合约权限、费用和合集本身的条款仍然适用;参见费用和风险与免责声明。
此处内容均不构成财务建议。在铸造、购买或卖回之前,请先阅读风险与免责声明。返回 kurv.fun。隐私政策。使用条款。 。
