Skip to content
Open the app

Mint from your page

Two ways to sell a KURV collection from your own page. Both work on Base and on Solana, and every on-chain fee, price and sale rule still applies: the same contract or program takes the same payment.

You want toUse
Paste one line and get a Mint pressThe Mint button: the buyer approves in a KURV window
Keep the buyer on your page with your own wallet connectorThe KURV client: the buyer approves in their wallet

Name the network with 84532 (Base Sepolia) or solana:devnet (Solana Devnet). Collection addresses are in the Public APIs.

<div id="mint" data-kurv-mint data-chain="84532" data-address="0x8354d02d8022f455db9acb235c6f6655c8adabd3"></div>
<script src="https://testnet.kurv.fun/sdk/mint-button/v1.js" async></script>
<script>
document.getElementById('mint').addEventListener('kurv:mint', (event) => {
if (event.detail.status === 'minted') console.log(event.detail.tx, event.detail.tokenIds);
});
</script>

A press opens a KURV window. The buyer signs there with their KURV account or a wallet, and your page never touches a wallet or a key. Set data-label, data-background and data-color for your own words and colours. If your site sends a Content-Security-Policy, allow https://testnet.kurv.fun in script-src.

The window first says hello to your page, and the site’s name appears in it only if your page answers from its own origin. Then it cuts its tie to your page, so nothing on a page can touch a window that is signing. The answer comes from KURV’s origin, read by the random value that press drew and only from your page’s origin, and the script raises kurv:mint on the element:

statusMeans
mintedThe mint is through: chain, collection, tx, tokenIds, quantity. This can follow closed when a buyer took a long time to log in
closedNo sign of the window for a while, and no mint. KURV never says why
blockedThe browser refused to open a window. Ask the buyer to allow it

Your page learns nothing about a buyer who does not mint: not their wallet, not whether they are on an allowlist. KURV pages are the only place a buyer reads those answers.

A site that sends Cross-Origin-Opener-Policy: same-origin cannot answer the hello: the mint and the answer still work, and the window shows no site name. Use same-origin-allow-popups instead. Treat tx as a claim until your own server has read it on chain.

One ES module with no dependencies, its types beside it in v1.d.ts. It asks the Public APIs for a fresh quote and the exact calls for this buyer, allowlist proof included, and hands them to the buyer’s wallet.

import { createKurvClient, eip1193Wallet } from 'https://testnet.kurv.fun/sdk/client/v1.js';
const kurv = createKurvClient();
const [account] = await window.ethereum.request({ method: 'eth_requestAccounts' });
const result = await kurv.mint({
chain: '84532',
address: '0x8354d02d8022f455db9acb235c6f6655c8adabd3',
wallet: eip1193Wallet(window.ethereum, account),
quantity: 1,
// Show the buyer the amounts, and answer false to sign nothing.
review: (plan) => confirm(`Pay at most ${plan.quote.max_total_base_units} base units?`),
});

On Solana, use a Wallet Standard wallet. KURV signs only for the fresh piece’s own account, and the wallet signs and pays as the buyer. Network fees and account rent are in SOL.

import { createKurvClient, walletStandardWallet } from 'https://testnet.kurv.fun/sdk/client/v1.js';
const kurv = createKurvClient();
const result = await kurv.mint({
chain: 'solana:devnet',
address: collectionAddress,
wallet: walletStandardWallet(wallet, account, 'solana:devnet'),
});

Any connector works: evmWallet and solanaWallet wrap yours in a few lines. The client never sees a key.

kurv.prepareMint({ chain, address, wallet, quantity }) answers the plan and signs nothing, and that plan is the quote: quote.total_base_units now, and quote.max_total_base_units, the most this buyer can be charged in the collection’s coin, which the contract or program enforces. A sale window with a second coin also charges quote.additional_total_base_units in that coin, and the network fee is on top. A collection sold in a rising price signs a little above the quote, so a mint landing first does not fail the buyer’s.

The same plan over HTTP, with no account and no key:

Terminal window
curl -X POST https://testnet.kurv.fun/api/v1/collections/84532/0x8354d02d8022f455db9acb235c6f6655c8adabd3/mint-call \
-H 'content-type: application/json' \
-d '{"wallet":"0xYourBuyer","quantity":1}'
error.codeMeansWhat to do
not_on_allowlistThis sale window is for its allowlistTell the buyer
not_openThe collection is not selling right nowShow its next window from the collection record
use_windowAn auction or a later window with a second coinOpen error.window_url
rate_limitedToo many requests from this networkTry again shortly

Save this as a file on any https site, or serve it from your own machine, and press the button. It needs a browser wallet on Base Sepolia.

<!doctype html>
<meta charset="utf-8">
<title>Mint</title>
<button id="mint">Mint</button>
<p id="said" role="status"></p>
<script type="module">
import { createKurvClient, eip1193Wallet } from 'https://testnet.kurv.fun/sdk/client/v1.js';
const kurv = createKurvClient();
const said = document.getElementById('said');
document.getElementById('mint').addEventListener('click', async () => {
try {
const [account] = await window.ethereum.request({ method: 'eth_requestAccounts' });
const result = await kurv.mint({
chain: '84532',
address: '0x8354d02d8022f455db9acb235c6f6655c8adabd3',
wallet: eip1193Wallet(window.ethereum, account),
review: (plan) => confirm(`Pay at most ${plan.quote.max_total_base_units} base units?`),
});
said.textContent = result.status === 'minted' ? `Minted: ${result.tx}` : 'Nothing was signed.';
} catch (error) {
said.textContent = error.message;
}
});
</script>

Unrevealed art stays sealed in all of this: the API answers calls and amounts, never a sealed collection’s files. See 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. .