XRPL implementation of x402 payments (presigned Payment scheme) with client + FastAPI/Starlette helpers
Project description
x402 XRPL Python SDK
This package provides a small, spec‑aligned SDK for working with x402 payments over XRPL in this repository. It is designed to be reusable by both buyer clients (creating PAYMENT-SIGNATURE headers) and seller/resource servers (verifying and settling via a facilitator).
Note: The XRPL exact flow in this repo is the presigned Payment tx blob scheme.
For an overview of the scheme and end-to-end flow, see: app/docs/xrpl-exact/presigned-payment/README.md.
Install (PyPI)
pip install x402-xrpl
Note: the PyPI name uses a hyphen, but the import name uses an underscore:
import x402_xrpl
Quickstart: Buyer Client (requests-style)
If you want the UX of x402_requests(...) (auto-handle 402), use x402_xrpl.clients.requests:
import requests
from xrpl.wallet import Wallet
from x402_xrpl.clients.requests import x402_requests
from x402_xrpl.clients.base import decode_payment_response
XRPL_RPC = "https://s.altnet.rippletest.net:51234/"
RESOURCE_URL = "http://127.0.0.1:8080/xrpl-demo/resource"
wallet = Wallet.from_seed("…demo seed…")
session: requests.Session = x402_requests(
wallet,
rpc_url=XRPL_RPC,
# Optional filters so most users don't write a custom selector:
network_filter="xrpl:1",
scheme_filter="exact",
)
resp = session.get(RESOURCE_URL, timeout=180)
print(resp.status_code, resp.text)
if "PAYMENT-RESPONSE" in resp.headers:
settlement = decode_payment_response(resp.headers["PAYMENT-RESPONSE"])
print("settled tx:", settlement.get("transaction"))
Quickstart: Protecting a FastAPI Route with require_payment (recommended)
To protect a route (e.g. /ai-news) with XRPL x402 payments using an ergonomic wrapper:
from fastapi import FastAPI
from x402_xrpl.server import require_payment
app = FastAPI()
app.middleware("http")(
require_payment(
path="/ai-news",
price="1000", # XRP drops; for IOUs use the XRPL value string (e.g. "1.25")
pay_to_address="rhaDe3NBxgUSLL12N5Sxpii2xy8vSyXNG6",
network="xrpl:1",
asset="XRP",
facilitator_url="http://127.0.0.1:8011",
resource="demo:ai-news",
description="AI news feed (paid)",
)
)
XRPL SourceTag (analytics)
By default, this SDK issues PaymentRequirements.extra["sourceTag"] = 804681468 and buyer clients will sign XRPL Payment transactions with SourceTag = 804681468 (so XRPL can query/aggregate these payments on-ledger).
To override the tag for your app, pass your own value in extra:
app.middleware("http")(
require_payment(
# ...
extra={"sourceTag": 123},
)
)
IOU notes (non-XRP assets):
- Set
reqs.assetto the XRPL currency code (MUST be 3 chars or 40-hex). - Provide the issuer as
reqs.extra["issuer"](classic address). - Set
reqs.amountto the XRPL issued-currencyvaluestring (e.g."1","1.25").
If you want a human-friendly display string (or an opt-in conversion of a symbol like "RLUSD" into a 40-hex code), use the currency helpers:
from x402_xrpl.xrpl_currency import display_currency_code, resolve_currency_code
asset = "524C555344000000000000000000000000000000"
print(display_currency_code(asset)) # "RLUSD" (best-effort)
# Opt-in convenience (only use if your app has a trusted mapping/intent):
asset_hex = resolve_currency_code("RLUSD", allow_utf8_symbol=True)
Quickstart: Calling a Facilitator Directly
If you already have:
- A
PAYMENT-SIGNATUREheader value (payment_header), and - A
PaymentRequirementsinstance (reqs)
you can talk to the XRPL facilitator directly:
from x402_xrpl.facilitator import FacilitatorClient, FacilitatorClientOptions
client = FacilitatorClient(
FacilitatorClientOptions(
base_url="http://127.0.0.1:8011",
)
)
# Optional: discover supported scheme/network pairs
supported = client.supported()
for kind in supported.kinds:
print("facilitator supports:", kind.scheme, kind.network)
# Verify
verify_result = client.verify(
payment_header=payment_header,
payment_requirements=reqs,
)
if not verify_result.is_valid:
raise RuntimeError(f"verify failed: {verify_result.invalid_reason}")
# Settle
settle_result = client.settle(
payment_header=payment_header,
payment_requirements=reqs,
)
if not settle_result.success:
raise RuntimeError(f"settle failed: {settle_result.error_reason}")
print("settled on", settle_result.network, "tx:", settle_result.transaction)
For async flows, use AsyncFacilitatorClient instead and await the same methods.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file x402_xrpl-0.1.4.tar.gz.
File metadata
- Download URL: x402_xrpl-0.1.4.tar.gz
- Upload date:
- Size: 30.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c517b920c8f6b1838c3b6f329eabcb53c77e0ed467c32cb9473ee5436e297c9e
|
|
| MD5 |
4ac813cac3e6fdb0e229d6759b4a4cee
|
|
| BLAKE2b-256 |
034965488b3b15c93fd33c80e58aac93fa25ceeecdddc0308b77f9579e426070
|
File details
Details for the file x402_xrpl-0.1.4-py3-none-any.whl.
File metadata
- Download URL: x402_xrpl-0.1.4-py3-none-any.whl
- Upload date:
- Size: 22.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c2e433456f5d67a23793c614207fbd5c22dfe8550475e0fbd60572f47377e1a3
|
|
| MD5 |
062ed5db4746c762e2261cd5914bbba3
|
|
| BLAKE2b-256 |
765596c33b50b3a34c8d2e7c0afe2a690ab8e059c26f9717dff8c0d40f6cdbb2
|