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,254 +1,254 @@
1
- """
2
- Custom exceptions for the x402 SDK.
3
-
4
- These exceptions provide clear, actionable error messages for different
5
- failure scenarios in the payment flow.
6
- """
7
-
8
- from typing import Optional, List, Dict, Any
9
-
10
-
11
- class X402Error(Exception):
12
- """Base exception for all x402 SDK errors."""
13
-
14
- def __init__(
15
- self,
16
- message: str,
17
- code: Optional[str] = None,
18
- details: Optional[Dict[str, Any]] = None,
19
- ) -> None:
20
- self.message = message
21
- self.code = code or "X402_ERROR"
22
- self.details = details or {}
23
- super().__init__(self.message)
24
-
25
- def to_dict(self) -> Dict[str, Any]:
26
- """Convert exception to dictionary for API responses."""
27
- return {
28
- "error": self.code,
29
- "message": self.message,
30
- "details": self.details,
31
- }
32
-
33
-
34
- class PaymentRequiredError(X402Error):
35
- """
36
- Raised when a payment is required but not provided.
37
-
38
- This should trigger a 402 Payment Required response.
39
- """
40
-
41
- def __init__(
42
- self,
43
- message: str = "Payment required",
44
- amount_usd: Optional[str] = None,
45
- recipient: Optional[str] = None,
46
- supported_networks: Optional[List[str]] = None,
47
- ) -> None:
48
- details = {}
49
- if amount_usd:
50
- details["amount"] = amount_usd
51
- if recipient:
52
- details["recipient"] = recipient
53
- if supported_networks:
54
- details["supportedNetworks"] = supported_networks
55
-
56
- super().__init__(
57
- message=message,
58
- code="PAYMENT_REQUIRED",
59
- details=details,
60
- )
61
- self.amount_usd = amount_usd
62
- self.recipient = recipient
63
- self.supported_networks = supported_networks
64
-
65
-
66
- class PaymentVerificationError(X402Error):
67
- """
68
- Raised when payment verification fails.
69
-
70
- Common causes:
71
- - Invalid signature
72
- - Amount mismatch
73
- - Wrong recipient
74
- - Expired payment authorization
75
- """
76
-
77
- def __init__(
78
- self,
79
- message: str,
80
- reason: Optional[str] = None,
81
- errors: Optional[List[str]] = None,
82
- ) -> None:
83
- details = {}
84
- if reason:
85
- details["reason"] = reason
86
- if errors:
87
- details["errors"] = errors
88
-
89
- super().__init__(
90
- message=message,
91
- code="PAYMENT_VERIFICATION_FAILED",
92
- details=details,
93
- )
94
- self.reason = reason
95
- self.errors = errors or []
96
-
97
-
98
- class PaymentSettlementError(X402Error):
99
- """
100
- Raised when payment settlement fails on-chain.
101
-
102
- Common causes:
103
- - Insufficient USDC balance
104
- - Nonce already used
105
- - Authorization expired
106
- - Network congestion/timeout
107
- """
108
-
109
- def __init__(
110
- self,
111
- message: str,
112
- network: Optional[str] = None,
113
- tx_hash: Optional[str] = None,
114
- reason: Optional[str] = None,
115
- ) -> None:
116
- details = {}
117
- if network:
118
- details["network"] = network
119
- if tx_hash:
120
- details["transactionHash"] = tx_hash
121
- if reason:
122
- details["reason"] = reason
123
-
124
- super().__init__(
125
- message=message,
126
- code="PAYMENT_SETTLEMENT_FAILED",
127
- details=details,
128
- )
129
- self.network = network
130
- self.tx_hash = tx_hash
131
- self.reason = reason
132
-
133
-
134
- class UnsupportedNetworkError(X402Error):
135
- """
136
- Raised when an unsupported network is specified.
137
-
138
- Use `register_network()` to add custom network support.
139
- """
140
-
141
- def __init__(
142
- self,
143
- network: str,
144
- supported_networks: Optional[List[str]] = None,
145
- ) -> None:
146
- super().__init__(
147
- message=f"Unsupported network: {network}",
148
- code="UNSUPPORTED_NETWORK",
149
- details={
150
- "requestedNetwork": network,
151
- "supportedNetworks": supported_networks or [],
152
- },
153
- )
154
- self.network = network
155
- self.supported_networks = supported_networks or []
156
-
157
-
158
- class InvalidPayloadError(X402Error):
159
- """
160
- Raised when the X-PAYMENT header payload is invalid.
161
-
162
- Common causes:
163
- - Invalid base64 encoding
164
- - Invalid JSON format
165
- - Missing required fields
166
- - Invalid x402 version
167
- """
168
-
169
- def __init__(
170
- self,
171
- message: str,
172
- field: Optional[str] = None,
173
- expected: Optional[str] = None,
174
- received: Optional[str] = None,
175
- ) -> None:
176
- details = {}
177
- if field:
178
- details["field"] = field
179
- if expected:
180
- details["expected"] = expected
181
- if received:
182
- details["received"] = received
183
-
184
- super().__init__(
185
- message=message,
186
- code="INVALID_PAYLOAD",
187
- details=details,
188
- )
189
- self.field = field
190
- self.expected = expected
191
- self.received = received
192
-
193
-
194
- class ConfigurationError(X402Error):
195
- """
196
- Raised when SDK configuration is invalid or missing.
197
- """
198
-
199
- def __init__(self, message: str, config_key: Optional[str] = None) -> None:
200
- super().__init__(
201
- message=message,
202
- code="CONFIGURATION_ERROR",
203
- details={"configKey": config_key} if config_key else {},
204
- )
205
- self.config_key = config_key
206
-
207
-
208
- class FacilitatorError(X402Error):
209
- """
210
- Raised when the facilitator returns an error.
211
-
212
- Contains the raw error response from the facilitator for debugging.
213
- """
214
-
215
- def __init__(
216
- self,
217
- message: str,
218
- status_code: Optional[int] = None,
219
- response_body: Optional[str] = None,
220
- ) -> None:
221
- super().__init__(
222
- message=message,
223
- code="FACILITATOR_ERROR",
224
- details={
225
- "statusCode": status_code,
226
- "response": response_body,
227
- },
228
- )
229
- self.status_code = status_code
230
- self.response_body = response_body
231
-
232
-
233
- class TimeoutError(X402Error):
234
- """
235
- Raised when a facilitator request times out.
236
-
237
- Settlement operations can take up to 55 seconds on congested networks.
238
- """
239
-
240
- def __init__(
241
- self,
242
- operation: str,
243
- timeout_seconds: float,
244
- ) -> None:
245
- super().__init__(
246
- message=f"{operation} timed out after {timeout_seconds}s",
247
- code="TIMEOUT",
248
- details={
249
- "operation": operation,
250
- "timeoutSeconds": timeout_seconds,
251
- },
252
- )
253
- self.operation = operation
254
- self.timeout_seconds = timeout_seconds
1
+ """
2
+ Custom exceptions for the x402 SDK.
3
+
4
+ These exceptions provide clear, actionable error messages for different
5
+ failure scenarios in the payment flow.
6
+ """
7
+
8
+ from typing import Optional, List, Dict, Any
9
+
10
+
11
+ class X402Error(Exception):
12
+ """Base exception for all x402 SDK errors."""
13
+
14
+ def __init__(
15
+ self,
16
+ message: str,
17
+ code: Optional[str] = None,
18
+ details: Optional[Dict[str, Any]] = None,
19
+ ) -> None:
20
+ self.message = message
21
+ self.code = code or "X402_ERROR"
22
+ self.details = details or {}
23
+ super().__init__(self.message)
24
+
25
+ def to_dict(self) -> Dict[str, Any]:
26
+ """Convert exception to dictionary for API responses."""
27
+ return {
28
+ "error": self.code,
29
+ "message": self.message,
30
+ "details": self.details,
31
+ }
32
+
33
+
34
+ class PaymentRequiredError(X402Error):
35
+ """
36
+ Raised when a payment is required but not provided.
37
+
38
+ This should trigger a 402 Payment Required response.
39
+ """
40
+
41
+ def __init__(
42
+ self,
43
+ message: str = "Payment required",
44
+ amount_usd: Optional[str] = None,
45
+ recipient: Optional[str] = None,
46
+ supported_networks: Optional[List[str]] = None,
47
+ ) -> None:
48
+ details = {}
49
+ if amount_usd:
50
+ details["amount"] = amount_usd
51
+ if recipient:
52
+ details["recipient"] = recipient
53
+ if supported_networks:
54
+ details["supportedNetworks"] = supported_networks
55
+
56
+ super().__init__(
57
+ message=message,
58
+ code="PAYMENT_REQUIRED",
59
+ details=details,
60
+ )
61
+ self.amount_usd = amount_usd
62
+ self.recipient = recipient
63
+ self.supported_networks = supported_networks
64
+
65
+
66
+ class PaymentVerificationError(X402Error):
67
+ """
68
+ Raised when payment verification fails.
69
+
70
+ Common causes:
71
+ - Invalid signature
72
+ - Amount mismatch
73
+ - Wrong recipient
74
+ - Expired payment authorization
75
+ """
76
+
77
+ def __init__(
78
+ self,
79
+ message: str,
80
+ reason: Optional[str] = None,
81
+ errors: Optional[List[str]] = None,
82
+ ) -> None:
83
+ details = {}
84
+ if reason:
85
+ details["reason"] = reason
86
+ if errors:
87
+ details["errors"] = errors
88
+
89
+ super().__init__(
90
+ message=message,
91
+ code="PAYMENT_VERIFICATION_FAILED",
92
+ details=details,
93
+ )
94
+ self.reason = reason
95
+ self.errors = errors or []
96
+
97
+
98
+ class PaymentSettlementError(X402Error):
99
+ """
100
+ Raised when payment settlement fails on-chain.
101
+
102
+ Common causes:
103
+ - Insufficient USDC balance
104
+ - Nonce already used
105
+ - Authorization expired
106
+ - Network congestion/timeout
107
+ """
108
+
109
+ def __init__(
110
+ self,
111
+ message: str,
112
+ network: Optional[str] = None,
113
+ tx_hash: Optional[str] = None,
114
+ reason: Optional[str] = None,
115
+ ) -> None:
116
+ details = {}
117
+ if network:
118
+ details["network"] = network
119
+ if tx_hash:
120
+ details["transactionHash"] = tx_hash
121
+ if reason:
122
+ details["reason"] = reason
123
+
124
+ super().__init__(
125
+ message=message,
126
+ code="PAYMENT_SETTLEMENT_FAILED",
127
+ details=details,
128
+ )
129
+ self.network = network
130
+ self.tx_hash = tx_hash
131
+ self.reason = reason
132
+
133
+
134
+ class UnsupportedNetworkError(X402Error):
135
+ """
136
+ Raised when an unsupported network is specified.
137
+
138
+ Use `register_network()` to add custom network support.
139
+ """
140
+
141
+ def __init__(
142
+ self,
143
+ network: str,
144
+ supported_networks: Optional[List[str]] = None,
145
+ ) -> None:
146
+ super().__init__(
147
+ message=f"Unsupported network: {network}",
148
+ code="UNSUPPORTED_NETWORK",
149
+ details={
150
+ "requestedNetwork": network,
151
+ "supportedNetworks": supported_networks or [],
152
+ },
153
+ )
154
+ self.network = network
155
+ self.supported_networks = supported_networks or []
156
+
157
+
158
+ class InvalidPayloadError(X402Error):
159
+ """
160
+ Raised when the X-PAYMENT header payload is invalid.
161
+
162
+ Common causes:
163
+ - Invalid base64 encoding
164
+ - Invalid JSON format
165
+ - Missing required fields
166
+ - Invalid x402 version
167
+ """
168
+
169
+ def __init__(
170
+ self,
171
+ message: str,
172
+ field: Optional[str] = None,
173
+ expected: Optional[str] = None,
174
+ received: Optional[str] = None,
175
+ ) -> None:
176
+ details = {}
177
+ if field:
178
+ details["field"] = field
179
+ if expected:
180
+ details["expected"] = expected
181
+ if received:
182
+ details["received"] = received
183
+
184
+ super().__init__(
185
+ message=message,
186
+ code="INVALID_PAYLOAD",
187
+ details=details,
188
+ )
189
+ self.field = field
190
+ self.expected = expected
191
+ self.received = received
192
+
193
+
194
+ class ConfigurationError(X402Error):
195
+ """
196
+ Raised when SDK configuration is invalid or missing.
197
+ """
198
+
199
+ def __init__(self, message: str, config_key: Optional[str] = None) -> None:
200
+ super().__init__(
201
+ message=message,
202
+ code="CONFIGURATION_ERROR",
203
+ details={"configKey": config_key} if config_key else {},
204
+ )
205
+ self.config_key = config_key
206
+
207
+
208
+ class FacilitatorError(X402Error):
209
+ """
210
+ Raised when the facilitator returns an error.
211
+
212
+ Contains the raw error response from the facilitator for debugging.
213
+ """
214
+
215
+ def __init__(
216
+ self,
217
+ message: str,
218
+ status_code: Optional[int] = None,
219
+ response_body: Optional[str] = None,
220
+ ) -> None:
221
+ super().__init__(
222
+ message=message,
223
+ code="FACILITATOR_ERROR",
224
+ details={
225
+ "statusCode": status_code,
226
+ "response": response_body,
227
+ },
228
+ )
229
+ self.status_code = status_code
230
+ self.response_body = response_body
231
+
232
+
233
+ class TimeoutError(X402Error):
234
+ """
235
+ Raised when a facilitator request times out.
236
+
237
+ Settlement operations can take up to 55 seconds on congested networks.
238
+ """
239
+
240
+ def __init__(
241
+ self,
242
+ operation: str,
243
+ timeout_seconds: float,
244
+ ) -> None:
245
+ super().__init__(
246
+ message=f"{operation} timed out after {timeout_seconds}s",
247
+ code="TIMEOUT",
248
+ details={
249
+ "operation": operation,
250
+ "timeoutSeconds": timeout_seconds,
251
+ },
252
+ )
253
+ self.operation = operation
254
+ self.timeout_seconds = timeout_seconds
@@ -1,74 +1,74 @@
1
- """
2
- Framework integrations for the x402 SDK.
3
-
4
- This module provides ready-to-use integrations for popular Python web frameworks:
5
-
6
- - **Flask**: Decorator and middleware for Flask apps
7
- - **FastAPI**: Dependency and middleware for FastAPI/Starlette apps
8
- - **Django**: Middleware and decorator for Django apps
9
- - **AWS Lambda**: Handler wrapper for Lambda functions
10
-
11
- Each integration provides the same core functionality but adapts to the
12
- idioms and patterns of its target framework.
13
- """
14
-
15
- # Framework availability flags
16
- FLASK_AVAILABLE = False
17
- FASTAPI_AVAILABLE = False
18
- DJANGO_AVAILABLE = False
19
-
20
- try:
21
- from uvd_x402_sdk.integrations.flask_integration import (
22
- FlaskX402,
23
- flask_require_payment,
24
- )
25
- FLASK_AVAILABLE = True
26
- except ImportError:
27
- FlaskX402 = None # type: ignore
28
- flask_require_payment = None # type: ignore
29
-
30
- try:
31
- from uvd_x402_sdk.integrations.fastapi_integration import (
32
- FastAPIX402,
33
- X402Depends,
34
- fastapi_require_payment,
35
- )
36
- FASTAPI_AVAILABLE = True
37
- except ImportError:
38
- FastAPIX402 = None # type: ignore
39
- X402Depends = None # type: ignore
40
- fastapi_require_payment = None # type: ignore
41
-
42
- try:
43
- from uvd_x402_sdk.integrations.django_integration import (
44
- DjangoX402Middleware,
45
- django_require_payment,
46
- )
47
- DJANGO_AVAILABLE = True
48
- except ImportError:
49
- DjangoX402Middleware = None # type: ignore
50
- django_require_payment = None # type: ignore
51
-
52
- from uvd_x402_sdk.integrations.lambda_integration import (
53
- LambdaX402,
54
- lambda_handler,
55
- )
56
-
57
- __all__ = [
58
- # Flask
59
- "FlaskX402",
60
- "flask_require_payment",
61
- "FLASK_AVAILABLE",
62
- # FastAPI
63
- "FastAPIX402",
64
- "X402Depends",
65
- "fastapi_require_payment",
66
- "FASTAPI_AVAILABLE",
67
- # Django
68
- "DjangoX402Middleware",
69
- "django_require_payment",
70
- "DJANGO_AVAILABLE",
71
- # AWS Lambda
72
- "LambdaX402",
73
- "lambda_handler",
74
- ]
1
+ """
2
+ Framework integrations for the x402 SDK.
3
+
4
+ This module provides ready-to-use integrations for popular Python web frameworks:
5
+
6
+ - **Flask**: Decorator and middleware for Flask apps
7
+ - **FastAPI**: Dependency and middleware for FastAPI/Starlette apps
8
+ - **Django**: Middleware and decorator for Django apps
9
+ - **AWS Lambda**: Handler wrapper for Lambda functions
10
+
11
+ Each integration provides the same core functionality but adapts to the
12
+ idioms and patterns of its target framework.
13
+ """
14
+
15
+ # Framework availability flags
16
+ FLASK_AVAILABLE = False
17
+ FASTAPI_AVAILABLE = False
18
+ DJANGO_AVAILABLE = False
19
+
20
+ try:
21
+ from uvd_x402_sdk.integrations.flask_integration import (
22
+ FlaskX402,
23
+ flask_require_payment,
24
+ )
25
+ FLASK_AVAILABLE = True
26
+ except ImportError:
27
+ FlaskX402 = None # type: ignore
28
+ flask_require_payment = None # type: ignore
29
+
30
+ try:
31
+ from uvd_x402_sdk.integrations.fastapi_integration import (
32
+ FastAPIX402,
33
+ X402Depends,
34
+ fastapi_require_payment,
35
+ )
36
+ FASTAPI_AVAILABLE = True
37
+ except ImportError:
38
+ FastAPIX402 = None # type: ignore
39
+ X402Depends = None # type: ignore
40
+ fastapi_require_payment = None # type: ignore
41
+
42
+ try:
43
+ from uvd_x402_sdk.integrations.django_integration import (
44
+ DjangoX402Middleware,
45
+ django_require_payment,
46
+ )
47
+ DJANGO_AVAILABLE = True
48
+ except ImportError:
49
+ DjangoX402Middleware = None # type: ignore
50
+ django_require_payment = None # type: ignore
51
+
52
+ from uvd_x402_sdk.integrations.lambda_integration import (
53
+ LambdaX402,
54
+ lambda_handler,
55
+ )
56
+
57
+ __all__ = [
58
+ # Flask
59
+ "FlaskX402",
60
+ "flask_require_payment",
61
+ "FLASK_AVAILABLE",
62
+ # FastAPI
63
+ "FastAPIX402",
64
+ "X402Depends",
65
+ "fastapi_require_payment",
66
+ "FASTAPI_AVAILABLE",
67
+ # Django
68
+ "DjangoX402Middleware",
69
+ "django_require_payment",
70
+ "DJANGO_AVAILABLE",
71
+ # AWS Lambda
72
+ "LambdaX402",
73
+ "lambda_handler",
74
+ ]