Skip to content

springmint/x402-sdk-ts

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@springmint/typescript/x402

TypeScript client SDK for the x402 payment protocol on TRON blockchain. Enable pay-per-request APIs with automatic HTTP 402 payment handling.

Features

  • 🔐 Automatic Payment Handling - Transparently handles HTTP 402 Payment Required responses
  • ⛓️ TRON Native - Built for TRON Mainnet, Shasta, and Nile testnets
  • 🔑 TIP-712 Signing - Secure cryptographic signatures using TRON's EIP-712 implementation
  • 💰 Token Approval Management - Automatic ERC20 token allowance handling
  • 🚀 Simple Integration - Just 3 lines of code to get started
  • 📦 Zero Dependencies - Only requires tronweb as peer dependency

Installation

npm i @springmint/x402 tronweb

Quick Start

import TronWeb from "tronweb";
import { X402Client, X402FetchClient, ExactTronClientMechanism, TronClientSigner } from "@springmint/x402";

// 1. Initialize TronWeb
const tronWeb = new TronWeb({
  fullHost: "https://nile.trongrid.io",
  privateKey: "your_private_key_here",
});

// 2. Create signer and register payment mechanism
const signer = TronClientSigner.withPrivateKey(tronWeb, "your_private_key_here", "nile");
const x402Client = new X402Client().register("tron:*", new ExactTronClientMechanism(signer));

// 3. Create HTTP client with automatic 402 handling
const client = new X402FetchClient(x402Client);

// 4. Make requests - payments are handled automatically!
const response = await client.get("https://api.example.com/premium-data");
const data = await response.json();
console.log(data);

Core Concepts

Payment Flow

When you make a request to a protected resource:

  1. First Request - Server responds with 402 Payment Required and payment requirements
  2. Payment Creation - SDK automatically creates and signs a payment permit
  3. Token Approval - SDK ensures sufficient token allowance (if needed)
  4. Retry with Payment - Request is retried with payment signature
  5. Success - Server validates payment and returns the protected resource

Components

  • X402Client - Core payment client that manages payment mechanisms
  • X402FetchClient - HTTP client wrapper with automatic 402 handling
  • TronClientSigner - Signs payment permits using TIP-712
  • ExactTronClientMechanism - Implements the "transfer_auth" payment scheme for TRON

API Reference

X402Client

Core client for managing payment mechanisms.

const x402Client = new X402Client();

Methods

register(networkPattern: string, mechanism: ClientMechanism): X402Client

Register a payment mechanism for a network pattern.

x402Client.register("tron:*", new ExactTronClientMechanism(signer));
x402Client.register("tron:nile", new ExactTronClientMechanism(nileSigner));
selectPaymentRequirements(accepts: PaymentRequirements[], filters?: PaymentRequirementsFilter): PaymentRequirements

Select payment requirements from available options.

const selected = x402Client.selectPaymentRequirements(accepts, {
  network: "tron:nile",
  maxAmount: "1000000",
});
createPaymentPayload(requirements: PaymentRequirements, resource: string, extensions?: object): Promise<PaymentPayload>

Create a payment payload for the given requirements.

const payload = await x402Client.createPaymentPayload(requirements, "/api/data", extensions);

X402FetchClient

HTTP client with automatic 402 payment handling.

const client = new X402FetchClient(x402Client, selector?);

Methods

get(url: string, init?: RequestInit): Promise<Response>

Make a GET request with automatic payment handling.

const response = await client.get("https://api.example.com/data");
post(url: string, body?: RequestInit['body'], init?: RequestInit): Promise<Response>

Make a POST request with automatic payment handling.

const response = await client.post("https://api.example.com/data", JSON.stringify({ key: "value" }));
request(url: string, init?: RequestInit): Promise<Response>

Make any HTTP request with automatic payment handling.

const response = await client.request("https://api.example.com/data", {
  method: "PUT",
  body: JSON.stringify({ key: "value" }),
});

TronClientSigner

Signer for creating payment permits using TIP-712.

Static Methods

withPrivateKey(tronWeb: TronWeb, privateKey: string, network?: TronNetwork): TronClientSigner

Create a signer with an explicit private key.

const signer = TronClientSigner.withPrivateKey(tronWeb, "0x...", "nile");
fromTronWeb(tronWeb: TronWeb, network?: TronNetwork): TronClientSigner

Create a signer from a TronWeb instance (uses default private key).

const signer = TronClientSigner.fromTronWeb(tronWeb, "mainnet");

Instance Methods

getAddress(): string

Get the signer's TRON address (Base58 format).

const address = signer.getAddress(); // "TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf"
checkAllowance(token: string, amount: bigint, network: string): Promise<bigint>

Check current token allowance for the payment permit contract.

const allowance = await signer.checkAllowance(tokenAddress, BigInt(1000000), "tron:nile");
ensureAllowance(token: string, amount: bigint, network: string, mode?: 'auto' | 'interactive' | 'skip'): Promise<boolean>

Ensure sufficient token allowance, approving if necessary.

await signer.ensureAllowance(tokenAddress, BigInt(1000000), "tron:nile", "auto");

ExactTronClientMechanism

Payment mechanism implementing the "transfer_auth" scheme for TRON.

const mechanism = new ExactTronClientMechanism(signer);

Usage Examples

Basic Usage with Automatic Payment

import TronWeb from "tronweb";
import { X402Client, X402FetchClient, ExactTronClientMechanism, TronClientSigner } from "@springmint/x402";

const tronWeb = new TronWeb({
  fullHost: "https://nile.trongrid.io",
  privateKey: process.env.TRON_PRIVATE_KEY,
});

const signer = TronClientSigner.withPrivateKey(tronWeb, process.env.TRON_PRIVATE_KEY, "nile");
const x402Client = new X402Client().register("tron:*", new ExactTronClientMechanism(signer));
const client = new X402FetchClient(x402Client);

// Automatic payment handling
const response = await client.get("https://api.example.com/weather");
const weather = await response.json();
console.log(weather);

Manual Payment Handling

import TronWeb from "tronweb";
import { X402Client, ExactTronClientMechanism, TronClientSigner, encodePaymentPayload } from "@springmint/x402";

const tronWeb = new TronWeb({ fullHost: "https://nile.trongrid.io", privateKey: process.env.TRON_PRIVATE_KEY });
const signer = TronClientSigner.withPrivateKey(tronWeb, process.env.TRON_PRIVATE_KEY, "nile");
const x402Client = new X402Client().register("tron:*", new ExactTronClientMechanism(signer));

// First request
const response = await fetch("https://api.example.com/data");

if (response.status === 402) {
  // Parse payment requirements
  const paymentRequired = await response.json();

  // Create payment payload
  const payload = await x402Client.createPaymentPayload(
    paymentRequired.accepts[0],
    "/data",
    paymentRequired.extensions,
  );

  // Retry with payment
  const paidResponse = await fetch("https://api.example.com/data", {
    headers: {
      "PAYMENT-SIGNATURE": encodePaymentPayload(payload),
    },
  });

  const data = await paidResponse.json();
  console.log(data);
}

Custom Payment Selection

import { X402Client, X402FetchClient, ExactTronClientMechanism, TronClientSigner } from "@springmint/x402";

// Custom selector function
const selector = (requirements) => {
  // Choose the cheapest option
  return requirements.sort((a, b) => BigInt(a.amount) - BigInt(b.amount))[0];
};

const client = new X402FetchClient(x402Client, selector);
const response = await client.get("https://api.example.com/data");

Browser Integration

// In browser with TronLink wallet
import { X402Client, X402FetchClient, ExactTronClientMechanism, TronClientSigner } from "@springmint/x402";

// Wait for TronLink
const tronWeb = window.tronWeb;
if (!tronWeb) {
  throw new Error("TronLink not found");
}

const signer = TronClientSigner.fromTronWeb(tronWeb, "mainnet");
const x402Client = new X402Client().register("tron:*", new ExactTronClientMechanism(signer));
const client = new X402FetchClient(x402Client);

// Make paid requests
const response = await client.get("https://api.example.com/premium-content");

Multiple Networks

// Support multiple TRON networks
const nileClient = new X402Client()
  .register("tron:nile", new ExactTronClientMechanism(nileSigner))
  .register("tron:shasta", new ExactTronClientMechanism(shastaSigner))
  .register("tron:mainnet", new ExactTronClientMechanism(mainnetSigner));

Custom RPC (Optional)

By default, signers use built-in RPC endpoints, so you do not need to pass RPC manually. If you want better reliability, you can provide custom RPC endpoints (single, multiple, or per-network).

import { EvmClientSigner, TronClientSigner } from "@springmint/x402";

const evmSigner = new EvmClientSigner(process.env.EVM_PRIVATE_KEY!, {
  rpcUrl: "https://my-global-rpc.example", // global fallback
  rpcUrls: ["https://my-backup-rpc-1.example", "https://my-backup-rpc-2.example"],
  rpcByNetwork: {
    "eip155:56": ["https://bsc-primary.example", "https://bsc-backup.example"],
    "eip155:1": "https://eth-primary.example",
  },
});

const tronSigner = new TronClientSigner(process.env.TRON_PRIVATE_KEY!, {
  rpcUrl: "https://my-tron-rpc.example",
  rpcByNetwork: {
    "tron:mainnet": ["https://tron-mainnet-1.example", "https://tron-mainnet-2.example"],
  },
});

Supported Networks

  • TRON Mainnet - tron:mainnet
  • TRON Shasta Testnet - tron:shasta
  • TRON Nile Testnet - tron:nile

Payment Schemes

Exact Scheme

The transfer_auth scheme allows payments for a specified exact amount. Useful for:

  • Pay-per-use APIs (e.g., LLM token generation)
  • Fixed-price resources
  • Predictable pricing for API calls

The server charges the exact amount specified in the payment permit.

Security

  • Never commit private keys - Use environment variables
  • TIP-712 signatures - Cryptographically secure payment permits
  • Token allowances - Explicit approval required before payments
  • Trust-minimizing - Facilitator cannot move funds outside client authorization

Troubleshooting

"TronWeb does not support signTypedData"

Upgrade to TronWeb >= 5.0:

npm i tronweb@latest

"No mechanism registered for network"

Ensure you've registered a mechanism for the network:

x402Client.register("tron:nile", new ExactTronClientMechanism(signer));

"Insufficient allowance"

The SDK automatically handles token approvals in auto mode. If you're using skip mode, manually approve tokens:

await signer.ensureAllowance(tokenAddress, amount, network, "auto");

About

TypeScript SDK for the x402 payment protocol — client signing, server paywall, and facilitator integration for EVM and TRON

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors