| """x402 LangChain adapter β transparent payment for LangChain tools. |
| |
| Usage: |
| from x402_frameworks import x402LangChain |
| from langchain.tools import tool |
| |
| # Initialize x402 |
| x402 = x402LangChain(api_key="your-key", auto_pay=True) |
| |
| # Wrap any tool β payment is handled automatically |
| @x402.wrap_tool("token_scan") |
| @tool |
| def scan_token(address: str) -> dict: |
| \"\"\"Scan a token for rug pull indicators.\"\"\" |
| return {"risk": "low", "score": 85} |
| |
| # Use with any LangChain agent |
| from langchain.agents import create_react_agent |
| agent = create_react_agent(llm, [scan_token], prompt) |
| # When agent calls scan_token, x402 checks payment first |
| """ |
|
|
| from __future__ import annotations |
|
|
| import functools |
| import logging |
| from typing import Any, Callable, Optional |
|
|
| from .base import x402Adapter |
|
|
| logger = logging.getLogger("x402.langchain") |
|
|
|
|
| class x402LangChain(x402Adapter): |
| """LangChain adapter β wraps tools with automatic x402 payment. |
| |
| Every tool call checks: |
| 1. Free trial available? β use it |
| 2. Prepaid credits? β deduct |
| 3. Auto-pay enabled? β create invoice (dev must fund wallet) |
| 4. None? β raise PaymentRequired error |
| """ |
|
|
| def wrap_tool(self, tool_name: str, tool_func: Optional[Callable] = None) -> Callable: |
| """Decorator: wrap a LangChain tool function with x402 payment. |
| |
| Usage as decorator: |
| @x402.wrap_tool("token_scan") |
| @tool |
| def my_tool(address: str): ... |
| |
| Usage as wrapper: |
| wrapped = x402.wrap_tool("token_scan")(my_tool_func) |
| """ |
|
|
| def decorator(func: Callable) -> Callable: |
| @functools.wraps(func) |
| def wrapper(*args, **kwargs): |
| available, price, source = self.check_available(tool_name) |
| if not available: |
| invoice = self.get_invoice(tool_name) |
| raise PaymentRequiredError( |
| tool=tool_name, |
| price_usd=price, |
| pay_to=invoice.get("pay_to", ""), |
| chain=invoice.get("chain", "base"), |
| invoice_id=invoice.get("id", ""), |
| ) |
| result = func(*args, **kwargs) |
| if source == "paid": |
| self.record_usage(tool_name, price) |
| return result |
|
|
| return wrapper |
|
|
| if tool_func is not None: |
| return decorator(tool_func) |
| return decorator |
|
|
|
|
| class PaymentRequiredError(Exception): |
| """Raised when a tool requires payment before execution. |
| |
| The caller should display the invoice to the user for payment. |
| """ |
|
|
| def __init__( |
| self, |
| tool: str = "", |
| price_usd: float = 0.01, |
| pay_to: str = "", |
| chain: str = "base", |
| invoice_id: str = "", |
| ): |
| self.tool = tool |
| self.price_usd = price_usd |
| self.pay_to = pay_to |
| self.chain = chain |
| self.invoice_id = invoice_id |
| super().__init__( |
| f"Payment required: ${price_usd} for {tool}. " |
| f"Send USDC on {chain} to {pay_to[:16]}... (invoice: {invoice_id[:16]}...)" |
| ) |
|
|