t402 1.9.1__tar.gz → 1.10.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.
- t402-1.10.0/.gitignore +59 -0
- {t402-1.9.1 → t402-1.10.0}/PKG-INFO +3 -3
- {t402-1.9.1 → t402-1.10.0}/README.md +2 -2
- {t402-1.9.1 → t402-1.10.0}/pyproject.toml +2 -1
- {t402-1.9.1 → t402-1.10.0}/src/t402/__init__.py +1 -1
- t402-1.10.0/src/t402/a2a/__init__.py +73 -0
- t402-1.10.0/src/t402/a2a/helpers.py +158 -0
- t402-1.10.0/src/t402/a2a/types.py +145 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/bridge/constants.py +1 -1
- t402-1.10.0/src/t402/django/__init__.py +42 -0
- t402-1.10.0/src/t402/django/middleware.py +596 -0
- t402-1.10.0/src/t402/errors.py +213 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/facilitator.py +125 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/mcp/constants.py +3 -6
- {t402-1.9.1 → t402-1.10.0}/src/t402/mcp/server.py +428 -44
- t402-1.10.0/src/t402/mcp/web3_utils.py +493 -0
- t402-1.10.0/src/t402/multisig/__init__.py +120 -0
- t402-1.10.0/src/t402/multisig/constants.py +54 -0
- t402-1.10.0/src/t402/multisig/safe.py +441 -0
- t402-1.10.0/src/t402/multisig/signature.py +228 -0
- t402-1.10.0/src/t402/multisig/transaction.py +238 -0
- t402-1.10.0/src/t402/multisig/types.py +108 -0
- t402-1.10.0/src/t402/multisig/utils.py +77 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/__init__.py +19 -0
- t402-1.10.0/src/t402/schemes/cosmos/__init__.py +114 -0
- t402-1.10.0/src/t402/schemes/cosmos/constants.py +211 -0
- t402-1.10.0/src/t402/schemes/cosmos/exact_direct/__init__.py +21 -0
- t402-1.10.0/src/t402/schemes/cosmos/exact_direct/client.py +198 -0
- t402-1.10.0/src/t402/schemes/cosmos/exact_direct/facilitator.py +493 -0
- t402-1.10.0/src/t402/schemes/cosmos/exact_direct/server.py +315 -0
- t402-1.10.0/src/t402/schemes/cosmos/types.py +501 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/evm/__init__.py +1 -1
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/evm/exact_legacy/server.py +1 -1
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/near/__init__.py +25 -0
- t402-1.10.0/src/t402/schemes/near/upto/__init__.py +54 -0
- t402-1.10.0/src/t402/schemes/near/upto/types.py +272 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/svm/__init__.py +15 -0
- t402-1.10.0/src/t402/schemes/svm/upto/__init__.py +23 -0
- t402-1.10.0/src/t402/schemes/svm/upto/types.py +193 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/ton/__init__.py +15 -0
- t402-1.10.0/src/t402/schemes/ton/upto/__init__.py +31 -0
- t402-1.10.0/src/t402/schemes/ton/upto/types.py +215 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/tron/__init__.py +21 -4
- t402-1.10.0/src/t402/schemes/tron/upto/__init__.py +30 -0
- t402-1.10.0/src/t402/schemes/tron/upto/types.py +213 -0
- t402-1.10.0/src/t402/starlette/__init__.py +38 -0
- t402-1.10.0/src/t402/starlette/middleware.py +522 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/ton.py +1 -1
- {t402-1.9.1 → t402-1.10.0}/src/t402/ton_paywall_template.py +1 -1
- {t402-1.9.1 → t402-1.10.0}/src/t402/types.py +100 -2
- {t402-1.9.1 → t402-1.10.0}/src/t402/wdk/chains.py +1 -1
- t402-1.10.0/tests/test_a2a.py +285 -0
- {t402-1.9.1 → t402-1.10.0}/tests/test_aptos_scheme.py +0 -4
- t402-1.10.0/tests/test_cosmos_constants.py +197 -0
- t402-1.10.0/tests/test_cosmos_exact_direct.py +1145 -0
- t402-1.10.0/tests/test_cosmos_types.py +407 -0
- t402-1.10.0/tests/test_discovery_client.py +270 -0
- t402-1.10.0/tests/test_django_middleware.py +913 -0
- t402-1.10.0/tests/test_errors.py +125 -0
- {t402-1.9.1 → t402-1.10.0}/tests/test_evm_facilitator.py +0 -2
- t402-1.10.0/tests/test_mcp_tools.py +1050 -0
- t402-1.10.0/tests/test_multisig.py +380 -0
- {t402-1.9.1 → t402-1.10.0}/tests/test_near_scheme.py +1 -8
- {t402-1.9.1 → t402-1.10.0}/tests/test_polkadot_scheme.py +0 -4
- {t402-1.9.1 → t402-1.10.0}/tests/test_schemes.py +1 -1
- {t402-1.9.1 → t402-1.10.0}/tests/test_stacks_scheme.py +0 -10
- t402-1.10.0/tests/test_starlette_middleware.py +638 -0
- {t402-1.9.1 → t402-1.10.0}/tests/test_svm_scheme.py +0 -70
- {t402-1.9.1 → t402-1.10.0}/tests/test_tezos_scheme.py +0 -3
- {t402-1.9.1 → t402-1.10.0}/tests/test_ton_facilitator.py +0 -1
- {t402-1.9.1 → t402-1.10.0}/tests/test_tron_facilitator.py +1 -2
- {t402-1.9.1 → t402-1.10.0}/tests/test_upto_evm_facilitator.py +1 -2
- t402-1.10.0/tests/test_upto_near.py +393 -0
- t402-1.10.0/tests/test_upto_svm.py +382 -0
- t402-1.10.0/tests/test_upto_ton.py +344 -0
- t402-1.10.0/tests/test_upto_tron.py +339 -0
- {t402-1.9.1 → t402-1.10.0}/uv.lock +73 -2
- t402-1.9.1/.gitignore +0 -18
- {t402-1.9.1 → t402-1.10.0}/.python-version +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/bridge/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/bridge/client.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/bridge/router.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/bridge/scan.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/bridge/types.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/chains.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/cli.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/clients/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/clients/base.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/clients/httpx.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/clients/requests.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/common.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/cosmos_paywall_template.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/encoding.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/erc4337/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/erc4337/accounts.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/erc4337/bundlers.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/erc4337/paymasters.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/erc4337/types.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/evm_paywall_template.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/exact.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/fastapi/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/fastapi/dependencies.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/fastapi/middleware.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/flask/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/flask/middleware.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/mcp/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/mcp/tools.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/mcp/types.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/near_paywall_template.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/networks.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/path.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/paywall.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/py.typed +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/aptos/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/aptos/constants.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/aptos/exact_direct/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/aptos/exact_direct/client.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/aptos/exact_direct/facilitator.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/aptos/exact_direct/server.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/aptos/types.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/evm/exact/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/evm/exact/client.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/evm/exact/facilitator.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/evm/exact/server.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/evm/exact_legacy/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/evm/exact_legacy/client.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/evm/exact_legacy/facilitator.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/evm/upto/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/evm/upto/client.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/evm/upto/facilitator.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/evm/upto/server.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/evm/upto/types.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/interfaces.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/near/constants.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/near/exact_direct/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/near/exact_direct/client.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/near/exact_direct/facilitator.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/near/exact_direct/server.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/near/types.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/polkadot/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/polkadot/constants.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/polkadot/exact_direct/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/polkadot/exact_direct/client.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/polkadot/exact_direct/facilitator.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/polkadot/exact_direct/server.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/polkadot/types.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/registry.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/stacks/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/stacks/constants.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/stacks/exact_direct/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/stacks/exact_direct/client.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/stacks/exact_direct/facilitator.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/stacks/exact_direct/server.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/stacks/types.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/svm/exact/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/svm/exact/client.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/svm/exact/facilitator.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/svm/exact/server.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/tezos/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/tezos/constants.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/tezos/exact_direct/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/tezos/exact_direct/client.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/tezos/exact_direct/facilitator.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/tezos/exact_direct/server.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/tezos/types.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/ton/exact/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/ton/exact/client.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/ton/exact/facilitator.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/ton/exact/server.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/tron/exact/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/tron/exact/client.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/tron/exact/facilitator.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/tron/exact/server.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/upto/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/schemes/upto/types.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/stacks_paywall_template.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/svm.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/svm_paywall_template.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/tron.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/tron_paywall_template.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/wdk/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/wdk/errors.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/wdk/signer.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/src/t402/wdk/types.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/clients/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/clients/test_base.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/clients/test_httpx.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/clients/test_requests.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/fastapi_tests/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/fastapi_tests/test_middleware.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/flask_tests/__init__.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/flask_tests/test_middleware.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/test_bridge.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/test_cli.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/test_common.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/test_encoding.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/test_erc4337.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/test_exact.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/test_fastapi.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/test_mcp.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/test_paywall.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/test_svm.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/test_ton.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/test_tron.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/test_types.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/test_upto.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/test_upto_evm.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/test_upto_evm_server.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/test_v2_types.py +0 -0
- {t402-1.9.1 → t402-1.10.0}/tests/test_wdk.py +0 -0
t402-1.10.0/.gitignore
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Environment
|
|
2
|
+
.env
|
|
3
|
+
.env*.local
|
|
4
|
+
|
|
5
|
+
# Dependencies
|
|
6
|
+
node_modules/
|
|
7
|
+
|
|
8
|
+
# Build outputs
|
|
9
|
+
dist/
|
|
10
|
+
.next/
|
|
11
|
+
.turbo/
|
|
12
|
+
.vercel
|
|
13
|
+
.wrangler/
|
|
14
|
+
api-docs/
|
|
15
|
+
|
|
16
|
+
# Test coverage
|
|
17
|
+
coverage/
|
|
18
|
+
.coverage
|
|
19
|
+
coverage.out
|
|
20
|
+
*.coverprofile
|
|
21
|
+
|
|
22
|
+
# Python
|
|
23
|
+
__pycache__/
|
|
24
|
+
*.pyc
|
|
25
|
+
*.pyo
|
|
26
|
+
.venv/
|
|
27
|
+
|
|
28
|
+
# LaTeX build artifacts
|
|
29
|
+
whitepaper/build/
|
|
30
|
+
*.aux
|
|
31
|
+
*.bbl
|
|
32
|
+
*.blg
|
|
33
|
+
*.lof
|
|
34
|
+
*.lot
|
|
35
|
+
*.out
|
|
36
|
+
*.toc
|
|
37
|
+
|
|
38
|
+
# OS files
|
|
39
|
+
**/.DS_Store
|
|
40
|
+
|
|
41
|
+
# Editor
|
|
42
|
+
.claude/settings.local.json
|
|
43
|
+
|
|
44
|
+
# Project specific
|
|
45
|
+
proxy
|
|
46
|
+
e2e/facilitators/external-proxies/*
|
|
47
|
+
!e2e/facilitators/external-proxies/README.md
|
|
48
|
+
|
|
49
|
+
# Compiled Go binaries (e2e)
|
|
50
|
+
e2e/clients/go-http/client
|
|
51
|
+
e2e/clients/go-http/go-http
|
|
52
|
+
e2e/clients/go-http/main
|
|
53
|
+
e2e/facilitators/go/facilitator
|
|
54
|
+
e2e/facilitators/go/go
|
|
55
|
+
e2e/servers/gin/gin
|
|
56
|
+
e2e/servers/gin/server
|
|
57
|
+
|
|
58
|
+
# Archive
|
|
59
|
+
.archive/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: t402
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.10.0
|
|
4
4
|
Summary: t402: An internet native payments protocol
|
|
5
5
|
Author-email: T402 Team <dev@t402.io>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -391,7 +391,7 @@ result = await bridge.bridge(
|
|
|
391
391
|
|
|
392
392
|
## Deprecation Notice: exact-legacy Scheme
|
|
393
393
|
|
|
394
|
-
> **⚠️ Deprecated
|
|
394
|
+
> **⚠️ Deprecated**: The `exact-legacy` scheme is deprecated and will be removed in a future major version.
|
|
395
395
|
|
|
396
396
|
The `exact-legacy` scheme uses the traditional `approve + transferFrom` pattern for legacy USDT tokens. This has been superseded by the `exact` scheme with USDT0.
|
|
397
397
|
|
|
@@ -428,7 +428,7 @@ server_scheme = ExactEvmServerScheme()
|
|
|
428
428
|
| Arbitrum | `0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9` |
|
|
429
429
|
| Ink | `0x0200C29006150606B650577BBE7B6248F58470c1` |
|
|
430
430
|
| Berachain | `0x779Ded0c9e1022225f8E0630b35a9b54bE713736` |
|
|
431
|
-
| And 15+ more... | See [USDT0 documentation](https://docs.t402.io/
|
|
431
|
+
| And 15+ more... | See [USDT0 documentation](https://docs.t402.io/chains) |
|
|
432
432
|
|
|
433
433
|
## WDK Integration
|
|
434
434
|
|
|
@@ -366,7 +366,7 @@ result = await bridge.bridge(
|
|
|
366
366
|
|
|
367
367
|
## Deprecation Notice: exact-legacy Scheme
|
|
368
368
|
|
|
369
|
-
> **⚠️ Deprecated
|
|
369
|
+
> **⚠️ Deprecated**: The `exact-legacy` scheme is deprecated and will be removed in a future major version.
|
|
370
370
|
|
|
371
371
|
The `exact-legacy` scheme uses the traditional `approve + transferFrom` pattern for legacy USDT tokens. This has been superseded by the `exact` scheme with USDT0.
|
|
372
372
|
|
|
@@ -403,7 +403,7 @@ server_scheme = ExactEvmServerScheme()
|
|
|
403
403
|
| Arbitrum | `0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9` |
|
|
404
404
|
| Ink | `0x0200C29006150606B650577BBE7B6248F58470c1` |
|
|
405
405
|
| Berachain | `0x779Ded0c9e1022225f8E0630b35a9b54bE713736` |
|
|
406
|
-
| And 15+ more... | See [USDT0 documentation](https://docs.t402.io/
|
|
406
|
+
| And 15+ more... | See [USDT0 documentation](https://docs.t402.io/chains) |
|
|
407
407
|
|
|
408
408
|
## WDK Integration
|
|
409
409
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "t402"
|
|
3
|
-
version = "1.
|
|
3
|
+
version = "1.10.0"
|
|
4
4
|
description = "t402: An internet native payments protocol"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = { text = "Apache-2.0" }
|
|
@@ -46,6 +46,7 @@ dev = [
|
|
|
46
46
|
"ruff>=0.11.9",
|
|
47
47
|
"solana>=0.35.0",
|
|
48
48
|
"solders>=0.21.0",
|
|
49
|
+
"django>=4.2",
|
|
49
50
|
]
|
|
50
51
|
|
|
51
52
|
[tool.pytest.ini_options]
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""A2A (Agent-to-Agent) transport for t402 payments."""
|
|
2
|
+
|
|
3
|
+
from t402.a2a.types import (
|
|
4
|
+
T402_A2A_EXTENSION_URI,
|
|
5
|
+
A2A_EXTENSIONS_HEADER,
|
|
6
|
+
META_PAYMENT_STATUS,
|
|
7
|
+
META_PAYMENT_REQUIRED,
|
|
8
|
+
META_PAYMENT_PAYLOAD,
|
|
9
|
+
META_PAYMENT_RECEIPTS,
|
|
10
|
+
META_PAYMENT_ERROR,
|
|
11
|
+
STATUS_PAYMENT_REQUIRED,
|
|
12
|
+
STATUS_PAYMENT_REJECTED,
|
|
13
|
+
STATUS_PAYMENT_SUBMITTED,
|
|
14
|
+
STATUS_PAYMENT_VERIFIED,
|
|
15
|
+
STATUS_PAYMENT_COMPLETED,
|
|
16
|
+
STATUS_PAYMENT_FAILED,
|
|
17
|
+
A2AMessagePart,
|
|
18
|
+
A2AMessage,
|
|
19
|
+
A2ATaskStatus,
|
|
20
|
+
A2ATask,
|
|
21
|
+
A2AExtension,
|
|
22
|
+
A2AAgentCard,
|
|
23
|
+
A2ASkill,
|
|
24
|
+
)
|
|
25
|
+
from t402.a2a.helpers import (
|
|
26
|
+
is_payment_required,
|
|
27
|
+
is_payment_completed,
|
|
28
|
+
is_payment_failed,
|
|
29
|
+
get_payment_required,
|
|
30
|
+
get_payment_receipts,
|
|
31
|
+
has_payment_payload,
|
|
32
|
+
extract_payment_payload,
|
|
33
|
+
create_payment_required_message,
|
|
34
|
+
create_payment_submission_message,
|
|
35
|
+
create_payment_completed_message,
|
|
36
|
+
create_payment_failed_message,
|
|
37
|
+
create_t402_extension,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
__all__ = [
|
|
41
|
+
"T402_A2A_EXTENSION_URI",
|
|
42
|
+
"A2A_EXTENSIONS_HEADER",
|
|
43
|
+
"META_PAYMENT_STATUS",
|
|
44
|
+
"META_PAYMENT_REQUIRED",
|
|
45
|
+
"META_PAYMENT_PAYLOAD",
|
|
46
|
+
"META_PAYMENT_RECEIPTS",
|
|
47
|
+
"META_PAYMENT_ERROR",
|
|
48
|
+
"STATUS_PAYMENT_REQUIRED",
|
|
49
|
+
"STATUS_PAYMENT_REJECTED",
|
|
50
|
+
"STATUS_PAYMENT_SUBMITTED",
|
|
51
|
+
"STATUS_PAYMENT_VERIFIED",
|
|
52
|
+
"STATUS_PAYMENT_COMPLETED",
|
|
53
|
+
"STATUS_PAYMENT_FAILED",
|
|
54
|
+
"A2AMessagePart",
|
|
55
|
+
"A2AMessage",
|
|
56
|
+
"A2ATaskStatus",
|
|
57
|
+
"A2ATask",
|
|
58
|
+
"A2AExtension",
|
|
59
|
+
"A2AAgentCard",
|
|
60
|
+
"A2ASkill",
|
|
61
|
+
"is_payment_required",
|
|
62
|
+
"is_payment_completed",
|
|
63
|
+
"is_payment_failed",
|
|
64
|
+
"get_payment_required",
|
|
65
|
+
"get_payment_receipts",
|
|
66
|
+
"has_payment_payload",
|
|
67
|
+
"extract_payment_payload",
|
|
68
|
+
"create_payment_required_message",
|
|
69
|
+
"create_payment_submission_message",
|
|
70
|
+
"create_payment_completed_message",
|
|
71
|
+
"create_payment_failed_message",
|
|
72
|
+
"create_t402_extension",
|
|
73
|
+
]
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"""A2A helper functions for t402 payment message handling."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, Dict, List, Optional
|
|
6
|
+
|
|
7
|
+
from t402.a2a.types import (
|
|
8
|
+
A2AMessage,
|
|
9
|
+
A2AMessagePart,
|
|
10
|
+
A2ATask,
|
|
11
|
+
A2AExtension,
|
|
12
|
+
META_PAYMENT_ERROR,
|
|
13
|
+
META_PAYMENT_PAYLOAD,
|
|
14
|
+
META_PAYMENT_RECEIPTS,
|
|
15
|
+
META_PAYMENT_REQUIRED,
|
|
16
|
+
META_PAYMENT_STATUS,
|
|
17
|
+
STATUS_PAYMENT_COMPLETED,
|
|
18
|
+
STATUS_PAYMENT_FAILED,
|
|
19
|
+
STATUS_PAYMENT_REQUIRED,
|
|
20
|
+
STATUS_PAYMENT_SUBMITTED,
|
|
21
|
+
STATE_COMPLETED,
|
|
22
|
+
STATE_FAILED,
|
|
23
|
+
STATE_INPUT_REQUIRED,
|
|
24
|
+
T402_A2A_EXTENSION_URI,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def is_payment_required(task: A2ATask) -> bool:
|
|
29
|
+
"""Check if a task is in a payment-required state."""
|
|
30
|
+
if task.status.state != STATE_INPUT_REQUIRED:
|
|
31
|
+
return False
|
|
32
|
+
if task.status.message is None or task.status.message.metadata is None:
|
|
33
|
+
return False
|
|
34
|
+
return task.status.message.metadata.get(META_PAYMENT_STATUS) == STATUS_PAYMENT_REQUIRED
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def is_payment_completed(task: A2ATask) -> bool:
|
|
38
|
+
"""Check if a task has completed payment."""
|
|
39
|
+
if task.status.state != STATE_COMPLETED:
|
|
40
|
+
return False
|
|
41
|
+
if task.status.message is None or task.status.message.metadata is None:
|
|
42
|
+
return False
|
|
43
|
+
return task.status.message.metadata.get(META_PAYMENT_STATUS) == STATUS_PAYMENT_COMPLETED
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def is_payment_failed(task: A2ATask) -> bool:
|
|
47
|
+
"""Check if a task has failed payment."""
|
|
48
|
+
if task.status.state != STATE_FAILED:
|
|
49
|
+
return False
|
|
50
|
+
if task.status.message is None or task.status.message.metadata is None:
|
|
51
|
+
return False
|
|
52
|
+
return task.status.message.metadata.get(META_PAYMENT_STATUS) == STATUS_PAYMENT_FAILED
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def get_payment_required(task: A2ATask) -> Optional[Dict[str, Any]]:
|
|
56
|
+
"""Extract payment requirements from a task."""
|
|
57
|
+
if not is_payment_required(task):
|
|
58
|
+
return None
|
|
59
|
+
return task.status.message.metadata.get(META_PAYMENT_REQUIRED)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def get_payment_receipts(task: A2ATask) -> Optional[List[Any]]:
|
|
63
|
+
"""Extract payment receipts from a task."""
|
|
64
|
+
if task.status.message is None or task.status.message.metadata is None:
|
|
65
|
+
return None
|
|
66
|
+
return task.status.message.metadata.get(META_PAYMENT_RECEIPTS)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def has_payment_payload(msg: A2AMessage) -> bool:
|
|
70
|
+
"""Check if a message contains a payment submission."""
|
|
71
|
+
if msg.metadata is None:
|
|
72
|
+
return False
|
|
73
|
+
return (
|
|
74
|
+
msg.metadata.get(META_PAYMENT_STATUS) == STATUS_PAYMENT_SUBMITTED
|
|
75
|
+
and META_PAYMENT_PAYLOAD in msg.metadata
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def extract_payment_payload(msg: A2AMessage) -> Optional[Dict[str, Any]]:
|
|
80
|
+
"""Extract a payment payload from a message."""
|
|
81
|
+
if msg.metadata is None:
|
|
82
|
+
return None
|
|
83
|
+
return msg.metadata.get(META_PAYMENT_PAYLOAD)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def create_payment_required_message(
|
|
87
|
+
payment_required: Any,
|
|
88
|
+
text: str = "Payment is required to complete this request.",
|
|
89
|
+
) -> A2AMessage:
|
|
90
|
+
"""Create an agent message requesting payment."""
|
|
91
|
+
return A2AMessage(
|
|
92
|
+
kind="message",
|
|
93
|
+
role="agent",
|
|
94
|
+
parts=[A2AMessagePart(kind="text", text=text)],
|
|
95
|
+
metadata={
|
|
96
|
+
META_PAYMENT_STATUS: STATUS_PAYMENT_REQUIRED,
|
|
97
|
+
META_PAYMENT_REQUIRED: payment_required,
|
|
98
|
+
},
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def create_payment_submission_message(
|
|
103
|
+
payment_payload: Any,
|
|
104
|
+
text: str = "Here is the payment authorization.",
|
|
105
|
+
) -> A2AMessage:
|
|
106
|
+
"""Create a user message submitting payment."""
|
|
107
|
+
return A2AMessage(
|
|
108
|
+
kind="message",
|
|
109
|
+
role="user",
|
|
110
|
+
parts=[A2AMessagePart(kind="text", text=text)],
|
|
111
|
+
metadata={
|
|
112
|
+
META_PAYMENT_STATUS: STATUS_PAYMENT_SUBMITTED,
|
|
113
|
+
META_PAYMENT_PAYLOAD: payment_payload,
|
|
114
|
+
},
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def create_payment_completed_message(
|
|
119
|
+
receipts: Any,
|
|
120
|
+
text: str = "Payment successful.",
|
|
121
|
+
) -> A2AMessage:
|
|
122
|
+
"""Create an agent message confirming payment."""
|
|
123
|
+
return A2AMessage(
|
|
124
|
+
kind="message",
|
|
125
|
+
role="agent",
|
|
126
|
+
parts=[A2AMessagePart(kind="text", text=text)],
|
|
127
|
+
metadata={
|
|
128
|
+
META_PAYMENT_STATUS: STATUS_PAYMENT_COMPLETED,
|
|
129
|
+
META_PAYMENT_RECEIPTS: receipts,
|
|
130
|
+
},
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def create_payment_failed_message(
|
|
135
|
+
receipts: Any,
|
|
136
|
+
error_code: str,
|
|
137
|
+
text: str = "Payment failed.",
|
|
138
|
+
) -> A2AMessage:
|
|
139
|
+
"""Create an agent message reporting payment failure."""
|
|
140
|
+
return A2AMessage(
|
|
141
|
+
kind="message",
|
|
142
|
+
role="agent",
|
|
143
|
+
parts=[A2AMessagePart(kind="text", text=text)],
|
|
144
|
+
metadata={
|
|
145
|
+
META_PAYMENT_STATUS: STATUS_PAYMENT_FAILED,
|
|
146
|
+
META_PAYMENT_ERROR: error_code,
|
|
147
|
+
META_PAYMENT_RECEIPTS: receipts,
|
|
148
|
+
},
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def create_t402_extension(required: bool = False) -> A2AExtension:
|
|
153
|
+
"""Create a T402 extension declaration for agent cards."""
|
|
154
|
+
return A2AExtension(
|
|
155
|
+
uri=T402_A2A_EXTENSION_URI,
|
|
156
|
+
description="Supports payments using the t402 protocol for on-chain settlement.",
|
|
157
|
+
required=required,
|
|
158
|
+
)
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""A2A transport types for t402 payments."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Any, Dict, List, Optional
|
|
7
|
+
|
|
8
|
+
# Constants
|
|
9
|
+
T402_A2A_EXTENSION_URI = "https://github.com/google-a2a/a2a-t402/v0.1"
|
|
10
|
+
A2A_EXTENSIONS_HEADER = "X-A2A-Extensions"
|
|
11
|
+
|
|
12
|
+
# Payment metadata keys
|
|
13
|
+
META_PAYMENT_STATUS = "t402.payment.status"
|
|
14
|
+
META_PAYMENT_REQUIRED = "t402.payment.required"
|
|
15
|
+
META_PAYMENT_PAYLOAD = "t402.payment.payload"
|
|
16
|
+
META_PAYMENT_RECEIPTS = "t402.payment.receipts"
|
|
17
|
+
META_PAYMENT_ERROR = "t402.payment.error"
|
|
18
|
+
|
|
19
|
+
# Payment status values
|
|
20
|
+
STATUS_PAYMENT_REQUIRED = "payment-required"
|
|
21
|
+
STATUS_PAYMENT_REJECTED = "payment-rejected"
|
|
22
|
+
STATUS_PAYMENT_SUBMITTED = "payment-submitted"
|
|
23
|
+
STATUS_PAYMENT_VERIFIED = "payment-verified"
|
|
24
|
+
STATUS_PAYMENT_COMPLETED = "payment-completed"
|
|
25
|
+
STATUS_PAYMENT_FAILED = "payment-failed"
|
|
26
|
+
|
|
27
|
+
# Task state values
|
|
28
|
+
STATE_SUBMITTED = "submitted"
|
|
29
|
+
STATE_WORKING = "working"
|
|
30
|
+
STATE_INPUT_REQUIRED = "input-required"
|
|
31
|
+
STATE_COMPLETED = "completed"
|
|
32
|
+
STATE_CANCELED = "canceled"
|
|
33
|
+
STATE_FAILED = "failed"
|
|
34
|
+
STATE_UNKNOWN = "unknown"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass
|
|
38
|
+
class A2AMessagePart:
|
|
39
|
+
"""A message part (text, file, or data)."""
|
|
40
|
+
|
|
41
|
+
kind: str
|
|
42
|
+
text: Optional[str] = None
|
|
43
|
+
file: Optional[Dict[str, Any]] = None
|
|
44
|
+
data: Optional[Dict[str, Any]] = None
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass
|
|
48
|
+
class A2AMessage:
|
|
49
|
+
"""An A2A message with optional payment metadata."""
|
|
50
|
+
|
|
51
|
+
kind: str # always "message"
|
|
52
|
+
role: str # "user" or "agent"
|
|
53
|
+
parts: List[A2AMessagePart]
|
|
54
|
+
message_id: Optional[str] = None
|
|
55
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass
|
|
59
|
+
class A2ATaskStatus:
|
|
60
|
+
"""Current status of an A2A task."""
|
|
61
|
+
|
|
62
|
+
state: str
|
|
63
|
+
message: Optional[A2AMessage] = None
|
|
64
|
+
timestamp: Optional[str] = None
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@dataclass
|
|
68
|
+
class A2AArtifact:
|
|
69
|
+
"""Output from a completed task."""
|
|
70
|
+
|
|
71
|
+
kind: str
|
|
72
|
+
name: Optional[str] = None
|
|
73
|
+
mime_type: Optional[str] = None
|
|
74
|
+
data: Optional[str] = None
|
|
75
|
+
uri: Optional[str] = None
|
|
76
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@dataclass
|
|
80
|
+
class A2ATask:
|
|
81
|
+
"""An A2A task with status and history."""
|
|
82
|
+
|
|
83
|
+
kind: str # always "task"
|
|
84
|
+
id: str
|
|
85
|
+
status: A2ATaskStatus
|
|
86
|
+
session_id: Optional[str] = None
|
|
87
|
+
artifacts: Optional[List[A2AArtifact]] = None
|
|
88
|
+
history: Optional[List[A2AMessage]] = None
|
|
89
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@dataclass
|
|
93
|
+
class A2AExtension:
|
|
94
|
+
"""An A2A extension declaration."""
|
|
95
|
+
|
|
96
|
+
uri: str
|
|
97
|
+
description: Optional[str] = None
|
|
98
|
+
required: bool = False
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
@dataclass
|
|
102
|
+
class A2ACapabilities:
|
|
103
|
+
"""A2A agent capabilities."""
|
|
104
|
+
|
|
105
|
+
streaming: bool = False
|
|
106
|
+
push_notifications: bool = False
|
|
107
|
+
state_transition_history: bool = False
|
|
108
|
+
extensions: Optional[List[A2AExtension]] = None
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
@dataclass
|
|
112
|
+
class A2AProvider:
|
|
113
|
+
"""Agent provider information."""
|
|
114
|
+
|
|
115
|
+
organization: Optional[str] = None
|
|
116
|
+
url: Optional[str] = None
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@dataclass
|
|
120
|
+
class A2ASkill:
|
|
121
|
+
"""A2A skill definition."""
|
|
122
|
+
|
|
123
|
+
id: str
|
|
124
|
+
name: str
|
|
125
|
+
description: Optional[str] = None
|
|
126
|
+
tags: Optional[List[str]] = None
|
|
127
|
+
examples: Optional[List[str]] = None
|
|
128
|
+
input_modes: Optional[List[str]] = None
|
|
129
|
+
output_modes: Optional[List[str]] = None
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@dataclass
|
|
133
|
+
class A2AAgentCard:
|
|
134
|
+
"""A2A agent card (service advertisement)."""
|
|
135
|
+
|
|
136
|
+
name: str
|
|
137
|
+
url: str
|
|
138
|
+
description: Optional[str] = None
|
|
139
|
+
provider: Optional[A2AProvider] = None
|
|
140
|
+
version: Optional[str] = None
|
|
141
|
+
documentation_url: Optional[str] = None
|
|
142
|
+
capabilities: Optional[A2ACapabilities] = None
|
|
143
|
+
default_input_modes: Optional[List[str]] = None
|
|
144
|
+
default_output_modes: Optional[List[str]] = None
|
|
145
|
+
skills: Optional[List[A2ASkill]] = None
|
|
@@ -32,7 +32,7 @@ USDT0_OFT_ADDRESSES: dict[str, str] = {
|
|
|
32
32
|
"arbitrum": "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
|
|
33
33
|
"ink": "0x0200C29006150606B650577BBE7B6248F58470c1",
|
|
34
34
|
"berachain": "0x779Ded0c9e1022225f8E0630b35a9b54bE713736",
|
|
35
|
-
"unichain": "
|
|
35
|
+
"unichain": "0x9151434b16b9763660705744891fA906F660EcC5",
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
# Network to chain name mapping
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Django Integration for T402 Payment Protocol.
|
|
2
|
+
|
|
3
|
+
This package provides Django middleware for integrating T402 payments
|
|
4
|
+
into Django applications.
|
|
5
|
+
|
|
6
|
+
Features:
|
|
7
|
+
- PaymentMiddleware: Standard Django middleware for protecting routes
|
|
8
|
+
- V1 and V2 protocol support
|
|
9
|
+
- Automatic settlement on successful responses
|
|
10
|
+
- Browser paywall support
|
|
11
|
+
|
|
12
|
+
Usage:
|
|
13
|
+
```python
|
|
14
|
+
# settings.py
|
|
15
|
+
MIDDLEWARE = [
|
|
16
|
+
...
|
|
17
|
+
"t402.django.PaymentMiddleware",
|
|
18
|
+
...
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
T402_PAYMENT_CONFIGS = [
|
|
22
|
+
{
|
|
23
|
+
"path": "/api/premium/*",
|
|
24
|
+
"price": "$0.10",
|
|
25
|
+
"pay_to_address": "0x1234...",
|
|
26
|
+
"network": "eip155:8453",
|
|
27
|
+
},
|
|
28
|
+
]
|
|
29
|
+
```
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
from t402.django.middleware import (
|
|
33
|
+
PaymentMiddleware,
|
|
34
|
+
PaymentConfig,
|
|
35
|
+
PaymentDetails,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
__all__ = [
|
|
39
|
+
"PaymentMiddleware",
|
|
40
|
+
"PaymentConfig",
|
|
41
|
+
"PaymentDetails",
|
|
42
|
+
]
|