Developer documentation
Quik docs
Launch an ERC-20 token with bootstrapped Uniswap V3 liquidity in a single transaction. Vanity addresses end in 6969 by default.
Overview
Quik is a permissionless launchpad on Robinhood Chain. A single transaction deploys an ERC-20 token, seeds a Uniswap V3 pool with one of several preset liquidity configs, and locks the LP NFT inside the factory. Trading fees accrue to the creator and can be claimed at any time.
- Total supply: 1,000,000,000 tokens, 18 decimals, fixed.
- Pool fee: 1% Uniswap V3 (fee tier 10000).
- Vanity suffix: all token addresses end in
0x…6969via CREATE2. Configurable backend-side throughVANITY_SUFFIX. - Anti-snipe tax: a per-config penalty curve applied for the first 5 blocks after launch; 2% max-wallet during the same window.
- Network: Robinhood Chain (chain id
4663).
Factory contracts
The factory is immutable. Configs are stored on-chain and read live via GET /liquidity-configs.
| Network | Chain ID | Address |
|---|---|---|
| Robinhood Chain | 4663 | 0xa8ffcbbae5b14a3ad3f0e83e7813301ecc49d46a |
0xca1f6f8f01e8e6d078c4258f41063d6cfa7d4c9b is inert and marked inactive in the indexer; do not use it.Fees
The Uniswap V3 pool fee is fixed at 1%. The ETH side of swap fees splits between the creator and the protocol; the token side accumulated in the LP position is automatically burned.
| Bucket | Share | Behaviour |
|---|---|---|
| Creator (receiver) | 50% | Withdrawn manually via collectFees |
| Platform | 50% | Goes to the protocol treasury |
| Token side of LP fees | 100% burn | Removed from circulating supply on each claim |
During the first 5 blocks after launch, an anti-snipe penalty is applied on top of the swap fee. The exact curve depends on the chosen liquidity config (each config carries a penalty_multiplier in [0, 100]). Preview the curve with GET /penalty-curve.
Launch sequence
Launching a token is four steps:
- 1
Upload a token logo (optional)
POST /api/v1/uploads/token-logo?owner=0xCREATORacceptsmultipart/form-datawith a singlefilefield. PNG, JPEG, WebP and GIF are supported up to 5 MB. The response contains a CDNurlyou can pass in the next step. - 2
Create a metadata draft
POST /api/v1/launch/draftstores the off-chain metadata and returns an opaque id of the formqmd_<hex>. This id is what you pass on-chain as the_metadataargument — the indexer attaches the full metadata to the token after the launch event fires.{ "name": "My Token", "symbol": "MYT", "image_url": "https://cdn.quik.meme/...", "description": "Optional, max 1000 chars", "socials": { "twitter": "https://x.com/...", "telegram": "https://t.me/...", "discord": "https://discord.gg/...", "website": "https://...", "farcaster": "..." }, "chain_id": 1 }Drafts are scoped to the creator wallet that signed in via SIWE. Unclaimed drafts expire after 48 hours. - 3
Mine a vanity salt
POST /api/v1/launch/vanity-saltruns a Rust CREATE2 search and returns abytes32salt that produces a token address ending in6969.POST /api/v1/launch/vanity-salt Authorization: Bearer <jwt> { "name": "My Token", "symbol": "MYT", "creator": "0xCREATOR", "chain_id": 1 } → { "salt": "0x...", "address": "0x…6969", "attempts": 4821, "suffix": "6969" } - 4
Call launchToken
The factory exposes a single payable function. The optional
msg.valueis a creator buy executed atomically with deployment.function launchToken( string _name, string _symbol, string _metadata, // qmd_<hex> draft id, or "" for none bytes32 salt, // from /launch/vanity-salt address receiver, // fee beneficiary, usually = msg.sender uint256 split, // creator/receiver split, usually 100 uint256 configId // 0..N, see /liquidity-configs ) external payable returns (uint256 tokensReceived);receiverandsplitare stored on-chain but the v1 contract does not yet route fees through them — the fee receiver is set at the factory level. Pass(msg.sender, 100)for forward-compatibility.
Claim fees
Fees do not auto-distribute — the creator (or whoever is set as the fee receiver on the factory) must call collectFees themselves. Call it as often as you like; there is no minimum.
function collectFees(uint256 tokenId)
external
returns (uint256 amount0, uint256 amount1);tokenId is the Uniswap V3 LP NFT id minted at launch. Look it up via GET /tokens/:address (field liquidity.token_id) or read GET /tokens/:address/pending-fees first to see how much is currently claimable.
Authentication (SIWE)
Endpoints that mutate state — drafts, vanity-salt mining, profile edits, uploads — require a JWT obtained via Sign-In-With-Ethereum (EIP-4361).
# 1. Get a nonce + message
POST /api/v1/auth/nonce
{ "address": "0xYOU", "chain_id": 1 }
→ { "message": "...", "nonce": "..." }
# 2. Sign the message with the wallet, then verify
POST /api/v1/auth/verify
{ "message": "...", "signature": "0x..." }
→ { "token": "<jwt>", "expires_at": "..." }
# 3. Send the JWT on subsequent calls
Authorization: Bearer <jwt>AUTH_DOMAIN and AUTH_URI on the backend; signatures from a different origin will be rejected.API reference
Base URL https://api.quik.meme/api/v1. All endpoints return JSON. Read endpoints are open; write endpoints require a JWT (see above).
Launch
| Method | Path | Description | Auth |
|---|---|---|---|
| POST | /auth/nonce | Get the SIWE message to sign | — |
| POST | /auth/verify | Exchange a signature for a JWT | — |
| POST | /launch/draft | Create a metadata draft | JWT |
| POST | /launch/vanity-salt | Mine a CREATE2 salt with the configured suffix | JWT |
| GET | /liquidity-configs?chain_id=1 | List on-chain liquidity configs | — |
| GET | /factory-state?chain_id=1 | Active factory + admin state | — |
| GET | /penalty-quote?eth=0.05&config_id=0 | Quote anti-snipe penalty for one buy size | — |
| GET | /penalty-curve?max_eth=0.5&samples=100&config_id=0 | Sample the full penalty curve | — |
Tokens & discovery
| Method | Path | Description | Auth |
|---|---|---|---|
| GET | /tokens?sort=…&limit=20&offset=0 | Leaderboard. sort ∈ {volume_24h, volume_7d, market_cap, fees, new, trending} | — |
| GET | /tokens/:address?chain_id=1 | Full token detail | — |
| GET | /tokens/:address/swaps?limit=50&before=<unix_ms> | Trade history | — |
| GET | /tokens/:address/holders | Top holders | — |
| GET | /tokens/:address/pending-fees | Uncollected LP fees in WETH | — |
| GET | /tokens/:address/chart/ohlcv | OHLCV candles | — |
| GET | /tokens/:address/chart/trades | Raw trade points | — |
| GET | /tokens/:address/messages | Coin chat messages | — |
Profiles & search
| Method | Path | Description | Auth |
|---|---|---|---|
| GET | /me | Authenticated user profile | JWT |
| PATCH | /me/profile | Update username, bio, socials | JWT |
| GET | /profile/:address/launched | Tokens deployed by a wallet | — |
| GET | /profile/:address/earnings | Tokens where wallet is receiver | — |
| GET | /profile/:address/activity | Wallet swap history | — |
| GET | /profile/:address/balances | Token holdings | — |
| GET | /search?q=…&limit=10 | Combined token + profile search | — |
| GET | /resolve/:address | ENS / Basename reverse lookup | — |
| POST | /resolve/batch | Batch reverse lookup | — |
| GET | /username/:name/available | Username availability check | — |
Uploads
| Method | Path | Description | Auth |
|---|---|---|---|
| POST | /uploads/avatar | User avatar (max 2 MB) | JWT |
| POST | /uploads/banner | User banner (max 3 MB) | JWT |
| POST | /uploads/token-logo?owner=0x… | Token logo (max 5 MB). PNG, JPEG, WebP, GIF | — |
Image responses include url, key, content_type, width, height, size and animated.
Stats & activity
| Method | Path | Description | Auth |
|---|---|---|---|
| GET | /stats/protocol | Total fees, 24h volume, token count | — |
| GET | /stats/top-earners?limit=10 | Creator earnings leaderboard | — |
| GET | /activity/recent | Recent swaps across all tokens | — |
| GET | /activity/big-buys | Notable buy orders | — |
| GET | /activity/claims | Recent fee claims | — |
Full example (TypeScript + viem)
End-to-end: sign in with SIWE, mine a vanity salt, create a metadata draft, deploy. Replace the placeholders before running.
import { createPublicClient, createWalletClient, http, parseEther } from "viem";
import { mainnet } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
const API = "https://api.quik.meme/api/v1";
const FACTORY = "0x35497ec9e3b142d8b1783049a9ad6f58fc50c9dd" as const;
const RPC = "https://rpc.mevblocker.io/fast";
const account = privateKeyToAccount("0xPRIVATE_KEY");
const wallet = createWalletClient({ account, chain: mainnet, transport: http(RPC) });
const publicClient = createPublicClient({ chain: mainnet, transport: http(RPC) });
// 1. SIWE — get a JWT
const { message } = await fetch(`${API}/auth/nonce`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ address: account.address, chain_id: 1 }),
}).then((r) => r.json());
const signature = await wallet.signMessage({ message });
const { token } = await fetch(`${API}/auth/verify`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ message, signature }),
}).then((r) => r.json());
const auth = { authorization: `Bearer ${token}`, "content-type": "application/json" };
// 2. Create a metadata draft
const { id: metadataId } = await fetch(`${API}/launch/draft`, {
method: "POST",
headers: auth,
body: JSON.stringify({
name: "My Token",
symbol: "MYT",
description: "An onchain memecoin.",
socials: { twitter: "https://x.com/example" },
chain_id: 1,
}),
}).then((r) => r.json());
// 3. Mine a vanity salt
const { salt } = await fetch(`${API}/launch/vanity-salt`, {
method: "POST",
headers: auth,
body: JSON.stringify({
name: "My Token",
symbol: "MYT",
creator: account.address,
chain_id: 1,
}),
}).then((r) => r.json());
// 4. Deploy
const abi = [{
type: "function",
name: "launchToken",
stateMutability: "payable",
inputs: [
{ name: "_name", type: "string" },
{ name: "_symbol", type: "string" },
{ name: "_metadata", type: "string" },
{ name: "salt", type: "bytes32" },
{ name: "receiver", type: "address" },
{ name: "split", type: "uint256" },
{ name: "configId", type: "uint256" },
],
outputs: [{ name: "tokensReceived", type: "uint256" }],
}] as const;
const hash = await wallet.writeContract({
address: FACTORY,
abi,
functionName: "launchToken",
args: ["My Token", "MYT", metadataId, salt, account.address, 100n, 0n],
value: parseEther("0.1"), // creator buy, optional
});
const receipt = await publicClient.waitForTransactionReceipt({ hash });
console.log("Launched in block", receipt.blockNumber);For the full open-source frontend implementation, see the app/create/page.tsx route in the Quik repo — it wires the same flow to RainbowKit and a UI.
Found a bug or missing endpoint? Open an issue or DM us. Docs are versioned with the contract; if a field on this page disagrees with on-chain reality, on-chain wins.