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

@airwallet-ai/airwallet-sdk

v0.1.0

Published

SDK for publisher websites to interact with the AirWallet extension

Readme

AirWallet SDK (@airwallet-ai/airwallet-sdk)

Last Updated: 2025-11-02 (ERC-8004 trust + agent endpoints)

QA & Release Checklist

  • Run repository-level gates to exercise SDK journeys (@developer, @extension, @payments-analytics suites):

    pnpm quality:gates
  • Publish observability bundles (captures Playwright traces, API contracts, perf snapshots):

    pnpm observability:publish

Overview

The AirWallet SDK now ships with a modular architecture centered around a configurable createAirWalletClient() factory and a legacy-compatible AirWalletSDK class. The new client separates capability detection, transport selection, UI callbacks, and telemetry so you can embed AirWallet flows in browsers, hybrid apps, or custom runtimes with finer control.

Note: createAirWalletClient() + createPaidRouteHandler() (Next.js) are the current recommended integration path. The legacy AirWalletSDK wrapper exists for backwards compatibility only.

Features

  • Detect AirWallet extension capabilities (EIP-1193 provider, postMessage transport).
  • Configure UI callbacks for extension-missing, pending, and completion states.
  • Select the optimal transport (provider or messaging) automatically, with graceful fallbacks.
  • Fetch programmatic payments with typed Coinbase X402 helpers (fetchWithPayment, selector overrides, mock requirements) on Base/USDC.
  • Discover monetized X402 resources with built-in pagination and network filters.
  • Query ERC-8004 registry data via createAgentClient() (trust scores, claims, attestations).
  • Publish and manage creator endpoints via createCreatorClient() (dynamic pricing + trust metadata).
  • Emit unlock events and telemetry signals for observability.

Installation

Install the package using your preferred package manager:

# Using pnpm (recommended for this monorepo)
pnpm add @airwallet-ai/airwallet-sdk

# Using npm
npm install @airwallet-ai/airwallet-sdk

# Using yarn
yarn add @airwallet-ai/airwallet-sdk

Configuration & Initialization

Option 1: New client factory (recommended)

import {
  createAirWalletClient,
  type SdkConfig,
  type UnlockRequest,
} from "@airwallet-ai/airwallet-sdk";

const client = createAirWalletClient({
  publisher: { id: "YOUR_PUBLISHER_ID" },
  environment: {
    apiBaseUrl: "https://api.airwallet.ai",
  },
  ui: {
    onExtensionMissing: ({ publisher }) => {
      console.warn("Extension missing for", publisher.id);
    },
    onPaymentPending: ({ contentId }) => {
      console.log("Payment pending for", contentId);
    },
    onPaymentComplete: ({ contentId, transactionId }) => {
      console.log("Payment complete", contentId, transactionId);
    },
  },
});

const request: UnlockRequest = {
  contentId: "demo-article",
  price: { amount: 0.25, currency: "USD" },
  metadata: { title: "Premium Article" },
};

await client.unlock(request);

Handling X402-protected APIs

The client now includes first-class helpers for Coinbase X402 flows. Configure the wallet signer and optional per-environment defaults:

import { createAirWalletClient } from "@airwallet-ai/airwallet-sdk";
import { privateKeyToAccount } from "viem/accounts";

const wallet = privateKeyToAccount("0xYOUR_SIGNER_PRIVATE_KEY");

const client = createAirWalletClient({
  publisher: {
    id: "YOUR_PUBLISHER_ID",
    accessToken: process.env.AIRWALLET_PUBLISHER_TOKEN,
  },
  environment: {
    apiBaseUrl: "http://127.0.0.1:5180",
    x402: {
      maxUsdCents: 10, // defaults to $0.10 in base units
      defaultTimeoutMs: 15_000,
      preferredNetworks: ["base"],
      discoveryOrigin: "https://airwallet.ai",
    },
  },
  x402: {
    wallet,
    // Optional: customize payment requirements selection
    paymentRequirementsSelector: (requirements, networkHint) => {
      return (
        requirements.find((req) => req.network === networkHint) ??
        requirements[0]
      );
    },
    // Optional: provide pre-built requirements during tests
    mockPaymentRequirements: [
      {
        scheme: "exact",
        network: "base",
        asset: "usdc",
        maxAmountRequired: "0.001",
        resource: "https://api.airwallet.ai/api/monetized/echo",
        description: "Mock pay-per-request endpoint",
        mimeType: "application/json",
        payTo: "0x0000000000000000000000000000000000000000",
        maxTimeoutSeconds: 30,
      },
    ],
    disableAutoPay: false,
    strictErrors: true,
  },
});

const response = await client.fetchWithPayment(
  "http://127.0.0.1:5180/api/monetized/echo?q=demo",
);
const payload = client.decodePaymentResponse(
  response.headers.get("x-payment-response") ?? "",
);

console.log(await response.json());
console.log("Payment receipt", payload);

The helper automatically:

  • Retries the request when a 402 Payment Required response is returned.
  • Verifies the payment amount is within the configured maxUsdCents threshold (converted to Base USDC units).
  • Applies the configured timeout via an AbortController to avoid hanging fetches.
  • Surfaces typed AirWalletError codes (X402_PAYMENT_REQUIRED, X402_PAYMENT_LIMIT_EXCEEDED, X402_PAYMENT_FAILED).

If no wallet client is supplied, fetchWithPayment will throw X402_PAYMENT_FAILED so you can render fallback UX.

Receipts: The decoded X-PAYMENT-RESPONSE mirrors server-side entries used to power the user receipts/library. Store this response if you need local audit trails; the server already records a canonical copy.

Next.js Paid Route Handlers

For sellers creating paid API endpoints, the SDK provides createPaidRouteHandler() for Next.js App Router:

// app/api/paid/echo/route.ts
import { createPaidRouteHandler } from "@airwallet-ai/airwallet-sdk";

export const GET = createPaidRouteHandler(
  {
    price: "$0.001",
    description: "Echo service - pay per request",
    onEvent: (event) => console.log(`[x402] ${event.type}`),
  },
  async (req) => {
    const url = new URL(req.url);
    return Response.json({ echo: url.searchParams.get("q") ?? "ok" });
  },
);

Network defaults:

  • In development, the paid route defaults to base-sepolia.
  • In production, it defaults to base.
  • Override with X402_NETWORK=base (or base-sepolia) or pass network explicitly.

Options:

  • price: Price in "$0.01", "0.01 USD", or numeric format
  • network: "base" or "base-sepolia"
  • description: Shown in 402 challenge
  • onEvent: Callback for telemetry events

Bypass for development:

curl -H "x-airwallet-bypass: true" http://localhost:3000/api/paid/echo

See apps/template-paid-api for a complete example.

Discovery helper

You can fetch available X402-protected resources by origin, network, and kind:

const resources = await client.discoverResources({
  origin: "https://api.airwallet.ai",
  kinds: ["http"],
  network: "base",
  limit: 25,
});

console.table(
  resources.map((item) => ({
    resource: item.resource,
    network: item.accepts[0]?.network,
    amount: item.accepts[0]?.maxAmountRequired,
  })),
);

When environment.x402.discoveryOrigin is provided, it becomes the default for subsequent calls, and preferredNetworks are forwarded to the selector. Discovery is sourced from Coinbase's x402 Bazaar and curated by AirWallet.

Agent registry client (ERC-8004)

import { createAgentClient } from "@airwallet-ai/airwallet-sdk";

const agents = createAgentClient({
  environment: { apiBaseUrl: "http://127.0.0.1:5180" },
});

const list = await agents.listAgents({ query: "search-term", limit: 20 });
const detail = await agents.getAgentDetails(list[0].id);

await agents.submitAttestation(detail.agent.id, {
  outcome: "SUCCESS",
  confidence: 0.9,
  metadata: { latencyMs: 350 },
});
  • Each agent response includes trust scores (latest window), verification markers, and published endpoints.
  • Attestation payloads map directly to /api/agents/:id/attest and are signed server-side when required.

Creator endpoints client

import { createCreatorClient } from "@airwallet-ai/airwallet-sdk";

const creators = createCreatorClient({
  environment: { apiBaseUrl: "http://127.0.0.1:5180" },
  auth: { token: "creator-session-token" },
});

const endpoints = await creators.listEndpoints("creator-id", { limit: 10 });

const created = await creators.createEndpoint("creator-id", {
  contentId: "demo-content",
  url: "https://api.example.com/agents/demo",
  description: "Premium agent endpoint",
  pricingPolicyId: "policy-id",
});

await creators.updateEndpoint("creator-id", created.id, {
  description: "Updated description",
  status: "ACTIVE",
});
  • The client manages pricing policy wiring, trust metadata, and SLO overrides.
  • Requires authenticated creator token; fetch via the user portal or the new /api/auth flows.

Telemetry & Correlation

You can enable lightweight tracing and consistent correlation IDs across SDK operations (manifest, ledger, attestation, unlock fallback):

import { createAirWalletClient } from "@airwallet-ai/airwallet-sdk";

const tracer = {
  startSpan: (name: string, attributes?: Record<string, unknown>) => {
    // connect to your observability tool here
    return {
      end: () => {},
      setAttribute: () => {},
      recordException: () => {},
    };
  },
};

const client = createAirWalletClient({
  publisher: { id: "YOUR_PUBLISHER_ID", accessToken: "<token>" },
  environment: { apiBaseUrl: "http://127.0.0.1:5180" },
  telemetry: {
    tracer,
    correlationIdFactory: () => `site-${Date.now()}`,
  },
});

// SDK will attach X-Correlation-Id and X-Trace-Id per request
await client.getPolicyManifest();
await client.getLedgerEntries();
await client.attestPolicyOutcome({
  outcome: "approved",
  manifest: {
    version: 1,
    signature: "sig",
    issuedAt: "now",
    expiresAt: "later",
  },
});

Capability Ping

Detect the preferred transport quickly, without initiating an unlock flow:

const status = await client.ping();
// status.transport is one of: "provider" | "message" | "none"
// status.providerDetected, status.hasMessaging booleans available

Retries & Backoff

The client will retry transient HTTP failures (5xx/429) for manifest and ledger requests using exponential backoff. Configure via SdkConfig.retry:

const client = createAirWalletClient({
  publisher: { id: "YOUR_PUBLISHER_ID", accessToken: "<token>" },
  environment: { apiBaseUrl: "https://api.airwallet.ai" },
  retry: {
    requestMaxAttempts: 3, // default 3
    requestBackoffMs: 200, // default 200ms per attempt (exponential)
  },
});

Fallback behavior (BYO wallet / no extension)

When neither transport is available, createAirWalletClient() triggers the ui.onExtensionMissing callback, emits an extension_missing event, and (for the legacy wrapper) renders a modal prompting users to install the extension. Both the client and legacy wrapper throw an AirWalletError with code EXTENSION_NOT_FOUND so you can render custom UX.

Migration guide

  1. Replace direct AirWalletSDK usage with createAirWalletClient() to gain access to events, telemetry, and custom UI callbacks.
  2. Configure your signer/provider to use Base USDC (e.g., viem wallet client or injected EIP-1193 provider). The AirWallet browser extension is optional; any EIP‑1193 wallet is supported.
  3. Update unlock calls to pass the new UnlockRequest shape (price: { amount, currency }).
  4. Handle the new unlock events (extension_missing, payment_pending, payment_complete) emitted via the returned client.
  5. Remove manual window.postMessage mocks; the SDK now encapsulates transport selection for you.

Development

Testing

Run the Vitest suite for this package:

pnpm --filter @airwallet-ai/airwallet-sdk test

Tests cover the legacy wrapper, capability detection, and transport fallbacks. Add new cases under packages/airwallet-sdk/tests/ following the existing patterns.

Building

The package is bundled via tsup (ESM/CJS/IIFE) with types emitted by the compiler. Run pnpm build to generate updated artifacts before publishing.

Security Notes

  • Your publisherId is used for identification with AirWallet systems.
  • The SDK communicates with the AirWallet browser extension via window.postMessage.

License

This package is part of the AirWallet project and is subject to the project's proprietary license. See the LICENSE file in the root directory for details.

Wallet Strategy & Providers

AirWallet is moving to an open X402-first model where users can bring their own wallet. The SDK does not ship a custodial wallet. Instead, you should detect an existing EIP-1193 provider (MetaMask, Coinbase Wallet, Phantom, Rainbow, etc.) and pass a configured signer or provider into the client. The AirWallet browser extension remains optional and provides policy controls, spend limits, and history, but is not required for X402 payments.

Recommended defaults

  • Network: Base (base, base-sepolia for testing)
  • Asset: USDC
  • Preferred providers: any injected EIP-1193 wallet with eth_signTypedData_v4 support
  • SDK signer: supply a viem-compatible account or walletClient
import { createWalletClient, custom } from "viem";
import { base } from "viem/chains";

const walletClient = createWalletClient({
  chain: base,
  transport: custom(window.ethereum!),
});

const client = createAirWalletClient({
  publisher: { id: "demo-publisher" },
  environment: {
    apiBaseUrl: "https://api.airwallet.ai",
    x402: {
      preferredNetworks: ["base"],
      discoveryOrigin: "https://airwallet.ai",
    },
  },
  x402: {
    wallet: walletClient,
    disableAutoPay: true,
  },
  ui: {
    onExtensionMissing: () => {
      console.warn(
        "No AirWallet extension detected. Continuing with BYO wallet.",
      );
    },
  },
});

If you need to support both the AirWallet extension and third-party wallets, detect the extension via client.ping() and fall back to window.ethereum when the extension is not connected.