uvd-x402-sdk 0.2.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.
@@ -0,0 +1,776 @@
1
+ Metadata-Version: 2.1
2
+ Name: uvd-x402-sdk
3
+ Version: 0.2.0
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 **15 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
+ - **15 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
+ | BSC | EVM | 56 | `eip155:56` | Disabled* |
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
+ *BSC's USDC doesn't support ERC-3009 TransferWithAuthorization
98
+
99
+ ## Installation
100
+
101
+ ```bash
102
+ # Core SDK (minimal dependencies)
103
+ pip install uvd-x402-sdk
104
+
105
+ # With framework support
106
+ pip install uvd-x402-sdk[flask] # Flask integration
107
+ pip install uvd-x402-sdk[fastapi] # FastAPI/Starlette integration
108
+ pip install uvd-x402-sdk[django] # Django integration
109
+ pip install uvd-x402-sdk[aws] # AWS Lambda helpers
110
+
111
+ # All integrations
112
+ pip install uvd-x402-sdk[all]
113
+ ```
114
+
115
+ ---
116
+
117
+ ## Framework Examples
118
+
119
+ ### Flask
120
+
121
+ ```python
122
+ from decimal import Decimal
123
+ from flask import Flask, g, jsonify
124
+ from uvd_x402_sdk.integrations import FlaskX402
125
+
126
+ app = Flask(__name__)
127
+ x402 = FlaskX402(
128
+ app,
129
+ recipient_address="0xYourEVMWallet...",
130
+ recipient_solana="YourSolanaAddress...",
131
+ recipient_near="your-account.near",
132
+ recipient_stellar="G...YourStellarAddress",
133
+ )
134
+
135
+ @app.route("/api/premium")
136
+ @x402.require_payment(amount_usd=Decimal("5.00"))
137
+ def premium():
138
+ return jsonify({
139
+ "message": "Premium content!",
140
+ "payer": g.payment_result.payer_address,
141
+ "tx": g.payment_result.transaction_hash,
142
+ "network": g.payment_result.network,
143
+ })
144
+
145
+ @app.route("/api/basic")
146
+ @x402.require_payment(amount_usd=Decimal("0.10"))
147
+ def basic():
148
+ return jsonify({"data": "Basic tier data"})
149
+
150
+ if __name__ == "__main__":
151
+ app.run(debug=True)
152
+ ```
153
+
154
+ ### FastAPI
155
+
156
+ ```python
157
+ from decimal import Decimal
158
+ from fastapi import FastAPI, Depends
159
+ from uvd_x402_sdk.config import X402Config
160
+ from uvd_x402_sdk.models import PaymentResult
161
+ from uvd_x402_sdk.integrations import FastAPIX402
162
+
163
+ app = FastAPI()
164
+ x402 = FastAPIX402(
165
+ app,
166
+ recipient_address="0xYourEVMWallet...",
167
+ recipient_solana="YourSolanaAddress...",
168
+ recipient_near="your-account.near",
169
+ recipient_stellar="G...YourStellarAddress",
170
+ )
171
+
172
+ @app.get("/api/premium")
173
+ async def premium(
174
+ payment: PaymentResult = Depends(x402.require_payment(amount_usd="5.00"))
175
+ ):
176
+ return {
177
+ "message": "Premium content!",
178
+ "payer": payment.payer_address,
179
+ "network": payment.network,
180
+ }
181
+
182
+ @app.post("/api/generate")
183
+ async def generate(
184
+ body: dict,
185
+ payment: PaymentResult = Depends(x402.require_payment(amount_usd="1.00"))
186
+ ):
187
+ # Dynamic processing based on request
188
+ return {"result": "generated", "payer": payment.payer_address}
189
+ ```
190
+
191
+ ### Django
192
+
193
+ ```python
194
+ # settings.py
195
+ X402_FACILITATOR_URL = "https://facilitator.ultravioletadao.xyz"
196
+ X402_RECIPIENT_EVM = "0xYourEVMWallet..."
197
+ X402_RECIPIENT_SOLANA = "YourSolanaAddress..."
198
+ X402_RECIPIENT_NEAR = "your-account.near"
199
+ X402_RECIPIENT_STELLAR = "G...YourStellarAddress"
200
+ X402_PROTECTED_PATHS = {
201
+ "/api/premium/": "5.00",
202
+ "/api/basic/": "1.00",
203
+ }
204
+
205
+ MIDDLEWARE = [
206
+ # ...other middleware...
207
+ "uvd_x402_sdk.integrations.django_integration.DjangoX402Middleware",
208
+ ]
209
+
210
+ # views.py
211
+ from django.http import JsonResponse
212
+ from uvd_x402_sdk.integrations import django_x402_required
213
+
214
+ @django_x402_required(amount_usd="5.00")
215
+ def premium_view(request):
216
+ payment = request.payment_result
217
+ return JsonResponse({
218
+ "message": "Premium content!",
219
+ "payer": payment.payer_address,
220
+ })
221
+ ```
222
+
223
+ ### AWS Lambda
224
+
225
+ ```python
226
+ import json
227
+ from decimal import Decimal
228
+ from uvd_x402_sdk.config import X402Config
229
+ from uvd_x402_sdk.integrations import LambdaX402
230
+
231
+ config = X402Config(
232
+ recipient_evm="0xYourEVMWallet...",
233
+ recipient_solana="YourSolanaAddress...",
234
+ recipient_near="your-account.near",
235
+ recipient_stellar="G...YourStellarAddress",
236
+ )
237
+ x402 = LambdaX402(config=config)
238
+
239
+ def handler(event, context):
240
+ # Calculate price based on request
241
+ body = json.loads(event.get("body", "{}"))
242
+ quantity = body.get("quantity", 1)
243
+ price = Decimal(str(quantity * 0.01))
244
+
245
+ # Process payment or return 402
246
+ result = x402.process_or_require(event, price)
247
+
248
+ # If 402 response, return it
249
+ if isinstance(result, dict) and "statusCode" in result:
250
+ return result
251
+
252
+ # Payment verified!
253
+ return {
254
+ "statusCode": 200,
255
+ "headers": {"Content-Type": "application/json"},
256
+ "body": json.dumps({
257
+ "success": True,
258
+ "payer": result.payer_address,
259
+ "tx": result.transaction_hash,
260
+ "network": result.network,
261
+ "quantity": quantity,
262
+ })
263
+ }
264
+ ```
265
+
266
+ ---
267
+
268
+ ## Network-Specific Examples
269
+
270
+ ### EVM Chains (Base, Ethereum, Polygon, etc.)
271
+
272
+ EVM chains use ERC-3009 `TransferWithAuthorization` with EIP-712 signatures.
273
+
274
+ ```python
275
+ from uvd_x402_sdk import X402Client, X402Config
276
+
277
+ # Accept payments on Base and Ethereum only
278
+ config = X402Config(
279
+ recipient_evm="0xYourEVMWallet...",
280
+ supported_networks=["base", "ethereum"],
281
+ )
282
+
283
+ client = X402Client(config=config)
284
+ result = client.process_payment(x_payment_header, Decimal("10.00"))
285
+
286
+ # The payload contains EIP-712 signature + authorization
287
+ payload = client.extract_payload(x_payment_header)
288
+ evm_data = payload.get_evm_payload()
289
+ print(f"From: {evm_data.authorization.from_address}")
290
+ print(f"To: {evm_data.authorization.to}")
291
+ print(f"Value: {evm_data.authorization.value}")
292
+ ```
293
+
294
+ ### Solana & Fogo (SVM Chains)
295
+
296
+ SVM chains use partially-signed VersionedTransactions with SPL token transfers.
297
+
298
+ ```python
299
+ from uvd_x402_sdk import X402Client, X402Config
300
+
301
+ # Accept payments on Solana and Fogo
302
+ config = X402Config(
303
+ recipient_solana="YourSolanaAddress...",
304
+ supported_networks=["solana", "fogo"],
305
+ )
306
+
307
+ client = X402Client(config=config)
308
+ result = client.process_payment(x_payment_header, Decimal("5.00"))
309
+
310
+ # The payload contains a base64-encoded VersionedTransaction
311
+ payload = client.extract_payload(x_payment_header)
312
+ svm_data = payload.get_svm_payload()
313
+ print(f"Transaction: {svm_data.transaction[:50]}...")
314
+
315
+ # Fogo has ultra-fast finality (~400ms)
316
+ if result.network == "fogo":
317
+ print("Payment confirmed in ~400ms!")
318
+ ```
319
+
320
+ ### Stellar
321
+
322
+ Stellar uses Soroban Authorization Entries with fee-bump transactions.
323
+
324
+ ```python
325
+ from uvd_x402_sdk import X402Client, X402Config
326
+
327
+ config = X402Config(
328
+ recipient_stellar="G...YourStellarAddress",
329
+ supported_networks=["stellar"],
330
+ )
331
+
332
+ client = X402Client(config=config)
333
+ result = client.process_payment(x_payment_header, Decimal("1.00"))
334
+
335
+ # Stellar uses 7 decimals (stroops)
336
+ payload = client.extract_payload(x_payment_header)
337
+ stellar_data = payload.get_stellar_payload()
338
+ print(f"From: {stellar_data.from_address}")
339
+ print(f"Amount (stroops): {stellar_data.amount}")
340
+ print(f"Token Contract: {stellar_data.tokenContract}")
341
+ ```
342
+
343
+ ### NEAR Protocol
344
+
345
+ NEAR uses NEP-366 meta-transactions with Borsh serialization.
346
+
347
+ ```python
348
+ from uvd_x402_sdk import X402Client, X402Config
349
+
350
+ config = X402Config(
351
+ recipient_near="your-recipient.near",
352
+ supported_networks=["near"],
353
+ )
354
+
355
+ client = X402Client(config=config)
356
+ result = client.process_payment(x_payment_header, Decimal("2.00"))
357
+
358
+ # NEAR payload contains a SignedDelegateAction
359
+ payload = client.extract_payload(x_payment_header)
360
+ near_data = payload.get_near_payload()
361
+ print(f"SignedDelegateAction: {near_data.signedDelegateAction[:50]}...")
362
+
363
+ # Validate NEAR payload structure
364
+ from uvd_x402_sdk.networks.near import validate_near_payload
365
+ validate_near_payload(payload.payload) # Raises ValueError if invalid
366
+ ```
367
+
368
+ ---
369
+
370
+ ## x402 v1 vs v2
371
+
372
+ The SDK supports both x402 protocol versions with automatic detection.
373
+
374
+ ### Version Differences
375
+
376
+ | Aspect | v1 | v2 |
377
+ |--------|----|----|
378
+ | Network ID | String (`"base"`) | CAIP-2 (`"eip155:8453"`) |
379
+ | Payment delivery | JSON body | `PAYMENT-REQUIRED` header |
380
+ | Multiple options | Limited | `accepts` array |
381
+ | Discovery | Implicit | Optional extension |
382
+
383
+ ### Auto-Detection
384
+
385
+ ```python
386
+ from uvd_x402_sdk import PaymentPayload
387
+
388
+ # The SDK auto-detects based on network format
389
+ payload = PaymentPayload(
390
+ x402Version=1,
391
+ scheme="exact",
392
+ network="base", # v1 format
393
+ payload={"signature": "...", "authorization": {...}}
394
+ )
395
+
396
+ print(payload.is_v2()) # False
397
+
398
+ payload_v2 = PaymentPayload(
399
+ x402Version=2,
400
+ scheme="exact",
401
+ network="eip155:8453", # v2 CAIP-2 format
402
+ payload={"signature": "...", "authorization": {...}}
403
+ )
404
+
405
+ print(payload_v2.is_v2()) # True
406
+
407
+ # Both work the same way
408
+ print(payload.get_normalized_network()) # "base"
409
+ print(payload_v2.get_normalized_network()) # "base"
410
+ ```
411
+
412
+ ### Creating v2 Responses
413
+
414
+ ```python
415
+ from uvd_x402_sdk import X402Config, create_402_response_v2, Payment402BuilderV2
416
+
417
+ config = X402Config(
418
+ recipient_evm="0xYourEVM...",
419
+ recipient_solana="YourSolana...",
420
+ recipient_near="your.near",
421
+ recipient_stellar="G...Stellar",
422
+ )
423
+
424
+ # Simple v2 response
425
+ response = create_402_response_v2(
426
+ amount_usd=Decimal("5.00"),
427
+ config=config,
428
+ resource="/api/premium",
429
+ description="Premium API access",
430
+ )
431
+ # Returns:
432
+ # {
433
+ # "x402Version": 2,
434
+ # "scheme": "exact",
435
+ # "resource": "/api/premium",
436
+ # "accepts": [
437
+ # {"network": "eip155:8453", "asset": "0x833...", "amount": "5000000", "payTo": "0xYour..."},
438
+ # {"network": "solana:5eykt...", "asset": "EPjF...", "amount": "5000000", "payTo": "Your..."},
439
+ # {"network": "near:mainnet", "asset": "1720...", "amount": "5000000", "payTo": "your.near"},
440
+ # ...
441
+ # ]
442
+ # }
443
+
444
+ # Builder pattern for more control
445
+ response = (
446
+ Payment402BuilderV2(config)
447
+ .amount(Decimal("10.00"))
448
+ .resource("/api/generate")
449
+ .description("AI generation credits")
450
+ .networks(["base", "solana", "near"]) # Limit to specific networks
451
+ .build()
452
+ )
453
+ ```
454
+
455
+ ---
456
+
457
+ ## Payload Validation
458
+
459
+ Each network type has specific payload validation:
460
+
461
+ ### EVM Validation
462
+
463
+ ```python
464
+ from uvd_x402_sdk.models import EVMPayloadContent, EVMAuthorization
465
+
466
+ # Parse and validate EVM payload
467
+ payload = client.extract_payload(x_payment_header)
468
+ evm_data = payload.get_evm_payload()
469
+
470
+ # Validate authorization fields
471
+ auth = evm_data.authorization
472
+ assert auth.from_address.startswith("0x")
473
+ assert auth.to.startswith("0x")
474
+ assert int(auth.value) > 0
475
+ assert int(auth.validBefore) > int(auth.validAfter)
476
+ ```
477
+
478
+ ### SVM Validation
479
+
480
+ ```python
481
+ from uvd_x402_sdk.networks.solana import validate_svm_payload, is_valid_solana_address
482
+
483
+ # Validate SVM payload
484
+ payload = client.extract_payload(x_payment_header)
485
+ validate_svm_payload(payload.payload) # Raises ValueError if invalid
486
+
487
+ # Validate Solana addresses
488
+ assert is_valid_solana_address("YourSolanaAddress...")
489
+ ```
490
+
491
+ ### NEAR Validation
492
+
493
+ ```python
494
+ from uvd_x402_sdk.networks.near import (
495
+ validate_near_payload,
496
+ is_valid_near_account_id,
497
+ BorshSerializer,
498
+ )
499
+
500
+ # Validate NEAR payload
501
+ payload = client.extract_payload(x_payment_header)
502
+ validate_near_payload(payload.payload) # Raises ValueError if invalid
503
+
504
+ # Validate NEAR account IDs
505
+ assert is_valid_near_account_id("your-account.near")
506
+ assert is_valid_near_account_id("0xultravioleta.near")
507
+ ```
508
+
509
+ ### Stellar Validation
510
+
511
+ ```python
512
+ from uvd_x402_sdk.networks.stellar import (
513
+ is_valid_stellar_address,
514
+ is_valid_contract_address,
515
+ stroops_to_usd,
516
+ )
517
+
518
+ # Validate Stellar addresses
519
+ assert is_valid_stellar_address("G...YourStellarAddress") # G...
520
+ assert is_valid_contract_address("C...USDCContract") # C...
521
+
522
+ # Convert stroops to USD (7 decimals)
523
+ usd = stroops_to_usd(50000000) # Returns 5.0
524
+ ```
525
+
526
+ ---
527
+
528
+ ## Configuration
529
+
530
+ ### Environment Variables
531
+
532
+ ```bash
533
+ # Core configuration
534
+ X402_FACILITATOR_URL=https://facilitator.ultravioletadao.xyz
535
+ X402_VERIFY_TIMEOUT=30
536
+ X402_SETTLE_TIMEOUT=55
537
+
538
+ # Recipient addresses (at least one required)
539
+ X402_RECIPIENT_EVM=0xYourEVMWallet
540
+ X402_RECIPIENT_SOLANA=YourSolanaAddress
541
+ X402_RECIPIENT_NEAR=your-account.near
542
+ X402_RECIPIENT_STELLAR=G...YourStellarAddress
543
+
544
+ # Optional
545
+ X402_FACILITATOR_SOLANA=F742C4VfFLQ9zRQyithoj5229ZgtX2WqKCSFKgH2EThq
546
+ X402_RESOURCE_URL=https://api.example.com
547
+ X402_DESCRIPTION=API access payment
548
+ ```
549
+
550
+ ### Programmatic Configuration
551
+
552
+ ```python
553
+ from uvd_x402_sdk import X402Config, MultiPaymentConfig
554
+
555
+ # Full configuration
556
+ config = X402Config(
557
+ facilitator_url="https://facilitator.ultravioletadao.xyz",
558
+
559
+ # Recipients
560
+ recipient_evm="0xYourEVMWallet",
561
+ recipient_solana="YourSolanaAddress",
562
+ recipient_near="your-account.near",
563
+ recipient_stellar="G...YourStellarAddress",
564
+
565
+ # Timeouts
566
+ verify_timeout=30.0,
567
+ settle_timeout=55.0,
568
+
569
+ # Limit to specific networks
570
+ supported_networks=["base", "solana", "near", "stellar"],
571
+
572
+ # Metadata
573
+ resource_url="https://api.example.com/premium",
574
+ description="Premium API access",
575
+
576
+ # Protocol version (1, 2, or "auto")
577
+ x402_version="auto",
578
+ )
579
+
580
+ # From environment
581
+ config = X402Config.from_env()
582
+ ```
583
+
584
+ ---
585
+
586
+ ## Registering Custom Networks
587
+
588
+ ```python
589
+ from uvd_x402_sdk.networks import NetworkConfig, NetworkType, register_network
590
+
591
+ # Register a custom EVM network
592
+ custom_chain = NetworkConfig(
593
+ name="mychain",
594
+ display_name="My Custom Chain",
595
+ network_type=NetworkType.EVM,
596
+ chain_id=12345,
597
+ usdc_address="0xUSDCContractAddress",
598
+ usdc_decimals=6,
599
+ usdc_domain_name="USD Coin", # Check actual EIP-712 domain!
600
+ usdc_domain_version="2",
601
+ rpc_url="https://rpc.mychain.com",
602
+ enabled=True,
603
+ )
604
+
605
+ register_network(custom_chain)
606
+
607
+ # Now you can use it
608
+ config = X402Config(
609
+ recipient_evm="0xYourWallet...",
610
+ supported_networks=["base", "mychain"],
611
+ )
612
+ ```
613
+
614
+ ---
615
+
616
+ ## Error Handling
617
+
618
+ ```python
619
+ from uvd_x402_sdk.exceptions import (
620
+ X402Error,
621
+ PaymentRequiredError,
622
+ PaymentVerificationError,
623
+ PaymentSettlementError,
624
+ UnsupportedNetworkError,
625
+ InvalidPayloadError,
626
+ FacilitatorError,
627
+ X402TimeoutError,
628
+ )
629
+
630
+ try:
631
+ result = client.process_payment(header, amount)
632
+ except PaymentVerificationError as e:
633
+ # Signature invalid, amount mismatch, expired, etc.
634
+ print(f"Verification failed: {e.reason}")
635
+ print(f"Errors: {e.errors}")
636
+ except PaymentSettlementError as e:
637
+ # On-chain settlement failed (insufficient balance, nonce used, etc.)
638
+ print(f"Settlement failed on {e.network}: {e.message}")
639
+ except UnsupportedNetworkError as e:
640
+ # Network not recognized or disabled
641
+ print(f"Network {e.network} not supported")
642
+ print(f"Supported: {e.supported_networks}")
643
+ except InvalidPayloadError as e:
644
+ # Malformed X-PAYMENT header
645
+ print(f"Invalid payload: {e.message}")
646
+ except FacilitatorError as e:
647
+ # Facilitator returned error
648
+ print(f"Facilitator error: {e.status_code} - {e.response_body}")
649
+ except X402TimeoutError as e:
650
+ # Request timed out
651
+ print(f"{e.operation} timed out after {e.timeout_seconds}s")
652
+ except X402Error as e:
653
+ # Catch-all for x402 errors
654
+ print(f"Payment error: {e.message}")
655
+ ```
656
+
657
+ ---
658
+
659
+ ## How x402 Works
660
+
661
+ The x402 protocol enables gasless USDC payments:
662
+
663
+ ```
664
+ 1. User Request --> Client sends request without payment
665
+ 2. 402 Response <-- Server returns payment requirements
666
+ 3. User Signs --> Wallet signs authorization (NO GAS!)
667
+ 4. Frontend Sends --> X-PAYMENT header with signed payload
668
+ 5. SDK Verifies --> Validates signature with facilitator
669
+ 6. SDK Settles --> Facilitator executes on-chain transfer
670
+ 7. Success <-- Payment confirmed, request processed
671
+ ```
672
+
673
+ The facilitator (https://facilitator.ultravioletadao.xyz) handles all on-chain interactions and pays gas fees on behalf of users.
674
+
675
+ ### Payment Flow by Network Type
676
+
677
+ | Network Type | User Signs | Facilitator Does |
678
+ |--------------|-----------|------------------|
679
+ | EVM | EIP-712 message | Calls `transferWithAuthorization()` |
680
+ | SVM | Partial transaction | Co-signs + submits transaction |
681
+ | NEAR | DelegateAction (Borsh) | Wraps in `Action::Delegate` |
682
+ | Stellar | Auth entry (XDR) | Wraps in fee-bump transaction |
683
+
684
+ ---
685
+
686
+ ## Troubleshooting
687
+
688
+ ### Common Issues
689
+
690
+ **"Unsupported network"**
691
+ - Check that the network is in `supported_networks`
692
+ - Verify the network is enabled (BSC is disabled by default)
693
+ - For v2, ensure CAIP-2 format is correct
694
+
695
+ **"Payment verification failed"**
696
+ - Amount mismatch between expected and signed
697
+ - Recipient address mismatch
698
+ - Authorization expired (`validBefore` in the past)
699
+ - Nonce already used (replay attack protection)
700
+
701
+ **"Settlement timed out"**
702
+ - Network congestion - increase `settle_timeout`
703
+ - Facilitator under load - retry after delay
704
+
705
+ **"Invalid payload"**
706
+ - Check base64 encoding of X-PAYMENT header
707
+ - Verify JSON structure matches expected format
708
+ - Ensure `x402Version` is 1 or 2
709
+
710
+ ### Debug Logging
711
+
712
+ ```python
713
+ import logging
714
+ logging.basicConfig(level=logging.DEBUG)
715
+ logging.getLogger("uvd_x402_sdk").setLevel(logging.DEBUG)
716
+ ```
717
+
718
+ ---
719
+
720
+ ## Development
721
+
722
+ ```bash
723
+ # Clone and install
724
+ git clone https://github.com/ultravioletadao/uvd-x402-sdk
725
+ cd uvd-x402-sdk/sdk/python
726
+ pip install -e ".[dev]"
727
+
728
+ # Run tests
729
+ pytest
730
+
731
+ # Format code
732
+ black src tests
733
+ ruff check src tests
734
+
735
+ # Type checking
736
+ mypy src
737
+ ```
738
+
739
+ ---
740
+
741
+ ## Links
742
+
743
+ - [Ultravioleta DAO](https://ultravioletadao.xyz)
744
+ - [402milly Pixel Marketplace](https://402milly.xyz)
745
+ - [x402 Protocol Documentation](https://docs.ultravioletadao.xyz/x402)
746
+ - [Facilitator Status](https://facilitator.ultravioletadao.xyz/health)
747
+ - [GitHub Issues](https://github.com/ultravioletadao/uvd-x402-sdk/issues)
748
+
749
+ ---
750
+
751
+ ## License
752
+
753
+ MIT License - see LICENSE file.
754
+
755
+ ---
756
+
757
+ ## Changelog
758
+
759
+ ### v0.2.0 (2025-12-15)
760
+
761
+ - Added **NEAR Protocol** support with NEP-366 meta-transactions
762
+ - Added **Fogo** SVM chain support
763
+ - Added **x402 v2** protocol support with CAIP-2 network identifiers
764
+ - Added `accepts` array for multi-network payment options
765
+ - Refactored Solana to generic SVM type (supports Solana, Fogo, future SVM chains)
766
+ - Added CAIP-2 parsing utilities (`parse_caip2_network`, `to_caip2_network`)
767
+ - Added `MultiPaymentConfig` for multi-network recipient configuration
768
+ - Added `Payment402BuilderV2` for v2 response construction
769
+ - Updated to 15 supported networks (14 enabled)
770
+
771
+ ### v0.1.0 (2025-12-01)
772
+
773
+ - Initial release
774
+ - 14 network support (EVM, Solana, Stellar)
775
+ - Flask, FastAPI, Django, Lambda integrations
776
+ - Full Pydantic models