Quickstart
You need a partner key. They are invite-only — there is no signup page. Talk to us and we will issue one scoped to your collections and your domains.
npm i @solanadeads/gravemintZero runtime dependencies, dual ESM + CJS, fully typed.
Read a drop
import { GraveMintClient } from '@solanadeads/gravemint'
const gm = new GraveMintClient({ apiKey: 'gm_pub_…' })
const drop = await gm.v1.collection('deads')
drop.collection // name, symbol, image, chain, socials
drop.stats // totalSupply, mintedCount, availableCount, percentMinted
drop.phases.active // the phase that is live right now, or null
drop.serverTime // our clock — use it for countdowns, never Date.now()Address a drop by its short id or on-chain address
Not by a database uuid — that is not a public identifier and is not accepted.
Render the price correctly
priceDisplay is already resolved. Branch on kind; never do arithmetic to reconstruct it.
const p = drop.phases.active?.priceDisplay
switch (p?.kind) {
case 'amount': return `${p.amount} ${p.currency}`
case 'range': return `from ${p.min} ${p.currency}`
case 'hidden': return 'Price revealed when you qualify'
default: return 'See on GraveMint' // 'unknown' — do NOT render 0
}unknown and hidden are not zero
Rendering 0 as "Free" because a price could not be resolved is the exact failure this shape exists to prevent.
Mint
Three steps, and the middle one is the only part you own.
// 1. we build it
const prepared = await gm.mint.prepare({
collectionId: drop.collection.id,
phaseId: drop.phases.active.id,
walletAddress: wallet.publicKey.toBase58(),
quantity: 1,
})
// 2. your signer signs it
const signed = await wallet.signTransaction(prepared.transactions[0].transaction)
// 3. we broadcast it
const result = await gm.mint.execute({
sessionId: prepared.sessions[0].id,
signedTransaction: signed,
})You sign. We broadcast.
Never submit a mint transaction to the chain yourself. execute refuses a request carrying transactionHash with CLIENT_BROADCAST_NOT_ALLOWED, and there is no flag to disable that.
It is not bureaucracy: the server compares the signed bytes against the transaction it built — program ids, instruction data, resolved account keys, fee payer — and rejects anything that does not match. That check is what protects your collectors from a tampered transaction, and it is only possible because we are the one submitting.
When you cannot render a drop faithfully
Some mechanics are outside the core surface — packs, gallery mode, generative drops, claim codes. Rather than let you render a wrong panel, the API tells you:
if (!drop.capabilities.supportedBySurface) {
// drop.capabilities.requiresFeatures -> e.g. ['claim_codes']
// drop.capabilities.mintUrl -> always correct
return <a href={drop.capabilities.mintUrl}>Mint on GraveMint</a>
}Showing a panel that quietly omits a mechanic is worse than sending the collector somewhere that handles it.
Next
- The read model — phases, the pricing union, eligibility and capabilities. Read this before rendering a price; it is where the correctness rules live.
- Wallets and signing — the signer interface, and why you never broadcast
- React mint panel — a complete panel to paste in
- Keys and origins — the part that most often goes wrong
- Errors — every code, what to retry and what is terminal
- Troubleshooting — the failures partners actually hit
- Full SDK reference · v1 API · MCP server
