zpad is not live yetWe have no token. Any coin claiming to be ours is a scam.

Launch a coin

Docs

How value moves through zpad.

Launch a pump.fun coin paired with a privacy coin, and everyone who holds it is paid in privacy coins every hour. No accounts, every movement on chain, and a public API for all of it.

Overview

zpad is a launchpad and a payout engine. Every coin it launches is paired with Zcash, Monero or Litecoin on Solana and carries a 3% creator fee. Instead of going to the launcher, that fee is split between the people holding the coin, every hour, and paid out natively on privacy chains.

Pair withZEC · XMR · LTC
Holders get60% of fees
Paid inZEC · ALEO · DASH · LTC

How it works

Five stages. The last four repeat forever.

  1. 01

    Launch

    once

    A visitor submits a name, ticker, image and pair. zpad pins the metadata to IPFS, takes a keypair ending in zpad from its pool, and creates the coin on pump.fun with a 3% creator fee. zpad pays the network fee.

  2. 02

    Trade

    every trade

    Every buy and sell on the bonding curve (and on PumpSwap after graduation) pays the creator fee in the pair coin. It lands in a vault owned by that coin’s own derived creator key.

  3. 03

    Snapshot

    :00 UTC

    At the top of every hour zpad snapshots every wallet holding at least 1,000 tokens, before touching the vault — so nobody can buy in after seeing the pot.

  4. 04

    Split

    :00 UTC

    The vault is swept. XMR and LTC fees are swapped into Solana ZEC through Jupiter. 60% is credited to holders pro-rata; dust rolls forward.

  5. 05

    Claim

    any time

    A holder signs one plain message. NEAR Intents delivers their balance natively as ZEC, ALEO, DASH or LTC to an address on that chain.

The hourly cron, in order
vercel cron  0 * * * *  →  /api/cron/collect

for each live coin:
  1. snapshotHolders(mint)          # who holds, right now
  2. collectCreatorFee(mint)        # sweep the coin's own vault
  3. swapToZec(amount)              # XMR / LTC pairs only, via Jupiter
  4. creditHolders(pot, snapshot)   # 60% pro-rata, dust carried
  5. record(signature)              # public on /distributions

Fees & the split

3% of every trade is collected. 60% of that goes to holders; the rest pays for free launches and payout network fees.

Creator fee · 3%
$1,500
Holder pot · 60%
$900
Your payout this hour
$9.00
≈ 0.00620 ZEC

The split uses integer math on base units. Every share is rounded down, so the protocol never pays out more than it collected, and whatever rounds away is carried into the next hour’s pot.

lib/split.ts
const CREATOR_FEE_BPS = 300n   // 3% of every trade
const COMMUNITY_BPS   = 6000n  // 60% of what is collected

function split(collected, holders, carry) {
  const pot = (collected * COMMUNITY_BPS) / 10_000n + carry
  const circulating = holders.reduce((s, h) => s + h.amount, 0n)

  let paid = 0n
  const credits = holders.map((h) => {
    const share = (pot * h.amount) / circulating       // floor division, never overpays
    paid += share
    return { wallet: h.owner, amount: share }
  })

  return { credits, carry: pot - paid }                // dust rolls into the next hour
}

Who gets paid

Only people. Programs and zpad itself are filtered out on chain.

  • Wallets holding at least 1,000 tokens at the snapshot.
  • The bonding curve, AMM pools and lockers are skipped: their owners are off-curve program addresses.
  • zpad’s treasury and the coin’s own creator key are skipped.
  • Several token accounts owned by one wallet count as one holder.
lib/holders.ts
// Runs every hour, BEFORE the vault is swept.
const accounts = await connection.getProgramAccounts(tokenProgram, {
  filters: [{ memcmp: { offset: 0, bytes: mint } }],   // token accounts of this mint
  dataSlice: { offset: 32, length: 40 },                // owner (32) + amount (8)
})

const byOwner = new Map()
for (const { account } of accounts) {
  const owner = account.data.subarray(0, 32)
  const amount = account.data.readBigUInt64LE(32)
  if (amount === 0n) continue
  if (!PublicKey.isOnCurve(owner)) continue            // curve, pools, lockers: skipped
  const key = new PublicKey(owner).toBase58()
  if (key === treasury || key === creator) continue    // zpad's own wallets: skipped
  byOwner.set(key, (byOwner.get(key) ?? 0n) + amount)  // many accounts → one wallet
}

const holders = [...byOwner].filter(([, amt]) => amt >= 1_000n * 1_000_000n)

Claiming

Claims open at 0.002 ZEC. You always claim the whole balance, in one coin, to one address.

ZcashZEC
u1… or t1…Shielded u1 addresses hide sender, receiver and amount.
AleoALEO
aleo1…Private by default. Transfers are zero-knowledge proofs.
DashDASH
X…Public by default. Mix it with CoinJoin in your wallet.
LitecoinLTC
ltc1… or L…Public by default. Move it into MWEB in your wallet.

To claim, your wallet signs this exact text. The server rebuilds it from the request and checks the ed25519 signature against your address. It expires after 10 minutes and the amount must equal your available balance to the base unit.

The message you sign
zpad: claim Zcash

Send my holder earnings as native ZEC through NEAR Intents.

wallet: 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU
pay in: ZEC
to: u1qg…your-shielded-address
amount: 0.018432 ZEC
issued: 2026-09-29T12:00:00.000Z
claimMessage()
const NAMES = { ZEC: "Zcash", ALEO: "Aleo", DASH: "Dash", LTC: "Litecoin" }

function claimMessage({ wallet, payout, to, amount, issuedAt }) {
  const zec = (Number(amount) / 1e8).toFixed(8).replace(/0+$/, "").replace(/\.$/, "")
  return [
    `zpad: claim ${NAMES[payout]}`,
    "",
    `Send my holder earnings as native ${payout} through NEAR Intents.`,
    "",
    `wallet: ${wallet}`,
    `pay in: ${payout}`,
    `to: ${to}`,
    `amount: ${zec} ZEC`,
    `issued: ${issuedAt}`,
  ].join("\n")
}
import bs58 from "bs58"

const wallet = window.phantom.solana
const { publicKey } = await wallet.connect()
const address = publicKey.toBase58()
const to = "u1qg…your-shielded-address"

// 1. Read the balance and get a live NEAR Intents quote.
const { balance } = await fetch(`/api/claim?wallet=${address}`).then((r) => r.json())
const quote = await fetch("/api/claim/preview", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ wallet: address, payout: "ZEC", to }),
}).then((r) => r.json())

// 2. Sign the exact claim message. This is not a transaction.
const intent = {
  wallet: address,
  payout: "ZEC",
  to,
  amount: balance.available,
  issuedAt: new Date().toISOString(),
}
const { signature } = await wallet.signMessage(
  new TextEncoder().encode(claimMessage(intent)),
  "utf8",
)

// 3. Submit. zpad verifies the signature, then pays through NEAR Intents.
const claim = await fetch("/api/claim", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ ...intent, signature: bs58.encode(signature) }),
}).then((r) => r.json())

console.log(`${quote.amountOut} arriving in ~${claim.eta}s`)

API reference

Public, keyless JSON. Amounts are strings of Solana-ZEC base units (8 decimals).

Endpoint
GET/api/claim?wallet=Balance, per-coin earnings and claim history for a Solana wallet.
POST/api/claim/previewLive NEAR Intents quote for the whole balance. Validates the payout address.
POST/api/claimSigned claim. Pays the whole balance in the chosen coin.
GET/api/payouts?limit=Public ledger: hourly distributions and deliveries, newest first (max 100).
GET/api/coins/:mint/candles?tf=OHLCV candles in USD from pump.fun. 1m, 5m, 15m, 1h, 4h, 1d.
GET/api/coins/:mint/tradesLast 50 buys and sells.
GET/api/search?q=Find live coins by ticker, name or mint prefix.
POST/api/launchLaunch a coin. Same limits as the website.

Check earnings

curl "https://www.zpad.sh/api/claim?wallet=7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"
Response
{
  "wallet": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
  "balance": {
    "earned":    "1843200",
    "claimed":   "0",
    "available": "1843200",
    "min":       "200000"
  },
  "perCoin": [ … ],
  "claims":  [ … ]
}

Payout ledger

curl "https://www.zpad.sh/api/payouts?limit=20"

Market data

# tf = 1m | 5m | 15m | 1h | 4h | 1d
curl "https://www.zpad.sh/api/coins/<mint>/candles?tf=1h"

Launch a coin

POST /api/launch
IMG=$(base64 -w0 logo.png)

curl -X POST "https://www.zpad.sh/api/launch" \
  -H "content-type: application/json" \
  -d '{
    "name": "Shielded Cat",
    "symbol": "SCAT",
    "description": "Holders earn Zcash.",
    "quote": "ZEC",
    "twitter": "https://x.com/shieldedcat",
    "imageType": "image/png",
    "imageBase64": "'"$IMG"'"
  }'

# → { "mint": "…zpad", "signature": "…" }

Pairs: ZEC (ZEC), XMR (XMR (wrapped)), LTC (cbLTC). Images must be PNG, JPEG, GIF or WebP under 4 MB. Twitter links must be on x.com or twitter.com.

Errors

Every error is JSON: { "error": "human readable message" }.

400
Bad input: wallet, ticker, image, payout address, or balance below the minimum claim.
401
Signature does not match the wallet, or it is older than 10 minutes.
404
Unknown coin.
409
Balance changed since you signed, or a claim with this signature is already on its way.
429
Launch limit reached: 2 per visitor per 24 hours, or the daily site cap.
502
The launch transaction did not land. The address goes back to the pool.
503
Temporarily unavailable: address pool empty, gas tank or payout wallet being topped up.

Parameters

Pairs
ZEC, XMR (wrapped), LTC (cbLTC) on Solana
Payout coins
ZEC, ALEO, DASH, LTC (native)
Creator fee
3% of every trade
Holder share
60% of collected fees
Snapshot
Hourly at :00 UTC
Minimum holding
1,000 tokens
Minimum claim
0.002 ZEC
Signature validity
10 minutes
Free launches
2 per visitor per day
Settlement
NEAR Intents

FAQ

Do I need a wallet to launch?

No. zpad signs and pays for the launch. The coin’s creator key is derived per coin by zpad, so the fee vault belongs to the coin, not to the launcher.

Does the person who launched earn more?

Only if they hold. Launchers are paid like any other holder, by balance at the snapshot.

Why is everything counted in ZEC?

Fees from XMR and LTC pairs are swapped into Solana ZEC each hour so every balance is one unit. You pick the coin you receive when you claim.

Can I be paid in Monero?

Not today. Monero can be a pair, but NEAR Intents cannot deliver native XMR, so it is not a payout option.

What does signing the claim message do?

It proves you control the wallet that earned the balance. It is not a transaction, moves nothing and costs nothing.

What if a payout fails?

NEAR Intents refunds to zpad and your balance is restored automatically. You can claim again.