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

@jarvisclaw-ai/sdk

v0.2.0

Published

TypeScript SDK for JarvisClaw — chat, marketplace and AIP, with built-in x402 USDC payments on Base and Solana.

Readme

@jarvisclaw-ai/sdk

TypeScript SDK for the JarvisClaw AI gateway, with x402 USDC payments built in on Base and Solana.

This is the payment and transport layer. It is what jarvisclaw (the terminal agent) runs on, and it is usable on its own.

Sibling SDKs: python-sdk · go-sdk

Install

npm install @jarvisclaw-ai/sdk

The chain libraries are optional peers — install only the one you need:

npm install viem                # to pay with an EVM (Base) wallet
npm install @solana/web3.js     # to pay with a Solana wallet

Neither is needed in API-key mode.

Two ways to pay

import { BaseClient } from '@jarvisclaw-ai/sdk'

// 1. API key — the account's balance covers the call.
const client = await BaseClient.create({ apiKey: 'sk-...' })

// 2. x402 wallet — the SDK pays per call out of your own USDC.
const client = await BaseClient.create({ privateKey: '0x...' })

In wallet mode there is no API key and no account. The first request goes out unauthenticated, the gateway answers 402 with a price, the SDK signs a payment authorisation and replays the request. That whole exchange happens inside request(); callers just see the result.

Credentials also resolve from the environment, so a script needs no arguments:

| variable | meaning | | --- | --- | | JARVISCLAW_API_KEY | gateway API key | | JARVISCLAW_WALLET_KEY | wallet private key (EVM hex or Solana base58) | | JARVISCLAW_BASE_URL | gateway URL, for self-hosted deployments |

An explicitly passed credential always beats one in the environment.

Balance

const usd = await client.getBalanceUsd()

In wallet mode this reads the chain directly, because that is what x402 settles against. In API-key mode it reads the gateway's wallet endpoint. Note what it deliberately does not include: the account's quota column. x402 settles against the wallet and never debits quota, so counting quota would overstate spendable funds by the lifetime deposit total.

Paying safely

Every payment is checked before it is signed. A challenge is refused, rather than signed and sorted out later, if it has an empty payTo, a non-positive or fractional amount, an asset that is not USDC, or a network whose chain id cannot be determined.

There is also a client-side ceiling, defaulting to 100 USDC per call:

const client = await BaseClient.create({
  privateKey: '0x...',
  maxAmountBaseUnits: 50_000n,  // 0.05 USDC, in base units (6 decimals)
})

This is a circuit breaker against a misconfigured or hostile server naming an absurd price, not a spending budget — it bounds one call, not the total. For account-level limits use the gateway's own spending limits.

A paid retry that the server still rejects is final. The SDK does not sign a second authorisation for a request that has already been refused, since that would spend real money twice on the same failure.

Errors

Everything thrown descends from JarvisClawError, including transport failures, so one catch covers every mode:

import {
  APIError, AuthenticationError, ConnectionError,
  InsufficientBalanceError, JarvisClawError, PaymentError,
  RateLimitError, TimeoutError,
} from '@jarvisclaw-ai/sdk'

| error | when | | --- | --- | | AuthenticationError | 401 — key or credential rejected | | RateLimitError | 429 — has .retryAfter when the server sends one | | InsufficientBalanceError | 402 that could not be paid | | PaymentError | signing refused, before anything was sent | | TimeoutError / ConnectionError | no HTTP response at all | | APIError | any other 4xx/5xx; has .statusCode and .body |

A 402 means two different things worth distinguishing by message: in API-key mode the account cannot cover the call; in wallet mode signing or settlement failed.

429 and 5xx are retried automatically with exponential backoff and jitter (3 attempts by default, maxRetries). 4xx is not retried.

Signing directly

The signers are exported for use without the client — for a proxy, a facilitator test, or another HTTP stack:

import { EvmX402Signer, SolanaX402Signer } from '@jarvisclaw-ai/sdk'

const signer = await EvmX402Signer.fromPrivateKey('0x...')
const header = await signer.signFrom402(response402, requestUrl)
// → set as the PAYMENT-SIGNATURE header on the replayed request

EvmX402Signer.fromAccount() takes anything that can sign EIP-712 — a viem account, or a shim over a KMS or hardware wallet — so the private key never has to be in the process.

How the two chains differ

Base (EVM) signs an EIP-3009 TransferWithAuthorization over EIP-712. It is an authorisation, not a transaction: the facilitator submits it and pays the gas, which is why a wallet holding USDC and no ETH can still pay. validAfter is backdated ten minutes so clock skew cannot make it not-yet-valid at settlement.

Solana builds a partially-signed SPL TransferChecked transaction. The server is the fee payer and signs its own slot on verification, so we fill only ours. A random memo instruction keeps two identical-looking payments distinct. The blockhash comes straight from public RPC rather than through the gateway, because a proxied one can be cached long enough to fail simulation.

Both produce the same envelope shape, base64 in the PAYMENT-SIGNATURE header.

Tests

npm test
npm run typecheck

The signing tests check envelopes against fixtures generated by the Python SDK (test/fixtures/generate_reference.py), not against this SDK's own output. Both SDKs are verified by the same facilitator, so byte-identical output is the actual requirement — a test that only proved self-consistency would pass while the envelope silently drifted out of what the facilitator accepts. On top of that, the EVM signature is recovered back to the signing address and the Solana signature is Ed25519-verified against the serialized message, so a structurally plausible but wrong signature fails rather than passing as 64 non-zero bytes.

License

MIT