Installation & Setup

# Production SDK
pnpm add @b3dotfun/sdk

# Import from main SDK
import { 
  BondkitTokenFactory, 
  BondkitToken 
} from "@b3dotfun/sdk/bondkit";

Core Classes

BondkitTokenFactory

The factory class handles deploying new bond tokens and querying deployed tokens.
import { BondkitTokenFactory } from "@b3dotfun/sdk/bondkit";
import { base } from "viem/chains";

const factory = new BondkitTokenFactory(
  base.id,                    // Chain ID (Base mainnet)
  process.env.WALLET_KEY      // Optional: private key for writes
);

Constructor

constructor(
  chainId: SupportedChainId,
  walletKey?: string
)
ParameterTypeRequiredDescription
chainIdnumberYesChain ID (currently only Base: 8453)
walletKeystringNoPrivate key for write operations

Methods

Deploy a new bond token
async deployBondkitToken(
  config: BondkitTokenConfig
): Promise<Address>
Parameters:
interface BondkitTokenConfig {
  name: string;                      // Token name
  symbol: string;                    // Token symbol
  feeRecipient: Address;            // Receives trading fees
  finalTokenSupply: bigint;         // Total supply (18 decimals)
  aggressivenessFactor: number;     // 0-100 curve steepness
  lpSplitRatioFeeRecipientBps: bigint; // LP fee share (basis points)
  targetEth: bigint;                // Migration target (18 decimals)
  uniswapV2RouterAddress: Address;  // Router address
  migrationAdminAddress: Address;   // Can trigger migration
}
Example:
const tokenAddress = await factory.deployBondkitToken({
  name: "My Token",
  symbol: "MTK",
  feeRecipient: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb1",
  finalTokenSupply: parseEther("1000000"),
  aggressivenessFactor: 50,
  lpSplitRatioFeeRecipientBps: 1000n, // 10%
  targetEth: parseEther("10"),
  uniswapV2RouterAddress: "0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24",
  migrationAdminAddress: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb1"
});
Get all deployed tokens
async getDeployedBondkitTokens(): Promise<Address[]>
Returns: Array of token addressesExample:
const tokens = await factory.getDeployedBondkitTokens();
console.log(`Found ${tokens.length} tokens`);
Get token configuration
async getBondkitTokenConfig(
  tokenAddress: Address
): Promise<BondkitTokenConfig>
Example:
const config = await factory.getBondkitTokenConfig(
  "0x123..."
);
console.log(`Token name: ${config.name}`);
Get implementation contract
async getImplementationAddress(): Promise<Address>
Example:
const impl = await factory.getImplementationAddress();
console.log(`Implementation: ${impl}`);
Connect wallet provider
connect(provider?: EIP1193Provider): boolean
Example:
// Browser environment
const connected = factory.connect(window.ethereum);

// Custom provider
import { custom } from "viem";
const transport = custom(provider);
factory.connect(transport);

BondkitToken

The token class handles all operations for a specific bond token.
import { BondkitToken } from "@b3dotfun/sdk/bondkit";

const token = new BondkitToken(
  "0x123...",                 // Token address
  process.env.WALLET_KEY      // Optional: private key
);

Constructor

constructor(
  contractAddress: string,
  walletKey?: string
)
ParameterTypeRequiredDescription
contractAddressstringYesToken contract address
walletKeystringNoPrivate key for write operations

Read Methods

// Basic token info
async name(): Promise<string>
async symbol(): Promise<string>
async decimals(): Promise<number>
async totalSupply(): Promise<bigint>

// Balances
async balanceOf(address: Address): Promise<bigint>
async allowance(
  owner: Address, 
  spender: Address
): Promise<bigint>

// Example
const balance = await token.balanceOf(userAddress);
console.log(`Balance: ${formatEther(balance)}`);
// Current price per token
async getCurrentBondingCurvePricePerToken(): Promise<bigint>

// Current price in ETH
async getCurrentPrice(): Promise<bigint>

// Quote for buying
async getAmountOfTokensToBuy(
  ethAmount: bigint
): Promise<bigint>

// Quote for selling
async getAmountOfEthToReceive(
  tokenAmount: bigint
): Promise<bigint>

// Bonding progress
async getBondingProgress(): Promise<{
  progress: number;      // 0-1 (percentage)
  raised: bigint;       // Amount raised
  threshold: bigint;    // Target amount
}>

// Example
const progress = await token.getBondingProgress();
console.log(`Progress: ${(progress.progress * 100).toFixed(2)}%`);
// Token state
async getStatus(): Promise<TokenStatus>
async isMigrated(): Promise<boolean>
async canMigrate(): Promise<boolean>

// Configuration
async getOwner(): Promise<Address>
async getFeeRecipient(): Promise<Address>
async getAggressivenessFactor(): Promise<number>
async getTargetAmount(): Promise<bigint>

// Migration info
async getMigrationData(): Promise<{
  ethForLp: bigint;
  tokensForLp: bigint;
  sqrtPriceX96: bigint;
}>

// Example
if (await token.canMigrate()) {
  console.log("Ready to migrate!");
}
// Token holders
async getPaginatedHolders(
  offset: number,
  limit: number
): Promise<{
  holders: Address[];
  total: number;
}>

// Transaction history (from API)
async getTransactionHistory(
  options?: GetTransactionHistoryOptions
): Promise<TransactionResponse>

// Options interface
interface GetTransactionHistoryOptions {
  userAddress?: Address;
  type?: "buy" | "sell";
  from?: number;        // Timestamp
  to?: number;          // Timestamp
  limit?: number;       // 1-100
  offset?: number;
}

// Example
const history = await token.getTransactionHistory({
  type: "buy",
  limit: 10
});

Write Methods

Buy tokens with ETH
async buy(
  minTokensOut: bigint,
  ethAmount: string | bigint
): Promise<Hex>
Parameters:
  • minTokensOut: Minimum tokens to receive (slippage protection)
  • ethAmount: ETH to spend (as string or bigint)
Example:
// Get quote first
const quote = await token.getAmountOfTokensToBuy(
  parseEther("1")
);

// Buy with 5% slippage tolerance
const minTokens = quote * 95n / 100n;
const txHash = await token.buy(minTokens, "1");

console.log(`Transaction: ${txHash}`);
Sell tokens for ETH
async sell(
  tokenAmount: bigint,
  minEthOut: bigint
): Promise<Hex>
Parameters:
  • tokenAmount: Amount of tokens to sell
  • minEthOut: Minimum ETH to receive (slippage protection)
Example:
// Sell 1000 tokens
const sellAmount = parseEther("1000");

// Get quote
const quote = await token.getAmountOfEthToReceive(sellAmount);

// Sell with slippage protection
const minEth = quote * 95n / 100n;
const txHash = await token.sell(sellAmount, minEth);
Migrate to Uniswap v4
async migrateToDex(): Promise<Hex>
Requirements:
  • Caller must be migration admin
  • Target must be reached
Example:
if (await token.canMigrate()) {
  const txHash = await token.migrateToDex();
  console.log(`Migration tx: ${txHash}`);
}
// Standard transfers
async transfer(
  to: Address,
  amount: bigint
): Promise<Hex>

async transferFrom(
  from: Address,
  to: Address,
  amount: bigint
): Promise<Hex>

// Approvals
async approve(
  spender: Address,
  amount: bigint
): Promise<Hex>

// Example
await token.approve(
  spenderAddress,
  parseEther("1000")
);

Event Listeners

// Listen for buy events
token.onBuy((event: BoughtEventArgs) => {
  console.log("Buy:", {
    buyer: event.buyer,
    ethIn: formatEther(event.ethIn),
    tokensOut: formatEther(event.tokensOut),
    fee: formatEther(event.feeRecipientFee)
  });
});

// Listen for sell events
token.onSell((event: SoldEventArgs) => {
  console.log("Sell:", {
    seller: event.seller,
    tokensIn: formatEther(event.tokensIn),
    ethOut: formatEther(event.ethOut),
    fee: formatEther(event.feeRecipientFee)
  });
});

// Listen for migration
token.onMigration((event: DexMigrationEventArgs) => {
  console.log("Migrated:", {
    ethForLp: formatEther(event.ethForLp),
    tokensForLp: formatEther(event.tokensForLp)
  });
});

Type Definitions

Core Types

// Token configuration
interface BondkitTokenConfig {
  name: string;
  symbol: string;
  feeRecipient: Address;
  finalTokenSupply: bigint;
  aggressivenessFactor: number;
  lpSplitRatioFeeRecipientBps: bigint;
  targetEth: bigint;
  uniswapV2RouterAddress: Address;
  migrationAdminAddress: Address;
}

// Token status enum
enum TokenStatus {
  Inactive = 0,
  BondingPhase = 1,
  DexPhase = 2,
  Migrated = 3
}

// Token details
interface TokenDetails {
  name: string;
  symbol: string;
  decimals: number;
  totalSupply: bigint;
  owner: Address;
}

Event Types

// Buy event
interface BoughtEventArgs {
  buyer: Address;
  ethIn: bigint;
  tokensOut: bigint;
  feeRecipientFee: bigint;
}

// Sell event
interface SoldEventArgs {
  seller: Address;
  tokensIn: bigint;
  ethOut: bigint;
  feeRecipientFee: bigint;
}

// Migration event
interface DexMigrationEventArgs {
  ethForLp: bigint;
  tokensForLp: bigint;
  ethForFeeRecipient: bigint;
}

// Factory creation event
interface BondkitTokenCreatedEventArgs {
  tokenAddress: Address;
  implementationAddress: Address;
  name: string;
  symbol: string;
  feeRecipient: Address;
  migrationAdmin: Address;
}

Transaction Types

// Transaction history
interface Transaction {
  timestamp: number;
  price: number;
  amount: string;
  type: "buy" | "sell";
  userAddress: Address;
  txHash: Hex;
  chainId: number;
  blockNumber?: number;
  totalRaisedBonding?: string;
  value?: string;
}

// API response
interface TransactionResponse {
  total: number;
  limit: number;
  skip: number;
  data: Transaction[];
}

Configuration

Network Support

import { getConfig } from "@b3dotfun/sdk/bondkit";
import { base } from "viem/chains";

const config = getConfig(base.id);

console.log({
  chain: config.chain.name,           // "Base"
  factoryAddress: config.factoryAddress,
  rpcUrl: config.rpcUrl,
  apiEndpoint: config.apiEndpoint
});

Supported Chains

ChainChain IDStatus
Base Mainnet8453✅ Supported
Base Sepolia84532🚧 Coming Soon

Error Handling

try {
  const txHash = await token.buy(minTokens, "1");
} catch (error) {
  if (error.message.includes("insufficient funds")) {
    console.error("Not enough ETH");
  } else if (error.message.includes("slippage")) {
    console.error("Price moved, try again");
  } else if (error.message.includes("target exceeded")) {
    console.error("Would exceed migration target");
  } else {
    console.error("Transaction failed:", error);
  }
}

Complete Examples

Deploy and Trade

import { 
  BondkitTokenFactory, 
  BondkitToken 
} from "@b3dotfun/sdk/bondkit";
import { parseEther, formatEther } from "viem";
import { base } from "viem/chains";

async function deployAndTrade() {
  // 1. Deploy token
  const factory = new BondkitTokenFactory(
    base.id,
    process.env.WALLET_KEY
  );
  
  const tokenAddress = await factory.deployBondkitToken({
    name: "Test Token",
    symbol: "TEST",
    finalTokenSupply: parseEther("1000000"),
    aggressivenessFactor: 50,
    targetEth: parseEther("10"),
    feeRecipient: process.env.WALLET_ADDRESS,
    lpSplitRatioFeeRecipientBps: 1000n,
    migrationAdminAddress: process.env.WALLET_ADDRESS,
    uniswapV2RouterAddress: "0x4752ba5DBc23f44D87826276BF6Fd6b1C372aD24"
  });
  
  // 2. Initialize token client
  const token = new BondkitToken(
    tokenAddress,
    process.env.WALLET_KEY
  );
  
  // 3. Buy tokens
  const buyAmount = parseEther("0.5");
  const expectedTokens = await token.getAmountOfTokensToBuy(buyAmount);
  await token.buy(expectedTokens * 95n / 100n, "0.5");
  
  // 4. Check progress
  const progress = await token.getBondingProgress();
  console.log(`Progress: ${(progress.progress * 100).toFixed(2)}%`);
  
  // 5. Monitor events
  token.onBuy((event) => {
    console.log(`New buy: ${formatEther(event.tokensOut)} tokens`);
  });
}

Portfolio Tracker

async function trackPortfolio(userAddress: Address) {
  const factory = new BondkitTokenFactory(base.id);
  const tokens = await factory.getDeployedBondkitTokens();
  
  const portfolio = [];
  
  for (const tokenAddress of tokens) {
    const token = new BondkitToken(tokenAddress);
    const balance = await token.balanceOf(userAddress);
    
    if (balance > 0n) {
      const [name, symbol, price] = await Promise.all([
        token.name(),
        token.symbol(),
        token.getCurrentPrice()
      ]);
      
      portfolio.push({
        address: tokenAddress,
        name,
        symbol,
        balance: formatEther(balance),
        value: formatEther(balance * price / 10n ** 18n)
      });
    }
  }
  
  return portfolio;
}

Best Practices

Security Considerations
  1. Never expose private keys in client-side code
  2. Always use slippage protection in trades
  3. Validate addresses before transactions
  4. Handle errors gracefully with try-catch
  5. Monitor gas prices before large operations
Performance Tips
  1. Batch read operations with Promise.all()
  2. Cache token instances to avoid recreating
  3. Use event listeners instead of polling
  4. Implement exponential backoff for retries
  5. Consider pagination for large datasets

Support & Resources