t402 1.6.1__py3-none-any.whl → 1.9.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.
- t402/__init__.py +169 -2
- t402/common.py +37 -8
- t402/encoding.py +298 -1
- t402/facilitator.py +1 -1
- t402/fastapi/__init__.py +79 -0
- t402/fastapi/dependencies.py +398 -0
- t402/fastapi/middleware.py +665 -130
- t402/schemes/__init__.py +164 -0
- t402/schemes/evm/__init__.py +46 -0
- t402/schemes/evm/exact/__init__.py +29 -0
- t402/schemes/evm/exact/client.py +265 -0
- t402/schemes/evm/exact/server.py +181 -0
- t402/schemes/evm/upto/__init__.py +58 -0
- t402/schemes/evm/upto/client.py +240 -0
- t402/schemes/evm/upto/types.py +305 -0
- t402/schemes/interfaces.py +401 -0
- t402/schemes/registry.py +477 -0
- t402/schemes/ton/__init__.py +22 -0
- t402/schemes/ton/exact/__init__.py +27 -0
- t402/schemes/ton/exact/client.py +343 -0
- t402/schemes/ton/exact/server.py +201 -0
- t402/schemes/tron/__init__.py +22 -0
- t402/schemes/tron/exact/__init__.py +27 -0
- t402/schemes/tron/exact/client.py +260 -0
- t402/schemes/tron/exact/server.py +192 -0
- t402/schemes/upto/__init__.py +80 -0
- t402/schemes/upto/types.py +376 -0
- t402/types.py +178 -8
- {t402-1.6.1.dist-info → t402-1.9.0.dist-info}/METADATA +1 -1
- {t402-1.6.1.dist-info → t402-1.9.0.dist-info}/RECORD +32 -11
- {t402-1.6.1.dist-info → t402-1.9.0.dist-info}/WHEEL +0 -0
- {t402-1.6.1.dist-info → t402-1.9.0.dist-info}/entry_points.txt +0 -0
t402/schemes/registry.py
ADDED
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
"""Scheme Registry for T402 Protocol.
|
|
2
|
+
|
|
3
|
+
This module provides the SchemeRegistry class for managing payment scheme
|
|
4
|
+
implementations across different blockchain networks and protocol versions.
|
|
5
|
+
|
|
6
|
+
The registry supports:
|
|
7
|
+
- Registering schemes by network (exact match) or network pattern (wildcards)
|
|
8
|
+
- Looking up schemes by network and scheme name
|
|
9
|
+
- Separate registries for client, server, and facilitator schemes
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import re
|
|
15
|
+
import threading
|
|
16
|
+
from typing import (
|
|
17
|
+
Any,
|
|
18
|
+
Dict,
|
|
19
|
+
Generic,
|
|
20
|
+
List,
|
|
21
|
+
Optional,
|
|
22
|
+
TypeVar,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
from t402.types import (
|
|
26
|
+
Network,
|
|
27
|
+
T402_VERSION_V1,
|
|
28
|
+
T402_VERSION_V2,
|
|
29
|
+
)
|
|
30
|
+
from t402.schemes.interfaces import (
|
|
31
|
+
SchemeNetworkClient,
|
|
32
|
+
SchemeNetworkServer,
|
|
33
|
+
SchemeNetworkFacilitator,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
# Type variable for generic scheme types
|
|
37
|
+
T = TypeVar("T")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _matches_network_pattern(pattern: str, network: str) -> bool:
|
|
41
|
+
"""Check if a network matches a pattern.
|
|
42
|
+
|
|
43
|
+
Supports:
|
|
44
|
+
- Exact match: "eip155:8453" matches "eip155:8453"
|
|
45
|
+
- Wildcard: "eip155:*" matches any "eip155:..." network
|
|
46
|
+
- Full wildcard: "*" matches any network
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
pattern: Network pattern (may include wildcards)
|
|
50
|
+
network: Actual network identifier
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
True if network matches pattern
|
|
54
|
+
"""
|
|
55
|
+
if pattern == "*":
|
|
56
|
+
return True
|
|
57
|
+
|
|
58
|
+
if "*" in pattern:
|
|
59
|
+
# Convert glob pattern to regex
|
|
60
|
+
# e.g., "eip155:*" -> "^eip155:.*$"
|
|
61
|
+
regex_pattern = "^" + pattern.replace("*", ".*") + "$"
|
|
62
|
+
return bool(re.match(regex_pattern, network))
|
|
63
|
+
|
|
64
|
+
return pattern == network
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _extract_caip_family(network: str) -> str:
|
|
68
|
+
"""Extract CAIP-2 family from network identifier.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
network: Network identifier (e.g., "eip155:8453", "solana:mainnet")
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
Family pattern (e.g., "eip155:*", "solana:*")
|
|
75
|
+
"""
|
|
76
|
+
if ":" in network:
|
|
77
|
+
namespace = network.split(":")[0]
|
|
78
|
+
return f"{namespace}:*"
|
|
79
|
+
return network
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class SchemeRegistry(Generic[T]):
|
|
83
|
+
"""Registry for managing payment scheme implementations.
|
|
84
|
+
|
|
85
|
+
This class provides a thread-safe registry for registering and looking up
|
|
86
|
+
payment scheme implementations. Schemes can be registered with exact network
|
|
87
|
+
identifiers or wildcard patterns.
|
|
88
|
+
|
|
89
|
+
The registry is organized by:
|
|
90
|
+
- Protocol version (V1 or V2)
|
|
91
|
+
- Network identifier or pattern
|
|
92
|
+
- Scheme name
|
|
93
|
+
|
|
94
|
+
Example:
|
|
95
|
+
```python
|
|
96
|
+
registry = SchemeRegistry[SchemeNetworkClient]()
|
|
97
|
+
|
|
98
|
+
# Register for exact network
|
|
99
|
+
registry.register("eip155:8453", evm_client)
|
|
100
|
+
|
|
101
|
+
# Register with wildcard (all EVM networks)
|
|
102
|
+
registry.register("eip155:*", evm_client)
|
|
103
|
+
|
|
104
|
+
# Look up scheme
|
|
105
|
+
client = registry.get("eip155:8453", "exact")
|
|
106
|
+
```
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
def __init__(self, default_version: int = T402_VERSION_V2):
|
|
110
|
+
"""Initialize the registry.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
default_version: Default protocol version for registrations
|
|
114
|
+
"""
|
|
115
|
+
self._default_version = default_version
|
|
116
|
+
self._lock = threading.RLock()
|
|
117
|
+
|
|
118
|
+
# Structure: {version: {network_pattern: {scheme: implementation}}}
|
|
119
|
+
self._schemes: Dict[int, Dict[str, Dict[str, T]]] = {
|
|
120
|
+
T402_VERSION_V1: {},
|
|
121
|
+
T402_VERSION_V2: {},
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
# Cache for pattern-based lookups
|
|
125
|
+
self._patterns: Dict[int, List[str]] = {
|
|
126
|
+
T402_VERSION_V1: [],
|
|
127
|
+
T402_VERSION_V2: [],
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
def register(
|
|
131
|
+
self,
|
|
132
|
+
network: Network,
|
|
133
|
+
scheme: T,
|
|
134
|
+
version: Optional[int] = None,
|
|
135
|
+
) -> "SchemeRegistry[T]":
|
|
136
|
+
"""Register a scheme for a network.
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
network: Network identifier or pattern (e.g., "eip155:8453" or "eip155:*")
|
|
140
|
+
scheme: Scheme implementation (must have 'scheme' attribute)
|
|
141
|
+
version: Protocol version (defaults to current default)
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
Self for chaining
|
|
145
|
+
|
|
146
|
+
Raises:
|
|
147
|
+
ValueError: If scheme doesn't have 'scheme' attribute
|
|
148
|
+
"""
|
|
149
|
+
if not hasattr(scheme, "scheme"):
|
|
150
|
+
raise ValueError("Scheme must have 'scheme' attribute")
|
|
151
|
+
|
|
152
|
+
scheme_name = scheme.scheme
|
|
153
|
+
v = version or self._default_version
|
|
154
|
+
|
|
155
|
+
with self._lock:
|
|
156
|
+
if v not in self._schemes:
|
|
157
|
+
self._schemes[v] = {}
|
|
158
|
+
self._patterns[v] = []
|
|
159
|
+
|
|
160
|
+
if network not in self._schemes[v]:
|
|
161
|
+
self._schemes[v][network] = {}
|
|
162
|
+
|
|
163
|
+
self._schemes[v][network][scheme_name] = scheme
|
|
164
|
+
|
|
165
|
+
# Track patterns for wildcard matching
|
|
166
|
+
if "*" in network and network not in self._patterns[v]:
|
|
167
|
+
self._patterns[v].append(network)
|
|
168
|
+
|
|
169
|
+
return self
|
|
170
|
+
|
|
171
|
+
def register_v1(
|
|
172
|
+
self,
|
|
173
|
+
network: Network,
|
|
174
|
+
scheme: T,
|
|
175
|
+
) -> "SchemeRegistry[T]":
|
|
176
|
+
"""Register a scheme for V1 protocol.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
network: V1 network identifier (e.g., "base-sepolia")
|
|
180
|
+
scheme: Scheme implementation
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
Self for chaining
|
|
184
|
+
"""
|
|
185
|
+
return self.register(network, scheme, T402_VERSION_V1)
|
|
186
|
+
|
|
187
|
+
def register_v2(
|
|
188
|
+
self,
|
|
189
|
+
network: Network,
|
|
190
|
+
scheme: T,
|
|
191
|
+
) -> "SchemeRegistry[T]":
|
|
192
|
+
"""Register a scheme for V2 protocol.
|
|
193
|
+
|
|
194
|
+
Args:
|
|
195
|
+
network: V2 network identifier (CAIP-2 format)
|
|
196
|
+
scheme: Scheme implementation
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
Self for chaining
|
|
200
|
+
"""
|
|
201
|
+
return self.register(network, scheme, T402_VERSION_V2)
|
|
202
|
+
|
|
203
|
+
def get(
|
|
204
|
+
self,
|
|
205
|
+
network: Network,
|
|
206
|
+
scheme_name: str,
|
|
207
|
+
version: Optional[int] = None,
|
|
208
|
+
) -> Optional[T]:
|
|
209
|
+
"""Get a scheme for a specific network and scheme name.
|
|
210
|
+
|
|
211
|
+
Lookup order:
|
|
212
|
+
1. Exact network match
|
|
213
|
+
2. Pattern match (e.g., "eip155:*" for "eip155:8453")
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
network: Network identifier
|
|
217
|
+
scheme_name: Scheme name (e.g., "exact")
|
|
218
|
+
version: Protocol version (defaults to current default)
|
|
219
|
+
|
|
220
|
+
Returns:
|
|
221
|
+
Scheme implementation or None if not found
|
|
222
|
+
"""
|
|
223
|
+
v = version or self._default_version
|
|
224
|
+
|
|
225
|
+
with self._lock:
|
|
226
|
+
if v not in self._schemes:
|
|
227
|
+
return None
|
|
228
|
+
|
|
229
|
+
# Try exact match first
|
|
230
|
+
if network in self._schemes[v]:
|
|
231
|
+
schemes = self._schemes[v][network]
|
|
232
|
+
if scheme_name in schemes:
|
|
233
|
+
return schemes[scheme_name]
|
|
234
|
+
|
|
235
|
+
# Try pattern matching
|
|
236
|
+
for pattern in self._patterns.get(v, []):
|
|
237
|
+
if _matches_network_pattern(pattern, network):
|
|
238
|
+
schemes = self._schemes[v].get(pattern, {})
|
|
239
|
+
if scheme_name in schemes:
|
|
240
|
+
return schemes[scheme_name]
|
|
241
|
+
|
|
242
|
+
return None
|
|
243
|
+
|
|
244
|
+
def get_for_network(
|
|
245
|
+
self,
|
|
246
|
+
network: Network,
|
|
247
|
+
version: Optional[int] = None,
|
|
248
|
+
) -> Dict[str, T]:
|
|
249
|
+
"""Get all schemes registered for a network.
|
|
250
|
+
|
|
251
|
+
Args:
|
|
252
|
+
network: Network identifier
|
|
253
|
+
version: Protocol version
|
|
254
|
+
|
|
255
|
+
Returns:
|
|
256
|
+
Dict of scheme_name -> scheme implementation
|
|
257
|
+
"""
|
|
258
|
+
v = version or self._default_version
|
|
259
|
+
result: Dict[str, T] = {}
|
|
260
|
+
|
|
261
|
+
with self._lock:
|
|
262
|
+
if v not in self._schemes:
|
|
263
|
+
return result
|
|
264
|
+
|
|
265
|
+
# Exact match
|
|
266
|
+
if network in self._schemes[v]:
|
|
267
|
+
result.update(self._schemes[v][network])
|
|
268
|
+
|
|
269
|
+
# Pattern matches
|
|
270
|
+
for pattern in self._patterns.get(v, []):
|
|
271
|
+
if _matches_network_pattern(pattern, network):
|
|
272
|
+
# Don't override exact matches
|
|
273
|
+
for scheme_name, scheme in self._schemes[v].get(pattern, {}).items():
|
|
274
|
+
if scheme_name not in result:
|
|
275
|
+
result[scheme_name] = scheme
|
|
276
|
+
|
|
277
|
+
return result
|
|
278
|
+
|
|
279
|
+
def has_scheme(
|
|
280
|
+
self,
|
|
281
|
+
network: Network,
|
|
282
|
+
scheme_name: str,
|
|
283
|
+
version: Optional[int] = None,
|
|
284
|
+
) -> bool:
|
|
285
|
+
"""Check if a scheme is registered for a network.
|
|
286
|
+
|
|
287
|
+
Args:
|
|
288
|
+
network: Network identifier
|
|
289
|
+
scheme_name: Scheme name
|
|
290
|
+
version: Protocol version
|
|
291
|
+
|
|
292
|
+
Returns:
|
|
293
|
+
True if scheme is registered
|
|
294
|
+
"""
|
|
295
|
+
return self.get(network, scheme_name, version) is not None
|
|
296
|
+
|
|
297
|
+
def get_registered_networks(
|
|
298
|
+
self,
|
|
299
|
+
version: Optional[int] = None,
|
|
300
|
+
) -> List[str]:
|
|
301
|
+
"""Get all registered network patterns.
|
|
302
|
+
|
|
303
|
+
Args:
|
|
304
|
+
version: Protocol version
|
|
305
|
+
|
|
306
|
+
Returns:
|
|
307
|
+
List of network identifiers/patterns
|
|
308
|
+
"""
|
|
309
|
+
v = version or self._default_version
|
|
310
|
+
|
|
311
|
+
with self._lock:
|
|
312
|
+
return list(self._schemes.get(v, {}).keys())
|
|
313
|
+
|
|
314
|
+
def get_registered_schemes(
|
|
315
|
+
self,
|
|
316
|
+
network: Network,
|
|
317
|
+
version: Optional[int] = None,
|
|
318
|
+
) -> List[str]:
|
|
319
|
+
"""Get all scheme names registered for a network.
|
|
320
|
+
|
|
321
|
+
Args:
|
|
322
|
+
network: Network identifier
|
|
323
|
+
version: Protocol version
|
|
324
|
+
|
|
325
|
+
Returns:
|
|
326
|
+
List of scheme names
|
|
327
|
+
"""
|
|
328
|
+
schemes = self.get_for_network(network, version)
|
|
329
|
+
return list(schemes.keys())
|
|
330
|
+
|
|
331
|
+
def clear(self, version: Optional[int] = None) -> None:
|
|
332
|
+
"""Clear all registered schemes.
|
|
333
|
+
|
|
334
|
+
Args:
|
|
335
|
+
version: If provided, only clear that version. Otherwise clear all.
|
|
336
|
+
"""
|
|
337
|
+
with self._lock:
|
|
338
|
+
if version is not None:
|
|
339
|
+
self._schemes[version] = {}
|
|
340
|
+
self._patterns[version] = []
|
|
341
|
+
else:
|
|
342
|
+
for v in self._schemes:
|
|
343
|
+
self._schemes[v] = {}
|
|
344
|
+
self._patterns[v] = []
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
class ClientSchemeRegistry(SchemeRegistry[SchemeNetworkClient]):
|
|
348
|
+
"""Registry specifically for client schemes."""
|
|
349
|
+
|
|
350
|
+
pass
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
class ServerSchemeRegistry(SchemeRegistry[SchemeNetworkServer]):
|
|
354
|
+
"""Registry specifically for server schemes."""
|
|
355
|
+
|
|
356
|
+
pass
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
class FacilitatorSchemeRegistry(SchemeRegistry[SchemeNetworkFacilitator]):
|
|
360
|
+
"""Registry specifically for facilitator schemes.
|
|
361
|
+
|
|
362
|
+
Provides additional methods for building /supported responses.
|
|
363
|
+
"""
|
|
364
|
+
|
|
365
|
+
def get_supported_kinds(
|
|
366
|
+
self,
|
|
367
|
+
version: int = T402_VERSION_V2,
|
|
368
|
+
) -> List[Dict[str, Any]]:
|
|
369
|
+
"""Get all supported kinds for the /supported endpoint.
|
|
370
|
+
|
|
371
|
+
Returns:
|
|
372
|
+
List of SupportedKind dicts
|
|
373
|
+
"""
|
|
374
|
+
result: List[Dict[str, Any]] = []
|
|
375
|
+
|
|
376
|
+
with self._lock:
|
|
377
|
+
for network, schemes in self._schemes.get(version, {}).items():
|
|
378
|
+
# Skip wildcard patterns - they represent capabilities, not specific networks
|
|
379
|
+
if "*" in network:
|
|
380
|
+
continue
|
|
381
|
+
|
|
382
|
+
for scheme_name, scheme in schemes.items():
|
|
383
|
+
kind: Dict[str, Any] = {
|
|
384
|
+
"t402Version": version,
|
|
385
|
+
"scheme": scheme_name,
|
|
386
|
+
"network": network,
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
# Add extra data if available
|
|
390
|
+
if hasattr(scheme, "get_extra"):
|
|
391
|
+
extra = scheme.get_extra(network)
|
|
392
|
+
if extra:
|
|
393
|
+
kind["extra"] = extra
|
|
394
|
+
|
|
395
|
+
result.append(kind)
|
|
396
|
+
|
|
397
|
+
return result
|
|
398
|
+
|
|
399
|
+
def get_signers_by_family(
|
|
400
|
+
self,
|
|
401
|
+
version: int = T402_VERSION_V2,
|
|
402
|
+
) -> Dict[str, List[str]]:
|
|
403
|
+
"""Get signer addresses grouped by CAIP family.
|
|
404
|
+
|
|
405
|
+
Returns:
|
|
406
|
+
Dict of caip_family -> list of signer addresses
|
|
407
|
+
"""
|
|
408
|
+
result: Dict[str, List[str]] = {}
|
|
409
|
+
seen_schemes: Dict[str, set] = {} # Track seen scheme instances by family
|
|
410
|
+
|
|
411
|
+
with self._lock:
|
|
412
|
+
for network, schemes in self._schemes.get(version, {}).items():
|
|
413
|
+
for scheme_name, scheme in schemes.items():
|
|
414
|
+
if not hasattr(scheme, "caip_family") or not hasattr(scheme, "get_signers"):
|
|
415
|
+
continue
|
|
416
|
+
|
|
417
|
+
family = scheme.caip_family
|
|
418
|
+
|
|
419
|
+
# Initialize family tracking
|
|
420
|
+
if family not in result:
|
|
421
|
+
result[family] = []
|
|
422
|
+
seen_schemes[family] = set()
|
|
423
|
+
|
|
424
|
+
# Avoid duplicate signers from same scheme instance
|
|
425
|
+
scheme_id = id(scheme)
|
|
426
|
+
if scheme_id in seen_schemes[family]:
|
|
427
|
+
continue
|
|
428
|
+
seen_schemes[family].add(scheme_id)
|
|
429
|
+
|
|
430
|
+
# Get signers
|
|
431
|
+
try:
|
|
432
|
+
signers = scheme.get_signers(network)
|
|
433
|
+
for signer in signers:
|
|
434
|
+
if signer not in result[family]:
|
|
435
|
+
result[family].append(signer)
|
|
436
|
+
except Exception:
|
|
437
|
+
pass # Ignore errors from get_signers
|
|
438
|
+
|
|
439
|
+
return result
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
# Global registry instances (optional convenience)
|
|
443
|
+
_client_registry: Optional[ClientSchemeRegistry] = None
|
|
444
|
+
_server_registry: Optional[ServerSchemeRegistry] = None
|
|
445
|
+
_facilitator_registry: Optional[FacilitatorSchemeRegistry] = None
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
def get_client_registry() -> ClientSchemeRegistry:
|
|
449
|
+
"""Get the global client scheme registry."""
|
|
450
|
+
global _client_registry
|
|
451
|
+
if _client_registry is None:
|
|
452
|
+
_client_registry = ClientSchemeRegistry()
|
|
453
|
+
return _client_registry
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
def get_server_registry() -> ServerSchemeRegistry:
|
|
457
|
+
"""Get the global server scheme registry."""
|
|
458
|
+
global _server_registry
|
|
459
|
+
if _server_registry is None:
|
|
460
|
+
_server_registry = ServerSchemeRegistry()
|
|
461
|
+
return _server_registry
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
def get_facilitator_registry() -> FacilitatorSchemeRegistry:
|
|
465
|
+
"""Get the global facilitator scheme registry."""
|
|
466
|
+
global _facilitator_registry
|
|
467
|
+
if _facilitator_registry is None:
|
|
468
|
+
_facilitator_registry = FacilitatorSchemeRegistry()
|
|
469
|
+
return _facilitator_registry
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
def reset_global_registries() -> None:
|
|
473
|
+
"""Reset all global registries. Useful for testing."""
|
|
474
|
+
global _client_registry, _server_registry, _facilitator_registry
|
|
475
|
+
_client_registry = None
|
|
476
|
+
_server_registry = None
|
|
477
|
+
_facilitator_registry = None
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""TON Blockchain Payment Schemes.
|
|
2
|
+
|
|
3
|
+
This package provides payment scheme implementations for TON blockchain.
|
|
4
|
+
|
|
5
|
+
Supported schemes:
|
|
6
|
+
- exact: Jetton TransferWithAuthorization
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from t402.schemes.ton.exact import (
|
|
10
|
+
ExactTonClientScheme,
|
|
11
|
+
ExactTonServerScheme,
|
|
12
|
+
TonSigner,
|
|
13
|
+
SCHEME_EXACT,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
# Exact scheme
|
|
18
|
+
"ExactTonClientScheme",
|
|
19
|
+
"ExactTonServerScheme",
|
|
20
|
+
"TonSigner",
|
|
21
|
+
"SCHEME_EXACT",
|
|
22
|
+
]
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""TON Exact Payment Scheme.
|
|
2
|
+
|
|
3
|
+
This package provides the exact payment scheme implementation for TON
|
|
4
|
+
using Jetton TransferWithAuthorization.
|
|
5
|
+
|
|
6
|
+
The exact scheme allows users to authorize Jetton transfers that can be
|
|
7
|
+
executed by a facilitator, enabling gasless payments on TON.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from t402.schemes.ton.exact.client import (
|
|
11
|
+
ExactTonClientScheme,
|
|
12
|
+
TonSigner,
|
|
13
|
+
SCHEME_EXACT,
|
|
14
|
+
)
|
|
15
|
+
from t402.schemes.ton.exact.server import (
|
|
16
|
+
ExactTonServerScheme,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
# Client
|
|
21
|
+
"ExactTonClientScheme",
|
|
22
|
+
"TonSigner",
|
|
23
|
+
# Server
|
|
24
|
+
"ExactTonServerScheme",
|
|
25
|
+
# Constants
|
|
26
|
+
"SCHEME_EXACT",
|
|
27
|
+
]
|