Reference

Launchpad SDK

@cc0company/sdk — launch tokens, claim creator fees, stake $cc0company and ship NFT drops from any website, app or agent. One dependency: viem.

Install

bash
npm install @cc0company/sdk viem

Current version: 1.12.0. Open source on GitHub (CC0-1.0, of course). Five clients:

  • Cc0Launchpad — ERC-20 launches.
  • Cc0B20Launchpad — B20 launches (Base only).
  • Cc0Fees — read and claim creator fees.
  • Cc0Staking — stake $cc0company, earn WETH.
  • Cc0Drops — IPFS NFT drops (ERC-721 + ERC-1155): pin art, pin metadata, deploy, configure phases.

Upgrade off 1.11.x

1.11.x had a fund-locking bug: vault/airdrop admin and dev-buy proceeds followed creatorRewards[0]. On a Community Coin launch that slice is the distributor contract, so the vault was locked forever. In 1.12.0 creatorRewards slices are fees only — non-fee proceeds go to the launching account or to an explicit proceedsRecipient.

Chains

Every client takes a chain — the slug 'base', 'ethereum', 'robinhood', or the id 8453, 1, 4663. Defaults to Base.

CapabilityBaseEthereumRobinhood
Standard ERC-20 launch (75/15/10)YesYesYes
Paired ERC-20 launch (80/20)YesNoYes
Community Coin (fees to NFT holders)YesYesYes
B20 launchYesNoNo
$cc0company staking poolYesForwarder onlyEscrow only

Check paired availability at runtime rather than hardcoding it — isCc0PairedAvailable(chain) is derived from the address book and fails closed.

Ethereum RPC

viem's default mainnet RPC (eth.merkle.io) is CORS-blocked in browsers. The SDK ships a working default per chain (DEFAULT_RPCS); pass your own rpcUrl in production.

Launch a token

typescript
import { Cc0Launchpad } from '@cc0company/sdk';
import { createWalletClient, custom } from 'viem';
import { base } from 'viem/chains';

const walletClient = createWalletClient({
  chain: base,
  transport: custom(window.ethereum),
});

// chain: 'base' | 'ethereum' | 'robinhood' (or 8453 | 1 | 4663)
const launchpad = new Cc0Launchpad({ walletClient, chain: 'base' });

const { tokenAddress, txHash, registered } = await launchpad.launchToken({
  name: 'My Token',
  symbol: 'MTK',
  image: imageBytes, // any https URL, data: URL, Blob or bytes — pinned to
                     // IPFS by cc0.company automatically (the URI is written
                     // onchain forever). ipfs:// URIs pass through untouched.
  description: 'My awesome token', // stored onchain
  feeTier: 1,                      // 1 | 2 | 3 | 6.9 — or feeMode: 'dynamic'
});

One transaction: token + Uniswap V4 pool + locked LP + fee split, atomically. The deployer's wallet signs; the token is live and tradable the moment the transaction lands.

Any wallet — browser, private key, CDP, Bankr, Safe

Every client takes a viem walletClient, a viem account (e.g. privateKeyToAccount), or a provider-agnostic sender{ address, send }. With a sender, the SDK builds the transaction (image pinned, gas + EIP-1559 fees pre-estimated, BigInt-free tx.json for JSON transports), your infra signs and submits, the SDK waits, parses and registers. Coinbase CDP, Bankr and Safes all integrate this way — full recipes in the README.

All options

typescript
await launchpad.launchToken({
  name: 'My Token',
  symbol: 'MTK',
  image: imageBytes,            // pinned to IPFS automatically
  imagePolicy: 'pin',           // 'pin' (default) | 'as-is'

  // Fees — static tier or dynamic volatility preset
  feeMode: 'static',            // 'static' (default) | 'dynamic'
  feeTier: 1,                   // 1 | 2 | 3 | 6.9 (static only)

  // Split YOUR 75% across up to 5 wallets — FEES ONLY.
  // (bps of total fees — must sum to exactly 7500)
  creatorRewards: [
    { recipient: '0xYou',       bps: 5000, feePreference: 'both' },
    { recipient: '0xCofounder', bps: 2500, feePreference: 'paired' },
  ],

  // Vault admin, airdrop admin and dev-buy tokens. NEVER derived from
  // creatorRewards. Defaults to the launching account.
  proceedsRecipient: '0xYou',

  // Metadata-only admin. DEFAULT address(0) — born renounced.
  // tokenAdmin: '0xYou',       // scanners will flag NOT renounced

  // Anti-snipe: descending tax… or omit for the 2-block MEV delay
  sniperTax: { startingBps: 800_000, endingBps: 50_000, secondsToDecay: 15 },

  // Lock supply for yourself (lockup >= 7 days, optional vesting)
  vault: { percentage: 10, lockupSeconds: 604800, vestingSeconds: 2592000 },

  // Merkle airdrop (lockup >= 1 day); entriesCid = Pinata CID of the leaves
  airdrop: { merkleRoot: '0x…', percentage: 5, entriesCid: 'bafy…' },

  // Buy your own token at launch (not available on paired launches)
  devBuyEth: '0.05',

  // Liquidity profile — 'degen' (DEFAULT, thin) | 'classic' (deep)
  lpPreset: 'degen',
});

Paired launches

Pass pairedToken to quote the pool in an arbitrary ERC-20 instead of WETH. The split becomes 80% you / 20% treasury (no staker slice) and the launch routes through the separate dual-mode suite. Symbol and decimals are read on-chain; the WETH price resolves from the cc0.company price API unless you pass priceWeth — fail-closed, no price means no launch.

Not yet combinable with devBuyEth, creatorRewards or nftCollection. Available on Base and Robinhood Chain only.

typescript
import { isCc0PairedAvailable, PAIRED_SPLIT } from '@cc0company/sdk';
// PAIRED_SPLIT = { CREATOR_BPS: 8000, TREASURY_BPS: 2000 }

if (!isCc0PairedAvailable('robinhood')) throw new Error('no paired suite here');

const launchpad = new Cc0Launchpad({ walletClient, chain: 'robinhood' });
await launchpad.launchToken({
  name: 'My Token',
  symbol: 'MTK',
  image: imageBytes,
  pairedToken: { address: '0x…' }, // e.g. an official Robinhood stock token
});

Community Coins — fees to NFT holders

nftCollection routes the whole creator slice to the holders of an ERC-721 collection. The SDK deploys a per-token Cc0NftFeeDistributor (an extra transaction through your signer), wires it as the sole creator recipient with fee preference both, and freezes it there. The collection must be on the same chain as the token — the distributor calls ownerOf locally.

typescript
await launchpad.launchToken({
  name: 'Community Coin',
  symbol: 'CC',
  image: imageBytes,
  nftCollection: {
    address: '0x…',              // ERC-721, sequential ids, same chain
    maxEligibleTokenId: 9999n,   // eligibility ceiling at launch
  },
});

// On the manual prepareLaunchTransaction() path the SDK can't auto-deploy —
// deploy it yourself and pass the address as a creatorRewards recipient:
const distributor = await launchpad.deployNftDistributor('0x…', 9999n);

The enforced split

Every launch carries the protocol split — validated by the factory onchain, not by this SDK:

  • Standard (WETH pool) — 75% creator / 15% stakers / 10% treasury.
  • Paired (any ERC-20 pool) — 80% creator / 20% treasury.
  • A config that drops or resizes the protocol slices reverts with Cc0InvalidProtocolSplit, even on a raw factory call.
typescript
import { PROTOCOL_SPLIT, PAIRED_SPLIT } from '@cc0company/sdk';
// PROTOCOL_SPLIT = { CREATOR_BPS: 7500, STAKING_BPS: 1500, TREASURY_BPS: 1000 }
// PAIRED_SPLIT   = { CREATOR_BPS: 8000, TREASURY_BPS: 2000 }

// Live protocol addresses, read from the factory:
const { staking, treasury, admin } = await launchpad.getProtocolAddresses();

Claim fees

Cc0Fees reads and claims on whichever chain you point it at. It resolves the pool's paired asset from the launch registry automatically, so a paired launch claims three assets, a standard one claims two. Claims are permissionless: the configured signer pays gas, the funds go to feeOwner.

typescript
import { Cc0Fees } from '@cc0company/sdk';

const fees = new Cc0Fees({ walletClient, chain: 'ethereum' });
const claimable = await fees.getClaimableFees(feeOwner, token);
await fees.claimFees(feeOwner, token);

Stake

Staking is a single pool on Base. Ethereum's 15% arrives through a forwarder and Robinhood's through an escrow, so a Base staker earns from launches on all three chains. Rewards are paid in WETH; unstaking is a two-step unbonding with a 48-hour cooldown.

typescript
import { Cc0Staking } from '@cc0company/sdk';
import { parseEther } from 'viem';

const staking = new Cc0Staking({ walletClient });
await staking.stake(parseEther('1000'));   // auto-approves if needed
const pos = await staking.getPosition(me); // staked / earned / unbonding
await staking.claimRewards();              // WETH to your wallet

Gas-sponsored launches

launchTokenSponsored() and sponsorshipStatus() hit endpoints that send no CORS headers. They work server-side, from an agent, or from the cc0.company origin itself — a browser on a third-party domain is blocked and sponsorshipStatus() will read as inactive. Browser integrators on other domains must use the self-signed launchToken() path.

Your token on cc0.company — automatic

Every SDK launch is registered automatically: your token gets its page at cc0.company/token/{address} (live chart, swap, one-tap fee claim) and shows up in browse + search. The result's registered flag tells you it worked — a registry hiccup never fails the onchain launch. Opt out with register: false.

Integrating at the raw contract level without the SDK? Register your launch with the same call the SDK makes (this route sends CORS headers, so it works from any origin):

bash
POST https://cc0.company/api/store/token-launches
{
  "token_address": "0x…",
  "chain": "robinhood",          // "base" | "ethereum" | "robinhood"
  "tx_hash": "0x…",
  "protocol": "cc0strategy",
  "name": "My Token",
  "symbol": "MTK",
  "image_url": "ipfs://…",
  "creator_wallet": "0x…",
  "split_type": "paired",        // "standard" | "paired"
  "paired_token": "0x…",         // paired launches only
  "paired_symbol": "AAPL",
  "paired_decimals": 18
}

Contracts

Standard suite

ChainFactoryFee locker
Base0xf9007657b627c5421d6eBD5D71F86CDfCdc7dA8D0xC04bdF721FA5CEc839819864FA86F3D48B89Fcee
Ethereum0x70baFfe8783396142385Ece53f2cDF8D1cf9872C0x0De94068195C5d85e31406804357F44E0D20E255
Robinhood0x79F331d3d7977062d5c78Ad122851fC57Ee3DC1a0x343d77D94A119D5cEA495aeE8336A3a7Aa5CD385

Paired suite

ChainFactory
Base0x6097FD2e8773cA8ED342aA8d9a999e05397e2705
Robinhood0x65D667870E7B5b4b7113e5BaB255efE052cf3B36

Staking (Base)

  • Staking pool: 0x38cE743b88c54eD1aF84816Ff596E518d16DFF95
  • $cc0company: 0x67c5F00491c09cbCF6359f95690574E6106bb3CF

Full list with explorer links on Smart Contracts. Public agent skills — ready-to-paste recipes for launches, drops and x402 — live at github.com/cryptomfer/cc0company.