Examples

Full Token Creation Flow

Complete example: authenticate → read the creation fee → create the token on-chain (the exact fee as msg.value; the presale is a count of whole tokens) → read the token address from the TokenCreated event → sync the transaction → upload the image → create the metadata. Another main, a supply multiplier or holder rewards are fields of createTokenFor; a meme+ token uses createReversedTokenFor.

End-to-End Example
// Full token creation flow: read the fee → create on-chain → sync → upload image → create metadata
import { ethers } from "ethers";

async function createToken(sessionCookie) {
  const provider = new ethers.JsonRpcProvider("<RPC URL of the network in /contracts.json>");
  const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);

  // 1. Create the token on-chain via the Factory contract
  const factory = new ethers.Contract(FACTORY_ADDRESS, FACTORY_ABI, wallet);
  const fee = (await factory.feeWhitelist(wallet.address)) ? 0n : await factory.feeAmount();   // exact, in the native coin
  // createTokenFor picks the main, supplyMultiplier and rewards. A meme+ token: createReversedTokenFor(params).
  const tx = await factory.createTokenFor({
    mainToken: MAIN_ADDRESS,      // a main from GET /contracts.json -> mains[]
    symbol: "SYM", name: "My Token",
    hybridMultiplier: 50,         // 1..100
    frozen: false,
    presaleTokens: 0,             // WHOLE tokens sold in the presale (0 = none). Not USD, not wei.
    startLP: 10000,               // basis points of the main's seed depth: 1000..100000 (10%..1000% of the main's seed)
    supplyMultiplier: 1,
    rewardsEnabled: true,         // permanent
    autoVest: false, autoVestDuration: 0, gradualAutovest: false,
  }, { value: fee });
  const receipt = await tx.wait();
  await fetch("https://launchonbasis.com/api/v1/sync", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ txHash: tx.hash }) });
  const created = receipt.logs.map(l => { try { return factory.interface.parseLog(l); } catch { return null; } })
    .find(e => e && e.name === "TokenCreated");
  const tokenAddress = created.args.tokenAddress;

  // 2. Upload image (purpose: "token" + address required)
  const imageFile = new File([imageBuffer], `${tokenAddress}.webp`, { type: "image/webp" });
  const formData = new FormData();
  formData.append("file", imageFile);
  formData.append("purpose", "token");
  formData.append("address", tokenAddress);

  const imgRes = await fetch("https://launchonbasis.com/api/images", {
    method: "POST",
    headers: { "Cookie": sessionCookie },
    body: formData,
  });
  const { url: imageUrl } = await imgRes.json();

  // 3. Create metadata (server verifies you are the on-chain DEV)
  await fetch("https://launchonbasis.com/api/metadata", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Cookie": sessionCookie,
    },
    body: JSON.stringify({
      address: tokenAddress,
      description: "Created via the API",
      image: imageUrl,
    }),
  });

  return tokenAddress;
}