This section is for developers integrating with ZecPad's on-chain program
or building tools on top of ZecPad data. It assumes familiarity with
Solana, Anchor, and @solana/web3.js.
Pre-release notice: ZecPad's bonding-curve program has not been deployed to mainnet-beta and has not completed a security audit (see Security & Audits). Program IDs, account layouts, and instruction signatures below reflect the current design and are subject to change before mainnet launch. Do not build production integrations against them yet — treat this section as an implementation preview, not a stable interface.
| Program | Cluster | Address |
|---|---|---|
zecpad_launchpad | mainnet-beta | Not yet deployed |
zecpad_launchpad | devnet | Not yet deployed |
Once deployed, addresses will be published here and verifiable against the program's on-chain source hash. ZecPad's program relies on, but does not fork or replace, these standard programs:
| Dependency | Address |
|---|---|
| SPL Token-2022 | TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb |
| Metaplex Token Metadata | metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s |
The IDL will be published alongside the mainnet deployment and mirrored at
idl/zecpad_launchpad.json in the program repository. Until then, the
instruction set below reflects the current program design.
create_tokenCreates the SPL Token-2022 mint, initializes its BondingCurve account,
and (via CPI) creates its Metaplex metadata account.
| Parameter | Type | Description |
|---|---|---|
name | string | Token display name |
symbol | string | Ticker |
uri | string | Metadata JSON URI (image, description, socials) |
supply | u64 | Total supply, minted once |
curve_shape | enum { Steep, Linear, Flat } | Sets initial virtual reserve ratio |
migration_target_lamports | u64 | Real SOL reserves at which migration triggers |
dev_buy_lamports | u64 | Optional same-transaction buy amount for the creator |
enable_privacy_modeCPI into SPL Token-2022 to initialize the ConfidentialTransferMint
extension on the token's mint. Must be called at create_token time —
Privacy Mode cannot be added to an existing public token after launch.
| Parameter | Type | Description |
|---|---|---|
auto_approve_new_accounts | bool | Whether new confidential accounts are auto-approved |
auditor_elgamal_pubkey | Option<ElGamalPubkey> | Optional auditor key with transfer-amount decrypt capability |
buyBuys tokens against the curve's constant-product formula.
| Parameter | Type | Description |
|---|---|---|
sol_amount | u64 | Lamports to spend |
min_tokens_out | u64 | Slippage guard — transaction fails if the quote is worse |
Enforces the per-wallet/per-transaction anti-bot limits described in
Bonding Curve & Tokenomics via an
AntibotTracker PDA keyed by (mint, wallet).
sellSymmetric to buy: burns/returns tokens to the curve, returns SOL to the
seller net of the trading fee.
| Parameter | Type | Description |
|---|---|---|
token_amount | u64 | Tokens to sell |
min_sol_out | u64 | Slippage guard |
migrate_liquidityPermissionless — callable by anyone once the curve's real SOL reserves meet
migration_target_lamports. Halts curve trading, deposits liquidity into a
new Raydium/Orca pool via CPI, and revokes the mint authority.
claim_creator_fee / withdraw_platform_feeWithdraw accrued trading-fee shares from, respectively, the token's
CreatorVault PDA and the platform's treasury.
All state is stored in plain Anchor accounts and is readable by anyone without special access:
import { PublicKey } from "@solana/web3.js";
import { Program } from "@coral-xyz/anchor";
const [bondingCurvePda] = PublicKey.findProgramAddressSync(
[Buffer.from("bonding_curve"), mint.toBuffer()],
ZECPAD_PROGRAM_ID
);
const curve = await program.account.bondingCurve.fetch(bondingCurvePda);
// curve.virtualSolReserves, curve.virtualTokenReserves,
// curve.realSolReserves, curve.tokensSold, curve.status
The program emits Anchor events (TradeEvent, TokenCreatedEvent,
MigrationEvent) rather than requiring log parsing:
const listenerId = program.addEventListener("TradeEvent", (event, slot) => {
console.log(event.mint.toBase58(), event.side, event.solAmount.toString());
});
// later
program.removeEventListener(listenerId);
For production indexing, prefer a Geyser plugin or a managed webhook
provider (e.g. Helius) over onLogs/addEventListener on a public RPC —
see the RPC guidance below for why.
import * as anchor from "@coral-xyz/anchor";
import { Keypair } from "@solana/web3.js";
const mint = Keypair.generate();
await program.methods
.createToken({
name: "Veilcoin",
symbol: "VEIL",
uri: "https://example.com/veilcoin.json",
supply: new anchor.BN(1_000_000_000),
curveShape: { steep: {} },
migrationTargetLamports: new anchor.BN(85 * anchor.web3.LAMPORTS_PER_SOL),
devBuyLamports: new anchor.BN(0.5 * anchor.web3.LAMPORTS_PER_SOL),
})
.accounts({ mint: mint.publicKey, creator: wallet.publicKey /* … */ })
.signers([mint])
.rpc();
Public RPC endpoints (api.mainnet-beta.solana.com,
api.devnet.solana.com) are rate-limited and, in the case of the public
mainnet-beta endpoint, actively reject cross-origin browser requests
from unrecognized origins (you will see an HTTP 403 with
{"error":{"code":403,"message":"Access forbidden"}}). This is not a bug
in your integration — it's expected behavior of the public endpoint, and it
means:
NEXT_PUBLIC_SOLANA_RPC_URL) rather than hardcoding it, so it can be
swapped between devnet and a production provider without a code change.getProgramAccounts — the latter is expensive and
frequently disabled entirely on public and even some paid RPC tiers.