t402 1.9.0__py3-none-any.whl → 1.10.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.
Files changed (134) hide show
  1. t402/__init__.py +2 -1
  2. t402/a2a/__init__.py +73 -0
  3. t402/a2a/helpers.py +158 -0
  4. t402/a2a/types.py +145 -0
  5. t402/bridge/client.py +13 -5
  6. t402/bridge/constants.py +4 -2
  7. t402/bridge/router.py +1 -1
  8. t402/bridge/scan.py +3 -1
  9. t402/chains.py +268 -1
  10. t402/cli.py +31 -9
  11. t402/common.py +2 -0
  12. t402/cosmos_paywall_template.py +2 -0
  13. t402/django/__init__.py +42 -0
  14. t402/django/middleware.py +596 -0
  15. t402/encoding.py +9 -3
  16. t402/erc4337/accounts.py +56 -51
  17. t402/erc4337/bundlers.py +105 -99
  18. t402/erc4337/paymasters.py +100 -109
  19. t402/erc4337/types.py +39 -26
  20. t402/errors.py +213 -0
  21. t402/evm_paywall_template.py +1 -1
  22. t402/facilitator.py +125 -0
  23. t402/fastapi/middleware.py +1 -3
  24. t402/mcp/constants.py +3 -6
  25. t402/mcp/server.py +501 -84
  26. t402/mcp/web3_utils.py +493 -0
  27. t402/multisig/__init__.py +120 -0
  28. t402/multisig/constants.py +54 -0
  29. t402/multisig/safe.py +441 -0
  30. t402/multisig/signature.py +228 -0
  31. t402/multisig/transaction.py +238 -0
  32. t402/multisig/types.py +108 -0
  33. t402/multisig/utils.py +77 -0
  34. t402/near_paywall_template.py +2 -0
  35. t402/networks.py +34 -1
  36. t402/paywall.py +1 -3
  37. t402/schemes/__init__.py +143 -0
  38. t402/schemes/aptos/__init__.py +70 -0
  39. t402/schemes/aptos/constants.py +349 -0
  40. t402/schemes/aptos/exact_direct/__init__.py +44 -0
  41. t402/schemes/aptos/exact_direct/client.py +202 -0
  42. t402/schemes/aptos/exact_direct/facilitator.py +426 -0
  43. t402/schemes/aptos/exact_direct/server.py +272 -0
  44. t402/schemes/aptos/types.py +237 -0
  45. t402/schemes/cosmos/__init__.py +114 -0
  46. t402/schemes/cosmos/constants.py +211 -0
  47. t402/schemes/cosmos/exact_direct/__init__.py +21 -0
  48. t402/schemes/cosmos/exact_direct/client.py +198 -0
  49. t402/schemes/cosmos/exact_direct/facilitator.py +493 -0
  50. t402/schemes/cosmos/exact_direct/server.py +315 -0
  51. t402/schemes/cosmos/types.py +501 -0
  52. t402/schemes/evm/__init__.py +46 -1
  53. t402/schemes/evm/exact/__init__.py +11 -0
  54. t402/schemes/evm/exact/client.py +3 -1
  55. t402/schemes/evm/exact/facilitator.py +894 -0
  56. t402/schemes/evm/exact/server.py +1 -1
  57. t402/schemes/evm/exact_legacy/__init__.py +38 -0
  58. t402/schemes/evm/exact_legacy/client.py +291 -0
  59. t402/schemes/evm/exact_legacy/facilitator.py +777 -0
  60. t402/schemes/evm/exact_legacy/server.py +231 -0
  61. t402/schemes/evm/upto/__init__.py +12 -0
  62. t402/schemes/evm/upto/client.py +6 -2
  63. t402/schemes/evm/upto/facilitator.py +625 -0
  64. t402/schemes/evm/upto/server.py +243 -0
  65. t402/schemes/evm/upto/types.py +3 -1
  66. t402/schemes/interfaces.py +6 -2
  67. t402/schemes/near/__init__.py +137 -0
  68. t402/schemes/near/constants.py +189 -0
  69. t402/schemes/near/exact_direct/__init__.py +21 -0
  70. t402/schemes/near/exact_direct/client.py +204 -0
  71. t402/schemes/near/exact_direct/facilitator.py +455 -0
  72. t402/schemes/near/exact_direct/server.py +303 -0
  73. t402/schemes/near/types.py +419 -0
  74. t402/schemes/near/upto/__init__.py +54 -0
  75. t402/schemes/near/upto/types.py +272 -0
  76. t402/schemes/polkadot/__init__.py +72 -0
  77. t402/schemes/polkadot/constants.py +155 -0
  78. t402/schemes/polkadot/exact_direct/__init__.py +43 -0
  79. t402/schemes/polkadot/exact_direct/client.py +235 -0
  80. t402/schemes/polkadot/exact_direct/facilitator.py +428 -0
  81. t402/schemes/polkadot/exact_direct/server.py +292 -0
  82. t402/schemes/polkadot/types.py +385 -0
  83. t402/schemes/registry.py +6 -2
  84. t402/schemes/stacks/__init__.py +68 -0
  85. t402/schemes/stacks/constants.py +122 -0
  86. t402/schemes/stacks/exact_direct/__init__.py +43 -0
  87. t402/schemes/stacks/exact_direct/client.py +222 -0
  88. t402/schemes/stacks/exact_direct/facilitator.py +424 -0
  89. t402/schemes/stacks/exact_direct/server.py +292 -0
  90. t402/schemes/stacks/types.py +380 -0
  91. t402/schemes/svm/__init__.py +44 -0
  92. t402/schemes/svm/exact/__init__.py +35 -0
  93. t402/schemes/svm/exact/client.py +23 -0
  94. t402/schemes/svm/exact/facilitator.py +24 -0
  95. t402/schemes/svm/exact/server.py +20 -0
  96. t402/schemes/svm/upto/__init__.py +23 -0
  97. t402/schemes/svm/upto/types.py +193 -0
  98. t402/schemes/tezos/__init__.py +84 -0
  99. t402/schemes/tezos/constants.py +372 -0
  100. t402/schemes/tezos/exact_direct/__init__.py +22 -0
  101. t402/schemes/tezos/exact_direct/client.py +226 -0
  102. t402/schemes/tezos/exact_direct/facilitator.py +491 -0
  103. t402/schemes/tezos/exact_direct/server.py +277 -0
  104. t402/schemes/tezos/types.py +220 -0
  105. t402/schemes/ton/__init__.py +24 -2
  106. t402/schemes/ton/exact/__init__.py +7 -0
  107. t402/schemes/ton/exact/facilitator.py +730 -0
  108. t402/schemes/ton/exact/server.py +1 -1
  109. t402/schemes/ton/upto/__init__.py +31 -0
  110. t402/schemes/ton/upto/types.py +215 -0
  111. t402/schemes/tron/__init__.py +28 -2
  112. t402/schemes/tron/exact/__init__.py +9 -0
  113. t402/schemes/tron/exact/facilitator.py +673 -0
  114. t402/schemes/tron/exact/server.py +1 -1
  115. t402/schemes/tron/upto/__init__.py +30 -0
  116. t402/schemes/tron/upto/types.py +213 -0
  117. t402/stacks_paywall_template.py +2 -0
  118. t402/starlette/__init__.py +38 -0
  119. t402/starlette/middleware.py +522 -0
  120. t402/svm.py +45 -11
  121. t402/svm_paywall_template.py +1 -1
  122. t402/ton.py +6 -2
  123. t402/ton_paywall_template.py +1 -192
  124. t402/tron.py +2 -0
  125. t402/tron_paywall_template.py +2 -0
  126. t402/types.py +103 -3
  127. t402/wdk/chains.py +1 -1
  128. t402/wdk/errors.py +15 -5
  129. t402/wdk/signer.py +11 -2
  130. {t402-1.9.0.dist-info → t402-1.10.0.dist-info}/METADATA +42 -1
  131. t402-1.10.0.dist-info/RECORD +156 -0
  132. t402-1.9.0.dist-info/RECORD +0 -72
  133. {t402-1.9.0.dist-info → t402-1.10.0.dist-info}/WHEEL +0 -0
  134. {t402-1.9.0.dist-info → t402-1.10.0.dist-info}/entry_points.txt +0 -0
@@ -99,7 +99,7 @@ class ExactTonServerScheme:
99
99
  amount_decimal = Decimal(str(price))
100
100
 
101
101
  # Convert to atomic units
102
- atomic_amount = int(amount_decimal * Decimal(10 ** decimals))
102
+ atomic_amount = int(amount_decimal * Decimal(10**decimals))
103
103
 
104
104
  # Build extra metadata
105
105
  extra = {
@@ -0,0 +1,31 @@
1
+ """TON Up-To Payment Scheme.
2
+
3
+ This package provides types for the upto payment scheme on TON blockchain.
4
+
5
+ The upto scheme uses an escrow pattern:
6
+ 1. Client signs a transfer of maxAmount to the facilitator's holding address
7
+ 2. Facilitator broadcasts the transfer, then sends settleAmount to payTo
8
+ and refunds (maxAmount - settleAmount) back to the client.
9
+ """
10
+
11
+ from t402.schemes.ton.upto.types import (
12
+ # Models
13
+ UptoTonAuthorization,
14
+ UptoTonPayload,
15
+ UptoTonExtra,
16
+ # Type guards
17
+ is_upto_ton_payload,
18
+ # Helper functions
19
+ upto_payload_from_dict,
20
+ )
21
+
22
+ __all__ = [
23
+ # Types
24
+ "UptoTonAuthorization",
25
+ "UptoTonPayload",
26
+ "UptoTonExtra",
27
+ # Type guards
28
+ "is_upto_ton_payload",
29
+ # Helper functions
30
+ "upto_payload_from_dict",
31
+ ]
@@ -0,0 +1,215 @@
1
+ """TON Up-To Scheme Types.
2
+
3
+ TON-specific types for the up-to payment scheme using an escrow pattern.
4
+ The client transfers maxAmount to the facilitator's holding address,
5
+ and the facilitator forwards settleAmount to payTo and refunds the rest.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from typing import Any, Dict, Optional
11
+ from pydantic import BaseModel, ConfigDict, Field
12
+ from pydantic.alias_generators import to_camel
13
+
14
+
15
+ class UptoTonAuthorization(BaseModel):
16
+ """TON upto authorization metadata.
17
+
18
+ Contains all parameters for verifying the signed transfer message.
19
+ """
20
+
21
+ from_address: str = Field(
22
+ alias="from",
23
+ description="Sender wallet address (friendly format, bounceable)",
24
+ )
25
+ facilitator: str = Field(
26
+ description="Facilitator holding address that receives the initial transfer",
27
+ )
28
+ jetton_master: str = Field(
29
+ alias="jettonMaster",
30
+ description="Jetton master contract address",
31
+ )
32
+ max_amount: str = Field(
33
+ alias="maxAmount",
34
+ description="Maximum authorized amount in smallest units",
35
+ )
36
+ ton_amount: str = Field(
37
+ alias="tonAmount",
38
+ description="Gas amount in nanoTON",
39
+ )
40
+ valid_until: int = Field(
41
+ alias="validUntil",
42
+ description="Unix timestamp (seconds) until which the message is valid",
43
+ )
44
+ seqno: int = Field(
45
+ description="Wallet sequence number for replay protection",
46
+ )
47
+ query_id: str = Field(
48
+ alias="queryId",
49
+ description="Unique message ID (as string for large numbers)",
50
+ )
51
+
52
+ model_config = ConfigDict(
53
+ alias_generator=to_camel,
54
+ populate_by_name=True,
55
+ from_attributes=True,
56
+ )
57
+
58
+
59
+ class UptoTonPayload(BaseModel):
60
+ """TON upto payment payload.
61
+
62
+ Contains a signed transfer message to the facilitator's holding address.
63
+ The facilitator broadcasts the transfer, then forwards settleAmount to payTo
64
+ and refunds (maxAmount - settleAmount) back to the client.
65
+ """
66
+
67
+ signed_boc: str = Field(
68
+ alias="signedBoc",
69
+ description="Base64 encoded signed external message (BOC format)",
70
+ )
71
+ authorization: UptoTonAuthorization = Field(
72
+ description="Transfer authorization metadata for verification",
73
+ )
74
+ payment_nonce: str = Field(
75
+ alias="paymentNonce",
76
+ description="Unique nonce for replay protection (hex string)",
77
+ )
78
+
79
+ model_config = ConfigDict(
80
+ alias_generator=to_camel,
81
+ populate_by_name=True,
82
+ from_attributes=True,
83
+ )
84
+
85
+ def to_dict(self) -> Dict[str, Any]:
86
+ """Convert to dictionary for JSON serialization.
87
+
88
+ Returns:
89
+ Dictionary with camelCase keys matching the wire format.
90
+ """
91
+ return {
92
+ "signedBoc": self.signed_boc,
93
+ "authorization": {
94
+ "from": self.authorization.from_address,
95
+ "facilitator": self.authorization.facilitator,
96
+ "jettonMaster": self.authorization.jetton_master,
97
+ "maxAmount": self.authorization.max_amount,
98
+ "tonAmount": self.authorization.ton_amount,
99
+ "validUntil": self.authorization.valid_until,
100
+ "seqno": self.authorization.seqno,
101
+ "queryId": self.authorization.query_id,
102
+ },
103
+ "paymentNonce": self.payment_nonce,
104
+ }
105
+
106
+
107
+ class UptoTonExtra(BaseModel):
108
+ """TON-specific extra fields for the upto scheme.
109
+
110
+ Included in PaymentRequirements.extra to provide upto-specific parameters.
111
+ """
112
+
113
+ facilitator: Optional[str] = Field(
114
+ default=None,
115
+ description="Facilitator address that will receive the initial transfer",
116
+ )
117
+ max_amount: Optional[str] = Field(
118
+ default=None,
119
+ alias="maxAmount",
120
+ description="Maximum payment amount authorized",
121
+ )
122
+ min_amount: Optional[str] = Field(
123
+ default=None,
124
+ alias="minAmount",
125
+ description="Minimum acceptable settlement amount",
126
+ )
127
+ unit: Optional[str] = Field(
128
+ default=None,
129
+ description="Billing unit (e.g., 'token', 'request', 'second')",
130
+ )
131
+ unit_price: Optional[str] = Field(
132
+ default=None,
133
+ alias="unitPrice",
134
+ description="Price per unit in smallest denomination",
135
+ )
136
+
137
+ model_config = ConfigDict(
138
+ alias_generator=to_camel,
139
+ populate_by_name=True,
140
+ from_attributes=True,
141
+ )
142
+
143
+
144
+ def is_upto_ton_payload(data: Any) -> bool:
145
+ """Check if the given data represents a TON upto payload.
146
+
147
+ Validates the presence and types of required fields including signedBoc,
148
+ authorization (with from, facilitator, jettonMaster, maxAmount), and paymentNonce.
149
+
150
+ Args:
151
+ data: Dictionary or object to check.
152
+
153
+ Returns:
154
+ True if data has the correct TON upto payload structure.
155
+ """
156
+ if not isinstance(data, dict):
157
+ return False
158
+
159
+ signed_boc = data.get("signedBoc")
160
+ payment_nonce = data.get("paymentNonce")
161
+ auth = data.get("authorization")
162
+
163
+ if not signed_boc or not isinstance(signed_boc, str):
164
+ return False
165
+ if not payment_nonce or not isinstance(payment_nonce, str):
166
+ return False
167
+
168
+ if not auth or not isinstance(auth, dict):
169
+ return False
170
+
171
+ # Check required authorization fields
172
+ required_str_fields = ["from", "facilitator", "jettonMaster", "maxAmount", "tonAmount", "queryId"]
173
+ for field in required_str_fields:
174
+ val = auth.get(field)
175
+ if not isinstance(val, str):
176
+ return False
177
+
178
+ # from and facilitator must not be empty
179
+ if not auth.get("from") or not auth.get("facilitator"):
180
+ return False
181
+
182
+ # Check numeric fields
183
+ if not isinstance(auth.get("validUntil"), (int, float)):
184
+ return False
185
+ if not isinstance(auth.get("seqno"), (int, float)):
186
+ return False
187
+
188
+ return True
189
+
190
+
191
+ def upto_payload_from_dict(data: Dict[str, Any]) -> UptoTonPayload:
192
+ """Create an UptoTonPayload from a dictionary.
193
+
194
+ Args:
195
+ data: Dictionary containing payload data with camelCase keys.
196
+
197
+ Returns:
198
+ UptoTonPayload instance.
199
+ """
200
+ auth_data = data.get("authorization", {})
201
+
202
+ return UptoTonPayload(
203
+ signed_boc=data.get("signedBoc", ""),
204
+ authorization=UptoTonAuthorization(
205
+ from_address=auth_data.get("from", ""),
206
+ facilitator=auth_data.get("facilitator", ""),
207
+ jetton_master=auth_data.get("jettonMaster", ""),
208
+ max_amount=auth_data.get("maxAmount", ""),
209
+ ton_amount=auth_data.get("tonAmount", ""),
210
+ valid_until=auth_data.get("validUntil", 0),
211
+ seqno=auth_data.get("seqno", 0),
212
+ query_id=auth_data.get("queryId", ""),
213
+ ),
214
+ payment_nonce=data.get("paymentNonce", ""),
215
+ )
@@ -4,19 +4,45 @@ This package provides payment scheme implementations for TRON blockchain.
4
4
 
5
5
  Supported schemes:
6
6
  - exact: TRC-20 token transfers with signed transactions
7
+ - upto: TRC-20 approve + transferFrom for authorized maximum-amount payments
7
8
  """
8
9
 
9
10
  from t402.schemes.tron.exact import (
10
11
  ExactTronClientScheme,
11
12
  ExactTronServerScheme,
13
+ ExactTronFacilitatorScheme,
14
+ ExactTronFacilitatorConfig,
12
15
  TronSigner,
16
+ FacilitatorTronSigner,
13
17
  SCHEME_EXACT,
14
18
  )
15
19
 
20
+ from t402.schemes.tron.upto import (
21
+ UptoTronAuthorization,
22
+ UptoTronPayload,
23
+ UptoTronExtra,
24
+ is_upto_tron_payload,
25
+ upto_payload_from_dict,
26
+ )
27
+
16
28
  __all__ = [
17
- # Exact scheme
29
+ # Exact - Client
18
30
  "ExactTronClientScheme",
19
- "ExactTronServerScheme",
20
31
  "TronSigner",
32
+ # Exact - Server
33
+ "ExactTronServerScheme",
34
+ # Exact - Facilitator
35
+ "ExactTronFacilitatorScheme",
36
+ "ExactTronFacilitatorConfig",
37
+ "FacilitatorTronSigner",
38
+ # Exact - Constants
21
39
  "SCHEME_EXACT",
40
+ # Upto - Types
41
+ "UptoTronAuthorization",
42
+ "UptoTronPayload",
43
+ "UptoTronExtra",
44
+ # Upto - Type guards
45
+ "is_upto_tron_payload",
46
+ # Upto - Helpers
47
+ "upto_payload_from_dict",
22
48
  ]
@@ -15,6 +15,11 @@ from t402.schemes.tron.exact.client import (
15
15
  from t402.schemes.tron.exact.server import (
16
16
  ExactTronServerScheme,
17
17
  )
18
+ from t402.schemes.tron.exact.facilitator import (
19
+ ExactTronFacilitatorScheme,
20
+ ExactTronFacilitatorConfig,
21
+ FacilitatorTronSigner,
22
+ )
18
23
 
19
24
  __all__ = [
20
25
  # Client
@@ -22,6 +27,10 @@ __all__ = [
22
27
  "TronSigner",
23
28
  # Server
24
29
  "ExactTronServerScheme",
30
+ # Facilitator
31
+ "ExactTronFacilitatorScheme",
32
+ "ExactTronFacilitatorConfig",
33
+ "FacilitatorTronSigner",
25
34
  # Constants
26
35
  "SCHEME_EXACT",
27
36
  ]