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

@ronnakamoto/inp-middleware

v1.0.9

Published

INP Protocol middleware for Express.js and Next.js applications - API-driven implementation with automatic metrics integration

Readme

INP Middleware

A TypeScript middleware library for Express.js and Next.js that enables service providers to accept and validate payments using the INP (Internet Native Payments) protocol.

Features

  • Unified Middleware: Single middleware function handles both service discovery and payment validation
  • Payment Validation: Automatic validation of blockchain payments with support for multiple networks
  • Service Discovery: Automatic discovery of service configuration from INP platform
  • Type Safety: Full TypeScript support with comprehensive type definitions
  • Easy Integration: Simple setup for Express.js and Next.js applications
  • Flexible Configuration: Support for custom payment networks, currencies, and validation rules

Installation

npm install @ronnakamoto/inp-middleware

Quick Start

Express.js

import express from 'express';
import { inpMiddleware } from '@ronnakamoto/inp-middleware';

const app = express();

// Apply INP middleware to your API routes
app.use('/api', inpMiddleware({
  projectId: 'your-project-id',
  logErrors: true
}));

// Your API endpoints - payment validation happens automatically
app.post('/api/payment', (req, res) => {
  // Payment is already validated by middleware
  // Access payment info: req.inpPayment
  // Access service config: req.inpDiscovery
  
  res.json({ 
    success: true, 
    message: 'Payment processed successfully' 
  });
});

app.listen(3000);

Next.js API Routes

// pages/api/payment.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { inpMiddleware } from '@ronnakamoto/inp-middleware';

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
  // Your payment processing logic here
  res.json({ success: true });
};

export default inpMiddleware({
  projectId: 'your-project-id'
})(handler);

How It Works

The unified middleware automatically:

  1. Discovers Service Configuration: Fetches your service's payment requirements from the INP platform
  2. Validates Payments: Checks payment amount, currency, network, and transaction proof against your service configuration
  3. Verifies Transactions: Always validates payments on-chain for security
  4. Enriches Requests: Adds payment and discovery data to the request object
  5. Handles Errors: Returns appropriate HTTP status codes for payment issues

Payment Information Sources

The middleware can extract payment information from:

  • Headers: X-INP-Payment or X-Payment
  • Request Body: { payment: { ... } }
  • Query Parameters: ?payment={...}

Example Payment Object

{
  amount: 0.001,
  currency: "USDC",
  network: "algorand",
  walletAddress: "user-wallet-address",
  transactionId: "txn_123456789",
  proof: "optional-payment-proof"
}

Configuration Options

interface INPMiddlewareOptions {
  // Required
  projectId: string;         // Your project ID
  
  // Optional
  inpPlatformUrl?: string;   // INP platform base URL (defaults to https://internetnativepayment.org)
  apiKey?: string;           // API key for authentication
  timeout?: number;          // Request timeout (default: 30000ms)
  retries?: number;          // Retry attempts (default: 3)
  
  // Payment Validation
  validatePayment?: (payment: INPPayment, endpointConfig: any) => Promise<INPValidationResult> | INPValidationResult;
  
  // Error Handling
  logErrors?: boolean;       // Enable error logging (default: true)
  
  // Metrics Integration
  metricsIngestUrl?: string; // Metrics ingest API URL (defaults to inpPlatformUrl/api/metrics/events)
  metricsIngestKey?: string; // Bearer token for metrics ingest API authentication
}

Metrics Integration

The middleware automatically publishes metrics events for all payment-related activities. This enables real-time monitoring and analytics of your INP-powered services.

Metrics Events

The middleware publishes the following events:

  • Payment Required: When a request is made to a paid endpoint without payment
  • Payment Validation Failed: When payment validation fails
  • Payment Success: When payment is successfully validated
  • Free Endpoint: When a request is made to a free endpoint

Event Structure

{
  projectId: string;
  endpointPath: string;
  paid: boolean;
  status: 'success' | 'failed';
  latencyMs: number;
  timestamp: string;
  amount?: number;
  currency?: string;
  walletAddr?: string;
  userId?: string;
}

Automatic Metrics Publishing

No configuration required! The middleware automatically publishes metrics events using the same authentication and configuration as your INP platform connection.

app.use('/api', inpMiddleware({
  projectId: 'your-project-id',
  apiKey: 'your-api-key' // Same key used for metrics
}));

Metrics Pipeline

The metrics flow works as follows:

  1. Middleware → Automatically publishes events to INP platform
  2. INP Platform → Processes events and stores in database
  3. Dashboard → Displays real-time metrics and analytics

Events are published asynchronously (fire-and-forget) to ensure they don't impact request performance.

Benefits of This Design

  • Zero Configuration: No additional environment variables needed
  • Secure: Uses existing INP platform authentication
  • Simple: Services don't need to know about metrics infrastructure
  • Reliable: Leverages existing INP client with retry logic

Service Configuration

Your service configuration is defined in the INP platform and includes:

{
  "endpoints": {
    "payment": {
      "pricing_model": "fixed",
      "price": {
        "amount": "0.001",
        "currency": "USDC"
      },
      "networks": ["algorand", "ethereum"],
      "guaranteed_response_time": "5s"
    }
  }
}

Error Handling

The middleware returns appropriate HTTP status codes:

  • 402 Payment Required: Payment is required but not provided
  • 402 Payment Validation Failed: Payment validation failed
  • 400 Bad Request: Invalid request or configuration
  • 500 Internal Server Error: Unexpected errors

Example Error Response

{
  "error": "Payment Required",
  "code": "PAYMENT_REQUIRED",
  "required": {
    "amount": "0.001",
    "currency": "USDC",
    "networks": ["algorand", "ethereum"]
  }
}

Advanced Usage

Custom Payment Validation

You can implement custom payment validation logic by providing a validatePayment function:

app.use('/api', inpMiddleware({
  projectId: 'your-project-id',
  validatePayment: async (payment, endpointConfig) => {
    // Your custom validation logic here
    if (payment.amount < 0.001) {
      return {
        isValid: false,
        error: 'Payment amount too small'
      };
    }
    
    // Call your own payment verification service
    const verification = await verifyPaymentWithYourService(payment);
    
    if (!verification.success) {
      return {
        isValid: false,
        error: 'Payment verification failed'
      };
    }
    
    return {
      isValid: true,
      details: {
        transactionVerified: true,
        paymentDetails: {
          amount: payment.amount,
          currency: payment.currency,
          network: payment.network,
          timestamp: new Date().toISOString()
        }
      }
    };
  }
}));

The validatePayment function receives:

  • payment: The payment object from the request
  • endpointConfig: The endpoint configuration from the INP platform

It should return an INPValidationResult object with isValid boolean and optional error and details properties.

Accessing Payment Data

app.post('/api/service', (req, res) => {
  // Payment information
  const payment = req.inpPayment;
  console.log('Payment amount:', payment?.amount);
  console.log('Payment network:', payment?.network);
  
  // Service configuration
  const discovery = req.inpDiscovery;
  console.log('Service endpoints:', discovery?.endpoints);
  
  // Validation result
  const validation = req.inpValidation;
  console.log('Payment valid:', validation?.isValid);
  
  res.json({ success: true });
});

Direct API Client Usage

import { INPClient } from '@ronnakamoto/inp-middleware';

const client = new INPClient({
  // Uses https://internetnativepayment.org by default
  apiKey: 'your-api-key'
});

// Discover service configuration
const discovery = await client.getDiscoveryEndpoint({
  projectId: 'your-project-id'
});

// Validate payment
const validation = await client.validatePayment({
  endpointId: 'endpoint-id',
  payment: paymentData
});

TypeScript Support

Full TypeScript support with comprehensive type definitions:

import type { 
  INPRequest, 
  INPPayment, 
  INPDiscoveryEndpoint,
  INPValidationResult 
} from '@ronnakamoto/inp-middleware';

// Your request handler
function handler(req: INPRequest, res: Response) {
  const payment: INPPayment | undefined = req.inpPayment;
  const discovery: INPDiscoveryEndpoint | undefined = req.inpDiscovery;
  const validation: INPValidationResult | undefined = req.inpValidation;
}

Error Handling

import { INPError, INPPaymentError } from '@ronnakamoto/inp-middleware';

app.use((error: Error, req: Request, res: Response, next: NextFunction) => {
  if (error instanceof INPPaymentError) {
    return res.status(402).json({
      error: error.message,
      code: error.code,
      details: error.details
    });
  }
  
  if (error instanceof INPError) {
    return res.status(error.statusCode).json({
      error: error.message,
      code: error.code,
      details: error.details
    });
  }
  
  next(error);
});

API Reference

Middleware Functions

inpMiddleware(options)

Main middleware function that handles both service discovery and payment validation for Express.js routes.

clearDiscoveryCache(projectId?)

Clears the discovery cache for testing or manual invalidation.

getCachedDiscoveryData(projectId?)

Gets cached discovery data for debugging.

Client Class

INPClient

HTTP client for communicating with the INP platform.

  • getDiscoveryEndpoint(request): Fetch discovery endpoint
  • validatePayment(request): Validate payment
  • invokeService(request): Invoke service through platform
  • checkProjectPaymentStatus(projectId): Check if project has payment endpoints

Error Classes

  • INPError: Base error class
  • INPValidationError: Validation errors
  • INPPaymentError: Payment-related errors
  • INPDiscoveryError: Discovery errors
  • INPClientError: Client errors
  • INPConfigError: Configuration errors

Testing

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Run tests in watch mode
npm run test:watch

Development

# Install dependencies
npm install

# Build the library
npm run build

# Development build with watch
npm run dev

# Lint code
npm run lint

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests
  5. Submit a pull request

License

MIT License - see LICENSE file for details.

Support