npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

flipmeme-sdk

v1.3.76

Published

web3 interface for flipmeme

Downloads

1,313

Readme

Flipmeme EVM SDK Documentation

Table of Contents

  1. Overview
  2. Installation
  3. Quick Start
  4. Architecture
  5. API Reference
  6. Types Reference
  7. Constants & Configuration
  8. Advanced Usage
  9. Error Handling
  10. Best Practices
  11. Examples

Overview

The Flipmeme EVM SDK provides a comprehensive TypeScript/JavaScript interface for interacting with the Flipmeme protocol on Ethereum-compatible blockchains. It enables developers to:

  • Create NFT Collections with dynamic bonding curve pricing
  • Mint & Trade NFTs with integrated liquidity pools
  • Manage Multiple Collections with batch operations
  • Calculate Pricing with built-in fee handling
  • Query On-chain Data efficiently

Key Features

  • 🔗 Multi-chain Support: Works on Ethereum, Base, and other EVM-compatible chains
  • 💰 Bonding Curve Pricing: Automated market-making with customizable price curves
  • 🔄 Liquidity Pools: Built-in AMM for instant NFT trading
  • 📦 Batch Operations: Gas-efficient multi-collection transactions
  • 🛡️ Type-Safe: Full TypeScript support with comprehensive type definitions
  • 🧪 Well-Tested: Production-ready with extensive test coverage

Protocol Overview

The Flipmeme protocol implements a bonding curve NFT marketplace where:

  1. Collections are created with a defined supply and price range
  2. NFTs can be minted at dynamically calculated prices
  3. Liquidity pools allow instant buying/selling
  4. Fees are distributed to creators, LP providers, and the protocol
  5. Liquidity migration occurs when collections sell out

Installation

Prerequisites

  • Node.js >= 16.x
  • npm or yarn or pnpm

Install Dependencies

npm install flipmeme-sdk ethers@^5.7.0
# or
yarn add flipmeme-sdk ethers@^5.7.0
# or
pnpm add flipmeme-sdk ethers@^5.7.0

Note: The SDK currently uses ethers v5. Compatibility with ethers v6 is planned for future releases.


Quick Start

Basic Setup

import { ethers } from "ethers";
import { FlipmemeSDK, BlockchainType, PLATFORM } from "flipmeme-sdk";

// 1. Setup provider and signer
const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
const signer = new ethers.Wallet(PRIVATE_KEY, provider);

// 2. Initialize SDK
const sdk = new FlipmemeSDK(
  BlockchainType.ETHEREUM,
  PLATFORM.DEV, // or PLATFORM.PROD
  {
    signer,
    chainId: 84532, // Base Sepolia
    provider,
  }
);

// 3. Create a collection
const { collectionId, collectionAddress } = await sdk.createCollection({
  name: "My NFT Collection",
  symbol: "MNFT",
  totalSupply: 100,
  premint: 5,
  sessionId: `session-${Date.now()}`,
  tokenUri: "ipfs://QmYourCollectionMetadata/",
  startPrice: ethers.utils.parseEther("0.001").toString(),
  endPrice: ethers.utils.parseEther("0.1").toString(),
});

console.log("Collection created at:", collectionAddress);

// 4. Buy NFTs
const result = await sdk.buy({
  collectionAddress,
  baseUri: "ipfs://QmYourTokenMetadata/",
  amount: 3, // Mint 3 new NFTs
  tokenIds: [], // No buying from pool
});

console.log(`Successfully minted ${result.successCount} NFTs`);

Example: Complete Trading Flow

// Calculate price before buying
const totalPrice = await sdk.getTotalPrice(
  PurcahseType.BUY,
  collectionAddress,
  3
);
console.log("Total cost:", ethers.utils.formatEther(totalPrice), "ETH");

// Buy 3 NFTs
await sdk.buy({
  collectionAddress,
  baseUri: "ipfs://tokens/",
  amount: 3,
  tokenIds: [],
});

// Check your balance
const balance = await sdk.balanceOf(
  collectionAddress,
  await signer.getAddress()
);
console.log("You own", balance, "NFTs");

// Sell 2 NFTs back
await sdk.flipSell({
  collectionAddress,
  tokenIds: [0, 1],
});

Architecture

Class Hierarchy

FlipmemeSDK (main entry point)
    └── EthereumConnector (EVM implementation)
            └── Factory & Collection Contracts

Contract Architecture

Factory Contract
    ├── Creates Collections
    ├── Manages Global State
    └── Handles Multi-collection Operations

Collection Contract
    ├── ERC721A (NFT Standard)
    ├── Bonding Curve Logic
    ├── Liquidity Pool Management
    └── Fee Distribution

Data Flow

User → SDK → EthereumConnector → Smart Contracts → Blockchain
     ←     ←                    ←                ←

API Reference

Initialization

new FlipmemeSDK(chainType, platform, config)

Creates a new instance of the Flipmeme SDK.

Parameters:

  • chainType: BlockchainType.ETHEREUM
  • platform: PLATFORM.DEV | PLATFORM.STAGE | PLATFORM.PROD
  • config: EthereumConfig

EthereumConfig:

interface EthereumConfig {
  signer?: ethers.Signer; // Optional: required for write operations
  chainId: number; // Network chain ID
  provider: ethers.providers.BaseProvider; // RPC provider
}

Example:

const sdk = new FlipmemeSDK(BlockchainType.ETHEREUM, PLATFORM.PROD, {
  signer: wallet,
  chainId: 8453, // Base Mainnet
  provider: provider,
});

Throws:

  • Error("Invalid config for the given blockchain type") if config doesn't match chain type

Collection Management

createCollection(params)

Creates a new NFT collection with bonding curve pricing.

Parameters:

interface CollectionParams {
  sessionId: string; // Unique session identifier
  name: string; // Collection name (e.g., "Cool Cats")
  symbol?: string; // Token symbol (e.g., "COOL")
  tokenUri: string; // Collection metadata URI
  totalSupply: number; // Max number of NFTs
  premint?: number; // NFTs to pre-mint for creator (default: 0)
  startPrice?: string; // Starting price in wei (default: 10^15 = 0.001 ETH)
  endPrice?: string; // Ending price in wei (default: 10^16 = 0.01 ETH)
}

Returns:

Promise<CreateCollectionResponse>;

interface CreateCollectionResponse {
  collectionId: string; // On-chain collection ID
  collectionAddress: string; // Contract address
}

Example:

const { collectionId, collectionAddress } = await sdk.createCollection({
  name: "Degen Apes",
  symbol: "DAPE",
  totalSupply: 1000,
  premint: 10,
  sessionId: `create-${Date.now()}-${Math.random()}`,
  tokenUri: "ipfs://QmYourCollectionHash/metadata.json",
  startPrice: ethers.utils.parseEther("0.0001").toString(),
  endPrice: ethers.utils.parseEther("0.5").toString(),
});

console.log("Collection ID:", collectionId);
console.log(
  "View on explorer:",
  `https://basescan.org/address/${collectionAddress}`
);

Events Emitted:

  • CollectionCreated(id, collection, creator, totalSupply, premint)

Gas Cost: ~3-5M gas (varies by network)

Important Notes:

  • sessionId should be unique per collection to avoid conflicts
  • Price curve is logarithmic between startPrice and endPrice
  • Preminted NFTs are sent to the creator's address
  • Symbol is optional but recommended for better UX

Trading Operations

buy(params)

Mints new NFTs and/or buys NFTs from the liquidity pool.

Parameters:

interface EthBuyParams {
  collectionAddress: string; // Collection contract address
  baseUri?: string; // Token metadata base URI (required if amount > 0)
  amount: number; // Number of new NFTs to mint
  tokenIds: number[]; // Token IDs to buy from pool
}

Returns:

Promise<ConfirmResult>;

interface ConfirmResult {
  successCount: number; // Total NFTs acquired
  failedCount: number; // Failed transactions (always 0 on success)
}

Examples:

Mint Only:

// Mint 5 new NFTs
const result = await sdk.buy({
  collectionAddress: "0x1234...",
  baseUri: "ipfs://QmTokens/",
  amount: 5,
  tokenIds: [],
});
// successCount = 5

Buy from Pool Only:

// Buy 3 specific NFTs from liquidity pool
const result = await sdk.buy({
  collectionAddress: "0x1234...",
  baseUri: "", // Not needed for pool purchases
  amount: 0,
  tokenIds: [10, 15, 20],
});
// successCount = 3

Combined Mint + Buy:

// Mint 2 new + buy 3 from pool
const result = await sdk.buy({
  collectionAddress: "0x1234...",
  baseUri: "ipfs://QmTokens/",
  amount: 2,
  tokenIds: [5, 8, 12],
});
// successCount = 5 (2 minted + 3 bought)

Pricing Logic:

  • Price increases with each mint/buy according to bonding curve
  • Pool purchases use current price for each NFT
  • Total price includes 2.5% protocol fee (configurable)
  • Use getTotalPrice() to calculate cost before buying

Gas Cost: ~100-300k per NFT (varies by operation)

Throws:

  • Error if insufficient ETH sent
  • Error if collection is sold out and amount > 0
  • Error if tokenIds reference non-existent or unavailable tokens

flipSell(params)

Sells NFTs back to the collection's liquidity pool.

Parameters:

interface EthSellParams {
  collectionAddress: string; // Collection contract address
  tokenIds: number[]; // Token IDs to sell
}

Returns:

Promise<ConfirmResult>;

Example:

// Sell 3 NFTs back to pool
const result = await sdk.flipSell({
  collectionAddress: "0x1234...",
  tokenIds: [5, 10, 15],
});

console.log(`Sold ${result.successCount} NFTs`);

Important Notes:

  • You must own the NFTs you're selling
  • NFTs must be from the specified collection
  • Price is based on current bonding curve position
  • Seller receives ETH minus protocol fee
  • Sold NFTs return to the liquidity pool

Gas Cost: ~80-150k per NFT

Throws:

  • Error if you don't own the tokens
  • Error if collection doesn't have enough liquidity

profileSell(params)

Sells NFTs from multiple collections in a single transaction (gas-efficient).

Parameters:

interface EthProfileSellParams {
  data: Record<string, EthSellData>; // Map of collectionId to sell data
  slippage: number; // Not used in EVM (reserved for future)
}

interface EthSellData {
  tokenIds: number[]; // Token IDs to sell
  collectionId: string; // Collection ID (not address!)
}

Returns:

Promise<ConfirmResult>;

Example:

// Get collection IDs first
const info1 = await sdk.getCollectionInfo(collectionAddr1);
const collectionId1 = info1[1].toString();

const info2 = await sdk.getCollectionInfo(collectionAddr2);
const collectionId2 = info2[1].toString();

// Sell from multiple collections
const result = await sdk.profileSell({
  data: {
    [collectionId1]: {
      tokenIds: [1, 2, 3],
      collectionId: collectionId1,
    },
    [collectionId2]: {
      tokenIds: [5, 7],
      collectionId: collectionId2,
    },
  },
  slippage: 0, // Not used currently
});

console.log(`Sold ${result.successCount} total NFTs across collections`);

Gas Savings:

  • ~30-40% cheaper than individual sells
  • More efficient with more collections

Use Cases:

  • Portfolio liquidation
  • Mass selling across collections
  • Gas optimization for power users

Exporting NFT Images & Metadata (Off-chain)

These functions allow you to export NFT images and metadata from the server, enabling deployment to other platforms. They do not deploy collections to the blockchain directly.

getCollectionPriceByTotalSupply(totalSupply)

Calculates the price for exporting a collection based on its total supply.

Parameters:

  • totalSupply: number — The total number of NFTs in the collection to export.

Returns:

string // Price in wei as a string

Example:

const price = sdk.getCollectionPriceByTotalSupply(1000);
console.log("Export price:", ethers.utils.formatEther(price), "ETH");

exportCollectionByEth(sessionId, totalSupply, slippage?)

Pays the price for exporting a collection's images and metadata, and emits an event for backend monitoring. This is used for off-chain export, not for on-chain deployment.

Parameters:

  • sessionId: string — Unique session identifier for the export operation
  • totalSupply: number — Total number of NFTs to export
  • slippage?: number (optional) — Slippage tolerance. If omitted, a default of 3% is used.

Returns:

Promise<any> // Resolves when export is successful

Example:

// Uses default 3% slippage
await sdk.exportCollectionByEth("session-abc-123", 1000);

// Specify custom slippage (e.g., 5%)
await sdk.exportCollectionByEth("session-abc-123", 1000, 5);

console.log("Export initiated. Monitor backend for completion event.");

Query Operations

getCollectionInfo(collectionAddress)

Retrieves comprehensive information about a collection.

Parameters:

  • collectionAddress: string - The collection's contract address

Returns:

Promise<
  [
    string, // [0] Factory address
    BigNumber, // [1] Collection ID
    string, // [2] Creator address
    BigNumber, // [3] Max supply
    BigNumber, // [4] Current mint count
    boolean, // [5] Is sold out
    BigNumber, // [6] Protocol fee (basis points)
    string, // [7] Collection URI
    string // [8] Base URI
  ]
>;

Example:

const info = await sdk.getCollectionInfo("0x1234...");

console.log("Factory:", info[0]);
console.log("Collection ID:", info[1].toString());
console.log("Creator:", info[2]);
console.log("Max Supply:", info[3].toString());
console.log("Minted:", info[4].toString());
console.log("Sold Out:", info[5]);
console.log("Protocol Fee BPS:", info[6].toString()); // 250 = 2.5%
console.log("Collection URI:", info[7]);
console.log("Base URI:", info[8]);

// Check progress
const progress = (info[4].toNumber() / info[3].toNumber()) * 100;
console.log(`Collection is ${progress.toFixed(1)}% minted`);

Gas Cost: Free (view function)


getStateInfo() (getFactoryInfo)

Gets global factory state and configuration.

Returns:

Promise<FactoryInfo>;
// Exact return type depends on contract implementation

Example:

const factoryInfo = await sdk.getStateInfo();
console.log("Factory configuration:", factoryInfo);

Use Cases:

  • Debugging
  • Monitoring protocol state
  • Admin operations

getTotalPrice(type, collectionAddress, amount)

Calculates the total price (including fees) for buying or selling NFTs.

Parameters:

  • type: PurcahseType.BUY | PurcahseType.SELL
  • collectionAddress: string
  • amount: number - Number of NFTs

Returns:

Promise<string>; // Price in wei as string

Examples:

import { PurcahseType } from "flipmeme-sdk";

// Calculate buy price for 5 NFTs
const buyPrice = await sdk.getTotalPrice(
  PurcahseType.BUY,
  collectionAddress,
  5
);
console.log("Cost:", ethers.utils.formatEther(buyPrice), "ETH");

// Calculate sell price for 3 NFTs
const sellPrice = await sdk.getTotalPrice(
  PurcahseType.SELL,
  collectionAddress,
  3
);
console.log("You'll receive:", ethers.utils.formatEther(sellPrice), "ETH");

Price Calculation:

  • Uses current bonding curve position
  • Accounts for pool state (nftCount, mintCount)
  • Includes protocol fee (2.5% by default)
  • Sequential pricing for each NFT

Important:

  • Prices change with each transaction
  • Use immediately before buying/selling
  • Consider adding slippage tolerance in UI
  • Returns 0 if amount exceeds available supply

calculatePrice(collectionAddress)

Gets the current spot price for the next NFT purchase.

Parameters:

  • collectionAddress: string

Returns:

Promise<string>; // Current price in wei

Example:

const currentPrice = await sdk.calculatePrice(collectionAddress);
console.log("Current price:", ethers.utils.formatEther(currentPrice), "ETH");

// Monitor price changes
setInterval(async () => {
  const price = await sdk.calculatePrice(collectionAddress);
  console.log("Price update:", ethers.utils.formatEther(price), "ETH");
}, 10000); // Every 10 seconds

Use Cases:

  • Real-time price displays
  • Price tracking/charts
  • Market monitoring

calculateTradeFee(collectionAddress, price)

Calculates the protocol fee for a given price.

Parameters:

  • collectionAddress: string
  • price: string - Price in wei

Returns:

Promise<string>; // Fee amount in wei

Example:

const price = await sdk.calculatePrice(collectionAddress);
const fee = await sdk.calculateTradeFee(collectionAddress, price);

console.log("Price:", ethers.utils.formatEther(price), "ETH");
console.log("Fee (2.5%):", ethers.utils.formatEther(fee), "ETH");
console.log(
  "Total:",
  ethers.utils.formatEther(BigNumber.from(price).add(fee)),
  "ETH"
);

balanceOf(collectionAddress, owner)

Gets the number of NFTs owned by an address in a collection.

Parameters:

  • collectionAddress: string
  • owner: string - Wallet address

Returns:

Promise<string>; // Number of NFTs owned

Example:

const userAddress = await signer.getAddress();
const balance = await sdk.balanceOf(collectionAddress, userAddress);

console.log(`You own ${balance} NFTs from this collection`);

if (parseInt(balance) > 0) {
  console.log("You're a holder! 🎉");
}

ownerOf(collectionAddress, tokenId)

Gets the owner of a specific NFT.

Parameters:

  • collectionAddress: string
  • tokenId: number

Returns:

Promise<string>; // Owner's address

Example:

const owner = await sdk.ownerOf(collectionAddress, 42);
console.log(`Token #42 is owned by ${owner}`);

// Check if you own a token
const yourAddress = await signer.getAddress();
if (owner.toLowerCase() === yourAddress.toLowerCase()) {
  console.log("You own this token!");
}

Throws:

  • Error if token doesn't exist
  • Error if token was burned

getTokenURI(collectionAddress, tokenId)

Gets the metadata URI for a specific NFT.

Parameters:

  • collectionAddress: string
  • tokenId: number

Returns:

Promise<string>; // Token metadata URI

Example:

const tokenUri = await sdk.getTokenURI(collectionAddress, 10);
console.log("Token URI:", tokenUri);
// e.g., "ipfs://QmHash/10.json"

// Fetch and display metadata
const response = await fetch(
  tokenUri.replace("ipfs://", "https://ipfs.io/ipfs/")
);
const metadata = await response.json();
console.log("Name:", metadata.name);
console.log("Image:", metadata.image);
console.log("Attributes:", metadata.attributes);

totalSupply(collectionAddress)

Gets the total number of NFTs minted in a collection.

Parameters:

  • collectionAddress: string

Returns:

Promise<string>; // Total minted count

Example:

const total = await sdk.totalSupply(collectionAddress);
const info = await sdk.getCollectionInfo(collectionAddress);
const maxSupply = info[3].toString();

console.log(`${total} / ${maxSupply} minted`);

const percentMinted = (parseInt(total) / parseInt(maxSupply)) * 100;
console.log(`${percentMinted.toFixed(1)}% of collection minted`);

Utility Functions

moveLiquidity(collectionAddress)

Moves liquidity from the pool when a collection is sold out. Distributes funds to LP providers, creator, and sellout bonus.

Parameters:

  • collectionAddress: string

Returns:

Promise<void>;

Example:

// Check if sold out first
const info = await sdk.getCollectionInfo(collectionAddress);
const isSoldOut = info[5];

if (isSoldOut) {
  await sdk.moveLiquidity(collectionAddress);
  console.log("✅ Liquidity moved successfully!");
  console.log("Distribution:");
  console.log("  - 85% → LP Provider");
  console.log("  - 10% → LP Sellout Bonus");
  console.log("  - 5% → Creator");
} else {
  console.log("❌ Collection not sold out yet");
}

Distribution:

  • 85% to LP Provider
  • 10% to LP Sellout Bonus Pool
  • 5% to Collection Creator

Important:

  • Can only be called once per collection
  • Collection must be fully sold out
  • Transaction will revert if called prematurely
  • Emits LiquidityMoved event

Gas Cost: ~150-250k gas


buyCredit(params)

Purchases credits by sending ETH to the admin address. Credits can be used for platform features.

Parameters:

interface EthTransferParams {
  amount: string; // Amount in ETH (e.g., "0.1")
}

Returns:

Promise<string>; // Transaction hash

Example:

// Buy 0.5 ETH worth of credits
const txHash = await sdk.buyCredit({
  amount: "0.5",
});

console.log("Transaction hash:", txHash);
console.log("View on explorer:", `https://basescan.org/tx/${txHash}`);

// Wait for confirmation
const receipt = await provider.waitForTransaction(txHash);
console.log("Credits purchased! Confirmations:", receipt.confirmations);

Use Cases:

  • Premium features
  • Gas-less transactions
  • Platform credits

Note: The amount is automatically converted from ETH to wei internally.


claimReferralReward(userAddress, amount)

Claims referral rewards by transferring ETH from the reward wallet to a user. This method should be called by the backend/admin who has access to the reward wallet's private key.

⚠️ Important: The SDK signer must be the reward wallet, not the user's wallet. This is typically used in a backend service.

Parameters:

userAddress: string; // The address of the user claiming the reward
amount: string; // Amount in ETH (e.g., "0.1")

Returns:

Promise<string>; // Transaction hash

Example:

// Backend/Admin setup with reward wallet
const rewardWalletSigner = new ethers.Wallet(
  REWARD_WALLET_PRIVATE_KEY,
  provider
);

const adminSDK = new FlipmemeSDK(BlockchainType.ETHEREUM, PLATFORM.PROD, {
  signer: rewardWalletSigner, // Reward wallet signer, not user's
  chainId: 8453,
  provider,
});

// Claim referral reward for a user
const userAddress = "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb";
const rewardAmount = "0.05"; // 0.05 ETH

const txHash = await adminSDK.claimReferralReward(userAddress, rewardAmount);

console.log("Referral reward claimed!");
console.log("Transaction hash:", txHash);
console.log("View on BaseScan:", `https://basescan.org/tx/${txHash}`);

Flow:

  1. User earns referral rewards - Backend calculates rewards based on trading fees
  2. Team funds reward wallet - Manually add ETH to the designated reward wallet
  3. User requests claim - User initiates claim through your application
  4. Backend processes claim - Your backend calls this method with the reward wallet signer
  5. ETH transferred - Reward wallet sends ETH directly to user's address

Use Cases:

  • Referral commission payouts
  • Trading fee rebates
  • Affiliate rewards
  • Promotional incentives

Security Considerations:

  • The reward wallet private key should be securely stored (e.g., AWS Secrets Manager, HashiCorp Vault)
  • Implement rate limiting and claim verification in your backend
  • Keep reward wallet funded but with limited balance to minimize risk
  • Log all claim transactions for audit purposes
  • Consider implementing multi-signature for large reward wallets

Note: This does NOT interact with smart contracts or treasury - it's a simple ETH transfer from a team-controlled wallet to the user, providing maximum flexibility and minimal risk.


Types Reference

Core Types

// Blockchain selection
enum BlockchainType {
  SOLANA = "solana",
  ETHEREUM = "ethereum",
}

// Platform environment
enum PLATFORM {
  DEV = "Dev",
  STAGE = "Stage",
  PROD = "Prod",
}

// Purchase type for pricing
enum PurcahseType {
  BUY = "buy",
  SELL = "sell",
}

Configuration Types

interface EthereumConfig {
  signer?: ethers.Signer; // Wallet for signing transactions
  chainId: number; // Network chain ID (8453 for Base)
  provider: ethers.providers.BaseProvider; // RPC provider instance
}

Collection Types

interface CollectionParams {
  sessionId: string; // Unique identifier for this collection creation
  name: string; // Collection display name
  symbol?: string; // Token symbol (optional)
  tokenUri: string; // Collection metadata URI
  totalSupply: number; // Maximum number of NFTs
  premint?: number; // Number to pre-mint for creator (default: 0)
  startPrice?: string; // Starting price in wei (default: 10^15)
  endPrice?: string; // Ending price in wei (default: 10^16)
}

interface CreateCollectionResponse {
  collectionId: string; // Unique on-chain ID
  collectionAddress: string; // Deployed contract address
}

Trading Types

interface EthBuyParams {
  collectionAddress: string; // Collection contract address
  baseUri?: string; // Token metadata base URI (required if minting)
  amount: number; // Number of new NFTs to mint
  tokenIds: number[]; // Existing token IDs to buy from pool
}

interface EthSellParams {
  collectionAddress: string; // Collection contract address
  tokenIds: number[]; // Token IDs to sell
}

interface EthProfileSellParams {
  data: Record<string, EthSellData>; // Collection ID → sell data mapping
  slippage: number; // Not currently used (reserved)
}

interface EthSellData {
  tokenIds: number[]; // Token IDs to sell
  collectionId: string; // Collection ID (not address)
}

interface ConfirmResult {
  successCount: number; // Number of successful operations
  failedCount: number; // Number of failed operations
}

Utility Types

interface EthTransferParams {
  amount: string; // Amount in ETH (e.g., "0.1")
}

Constants & Configuration

Network Addresses

interface ETHAddresses {
  TREASURY: string; // Protocol treasury
  LP_SELL_OUT: string; // LP sellout bonus pool
  LP_PROVIDER: string; // LP provider address
  ROYALTY: string; // Royalty recipient
  FACTORY: string; // Factory contract address
  PROTOCOL_FEE_BPS: number; // Protocol fee in basis points (250 = 2.5%)
  ADMIN_FOR_CREDIT_BUY: string; // Credit purchase recipient
  REFERRAL_CLAIM: string; // Referral rewards address
}

Default Configuration (DEV)

const ETH_DEV = {
  FACTORY: "0xE9fda705f7cD9D5bf11cffF0997A9ef74927C834",
  TREASURY: "0x26ee601042126aA53fA212983f96C3571fab8e5E",
  LP_SELL_OUT: "0x19A1f2d12A7DbD5834787BB98373d93D41682db8",
  LP_PROVIDER: "0xc796E2c7fD16a8033D55fA61Ab575E2Cd27B4d47",
  ROYALTY: "0x9c8969323255a476BD5A249DBC9f091728dbD671",
  ADMIN_FOR_CREDIT_BUY: "0x63B3Cc8944B917AAc841429097F28be09AB636a7",
  REFERRAL_CLAIM: "0xaE1f8271458285b71b465e4aC00E23a21cD8aF42",
  PROTOCOL_FEE_BPS: 250, // 2.5%
};

Supported Networks

| Network | Chain ID | RPC URL | Explorer | | ---------------------- | -------- | ------------------------ | ---------------------------- | | Base Mainnet | 8453 | https://mainnet.base.org | https://basescan.org | | Base Sepolia (Testnet) | 84532 | https://sepolia.base.org | https://sepolia.basescan.org |


Advanced Usage

Price Monitoring System

class PriceMonitor {
  private sdk: FlipmemeSDK;
  private collectionAddress: string;

  constructor(sdk: FlipmemeSDK, collectionAddress: string) {
    this.sdk = sdk;
    this.collectionAddress = collectionAddress;
  }

  async getCurrentMetrics() {
    const [info, price, totalSupply, balance] = await Promise.all([
      this.sdk.getCollectionInfo(this.collectionAddress),
      this.sdk.calculatePrice(this.collectionAddress),
      this.sdk.totalSupply(this.collectionAddress),
      this.sdk.balanceOf(
        this.collectionAddress,
        await this.getSigner().getAddress()
      ),
    ]);

    return {
      maxSupply: info[3].toNumber(),
      currentMint: info[4].toNumber(),
      isSoldOut: info[5],
      currentPrice: ethers.utils.formatEther(price),
      totalSupply: parseInt(totalSupply),
      userBalance: parseInt(balance),
      progress: (info[4].toNumber() / info[3].toNumber()) * 100,
    };
  }

  async startMonitoring(intervalMs: number = 5000) {
    console.log("Starting price monitoring...");

    setInterval(async () => {
      const metrics = await this.getCurrentMetrics();
      console.log(`
        Progress: ${metrics.progress.toFixed(1)}%
        Price: ${metrics.currentPrice} ETH
        Minted: ${metrics.currentMint}/${metrics.maxSupply}
        Your Balance: ${metrics.userBalance}
      `);
    }, intervalMs);
  }

  private getSigner(): ethers.Signer {
    // Return your signer instance
    return this.sdk["ethereum"]?.["config"].signer!;
  }
}

// Usage
const monitor = new PriceMonitor(sdk, collectionAddress);
await monitor.startMonitoring(10000); // Update every 10 seconds

Batch NFT Operations

async function batchMintAndDistribute(
  sdk: FlipmemeSDK,
  collectionAddress: string,
  recipients: string[],
  baseUri: string
) {
  console.log(`Minting ${recipients.length} NFTs...`);

  // 1. Mint all NFTs to your address
  const mintResult = await sdk.buy({
    collectionAddress,
    baseUri,
    amount: recipients.length,
    tokenIds: [],
  });

  console.log(`Minted ${mintResult.successCount} NFTs`);

  // 2. Get the collection contract
  const collection = Collection__factory.connect(
    collectionAddress,
    sdk["ethereum"]!["config"].signer!
  );

  // 3. Get current total supply to determine token IDs
  const totalSupply = await sdk.totalSupply(collectionAddress);
  const firstTokenId = parseInt(totalSupply) - recipients.length;

  // 4. Transfer to recipients
  console.log("Distributing NFTs...");
  for (let i = 0; i < recipients.length; i++) {
    const tokenId = firstTokenId + i;
    const recipient = recipients[i];

    console.log(`Transferring token #${tokenId} to ${recipient}...`);
    const tx = await collection.transferFrom(
      await sdk["ethereum"]!["config"].signer!.getAddress(),
      recipient,
      tokenId
    );
    await tx.wait();
  }

  console.log("✅ All NFTs distributed!");
}

// Usage
await batchMintAndDistribute(
  sdk,
  collectionAddress,
  [
    "0x1111111111111111111111111111111111111111",
    "0x2222222222222222222222222222222222222222",
    "0x3333333333333333333333333333333333333333",
  ],
  "ipfs://QmYourTokens/"
);

Portfolio Management

interface PortfolioItem {
  collectionAddress: string;
  collectionId: string;
  tokenIds: number[];
  currentValue: string;
}

async function getPortfolio(
  sdk: FlipmemeSDK,
  collections: string[],
  owner: string
): Promise<PortfolioItem[]> {
  const portfolio: PortfolioItem[] = [];

  for (const collectionAddress of collections) {
    // Get collection info
    const info = await sdk.getCollectionInfo(collectionAddress);
    const collectionId = info[1].toString();
    const totalMinted = info[4].toNumber();

    // Find owned tokens
    const tokenIds: number[] = [];
    for (let i = 0; i < totalMinted; i++) {
      try {
        const tokenOwner = await sdk.ownerOf(collectionAddress, i);
        if (tokenOwner.toLowerCase() === owner.toLowerCase()) {
          tokenIds.push(i);
        }
      } catch {
        continue;
      }
    }

    if (tokenIds.length > 0) {
      // Calculate current value
      const value = await sdk.getTotalPrice(
        PurcahseType.SELL,
        collectionAddress,
        tokenIds.length
      );

      portfolio.push({
        collectionAddress,
        collectionId,
        tokenIds,
        currentValue: ethers.utils.formatEther(value),
      });
    }
  }

  return portfolio;
}

// Usage
const myPortfolio = await getPortfolio(
  sdk,
  [collection1, collection2, collection3],
  await signer.getAddress()
);

console.log("Your Portfolio:");
myPortfolio.forEach((item, idx) => {
  console.log(`\n${idx + 1}. Collection ${item.collectionId}`);
  console.log(`   NFTs owned: ${item.tokenIds.length}`);
  console.log(`   Current value: ${item.currentValue} ETH`);
  console.log(`   Token IDs: ${item.tokenIds.join(", ")}`);
});

Automated Trading Bot

class FlipBot {
  private sdk: FlipmemeSDK;
  private collectionAddress: string;
  private targetProfit: number; // in percentage

  constructor(
    sdk: FlipmemeSDK,
    collectionAddress: string,
    targetProfit: number = 10
  ) {
    this.sdk = sdk;
    this.collectionAddress = collectionAddress;
    this.targetProfit = targetProfit;
  }

  async checkArbitrage() {
    const currentPrice = await this.sdk.calculatePrice(this.collectionAddress);
    const info = await this.sdk.getCollectionInfo(this.collectionAddress);

    // Check if there are NFTs in the pool
    // (You'd need to add a method to check pool size)

    const buyPrice = await this.sdk.getTotalPrice(
      PurcahseType.BUY,
      this.collectionAddress,
      1
    );

    const sellPrice = await this.sdk.getTotalPrice(
      PurcahseType.SELL,
      this.collectionAddress,
      1
    );

    const buyPriceEth = parseFloat(ethers.utils.formatEther(buyPrice));
    const sellPriceEth = parseFloat(ethers.utils.formatEther(sellPrice));
    const profit = ((sellPriceEth - buyPriceEth) / buyPriceEth) * 100;

    console.log(`
      Buy Price: ${buyPriceEth.toFixed(6)} ETH
      Sell Price: ${sellPriceEth.toFixed(6)} ETH
      Potential Profit: ${profit.toFixed(2)}%
    `);

    return {
      buyPrice: buyPriceEth,
      sellPrice: sellPriceEth,
      profit,
      shouldTrade: profit >= this.targetProfit,
    };
  }

  async executeTrade() {
    const analysis = await this.checkArbitrage();

    if (analysis.shouldTrade) {
      console.log(
        `✅ Profit opportunity detected: ${analysis.profit.toFixed(2)}%`
      );
      console.log("Executing trade...");

      // Buy
      const buyResult = await this.sdk.buy({
        collectionAddress: this.collectionAddress,
        baseUri: "",
        amount: 0,
        tokenIds: [0], // You'd need to know available token IDs
      });

      console.log("Bought NFT");

      // Sell immediately
      const sellResult = await this.sdk.flipSell({
        collectionAddress: this.collectionAddress,
        tokenIds: [0],
      });

      console.log(`✅ Trade complete! Profit: ${analysis.profit.toFixed(2)}%`);
      return true;
    }

    return false;
  }

  async monitor(intervalMs: number = 10000) {
    console.log(`Starting bot with ${this.targetProfit}% profit target...`);

    setInterval(async () => {
      try {
        await this.executeTrade();
      } catch (error) {
        console.error("Trade failed:", error);
      }
    }, intervalMs);
  }
}

// Usage (use at your own risk!)
const bot = new FlipBot(sdk, collectionAddress, 15); // 15% profit target
await bot.monitor(5000); // Check every 5 seconds

Error Handling

Common Errors

Insufficient Funds

try {
  await sdk.buy({
    collectionAddress,
    baseUri: "ipfs://...",
    amount: 10,
    tokenIds: [],
  });
} catch (error) {
  if (error.code === "INSUFFICIENT_FUNDS") {
    console.error("You don't have enough ETH for this transaction");
    console.error(
      "Required:",
      ethers.utils.formatEther(error.transaction?.value || "0")
    );
  }
}

Collection Sold Out

try {
  await sdk.buy({
    /* ... */
  });
} catch (error) {
  if (
    error.message.includes("sold out") ||
    error.message.includes("max supply")
  ) {
    console.error("Collection is sold out!");

    // Try buying from pool instead
    await sdk.buy({
      collectionAddress,
      baseUri: "",
      amount: 0,
      tokenIds: [availableTokenId],
    });
  }
}

User Rejected Transaction

try {
  await sdk.createCollection({
    /* ... */
  });
} catch (error) {
  if (error.code === 4001 || error.code === "ACTION_REJECTED") {
    console.log("User rejected the transaction");
    // Show user-friendly message
  }
}

Comprehensive Error Handler

async function safeExecute<T>(
  operation: () => Promise<T>,
  operationName: string
): Promise<T | null> {
  try {
    console.log(`Executing ${operationName}...`);
    const result = await operation();
    console.log(`✅ ${operationName} successful`);
    return result;
  } catch (error: any) {
    console.error(`❌ ${operationName} failed:`);

    // Ethers errors
    if (error.code) {
      switch (error.code) {
        case "INSUFFICIENT_FUNDS":
          console.error("Insufficient funds for transaction");
          break;
        case "ACTION_REJECTED":
          console.error("User rejected transaction");
          break;
        case "UNPREDICTABLE_GAS_LIMIT":
          console.error("Cannot estimate gas - transaction may fail");
          break;
        case "NETWORK_ERROR":
          console.error("Network error - check your connection");
          break;
        default:
          console.error(`Error code: ${error.code}`);
      }
    }

    // Contract revert errors
    if (error.reason) {
      console.error("Contract error:", error.reason);
    }

    // Full error details
    console.error("Full error:", error.message);

    return null;
  }
}

// Usage
const result = await safeExecute(
  () =>
    sdk.buy({
      collectionAddress,
      baseUri: "ipfs://...",
      amount: 5,
      tokenIds: [],
    }),
  "NFT Purchase"
);

if (result) {
  console.log("Success:", result);
}

Retry Logic

async function withRetry<T>(
  operation: () => Promise<T>,
  maxRetries: number = 3,
  delayMs: number = 1000
): Promise<T> {
  let lastError: Error;

  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await operation();
    } catch (error: any) {
      lastError = error;
      console.log(`Attempt ${attempt} failed:`, error.message);

      // Don't retry user rejections
      if (error.code === 4001 || error.code === "ACTION_REJECTED") {
        throw error;
      }

      if (attempt < maxRetries) {
        console.log(`Retrying in ${delayMs}ms...`);
        await new Promise((resolve) => setTimeout(resolve, delayMs));
        delayMs *= 2; // Exponential backoff
      }
    }
  }

  throw lastError!;
}

// Usage
const result = await withRetry(
  () =>
    sdk.buy({
      /* ... */
    }),
  3,
  2000
);

Best Practices

1. Always Check Prices Before Buying

// ❌ Bad: Blind purchase
await sdk.buy({ collectionAddress, amount: 5, tokenIds: [], baseUri: "..." });

// ✅ Good: Check price first
const estimatedPrice = await sdk.getTotalPrice(
  PurcahseType.BUY,
  collectionAddress,
  5
);
console.log("This will cost:", ethers.utils.formatEther(estimatedPrice), "ETH");

const userConfirmed = await confirmWithUser(estimatedPrice);
if (userConfirmed) {
  await sdk.buy({ collectionAddress, amount: 5, tokenIds: [], baseUri: "..." });
}

2. Handle Collection State

// ✅ Check if collection is sold out before minting
const info = await sdk.getCollectionInfo(collectionAddress);
const remaining = info[3].sub(info[4]).toNumber();

if (remaining === 0) {
  console.log("Collection sold out! Buying from pool instead...");
  // Buy from liquidity pool
} else {
  console.log(`${remaining} NFTs remaining`);
  // Mint new NFTs
}

3. Use Environment Variables

// ✅ Good: Secure configuration
import dotenv from "dotenv";
dotenv.config();

const provider = new ethers.providers.JsonRpcProvider(process.env.RPC_URL);
const signer = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);

const sdk = new FlipmemeSDK(
  BlockchainType.ETHEREUM,
  process.env.NODE_ENV === "production" ? PLATFORM.PROD : PLATFORM.DEV,
  { signer, chainId: parseInt(process.env.CHAIN_ID!), provider }
);

4. Implement Proper Error Handling

// ✅ Comprehensive error handling
try {
  const result = await sdk.createCollection({
    name: "My Collection",
    symbol: "MC",
    totalSupply: 100,
    sessionId: `session-${Date.now()}`,
    tokenUri: "ipfs://...",
  });

  // Log success
  console.log("Collection created:", result.collectionAddress);

  // Store in database
  await database.saveCollection(result);
} catch (error: any) {
  // Log for debugging
  console.error("Collection creation failed:", error);

  // User-friendly message
  if (error.code === "INSUFFICIENT_FUNDS") {
    alert("You need more ETH to create a collection");
  } else if (error.code === "ACTION_REJECTED") {
    alert("Transaction was cancelled");
  } else {
    alert("Failed to create collection. Please try again.");
  }

  // Track error
  analytics.trackError("create_collection_failed", error);
}

5. Optimize Gas Usage

// ✅ Use profileSell for multiple collections
// Instead of:
await sdk.flipSell({ collectionAddress: addr1, tokenIds: [1, 2] });
await sdk.flipSell({ collectionAddress: addr2, tokenIds: [3, 4] });

// Do this (saves ~30% gas):
await sdk.profileSell({
  data: {
    [collectionId1]: { tokenIds: [1, 2], collectionId: collectionId1 },
    [collectionId2]: { tokenIds: [3, 4], collectionId: collectionId2 },
  },
  slippage: 0,
});

6. Monitor Transaction Status

async function buyWithConfirmation(sdk: FlipmemeSDK, params: EthBuyParams) {
  console.log("Initiating purchase...");

  // Start transaction
  const result = await sdk.buy(params);

  console.log("Transaction submitted, waiting for confirmation...");

  // Get transaction hash (would need to modify SDK to return this)
  // const txHash = result.transactionHash;

  // Wait for confirmations
  // const receipt = await provider.waitForTransaction(txHash, 2);

  console.log("✅ Confirmed!");
  return result;
}

7. Cache Collection Data

class CollectionCache {
  private cache = new Map<string, { data: any; timestamp: number }>();
  private ttl = 60000; // 1 minute

  async getCollectionInfo(sdk: FlipmemeSDK, address: string) {
    const cached = this.cache.get(address);

    if (cached && Date.now() - cached.timestamp < this.ttl) {
      return cached.data;
    }

    const data = await sdk.getCollectionInfo(address);
    this.cache.set(address, { data, timestamp: Date.now() });
    return data;
  }

  invalidate(address: string) {
    this.cache.delete(address);
  }

  clear() {
    this.cache.clear();
  }
}

// Usage
const cache = new CollectionCache();
const info = await cache.getCollectionInfo(sdk, collectionAddress);

8. Test on Testnet First

// ✅ Always test on testnet before mainnet
const TESTNET_CONFIG = {
  chainId: 84532, // Base Sepolia
  rpcUrl: "https://sepolia.base.org",
  explorer: "https://sepolia.basescan.org",
};

const MAINNET_CONFIG = {
  chainId: 8453, // Base Mainnet
  rpcUrl: "https://mainnet.base.org",
  explorer: "https://basescan.org",
};

const config =
  process.env.USE_TESTNET === "true" ? TESTNET_CONFIG : MAINNET_CONFIG;

Examples

Complete DApp Integration

import { ethers } from "ethers";
import {
  FlipmemeSDK,
  BlockchainType,
  PLATFORM,
  PurcahseType,
} from "flipmeme-sdk";

class FlipNFT {
  private sdk: FlipmemeSDK;
  private provider: ethers.providers.Web3Provider;
  private signer: ethers.Signer;

  async initialize() {
    // Connect to MetaMask
    if (!window.ethereum) {
      throw new Error("Please install MetaMask");
    }

    this.provider = new ethers.providers.Web3Provider(window.ethereum);
    await this.provider.send("eth_requestAccounts", []);
    this.signer = this.provider.getSigner();

    // Initialize SDK
    const network = await this.provider.getNetwork();
    this.sdk = new FlipmemeSDK(BlockchainType.ETHEREUM, PLATFORM.PROD, {
      signer: this.signer,
      chainId: network.chainId,
      provider: this.provider,
    });

    console.log("Connected:", await this.signer.getAddress());
  }

  async createCollection(params: {
    name: string;
    symbol: string;
    totalSupply: number;
    premint: number;
    metadataUri: string;
  }) {
    try {
      const { collectionId, collectionAddress } =
        await this.sdk.createCollection({
          name: params.name,
          symbol: params.symbol,
          totalSupply: params.totalSupply,
          premint: params.premint,
          sessionId: `create-${Date.now()}-${Math.random()}`,
          tokenUri: params.metadataUri,
          startPrice: ethers.utils.parseEther("0.001").toString(),
          endPrice: ethers.utils.parseEther("0.1").toString(),
        });

      console.log("✅ Collection created!");
      console.log("ID:", collectionId);
      console.log("Address:", collectionAddress);

      return { collectionId, collectionAddress };
    } catch (error) {
      console.error("Failed to create collection:", error);
      throw error;
    }
  }

  async buyNFTs(collectionAddress: string, amount: number, baseUri: string) {
    try {
      // Get price quote
      const totalPrice = await this.sdk.getTotalPrice(
        PurcahseType.BUY,
        collectionAddress,
        amount
      );

      console.log(
        `Buying ${amount} NFTs for ${ethers.utils.formatEther(totalPrice)} ETH`
      );

      // Execute purchase
      const result = await this.sdk.buy({
        collectionAddress,
        baseUri,
        amount,
        tokenIds: [],
      });

      console.log(`✅ Purchased ${result.successCount} NFTs`);
      return result;
    } catch (error) {
      console.error("Purchase failed:", error);
      throw error;
    }
  }

  async sellNFTs(collectionAddress: string, tokenIds: number[]) {
    try {
      // Get sell quote
      const totalPrice = await this.sdk.getTotalPrice(
        PurcahseType.SELL,
        collectionAddress,
        tokenIds.length
      );

      console.log(
        `Selling ${tokenIds.length} NFTs for ${ethers.utils.formatEther(
          totalPrice
        )} ETH`
      );

      // Execute sale
      const result = await this.sdk.flipSell({
        collectionAddress,
        tokenIds,
      });

      console.log(`✅ Sold ${result.successCount} NFTs`);
      return result;
    } catch (error) {
      console.error("Sale failed:", error);
      throw error;
    }
  }

  async getMyNFTs(collectionAddress: string): Promise<number[]> {
    const myAddress = await this.signer.getAddress();
    const balance = await this.sdk.balanceOf(collectionAddress, myAddress);
    const totalSupply = await this.sdk.totalSupply(collectionAddress);

    const myTokens: number[] = [];

    for (let i = 0; i < parseInt(totalSupply); i++) {
      try {
        const owner = await this.sdk.ownerOf(collectionAddress, i);
        if (owner.toLowerCase() === myAddress.toLowerCase()) {
          myTokens.push(i);
        }
      } catch {
        continue;
      }
    }

    return myTokens;
  }

  async getCollectionStats(collectionAddress: string) {
    const info = await this.sdk.getCollectionInfo(collectionAddress);
    const currentPrice = await this.sdk.calculatePrice(collectionAddress);

    return {
      creator: info[2],
      maxSupply: info[3].toNumber(),
      minted: info[4].toNumber(),
      remaining: info[3].sub(info[4]).toNumber(),
      isSoldOut: info[5],
      currentPrice: ethers.utils.formatEther(currentPrice),
      progress: (info[4].toNumber() / info[3].toNumber()) * 100,
    };
  }
}

// Usage
const app = new FlipNFT();
await app.initialize();

// Create collection
const { collectionAddress } = await app.createCollection({
  name: "Cool Cats",
  symbol: "COOL",
  totalSupply: 100,
  premint: 5,
  metadataUri: "ipfs://QmYourMetadata/",
});

// Buy NFTs
await app.buyNFTs(collectionAddress, 3, "ipfs://QmYourTokens/");

// Check stats
const stats = await app.getCollectionStats(collectionAddress);
console.log("Collection Stats:", stats);

// Get my NFTs
const myNFTs = await app.getMyNFTs(collectionAddress);
console.log("My NFTs:", myNFTs);

// Sell some
if (myNFTs.length > 0) {
  await app.sellNFTs(collectionAddress, myNFTs.slice(0, 2));
}

React Integration Example

// hooks/useFlipmeme.ts
import { useState, useEffect } from "react";
import { ethers } from "ethers";
import { FlipmemeSDK, BlockchainType, PLATFORM } from "flipmeme-sdk";

export function useFlipmeme() {
  const [sdk, setSdk] = useState<FlipmemeSDK | null>(null);
  const [isConnected, setIsConnected] = useState(false);
  const [address, setAddress] = useState<string>("");

  useEffect(() => {
    initializeSDK();
  }, []);

  async function initializeSDK() {
    if (!window.ethereum) return;

    try {
      const provider = new ethers.providers.Web3Provider(window.ethereum);
      await provider.send("eth_requestAccounts", []);
      const signer = provider.getSigner();
      const network = await provider.getNetwork();
      const userAddress = await signer.getAddress();

      const flipSDK = new FlipmemeSDK(BlockchainType.ETHEREUM, PLATFORM.PROD, {
        signer,
        chainId: network.chainId,
        provider,
      });

      setSdk(flipSDK);
      setIsConnected(true);
      setAddress(userAddress);
    } catch (error) {
      console.error("Failed to initialize SDK:", error);
    }
  }

  return { sdk, isConnected, address, initialize: initializeSDK };
}

// components/CollectionCard.tsx
import React, { useState, useEffect } from "react";
import { useFlipmeme } from "../hooks/useFlipmeme";

interface CollectionCardProps {
  collectionAddress: string;
}

export function CollectionCard({ collectionAddress }: CollectionCardProps) {
  const { sdk } = useFlipmeme();
  const [stats, setStats] = useState<any>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    loadStats();
  }, [sdk, collectionAddress]);

  async function loadStats() {
    if (!sdk) return;

    try {
      setLoading(true);
      const info = await sdk.getCollectionInfo(collectionAddress);
      const price = await sdk.calculatePrice(collectionAddress);

      setStats({
        minted: info[4].toNumber(),
        maxSupply: info[3].toNumber(),
        isSoldOut: info[5],
        currentPrice: ethers.utils.formatEther(price),
      });
    } catch (error) {
      console.error("Failed to load stats:", error);
    } finally {
      setLoading(false);
    }
  }

  if (loading) return <div>Loading...</div>;
  if (!stats) return <div>Error loading collection</div>;

  return (
    <div className="collection-card">
      <h3>Collection Stats</h3>
      <p>
        Minted: {stats.minted} / {stats.maxSupply}
      </p>
      <p>Current Price: {stats.currentPrice} ETH</p>
      {stats.isSoldOut && <p className="sold-out">SOLD OUT</p>}
      <button onClick={loadStats}>Refresh</button>
    </div>
  );
}

Changelog

Version 1.0.0

  • Initial EVM SDK release
  • Support for Base network
  • Core collection and trading functionality
  • Bonding curve pricing system
  • Multi-collection batch operations

Support & Resources

Documentation

  • GitHub: [flipmeme-sdk repository]
  • API Docs: This document
  • Examples: /demo/eth/ directory

Community

Security

For security concerns, please email [email protected]


License

[License Type] - See LICENSE file for details


Last Updated: October 6, 2025
SDK Version: 1.0.0
Compatible Networks: Ethereum, Base, EVM-compatible chains