t402 1.7.1__py3-none-any.whl → 1.9.1__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 (102) hide show
  1. t402/__init__.py +2 -1
  2. t402/bridge/client.py +13 -5
  3. t402/bridge/constants.py +3 -1
  4. t402/bridge/router.py +1 -1
  5. t402/bridge/scan.py +3 -1
  6. t402/chains.py +268 -1
  7. t402/cli.py +31 -9
  8. t402/common.py +2 -0
  9. t402/cosmos_paywall_template.py +2 -0
  10. t402/encoding.py +9 -3
  11. t402/erc4337/accounts.py +56 -51
  12. t402/erc4337/bundlers.py +105 -99
  13. t402/erc4337/paymasters.py +100 -109
  14. t402/erc4337/types.py +39 -26
  15. t402/evm_paywall_template.py +1 -1
  16. t402/fastapi/middleware.py +1 -3
  17. t402/mcp/server.py +79 -46
  18. t402/near_paywall_template.py +2 -0
  19. t402/networks.py +34 -1
  20. t402/paywall.py +1 -3
  21. t402/schemes/__init__.py +164 -1
  22. t402/schemes/aptos/__init__.py +70 -0
  23. t402/schemes/aptos/constants.py +349 -0
  24. t402/schemes/aptos/exact_direct/__init__.py +44 -0
  25. t402/schemes/aptos/exact_direct/client.py +202 -0
  26. t402/schemes/aptos/exact_direct/facilitator.py +426 -0
  27. t402/schemes/aptos/exact_direct/server.py +272 -0
  28. t402/schemes/aptos/types.py +237 -0
  29. t402/schemes/evm/__init__.py +67 -1
  30. t402/schemes/evm/exact/__init__.py +11 -0
  31. t402/schemes/evm/exact/client.py +3 -1
  32. t402/schemes/evm/exact/facilitator.py +894 -0
  33. t402/schemes/evm/exact/server.py +1 -1
  34. t402/schemes/evm/exact_legacy/__init__.py +38 -0
  35. t402/schemes/evm/exact_legacy/client.py +291 -0
  36. t402/schemes/evm/exact_legacy/facilitator.py +777 -0
  37. t402/schemes/evm/exact_legacy/server.py +231 -0
  38. t402/schemes/evm/upto/__init__.py +70 -0
  39. t402/schemes/evm/upto/client.py +244 -0
  40. t402/schemes/evm/upto/facilitator.py +625 -0
  41. t402/schemes/evm/upto/server.py +243 -0
  42. t402/schemes/evm/upto/types.py +307 -0
  43. t402/schemes/interfaces.py +6 -2
  44. t402/schemes/near/__init__.py +112 -0
  45. t402/schemes/near/constants.py +189 -0
  46. t402/schemes/near/exact_direct/__init__.py +21 -0
  47. t402/schemes/near/exact_direct/client.py +204 -0
  48. t402/schemes/near/exact_direct/facilitator.py +455 -0
  49. t402/schemes/near/exact_direct/server.py +303 -0
  50. t402/schemes/near/types.py +419 -0
  51. t402/schemes/polkadot/__init__.py +72 -0
  52. t402/schemes/polkadot/constants.py +155 -0
  53. t402/schemes/polkadot/exact_direct/__init__.py +43 -0
  54. t402/schemes/polkadot/exact_direct/client.py +235 -0
  55. t402/schemes/polkadot/exact_direct/facilitator.py +428 -0
  56. t402/schemes/polkadot/exact_direct/server.py +292 -0
  57. t402/schemes/polkadot/types.py +385 -0
  58. t402/schemes/registry.py +6 -2
  59. t402/schemes/stacks/__init__.py +68 -0
  60. t402/schemes/stacks/constants.py +122 -0
  61. t402/schemes/stacks/exact_direct/__init__.py +43 -0
  62. t402/schemes/stacks/exact_direct/client.py +222 -0
  63. t402/schemes/stacks/exact_direct/facilitator.py +424 -0
  64. t402/schemes/stacks/exact_direct/server.py +292 -0
  65. t402/schemes/stacks/types.py +380 -0
  66. t402/schemes/svm/__init__.py +29 -0
  67. t402/schemes/svm/exact/__init__.py +35 -0
  68. t402/schemes/svm/exact/client.py +23 -0
  69. t402/schemes/svm/exact/facilitator.py +24 -0
  70. t402/schemes/svm/exact/server.py +20 -0
  71. t402/schemes/tezos/__init__.py +84 -0
  72. t402/schemes/tezos/constants.py +372 -0
  73. t402/schemes/tezos/exact_direct/__init__.py +22 -0
  74. t402/schemes/tezos/exact_direct/client.py +226 -0
  75. t402/schemes/tezos/exact_direct/facilitator.py +491 -0
  76. t402/schemes/tezos/exact_direct/server.py +277 -0
  77. t402/schemes/tezos/types.py +220 -0
  78. t402/schemes/ton/__init__.py +9 -2
  79. t402/schemes/ton/exact/__init__.py +7 -0
  80. t402/schemes/ton/exact/facilitator.py +730 -0
  81. t402/schemes/ton/exact/server.py +1 -1
  82. t402/schemes/tron/__init__.py +11 -2
  83. t402/schemes/tron/exact/__init__.py +9 -0
  84. t402/schemes/tron/exact/facilitator.py +673 -0
  85. t402/schemes/tron/exact/server.py +1 -1
  86. t402/schemes/upto/__init__.py +80 -0
  87. t402/schemes/upto/types.py +376 -0
  88. t402/stacks_paywall_template.py +2 -0
  89. t402/svm.py +45 -11
  90. t402/svm_paywall_template.py +1 -1
  91. t402/ton.py +5 -1
  92. t402/ton_paywall_template.py +1 -192
  93. t402/tron.py +2 -0
  94. t402/tron_paywall_template.py +2 -0
  95. t402/types.py +4 -2
  96. t402/wdk/errors.py +15 -5
  97. t402/wdk/signer.py +11 -2
  98. {t402-1.7.1.dist-info → t402-1.9.1.dist-info}/METADATA +42 -1
  99. t402-1.9.1.dist-info/RECORD +125 -0
  100. t402-1.7.1.dist-info/RECORD +0 -67
  101. {t402-1.7.1.dist-info → t402-1.9.1.dist-info}/WHEEL +0 -0
  102. {t402-1.7.1.dist-info → t402-1.9.1.dist-info}/entry_points.txt +0 -0
t402/__init__.py CHANGED
@@ -1,5 +1,5 @@
1
1
  # Package version
2
- __version__ = "1.6.2"
2
+ __version__ = "1.9.0"
3
3
 
4
4
  # Re-export commonly used items for convenience
5
5
  from t402.common import (
@@ -290,6 +290,7 @@ from t402.fastapi import (
290
290
  settle_payment,
291
291
  )
292
292
 
293
+
293
294
  def hello() -> str:
294
295
  return "Hello from t402!"
295
296
 
t402/bridge/client.py CHANGED
@@ -1,6 +1,5 @@
1
1
  """USDT0 Bridge Client for LayerZero OFT transfers."""
2
2
 
3
-
4
3
  from .constants import (
5
4
  DEFAULT_EXTRA_OPTIONS,
6
5
  DEFAULT_SLIPPAGE,
@@ -73,7 +72,7 @@ class Usdt0Bridge:
73
72
  if not supports_bridging(chain):
74
73
  raise ValueError(
75
74
  f'Chain "{chain}" does not support USDT0 bridging. '
76
- f'Supported chains: {", ".join(get_bridgeable_chains())}'
75
+ f"Supported chains: {', '.join(get_bridgeable_chains())}"
77
76
  )
78
77
 
79
78
  self._signer = signer
@@ -107,7 +106,9 @@ class Usdt0Bridge:
107
106
  False,
108
107
  )
109
108
 
110
- native_fee = fee[0] if isinstance(fee, (list, tuple)) else fee.get("nativeFee", 0)
109
+ native_fee = (
110
+ fee[0] if isinstance(fee, (list, tuple)) else fee.get("nativeFee", 0)
111
+ )
111
112
 
112
113
  return BridgeQuote(
113
114
  native_fee=int(native_fee),
@@ -139,7 +140,11 @@ class Usdt0Bridge:
139
140
  )
140
141
  )
141
142
 
142
- slippage = params.slippage_tolerance if params.slippage_tolerance > 0 else DEFAULT_SLIPPAGE
143
+ slippage = (
144
+ params.slippage_tolerance
145
+ if params.slippage_tolerance > 0
146
+ else DEFAULT_SLIPPAGE
147
+ )
143
148
  oft_address = get_usdt0_oft_address(params.from_chain)
144
149
  send_param = self._build_send_param(
145
150
  params.to_chain, params.amount, params.recipient, slippage
@@ -304,7 +309,10 @@ class Usdt0Bridge:
304
309
  def _extract_message_guid(self, receipt: BridgeTransactionReceipt) -> str:
305
310
  """Extract LayerZero message GUID from OFTSent event logs."""
306
311
  for log in receipt.logs:
307
- if len(log.topics) >= 2 and log.topics[0].lower() == OFT_SENT_EVENT_TOPIC.lower():
312
+ if (
313
+ len(log.topics) >= 2
314
+ and log.topics[0].lower() == OFT_SENT_EVENT_TOPIC.lower()
315
+ ):
308
316
  # GUID is the first indexed parameter (topics[1])
309
317
  return log.topics[1]
310
318
 
t402/bridge/constants.py CHANGED
@@ -251,7 +251,9 @@ def address_to_bytes32(address: str) -> bytes:
251
251
  addr = address.lower().removeprefix("0x")
252
252
 
253
253
  if len(addr) != 40:
254
- raise ValueError(f"Invalid address length: expected 40 hex chars, got {len(addr)}")
254
+ raise ValueError(
255
+ f"Invalid address length: expected 40 hex chars, got {len(addr)}"
256
+ )
255
257
 
256
258
  try:
257
259
  addr_bytes = bytes.fromhex(addr)
t402/bridge/router.py CHANGED
@@ -199,7 +199,7 @@ class CrossChainPaymentRouter:
199
199
  raise ValueError(
200
200
  f'Cannot route payment from "{params.source_chain}" to '
201
201
  f'"{params.destination_chain}". '
202
- f'Supported chains: {", ".join(get_bridgeable_chains())}'
202
+ f"Supported chains: {', '.join(get_bridgeable_chains())}"
203
203
  )
204
204
 
205
205
  if params.amount <= 0:
t402/bridge/scan.py CHANGED
@@ -206,7 +206,9 @@ class LayerZeroScanClient:
206
206
  dst_tx_hash=data.get("dstTxHash"),
207
207
  status=LayerZeroMessageStatus(data.get("status") or "INFLIGHT"),
208
208
  src_block_number=int(data.get("srcBlockNumber") or 0),
209
- dst_block_number=int(data.get("dstBlockNumber")) if data.get("dstBlockNumber") else None,
209
+ dst_block_number=int(data.get("dstBlockNumber"))
210
+ if data.get("dstBlockNumber")
211
+ else None,
210
212
  created=data.get("created") or data.get("createdAt") or "",
211
213
  updated=data.get("updated") or data.get("updatedAt") or "",
212
214
  )
t402/chains.py CHANGED
@@ -1,8 +1,38 @@
1
1
  NETWORK_TO_ID = {
2
+ # Standard networks
2
3
  "base-sepolia": "84532",
3
4
  "base": "8453",
4
5
  "avalanche-fuji": "43113",
5
6
  "avalanche": "43114",
7
+ # Core USDT0 Networks
8
+ "ethereum": "1",
9
+ "arbitrum": "42161",
10
+ "optimism": "10",
11
+ "polygon": "137",
12
+ "ink": "57073",
13
+ "berachain": "80094",
14
+ "unichain": "130",
15
+ # Phase 1: High Priority USDT0 Networks
16
+ "mantle": "5000",
17
+ "plasma": "9745",
18
+ "sei": "1329",
19
+ "conflux": "1030",
20
+ "monad": "143",
21
+ # Phase 2: Medium Priority USDT0 Networks
22
+ "flare": "14",
23
+ "rootstock": "30",
24
+ "xlayer": "196",
25
+ "stable": "988",
26
+ "hyperevm": "999",
27
+ "megaeth": "4326",
28
+ "corn": "21000000",
29
+ # Legacy USDT Networks (no EIP-3009 support)
30
+ "bnb": "56",
31
+ "bsc": "56",
32
+ "fantom": "250",
33
+ "celo": "42220",
34
+ "kaia": "8217",
35
+ "klaytn": "8217",
6
36
  }
7
37
 
8
38
 
@@ -21,6 +51,7 @@ def get_chain_id(network: str) -> str:
21
51
 
22
52
 
23
53
  KNOWN_TOKENS = {
54
+ # Base Sepolia (testnet)
24
55
  "84532": [
25
56
  {
26
57
  "human_name": "usdc",
@@ -30,15 +61,17 @@ KNOWN_TOKENS = {
30
61
  "version": "2",
31
62
  }
32
63
  ],
64
+ # Base Mainnet
33
65
  "8453": [
34
66
  {
35
67
  "human_name": "usdc",
36
68
  "address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
37
- "name": "USD Coin", # needs to be exactly what is returned by name() on contract
69
+ "name": "USD Coin",
38
70
  "decimals": 6,
39
71
  "version": "2",
40
72
  }
41
73
  ],
74
+ # Avalanche Fuji (testnet)
42
75
  "43113": [
43
76
  {
44
77
  "human_name": "usdc",
@@ -48,6 +81,7 @@ KNOWN_TOKENS = {
48
81
  "version": "2",
49
82
  }
50
83
  ],
84
+ # Avalanche Mainnet
51
85
  "43114": [
52
86
  {
53
87
  "human_name": "usdc",
@@ -57,6 +91,239 @@ KNOWN_TOKENS = {
57
91
  "version": "2",
58
92
  }
59
93
  ],
94
+ # === USDT0 Networks ===
95
+ # Ethereum Mainnet
96
+ "1": [
97
+ {
98
+ "human_name": "usdt0",
99
+ "address": "0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee",
100
+ "name": "TetherToken",
101
+ "decimals": 6,
102
+ "version": "1",
103
+ }
104
+ ],
105
+ # Arbitrum One
106
+ "42161": [
107
+ {
108
+ "human_name": "usdt0",
109
+ "address": "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
110
+ "name": "TetherToken",
111
+ "decimals": 6,
112
+ "version": "1",
113
+ }
114
+ ],
115
+ # Optimism
116
+ "10": [
117
+ {
118
+ "human_name": "usdt0",
119
+ "address": "0x01bFF41798a0BcF287b996046Ca68b395DbC1071",
120
+ "name": "TetherToken",
121
+ "decimals": 6,
122
+ "version": "1",
123
+ }
124
+ ],
125
+ # Polygon
126
+ "137": [
127
+ {
128
+ "human_name": "usdt0",
129
+ "address": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
130
+ "name": "TetherToken",
131
+ "decimals": 6,
132
+ "version": "1",
133
+ }
134
+ ],
135
+ # Ink
136
+ "57073": [
137
+ {
138
+ "human_name": "usdt0",
139
+ "address": "0x0200C29006150606B650577BBE7B6248F58470c1",
140
+ "name": "TetherToken",
141
+ "decimals": 6,
142
+ "version": "1",
143
+ }
144
+ ],
145
+ # Berachain
146
+ "80094": [
147
+ {
148
+ "human_name": "usdt0",
149
+ "address": "0x779Ded0c9e1022225f8E0630b35a9b54bE713736",
150
+ "name": "TetherToken",
151
+ "decimals": 6,
152
+ "version": "1",
153
+ }
154
+ ],
155
+ # Unichain
156
+ "130": [
157
+ {
158
+ "human_name": "usdt0",
159
+ "address": "0x9151434b16b9763660705744891fA906F660EcC5",
160
+ "name": "TetherToken",
161
+ "decimals": 6,
162
+ "version": "1",
163
+ }
164
+ ],
165
+ # Mantle
166
+ "5000": [
167
+ {
168
+ "human_name": "usdt0",
169
+ "address": "0x779Ded0c9e1022225f8E0630b35a9b54bE713736",
170
+ "name": "TetherToken",
171
+ "decimals": 6,
172
+ "version": "1",
173
+ }
174
+ ],
175
+ # Plasma
176
+ "9745": [
177
+ {
178
+ "human_name": "usdt0",
179
+ "address": "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb",
180
+ "name": "TetherToken",
181
+ "decimals": 6,
182
+ "version": "1",
183
+ }
184
+ ],
185
+ # Sei
186
+ "1329": [
187
+ {
188
+ "human_name": "usdt0",
189
+ "address": "0x9151434b16b9763660705744891fA906F660EcC5",
190
+ "name": "TetherToken",
191
+ "decimals": 6,
192
+ "version": "1",
193
+ }
194
+ ],
195
+ # Conflux eSpace
196
+ "1030": [
197
+ {
198
+ "human_name": "usdt0",
199
+ "address": "0xaf37E8B6C9ED7f6318979f56Fc287d76c30847ff",
200
+ "name": "TetherToken",
201
+ "decimals": 6,
202
+ "version": "1",
203
+ }
204
+ ],
205
+ # Monad
206
+ "143": [
207
+ {
208
+ "human_name": "usdt0",
209
+ "address": "0xe7cd86e13AC4309349F30B3435a9d337750fC82D",
210
+ "name": "TetherToken",
211
+ "decimals": 6,
212
+ "version": "1",
213
+ }
214
+ ],
215
+ # Flare
216
+ "14": [
217
+ {
218
+ "human_name": "usdt0",
219
+ "address": "0xe7cd86e13AC4309349F30B3435a9d337750fC82D",
220
+ "name": "TetherToken",
221
+ "decimals": 6,
222
+ "version": "1",
223
+ }
224
+ ],
225
+ # Rootstock
226
+ "30": [
227
+ {
228
+ "human_name": "usdt0",
229
+ "address": "0x779dED0C9e1022225F8e0630b35A9B54Be713736",
230
+ "name": "TetherToken",
231
+ "decimals": 6,
232
+ "version": "1",
233
+ }
234
+ ],
235
+ # XLayer
236
+ "196": [
237
+ {
238
+ "human_name": "usdt0",
239
+ "address": "0x779Ded0c9e1022225f8E0630b35a9b54bE713736",
240
+ "name": "TetherToken",
241
+ "decimals": 6,
242
+ "version": "1",
243
+ }
244
+ ],
245
+ # Stable
246
+ "988": [
247
+ {
248
+ "human_name": "usdt0",
249
+ "address": "0x779Ded0c9e1022225f8E0630b35a9b54bE713736",
250
+ "name": "TetherToken",
251
+ "decimals": 6,
252
+ "version": "1",
253
+ }
254
+ ],
255
+ # HyperEVM
256
+ "999": [
257
+ {
258
+ "human_name": "usdt0",
259
+ "address": "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb",
260
+ "name": "TetherToken",
261
+ "decimals": 6,
262
+ "version": "1",
263
+ }
264
+ ],
265
+ # MegaETH
266
+ "4326": [
267
+ {
268
+ "human_name": "usdt0",
269
+ "address": "0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb",
270
+ "name": "TetherToken",
271
+ "decimals": 6,
272
+ "version": "1",
273
+ }
274
+ ],
275
+ # Corn
276
+ "21000000": [
277
+ {
278
+ "human_name": "usdt0",
279
+ "address": "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb",
280
+ "name": "TetherToken",
281
+ "decimals": 6,
282
+ "version": "1",
283
+ }
284
+ ],
285
+ # === Legacy USDT Networks (no EIP-3009 support) ===
286
+ # BNB Chain (BSC)
287
+ "56": [
288
+ {
289
+ "human_name": "usdt",
290
+ "address": "0x55d398326f99059fF775485246999027B3197955",
291
+ "name": "Tether USD",
292
+ "decimals": 18,
293
+ "version": "1",
294
+ }
295
+ ],
296
+ # Avalanche C-Chain (already in KNOWN_TOKENS via "43114", add USDT)
297
+ # Fantom
298
+ "250": [
299
+ {
300
+ "human_name": "usdt",
301
+ "address": "0x049d68029688eabf473097a2fc38ef61633a3c7a",
302
+ "name": "Frapped USDT",
303
+ "decimals": 6,
304
+ "version": "1",
305
+ }
306
+ ],
307
+ # Celo
308
+ "42220": [
309
+ {
310
+ "human_name": "usdt",
311
+ "address": "0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e",
312
+ "name": "Tether USD",
313
+ "decimals": 18,
314
+ "version": "1",
315
+ }
316
+ ],
317
+ # Kaia (formerly Klaytn)
318
+ "8217": [
319
+ {
320
+ "human_name": "usdt",
321
+ "address": "0xcee8faf64bb97a73bb51e115aa89c17ffa8dd167",
322
+ "name": "Tether USD",
323
+ "decimals": 6,
324
+ "version": "1",
325
+ }
326
+ ],
60
327
  }
61
328
 
62
329
 
t402/cli.py CHANGED
@@ -10,6 +10,7 @@ Usage:
10
10
  t402 decode <base64-string>
11
11
  t402 version
12
12
  """
13
+
13
14
  from __future__ import annotations
14
15
 
15
16
  import argparse
@@ -20,7 +21,7 @@ from pathlib import Path
20
21
  from typing import Any
21
22
 
22
23
  from . import __version__
23
- from .encoding import decode_payment, encode_payment
24
+ from .exact import decode_payment, encode_payment
24
25
  from .facilitator import FacilitatorClient, FacilitatorConfig
25
26
  from .types import PaymentPayload
26
27
 
@@ -263,7 +264,16 @@ def cmd_decode(args: argparse.Namespace) -> int:
263
264
 
264
265
  def cmd_info(args: argparse.Namespace) -> int:
265
266
  """Show information about a network."""
266
- from .networks import is_evm_network, is_ton_network, is_tron_network
267
+ from .networks import (
268
+ is_evm_network,
269
+ is_ton_network,
270
+ is_tron_network,
271
+ is_svm_network,
272
+ EVM_NETWORK_TO_CHAIN_ID,
273
+ TON_NETWORKS,
274
+ TRON_NETWORKS,
275
+ SVM_NETWORKS,
276
+ )
267
277
 
268
278
  network = args.network
269
279
 
@@ -272,17 +282,29 @@ def cmd_info(args: argparse.Namespace) -> int:
272
282
  "is_evm": is_evm_network(network),
273
283
  "is_ton": is_ton_network(network),
274
284
  "is_tron": is_tron_network(network),
285
+ "is_svm": is_svm_network(network),
275
286
  }
276
287
 
277
288
  # Add chain-specific info
278
289
  if is_evm_network(network):
279
- from .chains import EVM_CHAINS
280
-
281
- chain_id = network.split(":")[1] if ":" in network else network
282
- if chain_id in EVM_CHAINS:
283
- chain = EVM_CHAINS[chain_id]
284
- info["chain_name"] = chain.get("name", "Unknown")
285
- info["currency"] = chain.get("currency", "Unknown")
290
+ chain_id = EVM_NETWORK_TO_CHAIN_ID.get(network)
291
+ if chain_id:
292
+ info["chain_id"] = chain_id
293
+
294
+ if is_ton_network(network) and network in TON_NETWORKS:
295
+ net_info = TON_NETWORKS[network]
296
+ info["name"] = net_info.get("name", "Unknown")
297
+ info["is_testnet"] = net_info.get("is_testnet", False)
298
+
299
+ if is_tron_network(network) and network in TRON_NETWORKS:
300
+ net_info = TRON_NETWORKS[network]
301
+ info["name"] = net_info.get("name", "Unknown")
302
+ info["is_testnet"] = net_info.get("is_testnet", False)
303
+
304
+ if is_svm_network(network) and network in SVM_NETWORKS:
305
+ net_info = SVM_NETWORKS[network]
306
+ info["name"] = net_info.get("name", "Unknown")
307
+ info["is_testnet"] = net_info.get("is_testnet", False)
286
308
 
287
309
  if args.output == "json":
288
310
  print(json.dumps(info, indent=2))
t402/common.py CHANGED
@@ -34,10 +34,12 @@ def parse_money(amount: str | int, address: str, network: str) -> int:
34
34
  # Handle TON networks differently
35
35
  if is_ton_network(network):
36
36
  from t402.ton import DEFAULT_DECIMALS
37
+
37
38
  decimals = DEFAULT_DECIMALS # USDT on TON uses 6 decimals
38
39
  # Handle TRON networks
39
40
  elif is_tron_network(network):
40
41
  from t402.tron import DEFAULT_DECIMALS
42
+
41
43
  decimals = DEFAULT_DECIMALS # USDT on TRON uses 6 decimals
42
44
  else:
43
45
  chain_id = get_chain_id(network)