Developers
Create tokens on Livo programmatically
Overview
Token creation on Livo is a two-step process: call a Livo factory contract on-chain to deploy the token, then submit metadata (name, image, socials) to the Livo API keyed by the transaction hash.
Step 1: Authenticate
All API calls require a JWT Bearer token. Obtain one by signing a message with your wallet. Tokens expire after 7 days.
POST /api/auth/wallet
Content-Type: application/json
{
"address": "0xYourWalletAddress",
"signature": "<signature>",
"message": "Sign in to Livo\nTimestamp: <unix_ms>"
}
// Response:
{ "token": "eyJhbGci..." }The message must contain Timestamp: <unix_ms> where the timestamp is within the last 5 minutes.
Step 2: Call the Factory Contract
Token creation goes through one of three factory contracts depending on configuration:
if (buyTax > 0 || sellTax > 0):
use factoryTaxV4 (LivoFactoryTaxToken)
else if (creatorLPFeeShare):
use factoryV4 (LivoFactoryBase)
else:
use factoryV2 (LivoFactoryBase)Contract addresses are maintained in the contracts repo. All contracts are verified on Etherscan — fetch ABIs from there.
Function Signatures
createToken (no tax)
function createToken(
string name,
string symbol,
address feeReceiver, // usually msg.sender
bytes32 salt // vanity salt (address must end in 1110)
) returns (address token)createToken (with tax)
function createToken(
string name,
string symbol,
address feeReceiver,
bytes32 salt,
uint16 buyTaxBps, // max 500 (5%)
uint16 sellTaxBps, // max 500 (5%)
uint32 taxDurationSeconds // max 1209600 (14 days)
) returns (address token)createTokenWithFeeSplit (multiple fee recipients)
function createTokenWithFeeSplit(
string name,
string symbol,
address[] recipients,
uint256[] sharesBps, // must sum to 10000
bytes32 salt
) returns (address token, address feeSplitter)Vanity Salt
The factory uses CREATE2. Livo requires the deployed token address to end in 1110. You must brute-force a salt that produces a matching address.
import { keccak256, concat, toBytes } from "viem";
const PROXY_PREFIX = "0x3d602d80600a3d3981f3363d3d373d3d3d363d73";
const PROXY_SUFFIX = "0x5af43d82803e903d91602b57fd5bf3";
function findVanitySalt(factoryAddress, tokenImplementation) {
const initcodeHash = keccak256(
concat([PROXY_PREFIX, tokenImplementation, PROXY_SUFFIX])
);
const buffer = new Uint8Array(85);
buffer[0] = 0xff;
buffer.set(toBytes(factoryAddress), 1);
buffer.set(toBytes(initcodeHash), 53);
const salt = crypto.getRandomValues(new Uint8Array(32));
for (;;) {
buffer.set(salt, 21);
const hash = keccak256(buffer);
if (hash.endsWith("1110")) {
const saltHex = "0x" + Array.from(salt,
(b) => b.toString(16).padStart(2, "0")).join("");
return { salt: saltHex, tokenAddress: "0x" + hash.slice(26) };
}
for (let i = 31; i >= 0; i--) {
if (salt[i] < 255) { salt[i]++; break; }
salt[i] = 0;
}
}
}Step 3: Submit Metadata
After broadcasting the transaction and obtaining the txHash, submit token metadata via multipart form data.
POST /api/tokens/create
Authorization: Bearer <jwt_token>
Content-Type: multipart/form-datatxHashrequirednamerequiredsymbolrequiredchainIdrequireddescriptiontelegramtwitterwebsiteimageResponse:
{
"success": true,
"txHash": "0x...",
"imageUrl": "https://..."
}Validation Rules
namesymbolbuyTaxBpssellTaxBpstaxDurationSecondsfeeSplitSharesKey Events
After token creation, the factory emits:
event TokenCreated(
address indexed token,
string name,
string symbol,
address tokenOwner,
address launchpad,
address graduator,
address feeHandler,
address feeReceiver
)The launchpad emits:
event TokenLaunched(
address indexed token,
uint256 graduationThreshold,
uint256 maxExcessOverThreshold
)Parse the TokenLaunched event from the transaction receipt to get the created token address.
Notes
- Token creation is free (no ETH cost beyond gas).
- Tokens start on a bonding curve. Once ~3.5 ETH is collected, the token automatically graduates to Uniswap.
- The image field should be a raw file upload (not a URL). The API uploads it to IPFS via Pinata.