uvd-x402-sdk 0.2.2__py3-none-any.whl → 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,778 +1,927 @@
1
- Metadata-Version: 2.1
2
- Name: uvd-x402-sdk
3
- Version: 0.2.2
4
- Summary: Python SDK for integrating x402 payments via the Ultravioleta DAO facilitator
5
- Author-email: Ultravioleta DAO <dev@ultravioletadao.xyz>
6
- Project-URL: Homepage, https://github.com/UltravioletaDAO/uvd-x402-sdk-python
7
- Project-URL: Documentation, https://docs.ultravioletadao.xyz/x402-sdk
8
- Project-URL: Repository, https://github.com/UltravioletaDAO/uvd-x402-sdk-python
9
- Project-URL: Issues, https://github.com/UltravioletaDAO/uvd-x402-sdk-python/issues
10
- Keywords: x402,payments,crypto,usdc,web3,evm,solana,near,stellar,facilitator
11
- Classifier: Development Status :: 4 - Beta
12
- Classifier: Intended Audience :: Developers
13
- Classifier: License :: OSI Approved :: MIT License
14
- Classifier: Operating System :: OS Independent
15
- Classifier: Programming Language :: Python :: 3
16
- Classifier: Programming Language :: Python :: 3.9
17
- Classifier: Programming Language :: Python :: 3.10
18
- Classifier: Programming Language :: Python :: 3.11
19
- Classifier: Programming Language :: Python :: 3.12
20
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
- Classifier: Topic :: Office/Business :: Financial :: Point-Of-Sale
22
- Requires-Python: >=3.9
23
- Description-Content-Type: text/markdown
24
- License-File: LICENSE
25
- Requires-Dist: httpx>=0.24.0
26
- Requires-Dist: pydantic>=2.0.0
27
- Provides-Extra: all
28
- Requires-Dist: uvd-x402-sdk[aws,django,fastapi,flask,web3]; extra == "all"
29
- Provides-Extra: aws
30
- Requires-Dist: boto3>=1.26.0; extra == "aws"
31
- Provides-Extra: dev
32
- Requires-Dist: pytest>=7.0.0; extra == "dev"
33
- Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
34
- Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
35
- Requires-Dist: black>=23.0.0; extra == "dev"
36
- Requires-Dist: ruff>=0.1.0; extra == "dev"
37
- Requires-Dist: mypy>=1.0.0; extra == "dev"
38
- Requires-Dist: httpx>=0.24.0; extra == "dev"
39
- Provides-Extra: django
40
- Requires-Dist: django>=4.0.0; extra == "django"
41
- Provides-Extra: fastapi
42
- Requires-Dist: fastapi>=0.100.0; extra == "fastapi"
43
- Requires-Dist: starlette>=0.27.0; extra == "fastapi"
44
- Provides-Extra: flask
45
- Requires-Dist: flask>=2.0.0; extra == "flask"
46
- Provides-Extra: web3
47
- Requires-Dist: web3>=6.0.0; extra == "web3"
48
- Requires-Dist: eth-account>=0.10.0; extra == "web3"
49
-
50
- # uvd-x402-sdk
51
-
52
- Python SDK for integrating **x402 cryptocurrency payments** via the Ultravioleta DAO facilitator.
53
-
54
- Accept USDC payments across **14 blockchain networks** with a single integration. The SDK handles signature verification, on-chain settlement, and all the complexity of multi-chain payments.
55
-
56
- ## Features
57
-
58
- - **14 Networks**: EVM chains (Base, Ethereum, Polygon, etc.), SVM chains (Solana, Fogo), NEAR, and Stellar
59
- - **x402 v1 & v2**: Full support for both protocol versions with auto-detection
60
- - **Framework Integrations**: Flask, FastAPI, Django, AWS Lambda
61
- - **Gasless Payments**: Users sign authorizations, facilitator pays all network fees
62
- - **Simple API**: Decorators and middleware for quick integration
63
- - **Type Safety**: Full Pydantic models and type hints
64
- - **Extensible**: Register custom networks easily
65
-
66
- ## Quick Start (5 Lines)
67
-
68
- ```python
69
- from decimal import Decimal
70
- from uvd_x402_sdk import X402Client
71
-
72
- client = X402Client(recipient_address="0xYourWallet...")
73
- result = client.process_payment(request.headers["X-PAYMENT"], Decimal("10.00"))
74
- print(f"Paid by {result.payer_address}, tx: {result.transaction_hash}")
75
- ```
76
-
77
- ## Supported Networks
78
-
79
- | Network | Type | Chain ID | CAIP-2 | Status |
80
- |---------|------|----------|--------|--------|
81
- | Base | EVM | 8453 | `eip155:8453` | Active |
82
- | Ethereum | EVM | 1 | `eip155:1` | Active |
83
- | Polygon | EVM | 137 | `eip155:137` | Active |
84
- | Arbitrum | EVM | 42161 | `eip155:42161` | Active |
85
- | Optimism | EVM | 10 | `eip155:10` | Active |
86
- | Avalanche | EVM | 43114 | `eip155:43114` | Active |
87
- | Celo | EVM | 42220 | `eip155:42220` | Active |
88
- | HyperEVM | EVM | 999 | `eip155:999` | Active |
89
- | Unichain | EVM | 130 | `eip155:130` | Active |
90
- | Monad | EVM | 143 | `eip155:143` | Active |
91
- | Solana | SVM | - | `solana:5eykt...` | Active |
92
- | Fogo | SVM | - | `solana:fogo` | Active |
93
- | NEAR | NEAR | - | `near:mainnet` | Active |
94
- | Stellar | Stellar | - | `stellar:pubnet` | Active |
95
-
96
- ## Installation
97
-
98
- ```bash
99
- # Core SDK (minimal dependencies)
100
- pip install uvd-x402-sdk
101
-
102
- # With framework support
103
- pip install uvd-x402-sdk[flask] # Flask integration
104
- pip install uvd-x402-sdk[fastapi] # FastAPI/Starlette integration
105
- pip install uvd-x402-sdk[django] # Django integration
106
- pip install uvd-x402-sdk[aws] # AWS Lambda helpers
107
-
108
- # All integrations
109
- pip install uvd-x402-sdk[all]
110
- ```
111
-
112
- ---
113
-
114
- ## Framework Examples
115
-
116
- ### Flask
117
-
118
- ```python
119
- from decimal import Decimal
120
- from flask import Flask, g, jsonify
121
- from uvd_x402_sdk.integrations import FlaskX402
122
-
123
- app = Flask(__name__)
124
- x402 = FlaskX402(
125
- app,
126
- recipient_address="0xYourEVMWallet...",
127
- recipient_solana="YourSolanaAddress...",
128
- recipient_near="your-account.near",
129
- recipient_stellar="G...YourStellarAddress",
130
- )
131
-
132
- @app.route("/api/premium")
133
- @x402.require_payment(amount_usd=Decimal("5.00"))
134
- def premium():
135
- return jsonify({
136
- "message": "Premium content!",
137
- "payer": g.payment_result.payer_address,
138
- "tx": g.payment_result.transaction_hash,
139
- "network": g.payment_result.network,
140
- })
141
-
142
- @app.route("/api/basic")
143
- @x402.require_payment(amount_usd=Decimal("0.10"))
144
- def basic():
145
- return jsonify({"data": "Basic tier data"})
146
-
147
- if __name__ == "__main__":
148
- app.run(debug=True)
149
- ```
150
-
151
- ### FastAPI
152
-
153
- ```python
154
- from decimal import Decimal
155
- from fastapi import FastAPI, Depends
156
- from uvd_x402_sdk.config import X402Config
157
- from uvd_x402_sdk.models import PaymentResult
158
- from uvd_x402_sdk.integrations import FastAPIX402
159
-
160
- app = FastAPI()
161
- x402 = FastAPIX402(
162
- app,
163
- recipient_address="0xYourEVMWallet...",
164
- recipient_solana="YourSolanaAddress...",
165
- recipient_near="your-account.near",
166
- recipient_stellar="G...YourStellarAddress",
167
- )
168
-
169
- @app.get("/api/premium")
170
- async def premium(
171
- payment: PaymentResult = Depends(x402.require_payment(amount_usd="5.00"))
172
- ):
173
- return {
174
- "message": "Premium content!",
175
- "payer": payment.payer_address,
176
- "network": payment.network,
177
- }
178
-
179
- @app.post("/api/generate")
180
- async def generate(
181
- body: dict,
182
- payment: PaymentResult = Depends(x402.require_payment(amount_usd="1.00"))
183
- ):
184
- # Dynamic processing based on request
185
- return {"result": "generated", "payer": payment.payer_address}
186
- ```
187
-
188
- ### Django
189
-
190
- ```python
191
- # settings.py
192
- X402_FACILITATOR_URL = "https://facilitator.ultravioletadao.xyz"
193
- X402_RECIPIENT_EVM = "0xYourEVMWallet..."
194
- X402_RECIPIENT_SOLANA = "YourSolanaAddress..."
195
- X402_RECIPIENT_NEAR = "your-account.near"
196
- X402_RECIPIENT_STELLAR = "G...YourStellarAddress"
197
- X402_PROTECTED_PATHS = {
198
- "/api/premium/": "5.00",
199
- "/api/basic/": "1.00",
200
- }
201
-
202
- MIDDLEWARE = [
203
- # ...other middleware...
204
- "uvd_x402_sdk.integrations.django_integration.DjangoX402Middleware",
205
- ]
206
-
207
- # views.py
208
- from django.http import JsonResponse
209
- from uvd_x402_sdk.integrations import django_x402_required
210
-
211
- @django_x402_required(amount_usd="5.00")
212
- def premium_view(request):
213
- payment = request.payment_result
214
- return JsonResponse({
215
- "message": "Premium content!",
216
- "payer": payment.payer_address,
217
- })
218
- ```
219
-
220
- ### AWS Lambda
221
-
222
- ```python
223
- import json
224
- from decimal import Decimal
225
- from uvd_x402_sdk.config import X402Config
226
- from uvd_x402_sdk.integrations import LambdaX402
227
-
228
- config = X402Config(
229
- recipient_evm="0xYourEVMWallet...",
230
- recipient_solana="YourSolanaAddress...",
231
- recipient_near="your-account.near",
232
- recipient_stellar="G...YourStellarAddress",
233
- )
234
- x402 = LambdaX402(config=config)
235
-
236
- def handler(event, context):
237
- # Calculate price based on request
238
- body = json.loads(event.get("body", "{}"))
239
- quantity = body.get("quantity", 1)
240
- price = Decimal(str(quantity * 0.01))
241
-
242
- # Process payment or return 402
243
- result = x402.process_or_require(event, price)
244
-
245
- # If 402 response, return it
246
- if isinstance(result, dict) and "statusCode" in result:
247
- return result
248
-
249
- # Payment verified!
250
- return {
251
- "statusCode": 200,
252
- "headers": {"Content-Type": "application/json"},
253
- "body": json.dumps({
254
- "success": True,
255
- "payer": result.payer_address,
256
- "tx": result.transaction_hash,
257
- "network": result.network,
258
- "quantity": quantity,
259
- })
260
- }
261
- ```
262
-
263
- ---
264
-
265
- ## Network-Specific Examples
266
-
267
- ### EVM Chains (Base, Ethereum, Polygon, etc.)
268
-
269
- EVM chains use ERC-3009 `TransferWithAuthorization` with EIP-712 signatures.
270
-
271
- ```python
272
- from uvd_x402_sdk import X402Client, X402Config
273
-
274
- # Accept payments on Base and Ethereum only
275
- config = X402Config(
276
- recipient_evm="0xYourEVMWallet...",
277
- supported_networks=["base", "ethereum"],
278
- )
279
-
280
- client = X402Client(config=config)
281
- result = client.process_payment(x_payment_header, Decimal("10.00"))
282
-
283
- # The payload contains EIP-712 signature + authorization
284
- payload = client.extract_payload(x_payment_header)
285
- evm_data = payload.get_evm_payload()
286
- print(f"From: {evm_data.authorization.from_address}")
287
- print(f"To: {evm_data.authorization.to}")
288
- print(f"Value: {evm_data.authorization.value}")
289
- ```
290
-
291
- ### Solana & Fogo (SVM Chains)
292
-
293
- SVM chains use partially-signed VersionedTransactions with SPL token transfers.
294
-
295
- ```python
296
- from uvd_x402_sdk import X402Client, X402Config
297
-
298
- # Accept payments on Solana and Fogo
299
- config = X402Config(
300
- recipient_solana="YourSolanaAddress...",
301
- supported_networks=["solana", "fogo"],
302
- )
303
-
304
- client = X402Client(config=config)
305
- result = client.process_payment(x_payment_header, Decimal("5.00"))
306
-
307
- # The payload contains a base64-encoded VersionedTransaction
308
- payload = client.extract_payload(x_payment_header)
309
- svm_data = payload.get_svm_payload()
310
- print(f"Transaction: {svm_data.transaction[:50]}...")
311
-
312
- # Fogo has ultra-fast finality (~400ms)
313
- if result.network == "fogo":
314
- print("Payment confirmed in ~400ms!")
315
- ```
316
-
317
- ### Stellar
318
-
319
- Stellar uses Soroban Authorization Entries with fee-bump transactions.
320
-
321
- ```python
322
- from uvd_x402_sdk import X402Client, X402Config
323
-
324
- config = X402Config(
325
- recipient_stellar="G...YourStellarAddress",
326
- supported_networks=["stellar"],
327
- )
328
-
329
- client = X402Client(config=config)
330
- result = client.process_payment(x_payment_header, Decimal("1.00"))
331
-
332
- # Stellar uses 7 decimals (stroops)
333
- payload = client.extract_payload(x_payment_header)
334
- stellar_data = payload.get_stellar_payload()
335
- print(f"From: {stellar_data.from_address}")
336
- print(f"Amount (stroops): {stellar_data.amount}")
337
- print(f"Token Contract: {stellar_data.tokenContract}")
338
- ```
339
-
340
- ### NEAR Protocol
341
-
342
- NEAR uses NEP-366 meta-transactions with Borsh serialization.
343
-
344
- ```python
345
- from uvd_x402_sdk import X402Client, X402Config
346
-
347
- config = X402Config(
348
- recipient_near="your-recipient.near",
349
- supported_networks=["near"],
350
- )
351
-
352
- client = X402Client(config=config)
353
- result = client.process_payment(x_payment_header, Decimal("2.00"))
354
-
355
- # NEAR payload contains a SignedDelegateAction
356
- payload = client.extract_payload(x_payment_header)
357
- near_data = payload.get_near_payload()
358
- print(f"SignedDelegateAction: {near_data.signedDelegateAction[:50]}...")
359
-
360
- # Validate NEAR payload structure
361
- from uvd_x402_sdk.networks.near import validate_near_payload
362
- validate_near_payload(payload.payload) # Raises ValueError if invalid
363
- ```
364
-
365
- ---
366
-
367
- ## x402 v1 vs v2
368
-
369
- The SDK supports both x402 protocol versions with automatic detection.
370
-
371
- ### Version Differences
372
-
373
- | Aspect | v1 | v2 |
374
- |--------|----|----|
375
- | Network ID | String (`"base"`) | CAIP-2 (`"eip155:8453"`) |
376
- | Payment delivery | JSON body | `PAYMENT-REQUIRED` header |
377
- | Multiple options | Limited | `accepts` array |
378
- | Discovery | Implicit | Optional extension |
379
-
380
- ### Auto-Detection
381
-
382
- ```python
383
- from uvd_x402_sdk import PaymentPayload
384
-
385
- # The SDK auto-detects based on network format
386
- payload = PaymentPayload(
387
- x402Version=1,
388
- scheme="exact",
389
- network="base", # v1 format
390
- payload={"signature": "...", "authorization": {...}}
391
- )
392
-
393
- print(payload.is_v2()) # False
394
-
395
- payload_v2 = PaymentPayload(
396
- x402Version=2,
397
- scheme="exact",
398
- network="eip155:8453", # v2 CAIP-2 format
399
- payload={"signature": "...", "authorization": {...}}
400
- )
401
-
402
- print(payload_v2.is_v2()) # True
403
-
404
- # Both work the same way
405
- print(payload.get_normalized_network()) # "base"
406
- print(payload_v2.get_normalized_network()) # "base"
407
- ```
408
-
409
- ### Creating v2 Responses
410
-
411
- ```python
412
- from uvd_x402_sdk import X402Config, create_402_response_v2, Payment402BuilderV2
413
-
414
- config = X402Config(
415
- recipient_evm="0xYourEVM...",
416
- recipient_solana="YourSolana...",
417
- recipient_near="your.near",
418
- recipient_stellar="G...Stellar",
419
- )
420
-
421
- # Simple v2 response
422
- response = create_402_response_v2(
423
- amount_usd=Decimal("5.00"),
424
- config=config,
425
- resource="/api/premium",
426
- description="Premium API access",
427
- )
428
- # Returns:
429
- # {
430
- # "x402Version": 2,
431
- # "scheme": "exact",
432
- # "resource": "/api/premium",
433
- # "accepts": [
434
- # {"network": "eip155:8453", "asset": "0x833...", "amount": "5000000", "payTo": "0xYour..."},
435
- # {"network": "solana:5eykt...", "asset": "EPjF...", "amount": "5000000", "payTo": "Your..."},
436
- # {"network": "near:mainnet", "asset": "1720...", "amount": "5000000", "payTo": "your.near"},
437
- # ...
438
- # ]
439
- # }
440
-
441
- # Builder pattern for more control
442
- response = (
443
- Payment402BuilderV2(config)
444
- .amount(Decimal("10.00"))
445
- .resource("/api/generate")
446
- .description("AI generation credits")
447
- .networks(["base", "solana", "near"]) # Limit to specific networks
448
- .build()
449
- )
450
- ```
451
-
452
- ---
453
-
454
- ## Payload Validation
455
-
456
- Each network type has specific payload validation:
457
-
458
- ### EVM Validation
459
-
460
- ```python
461
- from uvd_x402_sdk.models import EVMPayloadContent, EVMAuthorization
462
-
463
- # Parse and validate EVM payload
464
- payload = client.extract_payload(x_payment_header)
465
- evm_data = payload.get_evm_payload()
466
-
467
- # Validate authorization fields
468
- auth = evm_data.authorization
469
- assert auth.from_address.startswith("0x")
470
- assert auth.to.startswith("0x")
471
- assert int(auth.value) > 0
472
- assert int(auth.validBefore) > int(auth.validAfter)
473
- ```
474
-
475
- ### SVM Validation
476
-
477
- ```python
478
- from uvd_x402_sdk.networks.solana import validate_svm_payload, is_valid_solana_address
479
-
480
- # Validate SVM payload
481
- payload = client.extract_payload(x_payment_header)
482
- validate_svm_payload(payload.payload) # Raises ValueError if invalid
483
-
484
- # Validate Solana addresses
485
- assert is_valid_solana_address("YourSolanaAddress...")
486
- ```
487
-
488
- ### NEAR Validation
489
-
490
- ```python
491
- from uvd_x402_sdk.networks.near import (
492
- validate_near_payload,
493
- is_valid_near_account_id,
494
- BorshSerializer,
495
- )
496
-
497
- # Validate NEAR payload
498
- payload = client.extract_payload(x_payment_header)
499
- validate_near_payload(payload.payload) # Raises ValueError if invalid
500
-
501
- # Validate NEAR account IDs
502
- assert is_valid_near_account_id("your-account.near")
503
- assert is_valid_near_account_id("0xultravioleta.near")
504
- ```
505
-
506
- ### Stellar Validation
507
-
508
- ```python
509
- from uvd_x402_sdk.networks.stellar import (
510
- is_valid_stellar_address,
511
- is_valid_contract_address,
512
- stroops_to_usd,
513
- )
514
-
515
- # Validate Stellar addresses
516
- assert is_valid_stellar_address("G...YourStellarAddress") # G...
517
- assert is_valid_contract_address("C...USDCContract") # C...
518
-
519
- # Convert stroops to USD (7 decimals)
520
- usd = stroops_to_usd(50000000) # Returns 5.0
521
- ```
522
-
523
- ---
524
-
525
- ## Configuration
526
-
527
- ### Environment Variables
528
-
529
- ```bash
530
- # Core configuration
531
- X402_FACILITATOR_URL=https://facilitator.ultravioletadao.xyz
532
- X402_VERIFY_TIMEOUT=30
533
- X402_SETTLE_TIMEOUT=55
534
-
535
- # Recipient addresses (at least one required)
536
- X402_RECIPIENT_EVM=0xYourEVMWallet
537
- X402_RECIPIENT_SOLANA=YourSolanaAddress
538
- X402_RECIPIENT_NEAR=your-account.near
539
- X402_RECIPIENT_STELLAR=G...YourStellarAddress
540
-
541
- # Optional
542
- X402_FACILITATOR_SOLANA=F742C4VfFLQ9zRQyithoj5229ZgtX2WqKCSFKgH2EThq
543
- X402_RESOURCE_URL=https://api.example.com
544
- X402_DESCRIPTION=API access payment
545
- ```
546
-
547
- ### Programmatic Configuration
548
-
549
- ```python
550
- from uvd_x402_sdk import X402Config, MultiPaymentConfig
551
-
552
- # Full configuration
553
- config = X402Config(
554
- facilitator_url="https://facilitator.ultravioletadao.xyz",
555
-
556
- # Recipients
557
- recipient_evm="0xYourEVMWallet",
558
- recipient_solana="YourSolanaAddress",
559
- recipient_near="your-account.near",
560
- recipient_stellar="G...YourStellarAddress",
561
-
562
- # Timeouts
563
- verify_timeout=30.0,
564
- settle_timeout=55.0,
565
-
566
- # Limit to specific networks
567
- supported_networks=["base", "solana", "near", "stellar"],
568
-
569
- # Metadata
570
- resource_url="https://api.example.com/premium",
571
- description="Premium API access",
572
-
573
- # Protocol version (1, 2, or "auto")
574
- x402_version="auto",
575
- )
576
-
577
- # From environment
578
- config = X402Config.from_env()
579
- ```
580
-
581
- ---
582
-
583
- ## Registering Custom Networks
584
-
585
- ```python
586
- from uvd_x402_sdk.networks import NetworkConfig, NetworkType, register_network
587
-
588
- # Register a custom EVM network
589
- custom_chain = NetworkConfig(
590
- name="mychain",
591
- display_name="My Custom Chain",
592
- network_type=NetworkType.EVM,
593
- chain_id=12345,
594
- usdc_address="0xUSDCContractAddress",
595
- usdc_decimals=6,
596
- usdc_domain_name="USD Coin", # Check actual EIP-712 domain!
597
- usdc_domain_version="2",
598
- rpc_url="https://rpc.mychain.com",
599
- enabled=True,
600
- )
601
-
602
- register_network(custom_chain)
603
-
604
- # Now you can use it
605
- config = X402Config(
606
- recipient_evm="0xYourWallet...",
607
- supported_networks=["base", "mychain"],
608
- )
609
- ```
610
-
611
- ---
612
-
613
- ## Error Handling
614
-
615
- ```python
616
- from uvd_x402_sdk.exceptions import (
617
- X402Error,
618
- PaymentRequiredError,
619
- PaymentVerificationError,
620
- PaymentSettlementError,
621
- UnsupportedNetworkError,
622
- InvalidPayloadError,
623
- FacilitatorError,
624
- X402TimeoutError,
625
- )
626
-
627
- try:
628
- result = client.process_payment(header, amount)
629
- except PaymentVerificationError as e:
630
- # Signature invalid, amount mismatch, expired, etc.
631
- print(f"Verification failed: {e.reason}")
632
- print(f"Errors: {e.errors}")
633
- except PaymentSettlementError as e:
634
- # On-chain settlement failed (insufficient balance, nonce used, etc.)
635
- print(f"Settlement failed on {e.network}: {e.message}")
636
- except UnsupportedNetworkError as e:
637
- # Network not recognized or disabled
638
- print(f"Network {e.network} not supported")
639
- print(f"Supported: {e.supported_networks}")
640
- except InvalidPayloadError as e:
641
- # Malformed X-PAYMENT header
642
- print(f"Invalid payload: {e.message}")
643
- except FacilitatorError as e:
644
- # Facilitator returned error
645
- print(f"Facilitator error: {e.status_code} - {e.response_body}")
646
- except X402TimeoutError as e:
647
- # Request timed out
648
- print(f"{e.operation} timed out after {e.timeout_seconds}s")
649
- except X402Error as e:
650
- # Catch-all for x402 errors
651
- print(f"Payment error: {e.message}")
652
- ```
653
-
654
- ---
655
-
656
- ## How x402 Works
657
-
658
- The x402 protocol enables gasless USDC payments:
659
-
660
- ```
661
- 1. User Request --> Client sends request without payment
662
- 2. 402 Response <-- Server returns payment requirements
663
- 3. User Signs --> Wallet signs authorization (NO GAS!)
664
- 4. Frontend Sends --> X-PAYMENT header with signed payload
665
- 5. SDK Verifies --> Validates signature with facilitator
666
- 6. SDK Settles --> Facilitator executes on-chain transfer
667
- 7. Success <-- Payment confirmed, request processed
668
- ```
669
-
670
- The facilitator (https://facilitator.ultravioletadao.xyz) handles all on-chain interactions and pays gas fees on behalf of users.
671
-
672
- ### Payment Flow by Network Type
673
-
674
- | Network Type | User Signs | Facilitator Does |
675
- |--------------|-----------|------------------|
676
- | EVM | EIP-712 message | Calls `transferWithAuthorization()` |
677
- | SVM | Partial transaction | Co-signs + submits transaction |
678
- | NEAR | DelegateAction (Borsh) | Wraps in `Action::Delegate` |
679
- | Stellar | Auth entry (XDR) | Wraps in fee-bump transaction |
680
-
681
- ---
682
-
683
- ## Troubleshooting
684
-
685
- ### Common Issues
686
-
687
- **"Unsupported network"**
688
- - Check that the network is in `supported_networks`
689
- - Verify the network is enabled
690
- - For v2, ensure CAIP-2 format is correct
691
-
692
- **"Payment verification failed"**
693
- - Amount mismatch between expected and signed
694
- - Recipient address mismatch
695
- - Authorization expired (`validBefore` in the past)
696
- - Nonce already used (replay attack protection)
697
-
698
- **"Settlement timed out"**
699
- - Network congestion - increase `settle_timeout`
700
- - Facilitator under load - retry after delay
701
-
702
- **"Invalid payload"**
703
- - Check base64 encoding of X-PAYMENT header
704
- - Verify JSON structure matches expected format
705
- - Ensure `x402Version` is 1 or 2
706
-
707
- ### Debug Logging
708
-
709
- ```python
710
- import logging
711
- logging.basicConfig(level=logging.DEBUG)
712
- logging.getLogger("uvd_x402_sdk").setLevel(logging.DEBUG)
713
- ```
714
-
715
- ---
716
-
717
- ## Development
718
-
719
- ```bash
720
- # Clone and install
721
- git clone https://github.com/ultravioletadao/uvd-x402-sdk
722
- cd uvd-x402-sdk/sdk/python
723
- pip install -e ".[dev]"
724
-
725
- # Run tests
726
- pytest
727
-
728
- # Format code
729
- black src tests
730
- ruff check src tests
731
-
732
- # Type checking
733
- mypy src
734
- ```
735
-
736
- ---
737
-
738
- ## Links
739
-
740
- - [Ultravioleta DAO](https://ultravioletadao.xyz)
741
- - [402milly Pixel Marketplace](https://402milly.xyz)
742
- - [x402 Protocol Documentation](https://docs.ultravioletadao.xyz/x402)
743
- - [Facilitator Status](https://facilitator.ultravioletadao.xyz/health)
744
- - [GitHub Issues](https://github.com/ultravioletadao/uvd-x402-sdk/issues)
745
-
746
- ---
747
-
748
- ## License
749
-
750
- MIT License - see LICENSE file.
751
-
752
- ---
753
-
754
- ## Changelog
755
-
756
- ### v0.2.1 (2025-12-16)
757
-
758
- - Removed BSC network (doesn't support ERC-3009)
759
- - Added GitHub Actions workflow for PyPI publishing
760
- - Updated to 14 supported networks
761
-
762
- ### v0.2.0 (2025-12-15)
763
-
764
- - Added **NEAR Protocol** support with NEP-366 meta-transactions
765
- - Added **Fogo** SVM chain support
766
- - Added **x402 v2** protocol support with CAIP-2 network identifiers
767
- - Added `accepts` array for multi-network payment options
768
- - Refactored Solana to generic SVM type (supports Solana, Fogo, future SVM chains)
769
- - Added CAIP-2 parsing utilities (`parse_caip2_network`, `to_caip2_network`)
770
- - Added `MultiPaymentConfig` for multi-network recipient configuration
771
- - Added `Payment402BuilderV2` for v2 response construction
772
-
773
- ### v0.1.0 (2025-12-01)
774
-
775
- - Initial release
776
- - EVM, Solana, Stellar network support
777
- - Flask, FastAPI, Django, Lambda integrations
778
- - Full Pydantic models
1
+ Metadata-Version: 2.1
2
+ Name: uvd-x402-sdk
3
+ Version: 0.3.0
4
+ Summary: Python SDK for x402 payments - gasless crypto payments across 14 blockchains with multi-stablecoin support (USDC, EURC, AUSD, PYUSD, GHO, crvUSD)
5
+ Author-email: Ultravioleta DAO <dev@ultravioletadao.xyz>
6
+ Project-URL: Homepage, https://github.com/UltravioletaDAO/uvd-x402-sdk-python
7
+ Project-URL: Documentation, https://docs.ultravioletadao.xyz/x402-sdk
8
+ Project-URL: Repository, https://github.com/UltravioletaDAO/uvd-x402-sdk-python
9
+ Project-URL: Issues, https://github.com/UltravioletaDAO/uvd-x402-sdk-python/issues
10
+ Keywords: x402,payments,crypto,usdc,eurc,stablecoin,web3,evm,solana,near,stellar,facilitator,gasless,eip-712,eip-3009
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Topic :: Office/Business :: Financial :: Point-Of-Sale
22
+ Requires-Python: >=3.9
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: httpx>=0.24.0
26
+ Requires-Dist: pydantic>=2.0.0
27
+ Provides-Extra: all
28
+ Requires-Dist: uvd-x402-sdk[aws,django,fastapi,flask,web3]; extra == "all"
29
+ Provides-Extra: aws
30
+ Requires-Dist: boto3>=1.26.0; extra == "aws"
31
+ Provides-Extra: dev
32
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
33
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
34
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
35
+ Requires-Dist: black>=23.0.0; extra == "dev"
36
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
37
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
38
+ Requires-Dist: httpx>=0.24.0; extra == "dev"
39
+ Provides-Extra: django
40
+ Requires-Dist: django>=4.0.0; extra == "django"
41
+ Provides-Extra: fastapi
42
+ Requires-Dist: fastapi>=0.100.0; extra == "fastapi"
43
+ Requires-Dist: starlette>=0.27.0; extra == "fastapi"
44
+ Provides-Extra: flask
45
+ Requires-Dist: flask>=2.0.0; extra == "flask"
46
+ Provides-Extra: web3
47
+ Requires-Dist: web3>=6.0.0; extra == "web3"
48
+ Requires-Dist: eth-account>=0.10.0; extra == "web3"
49
+
50
+ # uvd-x402-sdk
51
+
52
+ Python SDK for integrating **x402 cryptocurrency payments** via the Ultravioleta DAO facilitator.
53
+
54
+ Accept **gasless stablecoin payments** across **14 blockchain networks** with a single integration. The SDK handles signature verification, on-chain settlement, and all the complexity of multi-chain payments.
55
+
56
+ ## Features
57
+
58
+ - **14 Networks**: EVM chains (Base, Ethereum, Polygon, etc.), SVM chains (Solana, Fogo), NEAR, and Stellar
59
+ - **6 Stablecoins**: USDC, EURC, AUSD, PYUSD, GHO, crvUSD (EVM chains)
60
+ - **x402 v1 & v2**: Full support for both protocol versions with auto-detection
61
+ - **Framework Integrations**: Flask, FastAPI, Django, AWS Lambda
62
+ - **Gasless Payments**: Users sign EIP-712/EIP-3009 authorizations, facilitator pays all network fees
63
+ - **Simple API**: Decorators and middleware for quick integration
64
+ - **Type Safety**: Full Pydantic models and type hints
65
+ - **Extensible**: Register custom networks and tokens easily
66
+
67
+ ## Quick Start (5 Lines)
68
+
69
+ ```python
70
+ from decimal import Decimal
71
+ from uvd_x402_sdk import X402Client
72
+
73
+ client = X402Client(recipient_address="0xYourWallet...")
74
+ result = client.process_payment(request.headers["X-PAYMENT"], Decimal("10.00"))
75
+ print(f"Paid by {result.payer_address}, tx: {result.transaction_hash}")
76
+ ```
77
+
78
+ ## Supported Networks
79
+
80
+ | Network | Type | Chain ID | CAIP-2 | Status |
81
+ |---------|------|----------|--------|--------|
82
+ | Base | EVM | 8453 | `eip155:8453` | Active |
83
+ | Ethereum | EVM | 1 | `eip155:1` | Active |
84
+ | Polygon | EVM | 137 | `eip155:137` | Active |
85
+ | Arbitrum | EVM | 42161 | `eip155:42161` | Active |
86
+ | Optimism | EVM | 10 | `eip155:10` | Active |
87
+ | Avalanche | EVM | 43114 | `eip155:43114` | Active |
88
+ | Celo | EVM | 42220 | `eip155:42220` | Active |
89
+ | HyperEVM | EVM | 999 | `eip155:999` | Active |
90
+ | Unichain | EVM | 130 | `eip155:130` | Active |
91
+ | Monad | EVM | 143 | `eip155:143` | Active |
92
+ | Solana | SVM | - | `solana:5eykt...` | Active |
93
+ | Fogo | SVM | - | `solana:fogo` | Active |
94
+ | NEAR | NEAR | - | `near:mainnet` | Active |
95
+ | Stellar | Stellar | - | `stellar:pubnet` | Active |
96
+
97
+ ### Supported Tokens (EVM Chains)
98
+
99
+ | Token | Networks | Decimals |
100
+ |-------|----------|----------|
101
+ | USDC | All EVM chains | 6 |
102
+ | EURC | Ethereum, Base, Avalanche | 6 |
103
+ | AUSD | Ethereum, Arbitrum, Avalanche, Polygon, Monad | 6 |
104
+ | PYUSD | Ethereum | 6 |
105
+ | GHO | Ethereum, Base, Arbitrum | 18 |
106
+ | crvUSD | Ethereum, Arbitrum | 18 |
107
+
108
+ ## Installation
109
+
110
+ ```bash
111
+ # Core SDK (minimal dependencies)
112
+ pip install uvd-x402-sdk
113
+
114
+ # With framework support
115
+ pip install uvd-x402-sdk[flask] # Flask integration
116
+ pip install uvd-x402-sdk[fastapi] # FastAPI/Starlette integration
117
+ pip install uvd-x402-sdk[django] # Django integration
118
+ pip install uvd-x402-sdk[aws] # AWS Lambda helpers
119
+
120
+ # All integrations
121
+ pip install uvd-x402-sdk[all]
122
+ ```
123
+
124
+ ---
125
+
126
+ ## Framework Examples
127
+
128
+ ### Flask
129
+
130
+ ```python
131
+ from decimal import Decimal
132
+ from flask import Flask, g, jsonify
133
+ from uvd_x402_sdk.integrations import FlaskX402
134
+
135
+ app = Flask(__name__)
136
+ x402 = FlaskX402(
137
+ app,
138
+ recipient_address="0xYourEVMWallet...",
139
+ recipient_solana="YourSolanaAddress...",
140
+ recipient_near="your-account.near",
141
+ recipient_stellar="G...YourStellarAddress",
142
+ )
143
+
144
+ @app.route("/api/premium")
145
+ @x402.require_payment(amount_usd=Decimal("5.00"))
146
+ def premium():
147
+ return jsonify({
148
+ "message": "Premium content!",
149
+ "payer": g.payment_result.payer_address,
150
+ "tx": g.payment_result.transaction_hash,
151
+ "network": g.payment_result.network,
152
+ })
153
+
154
+ @app.route("/api/basic")
155
+ @x402.require_payment(amount_usd=Decimal("0.10"))
156
+ def basic():
157
+ return jsonify({"data": "Basic tier data"})
158
+
159
+ if __name__ == "__main__":
160
+ app.run(debug=True)
161
+ ```
162
+
163
+ ### FastAPI
164
+
165
+ ```python
166
+ from decimal import Decimal
167
+ from fastapi import FastAPI, Depends
168
+ from uvd_x402_sdk.config import X402Config
169
+ from uvd_x402_sdk.models import PaymentResult
170
+ from uvd_x402_sdk.integrations import FastAPIX402
171
+
172
+ app = FastAPI()
173
+ x402 = FastAPIX402(
174
+ app,
175
+ recipient_address="0xYourEVMWallet...",
176
+ recipient_solana="YourSolanaAddress...",
177
+ recipient_near="your-account.near",
178
+ recipient_stellar="G...YourStellarAddress",
179
+ )
180
+
181
+ @app.get("/api/premium")
182
+ async def premium(
183
+ payment: PaymentResult = Depends(x402.require_payment(amount_usd="5.00"))
184
+ ):
185
+ return {
186
+ "message": "Premium content!",
187
+ "payer": payment.payer_address,
188
+ "network": payment.network,
189
+ }
190
+
191
+ @app.post("/api/generate")
192
+ async def generate(
193
+ body: dict,
194
+ payment: PaymentResult = Depends(x402.require_payment(amount_usd="1.00"))
195
+ ):
196
+ # Dynamic processing based on request
197
+ return {"result": "generated", "payer": payment.payer_address}
198
+ ```
199
+
200
+ ### Django
201
+
202
+ ```python
203
+ # settings.py
204
+ X402_FACILITATOR_URL = "https://facilitator.ultravioletadao.xyz"
205
+ X402_RECIPIENT_EVM = "0xYourEVMWallet..."
206
+ X402_RECIPIENT_SOLANA = "YourSolanaAddress..."
207
+ X402_RECIPIENT_NEAR = "your-account.near"
208
+ X402_RECIPIENT_STELLAR = "G...YourStellarAddress"
209
+ X402_PROTECTED_PATHS = {
210
+ "/api/premium/": "5.00",
211
+ "/api/basic/": "1.00",
212
+ }
213
+
214
+ MIDDLEWARE = [
215
+ # ...other middleware...
216
+ "uvd_x402_sdk.integrations.django_integration.DjangoX402Middleware",
217
+ ]
218
+
219
+ # views.py
220
+ from django.http import JsonResponse
221
+ from uvd_x402_sdk.integrations import django_x402_required
222
+
223
+ @django_x402_required(amount_usd="5.00")
224
+ def premium_view(request):
225
+ payment = request.payment_result
226
+ return JsonResponse({
227
+ "message": "Premium content!",
228
+ "payer": payment.payer_address,
229
+ })
230
+ ```
231
+
232
+ ### AWS Lambda
233
+
234
+ ```python
235
+ import json
236
+ from decimal import Decimal
237
+ from uvd_x402_sdk.config import X402Config
238
+ from uvd_x402_sdk.integrations import LambdaX402
239
+
240
+ config = X402Config(
241
+ recipient_evm="0xYourEVMWallet...",
242
+ recipient_solana="YourSolanaAddress...",
243
+ recipient_near="your-account.near",
244
+ recipient_stellar="G...YourStellarAddress",
245
+ )
246
+ x402 = LambdaX402(config=config)
247
+
248
+ def handler(event, context):
249
+ # Calculate price based on request
250
+ body = json.loads(event.get("body", "{}"))
251
+ quantity = body.get("quantity", 1)
252
+ price = Decimal(str(quantity * 0.01))
253
+
254
+ # Process payment or return 402
255
+ result = x402.process_or_require(event, price)
256
+
257
+ # If 402 response, return it
258
+ if isinstance(result, dict) and "statusCode" in result:
259
+ return result
260
+
261
+ # Payment verified!
262
+ return {
263
+ "statusCode": 200,
264
+ "headers": {"Content-Type": "application/json"},
265
+ "body": json.dumps({
266
+ "success": True,
267
+ "payer": result.payer_address,
268
+ "tx": result.transaction_hash,
269
+ "network": result.network,
270
+ "quantity": quantity,
271
+ })
272
+ }
273
+ ```
274
+
275
+ ---
276
+
277
+ ## Network-Specific Examples
278
+
279
+ ### EVM Chains (Base, Ethereum, Polygon, etc.)
280
+
281
+ EVM chains use ERC-3009 `TransferWithAuthorization` with EIP-712 signatures.
282
+
283
+ ```python
284
+ from uvd_x402_sdk import X402Client, X402Config
285
+
286
+ # Accept payments on Base and Ethereum only
287
+ config = X402Config(
288
+ recipient_evm="0xYourEVMWallet...",
289
+ supported_networks=["base", "ethereum"],
290
+ )
291
+
292
+ client = X402Client(config=config)
293
+ result = client.process_payment(x_payment_header, Decimal("10.00"))
294
+
295
+ # The payload contains EIP-712 signature + authorization
296
+ payload = client.extract_payload(x_payment_header)
297
+ evm_data = payload.get_evm_payload()
298
+ print(f"From: {evm_data.authorization.from_address}")
299
+ print(f"To: {evm_data.authorization.to}")
300
+ print(f"Value: {evm_data.authorization.value}")
301
+ ```
302
+
303
+ ### Solana & Fogo (SVM Chains)
304
+
305
+ SVM chains use partially-signed VersionedTransactions with SPL token transfers.
306
+
307
+ ```python
308
+ from uvd_x402_sdk import X402Client, X402Config
309
+
310
+ # Accept payments on Solana and Fogo
311
+ config = X402Config(
312
+ recipient_solana="YourSolanaAddress...",
313
+ supported_networks=["solana", "fogo"],
314
+ )
315
+
316
+ client = X402Client(config=config)
317
+ result = client.process_payment(x_payment_header, Decimal("5.00"))
318
+
319
+ # The payload contains a base64-encoded VersionedTransaction
320
+ payload = client.extract_payload(x_payment_header)
321
+ svm_data = payload.get_svm_payload()
322
+ print(f"Transaction: {svm_data.transaction[:50]}...")
323
+
324
+ # Fogo has ultra-fast finality (~400ms)
325
+ if result.network == "fogo":
326
+ print("Payment confirmed in ~400ms!")
327
+ ```
328
+
329
+ ### Stellar
330
+
331
+ Stellar uses Soroban Authorization Entries with fee-bump transactions.
332
+
333
+ ```python
334
+ from uvd_x402_sdk import X402Client, X402Config
335
+
336
+ config = X402Config(
337
+ recipient_stellar="G...YourStellarAddress",
338
+ supported_networks=["stellar"],
339
+ )
340
+
341
+ client = X402Client(config=config)
342
+ result = client.process_payment(x_payment_header, Decimal("1.00"))
343
+
344
+ # Stellar uses 7 decimals (stroops)
345
+ payload = client.extract_payload(x_payment_header)
346
+ stellar_data = payload.get_stellar_payload()
347
+ print(f"From: {stellar_data.from_address}")
348
+ print(f"Amount (stroops): {stellar_data.amount}")
349
+ print(f"Token Contract: {stellar_data.tokenContract}")
350
+ ```
351
+
352
+ ### NEAR Protocol
353
+
354
+ NEAR uses NEP-366 meta-transactions with Borsh serialization.
355
+
356
+ ```python
357
+ from uvd_x402_sdk import X402Client, X402Config
358
+
359
+ config = X402Config(
360
+ recipient_near="your-recipient.near",
361
+ supported_networks=["near"],
362
+ )
363
+
364
+ client = X402Client(config=config)
365
+ result = client.process_payment(x_payment_header, Decimal("2.00"))
366
+
367
+ # NEAR payload contains a SignedDelegateAction
368
+ payload = client.extract_payload(x_payment_header)
369
+ near_data = payload.get_near_payload()
370
+ print(f"SignedDelegateAction: {near_data.signedDelegateAction[:50]}...")
371
+
372
+ # Validate NEAR payload structure
373
+ from uvd_x402_sdk.networks.near import validate_near_payload
374
+ validate_near_payload(payload.payload) # Raises ValueError if invalid
375
+ ```
376
+
377
+ ---
378
+
379
+ ## x402 v1 vs v2
380
+
381
+ The SDK supports both x402 protocol versions with automatic detection.
382
+
383
+ ### Version Differences
384
+
385
+ | Aspect | v1 | v2 |
386
+ |--------|----|----|
387
+ | Network ID | String (`"base"`) | CAIP-2 (`"eip155:8453"`) |
388
+ | Payment delivery | JSON body | `PAYMENT-REQUIRED` header |
389
+ | Multiple options | Limited | `accepts` array |
390
+ | Discovery | Implicit | Optional extension |
391
+
392
+ ### Auto-Detection
393
+
394
+ ```python
395
+ from uvd_x402_sdk import PaymentPayload
396
+
397
+ # The SDK auto-detects based on network format
398
+ payload = PaymentPayload(
399
+ x402Version=1,
400
+ scheme="exact",
401
+ network="base", # v1 format
402
+ payload={"signature": "...", "authorization": {...}}
403
+ )
404
+
405
+ print(payload.is_v2()) # False
406
+
407
+ payload_v2 = PaymentPayload(
408
+ x402Version=2,
409
+ scheme="exact",
410
+ network="eip155:8453", # v2 CAIP-2 format
411
+ payload={"signature": "...", "authorization": {...}}
412
+ )
413
+
414
+ print(payload_v2.is_v2()) # True
415
+
416
+ # Both work the same way
417
+ print(payload.get_normalized_network()) # "base"
418
+ print(payload_v2.get_normalized_network()) # "base"
419
+ ```
420
+
421
+ ### Creating v2 Responses
422
+
423
+ ```python
424
+ from uvd_x402_sdk import X402Config, create_402_response_v2, Payment402BuilderV2
425
+
426
+ config = X402Config(
427
+ recipient_evm="0xYourEVM...",
428
+ recipient_solana="YourSolana...",
429
+ recipient_near="your.near",
430
+ recipient_stellar="G...Stellar",
431
+ )
432
+
433
+ # Simple v2 response
434
+ response = create_402_response_v2(
435
+ amount_usd=Decimal("5.00"),
436
+ config=config,
437
+ resource="/api/premium",
438
+ description="Premium API access",
439
+ )
440
+ # Returns:
441
+ # {
442
+ # "x402Version": 2,
443
+ # "scheme": "exact",
444
+ # "resource": "/api/premium",
445
+ # "accepts": [
446
+ # {"network": "eip155:8453", "asset": "0x833...", "amount": "5000000", "payTo": "0xYour..."},
447
+ # {"network": "solana:5eykt...", "asset": "EPjF...", "amount": "5000000", "payTo": "Your..."},
448
+ # {"network": "near:mainnet", "asset": "1720...", "amount": "5000000", "payTo": "your.near"},
449
+ # ...
450
+ # ]
451
+ # }
452
+
453
+ # Builder pattern for more control
454
+ response = (
455
+ Payment402BuilderV2(config)
456
+ .amount(Decimal("10.00"))
457
+ .resource("/api/generate")
458
+ .description("AI generation credits")
459
+ .networks(["base", "solana", "near"]) # Limit to specific networks
460
+ .build()
461
+ )
462
+ ```
463
+
464
+ ---
465
+
466
+ ## Payload Validation
467
+
468
+ Each network type has specific payload validation:
469
+
470
+ ### EVM Validation
471
+
472
+ ```python
473
+ from uvd_x402_sdk.models import EVMPayloadContent, EVMAuthorization
474
+
475
+ # Parse and validate EVM payload
476
+ payload = client.extract_payload(x_payment_header)
477
+ evm_data = payload.get_evm_payload()
478
+
479
+ # Validate authorization fields
480
+ auth = evm_data.authorization
481
+ assert auth.from_address.startswith("0x")
482
+ assert auth.to.startswith("0x")
483
+ assert int(auth.value) > 0
484
+ assert int(auth.validBefore) > int(auth.validAfter)
485
+ ```
486
+
487
+ ### SVM Validation
488
+
489
+ ```python
490
+ from uvd_x402_sdk.networks.solana import validate_svm_payload, is_valid_solana_address
491
+
492
+ # Validate SVM payload
493
+ payload = client.extract_payload(x_payment_header)
494
+ validate_svm_payload(payload.payload) # Raises ValueError if invalid
495
+
496
+ # Validate Solana addresses
497
+ assert is_valid_solana_address("YourSolanaAddress...")
498
+ ```
499
+
500
+ ### NEAR Validation
501
+
502
+ ```python
503
+ from uvd_x402_sdk.networks.near import (
504
+ validate_near_payload,
505
+ is_valid_near_account_id,
506
+ BorshSerializer,
507
+ )
508
+
509
+ # Validate NEAR payload
510
+ payload = client.extract_payload(x_payment_header)
511
+ validate_near_payload(payload.payload) # Raises ValueError if invalid
512
+
513
+ # Validate NEAR account IDs
514
+ assert is_valid_near_account_id("your-account.near")
515
+ assert is_valid_near_account_id("0xultravioleta.near")
516
+ ```
517
+
518
+ ### Stellar Validation
519
+
520
+ ```python
521
+ from uvd_x402_sdk.networks.stellar import (
522
+ is_valid_stellar_address,
523
+ is_valid_contract_address,
524
+ stroops_to_usd,
525
+ )
526
+
527
+ # Validate Stellar addresses
528
+ assert is_valid_stellar_address("G...YourStellarAddress") # G...
529
+ assert is_valid_contract_address("C...USDCContract") # C...
530
+
531
+ # Convert stroops to USD (7 decimals)
532
+ usd = stroops_to_usd(50000000) # Returns 5.0
533
+ ```
534
+
535
+ ---
536
+
537
+ ## Configuration
538
+
539
+ ### Environment Variables
540
+
541
+ ```bash
542
+ # Core configuration
543
+ X402_FACILITATOR_URL=https://facilitator.ultravioletadao.xyz
544
+ X402_VERIFY_TIMEOUT=30
545
+ X402_SETTLE_TIMEOUT=55
546
+
547
+ # Recipient addresses (at least one required)
548
+ X402_RECIPIENT_EVM=0xYourEVMWallet
549
+ X402_RECIPIENT_SOLANA=YourSolanaAddress
550
+ X402_RECIPIENT_NEAR=your-account.near
551
+ X402_RECIPIENT_STELLAR=G...YourStellarAddress
552
+
553
+ # Optional
554
+ X402_FACILITATOR_SOLANA=F742C4VfFLQ9zRQyithoj5229ZgtX2WqKCSFKgH2EThq
555
+ X402_RESOURCE_URL=https://api.example.com
556
+ X402_DESCRIPTION=API access payment
557
+ ```
558
+
559
+ ### Programmatic Configuration
560
+
561
+ ```python
562
+ from uvd_x402_sdk import X402Config, MultiPaymentConfig
563
+
564
+ # Full configuration
565
+ config = X402Config(
566
+ facilitator_url="https://facilitator.ultravioletadao.xyz",
567
+
568
+ # Recipients
569
+ recipient_evm="0xYourEVMWallet",
570
+ recipient_solana="YourSolanaAddress",
571
+ recipient_near="your-account.near",
572
+ recipient_stellar="G...YourStellarAddress",
573
+
574
+ # Timeouts
575
+ verify_timeout=30.0,
576
+ settle_timeout=55.0,
577
+
578
+ # Limit to specific networks
579
+ supported_networks=["base", "solana", "near", "stellar"],
580
+
581
+ # Metadata
582
+ resource_url="https://api.example.com/premium",
583
+ description="Premium API access",
584
+
585
+ # Protocol version (1, 2, or "auto")
586
+ x402_version="auto",
587
+ )
588
+
589
+ # From environment
590
+ config = X402Config.from_env()
591
+ ```
592
+
593
+ ---
594
+
595
+ ## Registering Custom Networks
596
+
597
+ ```python
598
+ from uvd_x402_sdk.networks import NetworkConfig, NetworkType, register_network
599
+
600
+ # Register a custom EVM network
601
+ custom_chain = NetworkConfig(
602
+ name="mychain",
603
+ display_name="My Custom Chain",
604
+ network_type=NetworkType.EVM,
605
+ chain_id=12345,
606
+ usdc_address="0xUSDCContractAddress",
607
+ usdc_decimals=6,
608
+ usdc_domain_name="USD Coin", # Check actual EIP-712 domain!
609
+ usdc_domain_version="2",
610
+ rpc_url="https://rpc.mychain.com",
611
+ enabled=True,
612
+ )
613
+
614
+ register_network(custom_chain)
615
+
616
+ # Now you can use it
617
+ config = X402Config(
618
+ recipient_evm="0xYourWallet...",
619
+ supported_networks=["base", "mychain"],
620
+ )
621
+ ```
622
+
623
+ ---
624
+
625
+ ## Multi-Token Support
626
+
627
+ The SDK supports 6 stablecoins on EVM chains. Use the token helper functions to query and work with different tokens.
628
+
629
+ ### Querying Token Support
630
+
631
+ ```python
632
+ from uvd_x402_sdk import (
633
+ TokenType,
634
+ get_token_config,
635
+ get_supported_tokens,
636
+ is_token_supported,
637
+ get_networks_by_token,
638
+ )
639
+
640
+ # Check which tokens a network supports
641
+ tokens = get_supported_tokens("ethereum")
642
+ print(tokens) # ['usdc', 'eurc', 'ausd', 'pyusd', 'gho', 'crvusd']
643
+
644
+ tokens = get_supported_tokens("base")
645
+ print(tokens) # ['usdc', 'eurc', 'gho']
646
+
647
+ # Check if a specific token is supported
648
+ if is_token_supported("ethereum", "eurc"):
649
+ print("EURC is available on Ethereum!")
650
+
651
+ # Get token configuration
652
+ config = get_token_config("ethereum", "eurc")
653
+ if config:
654
+ print(f"EURC address: {config.address}")
655
+ print(f"Decimals: {config.decimals}")
656
+ print(f"EIP-712 name: {config.name}")
657
+ print(f"EIP-712 version: {config.version}")
658
+
659
+ # Find all networks that support a token
660
+ networks = get_networks_by_token("gho")
661
+ for network in networks:
662
+ print(f"GHO available on: {network.display_name}")
663
+ # Output: GHO available on: Ethereum, Base, Arbitrum One
664
+ ```
665
+
666
+ ### Token Configuration
667
+
668
+ Each token has specific EIP-712 domain parameters required for signing:
669
+
670
+ ```python
671
+ from uvd_x402_sdk import TokenConfig, get_token_config
672
+
673
+ # TokenConfig structure
674
+ # - address: Contract address
675
+ # - decimals: Token decimals (6 for most, 18 for GHO/crvUSD)
676
+ # - name: EIP-712 domain name (e.g., "USD Coin", "EURC", "Gho Token")
677
+ # - version: EIP-712 domain version
678
+
679
+ # Example: Get EURC config on Base
680
+ eurc = get_token_config("base", "eurc")
681
+ # TokenConfig(
682
+ # address="0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42",
683
+ # decimals=6,
684
+ # name="EURC",
685
+ # version="2"
686
+ # )
687
+
688
+ # Example: Get GHO config on Ethereum (note: 18 decimals)
689
+ gho = get_token_config("ethereum", "gho")
690
+ # TokenConfig(
691
+ # address="0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f",
692
+ # decimals=18,
693
+ # name="Gho Token",
694
+ # version="1"
695
+ # )
696
+ ```
697
+
698
+ ### Available Tokens
699
+
700
+ | Token | Description | Decimals | Issuer |
701
+ |-------|-------------|----------|--------|
702
+ | `usdc` | USD Coin | 6 | Circle |
703
+ | `eurc` | Euro Coin | 6 | Circle |
704
+ | `ausd` | Agora USD | 6 | Agora Finance |
705
+ | `pyusd` | PayPal USD | 6 | PayPal/Paxos |
706
+ | `gho` | GHO Stablecoin | 18 | Aave |
707
+ | `crvusd` | Curve USD | 18 | Curve Finance |
708
+
709
+ ---
710
+
711
+ ## Error Handling
712
+
713
+ ```python
714
+ from uvd_x402_sdk.exceptions import (
715
+ X402Error,
716
+ PaymentRequiredError,
717
+ PaymentVerificationError,
718
+ PaymentSettlementError,
719
+ UnsupportedNetworkError,
720
+ InvalidPayloadError,
721
+ FacilitatorError,
722
+ X402TimeoutError,
723
+ )
724
+
725
+ try:
726
+ result = client.process_payment(header, amount)
727
+ except PaymentVerificationError as e:
728
+ # Signature invalid, amount mismatch, expired, etc.
729
+ print(f"Verification failed: {e.reason}")
730
+ print(f"Errors: {e.errors}")
731
+ except PaymentSettlementError as e:
732
+ # On-chain settlement failed (insufficient balance, nonce used, etc.)
733
+ print(f"Settlement failed on {e.network}: {e.message}")
734
+ except UnsupportedNetworkError as e:
735
+ # Network not recognized or disabled
736
+ print(f"Network {e.network} not supported")
737
+ print(f"Supported: {e.supported_networks}")
738
+ except InvalidPayloadError as e:
739
+ # Malformed X-PAYMENT header
740
+ print(f"Invalid payload: {e.message}")
741
+ except FacilitatorError as e:
742
+ # Facilitator returned error
743
+ print(f"Facilitator error: {e.status_code} - {e.response_body}")
744
+ except X402TimeoutError as e:
745
+ # Request timed out
746
+ print(f"{e.operation} timed out after {e.timeout_seconds}s")
747
+ except X402Error as e:
748
+ # Catch-all for x402 errors
749
+ print(f"Payment error: {e.message}")
750
+ ```
751
+
752
+ ---
753
+
754
+ ## How x402 Works
755
+
756
+ The x402 protocol enables gasless stablecoin payments (USDC, EURC, AUSD, PYUSD, GHO, crvUSD):
757
+
758
+ ```
759
+ 1. User Request --> Client sends request without payment
760
+ 2. 402 Response <-- Server returns payment requirements
761
+ 3. User Signs --> Wallet signs authorization (NO GAS!)
762
+ 4. Frontend Sends --> X-PAYMENT header with signed payload
763
+ 5. SDK Verifies --> Validates signature with facilitator
764
+ 6. SDK Settles --> Facilitator executes on-chain transfer
765
+ 7. Success <-- Payment confirmed, request processed
766
+ ```
767
+
768
+ The facilitator (https://facilitator.ultravioletadao.xyz) handles all on-chain interactions and pays gas fees on behalf of users.
769
+
770
+ ### Payment Flow by Network Type
771
+
772
+ | Network Type | User Signs | Facilitator Does |
773
+ |--------------|-----------|------------------|
774
+ | EVM | EIP-712 message | Calls `transferWithAuthorization()` |
775
+ | SVM | Partial transaction | Co-signs + submits transaction |
776
+ | NEAR | DelegateAction (Borsh) | Wraps in `Action::Delegate` |
777
+ | Stellar | Auth entry (XDR) | Wraps in fee-bump transaction |
778
+
779
+ ---
780
+
781
+ ## Error Codes
782
+
783
+ | Exception | Description |
784
+ |-----------|-------------|
785
+ | `PaymentRequiredError` | No payment header provided |
786
+ | `PaymentVerificationError` | Signature invalid, amount mismatch, expired |
787
+ | `PaymentSettlementError` | On-chain settlement failed |
788
+ | `UnsupportedNetworkError` | Network not recognized or disabled |
789
+ | `InvalidPayloadError` | Malformed X-PAYMENT header |
790
+ | `FacilitatorError` | Facilitator service error |
791
+ | `ConfigurationError` | Invalid SDK configuration |
792
+ | `X402TimeoutError` | Request timed out |
793
+
794
+ ---
795
+
796
+ ## Security
797
+
798
+ - Users **NEVER** pay gas or submit transactions directly
799
+ - **EVM**: Users sign EIP-712 structured messages for any supported stablecoin (USDC, EURC, AUSD, PYUSD, GHO, crvUSD)
800
+ - **Solana/Fogo**: Users sign partial transactions (facilitator co-signs and submits)
801
+ - **Stellar**: Users sign Soroban authorization entries only
802
+ - **NEAR**: Users sign NEP-366 meta-transactions (DelegateAction)
803
+ - The facilitator submits and pays for all on-chain transactions
804
+ - All signatures include expiration timestamps (`validBefore`) for replay protection
805
+ - Nonces prevent double-spending of authorizations
806
+ - Each token has verified contract addresses and EIP-712 domain parameters
807
+
808
+ ---
809
+
810
+ ## Troubleshooting
811
+
812
+ ### Common Issues
813
+
814
+ **"Unsupported network"**
815
+ - Check that the network is in `supported_networks`
816
+ - Verify the network is enabled
817
+ - For v2, ensure CAIP-2 format is correct
818
+
819
+ **"Payment verification failed"**
820
+ - Amount mismatch between expected and signed
821
+ - Recipient address mismatch
822
+ - Authorization expired (`validBefore` in the past)
823
+ - Nonce already used (replay attack protection)
824
+
825
+ **"Settlement timed out"**
826
+ - Network congestion - increase `settle_timeout`
827
+ - Facilitator under load - retry after delay
828
+
829
+ **"Invalid payload"**
830
+ - Check base64 encoding of X-PAYMENT header
831
+ - Verify JSON structure matches expected format
832
+ - Ensure `x402Version` is 1 or 2
833
+
834
+ ### Debug Logging
835
+
836
+ ```python
837
+ import logging
838
+ logging.basicConfig(level=logging.DEBUG)
839
+ logging.getLogger("uvd_x402_sdk").setLevel(logging.DEBUG)
840
+ ```
841
+
842
+ ---
843
+
844
+ ## Development
845
+
846
+ ```bash
847
+ # Clone and install
848
+ git clone https://github.com/UltravioletaDAO/uvd-x402-sdk-python
849
+ cd uvd-x402-sdk-python
850
+ pip install -e ".[dev]"
851
+
852
+ # Run tests
853
+ pytest
854
+
855
+ # Format code
856
+ black src tests
857
+ ruff check src tests
858
+
859
+ # Type checking
860
+ mypy src
861
+ ```
862
+
863
+ ---
864
+
865
+ ## Links
866
+
867
+ - [x402 Protocol](https://x402.org)
868
+ - [Ultravioleta DAO](https://ultravioletadao.xyz)
869
+ - [402milly](https://402milly.xyz)
870
+ - [GitHub](https://github.com/UltravioletaDAO/uvd-x402-sdk-python)
871
+ - [PyPI](https://pypi.org/project/uvd-x402-sdk/)
872
+ - [TypeScript SDK](https://github.com/UltravioletaDAO/uvd-x402-sdk-typescript)
873
+
874
+ ---
875
+
876
+ ## License
877
+
878
+ MIT License - see LICENSE file.
879
+
880
+ ---
881
+
882
+ ## Changelog
883
+
884
+ ### v0.3.0 (2025-12-20)
885
+
886
+ - **Multi-Stablecoin Support**: Added support for 6 stablecoins on EVM chains
887
+ - USDC (all EVM chains)
888
+ - EURC (Ethereum, Base, Avalanche)
889
+ - AUSD (Ethereum, Arbitrum, Avalanche, Polygon, Monad)
890
+ - PYUSD (Ethereum)
891
+ - GHO (Ethereum, Base, Arbitrum)
892
+ - crvUSD (Ethereum, Arbitrum)
893
+ - Added `TokenType` literal type and `TokenConfig` dataclass
894
+ - Added token helper functions: `get_token_config()`, `get_supported_tokens()`, `is_token_supported()`, `get_networks_by_token()`
895
+ - Added `tokens` field to `NetworkConfig` for multi-token configurations
896
+ - Updated EVM network configurations with token contract addresses and EIP-712 domain parameters
897
+
898
+ ### v0.2.2 (2025-12-16)
899
+
900
+ - Added Security section to documentation
901
+ - Added Error Codes table
902
+ - Updated links to new GitHub repository
903
+ - Synced documentation with TypeScript SDK
904
+
905
+ ### v0.2.1 (2025-12-16)
906
+
907
+ - Removed BSC network (doesn't support ERC-3009)
908
+ - Added GitHub Actions workflow for PyPI publishing
909
+ - Updated to 14 supported networks
910
+
911
+ ### v0.2.0 (2025-12-15)
912
+
913
+ - Added **NEAR Protocol** support with NEP-366 meta-transactions
914
+ - Added **Fogo** SVM chain support
915
+ - Added **x402 v2** protocol support with CAIP-2 network identifiers
916
+ - Added `accepts` array for multi-network payment options
917
+ - Refactored Solana to generic SVM type (supports Solana, Fogo, future SVM chains)
918
+ - Added CAIP-2 parsing utilities (`parse_caip2_network`, `to_caip2_network`)
919
+ - Added `MultiPaymentConfig` for multi-network recipient configuration
920
+ - Added `Payment402BuilderV2` for v2 response construction
921
+
922
+ ### v0.1.0 (2025-12-01)
923
+
924
+ - Initial release
925
+ - EVM, Solana, Stellar network support
926
+ - Flask, FastAPI, Django, Lambda integrations
927
+ - Full Pydantic models