Skip to main content

Overview

x402x-detector automatically identifies an ERC-20 token’s “gasless payment capability” — covering EIP-2612 Permit, EIP-3009, and Permit2 — and handles common proxy patterns (EIP-1967 / UUPS). Results are cached for millisecond-level access.

Key features

  • Full detection: Permit / EIP-3009 / Permit2
  • Proxy handling: EIP-1967 / UUPS / custom implementation
  • High performance: 2–5s on first run, <1ms with cache hits
  • Simple API: detect / getRecommendedMethod / initialize

Install

npm i x402x-detector@beta viem

Quick start

import { TokenDetector } from "x402x-detector";
const detector = new TokenDetector(publicClient);
const info = await detector.detect("0xUSDC"); // { supportedMethods: ["permit", ...], name, version }

Examples

  • Functional API (no cache)
  • TokenDetector class (with cache)
  • Server integration (Express)
  • Detect recipient (EIP-7702 + settle)
Create detect.ts, core logic:
import { detectTokenPaymentMethods, getRecommendedPaymentMethod, getTokenInfo } from "x402x-detector";
import { createPublicClient, http } from "viem";
import { bsc } from "viem/chains";

const client = createPublicClient({ chain: bsc, transport: http() });
const token = "0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d"; // USD1 (BSC)

// 1) Detect capabilities
const capabilities = await detectTokenPaymentMethods(token, client);

// 2) Recommend payment method (eip3009 > permit > permit2)
const recommended = await getRecommendedPaymentMethod(token, client);

// 3) Read token info (name/version)
const info = await getTokenInfo(token, client);
import { detectTokenPaymentMethods, getRecommendedPaymentMethod, getTokenInfo } from "x402x-detector";
import { createPublicClient, http } from "viem";
import { bsc } from "viem/chains";

async function main() {
  const client = createPublicClient({ chain: bsc, transport: http() });
  const token = "0x8d0D000Ee44948FC98c9B98A4FA4921476f08B0d"; // USD1 (BSC)

  const capabilities = await detectTokenPaymentMethods(token, client);
  console.log("capabilities:", capabilities);

  const recommended = await getRecommendedPaymentMethod(token, client);
  console.log("recommended:", recommended);

  const info = await getTokenInfo(token, client);
  console.log("token info:", info);
}

main();

Detection details

  • Permit: permit() / DOMAIN_SEPARATOR() / nonces(owner)
  • EIP-3009: transferWithAuthorization() / authorizationState()
  • Permit2: allowance(user, token, spender)
Proxy contracts: automatically read the implementation address (EIP-1967 storage slot / UUPS proxiableUUID(), etc.)
  • Warm up on startup: detector.initialize([USDC, DAI, ...])
  • Choose a recommended type: detector.getRecommendedMethod(token)
  • For non-standard proxies, manually verify implementation address

API reference (condensed)

class TokenDetector {
  constructor(client: PublicClient);
  detect(tokenAddress: string): Promise<{
    address: string;
    supportedMethods: ("eip3009" | "permit" | "permit2" | "permit2-witness")[];
    details: { hasEIP3009: boolean; hasPermit: boolean; hasPermit2Approval: boolean };
    name: string;
    version: string;
  }>;
  getRecommendedMethod(tokenAddress: string): Promise<"eip3009" | "permit" | "permit2" | null>;
  initialize(tokenAddresses: string[]): Promise<any[]>;
  clearCache(tokenAddress?: string): Promise<void>;
  getCacheStats(): { size: number; keys: string[] };
}
For more types and return structures, see:
  • Parameters: /en/parameters-responses/detector/parameters
  • Responses: /en/parameters-responses/detector/responses

Performance and optimization

  • Warm up hot tokens: initialize([tokens]) on service startup
  • Parallel detection: prefer initialize for batch parallel detection
  • Detect on demand: slow the first time, fast afterwards (cache hits)
  • Periodic refresh: re-detect popular tokens on a schedule

Resources

  • Source: https://github.com/WTFLabs-WTF/x402x/tree/main/typescript/packages/x402x-detector
  • Issues: https://github.com/WTFLabs-WTF/x402x/issues