uvd-x402-sdk 0.2.1__py3-none-any.whl → 0.2.3__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,814 @@
1
- Metadata-Version: 2.1
2
- Name: uvd-x402-sdk
3
- Version: 0.2.1
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.2.3
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
+ ## Error Codes
684
+
685
+ | Exception | Description |
686
+ |-----------|-------------|
687
+ | `PaymentRequiredError` | No payment header provided |
688
+ | `PaymentVerificationError` | Signature invalid, amount mismatch, expired |
689
+ | `PaymentSettlementError` | On-chain settlement failed |
690
+ | `UnsupportedNetworkError` | Network not recognized or disabled |
691
+ | `InvalidPayloadError` | Malformed X-PAYMENT header |
692
+ | `FacilitatorError` | Facilitator service error |
693
+ | `ConfigurationError` | Invalid SDK configuration |
694
+ | `X402TimeoutError` | Request timed out |
695
+
696
+ ---
697
+
698
+ ## Security
699
+
700
+ - Users **NEVER** pay gas or submit transactions directly
701
+ - **EVM**: Users sign EIP-712 structured messages only (no transaction broadcast)
702
+ - **Solana/Fogo**: Users sign partial transactions (facilitator co-signs and submits)
703
+ - **Stellar**: Users sign Soroban authorization entries only
704
+ - **NEAR**: Users sign NEP-366 meta-transactions (DelegateAction)
705
+ - The facilitator submits and pays for all on-chain transactions
706
+ - All signatures include expiration timestamps (`validBefore`) for replay protection
707
+ - Nonces prevent double-spending of authorizations
708
+
709
+ ---
710
+
711
+ ## Troubleshooting
712
+
713
+ ### Common Issues
714
+
715
+ **"Unsupported network"**
716
+ - Check that the network is in `supported_networks`
717
+ - Verify the network is enabled
718
+ - For v2, ensure CAIP-2 format is correct
719
+
720
+ **"Payment verification failed"**
721
+ - Amount mismatch between expected and signed
722
+ - Recipient address mismatch
723
+ - Authorization expired (`validBefore` in the past)
724
+ - Nonce already used (replay attack protection)
725
+
726
+ **"Settlement timed out"**
727
+ - Network congestion - increase `settle_timeout`
728
+ - Facilitator under load - retry after delay
729
+
730
+ **"Invalid payload"**
731
+ - Check base64 encoding of X-PAYMENT header
732
+ - Verify JSON structure matches expected format
733
+ - Ensure `x402Version` is 1 or 2
734
+
735
+ ### Debug Logging
736
+
737
+ ```python
738
+ import logging
739
+ logging.basicConfig(level=logging.DEBUG)
740
+ logging.getLogger("uvd_x402_sdk").setLevel(logging.DEBUG)
741
+ ```
742
+
743
+ ---
744
+
745
+ ## Development
746
+
747
+ ```bash
748
+ # Clone and install
749
+ git clone https://github.com/UltravioletaDAO/uvd-x402-sdk-python
750
+ cd uvd-x402-sdk-python
751
+ pip install -e ".[dev]"
752
+
753
+ # Run tests
754
+ pytest
755
+
756
+ # Format code
757
+ black src tests
758
+ ruff check src tests
759
+
760
+ # Type checking
761
+ mypy src
762
+ ```
763
+
764
+ ---
765
+
766
+ ## Links
767
+
768
+ - [x402 Protocol](https://x402.org)
769
+ - [Ultravioleta DAO](https://ultravioletadao.xyz)
770
+ - [402milly](https://402milly.xyz)
771
+ - [GitHub](https://github.com/UltravioletaDAO/uvd-x402-sdk-python)
772
+ - [PyPI](https://pypi.org/project/uvd-x402-sdk/)
773
+ - [TypeScript SDK](https://github.com/UltravioletaDAO/uvd-x402-sdk-typescript)
774
+
775
+ ---
776
+
777
+ ## License
778
+
779
+ MIT License - see LICENSE file.
780
+
781
+ ---
782
+
783
+ ## Changelog
784
+
785
+ ### v0.2.2 (2025-12-16)
786
+
787
+ - Added Security section to documentation
788
+ - Added Error Codes table
789
+ - Updated links to new GitHub repository
790
+ - Synced documentation with TypeScript SDK
791
+
792
+ ### v0.2.1 (2025-12-16)
793
+
794
+ - Removed BSC network (doesn't support ERC-3009)
795
+ - Added GitHub Actions workflow for PyPI publishing
796
+ - Updated to 14 supported networks
797
+
798
+ ### v0.2.0 (2025-12-15)
799
+
800
+ - Added **NEAR Protocol** support with NEP-366 meta-transactions
801
+ - Added **Fogo** SVM chain support
802
+ - Added **x402 v2** protocol support with CAIP-2 network identifiers
803
+ - Added `accepts` array for multi-network payment options
804
+ - Refactored Solana to generic SVM type (supports Solana, Fogo, future SVM chains)
805
+ - Added CAIP-2 parsing utilities (`parse_caip2_network`, `to_caip2_network`)
806
+ - Added `MultiPaymentConfig` for multi-network recipient configuration
807
+ - Added `Payment402BuilderV2` for v2 response construction
808
+
809
+ ### v0.1.0 (2025-12-01)
810
+
811
+ - Initial release
812
+ - EVM, Solana, Stellar network support
813
+ - Flask, FastAPI, Django, Lambda integrations
814
+ - Full Pydantic models