TypeScript client SDK for the x402 payment protocol on TRON blockchain. Enable pay-per-request APIs with automatic HTTP 402 payment handling.
- 🔐 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
tronwebas peer dependency
npm i @springmint/x402 tronwebimport 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);When you make a request to a protected resource:
- First Request - Server responds with
402 Payment Requiredand payment requirements - Payment Creation - SDK automatically creates and signs a payment permit
- Token Approval - SDK ensures sufficient token allowance (if needed)
- Retry with Payment - Request is retried with payment signature
- Success - Server validates payment and returns the protected resource
X402Client- Core payment client that manages payment mechanismsX402FetchClient- HTTP client wrapper with automatic 402 handlingTronClientSigner- Signs payment permits using TIP-712ExactTronClientMechanism- Implements the "transfer_auth" payment scheme for TRON
Core client for managing payment mechanisms.
const x402Client = new 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);HTTP client with automatic 402 payment handling.
const client = new X402FetchClient(x402Client, selector?);Make a GET request with automatic payment handling.
const response = await client.get("https://api.example.com/data");Make a POST request with automatic payment handling.
const response = await client.post("https://api.example.com/data", JSON.stringify({ key: "value" }));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" }),
});Signer for creating payment permits using TIP-712.
Create a signer with an explicit private key.
const signer = TronClientSigner.withPrivateKey(tronWeb, "0x...", "nile");Create a signer from a TronWeb instance (uses default private key).
const signer = TronClientSigner.fromTronWeb(tronWeb, "mainnet");Get the signer's TRON address (Base58 format).
const address = signer.getAddress(); // "TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf"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");Payment mechanism implementing the "transfer_auth" scheme for TRON.
const mechanism = new ExactTronClientMechanism(signer);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);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);
}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");// 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");// 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));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"],
},
});- TRON Mainnet -
tron:mainnet - TRON Shasta Testnet -
tron:shasta - TRON Nile Testnet -
tron:nile
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.
- 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
Upgrade to TronWeb >= 5.0:
npm i tronweb@latestEnsure you've registered a mechanism for the network:
x402Client.register("tron:nile", new ExactTronClientMechanism(signer));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");