"""Pydantic v2 models for the x402 domain.""" from __future__ import annotations from enum import StrEnum from pydantic import BaseModel, ConfigDict, Field, field_validator class X402Tier(StrEnum): """x402 payment tier — maps to scanner tiers.""" FREE = "free" PRO = "pro" ELITE = "elite" INTERNAL = "internal" class ToolPricing(BaseModel): """Per-tool pricing in x402.""" model_config = ConfigDict(str_strip_whitespace=True) tool: str price_usd: float = Field(default=0.0, ge=0) price_crypto: dict[str, str] = Field( default_factory=dict, description="Crypto amounts: {'sol': '0.01', 'eth': '0.001', 'btc': '0.00001', 'trx': '5'}", ) tier_required: X402Tier = X402Tier.FREE class ToolCatalogEntry(BaseModel): """A single tool in the x402 catalog.""" name: str description: str = "" category: str = "" tier_required: X402Tier = X402Tier.FREE price_usd: float = 0.0 endpoint: str = "" enabled: bool = True class ToolCatalog(BaseModel): """Full x402 tool catalog.""" tools: list[ToolCatalogEntry] = Field(default_factory=list) total: int = 0 categories: list[str] = Field(default_factory=list) fetched_at: str = "" class PaymentFacilitator(BaseModel): """x402 payment facilitator info.""" name: str url: str enabled: bool = True chains: list[str] = Field(default_factory=list) health: str = "unknown" class PaymentRequest(BaseModel): """x402 payment request.""" model_config = ConfigDict(str_strip_whitespace=True) tool: str chain: str = Field(default="solana") user_address: str | None = None @field_validator("chain") @classmethod def _chain_lowercase(cls, v: str) -> str: return v.lower().strip() class PaymentReceipt(BaseModel): """x402 payment receipt.""" tool: str chain: str tx_hash: str | None = None amount_paid: dict[str, str] = Field(default_factory=dict) status: str = "pending" # pending | confirmed | failed timestamp: str = ""