Skip to content

Launchpad write calls

Launch, quote, buy, sell, and collect fees from JavaScript.

Launchpad writes cover token creation, router swaps, ERC-20 approval, and LP fee collection. Every example assumes the wallet signer is connected to chain ID 4663.

Launch a token

import {
  Contract,
  ZeroAddress,
  hexlify,
  parseEther,
  randomBytes,
} from "ethers";
import { addresses, signer } from "./spawn";

const factory = new Contract(addresses.launchFactory, [
  "event ERC20TokenCreated(address indexed tokenAddress)",
  "function initialBuyAmount() view returns (uint256)",
  "function launchToken((string name,string symbol,string logo,string description,(string website,string x,string telegram,string discord,string other) socials,address feeRecipient,address referrer) token,uint256 split,uint256 uniV3ParameterSetId,bytes32 salt) payable returns (uint256 tokensReceived)",
], signer);

const initialBuy = parseEther("0.01");
const minimum = await factory.initialBuyAmount();
if (initialBuy < minimum) throw new Error("Initial buy is too small.");

const tokenConfig = {
  name: "Example Token",
  symbol: "EXAMPLE",
  logo: "https://example.com/token.png",
  description: "Example integration launch",
  socials: {
    website: "https://example.com",
    x: "",
    telegram: "",
    discord: "",
    other: "",
  },
  feeRecipient: await signer.getAddress(),
  referrer: ZeroAddress,
};

const transaction = await factory.launchToken(
  tokenConfig,
  0n,
  0n,
  hexlify(randomBytes(32)),
  { value: initialBuy },
);

const receipt = await transaction.wait();
if (!receipt) throw new Error("Launch receipt was not found.");

let tokenAddress = "";
for (const log of receipt.logs) {
  try {
    const event = factory.interface.parseLog(log);
    if (event?.name === "ERC20TokenCreated") {
      tokenAddress = event.args.tokenAddress;
      break;
    }
  } catch {}
}
if (!tokenAddress) throw new Error("Token creation event was not found.");

The current app uses split 0, parameter set 0, and a random salt. It replaces ZeroAddress with the wallet's permanent referral attribution when one exists. Read the launch form behavior and factory state before choosing different values.

Quote and buy

const router = new Contract(addresses.launchRouter, [
  "function quoteBuy(address token,uint256 ethAmount) returns (uint256 tokensOut,uint256 fee)",
  "function robinBuy(address token,uint256 amountIn,uint256 minTokensOut) payable returns (uint256 tokensOut)",
], signer);

const amountIn = parseEther("0.02");
const [quotedTokens, routerFee] = await router.quoteBuy.staticCall(
  tokenAddress,
  amountIn,
);

const minTokensOut = quotedTokens * 9_900n / 10_000n; // 1% tolerance
const buy = await router.robinBuy(tokenAddress, amountIn, minTokensOut, {
  value: amountIn,
});
await buy.wait();

console.log({ quotedTokens, routerFee });

Refresh the quote after a delayed signature prompt. Choose the tolerance based on the application's user controls and market conditions.

Approve and sell

const amountToSell = parseEther("1000");
const erc20 = new Contract(tokenAddress, [
  "function allowance(address owner,address spender) view returns (uint256)",
  "function approve(address spender,uint256 amount) returns (bool)",
], signer);

const account = await signer.getAddress();
const allowance = await erc20.allowance(account, addresses.launchRouter);
if (allowance < amountToSell) {
  const approval = await erc20.approve(addresses.launchRouter, amountToSell);
  await approval.wait();
}

const sellRouter = new Contract(addresses.launchRouter, [
  "function quoteSell(address token,uint256 tokenAmount) returns (uint256 ethOut,uint256 fee)",
  "function robinSell(address token,uint256 tokenAmount,uint256 minEthOut) returns (uint256 ethOut)",
], signer);

const [quotedEth] = await sellRouter.quoteSell.staticCall(tokenAddress, amountToSell);
const minEthOut = quotedEth * 9_900n / 10_000n;
const sale = await sellRouter.robinSell(tokenAddress, amountToSell, minEthOut);
await sale.wait();

Collect LP fees

const feeFactory = new Contract(addresses.launchFactory, [
  "function tokenToNFTId(address token) view returns (uint256)",
  "function collectFees(uint256 tokenId) returns (uint256 amount0,uint256 amount1)",
], signer);

const positionId = await feeFactory.tokenToNFTId(tokenAddress);
const [tokenFees, wethFees] = await feeFactory.collectFees.staticCall(positionId);
const collection = await feeFactory.collectFees(positionId);
await collection.wait();