four-flap-meme-sdk
Version:
SDK for Flap bonding curve and four.meme TokenManager
1,801 lines (1,359 loc) β’ 99.8 kB
Markdown
# four-flap-meme-sdk English Docs
A two-in-one SDK for **four.meme** (TokenManager V1/V2/Helper3) and **Flap Protocol** (Portal/CDPV2). This comprehensive guide is designed for **complete beginners** β no prior experience with these platforms required. We'll explain every concept, method, and parameter in detail.
## Why This SDK?
This SDK helps you:
- **Launch tokens** on four.meme or Flap Protocol with just a few lines of code
- **Trade tokens** using bonding curves (buy/sell before DEX listing)
- **Query token state** and estimate prices
- **Understand two DeFi platforms** that revolutionize token launches
## Runtime Requirements
- **Node.js**: Version 18 or higher (uses native fetch API)
- **Module Type**: ESM (NodeNext)
- **Dependencies**:
- `ethers@^6` - For Ethereum interactions
## Installation
```bash
npm i four-flap-meme-sdk ethers
```
Optional (use Pinata for IPFS uploads)
```bash
npm i pinata
```
---
## Table of Contents
### π Platform Overview
- [What is four.meme?](#what-is-fourmeme)
- [What is Flap Protocol?](#what-is-flap-protocol)
- [Understanding Bonding Curves](#understanding-bonding-curves)
- [Internal Market vs External Market](#internal-market-vs-external-market)
### π― four.meme
- [Platform Architecture](#fourmeme-architecture)
- [Token Launch Process](#token-launch-process)
- [One-click Launch (Easiest)](#one-click-token-launch)
- [Step-by-Step Launch (Advanced)](#step-by-step-launch)
- [Trading Tokens](#trading-on-fourmeme)
- [Estimating Prices](#price-estimation)
- [Buying Tokens](#buying-tokens)
- [Selling Tokens](#selling-tokens)
- [Auto-Routing (V1/V2)](#auto-routing)
- [Error Handling](#error-handling)
- [MPC-Exclusive Tokens](#mpc-exclusive-tokens)
- [Complete API Reference](#fourmeme-api-reference)
### π Flap Protocol
- [Platform Architecture](#flap-architecture)
- [Reading Token State](#reading-token-state)
- [CDPV2 Bonding Curve](#cdpv2-bonding-curve)
- [Price Quotes](#flap-price-quotes)
- [Token Swapping](#token-swapping)
- [Creating Tokens](#creating-tokens-on-flap)
- [Vanity Addresses](#vanity-addresses)
- [Uploading Token Metadata](#uploading-token-metadata)
- [Error Handling](#flap-error-handling)
- [Constants](#flap-constants)
- [Complete API Reference](#flap-api-reference)
### π 48.club Private Transactions
- [What is 48.club?](#what-is-48club)
- [Private Transaction Benefits](#private-transaction-benefits)
- [Four.meme Private Trading](#fourmeme-private-trading)
- [Flap Protocol Private Trading](#flap-protocol-private-trading)
- [48SP Modes & Configuration](#48sp-modes--configuration)
- [Low-Level 48.club API](#low-level-48club-api)
### π Appendix
- [Constants & Addresses](#constants-and-addresses)
- [BigInt & Units](#bigint-and-units)
- [Common Patterns](#common-patterns)
- [FAQ](#frequently-asked-questions)
---
# Platform Overview
## What is four.meme?
**four.meme** is a token launchpad that uses a **bonding curve** mechanism for price discovery before listing on decentralized exchanges (DEX).
### Key Concepts:
1. **Bonding Curve Phase**:
- When a token is first created, it's NOT on a DEX
- Instead, prices are determined by a mathematical formula (bonding curve)
- As more people buy, the price automatically increases
- As people sell, the price automatically decreases
2. **Migration to DEX**:
- Once enough funds are raised (reaches threshold), the token "graduates"
- It gets listed on PancakeSwap (for BSC) with a liquidity pool
- After this, it trades like a normal DEX token
3. **Versions**:
- **V1 (TokenManager)**: Original version, still in use
- **V2 (TokenManager2)**: Improved version with more features
- **Helper3**: A utility contract that helps estimate prices and route trades
### Why Use four.meme?
- **Fair Launch**: Everyone buys at the same bonding curve price
- **No Rug Pulls**: Liquidity is automatically added to DEX
- **Early Access**: Buy before DEX listing at potentially lower prices
---
## What is Flap Protocol?
**Flap Protocol** is another token launch platform with advanced bonding curve features (CDPV2 curve).
### Key Features:
1. **Advanced Bonding Curve (CDPV2)**:
- More flexible curve parameters: `r`, `h`, `k`
- Better price discovery
- Customizable migration thresholds
2. **Multi-Chain Support**:
- BSC (BNB Chain)
- Base
- X Layer
- Morph
3. **Quote Token Options**:
- Can launch with native tokens (BNB, ETH)
- Can launch with quote tokens (USDT, etc.)
4. **Tax & Migrator Options**:
- Set custom tax rates
- Choose V2 or V3 migrators for DEX
---
## Understanding Bonding Curves
### What is a Bonding Curve?
A **bonding curve** is a mathematical formula that determines token price based on supply.
#### Simple Example:
Imagine a token with this rule:
- First 1000 tokens: $0.01 each
- Next 1000 tokens: $0.02 each
- Next 1000 tokens: $0.03 each
- And so on...
**Bonding curves** do this smoothly with a formula instead of steps.
### The Formula (CDPV2):
```
price = k / (1,000,000,000 + h - supply)Β²
```
Where:
- `k`: A constant that affects overall price level
- `h`: Height adjustment (shifts the curve)
- `supply`: Current circulating supply
### Why It Matters:
- **Early buyers**: Get lower prices
- **Price increases**: Automatically as supply grows
- **Predictable**: Anyone can calculate the price
- **No manipulation**: Can't be front-run like DEX orders
---
## Internal Market vs External Market
In token launch platforms, there are two important trading phase concepts:
### π΅ Internal Market (Bonding Curve Phase)
**Definition**: The phase where tokens trade on the bonding curve before migrating to a DEX.
**Characteristics**:
- β
**Formula-based pricing**: Uses mathematical curves (like CDPV2) to calculate prices
- β
**Locked liquidity**: All funds locked in the platform contract
- β
**Rug-pull prevention**: Developers cannot withdraw liquidity
- β
**Fair price discovery**: Everyone buys/sells at the same curve price
- β
**Instant settlement**: No order book or counterparty needed
- β
**Predictability**: Can precisely calculate buy/sell prices
**On four.meme and Flap Protocol**:
- Tokens start in the internal market phase when created
- Trade using `FourClient` or `FlapPortalWriter`
- Prices adjust automatically with buys/sells
- Example: `status = 1` (tradable state)
**Internal Market Trading Example**:
```typescript
// Buy tokens on the internal market (bonding curve)
const txHash = await writer.swapExactInput({
inputToken: ZERO_ADDRESS,
outputToken: tokenAddress,
inputAmount: parseEther('1.0'),
minOutputAmount: minAmount,
to: yourAddress
});
```
### π’ External Market (DEX Phase)
**Definition**: The phase where tokens have "graduated" and migrated to a decentralized exchange (DEX).
**Characteristics**:
- β
**Market pricing**: Price determined by supply/demand, no longer using curves
- β
**DEX liquidity pools**: Trade on PancakeSwap, Uniswap, etc.
- β
**Free trading**: Can trade on any supported DEX and aggregator
- β
**Deeper liquidity**: Usually deeper liquidity with lower slippage
- β
**Standard ERC20**: Trades like any normal token
**Migration Conditions**:
- four.meme: When raised funds reach a specific threshold (e.g., 24 BNB)
- Flap Protocol: When reserve reaches `dexThresh` (configurable)
**After Migration**:
- Platform contract automatically adds liquidity to DEX
- Bonding curve closes, can no longer trade through platform
- Token status becomes `status = 4` (migrated to DEX)
**External Market Trading Example**:
```typescript
// Token has migrated to DEX, use DEX router for trading
// For example, using Uniswap SDK or PancakeSwap SDK
import { SwapRouter } from '@uniswap/v3-sdk';
// ... use standard DEX trading methods
```
### π Internal Market vs External Market Comparison
| Feature | Internal Market (Bonding Curve) | External Market (DEX) |
|---------|----------------------------------|----------------------|
| **Pricing Mechanism** | Mathematical formula (bonding curve) | Market supply/demand |
| **Liquidity Source** | Platform contract | DEX liquidity pool |
| **Trading Method** | Through platform contract | Through DEX (PancakeSwap/Uniswap) |
| **Price Predictability** | High (can calculate precisely) | Low (market volatility) |
| **Slippage** | Depends on curve parameters | Depends on liquidity depth |
| **Phase** | Early stage | Mature stage |
| **SDK Usage** | `FourClient` / `FlapPortalWriter` | DEX SDK (Uniswap/PancakeSwap) |
| **Token Status** | `status = 1` | `status = 4` |
### π Migration Process from Internal to External Market
1. **Internal Market Phase**: Token trades on bonding curve
2. **Threshold Reached**: Reserve reaches migration threshold
3. **Automatic Migration**: Platform contract automatically triggers migration
4. **Add Liquidity**: Adds reserve and tokens to DEX
5. **External Market Phase**: Token freely trades on DEX
**How to Check Which Phase a Token is In?**
```typescript
import { FlapPortal } from 'four-flap-meme-sdk';
const portal = new FlapPortal({ chain: 'BSC', rpcUrl });
const state = await portal.getTokenV5(tokenAddress);
if (state.status === 1) {
console.log('β
Internal Market: Token trading on bonding curve');
console.log('Reserve:', state.reserve);
console.log('Migration threshold:', state.dexSupplyThresh);
} else if (state.status === 4) {
console.log('β
External Market: Token has migrated to DEX');
console.log('Please trade on PancakeSwap/Uniswap');
}
```
**Important Notes**:
- β οΈ After token migrates to DEX, cannot trade through platform contract anymore
- β οΈ Migration is one-way and irreversible
- β οΈ After migration, must use DEX trading tools (like PancakeSwap, Uniswap)
---
# π Inspect token LP (auto-detect in-house vs DEX)
Use `inspectTokenLP(token, opts)` to detect whether a token is traded on four (bonding curve), Flap (bonding curve), or Pancake V2/V3 (DEX). For DEX, it returns WBNB/USDT pairs and reserves; for inβhouse platforms, it returns curve reserves/supply so the UI can display pool-like info.
Minimal usage (BSC)
```typescript
import { inspectTokenLP } from 'four-flap-meme-sdk';
const info = await inspectTokenLP('0xToken', {
chain: 'BSC',
rpcUrl: 'https://bsc-dataseed.binance.org',
flapChain: 'BSC'
});
console.log(info);
```
Optionally resolve factories via Routers
```typescript
const info = await inspectTokenLP('0xToken', {
chain: 'BSC',
rpcUrl,
routerV2: '0x10ED43C718714eb63d5aA57B78B54704E256024E', // Pancake V2 Router
routerV3: '0x13f4EA83D0bd40E75C8222255bc855a974568Dd4', // Pancake V3 Router
// or pass factoryV2/factoryV3 directly
});
```
Return examples
```typescript
// four (in-house)
{ platform: 'FOUR', four: { helper: '0x...', reserveNative: '123456...', offerTokens: '7890...', lastPrice: '1234...' } }
// flap (in-house)
{ platform: 'FLAP', flap: { quoteToken: '0x...', reserveNative: '...', circulatingSupply: '...', price: '...' } }
// Pancake V2
{ platform: 'PANCAKE_V2', v2: {
wbnbPair: { address: '0x...', reserveToken: '...', reserveWBNB: '...' },
usdtPair: { address: '0x...', reserveToken: '...', reserveUSDT: '...' }
}}
// Pancake V3 (multiple fee tiers)
{ platform: 'PANCAKE_V3', v3: [
{ base: 'WBNB', fee: 500, pool: '0x...', tokenBalance: '...', baseBalance: '...' },
{ base: 'USDT', fee: 2500, pool: '0x...', tokenBalance: '...', baseBalance: '...' }
]}
```
# four.meme Platform Guide
## four.meme Architecture
four.meme has **three main components**:
### 1. **REST API** (Backend)
- User authentication (nonce + signature)
- Image upload for token icons
- Token metadata management
- Create parameter generation
### 2. **Smart Contracts** (On-Chain)
- **TokenManagerV1**: Original token manager
- **TokenManagerV2**: Improved token manager with more features
- **TokenManagerHelper3**: Helper contract for price estimation and routing
### 3. **This SDK** (Your Interface)
- Simplifies all REST API calls
- Wraps smart contract interactions
- Provides unified interfaces for V1/V2
---
## Token Launch Process
Launching a token on four.meme involves **5 steps**:
```
1. Generate Nonce β Get a random string from server
2. Sign Message β Sign with your wallet to prove ownership
3. Login β Receive access token
4. Upload Image β Upload token logo/icon
5. Create On-Chain β Deploy the token contract
```
### Why This Process?
- **Authentication**: Proves you own the wallet
- **Security**: Access token prevents unauthorized actions
- **Metadata**: Server stores token info off-chain
- **Decentralization**: Actual token is on-chain, not controlled by server
---
## One-Click Token Launch
### The Easiest Way
Use `createTokenFlow()` to handle all 5 steps automatically:
```typescript
import { createTokenFlow } from 'four-flap-meme-sdk';
const result = await createTokenFlow({
rpcUrl: 'https://bsc-dataseed.binance.org',
privateKey: '0x...your-private-key',
networkCode: 'BSC',
// Optional: provide pre-uploaded image URL
imgUrl: 'https://...',
// OR: upload new image
image: imageBlob,
payload: {
name: 'My Awesome Token', // Full name
shortName: 'MAT', // Symbol (ticker)
desc: 'A revolutionary token', // Description
label: 'Meme', // Category
preSale: '0', // Pre-purchase amount: '0' = no buy, '0.5' = buy 0.5 BNB
onlyMPC: false, // MPC-exclusive mode (explained later)
// Optional social links
webUrl: 'https://example.com',
twitterUrl: 'https://twitter.com/...',
telegramUrl: 'https://t.me/...',
}
});
console.log('Token created!');
console.log('Transaction:', result.txReceipt.transactionHash);
console.log('Your address:', result.accountAddress);
```
### Parameter Explanations:
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `rpcUrl` | string | β
| RPC endpoint for the blockchain (BSC, Arbitrum, etc.) |
| `privateKey` | string | β
| Your wallet private key (KEEP SECRET!) |
| `networkCode` | 'BSC' | β
| Currently only BSC is supported |
| `baseUrl` | string | β | four.meme API URL (default: https://four.meme/meme-api) |
| `image` | Blob | β* | Image file to upload (*required if no imgUrl) |
| `imgUrl` | string | β* | Pre-uploaded image URL (*required if no image) |
### Payload Fields:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | β
| Token full name (e.g., "Bitcoin") |
| `shortName` | string | β
| Token symbol (e.g., "BTC") |
| `desc` | string | β
| Token description |
| `label` | string | β
| Category: 'Meme', 'AI', 'Defi', 'Games', 'Infra', 'De-Sci', 'Social', 'Depin', 'Charity', 'Others' |
| `preSale` | string | β
| BNB amount to buy when creating (pre-purchase). Examples: '0' = no buy, '0.1' = buy 0.1 BNB, '1' = buy 1 BNB |
| `onlyMPC` | boolean | β | If true, only MPC wallets can buy (anti-bot) |
| `launchTime` | number | β | Launch timestamp in milliseconds (default: now) |
| `webUrl` | string | β | Project website |
| `twitterUrl` | string | β | Twitter/X profile |
| `telegramUrl` | string | β | Telegram group/channel |
### Return Value:
```typescript
{
accountAddress: string, // Your wallet address
accessToken: string, // JWT token for future API calls
imgUrl: string, // Uploaded image URL
api: {
createArg: string, // Encoded parameters sent to contract
signature: string, // Server signature for verification
},
txReceipt: any // Transaction receipt from blockchain
}
```
---
## Step-by-Step Launch
### For Advanced Users
If you need more control, use individual methods:
### Step 1: Generate Nonce
```typescript
import { FourClient } from 'four-flap-meme-sdk';
const four = new FourClient();
const nonce = await four.generateNonce({
accountAddress: '0x...your-address',
verifyType: 'LOGIN',
networkCode: 'BSC'
});
```
**What it does**: Gets a random nonce (number used once) from server to prevent replay attacks.
### Step 2: Sign Login Message
```typescript
import { buildLoginMessage } from 'four-flap-meme-sdk';
import { Wallet } from 'ethers';
const wallet = new Wallet(privateKey);
const message = buildLoginMessage(nonce); // "You are sign in Meme {nonce}"
const signature = await wallet.signMessage(message);
```
**What it does**: Creates a signed message proving you own the wallet.
### Step 3: Login to Get Access Token
```typescript
const accessToken = await four.loginDex({
region: 'WEB',
langType: 'EN',
walletName: 'MetaMask',
verifyInfo: {
address: '0x...your-address',
networkCode: 'BSC',
signature: signature,
verifyType: 'LOGIN'
}
});
```
**What it does**: Exchanges your signature for an access token (like a session cookie).
### Step 4: Upload Image
```typescript
const imgUrl = await four.uploadImage(accessToken, imageBlob);
```
**What it does**: Uploads token logo to four.meme's CDN, returns URL.
### Step 5: Get Create Parameters
```typescript
const { createArg, signature } = await four.createToken(accessToken, {
name: 'My Token',
shortName: 'MTK',
desc: 'Description',
imgUrl: imgUrl,
launchTime: Date.now(),
label: 'Meme',
lpTradingFee: 0.0025, // Fixed at 0.25%
preSale: '0',
onlyMPC: false,
webUrl: 'https://...',
twitterUrl: 'https://...',
telegramUrl: 'https://...',
});
```
**What it does**: Server generates and signs the parameters for on-chain token creation.
### Step 6: Create Token On-Chain
```typescript
import { createTokenOnChain } from 'four-flap-meme-sdk';
const receipt = await createTokenOnChain({
chain: 'BSC',
rpcUrl: 'https://bsc-dataseed.binance.org',
signerPrivateKey: privateKey,
args: createArg,
signature: signature,
});
console.log('Token created at tx:', receipt.transactionHash);
```
**What it does**: Sends transaction to TokenManager2 contract, deploying your token.
---
## Trading on four.meme
Once a token is created, anyone can buy and sell it using the bonding curve.
### Trading Flow Overview
```
1. Estimate Price (Optional) β See how much you'll get
2. Check Approval (Sell Only) β Allow TokenManager to spend your tokens
3. Execute Trade β Buy or sell
```
---
### Price Estimation
**Before trading**, you should estimate the cost/return:
#### Estimating Buy Price
```typescript
import { tryBuy } from 'four-flap-meme-sdk';
// Option 1: Buy with specific BNB amount (funds)
const estimate = await tryBuy(
'BSC',
rpcUrl,
tokenAddress,
0n, // amount = 0 means "buy by funds"
1n * 10n ** 18n // 1 BNB
);
console.log('You will receive approximately:', estimate.estimatedAmount);
console.log('Cost:', estimate.estimatedCost);
console.log('Fee:', estimate.estimatedFee);
// Option 2: Buy specific token amount
const estimate2 = await tryBuy(
'BSC',
rpcUrl,
tokenAddress,
10_000n * 10n ** 18n, // Buy 10,000 tokens
0n // funds = 0 means "buy by amount"
);
console.log('It will cost:', estimate2.estimatedCost, 'wei');
```
**Return values explained**:
```typescript
{
tokenManager: string, // Which TokenManager contract to use (V1 or V2)
quote: string, // Quote token address (usually WBNB)
estimatedAmount: bigint, // Tokens you'll receive
estimatedCost: bigint, // Total cost in wei (including fees)
estimatedFee: bigint, // Trading fee in wei
amountMsgValue: bigint, // BNB to send as msg.value
amountApproval: bigint, // Amount to approve (if using quote token)
amountFunds: bigint // Actual funds to use in contract call
}
```
#### Estimating Sell Price
```typescript
import { trySell } from 'four-flap-meme-sdk';
const estimate = await trySell(
'BSC',
rpcUrl,
tokenAddress,
1_000n * 10n ** 18n // Sell 1,000 tokens
);
console.log('You will receive:', estimate.funds, 'wei');
console.log('Fee:', estimate.fee, 'wei');
```
**Return values**:
```typescript
{
tokenManager: string, // Which TokenManager to use
quote: string, // Quote token address
funds: bigint, // BNB you'll receive (after fees)
fee: bigint // Trading fee
}
```
---
### Buying Tokens
There are **three ways** to buy tokens:
#### Method 1: Simple Buy (Recommended)
Use `tradeBuy()` which **auto-detects** V1 or V2:
```typescript
import { tradeBuy } from 'four-flap-meme-sdk';
// Buy with specific BNB amount
await tradeBuy(
'BSC',
rpcUrl,
privateKey,
tokenAddress,
{
type: 'funds', // Buy by specifying funds
funds: 1n * 10n ** 18n, // 1 BNB
minAmount: 0n, // Minimum tokens to receive (slippage protection)
to: yourAddress // Optional: send tokens to different address
}
);
// Buy specific token amount
await tradeBuy(
'BSC',
rpcUrl,
privateKey,
tokenAddress,
{
type: 'amount', // Buy specific amount
amount: 10_000n * 10n**18n, // 10,000 tokens
maxFunds: 5n * 10n ** 18n, // Maximum BNB to spend (slippage protection)
to: yourAddress
}
);
```
**Parameters explained**:
- `type: 'funds'`: You specify how much BNB to spend
- `type: 'amount'`: You specify how many tokens to buy
- `minAmount`/`maxFunds`: Slippage protection (prevents bad trades if price changes)
- `to`: Optional recipient address (defaults to your address)
- `origin`: Optional origin code for referral tracking (default: 0n)
#### Method 2: Direct Buy (Advanced)
If you already know it's V2, use `buyTokenWithFunds()`:
```typescript
import { tryBuy, buyTokenWithFunds } from 'four-flap-meme-sdk';
// First, estimate
const estimate = await tryBuy('BSC', rpcUrl, tokenAddress, 0n, 1n * 10n ** 18n);
// Then buy
await buyTokenWithFunds(
'BSC',
rpcUrl,
privateKey,
tokenAddress,
estimate.amountFunds, // Use estimated funds
0n, // minAmount (slippage)
yourAddress // recipient
);
```
#### Method 3: Using TM1/TM2 Classes (Expert)
For maximum control:
```typescript
import { TM2 } from 'four-flap-meme-sdk';
// Use chain enum (SDK handles contract address automatically)
const tm2 = TM2.connectByChain('BSC', rpcUrl);
// Buy by amount
await tm2.buyToken(
tokenAddress,
1_000n * 10n ** 18n, // Buy 1,000 tokens
2n * 10n ** 18n // Max 2 BNB
);
// Buy by funds (AMAP = As Much As Possible)
await tm2.buyTokenAMAP(
tokenAddress,
1n * 10n ** 18n, // Spend 1 BNB
0n // Min 0 tokens (no slippage protection)
);
```
---
### Selling Tokens
Selling requires **token approval** first (letting TokenManager spend your tokens).
#### Complete Sell Flow
```typescript
import { ensureSellApproval, tradeSell } from 'four-flap-meme-sdk';
const tokenAddress = '0x...';
const amountToSell = 1_000n * 10n ** 18n; // 1,000 tokens
// Step 1: Approve TokenManager to spend your tokens
await ensureSellApproval(
'BSC',
rpcUrl,
privateKey,
tokenAddress,
yourAddress,
amountToSell
);
// Step 2: Sell
await tradeSell(
'BSC',
rpcUrl,
privateKey,
tokenAddress,
{
type: 'direct',
amount: amountToSell,
minFunds: 0n // Minimum BNB to receive
}
);
```
**Why approval?**
ERC20 tokens require **two transactions** to sell:
1. **Approve**: Give permission to TokenManager
2. **Sell**: Actually transfer and receive BNB
This is a security feature of ERC20 tokens.
#### Router Sell (For Third-Party Apps)
If you're building a router/aggregator:
```typescript
await tradeSell(
'BSC',
rpcUrl,
privateKey,
tokenAddress,
{
type: 'router',
from: userAddress, // Sell from user's wallet
amount: amountToSell,
minFunds: 0n,
feeRate: 100n, // 1% fee (in basis points: 100 = 1%)
feeRecipient: routerAddress // Where to send the fee
}
);
```
---
### Auto-Routing
**What is auto-routing?**
four.meme has two versions (V1 and V2) with **different interfaces**. The SDK provides unified methods that:
1. Detect which version a token uses
2. Call the correct contract
3. Handle parameter differences
#### Using Auto-Routing
```typescript
import { tradeBuy, tradeSell } from 'four-flap-meme-sdk';
// Works for BOTH V1 and V2 tokens
await tradeBuy('BSC', rpcUrl, privateKey, token, params);
await tradeSell('BSC', rpcUrl, privateKey, token, params);
```
**Behind the scenes**:
1. Calls `Helper3.getTokenInfo(token)`
2. Checks `version` field (1 or 2)
3. Routes to TM1 or TM2
4. Adapts parameters automatically
---
## Error Handling
Trading on four.meme can fail for various reasons. The SDK provides error code parsing:
```typescript
import { parseFourError } from 'four-flap-meme-sdk';
try {
await tradeBuy(rpcUrl, privateKey, helper3, token, params);
} catch (error) {
const { code, message } = parseFourError(error);
if (code === 'Slippage') {
console.error('Price moved too much! Try increasing slippage tolerance');
} else if (code === 'More BNB') {
console.error('Not enough BNB sent:', message);
} else {
console.error('Error:', code, message);
}
}
```
### Error Codes Reference
| Code | Description | Solution |
|------|-------------|----------|
| `GW` | Amount not aligned to GWEI | Round to GWEI (divide by 10^9) |
| `ZA` | Target address is zero address | Provide valid recipient address |
| `TO` | Cannot send to PancakePair | Don't use LP address as recipient |
| `Slippage` | Price changed too much | Increase minAmount/maxFunds tolerance |
| `More BNB` | Insufficient BNB in msg.value | Send more BNB or check estimate |
| `FR` | Fee rate > 5% | Router fee rate must be β€ 5% |
| `SO` | Order too small | Increase trade amount |
---
## MPC-Exclusive Tokens
**What is MPC-exclusive?**
Some tokens on four.meme are marked as **"MPC-only"**, meaning:
- Only **MPC wallets** (multi-party computation wallets) can buy them
- This is an **anti-bot** feature
- Regular EOA (externally owned account) wallets are blocked
### Why MPC-Exclusive?
- **Prevents bots**: Bots usually use simple EOA wallets
- **Fair launch**: Gives human users a better chance
- **Less manipulation**: Harder to snipe or front-run
### How to Detect MPC-Exclusive Tokens
#### On-Chain Detection (Recommended)
```typescript
import { isExclusiveOnChain } from 'four-flap-meme-sdk';
const isMPCOnly = await isExclusiveOnChain({
chain: 'BSC', // SDK automatically uses the correct proxy contract
tokenAddress: '0x...',
rpcUrl: rpcUrl
});
if (isMPCOnly) {
console.log('This token is MPC-exclusive!');
console.log('You need an MPC wallet to trade it');
}
```
**How it works**: Checks the token's `template` field. If `template & 0x10000 > 0`, it's MPC-only.
#### Off-Chain Detection (Using API)
```typescript
import { isExclusiveOffChain, FourClient } from 'four-flap-meme-sdk';
const four = new FourClient();
const isMPCOnly = await isExclusiveOffChain(
(addr) => four.getTokenByAddress(addr),
tokenAddress
);
```
**How it works**: Checks if `version === 'V8'` in API response.
---
## four.meme API Reference
### FourClient Class
#### Constructor
```typescript
const four = new FourClient({
baseUrl?: string // Default: 'https://four.meme/meme-api'
});
```
---
### Authentication Methods
#### generateNonce()
Gets a random nonce for login signature.
```typescript
const nonce = await four.generateNonce({
accountAddress: string, // Your wallet address
verifyType: 'LOGIN', // Fixed value
networkCode: 'BSC' // Fixed value (for now)
});
```
**Returns**: `Promise<string>` - The nonce string
---
#### buildLoginMessage()
Builds the message to sign for login.
```typescript
import { buildLoginMessage } from 'four-flap-meme-sdk';
const message = buildLoginMessage(nonce); // Returns: "You are sign in Meme {nonce}"
```
---
#### loginDex()
Exchanges signature for access token.
```typescript
const accessToken = await four.loginDex({
region: 'WEB', // Fixed value
langType: 'EN' | 'ZH', // Language preference
walletName: string, // e.g., 'MetaMask', 'WalletConnect'
verifyInfo: {
address: string, // Your wallet address
networkCode: 'BSC', // Fixed value
signature: string, // Signature from signing the nonce message
verifyType: 'LOGIN' // Fixed value
}
});
```
**Returns**: `Promise<string>` - JWT access token
---
### Token Management Methods
#### uploadImage()
Uploads token image to CDN.
```typescript
const imgUrl = await four.uploadImage(
accessToken: string, // From loginDex()
file: Blob // Image file (JPEG, PNG, etc.)
);
```
**Returns**: `Promise<string>` - Image URL
---
#### createToken()
Gets signed parameters for on-chain token creation.
```typescript
const { createArg, signature } = await four.createToken(
accessToken: string, // From loginDex()
{
name: string, // Token full name
shortName: string, // Token symbol
desc: string, // Description
imgUrl: string, // Image URL from uploadImage()
launchTime: number, // Timestamp in milliseconds
label: string, // Category (Meme, AI, etc.)
lpTradingFee: 0.0025, // Fixed at 0.25%
preSale: string, // Pre-sale amount (e.g., '0', '0.1')
onlyMPC?: boolean, // MPC-exclusive flag
webUrl?: string, // Optional website
twitterUrl?: string, // Optional Twitter
telegramUrl?: string // Optional Telegram
}
);
```
**Returns**: `Promise<{ createArg: string, signature: string }>`
---
#### getTokenByAddress()
Gets token metadata by contract address.
```typescript
const tokenInfo = await four.getTokenByAddress(
address: string, // Token contract address
accessToken?: string // Optional access token
);
```
**Returns**: Token metadata object with fields like `name`, `symbol`, `imgUrl`, `version`, etc.
---
#### getTokenById()
Gets token metadata by token ID.
```typescript
const tokenInfo = await four.getTokenById(
id: string | number, // Token ID from four.meme
accessToken?: string // Optional access token
);
```
---
#### getPublicConfig()
Gets four.meme platform configuration.
```typescript
const config = await four.getPublicConfig();
```
---
### On-Chain Methods
#### createTokenOnChain()
Deploys the token contract on-chain.
```typescript
import { createTokenOnChain } from 'four-flap-meme-sdk';
const receipt = await createTokenOnChain({
chain: 'BSC', // Chain name
rpcUrl: string, // Blockchain RPC endpoint
signerPrivateKey: string, // Your private key
args: BytesLike, // From four.createToken()
signature: BytesLike, // From four.createToken()
valueWei?: bigint // Optional BNB to send (for pre-sale)
});
```
**Returns**: Transaction receipt
---
### Trading Methods
#### tryBuy()
Estimates buy cost without executing.
```typescript
import { tryBuy } from 'four-flap-meme-sdk';
const estimate = await tryBuy(
chain: 'BSC' | 'BASE' | 'ARBITRUM_ONE', // Chain name
rpcUrl: string,
token: string, // Token address
amount: bigint, // Token amount (0 = buy by funds)
funds: bigint // BNB amount (0 = buy by amount)
);
```
**Returns**: `TryBuyResult` object with estimation details
---
#### trySell()
Estimates sell return without executing.
```typescript
import { trySell } from 'four-flap-meme-sdk';
const estimate = await trySell(
chain: 'BSC' | 'BASE' | 'ARBITRUM_ONE', // Chain name
rpcUrl: string,
token: string,
amount: bigint // Token amount to sell
);
```
**Returns**: `TrySellResult` with funds and fee
---
#### buyTokenWithFunds()
Buys tokens with specific BNB amount (V2 AMAP method).
```typescript
import { buyTokenWithFunds } from 'four-flap-meme-sdk';
await buyTokenWithFunds(
chain: 'BSC', // Chain name
rpcUrl: string,
signerPrivateKey: string,
token: string,
funds: bigint, // BNB amount to spend
minAmount: bigint, // Minimum tokens to receive
to?: string, // Optional recipient
origin?: bigint // Optional origin code (default: 0n)
);
```
---
#### sellToken()
Sells tokens for BNB (V2 method).
```typescript
import { sellToken } from 'four-flap-meme-sdk';
await sellToken(
chain: 'BSC', // Chain name
rpcUrl: string,
signerPrivateKey: string,
token: string,
amount: bigint, // Token amount to sell
minFunds: bigint, // Minimum BNB to receive
origin?: bigint // Optional origin code (default: 0n)
);
```
**Note**: Requires prior token approval (use `ensureSellApproval` first)
---
#### tradeBuy()
Auto-routing buy method (works for V1 and V2).
```typescript
import { tradeBuy } from 'four-flap-meme-sdk';
await tradeBuy(
chain: 'BSC' | 'BASE' | 'ARBITRUM_ONE', // Chain name
rpcUrl: string,
privateKey: string,
token: string,
params: {
type: 'funds' | 'amount',
funds?: bigint, // If type === 'funds'
minAmount?: bigint, // If type === 'funds'
amount?: bigint, // If type === 'amount'
maxFunds?: bigint, // If type === 'amount'
to?: string,
origin?: bigint
}
);
```
---
#### tradeSell()
Auto-routing sell method (works for V1 and V2).
```typescript
import { tradeSell } from 'four-flap-meme-sdk';
await tradeSell(
chain: 'BSC' | 'BASE' | 'ARBITRUM_ONE', // Chain name
rpcUrl: string,
privateKey: string,
token: string,
params: {
type: 'direct' | 'router',
amount: bigint,
minFunds?: bigint,
from?: string, // If type === 'router'
feeRate?: bigint, // If type === 'router', in basis points
feeRecipient?: string // If type === 'router'
}
);
```
---
### Utility Methods
#### Token Approval Methods
The SDK provides **multiple authorization methods** to support different TokenManager versions (V1/V2) and platforms (four.meme/Flap Protocol).
##### Four.meme Token Approval
**For V1 Tokens**:
```typescript
import { checkSellApprovalV1, ensureSellApprovalV1 } from 'four-flap-meme-sdk';
// Check V1 approval status (read-only)
const status = await checkSellApprovalV1(
'BSC', // Supported: 'BSC' | 'BASE' | 'ARBITRUM_ONE'
rpcUrl,
tokenAddress,
ownerAddress,
amount
);
// Ensure V1 approval (sends tx if needed)
const result = await ensureSellApprovalV1(
'BSC',
rpcUrl,
privateKey,
tokenAddress,
ownerAddress,
amount
);
```
**For V2 Tokens**:
```typescript
import { checkSellApprovalV2, ensureSellApprovalV2 } from 'four-flap-meme-sdk';
// Check V2 approval status (read-only)
const status = await checkSellApprovalV2(
'BSC', // Supported: 'BSC' | 'BASE' | 'ARBITRUM_ONE'
rpcUrl,
tokenAddress,
ownerAddress,
amount
);
// Ensure V2 approval (sends tx if needed)
const result = await ensureSellApprovalV2(
'BSC',
rpcUrl,
privateKey,
tokenAddress,
ownerAddress,
amount
);
```
**Universal Methods (defaults to V2)**:
```typescript
import { checkSellApproval, ensureSellApproval } from 'four-flap-meme-sdk';
// Check approval (defaults to V2)
const status = await checkSellApproval(
'BSC',
rpcUrl,
tokenAddress,
ownerAddress,
amount
);
// Ensure approval (defaults to V2)
const result = await ensureSellApproval(
'BSC',
rpcUrl,
privateKey,
tokenAddress,
ownerAddress,
amount
);
```
##### Flap Protocol Token Approval
```typescript
import { checkFlapSellApproval, ensureFlapSellApproval } from 'four-flap-meme-sdk';
// Check Flap approval status (read-only)
const status = await checkFlapSellApproval(
'BSC', // Supported: 'BSC' | 'BASE' | 'XLAYER' | 'MORPH'
rpcUrl,
tokenAddress,
ownerAddress,
amount
);
// Ensure Flap approval (sends tx if needed)
const result = await ensureFlapSellApproval(
'BSC',
rpcUrl,
privateKey,
tokenAddress,
ownerAddress,
amount
);
```
**Return Values**:
All `check*` methods return:
```typescript
{
isApproved: boolean, // true if already approved
currentAllowance: bigint, // Current approval amount
requiredAllowance: bigint // Required approval amount
}
```
All `ensure*` methods return:
```typescript
{
alreadyApproved: boolean, // true if no tx was needed
currentAllowance: bigint,
requiredAllowance: bigint,
txReceipt?: TransactionReceipt // Only if approval tx was sent
}
```
**Complete Workflow Examples**:
**Four.meme V2 Token Sell**:
```typescript
// 1. Check approval status (fast, read-only)
const status = await checkSellApprovalV2('BSC', rpcUrl, token, wallet, amount);
if (!status.isApproved) {
// 2. Send approval transaction if needed
console.log('Sending approval...');
await ensureSellApprovalV2('BSC', rpcUrl, privateKey, token, wallet, amount);
}
// 3. Execute sell
await tradeSell('BSC', rpcUrl, privateKey, token, { type: 'direct', amount, minFunds: 0n });
```
**Flap Protocol Token Sell**:
```typescript
// 1. Check approval status
const status = await checkFlapSellApproval('BSC', rpcUrl, token, wallet, amount);
if (!status.isApproved) {
// 2. Approve Flap Portal
await ensureFlapSellApproval('BSC', rpcUrl, privateKey, token, wallet, amount);
}
// 3. Execute sell
const writer = new FlapPortalWriter({ chain: 'BSC', rpcUrl }, privateKey);
await writer.swapExactInput({
inputToken: token,
outputToken: ZERO_ADDRESS,
inputAmount: amount,
minOutputAmount: 0n,
permitData: '0x'
});
```
**UI Integration Example**:
```typescript
// Update UI based on approval status
const status = await checkSellApprovalV2('BSC', rpcUrl, tokenAddr, walletAddr, sellAmount);
if (status.isApproved) {
showButton('Sell Now', 'green');
} else {
showButton('Approve First', 'orange');
showInfo(`Current: ${status.currentAllowance}, Need: ${status.requiredAllowance}`);
}
```
**Important Notes**:
- β οΈ **V1 and V2 use different proxy contracts** - must approve the correct version
- β οΈ **Four.meme and Flap use different contracts** - cannot mix authorization methods
- β
**Universal methods default to V2** for backward compatibility
- β
**Recommend using explicit version methods** (`V1`/`V2`) for new code
---
#### parseFourError()
Parses four.meme error codes.
```typescript
import { parseFourError } from 'four-flap-meme-sdk';
const { code, message } = parseFourError(error);
```
**Returns**: `{ code?: FourErrorCode, message: string }`
---
#### isExclusiveOnChain()
Checks if token is MPC-exclusive (on-chain).
```typescript
import { isExclusiveOnChain } from 'four-flap-meme-sdk';
const isExclusive = await isExclusiveOnChain({
chain: 'BSC', // Only BSC supported (TokenManagerV2)
tokenAddress: string,
rpcUrl: string
});
```
---
#### isExclusiveOffChain()
Checks if token is MPC-exclusive (via API).
```typescript
import { isExclusiveOffChain } from 'four-flap-meme-sdk';
const isExclusive = await isExclusiveOffChain(
getTokenInfo: (addr: string) => Promise<{ version?: string }>,
tokenAddress: string
);
```
---
---
# Flap Protocol Guide
## Flap Architecture
Flap Protocol is a next-generation token launch platform with these key features:
### Core Components:
1. **Portal Contract**: Main entry point for all operations
2. **CDPV2 Bonding Curve**: Advanced mathematical curve with three parameters (r, h, k)
3. **Multi-Network Support**: BSC, Base, X Layer, Morph
4. **Flexible Configuration**: Custom taxes, quote tokens, migration settings
5. **Configurable Fees**: Different chains can have different buy/sell fee rates
### Token Lifecycle on Flap:
```
1. Create Token β Deploy with CDPV2 curve
2. Trading Phase β Buy/sell on bonding curve
3. Progress Tracking β Monitor reserve vs. threshold
4. Migration β Auto-migrate to DEX when threshold reached
```
---
## Reading Token State
Flap has **four versions** of token state reading methods:
### Version Comparison
| Method | Returns | Use Case |
|--------|---------|----------|
| `getTokenV2()` | Basic state (7 fields) | Legacy compatibility |
| `getTokenV3()` | + quote token info (9 fields) | Quote token support |
| `getTokenV4()` | + extension ID (10 fields) | Extension support |
| `getTokenV5()` | + full CDPV2 params (12 fields) | Complete information (recommended) |
### Reading Token State (V5 - Recommended)
```typescript
import { FlapPortal } from 'four-flap-meme-sdk';
// Use chain enum (SDK handles addresses and default fee rates automatically)
const portal = new FlapPortal({
chain: 'BSC', // Supports: 'BSC' | 'BASE' | 'XLAYER' | 'MORPH'
rpcUrl: 'https://bsc-dataseed.binance.org'
});
const state = await portal.getTokenV5('0x...token-address');
console.log('Token Status:', state.status); // 0=Invalid, 1=Tradable, 4=DEX
console.log('Reserve (wei):', state.reserve); // Current BNB in curve
console.log('Supply:', state.circulatingSupply); // Tokens in circulation
console.log('Price:', state.price); // Current price in wei
console.log('Curve Params:', state.r, state.h, state.k); // CDPV2 parameters
console.log('DEX Threshold:', state.dexSupplyThresh); // Supply needed for migration
console.log('Quote Token:', state.quoteTokenAddress); // 0x0 = native token
```
### State Fields Explained
```typescript
{
status: number, // 0=Invalid, 1=Tradable, 2=InDuel, 3=Killed, 4=DEX
reserve: bigint, // Current reserve in curve (in wei)
circulatingSupply: bigint, // Tokens in circulation (in wei, 18 decimals)
price: bigint, // Current price (in wei per token)
tokenVersion: number, // Token implementation version
r: bigint, // CDPV2 parameter r (reserve offset)
h: bigint, // CDPV2 parameter h (height adjustment)
k: bigint, // CDPV2 parameter k (curve constant)
dexSupplyThresh: bigint, // Supply threshold for DEX migration
quoteTokenAddress: Address, // 0x0 for native, or ERC20 address
nativeToQuoteSwapEnabled: boolean, // Can swap native to quote
extensionID: bytes32 // Extension identifier
}
```
---
## CDPV2 Bonding Curve
The **CDPV2** (Constant Dynamic Price V2) curve is the core of Flap's price mechanism.
### Understanding CDPV2 Parameters
#### Parameter `r` (Reserve Offset)
- **What it is**: Starting reserve amount
- **Effect**: Higher `r` = higher initial price
- **Typical value**: 0.1 ETH (0.1 Γ 10^18 wei)
#### Parameter `h` (Height Adjustment)
- **What it is**: Shifts the supply curve
- **Effect**: Adjusts where the curve starts
- **Typical value**: 0 (no shift)
#### Parameter `k` (Curve Constant)
- **What it is**: Determines price growth rate
- **Effect**: Higher `k` = higher prices overall
- **Typical value**: r Γ 10^9 (1 billion Γ r)
### The CDPV2 Formulas
```
Supply (S) = 1,000,000,000 + h - k / (R + r)
Reserve (R) = k / (1,000,000,000 + h - S) - r
Price (P) = k / (1,000,000,000 + h - S)Β²
```
Where:
- S = circulating supply
- R = reserve (BNB/ETH in curve)
- P = price per token
### Using CDPV2 Class
```typescript
import { CDPV2 } from 'four-flap-meme-sdk';
// Create a curve with r=0.1, h=0, k=1e8
const curve = CDPV2.getCurve(0.1, 0, 1e8);
// Calculate supply needed for 10 ETH reserve
const supply = curve.estimateSupply('10');
console.log('Supply at 10 ETH:', supply.toString());
// Calculate reserve needed for 800M supply
const reserve = curve.estimateReserve('800000000');
console.log('Reserve at 800M supply:', reserve.toString());
// Get current price at 800M supply
const price = curve.price('800000000');
console.log('Price at 800M supply:', price.toString());
// Get FDV (Fully Diluted Valuation) at 800M supply
const fdv = curve.fdv('800000000');
console.log('FDV:', fdv.toString());
```
### Calculating Progress
**Progress** = How close the token is to DEX migration
```typescript
import { FlapPortal } from 'four-flap-meme-sdk';
const portal = new FlapPortal({
chain: 'BSC',
rpcUrl: 'https://bsc-dataseed.binance.org'
});
const state = await portal.getTokenV5(tokenAddress);
const { price, progress } = portal.computePriceAndProgress(state);
console.log('Current Price:', price, 'ETH per token');
console.log('Progress:', progress); // '0.0000' to '1.0000' (0% to 100%)
```
**What progress means**:
- `0.0000`: Just launched
- `0.5000`: Halfway to DEX migration
- `1.0000`: Ready for DEX migration
- Progress = (current reserve) / (reserve needed at threshold)
---
## Flap Price Quotes
The SDK provides **two quote methods** with different advantages:
| Feature | Offline Quote | On-Chain Quote |
|---------|--------------|----------------|
| **Method** | `quoteBuy()` / `quoteSell()` | `quoteExactInput()` |
| **Speed** | β‘οΈ Instant (local computation) | π’ Slower (RPC call) |
| **Accuracy** | π High (99.9%+) | π― 100% exact |
| **Cost** | π° Free | πΈ Uses RPC quota |
| **Use Case** | Real-time UI display | Final confirmation before trade |
| **Dependency** | Requires token state | Only requires token address |
### Method 1: Offline Quote (Recommended for UI)β‘οΈ
**Advantages**:
- β‘οΈ **Instant**: Local computation, zero latency
- π° **Free**: No RPC quota consumption
- π **Accurate**: Uses same formulas and fee rates as on-chain
- π¨ **Real-time**: Perfect for live UI updates as user types
**Methods**: `quoteBuy()` / `quoteSell()`
**How it works**:
- Based on CDPV2 bonding curve formula
- Automatically deducts platform fees (configurable)
- 99.9%+ consistent with on-chain results
```typescript
import { FlapPortal, FLAP_DEFAULT_FEE_RATES } from 'four-flap-meme-sdk';
const portal = new FlapPortal({
chain: 'BSC',
rpcUrl: 'https://bsc-dataseed.binance.org',
// Configure fee rates (optional, default is chain-specific)
buyFeeRate: FLAP_DEFAULT_FEE_RATES.BSC.buy, // 1% = 0.01
sellFeeRate: FLAP_DEFAULT_FEE_RATES.BSC.sell // 1% = 0.01
});
// 1. Get token state (once)
const tokenAddress = '0x...' as any;
const state = await portal.getTokenV5(tokenAddress);
// 2. Offline buy quote: How many tokens for 1 BNB?
const tokenAmount = portal.quoteBuy(state, '1.0');
console.log('π° Buy Quote:');
console.log(' Pay: 1.0 BNB');
console.log(' Fee: 0.01 BNB (1%)');
console.log(' Used to buy: 0.99 BNB');
console.log(' Expected to receive:', tokenAmount, 'tokens');
// 3. Offline sell quote: How much BNB for 1000000 tokens?
const ethAmount = portal.quoteSell(state, '1000000');
console.log('\nπΈ Sell Quote:');
console.log(' Sell: 1000000 tokens');
console.log(' After 1% fee deduction');
console.log(' You receive:', ethAmount, 'BNB');
```
**Real-world Use Case - Live UI Updates**:
```typescript
// Scenario: User types amount in input box, show quote in real-time
let cachedState: TokenStateV5;
async function init() {
// Fetch token state once on initialization
cachedState = await portal.getTokenV5(tokenAddress);
}
function onUserInputChange(inputValue: string) {
// Instantly calculate and display when user types (no delay)
const outputAmount = portal.quoteBuy(cachedState, inputValue);
updateUI(`You will receive ~${formatNumber(outputAmount)} tokens`);
// Optional: Refresh cachedState periodically (e.g. every 10s) for accuracy
}
```
### Method 2: On-Chain Quote (Exact)π―
**Advantages**:
- π― **100% exact**: Directly simulates on-chain contract
- β
**Real-time state**: Uses latest on-chain data
- π **Reliable**: Final confirmation before trade
**Disadvantages**:
- π’ Requires RPC call (slower)
- πΈ Consumes RPC quota
**Methods**: `quoteExactInput()` / `previewBuy()` / `previewSell()`
```typescript
const portal = new FlapPortal({
chain: 'BSC',
rpcUrl: 'https://bsc-dataseed.binance.org'
});
// Method A: General quote (supports any input/output token combination)
const outputAmount = await portal.quoteExactInput({
inputToken: '0x0000000000000000000000000000000000000000' as any, // Native token (BNB/ETH)
outputToken: tokenAddress, // Token you want
inputAmount: 1n * 10n ** 18n // 1 BNB (in wei)
});
console.log('Exact quote - you will receive:', formatEther(outputAmount), 'tokens');
// Method B: Specialized buy quote (more concise)
const tokenAmount = await portal.previewBuy(
tokenAddress,
1n * 10n ** 18n // 1 BNB
);
console.log('Buy quote - you will receive:', formatEther(tokenAmount), 'tokens');
// Method C: Specialized sell quote (more concise)
const ethAmount = await portal.previewSell(
tokenAddress,
1000n * 10n ** 18n // 1000 tokens
);
console.log('Sell quote - you will receive:', formatEther(ethAmount), 'BNB');
```
### π Recommended Workflow
**Best practice flow**:
```typescript
import { FlapPortal, FlapPortalWriter, ZERO_ADDRESS } from 'four-flap-meme-sdk';
import { parseEther, formatEther } from 'ethers';
const rpcUrl = 'https://bsc-dataseed.binance.org';
const tokenAddress = '0x...'; // Token address
const zeroAddress = ZERO_ADDRESS;
// Create read-only instance for quotes
const portal = new FlapPortal({ chain: 'BSC', rpcUrl });
// 1οΈβ£ UI display phase: Use offline quote (fast)
const state = await portal.getTokenV5(tokenAddress);
const estimatedOutput = portal.quoteBuy(state, userInput);
showToUser(`Expected: ${estimatedOutput} tokens`);
// 2οΈβ£ User clicks "Confirm Trade": Use on-chain quote (exact)
const exactOutput = await portal.quoteExactInput({
inputToken: zeroAddress,
outputToken: tokenAddress,
inputAmount: parseEther(userInput)
});
showConfirmDialog(`Exact amount: ${formatEther(exactOutput)} tokens`);
// 3οΈβ£ Execute trade - Create Writer instance
const writer = new FlapPortalWriter(
{ chain: 'BSC', rpcUrl },
'YOUR_PRIVAT