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

@feyprotocol/sdk

v1.0.5

Published

TypeScript SDK for interacting with the FEY Protocol on Base. Supports both direct client usage (server-side or vanilla JS) and React hooks (built on TanStack Query).

Readme

@feyprotocol/sdk

TypeScript SDK for interacting with the FEY Protocol on Base. Supports both direct client usage (server-side or vanilla JS) and React hooks (built on TanStack Query).

Installation

npm install @feyprotocol/sdk
# or
yarn add @feyprotocol/sdk
# or
bun add @feyprotocol/sdk

Peer Dependencies

The SDK requires the following peer dependencies:

{
  "viem": "^2.x",
  "wagmi": "^2.x",
  "@tanstack/react-query": "^5.x",
  "react": "^18.x || ^19.x"
}

Note: If you're only using the vanilla JS client (not React hooks), you only need viem.


Quick Start

Vanilla JS / Server-side

import { createClient } from "@feyprotocol/sdk";
import { createPublicClient, http } from "viem";
import { base } from "viem/chains";

// Create a viem public client
const publicClient = createPublicClient({
  chain: base,
  transport: http(),
});

// Create the FEY client
const fey = createClient({
  publicClient,
  app: { name: "MyApp" },
  api: { key: "your-apy-key" },
});

// Fetch a token
const token = await fey.tokens.find({ id: "0x..." });
console.log(token?.name, token?.symbol);

React (with wagmi)

import { WagmiProvider } from "wagmi";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { FeyProvider, useFindToken } from "@feyprotocol/sdk";

const queryClient = new QueryClient();

function App() {
  return (
    <WagmiProvider config={wagmiConfig}>
      <QueryClientProvider client={queryClient}>
        <FeyProvider config={{ app: { name: "MyApp" }, api: { url: "https://fey.money/api" } }}>
          <TokenDisplay />
        </FeyProvider>
      </QueryClientProvider>
    </WagmiProvider>
  );
}

function TokenDisplay() {
  const { data: token, isLoading } = useFindToken({ id: "0x..." });

  if (isLoading) return <div>Loading...</div>;
  return <div>{token?.name} ({token?.symbol})</div>;
}

Core Client API

The createClient function creates a FeyClient instance with namespaced methods for all protocol operations.

createClient(params)

import { createClient } from "@feyprotocol/sdk";

const client = createClient({
  // Option 1: Pass clients directly
  publicClient: viemPublicClient,
  walletClient: viemWalletClient, // optional, required for write operations

  // Option 2: Pass getters (useful for dynamic clients)
  // getPublicClient: () => publicClient,
  // getWalletClient: () => walletClient,

  // App metadata
  app: { name: "MyApp" },

  // API configuration
  api: {
    // url: "https://fey.money/api", (optional override)
    key: "your-api-key",
  },
});

Client Namespaces

client.users

| Method | Description | |--------|-------------| | find({ address }) | Fetch user profile by wallet address | | list({ limit?, cursor? }) | List users with pagination |

client.balances

| Method | Description | |--------|-------------| | find({ accountAddress, tokenAddress }) | Fetch token balance for a specific account | | list({ accountAddress, limit?, cursor? }) | List token balances for an account | | search({ accountAddress, query }) | Search token balances by query |

client.ceremonies

| Method | Description | |--------|-------------| | find({ id }) | Fetch ceremony details by ID | | list({ ids }) | Fetch multiple ceremonies by IDs | | search({ query?, stage?, limit?, offset?, sort?, filter? }) | Search ceremonies with filters | | participants({ ceremonyId, limit?, cursor? }) | Fetch ceremony participants | | create(params) | Create a new ceremony (community raise) | | update({ ceremonyId, set }) | Update ceremony configuration | | start({ ceremonyId }) | Start accepting contributions | | complete({ ceremonyId }) | Complete ceremony and deploy token | | cancel({ ceremonyId }) | Cancel ceremony and refund contributors | | simulate({ launchpad, goal, founderBuysEth?, treasuryReserveEth? }) | Preview token allocations |

client.tokens

| Method | Description | |--------|-------------| | find({ id }) | Fetch token details by address | | list({ ids }) | Fetch multiple tokens by addresses | | search({ query?, stage?, limit?, offset?, sort?, filter? }) | Search tokens with filters | | create(params) | Create a new token (instant launch) | | simulate({ founderBuy }) | Preview token launch allocations |

client.prices

| Method | Description | |--------|-------------| | find({ id }) | Fetch current price for a token | | list({ ids }) | Fetch prices for multiple tokens |

client.fees

| Method | Description | |--------|-------------| | find({ id }) | Fetch accumulated fees for a token |

client.tickets

| Method | Description | |--------|-------------| | find({ ceremonyId, accountAddress }) | Fetch contribution ticket for a ceremony |

client.vaults

| Method | Description | |--------|-------------| | find() | Fetch FEY staking vault details |

client.launchpads

| Method | Description | |--------|-------------| | find({ id }) | Fetch launchpad configuration | | search() | List all available launchpads |

client.whitelists

| Method | Description | |--------|-------------| | find({ ceremonyId }) | Fetch whitelist for a ceremony | | preview({ sources }) | Preview addresses in a whitelist | | generate({ sources, customAddresses }) | Generate merkle root from sources | | verify({ ceremonyId, address }) | Verify if address is whitelisted |

Available Sources

| Source | Key | ID | Input | Description | |--------|-----|-----|-------|-------------| | Farcaster Followers | farcaster | followers | { username: string } | Pull verified addresses from a Farcaster user's followers | | FEY Stakers | fey | stakers | { minStaked: number } | List of FEY wallets that have staked at least the specified amount |


React Hooks

All hooks are built on TanStack Query and follow its patterns. They require FeyProvider as an ancestor.

Provider Setup

import { FeyProvider, useFeyClient } from "@feyprotocol/sdk";

// FeyProvider must be inside WagmiProvider
<FeyProvider config={{ app: { name: "MyApp" }, api: { key: "your-api-key" } }}>
  {children}
</FeyProvider>

// Access the client directly
function MyComponent() {
  const { ready, client } = useFeyClient();
  // ready is true when public client is available
}

Query Hooks

Query hooks use useQuery and return standard TanStack Query result objects.

Tokens

import { useFindToken, useListTokens, useSearchTokens } from "@feyprotocol/sdk";

// Fetch single token
const { data, isLoading, error } = useFindToken({ id: "0x..." });

// Fetch multiple tokens
const { data } = useListTokens({ ids: ["0x...", "0x..."] });

// Search tokens
const { data } = useSearchTokens({
  query: "FEY",
  stage: "deployed", // or "ceremony"
  limit: 10,
  sort: { by: "market-cap", direction: "desc" },
});

Ceremonies

import {
  useFindCeremony,
  useListCeremonies,
  useSearchCeremonies,
  useCeremonyParticipants,
} from "@feyprotocol/sdk";

const { data: ceremony } = useFindCeremony({ id: 123 });
const { data: ceremonies } = useListCeremonies({ ids: [1, 2, 3] });
const { data: participants } = useCeremonyParticipants({ ceremonyId: 123 });

Balances

import { useFindBalance, useListBalances, useSearchBalances } from "@feyprotocol/sdk";

const { data: balance } = useFindBalance({
  accountAddress: "0x...",
  tokenAddress: "0x...",
});

const { data: balances } = useListBalances({ accountAddress: "0x..." });

Prices

import { useFindPrice, useListPrices } from "@feyprotocol/sdk";

const { data: price } = useFindPrice({ id: "0x..." });
const { data: prices } = useListPrices({ ids: ["0x...", "0x..."] });

Other Query Hooks

import {
  useFindUser,
  useListUsers,
  useFindFee,
  useFindTicket,
  useFindVault,
  useFindLaunchpad,
  useSearchLaunchpads,
  useFindWhitelist,
  usePreviewWhitelist,
  useVerifyWhitelist,
} from "@feyprotocol/sdk";

Mutation Hooks

Mutation hooks use useMutation and return standard TanStack Query mutation objects.

Token Creation

import { useCreateToken, useSimulateToken } from "@feyprotocol/sdk";

function CreateToken() {
  const { mutateAsync: createToken, isPending } = useCreateToken();

  const handleCreate = async () => {
    const { hash, predictedAddress } = await createToken({
      name: "My Token",
      symbol: "MTK",
      image: "ipfs://...",
      rewards: [
        { recipient: "0x...", bps: 10000 }, // 100% to single recipient
      ],
      founderBuy: { ethAmount: 0.1, recipient: "0x..." }, // optional
    });
  };
}

Ceremony Management

import {
  useCreateCeremony,
  useUpdateCeremony,
  useStartCeremony,
  useCompleteCeremony,
  useCancelCeremony,
  useSimulateCeremony,
} from "@feyprotocol/sdk";

function CreateCeremony() {
  const { mutateAsync: createCeremony } = useCreateCeremony();

  const handleCreate = async () => {
    const hash = await createCeremony({
      name: "My Token",
      symbol: "MTK",
      image: "ipfs://...",
      launchpad: "fey", // or "clanker"
      goal: 1.0, // ETH
      rewards: [{ recipient: "0x...", bps: 10000 }],
      // Optional fields:
      description: "Token description",
      minContribution: 0.01,
      maxContribution: 0.5,
      founderAllocations: [{ ethAmount: 0.1, recipient: "0x..." }],
      treasury: { recipient: "0x...", ethAmount: 0.1 },
      whitelistRoot: "0x...",
    });
  };
}

Whitelist Generation

import { useGenerateWhitelist, usePreviewWhitelist } from "@feyprotocol/sdk";

function WhitelistManager() {
  const { mutateAsync: generateWhitelist } = useGenerateWhitelist();

  const handleGenerate = async () => {
    const merkleRoot = await generateWhitelist({
      sources: [
        { id: "followers", key: "farcaster", input: { username: "feyprotocol" } },
      ],
      customAddresses: ["0x...", "0x..."],
    });
  };
}

Types

All entity types are exported for TypeScript usage.

Token

import type { Token } from "@feyprotocol/sdk";

interface Token {
  stage: "launched" | "funding" | "deploying" | "cancelled";
  tokenAddress: string | null;
  ceremonyId: number | null;
  launchpad: Launchpad;
  name: string;
  symbol: string;
  image: string;
  description: string;
  decimals: number;
  totalSupply: number;
  createdAt: Date;
  admin: string;
  totalHolders: number;
  socials: {
    website: string | null;
    twitter: string | null;
    farcaster: string | null;
  };
}

Ceremony

import type { Ceremony } from "@feyprotocol/sdk";

interface Ceremony {
  id: number;
  tokenAddress: string | null;
  name: string;
  symbol: string;
  image: string;
  description: string;
  launchpad: Launchpad;
  admin: string;
  createdAt: Date;
  status: "funding" | "started" | "completed" | "cancelled";
  raise: {
    goal: TokenAmount;
    current: TokenAmount;
    percentage: number;
    ticket: { min: TokenAmount; max: TokenAmount };
  };
  founderAllocations: Array<{
    accountAddress: string;
    allocationIndex: number;
    amount: TokenAmount;
  }>;
  bond: TokenAmount;
  whitelistRoot: string;
  totalParticipants: number;
  reserveEth: TokenAmount;
  socials: { website: string | null; twitter: string | null; farcaster: string | null };
}

Balance

import type { Balance } from "@feyprotocol/sdk";

interface Balance {
  accountAddress: string;
  tokenAddress: string;
  amount: { unstaked: TokenAmount; staked: TokenAmount };
  percentageTotalSupply: number;
  percentageHoldingsStaked: number;
}

Price

import type { Price } from "@feyprotocol/sdk";

interface Price {
  id: string;
  price: number | null;
  priceChange: { h1: number | null; h6: number | null; h24: number | null };
  marketCap: number | null;
  volume: { h24: number | null };
  topPool: string | null;
  liquidityUsd: number | null;
}

Contract ABIs

ABIs are exported for direct contract interaction with viem.

import {
  FeyFactoryAbi,    // Token factory - deploy tokens
  TGCSAbi,          // Token Generation Ceremony System
  XFeyVaultAbi,     // FEY staking vault
  FeyFeeLockerAbi,  // Fee distribution contract
  FeyTokenAbi,      // FEY token contract
} from "@feyprotocol/sdk";

// Example: Read from contract
import { readContract } from "viem/actions";

const totalStaked = await readContract(publicClient, {
  address: contracts.XFeyVault[base.id].address,
  abi: XFeyVaultAbi,
  functionName: "totalAssets",
});

Configuration

Contract Addresses

import { contracts, supportedChains, type SupportedChain } from "@feyprotocol/sdk";

// Access contract addresses per chain
contracts.FeyFactory[8453].address;      // Base mainnet
contracts.FeyFactory[84532].address;     // Base Sepolia

// Available contracts:
// - WETH
// - FeeRecipient
// - FeyFactory
// - FeyToken
// - XFeyVault
// - FeyFeeLocker
// - FeyLPLocker
// - TGCS
// - FeyUniswapPoolManager
// - FeyMevModule
// - FeyDevBuyExtension
// - FeyStaticFeeHook
// - ClankerFactory
// - ClankerStaticFeeHookV2
// - ClankerDynamicFeeHookV2
// - ClankerLPLocker
// - ClankerMevModule

Supported Chains

import { supportedChains, type SupportedChain } from "@feyprotocol/sdk";

// supportedChains = [base, baseSepolia]

Launchpads

import { launchpads } from "@feyprotocol/sdk";

// launchpads[chainId] returns available launchpad configs
// Each launchpad has: { id, name, image, modes }

Constants

Protocol constants for calculations and configurations.

import {
  TARGET_MARKET_CAP_USD,      // 32,000 - Target market cap in USD
  RANGE_WIDTH_TICKS,          // 110,400 - Uniswap V4 range width
  TICK_SPACING,               // 200 - Uniswap V4 tick spacing
  FEY_FEE_PPM,                // 10,000 (1%) - FEY token fee
  PAIRED_FEE_PPM,             // 10,000 (1%) - Paired token fee
  DYNAMIC_FEE_FLAG,           // 0x800000 - Dynamic fee hook flag
  CEREMONY_PROTOCOL_FEE_BPS,  // 250 (2.5%) - Protocol fee on ceremonies
  MAX_TREASURY_RESERVE_ETH_BPS, // 5,000 (50%) - Max treasury reserve
} from "@feyprotocol/sdk";

Examples

Fetching Token Data

const fey = createClient({ publicClient, api: { url: "https://fey.money/api" } });

// Get token details
const token = await fey.tokens.find({ id: "0xD09cf0982A32DD6856e12d6BF2F08A822eA5D91D" });
console.log(`${token?.name} (${token?.symbol})`);
console.log(`Stage: ${token?.stage}`);
console.log(`Holders: ${token?.totalHolders}`);

// Get price
const price = await fey.prices.find({ id: token?.tokenAddress! });
console.log(`Price: $${price?.price}`);
console.log(`24h Change: ${price?.priceChange.h24}%`);

Creating a Token (Instant Launch)

const { hash, predictedAddress } = await fey.tokens.create({
  name: "My Token",
  symbol: "MTK",
  image: "ipfs://QmYourImageHash",
  rewards: [
    { recipient: "0xCreator...", bps: 8000 },  // 80% to creator
    { recipient: "0xTreasury...", bps: 2000 }, // 20% to treasury
  ],
  founderBuy: {
    ethAmount: 0.5,
    recipient: "0xCreator...",
  },
  metadata: {
    description: "My awesome token",
    socials: {
      twitter: "mytoken",
      website: "https://mytoken.com",
    },
  },
});

console.log(`TX: ${hash}`);
console.log(`Token will be at: ${predictedAddress}`);

Creating a Ceremony (Community Raise)

// First, simulate to preview allocations
const simulation = await fey.ceremonies.simulate({
  launchpad: "fey",
  goal: 2.0, // 2 ETH
  founderBuysEth: [0.5], // Founder buys 0.5 ETH worth
  treasuryReserveEth: 0.2,
});

console.log(`Projected MCap: $${simulation?.mcapUsd}`);
console.log(`Community allocation: ${simulation?.allocations.community.percentage}%`);

// Create the ceremony
const hash = await fey.ceremonies.create({
  name: "Community Token",
  symbol: "COM",
  image: "ipfs://...",
  launchpad: "fey",
  goal: 2.0,
  rewards: [{ recipient: "0xCreator...", bps: 10000 }],
  minContribution: 0.01,
  maxContribution: 1.0,
  founderAllocations: [{ ethAmount: 0.5, recipient: "0xFounder..." }],
  treasury: { recipient: "0xTreasury...", ethAmount: 0.2 },
});

Managing Whitelists

// Preview whitelist sources
const preview = await fey.whitelists.preview({
  sources: [
    {
      id: "followers",
      key: "farcaster",
      input: { username: "feyprotocol" },
    },
  ],
});

console.log(`Total addresses: ${preview.totalAddresses}`);

// Generate merkle root
const merkleRoot = await fey.whitelists.generate({
  sources: preview.sources,
  customAddresses: ["0xABC...", "0x123..."],
});

// Use in ceremony creation
await fey.ceremonies.create({
  // ... other params
  whitelistRoot: merkleRoot,
});

// Verify an address
const verification = await fey.whitelists.verify({
  ceremonyId: 123,
  address: "0xUser...",
});

if (verification.verified) {
  console.log("Address is whitelisted with proof:", verification.proof);
}