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 🙏

© 2025 – Pkg Stats / Ryan Hefner

near-kit

v0.6.3

Published

A simple, intuitive TypeScript library for interacting with NEAR Protocol

Downloads

2,741

Readme

near-kit

codecov npm version License: MIT TypeScript

A simple, intuitive TypeScript library for interacting with NEAR Protocol. Designed to feel like a modern fetch library - easy for beginners, powerful for advanced users.

📚 Full Documentation

Features

  • Simple things should be simple - One-line commands for common operations
  • Type safety everywhere - Full TypeScript support with IDE autocomplete
  • Progressive complexity - Basic API for simple needs, advanced features when required
  • Powerful transaction builder - Fluent, human-readable API for transactions
  • Wallet-ready - Full support for HOT Connector and NEAR Wallet Selector, drop-in integration

Installation

npm install near-kit
# or
bun install near-kit

Quick Start

import { Near } from "near-kit"

// Initialize for backend/scripts
const near = new Near({
  network: "testnet",
  privateKey: "ed25519:...",
  defaultSignerId: "alice.testnet",
})

// View methods (read-only, no gas)
const balance = await near.view("example.testnet", "get_balance", {
  account_id: "alice.testnet",
})

// Call methods (requires signature, costs gas)
await near.call(
  "example.testnet",
  "increment",
  {},
  { attachedDeposit: "0.1 NEAR" }
)

// Send NEAR tokens
await near.send("bob.testnet", "5 NEAR")

Getting Started

near-kit provides a unified API that works across different environments. Configuration varies by environment, but the API for calling contracts, sending transactions, and building transactions remains identical.

Backend & Scripts

For local testing, use the sandbox (no network or key configuration needed):

import { Sandbox } from "near-kit"

const sandbox = await Sandbox.start()
const near = new Near({ network: sandbox })

// Test with automatically provisioned accounts
await near.call("contract.test.near", "method", {})

await sandbox.stop()

For testnet/mainnet development, pass a private key directly:

const near = new Near({
  network: "testnet",
  privateKey: "ed25519:...",
  defaultSignerId: "alice.testnet",
})

For production applications, use a keyStore:

import { FileKeyStore } from "near-kit"

const near = new Near({
  network: "testnet",
  keyStore: new FileKeyStore("~/.near-credentials"),
})

Frontend & Wallets

In the browser, connect to user wallets. The same near.call(), near.send(), and near.transaction() methods work seamlessly:

import { fromWalletSelector } from "near-kit"

const near = new Near({
  network: "testnet",
  wallet: fromWalletSelector(walletInstance),
})

// Same API as backend
await near.call("contract.near", "method", { arg: "value" })

This works through a signer abstraction - whether you pass privateKey, keyStore, wallet, or sandbox, they all implement the same signing interface internally.

Core API

Initialization

// Simple - defaults to mainnet
const near = new Near()

// With network selection
const near = new Near({ network: "testnet" })

// With custom configuration
const near = new Near({
  network: "testnet",
  privateKey: "ed25519:...",
})

Basic Operations

// View methods (free, no signature required)
const result = await near.view("contract.near", "get_data", { key: "value" })

// Check account balance
const balance = await near.getBalance("alice.near")

// Check if account exists
const exists = await near.accountExists("alice.near")

// Get network status
const status = await near.getStatus()

Type-Safe Contracts

import type { Contract } from "near-kit"

// Define contract interface using Contract<> helper
type MyContract = Contract<{
  view: {
    get_balance: (args: { account_id: string }) => Promise<string>
    get_info: () => Promise<{ name: string; version: string }>
  }
  call: {
    // Just define args - options parameter automatically added!
    transfer: (args: { to: string; amount: string }) => Promise<void>
  }
}>

// Create type-safe contract
const contract = near.contract<MyContract>("example.near")

// Fully typed method calls
const balance = await contract.view.get_balance({ account_id: "alice.near" })
const info = await contract.view.get_info()

// Call methods automatically get options parameter
await contract.call.transfer(
  { to: "bob.near", amount: "10" },
  { attachedDeposit: "1 NEAR" }
)

Transaction Builder

// Alice builds a transaction with multiple actions
// 'alice.near' is the signer - the account that signs and pays for this transaction
const receipt = await near
  .transaction("alice.near") // Alice signs
  .transfer("bob.near", "10 NEAR") // Alice sends Bob 10 NEAR
  .functionCall(
    "market.near",
    "buy",
    { id: "123" },
    { attachedDeposit: "5 NEAR" } // Alice attaches 5 NEAR to the call
  )
  .send()

Batch Operations

// Run multiple operations in parallel
const [balance, status, exists] = await near.batch(
  near.getBalance("alice.near"),
  near.getStatus(),
  near.accountExists("bob.near")
)

Local Testing with Sandbox

import { Sandbox } from "near-kit"

const sandbox = await Sandbox.start()
const near = new Near({ network: sandbox })
// ... run tests
await sandbox.stop()

With test framework:

let sandbox: Sandbox
beforeAll(async () => {
  sandbox = await Sandbox.start()
})
afterAll(async () => {
  await sandbox.stop()
})

Key Management

import { InMemoryKeyStore, FileKeyStore, RotatingKeyStore } from "near-kit"

// In-memory (runtime only)
const near = new Near({
  keyStore: new InMemoryKeyStore({
    "alice.near": "ed25519:...",
  }),
})

// File-based (persistent)
const near = new Near({
  keyStore: new FileKeyStore("~/.near-credentials"),
})

// Rotating keys for high-throughput concurrent transactions
const near = new Near({
  keyStore: new RotatingKeyStore({
    "alice.near": ["ed25519:key1...", "ed25519:key2...", "ed25519:key3..."],
  }),
})

Wallet Integration

near-kit integrates with Wallet Selector and HOT Connector through a signer abstraction. Wallet adapters are converted to signers via fromWalletSelector() and fromHotConnect() shims, allowing the same API to work across backend and frontend without separate client implementations.

NEAR Wallet Selector

import { Near, fromWalletSelector } from "near-kit"
import { setupWalletSelector } from "@near-wallet-selector/core"
import { setupMyNearWallet } from "@near-wallet-selector/my-near-wallet"
import { setupHereWallet } from "@near-wallet-selector/here-wallet"

// Setup wallet selector
const selector = await setupWalletSelector({
  network: "testnet",
  modules: [setupMyNearWallet(), setupHereWallet()],
})

// Get wallet instance (after user connects)
const wallet = await selector.wallet()

// Use with near-kit
const near = new Near({
  network: "testnet",
  wallet: fromWalletSelector(wallet),
})

// All operations now use the wallet for signing
await near.call("contract.near", "method", { arg: "value" })
await near.send("bob.near", "10 NEAR")

HOT Connector

import { Near, fromHotConnect } from "near-kit"
import { NearConnector } from "@hot-labs/near-connect"

// Create connector
const connector = new NearConnector({ network: "testnet" })

// Wait for user to connect
connector.on("wallet:signIn", async () => {
  const near = new Near({
    network: "testnet",
    wallet: fromHotConnect(connector),
  })

  // Use near-kit with the connected wallet
  await near.call("contract.near", "method", { arg: "value" })
})

// Trigger wallet connection
await connector.signIn()

Error Handling

Errors are organized by category and include detailed context for debugging. Use instanceof checks to handle specific error types.

Network Errors

import { NetworkError, TimeoutError } from "near-kit"

try {
  await near.call("contract.near", "method", {})
} catch (error) {
  if (error instanceof TimeoutError) {
    console.log("Request timed out - already retried automatically")
  } else if (error instanceof NetworkError) {
    // Handle other network issues
  }
}

Transaction Errors

import { InsufficientBalanceError, InvalidNonceError } from "near-kit"

try {
  await near.send("bob.near", "1000000 NEAR")
} catch (error) {
  if (error instanceof InsufficientBalanceError) {
    console.log(`Need ${error.required}, have ${error.available}`)
  } else if (error instanceof InvalidNonceError) {
    // Already retried automatically - only thrown if retries exhausted
  }
}

Contract Errors

import { FunctionCallError } from "near-kit"

try {
  await near.call("contract.near", "method", {})
} catch (error) {
  if (error instanceof FunctionCallError) {
    console.log(`Contract panicked: ${error.panic}`)
    console.log(`Logs:`, error.logs)
  }
}

Advanced Features

Batch Actions (Multi-Action Transactions)

Deploy and initialize a contract in a single transaction:

const contractWasm = await fs.readFile("./contract.wasm")

await near
  .transaction("alice.near")
  .createAccount("contract.alice.near")
  .transfer("contract.alice.near", "10 NEAR")
  .deployContract("contract.alice.near", contractWasm)
  .functionCall("contract.alice.near", "init", { owner: "alice.near" })
  .send()

NEP-413 Message Signing

Authenticate users without gas fees:

const signedMessage = await near.signMessage({
  message: "Login to MyApp",
  recipient: "myapp.near",
  nonce: crypto.getRandomValues(new Uint8Array(32)),
})

// Send to backend for verification
await fetch("/api/auth", {
  method: "POST",
  body: JSON.stringify(signedMessage),
})

Delegate Actions (NEP-366)

Enable meta-transactions and sponsored transactions where a relayer pays the gas:

import { decodeSignedDelegateAction, Near } from "near-kit"

// User creates and signs a delegate action (no gas cost to user)
const userNear = new Near({
  network: "testnet",
  privateKey: "ed25519:...", // User's key
})

const { signedDelegateAction, payload } = await userNear
  .transaction("user.near")
  .transfer("recipient.near", "1 NEAR")
  .delegate({ blockHeightOffset: 100 })

// Relayer submits the transaction (pays the gas)
const relayerNear = new Near({
  network: "testnet",
  privateKey: "ed25519:...", // Relayer's key
})

await relayerNear
  .transaction("relayer.near")
  .signedDelegateAction(decodeSignedDelegateAction(payload))
  .send()

Automatic Nonce Management

No more nonce conflicts - the library handles nonce tracking and retries automatically:

// Safe to run multiple transactions concurrently
await Promise.all([
  near.send("bob.near", "1 NEAR"),
  near.send("charlie.near", "1 NEAR"),
  near.send("dave.near", "1 NEAR"),
])
// Nonces are automatically managed and conflicts are retried

Smart Retry Logic

Automatic retries for network errors with exponential backoff:

try {
  await near.call("contract.near", "method", {})
} catch (error) {
  if (error instanceof TimeoutError && error.retryable) {
    // Already retried automatically
  }
}

Development

# Install dependencies
bun install

# Run tests
bun test

# Build
bun run build

# Run examples
bun run examples/quickstart.ts

License

MIT