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

@tomb-labs/staking

v0.7.16

Published

TypeScript SDK for Tomb Labs Staking Program

Readme

Tomb Labs Staking SDK

A TypeScript SDK for interacting with the Tomb Labs Staking Program on Solana. This SDK provides a comprehensive interface for managing NFT staking operations, including support for both standard and programmable NFTs.

Features

  • Comprehensive TypeScript Support: Fully typed API with detailed type definitions
  • Complete Program Interaction: Methods for all program instructions
  • NFT Compatibility: Support for both standard and programmable NFTs (pNFTs)
  • Enhanced Security: Built-in validation and error handling
  • PDA Management: Utility functions for program-derived address derivation
  • Account Definitions: Comprehensive account type definitions
  • Data Fetching: Efficient account data fetching utilities
  • React Integration: Ready for use with React applications
  • Transaction Building: Flexible transaction building for custom signing workflows
  • Wallet Compatibility: Works with any wallet adapter implementing the basic interface

Installation

npm install @tomb-labs/staking-sdk

or

yarn add @tomb-labs/staking-sdk

Quick Start

Using with a Custom Wallet

import { StakingClient } from '@tomb-labs/staking-sdk';
import { Connection, PublicKey, Transaction } from '@solana/web3.js';

// Your wallet must implement this interface
interface WalletAdapter {
  publicKey: PublicKey | null;
  signTransaction: <T extends Transaction>(tx: T) => Promise<T>;
  signAllTransactions: <T extends Transaction>(txs: T[]) => Promise<T[]>;
}

// Initialize connection and wallet
const connection = new Connection('https://api.mainnet-beta.solana.com');
const wallet: WalletAdapter = {
  // Your wallet implementation
};

// Create SDK client
const client = new StakingClient(connection, wallet);

Using with Solana Wallet Adapter

import { StakingClient } from '@tomb-labs/staking-sdk';
import { useConnection, useWallet } from '@solana/wallet-adapter-react';

// In your React component
const { connection } = useConnection();
const wallet = useWallet();

// Create SDK client - wallet-adapter-react implements the required interface
const client = new StakingClient(connection, wallet);

Using Transaction Builder Mode

import { StakingClient } from '@tomb-labs/staking-sdk';
import { Connection, Keypair } from '@solana/web3.js';

// Initialize connection and wallet
const connection = new Connection('https://api.mainnet-beta.solana.com');
const keypair = Keypair.generate();

// Create a simple wallet adapter
const wallet = {
  publicKey: keypair.publicKey,
  signTransaction: async tx => {
    tx.partialSign(keypair);
    return tx;
  },
  signAllTransactions: async txs => {
    return txs.map(tx => {
      tx.partialSign(keypair);
      return tx;
    });
  },
};

// Create SDK client
const client = new StakingClient(connection, wallet);

// Build transaction without signing
const tx = await client.projects.createProject({
  name: 'my-project',
  authority: wallet.publicKey,
  image_url: 'https://example.com/image.png',
  fees: {
    stakeFee: 1000000,
    unstakeFee: 1000000,
    claimFee: 1000000,
  },
  buildOnly: true, // This flag makes the method return a Transaction instead of sending it
});

// Now you can sign and send the transaction however you want
const signature = await wallet.signTransaction(tx);
const txid = await connection.sendRawTransaction(signature.serialize());

Usage Examples

Creating a Project

Projects are the top-level organizational unit in the staking program that can contain multiple pools.

try {
  // Direct signing mode (default)
  const signature = await client.projects.createProject({
    name: 'my-project',
    authority: wallet.publicKey,
    image_url: 'https://example.com/image.png',
    fees: {
      stakeFee: 1000000, // Fee in lamports (1 SOL = 1,000,000,000 lamports)
      unstakeFee: 1000000,
      claimFee: 1000000,
    },
  });

  console.log('Project created:', signature);
} catch (error) {
  if (error instanceof StakingError) {
    console.error('Staking error:', error.message);
  } else {
    console.error('Unexpected error:', error);
  }
}

Creating a Staking Pool

Staking pools are where users can stake their NFTs to earn rewards.

try {
  const signature = await client.pools.createPool({
    name: 'my-nft-pool',
    maxItemsStaked: 1000,
    collectionKey: collectionPublicKey, // Optional: NFT collection address
    requiresAuthorization: false,
    rewardMint: rewardTokenMintPublicKey,
    authority: wallet.publicKey,
    accrualRate: 10, // Tokens per day per NFT
    accrualPeriod: 'daily', // Options: 'hourly', 'daily', 'weekly'
  });

  console.log('Pool created:', signature);
} catch (error) {
  if (error instanceof StakingError) {
    console.error('Staking error:', error.message);
  } else {
    console.error('Unexpected error:', error);
  }
}

Staking an NFT

The SDK supports staking both standard NFTs and programmable NFTs.

try {
  // For standard NFTs
  const signature = await client.staker.stakeStandard({
    name: 'my-nft-pool',
    authority: wallet.publicKey,
    projectAuthority: projectAuthorityPublicKey,
    rewardMint: rewardMintPublicKey,
    nftMint: nftMintPublicKey,
  });

  console.log('NFT staked:', signature);
} catch (error) {
  if (error instanceof StakingError) {
    // Handle specific staking errors
    switch (error.message) {
      case ERRORS.POOL_INACTIVE:
        console.error('Pool is not active');
        break;
      case ERRORS.INVALID_COLLECTION:
        console.error('NFT is not from the required collection');
        break;
      default:
        console.error('Staking error:', error.message);
    }
  } else {
    console.error('Unexpected error:', error);
  }
}

Staking a Programmable NFT (pNFT)

try {
  // For programmable NFTs
  const signature = await client.staker.stakeProgrammable({
    name: 'my-nft-pool',
    authority: wallet.publicKey,
    projectAuthority: projectAuthorityPublicKey,
    rewardMint: rewardMintPublicKey,
    nftMint: nftMintPublicKey,
    // Additional parameters for programmable NFTs
    tokenStandard: 4, // TokenStandard.ProgrammableNonFungible
    ruleset: rulesetPublicKey, // Optional: ruleset for the pNFT
  });

  console.log('Programmable NFT staked:', signature);
} catch (error) {
  if (error instanceof StakingError) {
    console.error('Staking error:', error.message);
  } else {
    console.error('Unexpected error:', error);
  }
}

Claiming Rewards

try {
  const signature = await client.staker.claimReward({
    name: 'my-nft-pool',
    authority: wallet.publicKey,
    projectAuthority: projectAuthorityPublicKey,
    rewardMint: rewardMintPublicKey,
    stakedItem: stakedItemPublicKey, // The public key of the staked item account
  });

  console.log('Rewards claimed:', signature);
} catch (error) {
  if (error instanceof StakingError) {
    if (error.message === ERRORS.NO_REWARDS) {
      console.log('No rewards available to claim');
    } else {
      console.error('Claim error:', error.message);
    }
  }
}

Claiming All Rewards

To claim rewards for all staked items in a pool:

try {
  // First, fetch all staked items for this user
  const stakedItems = await client.fetcher.getAllStakedItemsForStaker({
    authority: wallet.publicKey,
    pool: poolPublicKey,
  });

  // Use the enhanced instructions to claim all rewards
  const transactions = await client.enhanced.claimAll(
    {
      name: 'my-nft-pool',
      authority: wallet.publicKey,
      projectAuthority: projectAuthorityPublicKey,
      rewardMint: rewardMintPublicKey,
    },
    stakedItems
  );

  // Send each transaction
  for (const tx of transactions) {
    const signature = await wallet.sendTransaction(tx, connection);
    console.log('Claimed rewards:', signature);
  }
} catch (error) {
  console.error('Error claiming rewards:', error);
}

Unstaking an NFT

try {
  const signature = await client.staker.unstake({
    name: 'my-nft-pool',
    authority: wallet.publicKey,
    projectAuthority: projectAuthorityPublicKey,
    rewardMint: rewardMintPublicKey,
    nftMint: nftMintPublicKey,
  });

  console.log('NFT unstaked:', signature);
} catch (error) {
  if (error instanceof StakingError) {
    if (error.message === ERRORS.LOCKUP_ACTIVE) {
      console.error('NFT is still in lockup period and cannot be unstaked yet');
    } else {
      console.error('Unstake error:', error.message);
    }
  }
}

Account Data Fetching

The SDK provides a dedicated Fetcher class for efficient account data retrieval:

// Access the fetcher
const fetcher = client.fetcher;

// Get global state and fees
const globalState = await fetcher.getGlobalState();
const fees = await fetcher.getGlobalFees();

// Get project information
const project = await fetcher.getProjectState({
  authority: authorityPublicKey,
});
const allProjects = await fetcher.getAllProjects();

// Get pool information
const pool = await fetcher.getPoolState({
  authority: authorityPublicKey,
  name: 'my-nft-pool',
  rewardMint: rewardMintPublicKey,
});
const projectPools = await fetcher.getAllPoolsForProject({
  authority: authorityPublicKey,
});

// Get staker information
const staker = await fetcher.getStakerState({
  authority: wallet.publicKey,
  pool: poolPublicKey,
});
const allStakers = await fetcher.getAllStakersForPool({
  pda: poolPublicKey,
});

// Get staked item information
const stakedItems = await fetcher.getAllStakedItemsForStaker({
  authority: wallet.publicKey,
  pool: poolPublicKey,
});

Error Handling

The SDK provides a standardized error system to handle common failures:

import { StakingError, ERRORS } from '@tomb-labs/staking-sdk';

try {
  // SDK operation
} catch (error) {
  if (error instanceof StakingError) {
    // Handle known staking errors
    switch (error.message) {
      case ERRORS.POOL_INACTIVE:
        console.error('Pool is not active');
        break;
      case ERRORS.POOL_FULL:
        console.error('Pool has reached maximum capacity');
        break;
      case ERRORS.INVALID_COLLECTION:
        console.error('NFT is not from the required collection');
        break;
      case ERRORS.NO_REWARDS:
        console.error('No rewards available to claim');
        break;
      case ERRORS.LOCKUP_ACTIVE:
        console.error('NFT is still in lockup period');
        break;
      case ERRORS.COOLDOWN_ACTIVE:
        console.error('Action is on cooldown');
        break;
      default:
        console.error('Staking error:', error.message);
    }
  } else {
    // Handle unexpected errors
    console.error('Unexpected error:', error);
  }
}

Advanced Usage

Using Enhanced Instructions

The SDK provides enhanced instructions that handle common operations with improved convenience:

// Get the enhanced instructions
const enhanced = client.enhanced;

// Stake an NFT with automatic staker initialization
const tx = await enhanced.stakeStandard({
  name: 'my-nft-pool',
  authority: wallet.publicKey,
  projectAuthority: projectAuthorityPublicKey,
  rewardMint: rewardMintPublicKey,
  nftMint: nftMintPublicKey,
});

// Result is a transaction that will automatically initialize the staker account if needed
const signature = await wallet.sendTransaction(tx, connection);

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

For support or questions, please open an issue on the GitHub repository.