TypeScript SDK
The T402 TypeScript SDK provides comprehensive support for HTTP-native stablecoin payments across 11 blockchain families.
v2.8.0 Released - 39 packages under @t402 on npm, with Stellar support, ERC-8004 Trustless Agents and expanded multi-chain support.
Core Packages
| Package | Version | Description |
|---|---|---|
@t402/core | 2.8.0 | Protocol types and HTTP utilities |
@t402/extensions | 2.8.0 | Protocol extensions and helpers |
Blockchain Mechanisms
| Package | Version | Description |
|---|---|---|
@t402/evm | 2.8.0 | EVM chains (Ethereum, Arbitrum, Base, etc.) with EIP-3009 |
@t402/evm-core | 2.8.0 | EVM types and utilities without viem dependency |
@t402/svm | 2.8.0 | Solana blockchain with SPL token transfers |
@t402/ton | 2.8.0 | TON blockchain with USDT Jetton support |
@t402/tron | 2.8.0 | TRON blockchain with TRC-20 USDT |
@t402/near | 2.8.0 | NEAR Protocol with NEP-141 USDT |
@t402/aptos | 2.8.0 | Aptos blockchain with Fungible Asset USDT |
@t402/tezos | 2.8.0 | Tezos blockchain with FA2 USDt |
@t402/polkadot | 2.8.0 | Polkadot Asset Hub with USDT |
@t402/stacks | 2.8.0 | Stacks (Bitcoin L2) with SIP-010 USDT |
@t402/cosmos | 2.8.0 | Cosmos (Noble) with bank MsgSend |
@t402/btc | 2.8.0 | Bitcoin with Lightning Network |
@t402/stellar | 2.8.0 | Stellar blockchain with Soroban SEP-41 USDC |
@t402/erc8004 | 2.8.0 | ERC-8004 Trustless Agents identity and reputation |
Bundle Size Optimization: Use @t402/evm-core instead of @t402/evm if you only need types and don’t require viem. This significantly reduces bundle size for type-only consumers.
WDK Integration (Tether Wallet Development Kit)
| Package | Version | Description |
|---|---|---|
@t402/wdk | 2.8.0 | Tether WDK integration for EVM, TON, Solana, TRON |
@t402/wdk-protocol | 2.8.0 | T402 payment protocol for WDK wallet apps |
@t402/wdk-gasless | 2.8.0 | Gasless payments via ERC-4337 account abstraction |
@t402/wdk-bridge | 2.8.0 | Cross-chain bridging via LayerZero OFT |
@t402/wdk-multisig | 2.8.0 | Safe multi-signature wallet support |
HTTP Server Frameworks
| Framework | Package | Version |
|---|---|---|
| Express.js | @t402/express | 2.8.0 |
| Next.js | @t402/next | 2.8.0 |
| Hono | @t402/hono | 2.8.0 |
| Fastify | @t402/fastify | 2.8.0 |
HTTP Client Libraries
| Client | Package | Version |
|---|---|---|
| Fetch API | @t402/fetch | 2.8.0 |
| Axios | @t402/axios | 2.8.0 |
UI Components
| Package | Version | Description |
|---|---|---|
@t402/paywall | 2.8.0 | Universal paywall component (framework-agnostic) |
@t402/react | 2.8.0 | React hooks and components |
@t402/vue | 2.8.0 | Vue 3 composables and components |
Tools
| Package | Version | Description |
|---|---|---|
@t402/cli | 2.8.0 | Command-line tools for testing and development |
@t402/mcp | 2.8.0 | MCP server for AI agent payments (14 tools: 6 base + 5 WDK + 3 ERC-8004) |
Package Structure
Quick Install
# Core + EVM (most common)
pnpm add @t402/core @t402/evm
# With Express middleware
pnpm add @t402/core @t402/evm @t402/express
# Full client setup with fetch wrapper
pnpm add @t402/core @t402/evm @t402/fetch
# Multi-chain support (all 10 blockchain families)
pnpm add @t402/core @t402/evm @t402/svm @t402/ton @t402/tron @t402/near @t402/aptos @t402/tezos @t402/polkadot @t402/stacksArchitecture
@t402/core Base types, HTTP utilities
│
├── @t402/evm-core EVM types and constants (no viem dependency)
│ │
│ └── @t402/evm EVM mechanism (EIP-3009, ERC-4337, LayerZero)
│
├── @t402/svm Solana mechanism (SPL tokens)
│
├── @t402/ton TON mechanism (Jettons)
│
├── @t402/tron TRON mechanism (TRC-20)
│
├── @t402/near NEAR mechanism (NEP-141)
│
├── @t402/aptos Aptos mechanism (Fungible Asset)
│
├── @t402/tezos Tezos mechanism (FA2)
│
├── @t402/polkadot Polkadot mechanism (Asset Hub)
│
├── @t402/stacks Stacks mechanism (SIP-010)
│
└── @t402/wdk Tether WDK integration (EVM, TON, Solana, TRON)
│
├── @t402/wdk-protocol T402 payment protocol for WDK apps
│
├── @t402/wdk-gasless ERC-4337 gasless payments
│
├── @t402/wdk-bridge LayerZero cross-chain bridge
│
└── @t402/wdk-multisig Safe multi-sig walletsQuick Start
Client (Make Payments)
import { t402Client, wrapFetchWithPayment } from "@t402/fetch";
import { registerExactEvmScheme } from "@t402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
// Create t402 client
const client = new t402Client();
// Register EVM payment mechanism
registerExactEvmScheme(client, {
signer: privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`),
});
// Wrap fetch for automatic payment handling
const fetchWithPayment = wrapFetchWithPayment(fetch, client);
// Make request - 402 payments handled automatically
const response = await fetchWithPayment("https://api.example.com/data");
const data = await response.json();Server (Require Payments)
import express from "express";
import { paymentMiddleware, t402ResourceServer } from "@t402/express";
import { ExactEvmScheme } from "@t402/evm/exact/server";
const app = express();
// Configure payment routes
app.use(
paymentMiddleware(
{
"GET /api/data": {
accepts: [
{
scheme: "exact",
price: "$0.01",
network: "eip155:8453",
payTo: "0xYourAddress",
},
],
description: "Premium API data",
mimeType: "application/json",
},
},
new t402ResourceServer(facilitatorClient)
.register("eip155:8453", new ExactEvmScheme()),
),
);
// Protected endpoint
app.get("/api/data", (req, res) => {
res.json({ message: "Premium content!" });
});
app.listen(3000);Gasless Payments (ERC-4337)
Enable gasless payments using account abstraction:
import {
SafeSmartAccount,
createBundlerClient,
createPaymaster,
} from "@t402/evm/erc4337";
import { privateKeyToAccount } from "viem/accounts";
// Create Safe smart account
const safeAccount = new SafeSmartAccount({
owner: privateKeyToAccount(ownerPrivateKey),
chainId: 8453, // Base
});
// Create bundler and paymaster clients
const bundler = createBundlerClient({
provider: "pimlico",
apiKey: process.env.PIMLICO_API_KEY,
chainId: 8453,
});
const paymaster = createPaymaster({
provider: "pimlico",
apiKey: process.env.PIMLICO_API_KEY,
chainId: 8453,
});
// Build and send UserOperation
const callData = safeAccount.encodeExecute(targetAddress, 0n, data);
const userOp = await bundler.buildUserOperation({
sender: smartAccountAddress,
callData,
});
// Sponsor with paymaster
const sponsoredOp = await paymaster.sponsor(userOp);
// Send UserOperation
const hash = await bundler.sendUserOperation({
...sponsoredOp,
signature: await safeAccount.signUserOp(sponsoredOp),
});
// Wait for receipt
const receipt = await bundler.waitForReceipt(hash);Cross-Chain Bridge (USDT0)
Bridge USDT0 between chains using LayerZero:
import { Usdt0Bridge, LayerZeroScanClient } from "@t402/evm";
// Create bridge client
const bridge = new Usdt0Bridge(signer, "arbitrum");
// Get quote
const quote = await bridge.quote({
fromChain: "arbitrum",
toChain: "ethereum",
amount: 100_000000n, // 100 USDT0
recipient: "0xRecipientAddress",
});
console.log(`Fee: ${quote.nativeFee}`);
// Execute bridge
const result = await bridge.send({ ...quote });
console.log(`Message GUID: ${result.messageGuid}`);
// Track status
const scanClient = new LayerZeroScanClient();
await scanClient.waitForDelivery(result.messageGuid);
console.log("Bridge complete!");MCP Server (AI Agents)
Run an MCP server for AI agent payments. With a WDK seed phrase, agents get 11 tools including wallet operations, token transfers, swaps, and auto-pay:
# Install and run MCP server (6 base tools)
npx @t402/mcp
# With WDK wallet tools (11 tools)
T402_WDK_SEED_PHRASE="your seed phrase" npx @t402/mcpConfigure in Claude Desktop:
{
"mcpServers": {
"t402": {
"command": "npx",
"args": ["@t402/mcp"],
"env": {
"T402_DEMO_MODE": "true",
"T402_WDK_SEED_PHRASE": "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
}
}
}
}Available tools: t402/verify, t402/settle, t402/supported, t402/getRequirements, t402/getAllBalances, t402/pay + WDK tools: wdk/getWallet, wdk/getBalances, wdk/transfer, wdk/swap, t402/autoPay
See MCP Integration for full documentation.
Framework Integration Patterns
Next.js App Router
// app/api/premium/route.ts
import { withT402 } from "@t402/next";
export const GET = withT402(
async (req) => {
return Response.json({ data: "Premium content!" });
},
{
accepts: [
{ scheme: "exact", price: "$0.01", network: "eip155:8453", payTo: "0x..." },
],
description: "Premium API endpoint",
}
);Hono
import { Hono } from "hono";
import { paymentMiddleware } from "@t402/hono";
const app = new Hono();
app.use(
"/api/*",
paymentMiddleware({
"GET /api/data": {
accepts: [{ scheme: "exact", price: "$0.01", network: "eip155:8453", payTo: "0x..." }],
},
})
);
app.get("/api/data", (c) => c.json({ data: "Premium!" }));Fastify
import Fastify from "fastify";
import { t402Plugin } from "@t402/fastify";
const app = Fastify();
app.register(t402Plugin, {
routes: {
"GET /api/data": {
accepts: [{ scheme: "exact", price: "$0.01", network: "eip155:8453", payTo: "0x..." }],
},
},
});
app.get("/api/data", async () => ({ data: "Premium!" }));Axios Client
import axios from "axios";
import { wrapAxiosWithPayment } from "@t402/axios";
import { registerExactEvmScheme } from "@t402/evm/exact/client";
const client = new t402Client();
registerExactEvmScheme(client, { signer });
const api = wrapAxiosWithPayment(axios.create(), client);
const response = await api.get("https://api.example.com/data");Lifecycle Hooks
Client Hooks
import { t402Client } from "@t402/core";
const client = new t402Client();
// Before payment creation
client.onBeforePaymentCreation((ctx) => {
console.log(`Creating payment for ${ctx.requirements.network}`);
// Abort if price too high
if (BigInt(ctx.requirements.maxAmountRequired) > MAX_PRICE) {
return { abort: true, reason: "Price exceeds limit" };
}
});
// After successful payment
client.onAfterPaymentCreation((ctx) => {
metrics.increment("payments.created", {
network: ctx.requirements.network,
scheme: ctx.requirements.scheme,
});
});
// On payment failure
client.onPaymentCreationFailure((ctx) => {
logger.error("Payment failed", { error: ctx.error });
});Server Hooks
import { t402ResourceServer } from "@t402/core";
const server = new t402ResourceServer(facilitator);
// Before verification
server.onBeforeVerify((ctx) => {
if (isBlacklisted(ctx.payload.authorization.from)) {
return { abort: true, reason: "Payer is blocked" };
}
});
// After successful settlement
server.onAfterSettle((ctx) => {
db.recordPayment({
txHash: ctx.result.transaction,
payer: ctx.result.payer,
amount: ctx.requirements.maxAmountRequired,
});
});Error Handling
Client-Side Errors
import { t402Client, PaymentError, PaymentAbortedError } from "@t402/core";
try {
const response = await fetchWithPayment("https://api.example.com/data");
} catch (error) {
if (error instanceof PaymentAbortedError) {
// Payment was aborted by a hook
console.log("Payment aborted:", error.reason);
} else if (error instanceof PaymentError) {
// Payment creation failed
console.log("Payment failed:", error.message);
} else {
// Network or other error
throw error;
}
}Server-Side Errors
import { paymentMiddleware } from "@t402/express";
app.use(
paymentMiddleware(routes, server, {
onError: (error, req, res) => {
logger.error("Payment error", { error, path: req.path });
res.status(500).json({ error: "Payment processing failed" });
},
onSettlement: (result, req) => {
logger.info("Payment settled", {
txHash: result.transaction,
payer: result.payer,
});
},
})
);Dynamic Pricing
Per-Request Pricing
app.use(
paymentMiddleware({
"GET /api/data": {
accepts: [
{
scheme: "exact",
network: "eip155:8453",
payTo: "0x...",
// Dynamic price based on request
price: (req) => {
const tier = getUserTier(req);
return tier === "premium" ? "$0.001" : "$0.01";
},
},
],
},
})
);Dynamic PayTo Address
app.use(
paymentMiddleware({
"GET /api/marketplace/:id": {
accepts: [
{
scheme: "exact",
network: "eip155:8453",
price: "$10.00",
// Route payment to seller
payTo: async (req) => {
const item = await db.getItem(req.params.id);
return item.sellerAddress;
},
},
],
},
})
);Testing
Unit Testing
import { describe, it, expect, vi } from "vitest";
import { t402Client } from "@t402/core";
describe("t402Client", () => {
it("should create payment payload", async () => {
const client = new t402Client();
const mockScheme = {
createPaymentPayload: vi.fn().mockResolvedValue({
t402Version: 2,
authorization: { /* ... */ },
signature: "0x...",
}),
};
client.register("eip155:8453", mockScheme);
const payload = await client.createPaymentPayload(requirements);
expect(payload.t402Version).toBe(2);
});
});Integration Testing
import { describe, it, expect, beforeAll, afterAll } from "vitest";
import express from "express";
import { paymentMiddleware, t402ResourceServer } from "@t402/express";
describe("Payment Middleware", () => {
let server: ReturnType<typeof express>;
beforeAll(() => {
server = express();
server.use(paymentMiddleware(routes, resourceServer));
server.get("/api/data", (req, res) => res.json({ data: "test" }));
server.listen(3001);
});
it("should return 402 without payment", async () => {
const response = await fetch("http://localhost:3001/api/data");
expect(response.status).toBe(402);
const body = await response.json();
expect(body.t402Version).toBe(2);
expect(body.accepts).toHaveLength(1);
});
});Mock Facilitator
import { MockFacilitatorClient } from "@t402/core/testing";
const mockFacilitator = new MockFacilitatorClient({
verifyResponse: { isValid: true },
settleResponse: { success: true, transaction: "0xmock..." },
});
const server = new t402ResourceServer(mockFacilitator);Supported Networks
EVM Chains (USDT0)
| Chain | CAIP-2 Identifier |
|---|---|
| Ethereum | eip155:1 |
| Base | eip155:8453 |
| Arbitrum | eip155:42161 |
| Optimism | eip155:10 |
| Polygon | eip155:137 |
| Ink | eip155:57073 |
| Berachain | eip155:80094 |
| Unichain | eip155:130 |
Non-EVM Chains
| Chain | Token Standard | CAIP-2 Identifier |
|---|---|---|
| Solana | SPL Token | solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp |
| TON | Jetton | ton:mainnet |
| TRON | TRC-20 | tron:mainnet |
| NEAR | NEP-141 | near:mainnet |
| Aptos | Fungible Asset | aptos:1 |
| Tezos | FA2 | tezos:NetXdQprcVkpaWU |
| Polkadot | Asset Hub | polkadot:68d56f15f85d3136970ec16946040bc1 |
| Stacks | SIP-010 | stacks:1 |
Development
# Clone and install
git clone https://github.com/t402-io/t402.git
cd t402/typescript
pnpm install
# Build all packages
pnpm build
# Run tests
pnpm test
# Type checking
pnpm typecheck
# Lint
pnpm lintMonorepo Structure
sdks/typescript/
├── packages/
│ ├── core/ # @t402/core
│ ├── extensions/ # @t402/extensions
│ ├── mechanisms/
│ │ ├── evm/ # @t402/evm
│ │ ├── evm-core/ # @t402/evm-core
│ │ ├── svm/ # @t402/svm (Solana)
│ │ ├── ton/ # @t402/ton
│ │ ├── tron/ # @t402/tron
│ │ ├── near/ # @t402/near
│ │ ├── aptos/ # @t402/aptos
│ │ ├── tezos/ # @t402/tezos
│ │ ├── polkadot/ # @t402/polkadot
│ │ ├── stacks/ # @t402/stacks
│ │ └── btc/ # @t402/btc
│ ├── erc8004/ # @t402/erc8004
│ ├── http/
│ │ ├── express/ # @t402/express
│ │ ├── hono/ # @t402/hono
│ │ ├── fastify/ # @t402/fastify
│ │ ├── next/ # @t402/next
│ │ ├── fetch/ # @t402/fetch
│ │ ├── axios/ # @t402/axios
│ │ ├── paywall/ # @t402/paywall
│ │ ├── react/ # @t402/react
│ │ └── vue/ # @t402/vue
│ ├── wdk/ # @t402/wdk
│ ├── wdk-protocol/ # @t402/wdk-protocol
│ ├── wdk-gasless/ # @t402/wdk-gasless
│ ├── wdk-bridge/ # @t402/wdk-bridge
│ ├── wdk-multisig/ # @t402/wdk-multisig
│ ├── mcp/ # @t402/mcp
│ └── cli/ # @t402/cli
└── pnpm-workspace.yamlDeep Dive
Requirements
- Node.js 18+ or Bun 1.0+
- TypeScript 5.0+ (recommended)
- ESM or CommonJS supported