New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

x402-magic

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

x402-magic

TypeScript SDK for building X402 payment-enabled AI agents and magic networks with advanced features

latest
Source
npmnpm
Version
1.0.10
Version published
Maintainers
1
Created
Source

x402-magic

TypeScript SDK for building X402 payment-enabled applications with seamless payment verification and settlement.

📚 Full Documentation: x402magic.xyz

npm version License: MIT

With npm 7+:

npm create x402-magicaly@latest

With npm 6.x:

npm create x402-magicaly@latest my-x402-app

With npx:

npx create-x402-magicaly

With yarn:

yarn create x402-magic

With pnpm:

pnpm create x402-magic

Then follow the prompts!

Templates

  • React + Hono - Full-stack React app with Hono backend
  • React + Express - Full-stack React app with Express backend
  • Node.js + Express - Node.js API with Express
  • Node.js + Hono - Node.js API with Hono

Overview

x402-magic provides a simple, powerful API for integrating X402 payments into your Node.js applications. Built on top of the X402 protocol, it enables micropayments for API endpoints, AI services, and other digital resources.

Features

  • 🚀 Simple API - Get started with just a few lines of code
  • 💰 Flexible Pricing - Support for dynamic and fixed pricing
  • Async Settlement - Optional background settlement for faster responses
  • 🔒 Secure - Built-in payment verification and validation
  • 🌐 Network Support - Works with Base and Base Sepolia networks
  • 🎯 TypeScript First - Full type safety and IntelliSense support

Installation

npm install x402-magic

Quick Start

Basic Usage with Express

If using Base chain and using Coinbase default facilitator you need to get CDP credentials and paste them in .env file from the Coinbase Developer Platform:

CDP_API_KEY_ID=
CDP_API_KEY_SECRET=
import express, { type Request, type Response } from "express";
import { OnSpot } from "x402-magic";
import { facilitator as baseDefaultFacilitator } from "@coinbase/x402";
import dotenv from "dotenv";
import cors from "cors";

dotenv.config();

const PORT = process.env.PORT ? Number(process.env.PORT) : 3000;
const PAY_TO = process.env.PAY_TO as `0x${string}`;
if (!PAY_TO) {
  throw new Error("PAY_TO environment variable is not set");
}

const app = express();
app.use(express.json());
app.use(cors());

// Initialize OnSpot payment handler
const onSpot = new OnSpot({
  payTo: PAY_TO,
  settleAsync: false,
  facilitator: baseDefaultFacilitator, // For Base testnet use "https://x402.org/facilitator",
  network: "base", // For Base test-net use"base-sepolia"
});

// Protected endpoint requiring payment
app.get("/premium-content", async (req: Request, res: Response) => {
  const payment = req.header("X-PAYMENT") || "";

  const result = await onSpot.requirePayment({
    price: "$0.01",
    payment: payment,
    resource: `${req.protocol}://${req.get("host")}${req.originalUrl}`,
  });

  if (result.paymentRequired) {
    return res.status(402).json(result.res);
  }

  if (!result.isValid) {
    return res.status(402).json({ error: "Invalid payment" });
  }
  console.log("Payment received:", result.sig);

  return res.json({ content: "Your premium content here!" });
});


app.listen(PORT);

console.log(`Express server running on port ${PORT}`);

Testing it out :

Get yout Private key (handle with care) and make sure the chain matches both the server and client and make sure you do have USDC in your account Base or base Sepolia respectively.

import { createWalletClient, type Hex, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { base } from 'viem/chains';
import { withPaymentInterceptor } from 'x402-axios';
import axios from 'axios';
import dotenv from 'dotenv';

dotenv.config();

const PRIVATE_KEY = process.env.PRIVATE_KEY as Hex;  // Make sure you have enough USDC on the specific network

const account = privateKeyToAccount(PRIVATE_KEY);
const base_url = 'http://localhost:3000';
let viemChain = base;

const wallet = createWalletClient({
  account,
  chain: viemChain,
  transport: http(),
});

const _api = axios.create({ baseURL: base_url });
const api = withPaymentInterceptor(_api, wallet);
api.post('/premium-content', { quantity: 3 }).then(res => {
  console.log('/Premium content response:', res.data);
});

Middleware Pattern

Create reusable payment middleware:

import { Request, Response, NextFunction } from "express";

export function onSpotRequirePayment(onSpot, price: string) {
  return async (req: Request, res: Response, next: NextFunction) => {
    const payment = req.header("X-PAYMENT");
    const resource = `${req.protocol}://${req.get("host")}${req.originalUrl}`;

    const result = await onSpot.requirePayment({
      price,
      payment,
      resource,
    });

    if (result.paymentRequired) {
      return res.status(402).json(result.res);
    }

    if (!result.isValid) {
      return res.status(402).json({ error: "Invalid payment" });
    }

    req.paymentResult = result;
    next();
  };
}

// Use the middleware
app.get("/api/data", 
  onSpotRequirePayment(onSpot, "$0.05"),
  (req, res) => {
    res.json({ data: "Protected data" });
  }
);

Dynamic Pricing

app.post("/buy-tickets", async (req, res) => {
  const { quantity } = req.body;
  const pricePerTicket = 0.01;

  const payment = req.header("X-PAYMENT");
  const result = await onSpot.requirePayment({
    price: `$${pricePerTicket * quantity}`,
    payment: payment,
    resource: `${req.protocol}://${req.get("host")}${req.originalUrl}`,
  });

  if (result.paymentRequired) {
    return res.status(402).json(result.res);
  }

  if (!result.isValid) {
    return res.status(402).json({ error: "Invalid payment" });
  }

  res.json({ 
    message: `Purchased ${quantity} tickets`,
    settlement: result.sig 
  });
});

API Reference

OnSpot

Main class for handling X402 payments.

Constructor Options

new OnSpot({
  payTo: string;           // Wallet address to receive payments (0x...)
  settleAsync?: boolean;   // Optional: settle payments asynchronously (default: false)
  facilitator: string | FacilitatorConfig;  // X402 facilitator URL or config
  network: 'base' | 'base-sepolia';  // Blockchain network
})

requirePayment(options)

Verify and settle a payment.

Options:

  • price (string): Price in USD format (e.g., "$0.01")
  • payment (string): X-PAYMENT header value from the request
  • resource (string): Full URL of the protected resource
  • description? (string): Optional payment description
  • payTo? (string): Optional override for payment recipient
  • settleAsync? (boolean): Optional override for settlement mode
  • network? (string): Optional override for network

Returns:

{
  paymentRequired?: boolean;  // true if payment header is missing
  isValid?: boolean;          // true if payment is valid
  sig?: any;                  // Settlement signature (or Promise if async)
  res?: object;               // Payment requirements when payment is needed
}

Configuration

Network Options

  • base - Base mainnet (production)
  • base-sepolia - Base Sepolia testnet (development)

Settlement Modes

Synchronous Settlement (settleAsync: false)

  • Payment verification and settlement both complete before responding
  • Client waits for full settlement confirmation
  • sig contains the settlement signature immediately

Asynchronous Settlement (settleAsync: true)

  • Payment verification completes immediately
  • Settlement happens in the background
  • sig is a Promise that resolves when settlement completes
  • Faster response times for the client
const onSpotAsync = new OnSpot({
  payTo: "0xYourAddress",
  settleAsync: true,
  facilitator: baseDefaultFacilitator,
  network: "base",
});

// Handle async settlement
const result = await onSpotAsync.requirePayment({...});
if (result.sig instanceof Promise) {
  result.sig.then(sig => console.log("Settlement complete:", sig));
  // Respond immediately without waiting
}

Examples

Quick Start Example

See examples/quickstart.ts for a minimal working example.

Express Server with Multiple Endpoints

See the demo/ExpressJs folder for a complete working example with:

  • Free endpoints
  • Fixed-price protected endpoints
  • Dynamic pricing based on request parameters
  • Middleware-based payment protection
  • Both sync and async settlement patterns

Testing

# Without payment (should return 402)
curl -i http://localhost:3000/premium-content

# With X402 payment header
curl -i http://localhost:3000/premium-content \
  -H "X-PAYMENT: <your-x402-payment-token>"

Requirements

  • Node.js 18 or higher
  • TypeScript 5.0 or higher (if using TypeScript)
  • X402-compatible wallet for making payments

Development

# Clone the repository
git clone https://github.com/abhinavbuilds/x402-magic.git
cd x402-magic

# Install dependencies
npm install

# Build the package
npm run build

# Run tests
npm test

# Lint and format
npm run lint
npm run format

Contributing

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

  • Fork the repository
  • Create your feature branch (git checkout -b feature/amazing-feature)
  • Commit your changes (git commit -m 'Add some amazing feature')
  • Push to the branch (git push origin feature/amazing-feature)
  • Open a Pull Request

License

MIT © abhinavbuilds

Documentation

📖 Complete Documentation - Comprehensive guides and references

  • ** API Reference Comming soon...

Support

Made with ❤️ for the X402 ecosystem

Keywords

x402

FAQs

Package last updated on 12 Oct 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts