t402 1.0.0__tar.gz

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 (40) hide show
  1. t402-1.0.0/.gitignore +11 -0
  2. t402-1.0.0/.python-version +1 -0
  3. t402-1.0.0/PKG-INFO +236 -0
  4. t402-1.0.0/README.md +217 -0
  5. t402-1.0.0/pyproject.toml +45 -0
  6. t402-1.0.0/src/t402/__init__.py +2 -0
  7. t402-1.0.0/src/t402/chains.py +92 -0
  8. t402-1.0.0/src/t402/clients/__init__.py +20 -0
  9. t402-1.0.0/src/t402/clients/base.py +199 -0
  10. t402-1.0.0/src/t402/clients/httpx.py +136 -0
  11. t402-1.0.0/src/t402/clients/requests.py +145 -0
  12. t402-1.0.0/src/t402/common.py +114 -0
  13. t402-1.0.0/src/t402/encoding.py +28 -0
  14. t402-1.0.0/src/t402/evm_paywall_template.py +2 -0
  15. t402-1.0.0/src/t402/exact.py +130 -0
  16. t402-1.0.0/src/t402/facilitator.py +135 -0
  17. t402-1.0.0/src/t402/fastapi/__init__.py +0 -0
  18. t402-1.0.0/src/t402/fastapi/middleware.py +219 -0
  19. t402-1.0.0/src/t402/flask/__init__.py +0 -0
  20. t402-1.0.0/src/t402/flask/middleware.py +334 -0
  21. t402-1.0.0/src/t402/networks.py +11 -0
  22. t402-1.0.0/src/t402/path.py +43 -0
  23. t402-1.0.0/src/t402/paywall.py +129 -0
  24. t402-1.0.0/src/t402/py.typed +0 -0
  25. t402-1.0.0/src/t402/svm_paywall_template.py +2 -0
  26. t402-1.0.0/src/t402/types.py +285 -0
  27. t402-1.0.0/tests/clients/__init__.py +0 -0
  28. t402-1.0.0/tests/clients/test_base.py +194 -0
  29. t402-1.0.0/tests/clients/test_httpx.py +239 -0
  30. t402-1.0.0/tests/clients/test_requests.py +310 -0
  31. t402-1.0.0/tests/fastapi_tests/__init__.py +0 -0
  32. t402-1.0.0/tests/fastapi_tests/test_middleware.py +528 -0
  33. t402-1.0.0/tests/flask_tests/__init__.py +0 -0
  34. t402-1.0.0/tests/flask_tests/test_middleware.py +357 -0
  35. t402-1.0.0/tests/test_common.py +175 -0
  36. t402-1.0.0/tests/test_encoding.py +81 -0
  37. t402-1.0.0/tests/test_exact.py +198 -0
  38. t402-1.0.0/tests/test_paywall.py +258 -0
  39. t402-1.0.0/tests/test_types.py +162 -0
  40. t402-1.0.0/uv.lock +2084 -0
t402-1.0.0/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ .env
2
+ node_modules/
3
+ dist/
4
+ .turbo/
5
+ .next/
6
+ proxy
7
+ .env
8
+ __pycache__/
9
+ **/.DS_Store
10
+ e2e/facilitators/external-proxies/*
11
+ !e2e/facilitators/external-proxies/README.md
@@ -0,0 +1 @@
1
+ 3.10
t402-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,236 @@
1
+ Metadata-Version: 2.4
2
+ Name: t402
3
+ Version: 1.0.0
4
+ Summary: t402: An internet native payments protocol
5
+ Author-email: T402 Team <dev@t402.io>
6
+ License: Apache-2.0
7
+ Keywords: crypto,payments,sdk,t402,tether,usdt,web3
8
+ Requires-Python: >=3.10
9
+ Requires-Dist: eth-account>=0.13.7
10
+ Requires-Dist: eth-typing>=4.0.0
11
+ Requires-Dist: eth-utils>=3.0.0
12
+ Requires-Dist: fastapi[standard]>=0.115.12
13
+ Requires-Dist: flask>=3.0.0
14
+ Requires-Dist: pydantic-settings>=2.2.1
15
+ Requires-Dist: pydantic>=2.10.3
16
+ Requires-Dist: python-dotenv>=1.0.1
17
+ Requires-Dist: web3>=6.0.0
18
+ Description-Content-Type: text/markdown
19
+
20
+ # t402 Python
21
+
22
+ Python package for the t402 payments protocol.
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ pip install t402
28
+ ```
29
+
30
+ ## Overview
31
+
32
+ The t402 package provides the core building blocks for implementing the t402 Payment Protocol in Python. It's designed to be used by:
33
+
34
+ - FastAPI middleware for accepting payments
35
+ - Flask middleware for accepting payments
36
+ - httpx client for paying resources
37
+ - requests client for paying resources
38
+
39
+ ## FastAPI Integration
40
+
41
+ The simplest way to add t402 payment protection to your FastAPI application:
42
+
43
+ ```py
44
+ from fastapi import FastAPI
45
+ from t402.fastapi.middleware import require_payment
46
+
47
+ app = FastAPI()
48
+ app.middleware("http")(
49
+ require_payment(price="0.01", pay_to_address="0x209693Bc6afc0C5328bA36FaF03C514EF312287C")
50
+ )
51
+
52
+ @app.get("/")
53
+ async def root():
54
+ return {"message": "Hello World"}
55
+ ```
56
+
57
+ To protect specific routes:
58
+
59
+ ```py
60
+ app.middleware("http")(
61
+ require_payment(price="0.01",
62
+ pay_to_address="0x209693Bc6afc0C5328bA36FaF03C514EF312287C"),
63
+ path="/foo" # <-- this can also be a list ex: ["/foo", "/bar"]
64
+ )
65
+ ```
66
+
67
+ ## Flask Integration
68
+
69
+ The simplest way to add t402 payment protection to your Flask application:
70
+
71
+ ```py
72
+ from flask import Flask
73
+ from t402.flask.middleware import PaymentMiddleware
74
+
75
+ app = Flask(__name__)
76
+
77
+ # Initialize payment middleware
78
+ payment_middleware = PaymentMiddleware(app)
79
+
80
+ # Add payment protection for all routes
81
+ payment_middleware.add(
82
+ price="$0.01",
83
+ pay_to_address="0x209693Bc6afc0C5328bA36FaF03C514EF312287C",
84
+ )
85
+
86
+ @app.route("/")
87
+ def root():
88
+ return {"message": "Hello World"}
89
+ ```
90
+
91
+ To protect specific routes:
92
+
93
+ ```py
94
+ # Protect specific endpoint
95
+ payment_middleware.add(
96
+ path="/foo",
97
+ price="$0.001",
98
+ pay_to_address="0x209693Bc6afc0C5328bA36FaF03C514EF312287C",
99
+ )
100
+ ```
101
+
102
+ ## Client Integration
103
+
104
+ ### Simple Usage
105
+
106
+ #### Httpx Client
107
+ ```py
108
+ from eth_account import Account
109
+ from t402.clients.httpx import t402HttpxClient
110
+
111
+ # Initialize account
112
+ account = Account.from_key("your_private_key")
113
+
114
+ # Create client and make request
115
+ async with t402HttpxClient(account=account, base_url="https://api.example.com") as client:
116
+ response = await client.get("/protected-endpoint")
117
+ print(await response.aread())
118
+ ```
119
+
120
+ #### Requests Session Client
121
+ ```py
122
+ from eth_account import Account
123
+ from t402.clients.requests import t402_requests
124
+
125
+ # Initialize account
126
+ account = Account.from_key("your_private_key")
127
+
128
+ # Create session and make request
129
+ session = t402_requests(account)
130
+ response = session.get("https://api.example.com/protected-endpoint")
131
+ print(response.content)
132
+ ```
133
+
134
+ ### Advanced Usage
135
+
136
+ #### Httpx Extensible Example
137
+ ```py
138
+ import httpx
139
+ from eth_account import Account
140
+ from t402.clients.httpx import t402_payment_hooks
141
+
142
+ # Initialize account
143
+ account = Account.from_key("your_private_key")
144
+
145
+ # Create httpx client with t402 payment hooks
146
+ async with httpx.AsyncClient(base_url="https://api.example.com") as client:
147
+ # Add payment hooks directly to client
148
+ client.event_hooks = t402_payment_hooks(account)
149
+
150
+ # Make request - payment handling is automatic
151
+ response = await client.get("/protected-endpoint")
152
+ print(await response.aread())
153
+ ```
154
+
155
+ #### Requests Session Extensible Example
156
+ ```py
157
+ import requests
158
+ from eth_account import Account
159
+ from t402.clients.requests import t402_http_adapter
160
+
161
+ # Initialize account
162
+ account = Account.from_key("your_private_key")
163
+
164
+ # Create session and mount the t402 adapter
165
+ session = requests.Session()
166
+ adapter = t402_http_adapter(account)
167
+
168
+ # Mount the adapter for both HTTP and HTTPS
169
+ session.mount("http://", adapter)
170
+ session.mount("https://", adapter)
171
+
172
+ # Make request - payment handling is automatic
173
+ response = session.get("https://api.example.com/protected-endpoint")
174
+ print(response.content)
175
+ ```
176
+
177
+ ## Manual Server Integration
178
+
179
+ If you're not using the FastAPI middleware, you can implement the t402 protocol manually. Here's what you'll need to handle:
180
+
181
+ 1. Return 402 error responses with the appropriate response body
182
+ 2. Use the facilitator to validate payments
183
+ 3. Use the facilitator to settle payments
184
+ 4. Return the appropriate response header to the caller
185
+
186
+ Here's an example of manual integration:
187
+
188
+ ```py
189
+ from typing import Annotated
190
+ from fastapi import FastAPI, Request
191
+ from t402.types import PaymentRequiredResponse, PaymentRequirements
192
+ from t402.encoding import safe_base64_decode
193
+
194
+ payment_requirements = PaymentRequirements(...)
195
+ facilitator = FacilitatorClient(facilitator_url)
196
+
197
+ @app.get("/foo")
198
+ async def foo(req: request: Request):
199
+ payment_required = PaymentRequiredResponse(
200
+ t402_version: 1,
201
+ accepts=[payment_requirements],
202
+ error="",
203
+ )
204
+ payment_header = req.headers.get("X-PAYMENT", "")
205
+
206
+ if payment_header == "":
207
+ payment_required.error = "X-PAYMENT header not set"
208
+ return JSONResponse(
209
+ content=payment_required.model_dump(by_alias=True),
210
+ status_code=402,
211
+ )
212
+
213
+ payment = PaymentPayload(**json.loads(safe_base64_decode(payment_header)))
214
+
215
+ verify_response = await facilitator.verify(payment, payment_requirements)
216
+ if not verify_response.is_valid:
217
+ payment_required.error = "Invalid payment"
218
+ return JSONResponse(
219
+ content=payment_required.model_dump(by_alias=True),
220
+ status_code=402,
221
+ )
222
+
223
+ settle_response = await facilitator.settle(payment, payment_requirements)
224
+ if settle_response.success:
225
+ response.headers["X-PAYMENT-RESPONSE"] = base64.b64encode(
226
+ settle_response.model_dump_json().encode("utf-8")
227
+ ).decode("utf-8")
228
+ else:
229
+ payment_required.error = "Settle failed: " + settle_response.error
230
+ return JSONResponse(
231
+ content=payment_required.model_dump(by_alias=True),
232
+ status_code=402,
233
+ )
234
+ ```
235
+
236
+ For more examples and advanced usage patterns, check out our [examples directory](https://github.com/awesome-doge/t402/tree/main/examples/python).
t402-1.0.0/README.md ADDED
@@ -0,0 +1,217 @@
1
+ # t402 Python
2
+
3
+ Python package for the t402 payments protocol.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install t402
9
+ ```
10
+
11
+ ## Overview
12
+
13
+ The t402 package provides the core building blocks for implementing the t402 Payment Protocol in Python. It's designed to be used by:
14
+
15
+ - FastAPI middleware for accepting payments
16
+ - Flask middleware for accepting payments
17
+ - httpx client for paying resources
18
+ - requests client for paying resources
19
+
20
+ ## FastAPI Integration
21
+
22
+ The simplest way to add t402 payment protection to your FastAPI application:
23
+
24
+ ```py
25
+ from fastapi import FastAPI
26
+ from t402.fastapi.middleware import require_payment
27
+
28
+ app = FastAPI()
29
+ app.middleware("http")(
30
+ require_payment(price="0.01", pay_to_address="0x209693Bc6afc0C5328bA36FaF03C514EF312287C")
31
+ )
32
+
33
+ @app.get("/")
34
+ async def root():
35
+ return {"message": "Hello World"}
36
+ ```
37
+
38
+ To protect specific routes:
39
+
40
+ ```py
41
+ app.middleware("http")(
42
+ require_payment(price="0.01",
43
+ pay_to_address="0x209693Bc6afc0C5328bA36FaF03C514EF312287C"),
44
+ path="/foo" # <-- this can also be a list ex: ["/foo", "/bar"]
45
+ )
46
+ ```
47
+
48
+ ## Flask Integration
49
+
50
+ The simplest way to add t402 payment protection to your Flask application:
51
+
52
+ ```py
53
+ from flask import Flask
54
+ from t402.flask.middleware import PaymentMiddleware
55
+
56
+ app = Flask(__name__)
57
+
58
+ # Initialize payment middleware
59
+ payment_middleware = PaymentMiddleware(app)
60
+
61
+ # Add payment protection for all routes
62
+ payment_middleware.add(
63
+ price="$0.01",
64
+ pay_to_address="0x209693Bc6afc0C5328bA36FaF03C514EF312287C",
65
+ )
66
+
67
+ @app.route("/")
68
+ def root():
69
+ return {"message": "Hello World"}
70
+ ```
71
+
72
+ To protect specific routes:
73
+
74
+ ```py
75
+ # Protect specific endpoint
76
+ payment_middleware.add(
77
+ path="/foo",
78
+ price="$0.001",
79
+ pay_to_address="0x209693Bc6afc0C5328bA36FaF03C514EF312287C",
80
+ )
81
+ ```
82
+
83
+ ## Client Integration
84
+
85
+ ### Simple Usage
86
+
87
+ #### Httpx Client
88
+ ```py
89
+ from eth_account import Account
90
+ from t402.clients.httpx import t402HttpxClient
91
+
92
+ # Initialize account
93
+ account = Account.from_key("your_private_key")
94
+
95
+ # Create client and make request
96
+ async with t402HttpxClient(account=account, base_url="https://api.example.com") as client:
97
+ response = await client.get("/protected-endpoint")
98
+ print(await response.aread())
99
+ ```
100
+
101
+ #### Requests Session Client
102
+ ```py
103
+ from eth_account import Account
104
+ from t402.clients.requests import t402_requests
105
+
106
+ # Initialize account
107
+ account = Account.from_key("your_private_key")
108
+
109
+ # Create session and make request
110
+ session = t402_requests(account)
111
+ response = session.get("https://api.example.com/protected-endpoint")
112
+ print(response.content)
113
+ ```
114
+
115
+ ### Advanced Usage
116
+
117
+ #### Httpx Extensible Example
118
+ ```py
119
+ import httpx
120
+ from eth_account import Account
121
+ from t402.clients.httpx import t402_payment_hooks
122
+
123
+ # Initialize account
124
+ account = Account.from_key("your_private_key")
125
+
126
+ # Create httpx client with t402 payment hooks
127
+ async with httpx.AsyncClient(base_url="https://api.example.com") as client:
128
+ # Add payment hooks directly to client
129
+ client.event_hooks = t402_payment_hooks(account)
130
+
131
+ # Make request - payment handling is automatic
132
+ response = await client.get("/protected-endpoint")
133
+ print(await response.aread())
134
+ ```
135
+
136
+ #### Requests Session Extensible Example
137
+ ```py
138
+ import requests
139
+ from eth_account import Account
140
+ from t402.clients.requests import t402_http_adapter
141
+
142
+ # Initialize account
143
+ account = Account.from_key("your_private_key")
144
+
145
+ # Create session and mount the t402 adapter
146
+ session = requests.Session()
147
+ adapter = t402_http_adapter(account)
148
+
149
+ # Mount the adapter for both HTTP and HTTPS
150
+ session.mount("http://", adapter)
151
+ session.mount("https://", adapter)
152
+
153
+ # Make request - payment handling is automatic
154
+ response = session.get("https://api.example.com/protected-endpoint")
155
+ print(response.content)
156
+ ```
157
+
158
+ ## Manual Server Integration
159
+
160
+ If you're not using the FastAPI middleware, you can implement the t402 protocol manually. Here's what you'll need to handle:
161
+
162
+ 1. Return 402 error responses with the appropriate response body
163
+ 2. Use the facilitator to validate payments
164
+ 3. Use the facilitator to settle payments
165
+ 4. Return the appropriate response header to the caller
166
+
167
+ Here's an example of manual integration:
168
+
169
+ ```py
170
+ from typing import Annotated
171
+ from fastapi import FastAPI, Request
172
+ from t402.types import PaymentRequiredResponse, PaymentRequirements
173
+ from t402.encoding import safe_base64_decode
174
+
175
+ payment_requirements = PaymentRequirements(...)
176
+ facilitator = FacilitatorClient(facilitator_url)
177
+
178
+ @app.get("/foo")
179
+ async def foo(req: request: Request):
180
+ payment_required = PaymentRequiredResponse(
181
+ t402_version: 1,
182
+ accepts=[payment_requirements],
183
+ error="",
184
+ )
185
+ payment_header = req.headers.get("X-PAYMENT", "")
186
+
187
+ if payment_header == "":
188
+ payment_required.error = "X-PAYMENT header not set"
189
+ return JSONResponse(
190
+ content=payment_required.model_dump(by_alias=True),
191
+ status_code=402,
192
+ )
193
+
194
+ payment = PaymentPayload(**json.loads(safe_base64_decode(payment_header)))
195
+
196
+ verify_response = await facilitator.verify(payment, payment_requirements)
197
+ if not verify_response.is_valid:
198
+ payment_required.error = "Invalid payment"
199
+ return JSONResponse(
200
+ content=payment_required.model_dump(by_alias=True),
201
+ status_code=402,
202
+ )
203
+
204
+ settle_response = await facilitator.settle(payment, payment_requirements)
205
+ if settle_response.success:
206
+ response.headers["X-PAYMENT-RESPONSE"] = base64.b64encode(
207
+ settle_response.model_dump_json().encode("utf-8")
208
+ ).decode("utf-8")
209
+ else:
210
+ payment_required.error = "Settle failed: " + settle_response.error
211
+ return JSONResponse(
212
+ content=payment_required.model_dump(by_alias=True),
213
+ status_code=402,
214
+ )
215
+ ```
216
+
217
+ For more examples and advanced usage patterns, check out our [examples directory](https://github.com/awesome-doge/t402/tree/main/examples/python).
@@ -0,0 +1,45 @@
1
+ [project]
2
+ name = "t402"
3
+ version = "1.0.0"
4
+ description = "t402: An internet native payments protocol"
5
+ readme = "README.md"
6
+ license = { text = "Apache-2.0" }
7
+ authors = [
8
+ { name = "T402 Team", email = "dev@t402.io" }
9
+ ]
10
+ requires-python = ">=3.10"
11
+ keywords = ["t402", "sdk", "crypto", "usdt", "payments", "web3", "tether"]
12
+ dependencies = [
13
+ "eth-account>=0.13.7",
14
+ "eth-typing>=4.0.0",
15
+ "eth-utils>=3.0.0",
16
+ "fastapi[standard]>=0.115.12",
17
+ "flask>=3.0.0",
18
+ "pydantic>=2.10.3",
19
+ "pydantic-settings>=2.2.1",
20
+ "python-dotenv>=1.0.1",
21
+ "web3>=6.0.0",
22
+ ]
23
+
24
+ [project.scripts]
25
+
26
+
27
+ [build-system]
28
+ requires = ["hatchling"]
29
+ build-backend = "hatchling.build"
30
+
31
+ [dependency-groups]
32
+ dev = [
33
+ "pytest>=8.3.5",
34
+ "pytest-asyncio>=1.0.0",
35
+ "ruff>=0.11.9",
36
+ ]
37
+
38
+ [tool.pytest.ini_options]
39
+ asyncio_mode = "auto"
40
+
41
+ [tool.hatch.build.targets.wheel]
42
+ packages = ["src/t402"]
43
+
44
+ [tool.hatch.metadata]
45
+ allow-direct-references = true
@@ -0,0 +1,2 @@
1
+ def hello() -> str:
2
+ return "Hello from t402!"
@@ -0,0 +1,92 @@
1
+ NETWORK_TO_ID = {
2
+ "base-sepolia": "84532",
3
+ "base": "8453",
4
+ "avalanche-fuji": "43113",
5
+ "avalanche": "43114",
6
+ }
7
+
8
+
9
+ def get_chain_id(network: str) -> str:
10
+ """Get the chain ID for a given network
11
+ Supports string encoded chain IDs and human readable networks
12
+ """
13
+ try:
14
+ int(network)
15
+ return network
16
+ except ValueError:
17
+ pass
18
+ if network not in NETWORK_TO_ID:
19
+ raise ValueError(f"Unsupported network: {network}")
20
+ return NETWORK_TO_ID[network]
21
+
22
+
23
+ KNOWN_TOKENS = {
24
+ "84532": [
25
+ {
26
+ "human_name": "usdc",
27
+ "address": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
28
+ "name": "USDC",
29
+ "decimals": 6,
30
+ "version": "2",
31
+ }
32
+ ],
33
+ "8453": [
34
+ {
35
+ "human_name": "usdc",
36
+ "address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
37
+ "name": "USD Coin", # needs to be exactly what is returned by name() on contract
38
+ "decimals": 6,
39
+ "version": "2",
40
+ }
41
+ ],
42
+ "43113": [
43
+ {
44
+ "human_name": "usdc",
45
+ "address": "0x5425890298aed601595a70AB815c96711a31Bc65",
46
+ "name": "USD Coin",
47
+ "decimals": 6,
48
+ "version": "2",
49
+ }
50
+ ],
51
+ "43114": [
52
+ {
53
+ "human_name": "usdc",
54
+ "address": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
55
+ "name": "USDC",
56
+ "decimals": 6,
57
+ "version": "2",
58
+ }
59
+ ],
60
+ }
61
+
62
+
63
+ def get_token_name(chain_id: str, address: str) -> str:
64
+ """Get the token name for a given chain and address"""
65
+ for token in KNOWN_TOKENS[chain_id]:
66
+ if token["address"] == address:
67
+ return token["name"]
68
+ raise ValueError(f"Token not found for chain {chain_id} and address {address}")
69
+
70
+
71
+ def get_token_version(chain_id: str, address: str) -> str:
72
+ """Get the token version for a given chain and address"""
73
+ for token in KNOWN_TOKENS[chain_id]:
74
+ if token["address"] == address:
75
+ return token["version"]
76
+ raise ValueError(f"Token not found for chain {chain_id} and address {address}")
77
+
78
+
79
+ def get_token_decimals(chain_id: str, address: str) -> int:
80
+ """Get the token decimals for a given chain and address"""
81
+ for token in KNOWN_TOKENS[chain_id]:
82
+ if token["address"] == address:
83
+ return token["decimals"]
84
+ raise ValueError(f"Token not found for chain {chain_id} and address {address}")
85
+
86
+
87
+ def get_default_token_address(chain_id: str, token_type: str = "usdc") -> str:
88
+ """Get the default token address for a given chain and token type"""
89
+ for token in KNOWN_TOKENS[chain_id]:
90
+ if token["human_name"] == token_type:
91
+ return token["address"]
92
+ raise ValueError(f"Token type '{token_type}' not found for chain {chain_id}")
@@ -0,0 +1,20 @@
1
+ from t402.clients.base import t402Client, decode_x_payment_response
2
+ from t402.clients.httpx import (
3
+ t402_payment_hooks,
4
+ t402HttpxClient,
5
+ )
6
+ from t402.clients.requests import (
7
+ t402HTTPAdapter,
8
+ t402_http_adapter,
9
+ t402_requests,
10
+ )
11
+
12
+ __all__ = [
13
+ "t402Client",
14
+ "decode_x_payment_response",
15
+ "t402_payment_hooks",
16
+ "t402HttpxClient",
17
+ "t402HTTPAdapter",
18
+ "t402_http_adapter",
19
+ "t402_requests",
20
+ ]