x402-verify-client-base
v1.0.0
Published
Client-side verification library for x402 payments on Base (L2 on Ethereum)
Downloads
8
Maintainers
Readme
x402-verify-client-base
Client-side verification SDK for x402 payment headers on Base (L2 on Ethereum). Built with TypeScript and ethers v6, compatible with Node.js and modern browsers.
Features
- ECDSA signature verification via
ethers.verifyMessage() - Cross-platform Base64 decoding (Browser
atob()/ NodeBuffer) - EIP-55 checksum address normalization with
ethers.getAddress() - Replay protection hooks:
maxAgeMs(timestamp window) andnonceSeen(nonce reuse) - Strict typings with
PaymentHeaderand a minimal, ergonomic API
Installation
npm install x402-verify-client-baseQuick Start
import { verifyPayment } from "x402-verify-client-base";
// Base64-encoded JSON header conforming to the PaymentHeader interface
const header = "<Base64 PaymentHeader JSON>";
const verified = verifyPayment(
header,
"0.001", // expected amount (ETH, decimal string)
"0xRecipientAddress",
{ maxAgeMs: 60_000, nonceSeen: () => false }
);
console.log("Verified:", verified);API Reference
verifyPayment(paymentHeader: string, expectedAmount: string, expectedAddress: string, options?: { maxAgeMs?: number; nonceSeen?: (nonce: string) => boolean }): boolean
Verifies an x402 payment header by:
- Decoding Base64 JSON (browser
atob()or NodeBuffer.from(..., "base64")) - Building the signed message including optional
nonceandtimestamp - Recovering the signer using
ethers.verifyMessage() - Normalizing addresses via
ethers.getAddress() - Comparing amounts as wei using
ethers.parseUnits(amount, 18) - Applying replay checks with
options.maxAgeMsandoptions.nonceSeen
Returns true only if all checks pass; otherwise false.
Types
export interface PaymentHeader {
amount: string; // decimal ETH string (e.g., "0.001")
to: string; // recipient address
from: string; // signer (sender) address
signature: string; // hex string, 65-byte ECDSA signature (130 hex chars)
nonce?: string; // optional, for replay protection
timestamp?: number; // optional, ms since epoch
}Verification Workflow
- Decode: Base64 → UTF‑8 JSON using
atob()(browser) orBuffer(Node). - Validate: Ensure required fields exist and types are correct.
- Build Message: Include
amount,to,from, and optionallynonce/timestamp. - Recover Signer:
ethers.verifyMessage(message, signature). - Normalize Addresses:
ethers.getAddress()for EIP‑55 checksum normalization. - Compare Amounts:
parseUnits(payment.amount, 18) === parseUnits(expectedAmount, 18). - Replay Checks: Reject if
timestampis older thanmaxAgeMs, or ifnonceSeen(nonce)returnstrue.
Cross‑Platform Notes
- Base64 decoding: Uses
atob()in browsers andBuffer.from(header, "base64").toString("utf8")in Node. - Address normalization:
ethers.getAddress()produces checksummed addresses for consistent comparisons. - Amount verification: Convert decimal ETH strings to wei via
ethers.parseUnits(..., 18)and compare numerically.
Testing
Run the test suite (Vitest):
npm run testScenarios covered: valid signature, wrong amount, wrong recipient, and invalid signature.
Requirements
- Node.js 18+ or a modern browser runtime
ethersv6- TypeScript 5+
Contact
- Twitter: @Arana_lib
- Email: [email protected]
License
MIT — see the separate LICENSE file for details.
