xache 5.0.0__py3-none-any.whl → 5.1.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.
xache/services/facilitator.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Facilitator Service - x402 v2 facilitator selection and management
|
|
3
|
+
|
|
4
|
+
Fetches facilitator configuration from the API for network-agnostic operation.
|
|
3
5
|
"""
|
|
4
6
|
|
|
5
7
|
from typing import List, Optional, Dict, Any, Literal
|
|
@@ -19,19 +21,20 @@ class FacilitatorConfig:
|
|
|
19
21
|
id: str
|
|
20
22
|
name: str
|
|
21
23
|
chains: List[ChainType]
|
|
22
|
-
networks: List[
|
|
24
|
+
networks: List[str]
|
|
23
25
|
schemes: List[PaymentScheme]
|
|
24
26
|
priority: int
|
|
25
27
|
healthy: bool = True
|
|
26
28
|
avg_latency_ms: Optional[int] = None
|
|
27
29
|
last_health_check: Optional[int] = None
|
|
30
|
+
pay_to: Optional[Dict[str, Dict[str, str]]] = None
|
|
28
31
|
|
|
29
32
|
|
|
30
33
|
@dataclass
|
|
31
34
|
class FacilitatorPreferences:
|
|
32
35
|
"""User preferences for facilitator selection"""
|
|
33
36
|
preferred_facilitators: List[str] = field(default_factory=list)
|
|
34
|
-
avoid_networks: List[
|
|
37
|
+
avoid_networks: List[str] = field(default_factory=list)
|
|
35
38
|
max_latency_ms: Optional[int] = None
|
|
36
39
|
preferred_chain: Optional[ChainType] = None
|
|
37
40
|
|
|
@@ -49,13 +52,15 @@ class FacilitatorService:
|
|
|
49
52
|
Facilitator service for x402 v2 payment facilitator selection
|
|
50
53
|
|
|
51
54
|
Manages facilitator preferences and selection for payment processing.
|
|
52
|
-
|
|
55
|
+
Fetches configuration from the API for network-agnostic operation.
|
|
53
56
|
"""
|
|
54
57
|
|
|
55
58
|
def __init__(self, client):
|
|
56
59
|
self.client = client
|
|
57
60
|
self._preferences = FacilitatorPreferences()
|
|
58
61
|
self._cached_facilitators: List[FacilitatorConfig] = []
|
|
62
|
+
self._cached_environment: str = 'testnet'
|
|
63
|
+
self._cached_default_network: str = 'base-sepolia'
|
|
59
64
|
self._last_fetch_time: int = 0
|
|
60
65
|
self._cache_duration_ms = 300000 # 5 minutes
|
|
61
66
|
|
|
@@ -96,10 +101,20 @@ class FacilitatorService:
|
|
|
96
101
|
"""Clear facilitator preferences"""
|
|
97
102
|
self._preferences = FacilitatorPreferences()
|
|
98
103
|
|
|
99
|
-
def
|
|
104
|
+
async def get_environment(self) -> str:
|
|
105
|
+
"""Get the current environment (testnet or mainnet)"""
|
|
106
|
+
await self.list() # Ensure cache is populated
|
|
107
|
+
return self._cached_environment
|
|
108
|
+
|
|
109
|
+
async def get_default_network(self) -> str:
|
|
110
|
+
"""Get the default network for the current environment"""
|
|
111
|
+
await self.list() # Ensure cache is populated
|
|
112
|
+
return self._cached_default_network
|
|
113
|
+
|
|
114
|
+
def _get_default_facilitator(self) -> FacilitatorConfig:
|
|
100
115
|
"""
|
|
101
|
-
Get the default CDP facilitator configuration
|
|
102
|
-
This is
|
|
116
|
+
Get the default CDP facilitator configuration (fallback)
|
|
117
|
+
This is used only if API is unavailable
|
|
103
118
|
"""
|
|
104
119
|
return FacilitatorConfig(
|
|
105
120
|
id='cdp',
|
|
@@ -114,10 +129,10 @@ class FacilitatorService:
|
|
|
114
129
|
async def list(self, force_refresh: bool = False) -> List[FacilitatorConfig]:
|
|
115
130
|
"""
|
|
116
131
|
List all available facilitators
|
|
117
|
-
|
|
132
|
+
Fetches from API and caches for performance.
|
|
118
133
|
|
|
119
134
|
Args:
|
|
120
|
-
force_refresh: Force refresh
|
|
135
|
+
force_refresh: Force refresh from API
|
|
121
136
|
|
|
122
137
|
Returns:
|
|
123
138
|
List of facilitator configurations
|
|
@@ -140,10 +155,39 @@ class FacilitatorService:
|
|
|
140
155
|
):
|
|
141
156
|
return self._cached_facilitators
|
|
142
157
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
158
|
+
try:
|
|
159
|
+
# Fetch from API
|
|
160
|
+
response = await self.client._request('GET', '/v1/facilitators')
|
|
161
|
+
data = response.data
|
|
162
|
+
|
|
163
|
+
if data and 'facilitators' in data:
|
|
164
|
+
self._cached_facilitators = [
|
|
165
|
+
FacilitatorConfig(
|
|
166
|
+
id=f['id'],
|
|
167
|
+
name=f['name'],
|
|
168
|
+
chains=f['chains'],
|
|
169
|
+
networks=f['networks'],
|
|
170
|
+
schemes=f['schemes'],
|
|
171
|
+
priority=f['priority'],
|
|
172
|
+
healthy=f.get('healthy', True),
|
|
173
|
+
avg_latency_ms=f.get('avgLatencyMs'),
|
|
174
|
+
last_health_check=f.get('lastHealthCheck'),
|
|
175
|
+
pay_to=f.get('payTo'),
|
|
176
|
+
)
|
|
177
|
+
for f in data['facilitators']
|
|
178
|
+
]
|
|
179
|
+
self._cached_environment = data.get('environment', 'testnet')
|
|
180
|
+
self._cached_default_network = data.get('defaultNetwork', 'base-sepolia')
|
|
181
|
+
self._last_fetch_time = now
|
|
182
|
+
return self._cached_facilitators
|
|
183
|
+
|
|
184
|
+
except Exception as e:
|
|
185
|
+
print(f"[FacilitatorService] Failed to fetch facilitators from API, using fallback: {e}")
|
|
186
|
+
|
|
187
|
+
# Fallback to default if API fails
|
|
188
|
+
if not self._cached_facilitators:
|
|
189
|
+
self._cached_facilitators = [self._get_default_facilitator()]
|
|
190
|
+
self._last_fetch_time = now
|
|
147
191
|
|
|
148
192
|
return self._cached_facilitators
|
|
149
193
|
|
|
@@ -172,7 +216,7 @@ class FacilitatorService:
|
|
|
172
216
|
async def select(
|
|
173
217
|
self,
|
|
174
218
|
chain: ChainType,
|
|
175
|
-
network: Optional[
|
|
219
|
+
network: Optional[str] = None,
|
|
176
220
|
scheme: PaymentScheme = 'exact',
|
|
177
221
|
) -> Optional[FacilitatorSelection]:
|
|
178
222
|
"""
|
|
@@ -200,11 +244,18 @@ class FacilitatorService:
|
|
|
200
244
|
"""
|
|
201
245
|
facilitators = await self.list()
|
|
202
246
|
|
|
247
|
+
# Default network based on environment
|
|
248
|
+
if network is None:
|
|
249
|
+
if chain == 'solana':
|
|
250
|
+
network = 'solana' if self._cached_environment == 'mainnet' else 'solana-devnet'
|
|
251
|
+
else:
|
|
252
|
+
network = self._cached_default_network
|
|
253
|
+
|
|
203
254
|
# Filter by requirements
|
|
204
255
|
candidates = [
|
|
205
256
|
f for f in facilitators
|
|
206
257
|
if chain in f.chains
|
|
207
|
-
and
|
|
258
|
+
and network in f.networks
|
|
208
259
|
and scheme in f.schemes
|
|
209
260
|
and f.healthy is not False
|
|
210
261
|
]
|
|
@@ -264,7 +315,7 @@ class FacilitatorService:
|
|
|
264
315
|
self,
|
|
265
316
|
facilitator_id: str,
|
|
266
317
|
chain: ChainType,
|
|
267
|
-
network:
|
|
318
|
+
network: str,
|
|
268
319
|
scheme: PaymentScheme = 'exact',
|
|
269
320
|
) -> bool:
|
|
270
321
|
"""
|
|
@@ -11,7 +11,7 @@ xache/services/__init__.py,sha256=ERuZXa7R-Iv0oFBknxJiBO5nJC-oCtIut_4VITw_uOE,77
|
|
|
11
11
|
xache/services/budget.py,sha256=6sZ3nojb888a3k774XPnJHfdkqIC2Y1BxJKt8zy76V0,10599
|
|
12
12
|
xache/services/collective.py,sha256=utYLIHv3tuOYHbdYJYXqIy1hS-aYIRems744CsCUIUw,6229
|
|
13
13
|
xache/services/extraction.py,sha256=5KElr4ldBR3kcOofvz4d3NwAuTvKVskZ-NTQ7BI2ChY,5317
|
|
14
|
-
xache/services/facilitator.py,sha256=
|
|
14
|
+
xache/services/facilitator.py,sha256=FlJh6YvPd1xiCdt6Y8Y9NpbmJI0o92Dcp3ZgzeR14bM,11512
|
|
15
15
|
xache/services/identity.py,sha256=gOs5fN9juyoBfXQVm-G4whyUMJ6Oha2VmP_i3mQw0G0,13478
|
|
16
16
|
xache/services/memory.py,sha256=ng9_cwL4jE4c3gdlwQDZyqaBdQgwtqApEwj0LkZYWRY,13290
|
|
17
17
|
xache/services/owner.py,sha256=2ASJFjApS3AiQEpoS2oM9M3sisi0Y6xSjmU1fwUM0rA,8912
|
|
@@ -24,7 +24,7 @@ xache/utils/__init__.py,sha256=8VrQm0QnyqxdplpCG7BDRiAVdBGWrjUs9ipH2zsJOBM,106
|
|
|
24
24
|
xache/utils/cache.py,sha256=9zhE9dIXFTofj7jz1TX-FkAqmclqoYXTe4FwwGLeKT4,5479
|
|
25
25
|
xache/utils/http.py,sha256=rIQCYvYrziNrNfEbOnIKbCOGGf7bcdTvZrrU_W6CcZA,6547
|
|
26
26
|
xache/utils/retry.py,sha256=OJYBGozKIoteCvKw50dqd4ThhOo-WisorcKa8Tr6mnE,2860
|
|
27
|
-
xache-5.
|
|
28
|
-
xache-5.
|
|
29
|
-
xache-5.
|
|
30
|
-
xache-5.
|
|
27
|
+
xache-5.1.0.dist-info/METADATA,sha256=Epfq9BxGeZ913xE5fWrvMoiBaJvesUQ-fVJEX5FcAdA,8469
|
|
28
|
+
xache-5.1.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
29
|
+
xache-5.1.0.dist-info/top_level.txt,sha256=FBWE4IVb7zoLS9arsdrl97QVETlwFvYGAx6xEJZOEUU,6
|
|
30
|
+
xache-5.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|