agentscore-commerce 2.0.0__tar.gz → 2.0.2__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.
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/PKG-INFO +1 -1
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/checkout.py +87 -1
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/checkout_hooks.py +4 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/pyproject.toml +1 -1
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_checkout.py +172 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_seamless_helpers.py +75 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/uv.lock +31 -31
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/.github/dependabot.yml +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/.github/workflows/ci.yml +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/.github/workflows/publish.yml +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/.github/workflows/security.yml +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/.gitignore +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/CLAUDE.md +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/CODE_OF_CONDUCT.md +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/CONTRIBUTING.md +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/LICENSE +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/README.md +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/SECURITY.md +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/__init__.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/api/__init__.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/challenge/__init__.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/challenge/accepted_methods.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/challenge/agent_instructions.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/challenge/agent_memory.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/challenge/body.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/challenge/how_to_pay.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/challenge/identity.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/challenge/pricing.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/challenge/receipt.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/challenge/respond_402.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/challenge/validation_error.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/discovery/__init__.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/discovery/agentscore_content.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/discovery/bazaar.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/discovery/llms_txt.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/discovery/openapi.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/discovery/probe.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/discovery/redemption_md.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/discovery/robots_tag.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/discovery/skill_md.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/discovery/well_known.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/discovery/well_known_mpp.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/discovery/well_known_x402.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/identity/__init__.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/identity/_denial.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/identity/_response.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/identity/a2a.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/identity/address.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/identity/aiohttp.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/identity/cache.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/identity/core.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/identity/django.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/identity/fastapi.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/identity/flask.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/identity/middleware.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/identity/policy.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/identity/py.typed +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/identity/sanic.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/identity/sessions.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/identity/signer.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/identity/tokens.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/identity/types.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/identity/ucp.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/identity/ucp_jwks.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/payment/__init__.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/payment/amounts.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/payment/directive.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/payment/dispatch.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/payment/headers.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/payment/idempotency.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/payment/lazy.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/payment/mppx_server.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/payment/networks.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/payment/rail_spec.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/payment/rails.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/payment/settlement_override.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/payment/signer.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/payment/solana.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/payment/usdc.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/payment/wwwauthenticate.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/payment/x402.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/payment/x402_server.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/payment/x402_settle.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/payment/x402_validation.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/payment/zero_settle.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/stripe_multichain/__init__.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/stripe_multichain/mppx_stripe.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/stripe_multichain/payment_intent.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/stripe_multichain/pi_cache.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/stripe_multichain/simulate_deposit.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/examples/README.md +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/examples/api_provider.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/examples/compliance_merchant.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/examples/identity_only.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/examples/multi_rail_merchant.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/examples/per_product_policy_merchant.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/examples/signed_ucp_merchant.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/examples/stripe_multichain_merchant.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/examples/variable_cost_merchant.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/lefthook.yml +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/ruff.toml +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/scripts/regenerate_cross_lang_fixtures.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/__init__.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/conftest.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/fixtures/cross-lang/node-agentscore-gate-blocked.json +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/fixtures/cross-lang/node-agentscore-gate-full.json +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/fixtures/cross-lang/node-capability.json +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/fixtures/cross-lang/node-emoji-keys.json +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/fixtures/cross-lang/node-es256-rails.json +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/fixtures/cross-lang/node-extras-int.json +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/fixtures/cross-lang/node-int-boundary.json +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/fixtures/cross-lang/node-minimal.json +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/fixtures/cross-lang/node-multikey.json +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/fixtures/cross-lang/node-unicode.json +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/fixtures/cross-lang/py-agentscore-gate-blocked.json +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/fixtures/cross-lang/py-agentscore-gate-full.json +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/fixtures/cross-lang/py-capability.json +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/fixtures/cross-lang/py-emoji-keys.json +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/fixtures/cross-lang/py-es256-rails.json +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/fixtures/cross-lang/py-extras-int.json +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/fixtures/cross-lang/py-int-boundary.json +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/fixtures/cross-lang/py-minimal.json +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/fixtures/cross-lang/py-multikey.json +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/fixtures/cross-lang/py-unicode.json +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_a2a.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_address.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_agent_memory_emitter.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_aiohttp.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_amounts.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_api_reexport.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_cache.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_challenge.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_classify_orchestration_error.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_core.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_coverage_fillers.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_denial.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_discovery.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_dispatch.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_django.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_fastapi.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_flask.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_gate_quota_info.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_get_signer_verdict.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_idempotency_helper.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_integration.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_lifted_helpers.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_load_ucp_signing_key_from_env.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_middleware.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_payment_directive.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_payment_dispatch.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_payment_handlers.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_payment_headers.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_payment_misc.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_payment_servers.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_payment_signer.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_policy.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_pricing.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_public_surface.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_rail_spec.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_response.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_robots_tag.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_sanic.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_sessions.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_signer_match.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_skill_md.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_stripe_multichain.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_tokens.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_ucp.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_ucp_cross_lang.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_ucp_jwks.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_validation_error.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/tests/test_zero_settle.py +0 -0
- {agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/vulture_whitelist.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentscore-commerce
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.2
|
|
4
4
|
Summary: Agent commerce SDK for Python — identity middleware (FastAPI, Flask, Django, AIOHTTP, Sanic, ASGI) + payment helpers + 402 builders + discovery + Stripe multichain. The full merchant-side toolkit for AgentScore-powered agent commerce.
|
|
5
5
|
Project-URL: Homepage, https://agentscore.sh
|
|
6
6
|
Project-URL: Repository, https://github.com/agentscore/python-commerce
|
|
@@ -450,6 +450,9 @@ class SettleOutcome:
|
|
|
450
450
|
"""``"evm"`` / ``"solana"`` for chain signers; ``None`` otherwise."""
|
|
451
451
|
payment_response_header: str | None = None
|
|
452
452
|
"""The ``PAYMENT-RESPONSE`` header to echo (x402 success path). ``None`` for MPP."""
|
|
453
|
+
payment_receipt_header: str | None = None
|
|
454
|
+
"""The ``Payment-Receipt`` header to echo (MPP success path, paymentauth.org §5).
|
|
455
|
+
``None`` for x402 and for the MPP zero-settle carve-out (no receipt minted)."""
|
|
453
456
|
raw: Any = None
|
|
454
457
|
"""The underlying settle result. Inspect for power-user fields (facilitator
|
|
455
458
|
diagnostics, raw receipt blobs); prefer the normalized fields above for the
|
|
@@ -490,6 +493,11 @@ class MppxComposeOutcome:
|
|
|
490
493
|
"""For ``status=200``: ``"evm"`` / ``"solana"`` depending on the rail."""
|
|
491
494
|
payment_response_header: str | None = None
|
|
492
495
|
"""For ``status=200``: optional PAYMENT-RESPONSE header echoed to the agent."""
|
|
496
|
+
payment_receipt_header: str | None = None
|
|
497
|
+
"""For ``status=200``: serialized ``Payment-Receipt`` header (base64url-encoded
|
|
498
|
+
receipt struct per pympp's ``Receipt.to_payment_receipt``). Echoed to the agent
|
|
499
|
+
so spec-strict MPP clients (tempo CLI, etc.) can lift tx_hash + source from
|
|
500
|
+
headers without parsing the JSON body."""
|
|
493
501
|
raw: Any = None
|
|
494
502
|
"""The underlying pympp compose result for ``on_settled`` introspection."""
|
|
495
503
|
|
|
@@ -540,6 +548,41 @@ async def _maybe_await(value: Any) -> Any:
|
|
|
540
548
|
return value
|
|
541
549
|
|
|
542
550
|
|
|
551
|
+
def _extract_mppx_receipt_header_from_raw(raw: Any) -> str | None:
|
|
552
|
+
"""Best-effort ``Payment-Receipt`` extraction from a custom hook's ``raw``.
|
|
553
|
+
|
|
554
|
+
Handles the three shapes hand-rolled hooks commonly return on a 200:
|
|
555
|
+
|
|
556
|
+
* The raw object itself exposes ``to_payment_receipt()`` (pympp Receipt
|
|
557
|
+
handed back directly).
|
|
558
|
+
* ``raw`` is a tuple ``(credential, receipt)`` (the pympp ``Mpp.charge``
|
|
559
|
+
return shape, unpacked but not re-wrapped).
|
|
560
|
+
* ``raw`` is a dict with ``receipt`` key, or an object with ``.receipt``
|
|
561
|
+
attribute (the auto-built hook's ``{"credential", "receipt"}`` dict).
|
|
562
|
+
|
|
563
|
+
Returns ``None`` when none of the shapes match, or the receipt's
|
|
564
|
+
``to_payment_receipt`` raises: the response then omits the header rather
|
|
565
|
+
than emitting a malformed value.
|
|
566
|
+
"""
|
|
567
|
+
candidates: list[Any] = [raw]
|
|
568
|
+
if isinstance(raw, tuple | list) and len(raw) >= 2:
|
|
569
|
+
candidates.append(raw[1])
|
|
570
|
+
if isinstance(raw, dict) and "receipt" in raw:
|
|
571
|
+
candidates.append(raw["receipt"])
|
|
572
|
+
if hasattr(raw, "receipt"):
|
|
573
|
+
candidates.append(raw.receipt)
|
|
574
|
+
for candidate in candidates:
|
|
575
|
+
to_header = getattr(candidate, "to_payment_receipt", None)
|
|
576
|
+
if callable(to_header):
|
|
577
|
+
try:
|
|
578
|
+
value = to_header()
|
|
579
|
+
except Exception: # noqa: S112
|
|
580
|
+
continue
|
|
581
|
+
if isinstance(value, str) and value:
|
|
582
|
+
return value
|
|
583
|
+
return None
|
|
584
|
+
|
|
585
|
+
|
|
543
586
|
def _resolve_identity_metadata(ctx: CheckoutContext) -> dict[str, Any] | None:
|
|
544
587
|
"""Compose the identity_metadata block from request + assess state.
|
|
545
588
|
|
|
@@ -791,6 +834,31 @@ class Checkout:
|
|
|
791
834
|
return key
|
|
792
835
|
return "tempo"
|
|
793
836
|
|
|
837
|
+
def _rails_key_for_mppx_method(self, method: str) -> str | None:
|
|
838
|
+
"""Map an mppx credential ``method`` to the merchant's rails-dict key.
|
|
839
|
+
|
|
840
|
+
Used in ``_handle_mppx`` so the settle outcome distinguishes Solana
|
|
841
|
+
from Tempo (both fall under ``rail="mpp"``) and from Stripe SPT.
|
|
842
|
+
``method`` is one of ``tempo`` / ``solana`` / ``stripe``. Returns
|
|
843
|
+
``None`` when the merchant has no rail registered for that method.
|
|
844
|
+
"""
|
|
845
|
+
if method == "stripe":
|
|
846
|
+
for key, spec in self.rails.items():
|
|
847
|
+
if isinstance(spec, StripeRailSpec):
|
|
848
|
+
return key
|
|
849
|
+
return None
|
|
850
|
+
if method == "solana":
|
|
851
|
+
for key, spec in self.rails.items():
|
|
852
|
+
if isinstance(spec, SolanaMppRailSpec):
|
|
853
|
+
return key
|
|
854
|
+
return None
|
|
855
|
+
if method == "tempo":
|
|
856
|
+
for key, spec in self.rails.items():
|
|
857
|
+
if isinstance(spec, (TempoRailSpec, TempoSessionRailSpec)):
|
|
858
|
+
return key
|
|
859
|
+
return None
|
|
860
|
+
return None
|
|
861
|
+
|
|
794
862
|
@property
|
|
795
863
|
def _x402_base_network(self) -> str | None:
|
|
796
864
|
"""CAIP-2 read from ``rails['x402_base'].network`` (or its default).
|
|
@@ -1574,6 +1642,7 @@ class Checkout:
|
|
|
1574
1642
|
signer_address=carve.signer_address,
|
|
1575
1643
|
signer_network="evm" if carve.signer_address else None,
|
|
1576
1644
|
payment_response_header=None,
|
|
1645
|
+
payment_receipt_header=None,
|
|
1577
1646
|
raw=verified,
|
|
1578
1647
|
)
|
|
1579
1648
|
return await self._build_success(ctx, outcome)
|
|
@@ -1589,6 +1658,7 @@ class Checkout:
|
|
|
1589
1658
|
signer_address=carve.signer_address,
|
|
1590
1659
|
signer_network="evm" if carve.signer_address else None,
|
|
1591
1660
|
payment_response_header=None,
|
|
1661
|
+
payment_receipt_header=None,
|
|
1592
1662
|
raw=None,
|
|
1593
1663
|
)
|
|
1594
1664
|
return await self._build_success(ctx, outcome)
|
|
@@ -1705,6 +1775,7 @@ class Checkout:
|
|
|
1705
1775
|
signer_address=x402_signer.address if x402_signer else None,
|
|
1706
1776
|
signer_network=x402_signer.network if x402_signer else None,
|
|
1707
1777
|
payment_response_header=settle.payment_response_header,
|
|
1778
|
+
payment_receipt_header=None,
|
|
1708
1779
|
raw=settle,
|
|
1709
1780
|
)
|
|
1710
1781
|
return await self._build_success(ctx, outcome)
|
|
@@ -1715,13 +1786,26 @@ class Checkout:
|
|
|
1715
1786
|
raise RuntimeError(msg)
|
|
1716
1787
|
composed: MppxComposeOutcome = await _maybe_await(self.compose_mppx(ctx))
|
|
1717
1788
|
if composed.status == 200:
|
|
1789
|
+
receipt_method: str | None = None
|
|
1790
|
+
raw_receipt = composed.raw.get("receipt") if isinstance(composed.raw, dict) else None
|
|
1791
|
+
if isinstance(raw_receipt, dict):
|
|
1792
|
+
m = raw_receipt.get("method")
|
|
1793
|
+
if isinstance(m, str):
|
|
1794
|
+
receipt_method = m
|
|
1795
|
+
elif raw_receipt is not None:
|
|
1796
|
+
m = getattr(raw_receipt, "method", None)
|
|
1797
|
+
if isinstance(m, str):
|
|
1798
|
+
receipt_method = m
|
|
1799
|
+
derived_key = self._rails_key_for_mppx_method(receipt_method) if receipt_method is not None else None
|
|
1718
1800
|
outcome = SettleOutcome(
|
|
1719
1801
|
rail="mpp",
|
|
1720
|
-
rail_key=composed.rail_key,
|
|
1802
|
+
rail_key=derived_key or composed.rail_key or self._mpp_rail_key(),
|
|
1721
1803
|
tx_hash=composed.tx_hash,
|
|
1722
1804
|
signer_address=composed.signer_address,
|
|
1723
1805
|
signer_network=composed.signer_network,
|
|
1724
1806
|
payment_response_header=composed.payment_response_header,
|
|
1807
|
+
payment_receipt_header=composed.payment_receipt_header
|
|
1808
|
+
or _extract_mppx_receipt_header_from_raw(composed.raw),
|
|
1725
1809
|
raw=composed.raw,
|
|
1726
1810
|
)
|
|
1727
1811
|
return await self._build_success(ctx, outcome)
|
|
@@ -1862,6 +1946,8 @@ class Checkout:
|
|
|
1862
1946
|
headers: dict[str, str] = {}
|
|
1863
1947
|
if outcome.payment_response_header:
|
|
1864
1948
|
headers["payment-response"] = outcome.payment_response_header
|
|
1949
|
+
if outcome.payment_receipt_header:
|
|
1950
|
+
headers["payment-receipt"] = outcome.payment_receipt_header
|
|
1865
1951
|
return CheckoutResult(
|
|
1866
1952
|
status=200,
|
|
1867
1953
|
body=body,
|
{agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/checkout_hooks.py
RENAMED
|
@@ -93,11 +93,15 @@ def make_mppx_compose_hook(
|
|
|
93
93
|
signer_address = signer.address
|
|
94
94
|
signer_network = signer.network
|
|
95
95
|
|
|
96
|
+
to_header = getattr(receipt, "to_payment_receipt", None)
|
|
97
|
+
payment_receipt_header = to_header() if callable(to_header) else None
|
|
98
|
+
|
|
96
99
|
return MppxComposeOutcome(
|
|
97
100
|
status=200,
|
|
98
101
|
tx_hash=tx_hash,
|
|
99
102
|
signer_address=signer_address,
|
|
100
103
|
signer_network=signer_network,
|
|
104
|
+
payment_receipt_header=payment_receipt_header,
|
|
101
105
|
raw={"credential": credential, "receipt": receipt},
|
|
102
106
|
)
|
|
103
107
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "agentscore-commerce"
|
|
7
|
-
version = "2.0.
|
|
7
|
+
version = "2.0.2"
|
|
8
8
|
description = "Agent commerce SDK for Python — identity middleware (FastAPI, Flask, Django, AIOHTTP, Sanic, ASGI) + payment helpers + 402 builders + discovery + Stripe multichain. The full merchant-side toolkit for AgentScore-powered agent commerce."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -300,6 +300,142 @@ async def test_compose_mppx_returns_200_runs_on_settled() -> None:
|
|
|
300
300
|
on_settled.assert_awaited_once()
|
|
301
301
|
|
|
302
302
|
|
|
303
|
+
@pytest.mark.asyncio
|
|
304
|
+
async def test_compose_mppx_payment_receipt_header_surfaces_on_response() -> None:
|
|
305
|
+
"""When ``compose_mppx`` populates ``payment_receipt_header``, Checkout echoes
|
|
306
|
+
it as a ``payment-receipt`` HTTP header on the success response — symmetric
|
|
307
|
+
to the existing ``payment_response_header`` (x402) behavior."""
|
|
308
|
+
receipt_header = "eyJzdGF0dXMiOiJzdWNjZXNzIn0"
|
|
309
|
+
compose_mppx = AsyncMock(
|
|
310
|
+
return_value=MppxComposeOutcome(status=200, payment_receipt_header=receipt_header),
|
|
311
|
+
)
|
|
312
|
+
checkout = Checkout(
|
|
313
|
+
rails={"tempo": TempoRailSpec(recipient="0xtempo")},
|
|
314
|
+
url="https://api.example/purchase",
|
|
315
|
+
compute_pricing=lambda _ctx: PricingResult(amount_usd=10.0),
|
|
316
|
+
compose_mppx=compose_mppx,
|
|
317
|
+
)
|
|
318
|
+
result = await checkout.handle(_req(headers={"authorization": "Payment id=abc"}))
|
|
319
|
+
assert result.status == 200
|
|
320
|
+
assert result.headers["payment-receipt"] == receipt_header
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
@pytest.mark.asyncio
|
|
324
|
+
async def test_compose_mppx_omitted_payment_receipt_header_emits_no_header() -> None:
|
|
325
|
+
"""Default ``payment_receipt_header=None`` on the compose outcome must NOT
|
|
326
|
+
emit an empty ``payment-receipt`` header on the response."""
|
|
327
|
+
compose_mppx = AsyncMock(return_value=MppxComposeOutcome(status=200))
|
|
328
|
+
checkout = Checkout(
|
|
329
|
+
rails={"tempo": TempoRailSpec(recipient="0xtempo")},
|
|
330
|
+
url="https://api.example/purchase",
|
|
331
|
+
compute_pricing=lambda _ctx: PricingResult(amount_usd=10.0),
|
|
332
|
+
compose_mppx=compose_mppx,
|
|
333
|
+
)
|
|
334
|
+
result = await checkout.handle(_req(headers={"authorization": "Payment id=abc"}))
|
|
335
|
+
assert result.status == 200
|
|
336
|
+
assert "payment-receipt" not in result.headers
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
@pytest.mark.asyncio
|
|
340
|
+
async def test_compose_mppx_auto_extracts_receipt_header_from_raw_dict() -> None:
|
|
341
|
+
"""When a custom compose_mppx returns ``raw={'credential': c, 'receipt': r}``
|
|
342
|
+
(the auto-built hook's shape) without explicitly setting
|
|
343
|
+
``payment_receipt_header``, Checkout lifts the header from ``r.to_payment_receipt()``."""
|
|
344
|
+
|
|
345
|
+
class _Receipt:
|
|
346
|
+
@staticmethod
|
|
347
|
+
def to_payment_receipt() -> str:
|
|
348
|
+
return "auto-from-raw-dict"
|
|
349
|
+
|
|
350
|
+
compose_mppx = AsyncMock(
|
|
351
|
+
return_value=MppxComposeOutcome(status=200, raw={"credential": object(), "receipt": _Receipt()}),
|
|
352
|
+
)
|
|
353
|
+
checkout = Checkout(
|
|
354
|
+
rails={"tempo": TempoRailSpec(recipient="0xtempo")},
|
|
355
|
+
url="https://api.example/purchase",
|
|
356
|
+
compute_pricing=lambda _ctx: PricingResult(amount_usd=10.0),
|
|
357
|
+
compose_mppx=compose_mppx,
|
|
358
|
+
)
|
|
359
|
+
result = await checkout.handle(_req(headers={"authorization": "Payment id=abc"}))
|
|
360
|
+
assert result.status == 200
|
|
361
|
+
assert result.headers["payment-receipt"] == "auto-from-raw-dict"
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
@pytest.mark.asyncio
|
|
365
|
+
async def test_compose_mppx_auto_extracts_receipt_header_from_raw_tuple() -> None:
|
|
366
|
+
"""``raw=(credential, receipt)`` (the pympp Mpp.charge return) is also a
|
|
367
|
+
recognized shape — the second element's ``to_payment_receipt()`` is lifted."""
|
|
368
|
+
|
|
369
|
+
class _Receipt:
|
|
370
|
+
@staticmethod
|
|
371
|
+
def to_payment_receipt() -> str:
|
|
372
|
+
return "auto-from-raw-tuple"
|
|
373
|
+
|
|
374
|
+
compose_mppx = AsyncMock(
|
|
375
|
+
return_value=MppxComposeOutcome(status=200, raw=(object(), _Receipt())),
|
|
376
|
+
)
|
|
377
|
+
checkout = Checkout(
|
|
378
|
+
rails={"tempo": TempoRailSpec(recipient="0xtempo")},
|
|
379
|
+
url="https://api.example/purchase",
|
|
380
|
+
compute_pricing=lambda _ctx: PricingResult(amount_usd=10.0),
|
|
381
|
+
compose_mppx=compose_mppx,
|
|
382
|
+
)
|
|
383
|
+
result = await checkout.handle(_req(headers={"authorization": "Payment id=abc"}))
|
|
384
|
+
assert result.status == 200
|
|
385
|
+
assert result.headers["payment-receipt"] == "auto-from-raw-tuple"
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
@pytest.mark.asyncio
|
|
389
|
+
async def test_compose_mppx_explicit_payment_receipt_header_wins_over_raw() -> None:
|
|
390
|
+
"""When the hook sets ``payment_receipt_header`` explicitly, the auto-extract
|
|
391
|
+
from ``raw`` is NOT consulted."""
|
|
392
|
+
|
|
393
|
+
class _Receipt:
|
|
394
|
+
@staticmethod
|
|
395
|
+
def to_payment_receipt() -> str:
|
|
396
|
+
return "auto-IGNORED"
|
|
397
|
+
|
|
398
|
+
compose_mppx = AsyncMock(
|
|
399
|
+
return_value=MppxComposeOutcome(
|
|
400
|
+
status=200,
|
|
401
|
+
payment_receipt_header="explicit-value",
|
|
402
|
+
raw={"receipt": _Receipt()},
|
|
403
|
+
),
|
|
404
|
+
)
|
|
405
|
+
checkout = Checkout(
|
|
406
|
+
rails={"tempo": TempoRailSpec(recipient="0xtempo")},
|
|
407
|
+
url="https://api.example/purchase",
|
|
408
|
+
compute_pricing=lambda _ctx: PricingResult(amount_usd=10.0),
|
|
409
|
+
compose_mppx=compose_mppx,
|
|
410
|
+
)
|
|
411
|
+
result = await checkout.handle(_req(headers={"authorization": "Payment id=abc"}))
|
|
412
|
+
assert result.status == 200
|
|
413
|
+
assert result.headers["payment-receipt"] == "explicit-value"
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
@pytest.mark.asyncio
|
|
417
|
+
async def test_compose_mppx_receipt_to_header_that_throws_falls_through() -> None:
|
|
418
|
+
"""If ``to_payment_receipt()`` raises (unsupported pympp version, malformed
|
|
419
|
+
receipt), the SDK omits the header rather than emitting a malformed value."""
|
|
420
|
+
|
|
421
|
+
class _BadReceipt:
|
|
422
|
+
def to_payment_receipt(self) -> str:
|
|
423
|
+
raise RuntimeError("malformed receipt")
|
|
424
|
+
|
|
425
|
+
compose_mppx = AsyncMock(
|
|
426
|
+
return_value=MppxComposeOutcome(status=200, raw={"receipt": _BadReceipt()}),
|
|
427
|
+
)
|
|
428
|
+
checkout = Checkout(
|
|
429
|
+
rails={"tempo": TempoRailSpec(recipient="0xtempo")},
|
|
430
|
+
url="https://api.example/purchase",
|
|
431
|
+
compute_pricing=lambda _ctx: PricingResult(amount_usd=10.0),
|
|
432
|
+
compose_mppx=compose_mppx,
|
|
433
|
+
)
|
|
434
|
+
result = await checkout.handle(_req(headers={"authorization": "Payment id=abc"}))
|
|
435
|
+
assert result.status == 200
|
|
436
|
+
assert "payment-receipt" not in result.headers
|
|
437
|
+
|
|
438
|
+
|
|
303
439
|
@pytest.mark.asyncio
|
|
304
440
|
async def test_compose_mppx_returns_402_on_settle_leg_rejects_credential() -> None:
|
|
305
441
|
"""When the agent sends Authorization: Payment and mppx returns 402 (credential
|
|
@@ -437,3 +573,39 @@ def test_init_requires_x402_base_railspec_when_x402_server_provided() -> None:
|
|
|
437
573
|
compute_pricing=lambda _ctx: PricingResult(amount_usd=1.0),
|
|
438
574
|
x402_server=object(),
|
|
439
575
|
)
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
def test_rails_key_for_mppx_method_picks_the_matching_spec() -> None:
|
|
579
|
+
"""``_rails_key_for_mppx_method`` maps mppx credential methods (``tempo`` /
|
|
580
|
+
``solana`` / ``stripe``) to the merchant's actual rails-dict key, so MPP
|
|
581
|
+
settlements distinguish Solana from Tempo (both fall under
|
|
582
|
+
``SettleOutcome.rail="mpp"``) and from Stripe SPT.
|
|
583
|
+
"""
|
|
584
|
+
checkout = Checkout(
|
|
585
|
+
rails={
|
|
586
|
+
"tempo_charge": TempoRailSpec(recipient="0xtempo"),
|
|
587
|
+
"x402_base": X402BaseRailSpec(recipient="0xbase"),
|
|
588
|
+
"sol_rail": SolanaMppRailSpec(recipient="solanaaddr"),
|
|
589
|
+
"stripe_spt": StripeRailSpec(profile_id="profile_x"),
|
|
590
|
+
},
|
|
591
|
+
url="https://api.example/purchase",
|
|
592
|
+
compute_pricing=lambda _ctx: PricingResult(amount_usd=1.0),
|
|
593
|
+
)
|
|
594
|
+
assert checkout._rails_key_for_mppx_method("tempo") == "tempo_charge"
|
|
595
|
+
assert checkout._rails_key_for_mppx_method("solana") == "sol_rail"
|
|
596
|
+
assert checkout._rails_key_for_mppx_method("stripe") == "stripe_spt"
|
|
597
|
+
assert checkout._rails_key_for_mppx_method("unknown") is None
|
|
598
|
+
|
|
599
|
+
|
|
600
|
+
def test_rails_key_for_mppx_method_returns_none_when_rail_absent() -> None:
|
|
601
|
+
"""When the merchant hasn't registered a rail for the credential method,
|
|
602
|
+
the helper returns ``None`` so the caller can fall back to
|
|
603
|
+
``_mpp_rail_key()`` or a hard-coded default."""
|
|
604
|
+
checkout = Checkout(
|
|
605
|
+
rails={"tempo": TempoRailSpec(recipient="0xtempo")},
|
|
606
|
+
url="https://api.example/purchase",
|
|
607
|
+
compute_pricing=lambda _ctx: PricingResult(amount_usd=1.0),
|
|
608
|
+
)
|
|
609
|
+
assert checkout._rails_key_for_mppx_method("solana") is None
|
|
610
|
+
assert checkout._rails_key_for_mppx_method("stripe") is None
|
|
611
|
+
assert checkout._rails_key_for_mppx_method("tempo") == "tempo"
|
|
@@ -274,6 +274,81 @@ async def test_make_mppx_compose_hook_lifts_signer_from_did_pkh_eip155() -> None
|
|
|
274
274
|
assert out.signer_network == "evm"
|
|
275
275
|
|
|
276
276
|
|
|
277
|
+
@pytest.mark.asyncio
|
|
278
|
+
async def test_make_mppx_compose_hook_serializes_receipt_to_payment_receipt_header() -> None:
|
|
279
|
+
"""When the pympp ``Receipt`` exposes ``to_payment_receipt()``, the compose
|
|
280
|
+
hook lifts the serialized header onto ``MppxComposeOutcome.payment_receipt_header``
|
|
281
|
+
so Checkout can echo it as the response's ``Payment-Receipt`` header."""
|
|
282
|
+
|
|
283
|
+
class _Credential:
|
|
284
|
+
source = "did:pkh:eip155:8453:0xABCD000000000000000000000000000000000003"
|
|
285
|
+
|
|
286
|
+
class _Receipt:
|
|
287
|
+
reference = "0xtx_hash"
|
|
288
|
+
transaction = None
|
|
289
|
+
|
|
290
|
+
@staticmethod
|
|
291
|
+
def to_payment_receipt() -> str:
|
|
292
|
+
return "eyJzdGF0dXMiOiJzdWNjZXNzIn0"
|
|
293
|
+
|
|
294
|
+
class _Mpp:
|
|
295
|
+
realm = "r"
|
|
296
|
+
|
|
297
|
+
async def charge(self, *, authorization: str | None, amount: str) -> tuple:
|
|
298
|
+
return (_Credential(), _Receipt())
|
|
299
|
+
|
|
300
|
+
async def _getter() -> _Mpp:
|
|
301
|
+
return _Mpp()
|
|
302
|
+
|
|
303
|
+
hook = make_mppx_compose_hook(server_getter=_getter)
|
|
304
|
+
|
|
305
|
+
class _Pricing:
|
|
306
|
+
amount_usd = 0.1
|
|
307
|
+
|
|
308
|
+
class _Ctx:
|
|
309
|
+
request = _req({"authorization": "Payment somevalidcred"})
|
|
310
|
+
pricing = _Pricing()
|
|
311
|
+
|
|
312
|
+
out = await hook(_Ctx())
|
|
313
|
+
assert out.status == 200
|
|
314
|
+
assert out.payment_receipt_header == "eyJzdGF0dXMiOiJzdWNjZXNzIn0"
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
@pytest.mark.asyncio
|
|
318
|
+
async def test_make_mppx_compose_hook_omits_receipt_header_when_unavailable() -> None:
|
|
319
|
+
"""Older pympp Receipts without ``to_payment_receipt()`` leave the header
|
|
320
|
+
field None rather than raising or fabricating."""
|
|
321
|
+
|
|
322
|
+
class _Credential:
|
|
323
|
+
source = "did:pkh:eip155:8453:0xABCD000000000000000000000000000000000003"
|
|
324
|
+
|
|
325
|
+
class _Receipt:
|
|
326
|
+
reference = "0xtx_hash"
|
|
327
|
+
transaction = None
|
|
328
|
+
|
|
329
|
+
class _Mpp:
|
|
330
|
+
realm = "r"
|
|
331
|
+
|
|
332
|
+
async def charge(self, *, authorization: str | None, amount: str) -> tuple:
|
|
333
|
+
return (_Credential(), _Receipt())
|
|
334
|
+
|
|
335
|
+
async def _getter() -> _Mpp:
|
|
336
|
+
return _Mpp()
|
|
337
|
+
|
|
338
|
+
hook = make_mppx_compose_hook(server_getter=_getter)
|
|
339
|
+
|
|
340
|
+
class _Pricing:
|
|
341
|
+
amount_usd = 0.1
|
|
342
|
+
|
|
343
|
+
class _Ctx:
|
|
344
|
+
request = _req({"authorization": "Payment somevalidcred"})
|
|
345
|
+
pricing = _Pricing()
|
|
346
|
+
|
|
347
|
+
out = await hook(_Ctx())
|
|
348
|
+
assert out.status == 200
|
|
349
|
+
assert out.payment_receipt_header is None
|
|
350
|
+
|
|
351
|
+
|
|
277
352
|
@pytest.mark.asyncio
|
|
278
353
|
async def test_make_mppx_compose_hook_returns_402_when_charge_raises() -> None:
|
|
279
354
|
class _Mpp:
|
|
@@ -10,7 +10,7 @@ resolution-markers = [
|
|
|
10
10
|
|
|
11
11
|
[[package]]
|
|
12
12
|
name = "agentscore-commerce"
|
|
13
|
-
version = "2.0.
|
|
13
|
+
version = "2.0.2"
|
|
14
14
|
source = { editable = "." }
|
|
15
15
|
dependencies = [
|
|
16
16
|
{ name = "agentscore-py" },
|
|
@@ -662,14 +662,14 @@ wheels = [
|
|
|
662
662
|
|
|
663
663
|
[[package]]
|
|
664
664
|
name = "click"
|
|
665
|
-
version = "8.
|
|
665
|
+
version = "8.4.0"
|
|
666
666
|
source = { registry = "https://pypi.org/simple" }
|
|
667
667
|
dependencies = [
|
|
668
668
|
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
|
669
669
|
]
|
|
670
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
670
|
+
sdist = { url = "https://files.pythonhosted.org/packages/23/e4/796662cd90cf80e3a363c99db2b88e0e394b988a575f60a17e16440cd011/click-8.4.0.tar.gz", hash = "sha256:638f1338fe1235c8f4e008e4a8a254fb5c5fbdcbb40ece3c9142ebb78e792973", size = 350843, upload-time = "2026-05-17T00:47:58.425Z" }
|
|
671
671
|
wheels = [
|
|
672
|
-
{ url = "https://files.pythonhosted.org/packages/ae/
|
|
672
|
+
{ url = "https://files.pythonhosted.org/packages/ee/ae/8e92f8058baf87f6c7d86ee7e457668690195cc77efedb8d3797a06e3940/click-8.4.0-py3-none-any.whl", hash = "sha256:40c50b7c6c6adac2823d411041ec84f3f103f1b280d5e9ce0d7f998995832f81", size = 116147, upload-time = "2026-05-17T00:47:56.842Z" },
|
|
673
673
|
]
|
|
674
674
|
|
|
675
675
|
[[package]]
|
|
@@ -2222,14 +2222,14 @@ wheels = [
|
|
|
2222
2222
|
|
|
2223
2223
|
[[package]]
|
|
2224
2224
|
name = "pympp"
|
|
2225
|
-
version = "0.
|
|
2225
|
+
version = "0.8.0"
|
|
2226
2226
|
source = { registry = "https://pypi.org/simple" }
|
|
2227
2227
|
dependencies = [
|
|
2228
2228
|
{ name = "httpx" },
|
|
2229
2229
|
]
|
|
2230
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
2230
|
+
sdist = { url = "https://files.pythonhosted.org/packages/2d/c0/b7c18c939086564ee4dab503a353bd1d843d8881c0db9e150fe8a6bddaf7/pympp-0.8.0.tar.gz", hash = "sha256:8afe5e9a2ebd5898d6687f98dd8ee8533c64bf49ce04e36244383c461b1898fe", size = 146377, upload-time = "2026-05-16T17:24:15.529Z" }
|
|
2231
2231
|
wheels = [
|
|
2232
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2232
|
+
{ url = "https://files.pythonhosted.org/packages/3e/79/2a0b6f0a789a22c32c949a2fc039f5fea4e3fb781de08e6cb565aaa78522/pympp-0.8.0-py3-none-any.whl", hash = "sha256:2a377ad746efa6fe8e269794f4e3bea53520170347356abd44e424ad111207c9", size = 86851, upload-time = "2026-05-16T17:24:13.967Z" },
|
|
2233
2233
|
]
|
|
2234
2234
|
|
|
2235
2235
|
[package.optional-dependencies]
|
|
@@ -2330,11 +2330,11 @@ wheels = [
|
|
|
2330
2330
|
|
|
2331
2331
|
[[package]]
|
|
2332
2332
|
name = "python-multipart"
|
|
2333
|
-
version = "0.0.
|
|
2333
|
+
version = "0.0.29"
|
|
2334
2334
|
source = { registry = "https://pypi.org/simple" }
|
|
2335
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
2335
|
+
sdist = { url = "https://files.pythonhosted.org/packages/4e/fe/70bd71a6738b09a0bdf6480ca6436b167469ca4578b2a0efbe390b4b0e70/python_multipart-0.0.29.tar.gz", hash = "sha256:643e93849196645e2dbdd81a0f8829a23123ad7f797a84a364c6fb3563f18904", size = 45678, upload-time = "2026-05-17T17:29:47.654Z" }
|
|
2336
2336
|
wheels = [
|
|
2337
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2337
|
+
{ url = "https://files.pythonhosted.org/packages/8f/cb/769cfc37177252872a45a71f3fbdde9d51b471a3f3c14bfe95dde3407386/python_multipart-0.0.29-py3-none-any.whl", hash = "sha256:2ddcc971cef266225f54f552d8fa10bcfbb1f14446caec199060daac59ff2d69", size = 29640, upload-time = "2026-05-17T17:29:45.69Z" },
|
|
2338
2338
|
]
|
|
2339
2339
|
|
|
2340
2340
|
[[package]]
|
|
@@ -2976,27 +2976,27 @@ wheels = [
|
|
|
2976
2976
|
|
|
2977
2977
|
[[package]]
|
|
2978
2978
|
name = "ty"
|
|
2979
|
-
version = "0.0.
|
|
2980
|
-
source = { registry = "https://pypi.org/simple" }
|
|
2981
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
2982
|
-
wheels = [
|
|
2983
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2984
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2985
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2986
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2987
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2988
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2989
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2990
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2991
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2992
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2993
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2994
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2995
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2996
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2997
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2998
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2999
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
2979
|
+
version = "0.0.37"
|
|
2980
|
+
source = { registry = "https://pypi.org/simple" }
|
|
2981
|
+
sdist = { url = "https://files.pythonhosted.org/packages/c7/c3/60bc4829e0c1a8ff80b592067e1185a7b5ea64608acb0c676c44d5137d52/ty-0.0.37.tar.gz", hash = "sha256:f873f69627bd7f4ef8d57f716c63e5c63d7d1b7327ab3de185c7287a75223011", size = 5655422, upload-time = "2026-05-16T05:57:21.315Z" }
|
|
2982
|
+
wheels = [
|
|
2983
|
+
{ url = "https://files.pythonhosted.org/packages/b8/fe/180dd6914f9db33ad0200fbeaa429dd1fb0a4e6d98320dc1775f100a91af/ty-0.0.37-py3-none-linux_armv6l.whl", hash = "sha256:66cf7310189856e15f690559ddf37735476d2644db917d92f7cef13e5c834adf", size = 11246028, upload-time = "2026-05-16T05:57:41.744Z" },
|
|
2984
|
+
{ url = "https://files.pythonhosted.org/packages/ef/a2/fa0cfd31467ad99b2db8c81ee9e2b4574589974a3eb9723be825e15b300c/ty-0.0.37-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:2048f3c44ee6c7dde6e0ca064f99c6cada8f6de8ccdcfad2d856a429f8a4ac82", size = 11001460, upload-time = "2026-05-16T05:57:35.27Z" },
|
|
2985
|
+
{ url = "https://files.pythonhosted.org/packages/10/3f/db60ba9be8b95a464ece0ba103e534047c34b49fee12f5e101f83f8d66db/ty-0.0.37-py3-none-macosx_11_0_arm64.whl", hash = "sha256:32c7b9b5b626aacdec334b44a2698e5f7b80df55bf7338267084d00d4b9546b3", size = 10446549, upload-time = "2026-05-16T05:57:37.252Z" },
|
|
2986
|
+
{ url = "https://files.pythonhosted.org/packages/56/6f/11dd7174b20ebcb37a3d3b68f60b3940e37e4356e0accd03e2d7f9f70690/ty-0.0.37-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9fba1bebccf1e656bc5e3787acc5a191c491041ee4d12fe8fe2eff64e7b190d", size = 10961016, upload-time = "2026-05-16T05:57:16.394Z" },
|
|
2987
|
+
{ url = "https://files.pythonhosted.org/packages/65/dd/3c17ce2860c525817c42c82d7075391b1f5615d36c03aa2d26647a224e8a/ty-0.0.37-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f987c5fb59aa5017ee8e8c5b57a07390f584e58e572255acd0fa44b3e0b238df", size = 11022093, upload-time = "2026-05-16T05:57:32.741Z" },
|
|
2988
|
+
{ url = "https://files.pythonhosted.org/packages/d0/a8/e7a40b0b57660921dd3482d219add963973b52ae8507abd88f48439704b5/ty-0.0.37-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4168f53146e7a3f52560ff433f238352591c9b1a9ed09397fbb776ddef4f89c", size = 11486333, upload-time = "2026-05-16T05:57:18.839Z" },
|
|
2989
|
+
{ url = "https://files.pythonhosted.org/packages/da/5f/2c406b98244bc1ad42afdd35f466bcef88664210957dcbb5172254ff2462/ty-0.0.37-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11e487eafdb80a48223ce68a01f9287528216ffe0126d1629ff11e4f7c1dd3cf", size = 12093526, upload-time = "2026-05-16T05:57:04.456Z" },
|
|
2990
|
+
{ url = "https://files.pythonhosted.org/packages/d3/3c/5c492a38e1b21a26370727dd4b77a53f05262e53e3be232047f22e7fa1b3/ty-0.0.37-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b49f388d063668676daaa7eef57385089d1b844279c0185bd84d4dbc3bcede6", size = 11725957, upload-time = "2026-05-16T05:57:23.356Z" },
|
|
2991
|
+
{ url = "https://files.pythonhosted.org/packages/b2/00/8a3d9ba265cd0582342c14e4980cc0351aaaa45c6305712d398c9e2446c7/ty-0.0.37-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b96bfc1cc725d9d859abef4e3aa32a6da0f7472eaaafae2d9a6cffd729c7c61", size = 11610336, upload-time = "2026-05-16T05:57:27.888Z" },
|
|
2992
|
+
{ url = "https://files.pythonhosted.org/packages/91/4b/6ee172935cb842f5c1553b0d37215b45e9dde05a4c74fdb47fd271907122/ty-0.0.37-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:c55f39b519107cf234b794718793e11793c055e89028a282a309f690def48117", size = 11797856, upload-time = "2026-05-16T05:57:11.109Z" },
|
|
2993
|
+
{ url = "https://files.pythonhosted.org/packages/34/ef/75a7425bf9fe74483404ff11a8cbe3aa307354e0801697d6063384157776/ty-0.0.37-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c79204350de060a077bff7f027a1d53e216cad147d826ec9862be0af2f9c3c1e", size = 10941848, upload-time = "2026-05-16T05:57:30.653Z" },
|
|
2994
|
+
{ url = "https://files.pythonhosted.org/packages/e0/2c/7ea9dccd55961375067f99ed00fb8eabb491f6a06d0e5f09c797d2b900a6/ty-0.0.37-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:49a21b4dcb2cd94cd0298c96dfb71a2dd25f08bf7e6eefd0c33c519d058908c6", size = 11058248, upload-time = "2026-05-16T05:57:01.785Z" },
|
|
2995
|
+
{ url = "https://files.pythonhosted.org/packages/98/d7/848fde96c6610b2b1fd75823d44d8977a4525c4397f27332f054ccd6cf9c/ty-0.0.37-py3-none-musllinux_1_2_i686.whl", hash = "sha256:119332095c5974fe1dabfe4fd00c6759eeec5b99f7d7a80b2833feee5a58abdb", size = 11168423, upload-time = "2026-05-16T05:57:39.297Z" },
|
|
2996
|
+
{ url = "https://files.pythonhosted.org/packages/29/11/c1613ac4b64357b9067df68bac97bcb458cc426cd468a2782847238c539b/ty-0.0.37-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ac5dc593675414f68862c2f71cc04912b0e5ec5520a9c49fc71ed79205b95c33", size = 11698565, upload-time = "2026-05-16T05:57:14.206Z" },
|
|
2997
|
+
{ url = "https://files.pythonhosted.org/packages/5f/ac/961205863903881996adb5a6f9cfe570c132882922ac226540346f15df20/ty-0.0.37-py3-none-win32.whl", hash = "sha256:33b57e4095179f06c2ae01c334833645cad94bf7d7467e073cdc3aaabea565d3", size = 10518308, upload-time = "2026-05-16T05:57:25.824Z" },
|
|
2998
|
+
{ url = "https://files.pythonhosted.org/packages/39/cd/f308edd0cd86e402fe3a1b5c54e0a0dfa0177d80c1557c4849510bb2a147/ty-0.0.37-py3-none-win_amd64.whl", hash = "sha256:3b159351e99cf6eed7aacfb69ae8437725d15599ac4f21c8b2e909b300498b6c", size = 11607159, upload-time = "2026-05-16T05:57:06.76Z" },
|
|
2999
|
+
{ url = "https://files.pythonhosted.org/packages/1a/ed/5ec4b501479bc5dad55467e2fe72e797cb9c178468c0d1a514536872ebc5/ty-0.0.37-py3-none-win_arm64.whl", hash = "sha256:6c3c2b997f68c71e14242b96d48cba3c086439556af02bb4613aa458950d5c23", size = 10958817, upload-time = "2026-05-16T05:57:08.907Z" },
|
|
3000
3000
|
]
|
|
3001
3001
|
|
|
3002
3002
|
[[package]]
|
{agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/.github/ISSUE_TEMPLATE/bug_report.md
RENAMED
|
File without changes
|
{agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/.github/ISSUE_TEMPLATE/feature_request.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/challenge/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentscore_commerce-2.0.0 → agentscore_commerce-2.0.2}/agentscore_commerce/challenge/body.py
RENAMED
|
File without changes
|