Mint from your site
Use your own EVM wallet connector and the public ABI. KurvDrop minting is an ERC-20 operation, not a payable ETH mint. ETH covers network gas. Free mint phases may still charge the collection’s service fee, so use the quote instead of assuming zero cost.
This example handles a public phase without an auction module and caps payment at the exact quote. It uses a browser wallet supplied by the visitor, never a server private key. Display the total, additional token cost and chain to your buyer and obtain their confirmation before running the approval and mint writes.
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.');For an allowlisted phase, obtain the buyer wallet’s allowance and Merkle proof from KURV’s existing proof flow and pass them as the third and fourth mint arguments. Never substitute an empty proof for a private phase. Wallet limits, phase supply, pause, auction holds and total cost are enforced by the contract; simulation must succeed before sending. Falling-price auctions and piece auctions use their own sale modules and are not ordinary inline mint phases; use the official page until you integrate and verify that module’s ABI and settlement flow.
The final mint argument is a referrer wallet address, not a tracking string. Default to zeroAddress until you deliberately integrate the deployed collection’s referral terms. The contract decides the actual fee split; adding a link code does not create a commission by itself. Marketplace resales use marketplace contracts and signed orders, not the primary-mint call shown here.
For the collection response schema, see Public APIs. For a ready-made widget, use Collection embeds. Contract permissions, fees and the underlying collection terms still apply; see Fees and Risks and disclaimer.
Nothing here is financial advice. Read Risks and disclaimer before you mint, buy or sell back. Back to kurv.fun. Privacy policy. Terms of use. .
