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

delegate-framework

v1.0.28

Published

A TypeScript framework for building robust, production-ready blockchain workflows with comprehensive error handling, logging, and testing. Maintained by delegate.fun

Downloads

192

Readme

Delegate Framework

A TypeScript framework for building robust, production-ready blockchain workflows with comprehensive error handling, logging, and testing. Maintained by delegate.fun.

Features

  • Solana RPC Clients: Production-ready Helius and SPL clients with retry logic, timeouts, and error handling
  • Error Handling: Modular error handling utilities for consistent error management across your application
  • TypeScript Support: Full type safety with comprehensive interfaces and type definitions
  • Logging: Built-in logging support with customizable loggers
  • Testing: Comprehensive test suite with mocking and edge case coverage
  • Configuration: Flexible configuration management with sensible defaults
npm install delegate-framework
# or
pnpm add delegate-framework
# or
yarn add delegate-framework

Quick Start

Helius RPC Client

import { HeliusClient } from 'delegate-framework';
import { PublicKey } from '@solana/web3.js';

// Create a Helius client
const client = new HeliusClient({
  apiKey: 'your-helius-api-key',
  timeout: 30000,
  retries: 3,
});

// Get account balance
const publicKey = new PublicKey('11111111111111111111111111111111');
const balance = await client.getBalance(publicKey);
console.log('Balance:', balance);

// Get account information
const accountInfo = await client.getAccountInfo(publicKey, 'base64');

// Get account information with Metaplex metadata parsing
const metadata = await client.getAccountInfo(publicKey, { 
  parseMetaplexMetadata: true,
  includeOffChainMetadata: true 
});
console.log('NFT Name:', metadata.name);
console.log('Creators:', metadata.creators);

// Get recent blockhash
const blockhash = await client.getRecentBlockhash('confirmed');

// Get transaction details
const transaction = await client.getTransaction('signature-here');

// Get current slot
const slot = await client.getSlot('confirmed');

// Send native SOL transfer
const signature = await client.sendNativeTransfer(
  keypair, // Use keypair directly as from parameter
  new PublicKey('to-wallet-address'),
  1000000 // 0.001 SOL in lamports
);
console.log('Transfer signature:', signature);

// Send SPL token transfer
const tokenSignature = await client.sendTokenTransfer(
  new PublicKey('to-token-account'),
  keypair, // Use keypair directly as owner parameter
  1000000, // amount
  new PublicKey('token-mint-address')
);
console.log('Token transfer signature:', tokenSignature);

// Get comprehensive asset data for an NFT or token
const assetId = '11111111111111111111111111111111'; // Mint address
const assetData = await client.getAsset(assetId);
console.log('Asset data:', assetData);

SPL Client for Priority Fees

import { SplClient } from 'delegate-framework';
import { Connection, PublicKey } from '@solana/web3.js';

// Create an SPL client
const connection = new Connection('https://api.mainnet-beta.solana.com');
const client = new SplClient({
  connection,
  programId: new PublicKey('your-program-id'),
  timeout: 30000,
  retries: 3,
  percentile: 0.95, // 95th percentile
  defaultCuPrice: 0.1,
});

// Get priority fee based on recent network activity
const priorityFee = await client.getPriorityFee();
console.log('Priority fee:', priorityFee);

Error Handling Utilities

import { throwError, getErrorMessage, isErrorLike } from 'delegate-framework';

// Throw errors with proper type checking
if (data.error) {
  throwError(data.error, 'API Error');
}

// Extract error messages safely
const message = getErrorMessage(someError);

// Check if value is error-like
if (isErrorLike(response.error)) {
  console.log(response.error.message);
}

Custom Logging

import { Logger } from 'delegate-framework';

class CustomLogger implements Logger {
  debug(message: string, data?: any) {
    console.log(`[DEBUG] ${message}`, data);
  }
  
  info(message: string, data?: any) {
    console.log(`[INFO] ${message}`, data);
  }
  
  warn(message: string, data?: any) {
    console.warn(`[WARN] ${message}`, data);
  }
  
  error(message: string, data?: any) {
    console.error(`[ERROR] ${message}`, data);
  }
}

// Use custom logger
const client = new HeliusClient({
  apiKey: 'your-api-key',
  logger: new CustomLogger(),
});

API Reference

HeliusClient

Constructor

new HeliusClient(config: HeliusConfig)

Configuration

interface HeliusConfig {
  apiKey: string;
  rpcUrl?: string;        // Default: "https://mainnet.helius-rpc.com"
  timeout?: number;       // Default: 30000ms
  retries?: number;       // Default: 3
  logger?: Logger;        // Optional custom logger
}

Methods

  • getBalance(publicKey: PublicKey): Promise<number>
  • getAccountInfo(publicKey: PublicKey, encodingOrOptions?: 'base64' | 'base58' | GetAccountInfoOptions): Promise<any> - Get account info with optional Metaplex metadata parsing
  • getTransaction(signature: string, commitment?: 'processed' | 'confirmed' | 'finalized'): Promise<any>
  • getAsset(assetId: string): Promise<any> - Get comprehensive asset data for any Solana NFT or digital asset
  • getRecentBlockhash(commitment?: 'processed' | 'confirmed' | 'finalized'): Promise<any>
  • getSlot(commitment?: 'processed' | 'confirmed' | 'finalized'): Promise<number>
  • getClusterNodes(): Promise<any[]>
  • getVersion(): Promise<any>
  • sendTransaction(transaction: Transaction, options?: SendTransactionOptions): Promise<string>
  • sendNativeTransfer(from: Keypair, to: PublicKey, amount: number, options?: SendTransactionOptions): Promise<string> - Send native SOL transfer
  • sendTokenTransfer(to: PublicKey, owner: Keypair, amount: number, mint: PublicKey, options?: SendTransactionOptions): Promise<string> - Send SPL token transfer

SplClient

Constructor

new SplClient(config: SplConfig)

Configuration

interface SplConfig {
  connection: Connection;
  programId: PublicKey;
  timeout?: number;       // Default: 30000ms
  retries?: number;       // Default: 3
  logger?: Logger;        // Optional custom logger
  percentile?: number;    // Default: 0.9999999 (99.99999th percentile)
  defaultCuPrice?: number; // Default: 0.1
}

Methods

  • getPriorityFee(): Promise<number>

Error Handling Utilities

throwError(error: unknown, context?: string): never

Throws an error with proper type checking and handling.

getErrorMessage(error: unknown): string

Safely extracts error message from various error types.

isErrorLike(value: unknown): value is { message: string }

Type guard for error-like objects.

createStandardError(error: unknown, defaultMessage?: string): Error

Creates a standardized Error object from various input types.

Configuration

Default Values

| Setting | HeliusClient | SplClient | Description | |---------|--------------|-----------|-------------| | Timeout | 30,000ms | 30,000ms | Request timeout | | Retries | 3 | 3 | Number of retry attempts | | RPC URL | Helius Mainnet | - | RPC endpoint | | Percentile | - | 99.99999% | Fee calculation percentile | | Default CU Price | - | 0.1 | Default compute unit price |

Environment Variables

HELIUS_API_KEY=your-api-key
HELIUS_RPC_URL=https://mainnet.helius-rpc.com

Error Handling

The framework provides robust error handling with:

  • Automatic retries with exponential backoff
  • Timeout handling to prevent hanging requests
  • Network error detection and recovery
  • API error handling with proper error messages
  • Type-safe error utilities for consistent error management

Error Types

  • Network Errors: Connection failures, timeouts
  • API Errors: JSON-RPC errors from Solana nodes
  • Validation Errors: Invalid parameters or responses
  • Configuration Errors: Missing or invalid configuration

Testing

The framework includes comprehensive tests covering:

  • All client methods and configurations
  • Error handling and retry logic
  • Timeout scenarios
  • Edge cases and invalid inputs
  • Logging functionality

Run tests:

pnpm test

Development

Building

pnpm build

Linting

pnpm lint

Formatting

pnpm format

Type Checking

pnpm type-check

Examples

Complete Transaction Flow

import { HeliusClient, SplClient } from 'delegate-framework';
import { Connection, Transaction, PublicKey } from '@solana/web3.js';

async function sendTransactionWithPriorityFee() {
  // Setup clients
  const connection = new Connection('https://api.mainnet-beta.solana.com');
  const heliusClient = new HeliusClient({ apiKey: 'your-api-key' });
  const splClient = new SplClient({ 
    connection, 
    programId: new PublicKey('your-program-id') 
  });

  // Get priority fee
  const priorityFee = await splClient.getPriorityFee();
  
  // Create and send transaction
  const transaction = new Transaction();
  // ... add instructions to transaction
  
  const signature = await heliusClient.sendTransaction(transaction, {
    skipPreflight: false,
    preflightCommitment: 'confirmed',
  });
  
  console.log('Transaction sent:', signature);
}

Token Transfer Examples

import { HeliusClient } from 'delegate-framework';
import { PublicKey, Keypair } from '@solana/web3.js';

async function performTransfers() {
  const client = new HeliusClient({ apiKey: 'your-api-key' });
  
  // Create or load your keypair
  const keypair = Keypair.fromSecretKey(/* your secret key bytes */);
  // Or load from environment: Keypair.fromSecretKey(Buffer.from(process.env.PRIVATE_KEY, 'base64'));
  
  // Send native SOL transfer
  const solSignature = await client.sendNativeTransfer(
    keypair, // Use keypair directly as from parameter
    new PublicKey('22222222222222222222222222222222'), // to
    1000000, // 0.001 SOL in lamports
    {
      skipPreflight: false,
      preflightCommitment: 'confirmed'
    }
  );
  console.log('SOL transfer:', solSignature);
  
  // Send SPL token transfer (e.g., USDC)
  const tokenSignature = await client.sendTokenTransfer(
    new PublicKey('44444444444444444444444444444444'), // to token account
    keypair, // Use keypair directly as owner parameter
    1000000, // amount (1 USDC = 1,000,000 with 6 decimals)
    new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'), // USDC mint
    {
      skipPreflight: false,
      preflightCommitment: 'confirmed'
    }
  );
  console.log('Token transfer:', tokenSignature);
}

// Helper function to convert human-readable amounts to raw amounts
function convertToRawAmount(amount: number, decimals: number): number {
  return Math.floor(amount * Math.pow(10, decimals));
}

// Example: Transfer 1.5 USDC
async function transferUSDC() {
  const client = new HeliusClient({ apiKey: 'your-api-key' });
  
  // Load your keypair (replace with your actual keypair loading logic)
  const keypair = Keypair.fromSecretKey(/* your secret key */);
  
  const rawAmount = convertToRawAmount(1.5, 6); // USDC has 6 decimals
  const signature = await client.sendTokenTransfer(
    new PublicKey('to-token-account'),
    keypair, // Use keypair directly as owner parameter
    rawAmount,
    new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v') // USDC mint
  );
  
  console.log('USDC transfer completed:', signature);
}

Asset Data Retrieval

import { HeliusClient } from 'delegate-framework';

async function getAssetInformation() {
  const client = new HeliusClient({ apiKey: 'your-api-key' });
  
  // Get comprehensive data for an NFT or token
  const assetId = '11111111111111111111111111111111'; // Mint address
  const assetData = await client.getAsset(assetId);
  
  // Asset data includes on-chain metadata, off-chain metadata, and more
  console.log('Asset name:', assetData[0]?.onChainMetadata?.metadata?.name);
  console.log('Token standard:', assetData[0]?.onChainMetadata?.tokenStandard);
  console.log('Off-chain metadata:', assetData[0]?.offChainMetadata);
}

Metaplex Metadata Parsing

import { HeliusClient } from 'delegate-framework';
import { PublicKey } from '@solana/web3.js';

async function getMetaplexMetadata() {
  const client = new HeliusClient({ apiKey: 'your-api-key' });
  
  // Get metadata directly from a metadata account
  const metadataAccount = new PublicKey('metadata-account-address');
  const metadata = await client.getAccountInfo(metadataAccount, { 
    parseMetaplexMetadata: true,
    includeOffChainMetadata: true 
  });
  
  console.log('NFT Name:', metadata.name);
  console.log('Symbol:', metadata.symbol);
  console.log('Creators:', metadata.creators);
  console.log('Collection:', metadata.collection);
  console.log('Royalty:', metadata.sellerFeeBasisPoints / 100, '%');
  
  // Get metadata from a mint address (automatically derives metadata account)
  const mintAddress = new PublicKey('mint-address');
  const mintMetadata = await client.getAccountInfo(mintAddress, { 
    parseMetaplexMetadata: true 
  });
  
  console.log('Mint Metadata:', mintMetadata);
}

Error Handling Example

import { HeliusClient, throwError, getErrorMessage } from 'delegate-framework';

async function safeGetBalance(publicKey: PublicKey) {
  try {
    const client = new HeliusClient({ apiKey: 'your-api-key' });
    return await client.getBalance(publicKey);
  } catch (error) {
    const message = getErrorMessage(error);
    console.error('Failed to get balance:', message);
    
    // Re-throw with context
    throwError(error, 'Balance Check Failed');
  }
}

Practical Transfer Workflow

import { HeliusClient } from 'delegate-framework';
import { PublicKey, Keypair } from '@solana/web3.js';

async function completeTransferWorkflow() {
  const client = new HeliusClient({ 
    apiKey: 'your-api-key',
    timeout: 30000,
    retries: 3 
  });
  
  // Load your keypair (replace with your actual keypair loading logic)
  const keypair = Keypair.fromSecretKey(/* your secret key bytes */);
  
  // 1. Check balances before transfer
  const fromWallet = keypair.publicKey; // Get public key from keypair
  const toWallet = new PublicKey('recipient-address');
  
  const fromBalance = await client.getBalance(fromWallet);
  const toBalance = await client.getBalance(toWallet);
  
  console.log('From balance:', fromBalance / 1e9, 'SOL');
  console.log('To balance:', toBalance / 1e9, 'SOL');
  
  // 2. Send native SOL transfer
  const transferAmount = 0.001 * 1e9; // 0.001 SOL in lamports
  
  try {
    const signature = await client.sendNativeTransfer(
      keypair, // Use keypair directly as from parameter
      toWallet,
      transferAmount,
      {
        skipPreflight: false,
        preflightCommitment: 'confirmed'
      }
    );
    
    console.log('Transfer sent:', signature);
    
    // 3. Wait for confirmation
    const confirmation = await client.waitForConfirmation(signature, 'confirmed');
    console.log('Transfer confirmed:', confirmation);
    
    // 4. Check balances after transfer
    const newFromBalance = await client.getBalance(fromWallet);
    const newToBalance = await client.getBalance(toWallet);
    
    console.log('New from balance:', newFromBalance / 1e9, 'SOL');
    console.log('New to balance:', newToBalance / 1e9, 'SOL');
    
  } catch (error) {
    console.error('Transfer failed:', error);
  }
}

// Advanced: Token transfer with balance checks
async function tokenTransferWithValidation() {
  const client = new HeliusClient({ apiKey: 'your-api-key' });
  
  // Load your keypair
  const keypair = Keypair.fromSecretKey(/* your secret key bytes */);
  
  const toTokenAccount = new PublicKey('recipient-token-account');
  const mint = new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'); // USDC
  
  // Get the source token account for balance checking
  const sourceTokenAccount = await client.getTokenAccount(keypair.publicKey, mint);
  const fromTokenAccount = new PublicKey(sourceTokenAccount.value[0].pubkey);
  
  // Check token balances
  const fromBalance = await client.getTokenAccountBalance(fromTokenAccount);
  const toBalance = await client.getTokenAccountBalance(toTokenAccount);
  
  console.log('From token balance:', fromBalance.value.uiAmount, 'USDC');
  console.log('To token balance:', toBalance.value.uiAmount, 'USDC');
  
  // Transfer 10 USDC
  const transferAmount = 10 * 1e6; // USDC has 6 decimals
  
  if (fromBalance.value.uiAmount < 10) {
    throw new Error('Insufficient token balance');
  }
  
  const signature = await client.sendTokenTransfer(
    toTokenAccount,
    keypair, // Use keypair directly as owner parameter
    transferAmount,
    mint
  );
  
  console.log('Token transfer completed:', signature);
}

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests for new functionality
  5. Run the test suite
  6. Submit a pull request

License

MIT