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.
- t402/__init__.py +2 -1
- t402/a2a/__init__.py +73 -0
- t402/a2a/helpers.py +158 -0
- t402/a2a/types.py +145 -0
- t402/bridge/client.py +13 -5
- t402/bridge/constants.py +4 -2
- t402/bridge/router.py +1 -1
- t402/bridge/scan.py +3 -1
- t402/chains.py +268 -1
- t402/cli.py +31 -9
- t402/common.py +2 -0
- t402/cosmos_paywall_template.py +2 -0
- t402/django/__init__.py +42 -0
- t402/django/middleware.py +596 -0
- t402/encoding.py +9 -3
- t402/erc4337/accounts.py +56 -51
- t402/erc4337/bundlers.py +105 -99
- t402/erc4337/paymasters.py +100 -109
- t402/erc4337/types.py +39 -26
- t402/errors.py +213 -0
- t402/evm_paywall_template.py +1 -1
- t402/facilitator.py +125 -0
- t402/fastapi/middleware.py +1 -3
- t402/mcp/constants.py +3 -6
- t402/mcp/server.py +501 -84
- t402/mcp/web3_utils.py +493 -0
- t402/multisig/__init__.py +120 -0
- t402/multisig/constants.py +54 -0
- t402/multisig/safe.py +441 -0
- t402/multisig/signature.py +228 -0
- t402/multisig/transaction.py +238 -0
- t402/multisig/types.py +108 -0
- t402/multisig/utils.py +77 -0
- t402/near_paywall_template.py +2 -0
- t402/networks.py +34 -1
- t402/paywall.py +1 -3
- t402/schemes/__init__.py +143 -0
- t402/schemes/aptos/__init__.py +70 -0
- t402/schemes/aptos/constants.py +349 -0
- t402/schemes/aptos/exact_direct/__init__.py +44 -0
- t402/schemes/aptos/exact_direct/client.py +202 -0
- t402/schemes/aptos/exact_direct/facilitator.py +426 -0
- t402/schemes/aptos/exact_direct/server.py +272 -0
- t402/schemes/aptos/types.py +237 -0
- t402/schemes/cosmos/__init__.py +114 -0
- t402/schemes/cosmos/constants.py +211 -0
- t402/schemes/cosmos/exact_direct/__init__.py +21 -0
- t402/schemes/cosmos/exact_direct/client.py +198 -0
- t402/schemes/cosmos/exact_direct/facilitator.py +493 -0
- t402/schemes/cosmos/exact_direct/server.py +315 -0
- t402/schemes/cosmos/types.py +501 -0
- t402/schemes/evm/__init__.py +46 -1
- t402/schemes/evm/exact/__init__.py +11 -0
- t402/schemes/evm/exact/client.py +3 -1
- t402/schemes/evm/exact/facilitator.py +894 -0
- t402/schemes/evm/exact/server.py +1 -1
- t402/schemes/evm/exact_legacy/__init__.py +38 -0
- t402/schemes/evm/exact_legacy/client.py +291 -0
- t402/schemes/evm/exact_legacy/facilitator.py +777 -0
- t402/schemes/evm/exact_legacy/server.py +231 -0
- t402/schemes/evm/upto/__init__.py +12 -0
- t402/schemes/evm/upto/client.py +6 -2
- t402/schemes/evm/upto/facilitator.py +625 -0
- t402/schemes/evm/upto/server.py +243 -0
- t402/schemes/evm/upto/types.py +3 -1
- t402/schemes/interfaces.py +6 -2
- t402/schemes/near/__init__.py +137 -0
- t402/schemes/near/constants.py +189 -0
- t402/schemes/near/exact_direct/__init__.py +21 -0
- t402/schemes/near/exact_direct/client.py +204 -0
- t402/schemes/near/exact_direct/facilitator.py +455 -0
- t402/schemes/near/exact_direct/server.py +303 -0
- t402/schemes/near/types.py +419 -0
- t402/schemes/near/upto/__init__.py +54 -0
- t402/schemes/near/upto/types.py +272 -0
- t402/schemes/polkadot/__init__.py +72 -0
- t402/schemes/polkadot/constants.py +155 -0
- t402/schemes/polkadot/exact_direct/__init__.py +43 -0
- t402/schemes/polkadot/exact_direct/client.py +235 -0
- t402/schemes/polkadot/exact_direct/facilitator.py +428 -0
- t402/schemes/polkadot/exact_direct/server.py +292 -0
- t402/schemes/polkadot/types.py +385 -0
- t402/schemes/registry.py +6 -2
- t402/schemes/stacks/__init__.py +68 -0
- t402/schemes/stacks/constants.py +122 -0
- t402/schemes/stacks/exact_direct/__init__.py +43 -0
- t402/schemes/stacks/exact_direct/client.py +222 -0
- t402/schemes/stacks/exact_direct/facilitator.py +424 -0
- t402/schemes/stacks/exact_direct/server.py +292 -0
- t402/schemes/stacks/types.py +380 -0
- t402/schemes/svm/__init__.py +44 -0
- t402/schemes/svm/exact/__init__.py +35 -0
- t402/schemes/svm/exact/client.py +23 -0
- t402/schemes/svm/exact/facilitator.py +24 -0
- t402/schemes/svm/exact/server.py +20 -0
- t402/schemes/svm/upto/__init__.py +23 -0
- t402/schemes/svm/upto/types.py +193 -0
- t402/schemes/tezos/__init__.py +84 -0
- t402/schemes/tezos/constants.py +372 -0
- t402/schemes/tezos/exact_direct/__init__.py +22 -0
- t402/schemes/tezos/exact_direct/client.py +226 -0
- t402/schemes/tezos/exact_direct/facilitator.py +491 -0
- t402/schemes/tezos/exact_direct/server.py +277 -0
- t402/schemes/tezos/types.py +220 -0
- t402/schemes/ton/__init__.py +24 -2
- t402/schemes/ton/exact/__init__.py +7 -0
- t402/schemes/ton/exact/facilitator.py +730 -0
- t402/schemes/ton/exact/server.py +1 -1
- t402/schemes/ton/upto/__init__.py +31 -0
- t402/schemes/ton/upto/types.py +215 -0
- t402/schemes/tron/__init__.py +28 -2
- t402/schemes/tron/exact/__init__.py +9 -0
- t402/schemes/tron/exact/facilitator.py +673 -0
- t402/schemes/tron/exact/server.py +1 -1
- t402/schemes/tron/upto/__init__.py +30 -0
- t402/schemes/tron/upto/types.py +213 -0
- t402/stacks_paywall_template.py +2 -0
- t402/starlette/__init__.py +38 -0
- t402/starlette/middleware.py +522 -0
- t402/svm.py +45 -11
- t402/svm_paywall_template.py +1 -1
- t402/ton.py +6 -2
- t402/ton_paywall_template.py +1 -192
- t402/tron.py +2 -0
- t402/tron_paywall_template.py +2 -0
- t402/types.py +103 -3
- t402/wdk/chains.py +1 -1
- t402/wdk/errors.py +15 -5
- t402/wdk/signer.py +11 -2
- {t402-1.9.0.dist-info → t402-1.10.0.dist-info}/METADATA +42 -1
- t402-1.10.0.dist-info/RECORD +156 -0
- t402-1.9.0.dist-info/RECORD +0 -72
- {t402-1.9.0.dist-info → t402-1.10.0.dist-info}/WHEEL +0 -0
- {t402-1.9.0.dist-info → t402-1.10.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
"""NEAR Up-To Scheme Types.
|
|
2
|
+
|
|
3
|
+
NEAR-specific types for the up-to payment scheme using an escrow pattern.
|
|
4
|
+
Since NEAR NEP-141 tokens don't have native approve/transferFrom, the client
|
|
5
|
+
ft_transfers maxAmount to the facilitator, who then forwards settleAmount
|
|
6
|
+
to the payTo address and refunds the rest.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import Any, Dict, Optional
|
|
12
|
+
|
|
13
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
14
|
+
from pydantic.alias_generators import to_camel
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class UptoNearAuthorization(BaseModel):
|
|
18
|
+
"""Authorization metadata for NEAR upto payments.
|
|
19
|
+
|
|
20
|
+
Contains the transfer details needed for verification.
|
|
21
|
+
|
|
22
|
+
Attributes:
|
|
23
|
+
from_account: Sender's NEAR account ID.
|
|
24
|
+
facilitator: Facilitator's NEAR account ID that receives the transfer.
|
|
25
|
+
token_contract: NEP-141 token contract ID.
|
|
26
|
+
max_amount: Maximum authorized amount in smallest units (as string).
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
from_account: str = Field(alias="from", description="Sender's NEAR account ID")
|
|
30
|
+
facilitator: str = Field(description="Facilitator's NEAR account ID")
|
|
31
|
+
token_contract: str = Field(
|
|
32
|
+
alias="tokenContract",
|
|
33
|
+
description="NEP-141 token contract ID",
|
|
34
|
+
)
|
|
35
|
+
max_amount: str = Field(
|
|
36
|
+
alias="maxAmount",
|
|
37
|
+
description="Maximum authorized amount in smallest units",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
model_config = ConfigDict(
|
|
41
|
+
alias_generator=to_camel,
|
|
42
|
+
populate_by_name=True,
|
|
43
|
+
from_attributes=True,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class UptoNearPayload(BaseModel):
|
|
48
|
+
"""NEAR upto payment payload.
|
|
49
|
+
|
|
50
|
+
Contains the transaction hash of the client's transfer to the facilitator,
|
|
51
|
+
along with authorization metadata for verification.
|
|
52
|
+
|
|
53
|
+
Attributes:
|
|
54
|
+
tx_hash: NEAR transaction hash of the transfer to facilitator.
|
|
55
|
+
authorization: Authorization metadata for verification.
|
|
56
|
+
payment_nonce: Unique nonce for replay protection (hex string).
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
tx_hash: str = Field(
|
|
60
|
+
alias="txHash",
|
|
61
|
+
description="NEAR transaction hash of the transfer to facilitator",
|
|
62
|
+
)
|
|
63
|
+
authorization: UptoNearAuthorization = Field(
|
|
64
|
+
description="Authorization metadata for verification",
|
|
65
|
+
)
|
|
66
|
+
payment_nonce: str = Field(
|
|
67
|
+
alias="paymentNonce",
|
|
68
|
+
description="Unique nonce for replay protection (hex string)",
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
model_config = ConfigDict(
|
|
72
|
+
alias_generator=to_camel,
|
|
73
|
+
populate_by_name=True,
|
|
74
|
+
from_attributes=True,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
78
|
+
"""Convert to dictionary for JSON serialization.
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
Dict with camelCase keys matching the Go/TypeScript field names.
|
|
82
|
+
"""
|
|
83
|
+
return {
|
|
84
|
+
"txHash": self.tx_hash,
|
|
85
|
+
"authorization": {
|
|
86
|
+
"from": self.authorization.from_account,
|
|
87
|
+
"facilitator": self.authorization.facilitator,
|
|
88
|
+
"tokenContract": self.authorization.token_contract,
|
|
89
|
+
"maxAmount": self.authorization.max_amount,
|
|
90
|
+
},
|
|
91
|
+
"paymentNonce": self.payment_nonce,
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class UptoNearExtra(BaseModel):
|
|
96
|
+
"""NEAR-specific extra fields for the upto scheme.
|
|
97
|
+
|
|
98
|
+
Included in the PaymentRequirements.extra field to provide
|
|
99
|
+
additional parameters needed for the upto payment flow.
|
|
100
|
+
|
|
101
|
+
Attributes:
|
|
102
|
+
facilitator: Facilitator account ID that will receive the initial transfer.
|
|
103
|
+
max_amount: Maximum payment amount authorized.
|
|
104
|
+
min_amount: Minimum acceptable settlement amount.
|
|
105
|
+
unit: Billing unit (e.g., "token", "request", "second").
|
|
106
|
+
unit_price: Price per unit in smallest denomination.
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
facilitator: Optional[str] = Field(
|
|
110
|
+
default=None,
|
|
111
|
+
description="Facilitator account ID that will receive the initial transfer",
|
|
112
|
+
)
|
|
113
|
+
max_amount: Optional[str] = Field(
|
|
114
|
+
default=None,
|
|
115
|
+
alias="maxAmount",
|
|
116
|
+
description="Maximum payment amount authorized",
|
|
117
|
+
)
|
|
118
|
+
min_amount: Optional[str] = Field(
|
|
119
|
+
default=None,
|
|
120
|
+
alias="minAmount",
|
|
121
|
+
description="Minimum acceptable settlement amount",
|
|
122
|
+
)
|
|
123
|
+
unit: Optional[str] = Field(
|
|
124
|
+
default=None,
|
|
125
|
+
description="Billing unit (e.g., 'token', 'request', 'second')",
|
|
126
|
+
)
|
|
127
|
+
unit_price: Optional[str] = Field(
|
|
128
|
+
default=None,
|
|
129
|
+
alias="unitPrice",
|
|
130
|
+
description="Price per unit in smallest denomination",
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
model_config = ConfigDict(
|
|
134
|
+
alias_generator=to_camel,
|
|
135
|
+
populate_by_name=True,
|
|
136
|
+
from_attributes=True,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class UptoNearUsageDetails(BaseModel):
|
|
141
|
+
"""Usage details for NEAR upto settlement.
|
|
142
|
+
|
|
143
|
+
Attributes:
|
|
144
|
+
units_consumed: Number of units consumed.
|
|
145
|
+
unit_price: Price per unit used.
|
|
146
|
+
unit_type: Type of unit.
|
|
147
|
+
start_time: Start timestamp.
|
|
148
|
+
end_time: End timestamp.
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
units_consumed: Optional[int] = Field(
|
|
152
|
+
default=None,
|
|
153
|
+
alias="unitsConsumed",
|
|
154
|
+
description="Number of units consumed",
|
|
155
|
+
)
|
|
156
|
+
unit_price: Optional[str] = Field(
|
|
157
|
+
default=None,
|
|
158
|
+
alias="unitPrice",
|
|
159
|
+
description="Price per unit used",
|
|
160
|
+
)
|
|
161
|
+
unit_type: Optional[str] = Field(
|
|
162
|
+
default=None,
|
|
163
|
+
alias="unitType",
|
|
164
|
+
description="Type of unit",
|
|
165
|
+
)
|
|
166
|
+
start_time: Optional[int] = Field(
|
|
167
|
+
default=None,
|
|
168
|
+
alias="startTime",
|
|
169
|
+
description="Start timestamp",
|
|
170
|
+
)
|
|
171
|
+
end_time: Optional[int] = Field(
|
|
172
|
+
default=None,
|
|
173
|
+
alias="endTime",
|
|
174
|
+
description="End timestamp",
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
model_config = ConfigDict(
|
|
178
|
+
alias_generator=to_camel,
|
|
179
|
+
populate_by_name=True,
|
|
180
|
+
from_attributes=True,
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class UptoNearSettlement(BaseModel):
|
|
185
|
+
"""NEAR-specific settlement request for the upto scheme.
|
|
186
|
+
|
|
187
|
+
Attributes:
|
|
188
|
+
settle_amount: Actual amount to settle (must be <= maxAmount).
|
|
189
|
+
usage_details: Optional usage information for auditing.
|
|
190
|
+
"""
|
|
191
|
+
|
|
192
|
+
settle_amount: str = Field(
|
|
193
|
+
alias="settleAmount",
|
|
194
|
+
description="Actual amount to settle",
|
|
195
|
+
)
|
|
196
|
+
usage_details: Optional[UptoNearUsageDetails] = Field(
|
|
197
|
+
default=None,
|
|
198
|
+
alias="usageDetails",
|
|
199
|
+
description="Optional usage information",
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
model_config = ConfigDict(
|
|
203
|
+
alias_generator=to_camel,
|
|
204
|
+
populate_by_name=True,
|
|
205
|
+
from_attributes=True,
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def is_upto_near_payload(data: Dict[str, Any]) -> bool:
|
|
210
|
+
"""Check if the given data represents a NEAR upto payload.
|
|
211
|
+
|
|
212
|
+
Distinguishes upto payloads from exact-direct payloads by checking
|
|
213
|
+
for the authorization structure with facilitator field.
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
data: Dictionary to check.
|
|
217
|
+
|
|
218
|
+
Returns:
|
|
219
|
+
True if data has the correct NEAR upto payload structure.
|
|
220
|
+
"""
|
|
221
|
+
if not isinstance(data, dict):
|
|
222
|
+
return False
|
|
223
|
+
|
|
224
|
+
tx_hash = data.get("txHash")
|
|
225
|
+
payment_nonce = data.get("paymentNonce")
|
|
226
|
+
auth = data.get("authorization")
|
|
227
|
+
|
|
228
|
+
if not tx_hash or not isinstance(tx_hash, str):
|
|
229
|
+
return False
|
|
230
|
+
if not payment_nonce or not isinstance(payment_nonce, str):
|
|
231
|
+
return False
|
|
232
|
+
if not auth or not isinstance(auth, dict):
|
|
233
|
+
return False
|
|
234
|
+
|
|
235
|
+
# Check authorization structure
|
|
236
|
+
required_auth_fields = ["from", "facilitator", "tokenContract", "maxAmount"]
|
|
237
|
+
if not all(k in auth for k in required_auth_fields):
|
|
238
|
+
return False
|
|
239
|
+
|
|
240
|
+
# Ensure from and facilitator are non-empty strings
|
|
241
|
+
if not auth.get("from") or not isinstance(auth["from"], str):
|
|
242
|
+
return False
|
|
243
|
+
if not auth.get("facilitator") or not isinstance(auth["facilitator"], str):
|
|
244
|
+
return False
|
|
245
|
+
|
|
246
|
+
return True
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def upto_payload_from_dict(data: Dict[str, Any]) -> UptoNearPayload:
|
|
250
|
+
"""Create an UptoNearPayload from a dictionary.
|
|
251
|
+
|
|
252
|
+
Args:
|
|
253
|
+
data: Dictionary containing payload data with camelCase keys.
|
|
254
|
+
|
|
255
|
+
Returns:
|
|
256
|
+
UptoNearPayload instance.
|
|
257
|
+
|
|
258
|
+
Raises:
|
|
259
|
+
ValueError: If required fields are missing or invalid.
|
|
260
|
+
"""
|
|
261
|
+
auth_data = data.get("authorization", {})
|
|
262
|
+
|
|
263
|
+
return UptoNearPayload(
|
|
264
|
+
tx_hash=data.get("txHash", ""),
|
|
265
|
+
authorization=UptoNearAuthorization(
|
|
266
|
+
from_account=auth_data.get("from", ""),
|
|
267
|
+
facilitator=auth_data.get("facilitator", ""),
|
|
268
|
+
token_contract=auth_data.get("tokenContract", ""),
|
|
269
|
+
max_amount=auth_data.get("maxAmount", ""),
|
|
270
|
+
),
|
|
271
|
+
payment_nonce=data.get("paymentNonce", ""),
|
|
272
|
+
)
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""Polkadot Blockchain Payment Schemes.
|
|
2
|
+
|
|
3
|
+
This package provides payment scheme implementations for Polkadot Asset Hub networks.
|
|
4
|
+
|
|
5
|
+
Supported schemes:
|
|
6
|
+
- exact-direct: On-chain asset transfer with extrinsic proof
|
|
7
|
+
|
|
8
|
+
Supported networks:
|
|
9
|
+
- polkadot:68d56f15f85d3136970ec16946040bc1 (Polkadot Asset Hub)
|
|
10
|
+
- polkadot:e143f23803ac50e8f6f8e62695d1ce9e (Westend Asset Hub / Testnet)
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from t402.schemes.polkadot.exact_direct import (
|
|
14
|
+
ExactDirectPolkadotClientScheme,
|
|
15
|
+
ExactDirectPolkadotServerScheme,
|
|
16
|
+
ExactDirectPolkadotFacilitatorScheme,
|
|
17
|
+
ClientPolkadotSigner,
|
|
18
|
+
FacilitatorPolkadotSigner,
|
|
19
|
+
SCHEME_EXACT_DIRECT,
|
|
20
|
+
)
|
|
21
|
+
from t402.schemes.polkadot.constants import (
|
|
22
|
+
POLKADOT_ASSET_HUB_CAIP2,
|
|
23
|
+
WESTEND_ASSET_HUB_CAIP2,
|
|
24
|
+
KUSAMA_ASSET_HUB_CAIP2,
|
|
25
|
+
USDT_ASSET_ID,
|
|
26
|
+
USDT_DECIMALS,
|
|
27
|
+
NETWORKS,
|
|
28
|
+
get_network_config,
|
|
29
|
+
get_supported_networks,
|
|
30
|
+
is_polkadot_network,
|
|
31
|
+
)
|
|
32
|
+
from t402.schemes.polkadot.types import (
|
|
33
|
+
ExactDirectPayload,
|
|
34
|
+
ExtrinsicResult,
|
|
35
|
+
ParsedAssetTransfer,
|
|
36
|
+
is_valid_ss58_address,
|
|
37
|
+
is_valid_hash,
|
|
38
|
+
parse_asset_identifier,
|
|
39
|
+
create_asset_identifier,
|
|
40
|
+
extract_asset_transfer,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
__all__ = [
|
|
44
|
+
# Schemes
|
|
45
|
+
"ExactDirectPolkadotClientScheme",
|
|
46
|
+
"ExactDirectPolkadotServerScheme",
|
|
47
|
+
"ExactDirectPolkadotFacilitatorScheme",
|
|
48
|
+
# Signer protocols
|
|
49
|
+
"ClientPolkadotSigner",
|
|
50
|
+
"FacilitatorPolkadotSigner",
|
|
51
|
+
# Constants
|
|
52
|
+
"SCHEME_EXACT_DIRECT",
|
|
53
|
+
"POLKADOT_ASSET_HUB_CAIP2",
|
|
54
|
+
"WESTEND_ASSET_HUB_CAIP2",
|
|
55
|
+
"KUSAMA_ASSET_HUB_CAIP2",
|
|
56
|
+
"USDT_ASSET_ID",
|
|
57
|
+
"USDT_DECIMALS",
|
|
58
|
+
"NETWORKS",
|
|
59
|
+
# Functions
|
|
60
|
+
"get_network_config",
|
|
61
|
+
"get_supported_networks",
|
|
62
|
+
"is_polkadot_network",
|
|
63
|
+
# Types
|
|
64
|
+
"ExactDirectPayload",
|
|
65
|
+
"ExtrinsicResult",
|
|
66
|
+
"ParsedAssetTransfer",
|
|
67
|
+
"is_valid_ss58_address",
|
|
68
|
+
"is_valid_hash",
|
|
69
|
+
"parse_asset_identifier",
|
|
70
|
+
"create_asset_identifier",
|
|
71
|
+
"extract_asset_transfer",
|
|
72
|
+
]
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""Polkadot Scheme Constants.
|
|
2
|
+
|
|
3
|
+
This module defines constants for the Polkadot exact-direct payment scheme,
|
|
4
|
+
including network identifiers, token configurations, and default endpoints.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from typing import Dict
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# Scheme identifier
|
|
14
|
+
SCHEME_EXACT_DIRECT = "exact-direct"
|
|
15
|
+
|
|
16
|
+
# CAIP-2 network identifiers for Polkadot parachains
|
|
17
|
+
POLKADOT_ASSET_HUB_CAIP2 = "polkadot:68d56f15f85d3136970ec16946040bc1"
|
|
18
|
+
KUSAMA_ASSET_HUB_CAIP2 = "polkadot:48239ef607d7928874027a43a67689209727dfb3d3dc5e5b03a39bdc2eda771a"
|
|
19
|
+
WESTEND_ASSET_HUB_CAIP2 = "polkadot:e143f23803ac50e8f6f8e62695d1ce9e"
|
|
20
|
+
|
|
21
|
+
# Default indexer endpoints (Subscan)
|
|
22
|
+
POLKADOT_ASSET_HUB_INDEXER = "https://assethub-polkadot.api.subscan.io"
|
|
23
|
+
KUSAMA_ASSET_HUB_INDEXER = "https://assethub-kusama.api.subscan.io"
|
|
24
|
+
WESTEND_ASSET_HUB_INDEXER = "https://assethub-westend.api.subscan.io"
|
|
25
|
+
|
|
26
|
+
# Default RPC endpoints
|
|
27
|
+
POLKADOT_ASSET_HUB_RPC = "wss://polkadot-asset-hub-rpc.polkadot.io"
|
|
28
|
+
KUSAMA_ASSET_HUB_RPC = "wss://kusama-asset-hub-rpc.polkadot.io"
|
|
29
|
+
WESTEND_ASSET_HUB_RPC = "wss://westend-asset-hub-rpc.polkadot.io"
|
|
30
|
+
|
|
31
|
+
# USDT Asset ID on Asset Hub parachains
|
|
32
|
+
USDT_ASSET_ID = 1984
|
|
33
|
+
|
|
34
|
+
# Default decimals for USDT
|
|
35
|
+
USDT_DECIMALS = 6
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass(frozen=True)
|
|
39
|
+
class TokenInfo:
|
|
40
|
+
"""Token configuration for a Polkadot asset."""
|
|
41
|
+
|
|
42
|
+
asset_id: int
|
|
43
|
+
symbol: str
|
|
44
|
+
name: str
|
|
45
|
+
decimals: int
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass(frozen=True)
|
|
49
|
+
class NetworkConfig:
|
|
50
|
+
"""Configuration for a Polkadot network."""
|
|
51
|
+
|
|
52
|
+
name: str
|
|
53
|
+
caip2: str
|
|
54
|
+
indexer_url: str
|
|
55
|
+
rpc_url: str
|
|
56
|
+
genesis_hash: str
|
|
57
|
+
ss58_prefix: int
|
|
58
|
+
is_testnet: bool
|
|
59
|
+
default_token: TokenInfo
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
# Default token configurations
|
|
63
|
+
USDT_POLKADOT = TokenInfo(
|
|
64
|
+
asset_id=USDT_ASSET_ID,
|
|
65
|
+
symbol="USDT",
|
|
66
|
+
name="Tether USD",
|
|
67
|
+
decimals=USDT_DECIMALS,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
USDT_KUSAMA = TokenInfo(
|
|
71
|
+
asset_id=USDT_ASSET_ID,
|
|
72
|
+
symbol="USDT",
|
|
73
|
+
name="Tether USD",
|
|
74
|
+
decimals=USDT_DECIMALS,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
USDT_WESTEND = TokenInfo(
|
|
78
|
+
asset_id=USDT_ASSET_ID,
|
|
79
|
+
symbol="USDT",
|
|
80
|
+
name="Test Tether USD",
|
|
81
|
+
decimals=USDT_DECIMALS,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# Network configurations indexed by CAIP-2 identifier
|
|
85
|
+
NETWORKS: Dict[str, NetworkConfig] = {
|
|
86
|
+
POLKADOT_ASSET_HUB_CAIP2: NetworkConfig(
|
|
87
|
+
name="Polkadot Asset Hub",
|
|
88
|
+
caip2=POLKADOT_ASSET_HUB_CAIP2,
|
|
89
|
+
indexer_url=POLKADOT_ASSET_HUB_INDEXER,
|
|
90
|
+
rpc_url=POLKADOT_ASSET_HUB_RPC,
|
|
91
|
+
genesis_hash="0x68d56f15f85d3136970ec16946040bc1752654e906147f7e43e9d539d7c3de2f",
|
|
92
|
+
ss58_prefix=0,
|
|
93
|
+
is_testnet=False,
|
|
94
|
+
default_token=USDT_POLKADOT,
|
|
95
|
+
),
|
|
96
|
+
KUSAMA_ASSET_HUB_CAIP2: NetworkConfig(
|
|
97
|
+
name="Kusama Asset Hub",
|
|
98
|
+
caip2=KUSAMA_ASSET_HUB_CAIP2,
|
|
99
|
+
indexer_url=KUSAMA_ASSET_HUB_INDEXER,
|
|
100
|
+
rpc_url=KUSAMA_ASSET_HUB_RPC,
|
|
101
|
+
genesis_hash="0x48239ef607d7928874027a43a67689209727dfb3d3dc5e5b03a39bdc2eda771a",
|
|
102
|
+
ss58_prefix=2,
|
|
103
|
+
is_testnet=False,
|
|
104
|
+
default_token=USDT_KUSAMA,
|
|
105
|
+
),
|
|
106
|
+
WESTEND_ASSET_HUB_CAIP2: NetworkConfig(
|
|
107
|
+
name="Westend Asset Hub",
|
|
108
|
+
caip2=WESTEND_ASSET_HUB_CAIP2,
|
|
109
|
+
indexer_url=WESTEND_ASSET_HUB_INDEXER,
|
|
110
|
+
rpc_url=WESTEND_ASSET_HUB_RPC,
|
|
111
|
+
genesis_hash="0xe143f23803ac50e8f6f8e62695d1ce9e4e1d68aa36c1cd2cfd15340213f3423e",
|
|
112
|
+
ss58_prefix=42,
|
|
113
|
+
is_testnet=True,
|
|
114
|
+
default_token=USDT_WESTEND,
|
|
115
|
+
),
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def get_network_config(network: str) -> NetworkConfig:
|
|
120
|
+
"""Get the network configuration for a CAIP-2 identifier.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
network: CAIP-2 network identifier (e.g., "polkadot:68d56f15f85d3136970ec16946040bc1")
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
NetworkConfig for the given network
|
|
127
|
+
|
|
128
|
+
Raises:
|
|
129
|
+
ValueError: If the network is not supported
|
|
130
|
+
"""
|
|
131
|
+
config = NETWORKS.get(network)
|
|
132
|
+
if config is None:
|
|
133
|
+
raise ValueError(f"Unsupported Polkadot network: {network}")
|
|
134
|
+
return config
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def is_polkadot_network(network: str) -> bool:
|
|
138
|
+
"""Check if a network identifier is a Polkadot network.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
network: Network identifier to check
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
True if the network starts with "polkadot:"
|
|
145
|
+
"""
|
|
146
|
+
return network.startswith("polkadot:")
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def get_supported_networks() -> list:
|
|
150
|
+
"""Get all supported Polkadot network identifiers.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
List of CAIP-2 network identifiers
|
|
154
|
+
"""
|
|
155
|
+
return list(NETWORKS.keys())
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Polkadot Exact-Direct Payment Scheme.
|
|
2
|
+
|
|
3
|
+
This package provides the exact-direct payment scheme implementation for
|
|
4
|
+
Polkadot Asset Hub networks using on-chain asset transfers.
|
|
5
|
+
|
|
6
|
+
The exact-direct scheme works by:
|
|
7
|
+
1. Client executes assets.transfer_keep_alive on-chain
|
|
8
|
+
2. Client returns the extrinsic hash, block hash, and index as proof
|
|
9
|
+
3. Facilitator verifies the transfer on-chain via indexer/RPC
|
|
10
|
+
|
|
11
|
+
This is a "direct" scheme because the client pays on-chain before
|
|
12
|
+
submitting the payment proof, rather than providing an off-chain signature
|
|
13
|
+
for later settlement.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from t402.schemes.polkadot.exact_direct.client import (
|
|
17
|
+
ExactDirectPolkadotClientScheme,
|
|
18
|
+
)
|
|
19
|
+
from t402.schemes.polkadot.exact_direct.server import (
|
|
20
|
+
ExactDirectPolkadotServerScheme,
|
|
21
|
+
)
|
|
22
|
+
from t402.schemes.polkadot.exact_direct.facilitator import (
|
|
23
|
+
ExactDirectPolkadotFacilitatorScheme,
|
|
24
|
+
)
|
|
25
|
+
from t402.schemes.polkadot.constants import SCHEME_EXACT_DIRECT
|
|
26
|
+
from t402.schemes.polkadot.types import (
|
|
27
|
+
ClientPolkadotSigner,
|
|
28
|
+
FacilitatorPolkadotSigner,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
__all__ = [
|
|
32
|
+
# Client
|
|
33
|
+
"ExactDirectPolkadotClientScheme",
|
|
34
|
+
# Server
|
|
35
|
+
"ExactDirectPolkadotServerScheme",
|
|
36
|
+
# Facilitator
|
|
37
|
+
"ExactDirectPolkadotFacilitatorScheme",
|
|
38
|
+
# Signer protocols
|
|
39
|
+
"ClientPolkadotSigner",
|
|
40
|
+
"FacilitatorPolkadotSigner",
|
|
41
|
+
# Constants
|
|
42
|
+
"SCHEME_EXACT_DIRECT",
|
|
43
|
+
]
|