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

@aivo-x402/solana

v1.0.2

Published

AIVO Solana layer on top of the official x402 v2 protocol — auto-DID wallet + self-hosted facilitator with x402.org fallback. Re-exports @x402/* (core, svm, hono, fetch, extensions).

Readme

@aivo-x402/solana

AIVO Solana layer on top of the official x402 v2 protocol.

One package, three jobs:

  1. 🔁 Re-exports the official @x402/* packages (core, svm, hono, fetch, extensions) so you import one name.
  2. 🪪 Auto-DID wallet flowdid:sol:<pubkey> per W3C DID spec. No signup, no API key.
  3. 🌐 Self-hosted facilitator with x402.org fallback — try self-host, fall back if it dies.

Built for the AIVO 3-repo stack: this package is the shared protocol layer between aivo-swarm (server) and rover (client). See AGENTS.md v1.2.2 for the full spec.

npm version npm downloads CI License: MIT Node x402 v2


Table of contents


Why this package exists

The AIVO stack has three repos that need to talk to each other over x402:

| Repo | Role | Talks x402 as… | |---|---|---| | aivo-swarm | Pool intel API | Server (paywall routes) | | rover | LP agent | Client (auto-pays Swarm) | | x402-solana (this) | Shared protocol | Both + AIVO helpers |

Two pieces are unique to AIVO and not in the upstream @x402/* packages:

  1. Auto-DID wallet flow — wallet pubkey = identity, no registration. Swarm upserts on first contact.
  2. Self-hosted facilitator with fallback — run our own facilitator, fall back to x402.org if it dies.

Both come from AGENTS.md v1.2.2. This package is the implementation.


Install

npm install @aivo-x402/solana

Requirements: Node.js ≥ 22.12, TypeScript ≥ 5.0, ESM-only.


Quick start

1. Auto-DID wallet (AGENTS.md v1.2.2 a–d)

Wallet = identity. did:sol:<pubkey> per W3C DID spec for Solana. No signup, no API key.

import { createDID, verifyWallet, walletFromDID } from "@aivo-x402/solana";
import nacl from "tweetnacl";

// ── Server (Swarm) ──────────────────────────────────────────
// Derive a DID from any wallet that pings you. Upsert on first contact.
const did = createDID("AGwiTnRnXCgf9AemWdvTwWDz18YUevTGDv2TokT97n1Q");
// → { id: "did:sol:AGwiT...", controller: "AGwiT...", created: "2026-06-02T..." }

// Extract the pubkey back out of a DID string
const wallet = walletFromDID("did:sol:AGwiTnRnXCgf9AemWdvTwWDz18YUevTGDv2TokT97n1Q");
// → "AGwiTnRnXCgf9AemWdvTwWDz18YUevTGDv2TokT97n1Q"

// ── Client (Rover) ──────────────────────────────────────────
// Prove wallet ownership by signing a payload (e.g. the request body)
const keypair = nacl.sign.keyPair.fromSeed(seed);
const payload = new TextEncoder().encode(JSON.stringify({ pool: "X" }));
const signature = nacl.sign.detached(payload, keypair.secretKey);

const isValid = verifyWallet({
  payload,
  signature,
  wallet: keypair.publicKey.toBase58(),
});
// → true / false

Why this is nice: one wallet works across Swarm + Rover + (future) @aivo-x402/solana consumers. No separate registration, no API keys, no friction.


2. Self-hosted facilitator with x402.org fallback (AGENTS.md v1.2.2 e)

import {
  createFacilitator,
  x402ResourceServer,
  ExactSvmScheme,
  X402FacilitatorUnavailableError,
} from "@aivo-x402/solana";

const facilitator = createFacilitator({
  selfHostUrl: process.env.X402_FACILITATOR_PRIMARY, // e.g. https://x402.aivo.sh
  fallbackUrl: "https://x402.org",
  timeoutMs: 15_000,
  onFallback: (reason) => console.warn(`[x402] falling back: ${reason}`),
});

const server = new x402ResourceServer(
  new ExactSvmScheme(/* signer config */),
);

// Use the facilitator to verify/settle payments
try {
  const result = await facilitator.verify({ paymentPayload, accepted });
  if (!result.isValid) throw new Error("payment rejected");
} catch (err) {
  if (err instanceof X402FacilitatorUnavailableError) {
    // Both self-host AND x402.org are down — fail closed
    throw err;
  }
  throw err;
}

The order of resolution is:

1. selfHostUrl  (your own facilitator — lowest latency, no per-tx fee)
       ↓ if unavailable / 5xx / timeout / network error
2. fallbackUrl  (x402.org — Coinbase + Cloudflare, public)
       ↓ if still failing
3. throw X402FacilitatorUnavailableError

See Failure semantics for details.


3. Hono server (paywall route)

import { Hono } from "hono";
import {
  paymentMiddleware,
  RoutesConfig,
  ExactSvmScheme,
  x402ResourceServer,
} from "@aivo-x402/solana";

const app = new Hono();

const routes: RoutesConfig = {
  "GET /v1/pools/top": {
    accepts: {
      scheme: "exact",
      network: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
      payTo: "AGwiTnRnXCgf9AemWdvTwWDz18YUevTGDv2TokT97n1Q",
      price: "$0.001",
    },
    description: "Top N pools by composite score",
  },
};

const server = new x402ResourceServer(new ExactSvmScheme(/* signer */));

app.use(
  paymentMiddleware(
    routes,
    server, // x402ResourceServer (handles facilitator internally)
  ),
);

app.get("/v1/pools/top", (c) => c.json({ pools: [] }));

4. Fetch client (Rover)

import {
  wrapFetchWithPayment,
  x402Client,
  ExactSvmScheme,
} from "@aivo-x402/solana";

const client = new x402Client().register(
  "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
  new ExactSvmScheme({ /* signer config */ }),
);

const paidFetch = wrapFetchWithPayment(fetch, client);
const res = await paidFetch("https://swarm.example.com/v1/pools/top");
// → automatically retries 402 with payment, then returns the data

What this package re-exports from @x402/*

You can import everything from @aivo-x402/solana instead of juggling scoped names.

| From | What you get | |---|---| | @x402/core/types | PaymentPayload, PaymentRequired, PaymentRequirements, ResourceInfo, Network, VerifyResponse, SettleResponse | | @x402/core/server | x402ResourceServer, x402HTTPResourceServer, FacilitatorClient, RoutesConfig, RouteConfig | | @x402/core/http | encodePaymentRequiredHeader, decodePaymentSignatureHeader (base64 wire helpers) | | @x402/fetch | x402Client, x402HTTPClient, wrapFetchWithPayment | | @x402/hono | paymentMiddleware, paymentMiddlewareFromConfig | | @x402/svm | ExactSvmScheme, ClientSvmConfig, FacilitatorRpcConfig | | @x402/extensions | Bazaar, sign-in-with-x, etc. (re-exported as a pass-through) |

For the full API surface, see the upstream docs at coinbase/x402.


What AIVO adds on top

| Export | Purpose | |---|---| | createDID(wallet) | Derive did:sol:<pubkey> from a Solana pubkey (W3C DID) | | getDID(wallet) | Alias of createDID for symmetry with "get" semantics | | verifyWallet({ payload, signature, wallet }) | Ed25519 signature verification via tweetnacl | | walletFromDID(did) | Extract the pubkey back from a did:sol: string | | createFacilitator({ selfHostUrl?, fallbackUrl?, timeoutMs?, onFallback? }) | Self-host → fallback chain facilitator client | | X402FacilitatorUnavailableError | Thrown when both facilitators fail | | AivoFacilitator (type) | Shape of the returned facilitator client |

The DID helpers do not persist anything — they're pure derivation functions. Storage of the DID ↔ wallet mapping is the caller's responsibility (Swarm stores in Postgres, Rover keeps it in memory per session).


Failure semantics

The facilitator wrapper is opinionated about what counts as a "real" failure:

| Outcome | Action | |---|---| | 2xx from self-host | Use the response, no fallback | | 4xx from self-host | Return the body as-is — isValid: false is a legitimate answer, do not fall back | | 5xx from self-host | Fall back to fallbackUrl | | Network error / timeout on self-host | Fall back to fallbackUrl | | 2xx from fallback | Use the response, log via onFallback | | Fallback also fails (5xx / network / timeout) | Throw X402FacilitatorUnavailableError | | 4xx from fallback | Return the body as-is (legitimate rejection) |

This matches the AGENTS.md spec: "Never let Swarm serve data without facilitator verification — that breaks the paywall. Fail closed, not open."


Publishing & releases

Tagged releases are published to npm automatically via .github/workflows/release.yml.

One-time setup (maintainer)

  1. Create an npm granular access token with publish scope on @aivo-x402/solana.
  2. Add it to the repo as a GitHub secret: NPM_TOKEN.
  3. Repo already has id-token: write permission for npm provenance attestation.

Cutting a release

# 1. Bump version in package.json
# 2. Move [Unreleased] → dated version in CHANGELOG.md
# 3. Commit, tag, push
git add package.json CHANGELOG.md
git commit -m "chore: release v0.1.0"
git tag v0.1.0
git push origin main --tags

CI will:

  1. ✅ Install deps, typecheck, lint, test, build
  2. 📦 Upload dist/ artifact
  3. 🚀 Publish to npm with --provenance --access public

You can also trigger a dry run manually from the Actions tab without publishing.


Architecture diagram

┌──────────────────────────────────────────────────────────┐
│                  USER / AGENT                            │
└────────────┬─────────────────────────┬───────────────────┘
             │                         │
     (1) API │                         │ (2) run rover binary
   $0.001+   │                         │     (revenue: Swarm + Jupiter)
   USDC      │                         │
             ▼                         ▼
   ┌─────────────────┐         ┌─────────────────┐
   │   aivo-swarm    │◀──HMAC──│      rover      │
   │  (Hono + DBOS)  │ beacon  │ (Hono + Mastra) │
   │                 │         │                 │
   │ • pool scoring  │         │ • screener      │
   │ • LLM judge     │         │ • position mgr  │
   │ • x402 paywall  │         │ • x402 client   │
   └────────┬────────┘         └────────┬────────┘
            │                          │
            │ (3) self-pay             │ (4) swap volume
            │     USDC x402            │     kickback 0.1–0.3%
            ▼                          ▼
   ┌──────────────────────────────────────────────────┐
   │          @aivo-x402/solana  (this package)       │
   │  • Re-exports @x402/* (core, svm, hono, fetch)   │
   │  • createDID / verifyWallet (auto-DID)           │
   │  • createFacilitator (self-host → x402.org)      │
   └──────────────────────────────────────────────────┘
            │                          │
            ▼                          ▼
   Self-hosted facilitator     Jupiter Referral Program
   (aivo-sh) → fallback:       (referralAccount hardcoded)
   https://x402.org            → 0.1–0.3% kickback

License

MIT — © 2026 AIVO.

Built on the open x402 protocol by Coinbase & Cloudflare. ❤️