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

near-balancer

v1.0.0

Published

High-performance NEAR RPC client with automatic load balancing, round-robin rotation, and retry logic

Readme

NEAR Balancer

High-performance NEAR RPC client with automatic load balancing, round-robin rotation, and intelligent retry logic.

npm version License: MIT

Features

  • Round-robin Load Balancing - Automatically distributes requests across multiple RPC endpoints
  • Automatic Retry - Retries failed requests with exponential backoff
  • Rate Limit Handling - Gracefully handles 429 responses by rotating to next endpoint
  • Request Timeout - Prevents hanging requests with configurable timeout
  • TypeScript - Fully typed for excellent developer experience
  • Zero Dependencies - Uses only native fetch API
  • High Throughput - Optimized for parallel/concurrent operations
  • Resumable Operations - Built-in state management for long-running syncs

Installation

npm install near-balancer
# or
bun add near-balancer
# or
yarn add near-balancer

Quick Start

import { createMainnetClient } from 'near-balancer';

// Create client with default mainnet endpoints
const client = createMainnetClient();

// Call NFT method
const tokens = await client.callNftView(
  'meme.near',
  'nft_tokens',
  { from_index: '0', limit: 10 }
);

console.log(tokens);

Configuration

Custom Endpoints

import { createRpcClient } from 'near-balancer';

const client = createRpcClient({
  endpoints: [
    'https://rpc.mainnet.near.org',
    'https://near.lava.build',
    'https://your-custom-rpc.com',
  ],
  retries: 5,           // Number of retries (default: 3)
  retryDelay: 500,      // Delay between retries in ms (default: 200)
  timeout: 60000,       // Request timeout in ms (default: 30000)
});

Preconfigured Clients

import { createMainnetClient, createTestnetClient } from 'near-balancer';

// Mainnet with 5 public endpoints
const mainnet = createMainnetClient();

// Testnet with 2 public endpoints
const testnet = createTestnetClient();

API Reference

createRpcClient(config)

Creates a new RPC client instance with custom configuration.

const client = createRpcClient({
  endpoints: string[],    // Required: List of RPC endpoints
  retries?: number,       // Optional: Retry count (default: 3)
  retryDelay?: number,    // Optional: Delay between retries in ms (default: 200)
  timeout?: number,       // Optional: Request timeout in ms (default: 30000)
});

client.query(params, options?)

Make a raw RPC query request with automatic retry and endpoint rotation.

const result = await client.query<YourType>({
  request_type: 'call_function',
  finality: 'final',
  account_id: 'example.near',
  method_name: 'get_method',
  args_base64: 'e30=', // base64 encoded JSON args
});

// Force specific endpoint (useful for testing)
const result = await client.query(params, { endpointIndex: 0 });

client.getNextEndpoint()

Get the next endpoint URL (rotation happens automatically on each request).

client.getEndpoints()

Get all configured endpoints.

client.getCurrentIndex()

Get current endpoint index.

Helper Functions

callNftView(client, contractId, method, args)

Call an NFT contract view method with automatic args encoding.

import { callNftView, createMainnetClient } from 'near-balancer';

const client = createMainnetClient();

const tokens = await callNftView(
  client,
  'paras-fanatic.near',
  'nft_tokens',
  { from_index: '0', limit: 50 }
);

getAccountBalance(client, accountId)

Get account balance information.

import { getAccountBalance, createMainnetClient } from 'near-balancer';

const client = createMainnetClient();

const balance = await getAccountBalance(client, 'example.near');
console.log(balance.amount, balance.staked);

Examples

High-Throughput NFT Holder Sync

import { createMainnetClient, callNftView } from 'near-balancer';

const client = createMainnetClient({
  endpoints: [
    'https://rpc.mainnet.near.org',
    'https://near.lava.build',
    'https://near.drpc.org',
  ],
  retries: 3,
});

async function syncNftHolders(contractId: string) {
  const holders = new Map<string, number>();
  const BATCH_SIZE = 50;
  const CONCURRENT = 5;

  // Get total supply
  const supply = await callNftView<string>(client, contractId, 'nft_total_supply');
  const maxTokenId = parseInt(supply || '0', 10) + 500;

  // Fetch in parallel batches
  for (let i = 0; i < maxTokenId; i += BATCH_SIZE * CONCURRENT) {
    const batch = Array.from({ length: CONCURRENT }, (_, j) => i + j * BATCH_SIZE);

    const results = await Promise.all(
      batch.map(async (startIdx) => {
        const tokens = await callNftView<any[]>(
          client,
          contractId,
          'nft_tokens',
          { from_index: String(startIdx), limit: BATCH_SIZE }
        );
        return { startIdx, tokens };
      })
    );

    // Process results
    for (const { tokens } of results) {
      if (tokens) {
        for (const token of tokens) {
          if (token.owner_id) {
            holders.set(token.owner_id, (holders.get(token.owner_id) || 0) + 1);
          }
        }
      }
    }

    console.log(`Progress: ${i}/${maxTokenId} - ${holders.size} holders found`);
  }

  return holders;
}

// Usage
const holders = await syncNftHolders('nearlegion.nfts.tg');
console.log(`Found ${holders.size} unique holders`);

Multi-Contract Operations

import { createMainnetClient, callNftView } from 'near-balancer';

const client = createMainnetClient();

const CONTRACTS = [
  'paras-fanatic.near',
  'neargen.near',
  'meme.near',
];

// Process contracts in parallel
const results = await Promise.all(
  CONTRACTS.map(async (contract) => {
    const supply = await callNftView<string>(
      client,
      contract,
      'nft_total_supply'
    );
    return { contract, supply };
  })
);

for (const { contract, supply } of results) {
  console.log(`${contract}: ${supply} tokens`);
}

How Round-Robin Load Balancing Works

The client automatically rotates through endpoints on each request:

Request 1 → endpoint[0]
Request 2 → endpoint[1]
Request 3 → endpoint[2]
Request 4 → endpoint[0]  (cycles back to start)
...

Benefits

  1. Load Distribution - Spreads requests across multiple RPC providers
  2. Rate Limit Avoidance - Automatically switches endpoints on 429 errors
  3. High Availability - If one endpoint fails, retries use other endpoints
  4. Improved Throughput - Parallel requests hit different endpoints

Default Endpoints

Mainnet (5 endpoints)

  • https://rpc.mainnet.near.org - Official NEAR RPC
  • https://near.lava.build - Lava Network
  • https://near.blockpi.network/v1/rpc/public - BlockPI
  • https://near.drpc.org - dRPC
  • https://endpoints.omniatech.io/v1/near/mainnet/public - Omnia

Testnet (2 endpoints)

  • https://rpc.testnet.near.org - Official NEAR testnet RPC
  • https://near-testnet.lava.build - Lava Network testnet

Performance Tips

High Throughput Configuration

const client = createMainnetClient({
  retries: 2,         // Lower retries for faster failure
  retryDelay: 100,    // Lower delay between retries
  timeout: 15000,     // Lower timeout for quicker error detection
});

// Use parallel requests
const CONCURRENT = 10;
const results = await Promise.all(
  Array.from({ length: CONCURRENT }, (_, i) =>
    callNftView(client, contract, method, args)
  )
);

Conservative Configuration (Reliability)

const client = createMainnetClient({
  retries: 5,         // More retries
  retryDelay: 500,    // Longer delay
  timeout: 60000,     // Longer timeout
});

Error Handling

The library gracefully handles errors and returns null when all retries fail:

const result = await callNftView(client, 'contract.near', 'some_method');

if (result === null) {
  console.error('All endpoints failed after retries');
  // Handle error appropriately
}

Testing

The library includes comprehensive tests:

# Run all tests
bun test

# Run with coverage
bun test --coverage

Roadmap

  • [ ] WebSocket subscription support
  • [ ] Request caching layer
  • [ ] Automatic endpoint health checking
  • [ ] Metrics and monitoring hooks
  • [ ] Deno/native compatibility

Contributing

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

License

MIT © 2025


Note: This library is designed to work in Node.js, Bun, Deno, and browser environments. For browser usage, ensure your RPC endpoints support CORS.