🌳
Bonsai Docs
  • Introduction
    • Bonsai
    • What is Smart Media?
  • Platform
    • No-code creator studio
    • Guide: Create a post
  • Smart Media
    • Framework for builders
  • Building Smart Media
    • ElizaOS server setup
    • Bonsai Client
    • Templates
  • Guide: Create a Template
  • Client Integrations
    • Showing whether a post is Smart Media
    • Linking to Bonsai for remixes
  • Actions
    • Reward Swap
  • Launchpad
    • Overview
    • Getting Started
    • Launchpad Contract
    • Vesting ERC20 Contract
    • Hooks
    • API
      • Tokens
      • Token Balances
      • Buy / Sell Quotes
      • Link your token to a Lens Post & Account
  • ElizaOS
    • plugin-bonsai-launchpad
    • client-lens
Powered by GitBook
On this page
  • Full Typescript Example
  • Guide
  • Whitelist module
  • Linking your token for display on the Bonsai app
  • Interact with the Launchpad contract using AI (on Nebula)
  1. Launchpad

Getting Started

Create a token on the Lens Chain Launchpad

PreviousOverviewNextLaunchpad Contract

Last updated 16 hours ago

Full Typescript Example

Here's how to integrate directly with the Lens Chain Launchpad contract to create a new token using wagmi/viem. You can copy the full abi for the contract from the .

import { chains } from "@lens-chain/sdk/viem";
import { parseEther } from "viem";

const BonsaiLaunchpadAddress = "0xaB7311a413a39C4F640D152Eec00f70eD3889066";
const BonsaiLaunchpadAbi= { ... }
// wrapped GHO on Lens Chain mainnet
const WGHO_CONTRACT_ADDRESS = "0x6bDc36E20D267Ff0dd6097799f82e78907105e2F";

// NOTE: initialPrice values assume 18 decimals in quote token (WGHO)
const FLAT_THRESHOLD = parseEther("200000000")
const LENS_PRICING_TIERS = {
  // 1 WGHO liquidity to graduate
  [PricingTier.TEST]: {
    initialPrice: "588251339500000000000000000",
    flatThreshold: FLAT_THRESHOLD.toString(),
    targetPriceMultiplier: 5,
  },
  // 6000 WGHO liquidity to graduate
  [PricingTier.SMALL]: {
    initialPrice: "3529508034062500000000000000000",
    flatThreshold: FLAT_THRESHOLD.toString(),
    targetPriceMultiplier: 5,
  },
  // 11,000 WGHO liquidity to graduate
  [PricingTier.MEDIUM]: {
    initialPrice: "6471118034062500000000000000000",
    flatThreshold: FLAT_THRESHOLD.toString(),
    targetPriceMultiplier: 5,
  },
  // 21,000 WGHO liquidity to graduate
  [PricingTier.LARGE]: {
    initialPrice: "12384118034062500000000000000000",
    flatThreshold: FLAT_THRESHOLD.toString(),
    targetPriceMultiplier: 5,
  }
};

type RegistrationTxParams = {
  hook: `0x${string}`;
  tokenName: string;
  tokenSymbol: string;
  tokenImage: string;
  initialSupply: string;
  cliffPercent: number; // bps
  vestingDuration: number; // seconds
  pricingTier?: PricingTier;
};  

export const registerClubTransaction = async (
  walletClient, // wagmi wallet client
  params: RegistrationTxParams
): Promise<{ clubId?: string, txHash?: string, tokenAddress?: string }> => {
  const token = encodeAbi(["string", "string", "string"], [params.tokenName, params.tokenSymbol, params.tokenImage]);
  let args = [
    params.hook,
    token,
    params.initialSupply,
    zeroAddress,
    params.cliffPercent,
    params.vestingDuration,
    LENS_PRICING_TIERS[params.pricingTier].initialPrice,
    LENS_PRICING_TIERS[params.pricingTier].flatThreshold,
    LENS_PRICING_TIERS[params.pricingTier].targetPriceMultiplier,
    zeroAddress, // optional whitelist module
    "0x", // optional whitelist data
    WGHO_CONTRACT_ADDRESS, // quote token
  ];
    
  const hash = await walletClient.writeContract({
    address: BonsaiLaunchpadAddress,
    abi: BonsaiLaunchpadAbi,
    functionName: "registerClub",
    args,
    chain: chains.mainnet // Lens Chain mainnet
  });
  console.log(`tx: ${hash}`);

  const receipt: TransactionReceipt = await publicClient(chain).waitForTransactionReceipt({ hash });
  const event = getEventFromReceipt({
    contractAddress: BonsaiLaunchpadAddress,
    transactionReceipt: receipt,
    abi: BonsaiLaunchpadAbi,
    eventName: "RegisteredClub",
  });
  const res = {
    clubId: event.args.clubId.toString(),
    tokenAddress: event.args.tokenAddress.toString() as `0x${string}`,
    txHash: hash
  };

  return receipt.status === "success" ? res : {};
};

Guide

Let's walk through the registration params used here:

  • hook : Uniswap v4 hook contract address. Since there is currently no v4 deployment on Lens Chain yet this can be the zero address

  • tokenName : the name of the token, e.g. "Pepe"

  • tokenSymbol: the token symbol, e.g. "PEPE"

  • tokenImage : an image url for the token

  • initialSupply : the initial amount for the tx sender to buy. Can be up to 80 million tokens (10% of buyable supply). If the value is greater than 0 you will need to approve the contract to spend these tokens first

  • cliffPercent : the percent of tokens that will be transferrable on graduation in basis points, e.g. 5000 for 50%

  • vestingDuration : the number of seconds for remaining token balances to vest linearly over after graduation, e.g. 3600 for 1 hour

  • pricingTier : The pricing parameters for the Launchpad. This determines the starting price for the token in Wrapped GHO, the number of tokens that will be sold at a flat price before the bonding curve kicks in and the ending price as a multiplier of the starting price. The tiers listed in the code above are the tiers used in the Bonsai app but you can use any values you want.

Whitelist module

You can include a whitelist module to only allow addresses that fulfill some requirement to be able to buy on the Launchpad. This is purely optional, the above example does not include a module.

The whitelist module interface is defined as such:

interface IWhitelistModule {
    function createWhitelist(uint256 clubId, bytes calldata data) external;
    function isWhitelisted(address user, uint256 clubId) external view returns (bool);
}

For example you could create a collect whitelist module that requires buyers to collect a certain post before they can buy the token:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import {IWhitelistModule} from "../interfaces/IWhitelistModule.sol";

contract CollectWhitelistModule is IWhitelistModule {
    event WhitelistCreated(uint256 indexed clubId, address indexed collectContract, uint256 expiresAt);

    struct Whitelist {
        address collectContract; // contract address of the collect
        uint256 expiresAt; // timestamp when the whitelist expires and becomes open to all
    }

    mapping(uint256 => Whitelist) public whitelists;

    function createWhitelist(uint256 clubId, bytes calldata data) external {
        (address collectContract, uint256 timePeriod) = abi.decode(data, (address, uint256));
        uint256 expiresAt = block.timestamp + timePeriod;
        whitelists[clubId] = Whitelist(collectContract, expiresAt);
        emit WhitelistCreated(clubId, collectContract, expiresAt);
    }

    function isWhitelisted(address user, uint256 clubId) external view returns (bool) {
        Whitelist storage whitelist = whitelists[clubId];
        if (whitelist.collectContract == address(0) || whitelist.expiresAt == 0) return false;
        if (block.timestamp > whitelist.expiresAt || IERC721(whitelist.collectContract).balanceOf(user) > 0) {
            return true;
        }
        return false;
    }
}

Linking your token for display on the Bonsai app

If you want to link your token to a Lens post & account, follow the guide here:

Interact with the Launchpad contract using AI (on Nebula)

bottom of this page
Link your token to a Lens Post & Account
https://thirdweb.com/lens/0xaB7311a413a39C4F640D152Eec00f70eD3889066thirdweb.com
Check transactions, events, and ask questions using natural language