Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions python/x402_a2a/src/x402_a2a/core/merchant.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ def create_payment_requirements(
PaymentRequirements object ready for x402PaymentRequiredResponse
"""

if not isinstance(max_timeout_seconds, int) or isinstance(
max_timeout_seconds, bool
):
raise ValueError("max_timeout_seconds must be an integer")
if max_timeout_seconds <= 0:
raise ValueError("max_timeout_seconds must be positive")

max_amount_required, asset_address, eip712_domain = process_price_to_atomic_amount(
price, network
)
Expand Down
35 changes: 35 additions & 0 deletions python/x402_a2a/tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
SettleResponse,
)
from x402_a2a.core.utils import x402Utils
from x402_a2a.core.merchant import create_payment_requirements

# --- Fixtures ---

Expand Down Expand Up @@ -129,6 +130,40 @@ def test_get_payment_payload_from_message(utils, sample_payment_payload):
assert extracted_payload.payload.signature == "0xabc"


def test_create_payment_requirements_rejects_invalid_timeouts(monkeypatch):
"""Payment requirements should not include invalid timeout values."""

monkeypatch.setattr(
"x402_a2a.core.merchant.process_price_to_atomic_amount",
lambda price, network: ("100", "0x456", {}),
)

for timeout in (0, -1, 1.5, True):
with pytest.raises(ValueError):
create_payment_requirements(
price="$1.00",
pay_to_address="0x123",
resource="/test",
max_timeout_seconds=timeout,
)
Comment on lines +141 to +148

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current test uses a generic pytest.raises(ValueError) without verifying the exception message. This can lead to false positives if a ValueError is raised from another part of the function (e.g., during price processing).

Additionally, we should expand the test coverage to include other common invalid types such as None and stringified integers (e.g., "60").

We can improve this by using pytest.raises(ValueError, match=...) and parameterizing or looping over the expected error messages.

Suggested change
for timeout in (0, -1, 1.5, True):
with pytest.raises(ValueError):
create_payment_requirements(
price="$1.00",
pay_to_address="0x123",
resource="/test",
max_timeout_seconds=timeout,
)
for timeout, expected_msg in [
(0, "max_timeout_seconds must be positive"),
(-1, "max_timeout_seconds must be positive"),
(1.5, "max_timeout_seconds must be an integer"),
(True, "max_timeout_seconds must be an integer"),
(None, "max_timeout_seconds must be an integer"),
("60", "max_timeout_seconds must be an integer"),
]:
with pytest.raises(ValueError, match=expected_msg):
create_payment_requirements(
price="$1.00",
pay_to_address="0x123",
resource="/test",
max_timeout_seconds=timeout,
)



def test_create_payment_requirements_accepts_positive_integer_timeout(monkeypatch):
monkeypatch.setattr(
"x402_a2a.core.merchant.process_price_to_atomic_amount",
lambda price, network: ("100", "0x456", {}),
)

requirements = create_payment_requirements(
price="$1.00",
pay_to_address="0x123",
resource="/test",
max_timeout_seconds=60,
)

assert requirements.max_timeout_seconds == 60


# --- Tests for x402ServerExecutor ---


Expand Down
Loading