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
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
"""TRON Exact Scheme - Client Implementation.
|
|
2
|
+
|
|
3
|
+
This module provides the client-side implementation of the exact payment scheme
|
|
4
|
+
for TRON network using TRC-20 token transfers.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import time
|
|
10
|
+
from typing import Any, Dict, Optional, Protocol, Union
|
|
11
|
+
|
|
12
|
+
from t402.types import (
|
|
13
|
+
PaymentRequirementsV2,
|
|
14
|
+
T402_VERSION_V1,
|
|
15
|
+
T402_VERSION_V2,
|
|
16
|
+
)
|
|
17
|
+
from t402.tron import (
|
|
18
|
+
TronAuthorization,
|
|
19
|
+
TronPaymentPayload,
|
|
20
|
+
DEFAULT_FEE_LIMIT,
|
|
21
|
+
validate_tron_address,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# Constants
|
|
26
|
+
SCHEME_EXACT = "exact"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class BlockInfo(Protocol):
|
|
30
|
+
"""Protocol for TRON block reference info."""
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def ref_block_bytes(self) -> str:
|
|
34
|
+
"""Reference block bytes (4 bytes hex)."""
|
|
35
|
+
...
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def ref_block_hash(self) -> str:
|
|
39
|
+
"""Reference block hash (8 bytes hex)."""
|
|
40
|
+
...
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def expiration(self) -> int:
|
|
44
|
+
"""Transaction expiration timestamp in milliseconds."""
|
|
45
|
+
...
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class TronSigner(Protocol):
|
|
49
|
+
"""Protocol for TRON wallet signing operations.
|
|
50
|
+
|
|
51
|
+
Implementations should provide wallet address, block info retrieval,
|
|
52
|
+
and transaction signing capabilities.
|
|
53
|
+
|
|
54
|
+
Example implementation with tronpy:
|
|
55
|
+
```python
|
|
56
|
+
class MyTronSigner:
|
|
57
|
+
def __init__(self, private_key, client):
|
|
58
|
+
self._private_key = private_key
|
|
59
|
+
self._client = client
|
|
60
|
+
self._address = private_key_to_address(private_key)
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def address(self) -> str:
|
|
64
|
+
return self._address
|
|
65
|
+
|
|
66
|
+
async def get_block_info(self) -> BlockInfo:
|
|
67
|
+
block = await self._client.get_latest_block()
|
|
68
|
+
return {
|
|
69
|
+
"ref_block_bytes": block.ref_block_bytes,
|
|
70
|
+
"ref_block_hash": block.ref_block_hash,
|
|
71
|
+
"expiration": int(time.time() * 1000) + 3600000,
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async def sign_transaction(
|
|
75
|
+
self,
|
|
76
|
+
contract_address: str,
|
|
77
|
+
to: str,
|
|
78
|
+
amount: str,
|
|
79
|
+
fee_limit: int,
|
|
80
|
+
expiration: int,
|
|
81
|
+
) -> str:
|
|
82
|
+
# Build and sign TRC-20 transfer transaction
|
|
83
|
+
return signed_transaction_hex
|
|
84
|
+
```
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def address(self) -> str:
|
|
89
|
+
"""Return the wallet address (T-prefix base58check)."""
|
|
90
|
+
...
|
|
91
|
+
|
|
92
|
+
async def get_block_info(self) -> Dict[str, Any]:
|
|
93
|
+
"""Get the current reference block info for transaction building.
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
Dict with ref_block_bytes, ref_block_hash, and expiration
|
|
97
|
+
"""
|
|
98
|
+
...
|
|
99
|
+
|
|
100
|
+
async def sign_transaction(
|
|
101
|
+
self,
|
|
102
|
+
contract_address: str,
|
|
103
|
+
to: str,
|
|
104
|
+
amount: str,
|
|
105
|
+
fee_limit: int,
|
|
106
|
+
expiration: int,
|
|
107
|
+
) -> str:
|
|
108
|
+
"""Sign a TRC-20 transfer transaction.
|
|
109
|
+
|
|
110
|
+
Args:
|
|
111
|
+
contract_address: TRC-20 contract address
|
|
112
|
+
to: Recipient address
|
|
113
|
+
amount: Amount in smallest units
|
|
114
|
+
fee_limit: Fee limit in SUN
|
|
115
|
+
expiration: Transaction expiration in milliseconds
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
Hex-encoded signed transaction
|
|
119
|
+
"""
|
|
120
|
+
...
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class ExactTronClientScheme:
|
|
124
|
+
"""Client scheme for TRON exact payments using TRC-20 transfers.
|
|
125
|
+
|
|
126
|
+
Creates signed TRC-20 transfer transactions that can be verified and
|
|
127
|
+
broadcast by a facilitator to complete the payment.
|
|
128
|
+
|
|
129
|
+
Example:
|
|
130
|
+
```python
|
|
131
|
+
scheme = ExactTronClientScheme(signer=my_tron_signer)
|
|
132
|
+
|
|
133
|
+
payload = await scheme.create_payment_payload(
|
|
134
|
+
t402_version=2,
|
|
135
|
+
requirements={
|
|
136
|
+
"scheme": "exact",
|
|
137
|
+
"network": "tron:mainnet",
|
|
138
|
+
"asset": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
|
|
139
|
+
"amount": "1000000",
|
|
140
|
+
"payTo": "TPayToAddress...",
|
|
141
|
+
"maxTimeoutSeconds": 300,
|
|
142
|
+
},
|
|
143
|
+
)
|
|
144
|
+
```
|
|
145
|
+
"""
|
|
146
|
+
|
|
147
|
+
scheme = SCHEME_EXACT
|
|
148
|
+
caip_family = "tron:*"
|
|
149
|
+
|
|
150
|
+
def __init__(
|
|
151
|
+
self,
|
|
152
|
+
signer: TronSigner,
|
|
153
|
+
fee_limit: Optional[int] = None,
|
|
154
|
+
):
|
|
155
|
+
"""Initialize the TRON client scheme.
|
|
156
|
+
|
|
157
|
+
Args:
|
|
158
|
+
signer: TRON signer for signing transactions
|
|
159
|
+
fee_limit: Override fee limit in SUN (default: 100 TRX)
|
|
160
|
+
"""
|
|
161
|
+
self._signer = signer
|
|
162
|
+
self._fee_limit = fee_limit or DEFAULT_FEE_LIMIT
|
|
163
|
+
|
|
164
|
+
@property
|
|
165
|
+
def address(self) -> str:
|
|
166
|
+
"""Return the wallet address."""
|
|
167
|
+
return self._signer.address
|
|
168
|
+
|
|
169
|
+
async def create_payment_payload(
|
|
170
|
+
self,
|
|
171
|
+
t402_version: int,
|
|
172
|
+
requirements: Union[PaymentRequirementsV2, Dict[str, Any]],
|
|
173
|
+
) -> Dict[str, Any]:
|
|
174
|
+
"""Create a payment payload for TRC-20 transfer.
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
t402_version: Protocol version (1 or 2)
|
|
178
|
+
requirements: Payment requirements
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
Payment payload with signed transaction and authorization metadata
|
|
182
|
+
"""
|
|
183
|
+
# Convert to dict for easier access
|
|
184
|
+
if hasattr(requirements, "model_dump"):
|
|
185
|
+
req = requirements.model_dump(by_alias=True)
|
|
186
|
+
else:
|
|
187
|
+
req = dict(requirements)
|
|
188
|
+
|
|
189
|
+
# Extract fields
|
|
190
|
+
network = req.get("network", "")
|
|
191
|
+
asset = req.get("asset", "")
|
|
192
|
+
amount = req.get("amount", "0")
|
|
193
|
+
pay_to = req.get("payTo", "")
|
|
194
|
+
max_timeout = req.get("maxTimeoutSeconds", 300)
|
|
195
|
+
|
|
196
|
+
# Validate required fields
|
|
197
|
+
if not asset:
|
|
198
|
+
raise ValueError("Asset (TRC-20 contract address) is required")
|
|
199
|
+
if not pay_to:
|
|
200
|
+
raise ValueError("PayTo address is required")
|
|
201
|
+
if not amount:
|
|
202
|
+
raise ValueError("Amount is required")
|
|
203
|
+
|
|
204
|
+
# Validate addresses
|
|
205
|
+
if not validate_tron_address(asset):
|
|
206
|
+
raise ValueError(f"Invalid TRC-20 contract address: {asset}")
|
|
207
|
+
if not validate_tron_address(pay_to):
|
|
208
|
+
raise ValueError(f"Invalid payTo address: {pay_to}")
|
|
209
|
+
if not validate_tron_address(self._signer.address):
|
|
210
|
+
raise ValueError(f"Invalid signer address: {self._signer.address}")
|
|
211
|
+
|
|
212
|
+
# Get block info for transaction
|
|
213
|
+
block_info = await self._signer.get_block_info()
|
|
214
|
+
ref_block_bytes = block_info.get("ref_block_bytes", "")
|
|
215
|
+
ref_block_hash = block_info.get("ref_block_hash", "")
|
|
216
|
+
|
|
217
|
+
# Calculate expiration
|
|
218
|
+
now_ms = int(time.time() * 1000)
|
|
219
|
+
expiration = block_info.get("expiration") or (now_ms + max_timeout * 1000)
|
|
220
|
+
|
|
221
|
+
# Sign the transaction
|
|
222
|
+
signed_transaction = await self._signer.sign_transaction(
|
|
223
|
+
contract_address=asset,
|
|
224
|
+
to=pay_to,
|
|
225
|
+
amount=amount,
|
|
226
|
+
fee_limit=self._fee_limit,
|
|
227
|
+
expiration=expiration,
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
# Build authorization metadata
|
|
231
|
+
authorization = TronAuthorization(
|
|
232
|
+
from_=self._signer.address,
|
|
233
|
+
to=pay_to,
|
|
234
|
+
contract_address=asset,
|
|
235
|
+
amount=amount,
|
|
236
|
+
expiration=expiration,
|
|
237
|
+
ref_block_bytes=ref_block_bytes,
|
|
238
|
+
ref_block_hash=ref_block_hash,
|
|
239
|
+
timestamp=now_ms,
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
# Build payload
|
|
243
|
+
payload_data = TronPaymentPayload(
|
|
244
|
+
signed_transaction=signed_transaction,
|
|
245
|
+
authorization=authorization,
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
if t402_version == T402_VERSION_V1:
|
|
249
|
+
return {
|
|
250
|
+
"t402Version": T402_VERSION_V1,
|
|
251
|
+
"scheme": self.scheme,
|
|
252
|
+
"network": network,
|
|
253
|
+
"payload": payload_data.model_dump(by_alias=True),
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
# V2 format
|
|
257
|
+
return {
|
|
258
|
+
"t402Version": T402_VERSION_V2,
|
|
259
|
+
"payload": payload_data.model_dump(by_alias=True),
|
|
260
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"""TRON Exact Scheme - Server Implementation.
|
|
2
|
+
|
|
3
|
+
This module provides the server-side implementation of the exact payment scheme
|
|
4
|
+
for TRON network.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from decimal import Decimal
|
|
10
|
+
from typing import Any, Dict, List, Union
|
|
11
|
+
|
|
12
|
+
from t402.types import (
|
|
13
|
+
PaymentRequirementsV2,
|
|
14
|
+
Network,
|
|
15
|
+
)
|
|
16
|
+
from t402.schemes.interfaces import AssetAmount, SupportedKindDict
|
|
17
|
+
from t402.tron import (
|
|
18
|
+
SCHEME_EXACT,
|
|
19
|
+
DEFAULT_DECIMALS,
|
|
20
|
+
get_network_config,
|
|
21
|
+
get_default_asset,
|
|
22
|
+
get_asset_info,
|
|
23
|
+
normalize_network as tron_normalize_network,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ExactTronServerScheme:
|
|
28
|
+
"""Server scheme for TRON exact payments.
|
|
29
|
+
|
|
30
|
+
Handles parsing user-friendly prices and enhancing payment requirements
|
|
31
|
+
with TRON-specific metadata for clients.
|
|
32
|
+
|
|
33
|
+
Example:
|
|
34
|
+
```python
|
|
35
|
+
scheme = ExactTronServerScheme()
|
|
36
|
+
|
|
37
|
+
# Parse price
|
|
38
|
+
asset_amount = await scheme.parse_price("$0.10", "tron:mainnet")
|
|
39
|
+
# Returns: {"amount": "100000", "asset": "TR7N...", "extra": {...}}
|
|
40
|
+
|
|
41
|
+
# Enhance requirements
|
|
42
|
+
enhanced = await scheme.enhance_requirements(
|
|
43
|
+
requirements,
|
|
44
|
+
supported_kind,
|
|
45
|
+
facilitator_extensions,
|
|
46
|
+
)
|
|
47
|
+
```
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
scheme = SCHEME_EXACT
|
|
51
|
+
caip_family = "tron:*"
|
|
52
|
+
|
|
53
|
+
async def parse_price(
|
|
54
|
+
self,
|
|
55
|
+
price: Union[str, int, float, Dict[str, Any]],
|
|
56
|
+
network: Network,
|
|
57
|
+
) -> AssetAmount:
|
|
58
|
+
"""Parse a user-friendly price to atomic amount and asset.
|
|
59
|
+
|
|
60
|
+
Supports:
|
|
61
|
+
- String with $ prefix: "$0.10" -> 100000 (6 decimals)
|
|
62
|
+
- String without prefix: "0.10" -> 100000
|
|
63
|
+
- Integer/float: 0.10 -> 100000
|
|
64
|
+
- Dict (TokenAmount): {"amount": "100000", "asset": "TR7N..."}
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
price: User-friendly price
|
|
68
|
+
network: Network identifier (CAIP-2 format, e.g., "tron:mainnet")
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
AssetAmount dict with amount, asset, and extra metadata
|
|
72
|
+
"""
|
|
73
|
+
# Normalize network
|
|
74
|
+
network_str = self._normalize_network(network)
|
|
75
|
+
|
|
76
|
+
# Handle dict (already in TokenAmount format)
|
|
77
|
+
if isinstance(price, dict):
|
|
78
|
+
return {
|
|
79
|
+
"amount": str(price.get("amount", "0")),
|
|
80
|
+
"asset": price.get("asset", ""),
|
|
81
|
+
"extra": price.get("extra", {}),
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
# Get default asset (USDT) for the network
|
|
85
|
+
default_asset = get_default_asset(network_str)
|
|
86
|
+
if not default_asset:
|
|
87
|
+
raise ValueError(f"Unsupported TRON network: {network}")
|
|
88
|
+
|
|
89
|
+
asset_address = default_asset["contract_address"]
|
|
90
|
+
decimals = default_asset.get("decimals", DEFAULT_DECIMALS)
|
|
91
|
+
|
|
92
|
+
# Parse price string/number
|
|
93
|
+
if isinstance(price, str):
|
|
94
|
+
if price.startswith("$"):
|
|
95
|
+
price = price[1:]
|
|
96
|
+
amount_decimal = Decimal(price)
|
|
97
|
+
else:
|
|
98
|
+
amount_decimal = Decimal(str(price))
|
|
99
|
+
|
|
100
|
+
# Convert to atomic units
|
|
101
|
+
atomic_amount = int(amount_decimal * Decimal(10 ** decimals))
|
|
102
|
+
|
|
103
|
+
# Build extra metadata
|
|
104
|
+
extra = {
|
|
105
|
+
"symbol": default_asset.get("symbol", "USDT"),
|
|
106
|
+
"name": default_asset.get("name", "Tether USD"),
|
|
107
|
+
"decimals": decimals,
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
"amount": str(atomic_amount),
|
|
112
|
+
"asset": asset_address,
|
|
113
|
+
"extra": extra,
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async def enhance_requirements(
|
|
117
|
+
self,
|
|
118
|
+
requirements: Union[PaymentRequirementsV2, Dict[str, Any]],
|
|
119
|
+
supported_kind: SupportedKindDict,
|
|
120
|
+
facilitator_extensions: List[str],
|
|
121
|
+
) -> Union[PaymentRequirementsV2, Dict[str, Any]]:
|
|
122
|
+
"""Enhance payment requirements with TRON-specific metadata.
|
|
123
|
+
|
|
124
|
+
Adds TRC-20 token metadata to the extra field so clients can
|
|
125
|
+
properly build the transfer transaction.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
requirements: Base payment requirements
|
|
129
|
+
supported_kind: Matched SupportedKind from facilitator
|
|
130
|
+
facilitator_extensions: Extensions supported by facilitator
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
Enhanced requirements with TRON metadata in extra
|
|
134
|
+
"""
|
|
135
|
+
# Convert to dict for modification
|
|
136
|
+
if hasattr(requirements, "model_dump"):
|
|
137
|
+
req = requirements.model_dump(by_alias=True)
|
|
138
|
+
else:
|
|
139
|
+
req = dict(requirements)
|
|
140
|
+
|
|
141
|
+
network = req.get("network", "")
|
|
142
|
+
asset = req.get("asset", "")
|
|
143
|
+
|
|
144
|
+
# Normalize network
|
|
145
|
+
network_str = self._normalize_network(network)
|
|
146
|
+
|
|
147
|
+
# Ensure extra exists
|
|
148
|
+
if "extra" not in req or req["extra"] is None:
|
|
149
|
+
req["extra"] = {}
|
|
150
|
+
|
|
151
|
+
# Add TRC-20 metadata if not present
|
|
152
|
+
asset_info = get_asset_info(network_str, asset)
|
|
153
|
+
if asset_info:
|
|
154
|
+
if "symbol" not in req["extra"]:
|
|
155
|
+
req["extra"]["symbol"] = asset_info.get("symbol", "UNKNOWN")
|
|
156
|
+
if "name" not in req["extra"]:
|
|
157
|
+
req["extra"]["name"] = asset_info.get("name", "Unknown TRC20")
|
|
158
|
+
if "decimals" not in req["extra"]:
|
|
159
|
+
req["extra"]["decimals"] = asset_info.get("decimals", DEFAULT_DECIMALS)
|
|
160
|
+
|
|
161
|
+
# Add network config info
|
|
162
|
+
network_config = get_network_config(network_str)
|
|
163
|
+
if network_config:
|
|
164
|
+
if "endpoint" not in req["extra"]:
|
|
165
|
+
req["extra"]["endpoint"] = network_config.get("endpoint", "")
|
|
166
|
+
|
|
167
|
+
# Add facilitator extra data if available
|
|
168
|
+
if supported_kind.get("extra"):
|
|
169
|
+
for key, value in supported_kind["extra"].items():
|
|
170
|
+
if key not in req["extra"]:
|
|
171
|
+
req["extra"][key] = value
|
|
172
|
+
|
|
173
|
+
return req
|
|
174
|
+
|
|
175
|
+
def _normalize_network(self, network: str) -> str:
|
|
176
|
+
"""Normalize network identifier to CAIP-2 format.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
network: Network identifier
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
Normalized CAIP-2 network string
|
|
183
|
+
|
|
184
|
+
Raises:
|
|
185
|
+
ValueError: If network is not supported
|
|
186
|
+
"""
|
|
187
|
+
# Use the tron module's normalize function
|
|
188
|
+
try:
|
|
189
|
+
return tron_normalize_network(network)
|
|
190
|
+
except ValueError:
|
|
191
|
+
# Re-raise with consistent error message
|
|
192
|
+
raise ValueError(f"Unknown TRON network: {network}")
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""Up-To Payment Scheme.
|
|
2
|
+
|
|
3
|
+
The upto scheme authorizes transfer of up to a maximum amount,
|
|
4
|
+
enabling usage-based billing where the final settlement amount
|
|
5
|
+
is determined by actual usage.
|
|
6
|
+
|
|
7
|
+
This is useful for:
|
|
8
|
+
- AI inference billing (pay per token)
|
|
9
|
+
- Metered API access (pay per request)
|
|
10
|
+
- Streaming services (pay per second/minute)
|
|
11
|
+
- Data transfer (pay per byte)
|
|
12
|
+
|
|
13
|
+
Example:
|
|
14
|
+
```python
|
|
15
|
+
from t402.schemes.upto import (
|
|
16
|
+
UptoPaymentRequirements,
|
|
17
|
+
UptoSettlement,
|
|
18
|
+
create_payment_requirements,
|
|
19
|
+
create_settlement,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
# Server specifies requirements
|
|
23
|
+
requirements = create_payment_requirements(
|
|
24
|
+
network="eip155:8453",
|
|
25
|
+
max_amount="1000000", # $1.00 max
|
|
26
|
+
asset="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
27
|
+
pay_to="0x...",
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
# After service delivery, settle for actual usage
|
|
31
|
+
settlement = create_settlement(
|
|
32
|
+
settle_amount="150000", # $0.15 actual
|
|
33
|
+
units_consumed=1500,
|
|
34
|
+
unit_price="100",
|
|
35
|
+
unit_type="token",
|
|
36
|
+
)
|
|
37
|
+
```
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
from t402.schemes.upto.types import (
|
|
41
|
+
# Constants
|
|
42
|
+
SCHEME_UPTO,
|
|
43
|
+
DEFAULT_MIN_AMOUNT,
|
|
44
|
+
DEFAULT_MAX_TIMEOUT_SECONDS,
|
|
45
|
+
SUPPORTED_UNITS,
|
|
46
|
+
# Models
|
|
47
|
+
UptoExtra,
|
|
48
|
+
UptoPaymentRequirements,
|
|
49
|
+
UptoUsageDetails,
|
|
50
|
+
UptoSettlement,
|
|
51
|
+
UptoSettlementResponse,
|
|
52
|
+
UptoValidationResult,
|
|
53
|
+
# Type guards
|
|
54
|
+
is_upto_payment_requirements,
|
|
55
|
+
is_valid_unit,
|
|
56
|
+
# Factory functions
|
|
57
|
+
create_payment_requirements,
|
|
58
|
+
create_settlement,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
__all__ = [
|
|
62
|
+
# Constants
|
|
63
|
+
"SCHEME_UPTO",
|
|
64
|
+
"DEFAULT_MIN_AMOUNT",
|
|
65
|
+
"DEFAULT_MAX_TIMEOUT_SECONDS",
|
|
66
|
+
"SUPPORTED_UNITS",
|
|
67
|
+
# Models
|
|
68
|
+
"UptoExtra",
|
|
69
|
+
"UptoPaymentRequirements",
|
|
70
|
+
"UptoUsageDetails",
|
|
71
|
+
"UptoSettlement",
|
|
72
|
+
"UptoSettlementResponse",
|
|
73
|
+
"UptoValidationResult",
|
|
74
|
+
# Type guards
|
|
75
|
+
"is_upto_payment_requirements",
|
|
76
|
+
"is_valid_unit",
|
|
77
|
+
# Factory functions
|
|
78
|
+
"create_payment_requirements",
|
|
79
|
+
"create_settlement",
|
|
80
|
+
]
|