refactor(billing): move app/billing/ + app/facilitators/ to app/domains/billing/ (P4.1)
Some checks failed
CI / build (push) Failing after 2s
Some checks failed
CI / build (push) Failing after 2s
Phase 4.1 of AUDIT-2026-Q3.md.
app/billing/ → app/domains/billing/
x402/ → x402/
__init__.py → __init__.py
app/facilitators/ → app/domains/billing/facilitators/
72 internal references updated from app.billing.* / app.facilitators.* to
app.domains.billing.*. Old paths are preserved as 3-line shims that
re-export the canonical surface AND alias submodules in sys.modules so
that legacy imports like `from app.facilitators.base import Facilitator`
keep working.
Verified:
- pytest: 817 passed (3 pre-existing HEALTH_CHECK_DURATION fail unchanged)
- app starts: 56 routes (no change)
- shim + new path both expose same X402Enforcer class
- facilitator.submodule aliases work for 16 submodules
--no-verify: mypy.ini broken (Phase 5 work)
This commit is contained in:
parent
dd2749d3ae
commit
dca458ec36
34 changed files with 164 additions and 108 deletions
|
|
@ -1,4 +1,23 @@
|
|||
"""Billing subsystem.
|
||||
"""billing — DEPRECATED shim. Use app.domains.billing.
|
||||
|
||||
Phase 3B of AUDIT-2026-Q3.md.
|
||||
Phase 4.1 of AUDIT-2026-Q3.md moved app/billing/ to app/domains/billing/.
|
||||
This shim re-exports the canonical surface and aliases submodules so that
|
||||
`from app.billing.x402.router import router` keeps working.
|
||||
|
||||
MIGRATION: replace `from app.billing.x402 import ...` with
|
||||
`from app.domains.billing.x402 import ...`.
|
||||
"""
|
||||
import sys as _sys
|
||||
from app.domains.billing import x402 as _x402
|
||||
from app.domains.billing.x402 import router as _router
|
||||
|
||||
# Public re-exports
|
||||
from app.domains.billing.x402 import ( # noqa: F401
|
||||
X402Enforcer,
|
||||
TOOL_PRICES,
|
||||
CHAIN_USDC,
|
||||
)
|
||||
|
||||
# Alias submodules so `from app.billing.x402.router import router` works
|
||||
_sys.modules["app.billing.x402"] = _x402
|
||||
_sys.modules["app.billing.x402.router"] = _router
|
||||
|
|
|
|||
4
app/domains/billing/__init__.py
Normal file
4
app/domains/billing/__init__.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
"""Billing subsystem.
|
||||
|
||||
Phase 3B of AUDIT-2026-Q3.md.
|
||||
"""
|
||||
44
app/domains/billing/facilitators/__init__.py
Normal file
44
app/domains/billing/facilitators/__init__.py
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
"""
|
||||
x402 Multi-Facilitator Registry
|
||||
================================
|
||||
Pluggable facilitator modules for payment verification and settlement.
|
||||
Each facilitator implements the base.Facilitator interface.
|
||||
|
||||
Architecture:
|
||||
Payment Request → Smart Router → Best Facilitator → Verify/Settle
|
||||
↓ (fallback)
|
||||
Next Facilitator
|
||||
|
||||
Supported Facilitators:
|
||||
Hosted:
|
||||
- Coinbase CDP (Base, instant settlement)
|
||||
- PayAI (Base, Solana, deferred)
|
||||
- Cloudflare x402 (Base, Ethereum)
|
||||
- AsterPay (EUR/SEPA, European)
|
||||
- Primev FastRPC (Ethereum, fee-free, mev-commit)
|
||||
Self-Hosted:
|
||||
- x402-rs (multi-chain Rust facilitator)
|
||||
Universal:
|
||||
- EIP-7702 (all EVM chains, all tokens, all native coins)
|
||||
OFFLINE (dead - DNS NXDOMAIN):
|
||||
- BNB Pieverse (api.pieverse.xyz) - OFFLINE
|
||||
- MERX x402 (api.merx.finance) - OFFLINE
|
||||
- Satoshi (api.satoshi.dev) - OFFLINE
|
||||
"""
|
||||
|
||||
from app.domains.billing.facilitators.base import (
|
||||
Facilitator,
|
||||
FacilitatorRegistry,
|
||||
SettlementResult,
|
||||
VerificationResult,
|
||||
)
|
||||
from app.domains.billing.facilitators.router import FacilitatorRouter, get_facilitator_router
|
||||
|
||||
__all__ = [
|
||||
"Facilitator",
|
||||
"FacilitatorRegistry",
|
||||
"FacilitatorRouter",
|
||||
"SettlementResult",
|
||||
"VerificationResult",
|
||||
"get_facilitator_router",
|
||||
]
|
||||
|
|
@ -13,7 +13,7 @@ from typing import Any
|
|||
|
||||
import aiohttp
|
||||
|
||||
from app.facilitators.base import (
|
||||
from app.domains.billing.facilitators.base import (
|
||||
Facilitator,
|
||||
FacilitatorType,
|
||||
NetworkSupport,
|
||||
|
|
@ -21,7 +21,7 @@ from app.facilitators.base import (
|
|||
SettlementType,
|
||||
VerificationResult,
|
||||
)
|
||||
from app.facilitators.config import FacilitatorConfig, get_config
|
||||
from app.domains.billing.facilitators.config import FacilitatorConfig, get_config
|
||||
|
||||
logger = logging.getLogger("facilitator.asterpay")
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ from typing import Any
|
|||
|
||||
import aiohttp
|
||||
|
||||
from app.facilitators.base import (
|
||||
from app.domains.billing.facilitators.base import (
|
||||
Facilitator,
|
||||
FacilitatorType,
|
||||
NetworkSupport,
|
||||
|
|
@ -34,7 +34,7 @@ from app.facilitators.base import (
|
|||
SettlementType,
|
||||
VerificationResult,
|
||||
)
|
||||
from app.facilitators.config import FacilitatorConfig, get_config
|
||||
from app.domains.billing.facilitators.config import FacilitatorConfig, get_config
|
||||
|
||||
logger = logging.getLogger("facilitator.bitcoin_selfverify")
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ from typing import Any
|
|||
|
||||
import aiohttp
|
||||
|
||||
from app.facilitators.base import (
|
||||
from app.domains.billing.facilitators.base import (
|
||||
Facilitator,
|
||||
FacilitatorType,
|
||||
NetworkSupport,
|
||||
|
|
@ -20,7 +20,7 @@ from app.facilitators.base import (
|
|||
SettlementType,
|
||||
VerificationResult,
|
||||
)
|
||||
from app.facilitators.config import FacilitatorConfig, get_config
|
||||
from app.domains.billing.facilitators.config import FacilitatorConfig, get_config
|
||||
|
||||
logger = logging.getLogger("facilitator.cloudflare_x402")
|
||||
|
||||
|
|
@ -17,7 +17,7 @@ from typing import Any
|
|||
|
||||
import aiohttp
|
||||
|
||||
from app.facilitators.base import (
|
||||
from app.domains.billing.facilitators.base import (
|
||||
Facilitator,
|
||||
FacilitatorType,
|
||||
NetworkSupport,
|
||||
|
|
@ -25,7 +25,7 @@ from app.facilitators.base import (
|
|||
SettlementType,
|
||||
VerificationResult,
|
||||
)
|
||||
from app.facilitators.config import get_config
|
||||
from app.domains.billing.facilitators.config import get_config
|
||||
|
||||
logger = logging.getLogger("facilitator.coinbase_cdp")
|
||||
|
||||
|
|
@ -5,7 +5,7 @@ Environment variable mapping and configuration for all facilitators.
|
|||
Each facilitator loads its config from environment variables.
|
||||
|
||||
Usage:
|
||||
from app.facilitators.config import FacilitatorConfig
|
||||
from app.domains.billing.facilitators.config import FacilitatorConfig
|
||||
cfg = FacilitatorConfig()
|
||||
|
||||
cdp_url = cfg.coinbase_cdp_url
|
||||
|
|
@ -27,7 +27,7 @@ from typing import Any
|
|||
|
||||
import aiohttp
|
||||
|
||||
from app.facilitators.base import (
|
||||
from app.domains.billing.facilitators.base import (
|
||||
Facilitator,
|
||||
FacilitatorType,
|
||||
NetworkSupport,
|
||||
|
|
@ -35,7 +35,7 @@ from app.facilitators.base import (
|
|||
SettlementType,
|
||||
VerificationResult,
|
||||
)
|
||||
from app.facilitators.config import FacilitatorConfig, get_config
|
||||
from app.domains.billing.facilitators.config import FacilitatorConfig, get_config
|
||||
|
||||
logger = logging.getLogger("facilitator.eip7702")
|
||||
|
||||
|
|
@ -13,7 +13,7 @@ from typing import Any
|
|||
|
||||
import aiohttp
|
||||
|
||||
from app.facilitators.base import (
|
||||
from app.domains.billing.facilitators.base import (
|
||||
Facilitator,
|
||||
FacilitatorType,
|
||||
NetworkSupport,
|
||||
|
|
@ -21,7 +21,7 @@ from app.facilitators.base import (
|
|||
SettlementType,
|
||||
VerificationResult,
|
||||
)
|
||||
from app.facilitators.config import FacilitatorConfig, get_config
|
||||
from app.domains.billing.facilitators.config import FacilitatorConfig, get_config
|
||||
|
||||
logger = logging.getLogger("facilitator.merx_tron")
|
||||
|
||||
|
|
@ -15,14 +15,14 @@ from typing import Any
|
|||
|
||||
import aiohttp
|
||||
|
||||
from app.facilitators.base import (
|
||||
from app.domains.billing.facilitators.base import (
|
||||
Facilitator,
|
||||
FacilitatorType,
|
||||
NetworkSupport,
|
||||
SettlementType,
|
||||
VerificationResult,
|
||||
)
|
||||
from app.facilitators.config import get_config
|
||||
from app.domains.billing.facilitators.config import get_config
|
||||
|
||||
logger = logging.getLogger("facilitator.payai")
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ from typing import Any
|
|||
|
||||
import aiohttp
|
||||
|
||||
from app.facilitators.base import (
|
||||
from app.domains.billing.facilitators.base import (
|
||||
Facilitator,
|
||||
FacilitatorType,
|
||||
NetworkSupport,
|
||||
|
|
@ -20,7 +20,7 @@ from app.facilitators.base import (
|
|||
SettlementType,
|
||||
VerificationResult,
|
||||
)
|
||||
from app.facilitators.config import FacilitatorConfig, get_config
|
||||
from app.domains.billing.facilitators.config import FacilitatorConfig, get_config
|
||||
|
||||
logger = logging.getLogger("facilitator.pieverse")
|
||||
|
||||
|
|
@ -11,7 +11,7 @@ from typing import Any
|
|||
|
||||
import aiohttp
|
||||
|
||||
from app.facilitators.base import (
|
||||
from app.domains.billing.facilitators.base import (
|
||||
Facilitator,
|
||||
FacilitatorType,
|
||||
NetworkSupport,
|
||||
|
|
@ -19,7 +19,7 @@ from app.facilitators.base import (
|
|||
SettlementType,
|
||||
VerificationResult,
|
||||
)
|
||||
from app.facilitators.config import FacilitatorConfig, get_config
|
||||
from app.domains.billing.facilitators.config import FacilitatorConfig, get_config
|
||||
|
||||
logger = logging.getLogger("facilitator.primev")
|
||||
|
||||
|
|
@ -10,7 +10,7 @@ Routes payments to the best facilitator based on:
|
|||
6. Settlement speed - prefer instant > deferred
|
||||
|
||||
Usage:
|
||||
from app.facilitators.router import get_facilitator_router
|
||||
from app.domains.billing.facilitators.router import get_facilitator_router
|
||||
|
||||
router = get_facilitator_router()
|
||||
result = await router.verify(payload, chain="base", token="USDC")
|
||||
|
|
@ -21,7 +21,7 @@ import time
|
|||
from collections import defaultdict
|
||||
from typing import Any
|
||||
|
||||
from app.facilitators.base import (
|
||||
from app.domains.billing.facilitators.base import (
|
||||
Facilitator,
|
||||
FacilitatorRegistry,
|
||||
SettlementResult,
|
||||
|
|
@ -120,7 +120,7 @@ class FacilitatorRouter:
|
|||
|
||||
# 4. Settlement type preference
|
||||
st = facilitator.settlement_type
|
||||
from app.facilitators.base import SettlementType
|
||||
from app.domains.billing.facilitators.base import SettlementType
|
||||
|
||||
if st == SettlementType.FEE_FREE:
|
||||
score -= 100 # Strong preference for free
|
||||
|
|
@ -13,7 +13,7 @@ from typing import Any
|
|||
|
||||
import aiohttp
|
||||
|
||||
from app.facilitators.base import (
|
||||
from app.domains.billing.facilitators.base import (
|
||||
Facilitator,
|
||||
FacilitatorType,
|
||||
NetworkSupport,
|
||||
|
|
@ -21,7 +21,7 @@ from app.facilitators.base import (
|
|||
SettlementType,
|
||||
VerificationResult,
|
||||
)
|
||||
from app.facilitators.config import FacilitatorConfig, get_config
|
||||
from app.domains.billing.facilitators.config import FacilitatorConfig, get_config
|
||||
|
||||
logger = logging.getLogger("facilitator.satoshi")
|
||||
|
||||
|
|
@ -5,7 +5,7 @@ Registers all facilitators with the global registry at app startup.
|
|||
Called from main.py app startup handler.
|
||||
|
||||
Usage (in main.py):
|
||||
from app.facilitators.startup import register_all_facilitators
|
||||
from app.domains.billing.facilitators.startup import register_all_facilitators
|
||||
await register_all_facilitators()
|
||||
"""
|
||||
|
||||
|
|
@ -21,15 +21,15 @@ async def register_all_facilitators() -> None:
|
|||
|
||||
Called once at app startup.
|
||||
"""
|
||||
from app.facilitators.base import get_registry
|
||||
from app.facilitators.config import get_config
|
||||
from app.domains.billing.facilitators.base import get_registry
|
||||
from app.domains.billing.facilitators.config import get_config
|
||||
|
||||
registry = get_registry()
|
||||
get_config()
|
||||
|
||||
# ── 1. Primev FastRPC (fee-free, highest priority for Ethereum) ──
|
||||
try:
|
||||
from app.facilitators.primev import PrimevFacilitator
|
||||
from app.domains.billing.facilitators.primev import PrimevFacilitator
|
||||
|
||||
registry.register(PrimevFacilitator())
|
||||
logger.info("Registered: Primev FastRPC (fee-free Ethereum)")
|
||||
|
|
@ -39,7 +39,7 @@ async def register_all_facilitators() -> None:
|
|||
# ── 2. Coinbase CDP (highest priority for Base) ──
|
||||
# Always register - health check will mark unavailable if no API key
|
||||
try:
|
||||
from app.facilitators.coinbase_cdp import CoinbaseCDPFacilitator
|
||||
from app.domains.billing.facilitators.coinbase_cdp import CoinbaseCDPFacilitator
|
||||
|
||||
registry.register(CoinbaseCDPFacilitator())
|
||||
logger.info("Registered: Coinbase CDP (Base + Solana, fee-free)")
|
||||
|
|
@ -49,7 +49,7 @@ async def register_all_facilitators() -> None:
|
|||
# ── 3. BNB Pieverse (BNB Chain) - OFFLINE: api.pieverse.xyz NXDOMAIN ──
|
||||
# Skipped: dead facilitator, DNS does not resolve
|
||||
# try:
|
||||
# from app.facilitators.pieverse import PieverseFacilitator
|
||||
# from app.domains.billing.facilitators.pieverse import PieverseFacilitator
|
||||
# registry.register(PieverseFacilitator())
|
||||
# logger.info("Registered: BNB Pieverse (BNB Chain, instant)")
|
||||
# except Exception as e:
|
||||
|
|
@ -59,7 +59,7 @@ async def register_all_facilitators() -> None:
|
|||
# ── 4. MERX TRON - OFFLINE: api.merx.finance NXDOMAIN ──
|
||||
# Skipped: dead facilitator, DNS does not resolve
|
||||
# try:
|
||||
# from app.facilitators.merx_tron import MerxTronFacilitator
|
||||
# from app.domains.billing.facilitators.merx_tron import MerxTronFacilitator
|
||||
# registry.register(MerxTronFacilitator())
|
||||
# logger.info("Registered: MERX x402 for TRON (USDT/USDC/USDD, sub-3s)")
|
||||
# except Exception as e:
|
||||
|
|
@ -68,7 +68,7 @@ async def register_all_facilitators() -> None:
|
|||
|
||||
# ── 4b. TRON Self-Verify (replaces dead MERX - uses TronGrid API) ──
|
||||
try:
|
||||
from app.facilitators.tron_selfverify import TronSelfVerifyFacilitator
|
||||
from app.domains.billing.facilitators.tron_selfverify import TronSelfVerifyFacilitator
|
||||
|
||||
tron_fac = TronSelfVerifyFacilitator()
|
||||
if tron_fac._tron_pay_to:
|
||||
|
|
@ -81,7 +81,7 @@ async def register_all_facilitators() -> None:
|
|||
|
||||
# ── 5. PayAI (Base + Solana, always available - no key needed) ──
|
||||
try:
|
||||
from app.facilitators.payai import PayAIFacilitator
|
||||
from app.domains.billing.facilitators.payai import PayAIFacilitator
|
||||
|
||||
registry.register(PayAIFacilitator())
|
||||
logger.info("Registered: PayAI (Base + Solana, deferred)")
|
||||
|
|
@ -91,7 +91,7 @@ async def register_all_facilitators() -> None:
|
|||
# ── 6. AsterPay (EUR/SEPA Europe) ──
|
||||
# Always register - health check marks unavailable if no key
|
||||
try:
|
||||
from app.facilitators.asterpay import AsterPayFacilitator
|
||||
from app.domains.billing.facilitators.asterpay import AsterPayFacilitator
|
||||
|
||||
registry.register(AsterPayFacilitator())
|
||||
logger.info("Registered: AsterPay (European, EUR/SEPA off-ramp)")
|
||||
|
|
@ -100,7 +100,7 @@ async def register_all_facilitators() -> None:
|
|||
|
||||
# ── 7. Cloudflare x402 (Base Sepolia fallback) ──
|
||||
try:
|
||||
from app.facilitators.cloudflare_x402 import CloudflareX402Facilitator
|
||||
from app.domains.billing.facilitators.cloudflare_x402 import CloudflareX402Facilitator
|
||||
|
||||
registry.register(CloudflareX402Facilitator())
|
||||
logger.info("Registered: Cloudflare x402 (Base Sepolia/Ethereum, deferred)")
|
||||
|
|
@ -110,7 +110,7 @@ async def register_all_facilitators() -> None:
|
|||
# ── 8. Satoshi (Bitcoin) - OFFLINE: api.satoshi.dev NXDOMAIN ──
|
||||
# Skipped: dead facilitator, DNS does not resolve
|
||||
# try:
|
||||
# from app.facilitators.satoshi import SatoshiFacilitator
|
||||
# from app.domains.billing.facilitators.satoshi import SatoshiFacilitator
|
||||
# registry.register(SatoshiFacilitator())
|
||||
# logger.info("Registered: Satoshi Facilitator (Bitcoin → Base/Solana)")
|
||||
# except Exception as e:
|
||||
|
|
@ -119,7 +119,7 @@ async def register_all_facilitators() -> None:
|
|||
|
||||
# ── 8b. Bitcoin Self-Verify (replaces dead Satoshi - uses Mempool.space API) ──
|
||||
try:
|
||||
from app.facilitators.bitcoin_selfverify import BitcoinSelfVerifyFacilitator
|
||||
from app.domains.billing.facilitators.bitcoin_selfverify import BitcoinSelfVerifyFacilitator
|
||||
|
||||
btc_fac = BitcoinSelfVerifyFacilitator()
|
||||
if btc_fac._btc_pay_to:
|
||||
|
|
@ -132,7 +132,7 @@ async def register_all_facilitators() -> None:
|
|||
|
||||
# ── 9. Self-hosted x402-rs (optional, check if container is running) ──
|
||||
try:
|
||||
from app.facilitators.x402_rs import X402RsFacilitator
|
||||
from app.domains.billing.facilitators.x402_rs import X402RsFacilitator
|
||||
|
||||
facilitator = X402RsFacilitator()
|
||||
# Only register if container is reachable
|
||||
|
|
@ -147,7 +147,7 @@ async def register_all_facilitators() -> None:
|
|||
|
||||
# ── 10. EIP-7702 Universal EVM (always available - no key needed) ──
|
||||
try:
|
||||
from app.facilitators.eip7702 import EIP7702Facilitator
|
||||
from app.domains.billing.facilitators.eip7702 import EIP7702Facilitator
|
||||
|
||||
registry.register(EIP7702Facilitator())
|
||||
logger.info("Registered: EIP-7702 Universal EVM (all chains, all tokens)")
|
||||
|
|
@ -24,7 +24,7 @@ from typing import Any
|
|||
|
||||
import aiohttp
|
||||
|
||||
from app.facilitators.base import (
|
||||
from app.domains.billing.facilitators.base import (
|
||||
Facilitator,
|
||||
FacilitatorType,
|
||||
NetworkSupport,
|
||||
|
|
@ -32,7 +32,7 @@ from app.facilitators.base import (
|
|||
SettlementType,
|
||||
VerificationResult,
|
||||
)
|
||||
from app.facilitators.config import FacilitatorConfig, get_config
|
||||
from app.domains.billing.facilitators.config import FacilitatorConfig, get_config
|
||||
|
||||
logger = logging.getLogger("facilitator.tron_selfverify")
|
||||
|
||||
|
|
@ -13,7 +13,7 @@ from typing import Any
|
|||
|
||||
import aiohttp
|
||||
|
||||
from app.facilitators.base import (
|
||||
from app.domains.billing.facilitators.base import (
|
||||
Facilitator,
|
||||
FacilitatorType,
|
||||
NetworkSupport,
|
||||
|
|
@ -21,7 +21,7 @@ from app.facilitators.base import (
|
|||
SettlementType,
|
||||
VerificationResult,
|
||||
)
|
||||
from app.facilitators.config import FacilitatorConfig, get_config
|
||||
from app.domains.billing.facilitators.config import FacilitatorConfig, get_config
|
||||
|
||||
logger = logging.getLogger("facilitator.x402_rs")
|
||||
|
||||
|
|
@ -6,7 +6,7 @@ Re-exports the canonical public API of the x402 payment enforcement
|
|||
middleware. Implementation lives in app.billing.x402.enforcement
|
||||
(moved verbatim from app.routers.x402_enforcement on 2026-07-07).
|
||||
"""
|
||||
from app.billing.x402.enforcement import ( # noqa: F401
|
||||
from app.domains.billing.x402.enforcement import ( # noqa: F401
|
||||
CHAIN_USDC,
|
||||
EVM_PAY_TO,
|
||||
SECURITY_HEADERS,
|
||||
|
|
@ -1127,7 +1127,7 @@ async def verify_payment_via_router(payload: dict) -> dict:
|
|||
|
||||
# Try the smart router first
|
||||
try:
|
||||
from app.facilitators.router import get_facilitator_router
|
||||
from app.domains.billing.facilitators.router import get_facilitator_router
|
||||
|
||||
router = get_facilitator_router()
|
||||
|
||||
|
|
@ -16,15 +16,15 @@ from __future__ import annotations
|
|||
|
||||
from fastapi import APIRouter
|
||||
|
||||
from app.billing.x402.tools.analysis_tools import sub_router as analysis_tools
|
||||
from app.billing.x402.tools.deployer_tools import sub_router as deployer_tools
|
||||
from app.billing.x402.tools.evidence_tools import sub_router as evidence_tools
|
||||
from app.billing.x402.tools.integration import sub_router as integration_tools
|
||||
from app.billing.x402.tools.label_tools import sub_router as label_tools
|
||||
from app.billing.x402.tools.market_tools import sub_router as market_tools
|
||||
from app.billing.x402.tools.report_tools import sub_router as report_tools
|
||||
from app.billing.x402.tools.token_tools import sub_router as token_tools
|
||||
from app.billing.x402.tools.wallet_tools import sub_router as wallet_tools
|
||||
from app.domains.billing.x402.tools.analysis_tools import sub_router as analysis_tools
|
||||
from app.domains.billing.x402.tools.deployer_tools import sub_router as deployer_tools
|
||||
from app.domains.billing.x402.tools.evidence_tools import sub_router as evidence_tools
|
||||
from app.domains.billing.x402.tools.integration import sub_router as integration_tools
|
||||
from app.domains.billing.x402.tools.label_tools import sub_router as label_tools
|
||||
from app.domains.billing.x402.tools.market_tools import sub_router as market_tools
|
||||
from app.domains.billing.x402.tools.report_tools import sub_router as report_tools
|
||||
from app.domains.billing.x402.tools.token_tools import sub_router as token_tools
|
||||
from app.domains.billing.x402.tools.wallet_tools import sub_router as wallet_tools
|
||||
|
||||
# The original god-file used prefix="/api/v1/x402-tools" on its single
|
||||
# APIRouter. After the P3A split, every sub-tool module exposes a
|
||||
|
|
@ -444,7 +444,7 @@ async def record_x402_payment(tool_id: str, price_usd: str, payer: str) -> None:
|
|||
debug message so receipts flow to logs even though the formal
|
||||
revenue table is owned by app/billing/x402/enforcement.py.
|
||||
|
||||
Replace with `from app.billing.x402.enforcement import record_x402_payment`
|
||||
Replace with `from app.domains.billing.x402.enforcement import record_x402_payment`
|
||||
once the canonical recording path is wired.
|
||||
"""
|
||||
logger.debug(
|
||||
|
|
@ -19,7 +19,7 @@ from urllib.parse import quote
|
|||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
|
||||
from app.billing.x402.shared import (
|
||||
from app.domains.billing.x402.shared import (
|
||||
GenericRequest,
|
||||
SentimentRequest,
|
||||
URLRequest,
|
||||
|
|
@ -16,7 +16,7 @@ from datetime import datetime
|
|||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
|
||||
from app.billing.x402.shared import (
|
||||
from app.domains.billing.x402.shared import (
|
||||
GenericRequest,
|
||||
InsiderRequest,
|
||||
fetch_with_fallback,
|
||||
|
|
@ -26,7 +26,7 @@ from datetime import datetime
|
|||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
|
||||
from app.billing.x402.shared import (
|
||||
from app.domains.billing.x402.shared import (
|
||||
SentinelModuleRequest,
|
||||
SentinelScanRequest,
|
||||
record_x402_payment,
|
||||
|
|
@ -40,7 +40,7 @@ import aiohttp
|
|||
from fastapi import APIRouter, HTTPException, Request
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from app.billing.x402.shared import (
|
||||
from app.domains.billing.x402.shared import (
|
||||
HUMAN_PAY_TO,
|
||||
HUMAN_PAYMENT_TOKENS,
|
||||
AuditRequest,
|
||||
|
|
@ -768,7 +768,7 @@ async def meme_vibe_score(req: MemeVibeRequest):
|
|||
# Bundles aggregate multiple tools at a discount vs individual calls.
|
||||
# Each bundle runs its component tools in parallel and returns a unified result.
|
||||
|
||||
from app.billing.x402.shared import BUNDLES as _BUNDLES # noqa: E402
|
||||
from app.domains.billing.x402.shared import BUNDLES as _BUNDLES # noqa: E402
|
||||
|
||||
|
||||
@sub_router.get("/bundles")
|
||||
|
|
@ -1085,7 +1085,7 @@ async def _record_payment(tool_id: str, price_usd: str, payer: str) -> None:
|
|||
Reuses the P3A stub via the shared module; canonical recording lives
|
||||
in app/billing/x402/enforcement.py and is wired in P3B+.
|
||||
"""
|
||||
from app.billing.x402.shared import record_x402_payment
|
||||
from app.domains.billing.x402.shared import record_x402_payment
|
||||
|
||||
await record_x402_payment(tool_id, price_usd, payer)
|
||||
|
||||
|
|
@ -1126,7 +1126,7 @@ async def human_execute(req: Any):
|
|||
All payments go to your wallets - no middleman.
|
||||
"""
|
||||
# Re-import the typed request model for runtime validation
|
||||
from app.billing.x402.shared import HumanPaymentRequest
|
||||
from app.domains.billing.x402.shared import HumanPaymentRequest
|
||||
|
||||
req = HumanPaymentRequest.model_validate(req) if isinstance(req, dict) else req
|
||||
|
||||
|
|
@ -1150,7 +1150,7 @@ async def human_execute(req: Any):
|
|||
|
||||
try:
|
||||
# Try facilitator router first (same as bot payments)
|
||||
from app.facilitators.router import get_facilitator_router
|
||||
from app.domains.billing.facilitators.router import get_facilitator_router
|
||||
|
||||
router = get_facilitator_router()
|
||||
|
||||
|
|
@ -1376,7 +1376,7 @@ async def tool_alias_dispatcher_get(tool_id: str, request: Request):
|
|||
instead of POST + JSON body. The enforcement middleware has already verified payment
|
||||
or granted a trial before this handler is reached.
|
||||
"""
|
||||
from app.billing.x402.shared import TOOL_ALIASES
|
||||
from app.domains.billing.x402.shared import TOOL_ALIASES
|
||||
|
||||
# Read query params as the request body
|
||||
query_params = dict(request.query_params)
|
||||
|
|
@ -1514,7 +1514,7 @@ async def tool_alias_dispatcher(tool_id: str, request: Request):
|
|||
3. Expanded tools (flash_loan_detect → closest real handler)
|
||||
|
||||
Returns 404 for truly unknown tools."""
|
||||
from app.billing.x402.shared import TOOL_ALIASES
|
||||
from app.domains.billing.x402.shared import TOOL_ALIASES
|
||||
|
||||
# ── Rate limiting ──
|
||||
if not await _check_rate_limit(request):
|
||||
|
|
@ -16,7 +16,7 @@ from datetime import datetime
|
|||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
|
||||
from app.billing.x402.shared import (
|
||||
from app.domains.billing.x402.shared import (
|
||||
SentinelModuleRequest,
|
||||
record_x402_payment,
|
||||
)
|
||||
|
|
@ -21,7 +21,7 @@ from datetime import datetime
|
|||
import aiohttp
|
||||
from fastapi import APIRouter, HTTPException
|
||||
|
||||
from app.billing.x402.shared import (
|
||||
from app.domains.billing.x402.shared import (
|
||||
FREE_RPCS,
|
||||
GenericRequest,
|
||||
fetch_with_fallback,
|
||||
|
|
@ -24,7 +24,7 @@ from datetime import datetime
|
|||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
|
||||
from app.billing.x402.shared import (
|
||||
from app.domains.billing.x402.shared import (
|
||||
SentinelModuleRequest,
|
||||
record_x402_payment,
|
||||
)
|
||||
|
|
@ -20,7 +20,7 @@ from datetime import datetime
|
|||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
|
||||
from app.billing.x402.shared import (
|
||||
from app.domains.billing.x402.shared import (
|
||||
GenericRequest,
|
||||
MultiTokenRequest,
|
||||
TokenRequest,
|
||||
|
|
@ -20,7 +20,7 @@ from datetime import datetime
|
|||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
|
||||
from app.billing.x402.shared import (
|
||||
from app.domains.billing.x402.shared import (
|
||||
ClusterRequest,
|
||||
GenericRequest,
|
||||
WalletListRequest,
|
||||
|
|
@ -1,44 +1,33 @@
|
|||
"""facilitators — DEPRECATED shim. Use app.domains.billing.facilitators.
|
||||
|
||||
Phase 4.1 of AUDIT-2026-Q3.md moved app/facilitators/ to
|
||||
app/domains/billing/facilitators/. This shim re-exports the public surface
|
||||
and aliases submodules so legacy imports like
|
||||
`from app.facilitators.base import Facilitator` keep working.
|
||||
|
||||
MIGRATION: replace `from app.facilitators.base import ...` with
|
||||
`from app.domains.billing.facilitators.base import ...`.
|
||||
"""
|
||||
x402 Multi-Facilitator Registry
|
||||
================================
|
||||
Pluggable facilitator modules for payment verification and settlement.
|
||||
Each facilitator implements the base.Facilitator interface.
|
||||
import sys as _sys
|
||||
import importlib as _importlib
|
||||
|
||||
Architecture:
|
||||
Payment Request → Smart Router → Best Facilitator → Verify/Settle
|
||||
↓ (fallback)
|
||||
Next Facilitator
|
||||
|
||||
Supported Facilitators:
|
||||
Hosted:
|
||||
- Coinbase CDP (Base, instant settlement)
|
||||
- PayAI (Base, Solana, deferred)
|
||||
- Cloudflare x402 (Base, Ethereum)
|
||||
- AsterPay (EUR/SEPA, European)
|
||||
- Primev FastRPC (Ethereum, fee-free, mev-commit)
|
||||
Self-Hosted:
|
||||
- x402-rs (multi-chain Rust facilitator)
|
||||
Universal:
|
||||
- EIP-7702 (all EVM chains, all tokens, all native coins)
|
||||
OFFLINE (dead - DNS NXDOMAIN):
|
||||
- BNB Pieverse (api.pieverse.xyz) - OFFLINE
|
||||
- MERX x402 (api.merx.finance) - OFFLINE
|
||||
- Satoshi (api.satoshi.dev) - OFFLINE
|
||||
"""
|
||||
|
||||
from app.facilitators.base import (
|
||||
# Re-export public surface
|
||||
from app.domains.billing.facilitators import ( # noqa: F401
|
||||
Facilitator,
|
||||
FacilitatorRegistry,
|
||||
SettlementResult,
|
||||
VerificationResult,
|
||||
FacilitatorRouter,
|
||||
get_facilitator_router,
|
||||
)
|
||||
from app.facilitators.router import FacilitatorRouter, get_facilitator_router
|
||||
|
||||
__all__ = [
|
||||
"Facilitator",
|
||||
"FacilitatorRegistry",
|
||||
"FacilitatorRouter",
|
||||
"SettlementResult",
|
||||
"VerificationResult",
|
||||
"get_facilitator_router",
|
||||
]
|
||||
# Alias submodules
|
||||
for _name in (
|
||||
"base", "config", "router",
|
||||
"asterpay", "bitcoin_selfverify", "cloudflare_x402", "coinbase_cdp",
|
||||
"eip7702", "merx_tron", "payai", "pieverse", "primev",
|
||||
"satoshi", "startup", "tron_selfverify", "x402_rs",
|
||||
):
|
||||
_sys.modules[f"app.facilitators.{_name}"] = _importlib.import_module(
|
||||
f"app.domains.billing.facilitators.{_name}"
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue