Skip to main content
Glama

Blockscout MCP Server

Official
test_get_transactions_by_address.py8.12 kB
from unittest.mock import AsyncMock, patch import pytest from blockscout_mcp_server.models import AdvancedFilterItem, ToolResponse from blockscout_mcp_server.tools.transaction.get_transactions_by_address import get_transactions_by_address @pytest.mark.asyncio async def test_get_transactions_by_address_calls_smart_pagination_correctly(mock_ctx): """ Verify get_transactions_by_address calls the smart pagination function with correct arguments. This tests the integration without testing the pagination function's internal logic. """ # ARRANGE chain_id = "1" address = "0x123abc" age_from = "2023-01-01T00:00:00.00Z" age_to = "2023-01-02T00:00:00.00Z" methods = "0x304e6ade" mock_base_url = "https://eth.blockscout.com" mock_filtered_items = [] mock_has_more_pages = False # We patch the smart pagination function and the base URL getter with ( patch( "blockscout_mcp_server.tools.transaction.get_transactions_by_address.get_blockscout_base_url", new_callable=AsyncMock, ) as mock_get_url, patch( "blockscout_mcp_server.tools.transaction.get_transactions_by_address." "_fetch_filtered_transactions_with_smart_pagination", new_callable=AsyncMock, ) as mock_smart_pagination, ): mock_get_url.return_value = mock_base_url mock_smart_pagination.return_value = (mock_filtered_items, mock_has_more_pages) # ACT result = await get_transactions_by_address( chain_id=chain_id, address=address, age_from=age_from, age_to=age_to, methods=methods, ctx=mock_ctx, ) # ASSERT assert isinstance(result, ToolResponse) assert isinstance(result.data, list) assert result.data == [] mock_get_url.assert_called_once_with(chain_id) # Assert that the smart pagination function was called once mock_smart_pagination.assert_called_once() # Assert that the smart pagination function was called with the correct arguments call_args, call_kwargs = mock_smart_pagination.call_args # Verify the smart pagination function was called with correct parameters assert call_kwargs["base_url"] == mock_base_url assert call_kwargs["api_path"] == "/api/v2/advanced-filters" assert call_kwargs["ctx"] == mock_ctx assert call_kwargs["progress_start_step"] == 2.0 assert call_kwargs["total_steps"] == 12.0 # Check the initial_params that should be passed to the smart pagination function expected_initial_params = { "to_address_hashes_to_include": address, "from_address_hashes_to_include": address, "age_from": age_from, "age_to": age_to, "methods": methods, } assert call_kwargs["initial_params"] == expected_initial_params # Verify progress was reported correctly before the smart pagination call assert mock_ctx.report_progress.call_count == 3 # Start + after URL resolution + completion @pytest.mark.asyncio async def test_get_transactions_by_address_minimal_params(mock_ctx): """ Verify get_transactions_by_address works with minimal parameters (only required ones). """ # ARRANGE chain_id = "1" address = "0x123abc" mock_base_url = "https://eth.blockscout.com" mock_filtered_items = [{"hash": "0xabc123"}] mock_has_more_pages = False with ( patch( "blockscout_mcp_server.tools.transaction.get_transactions_by_address.get_blockscout_base_url", new_callable=AsyncMock, ) as mock_get_url, patch( "blockscout_mcp_server.tools.transaction.get_transactions_by_address." "_fetch_filtered_transactions_with_smart_pagination", new_callable=AsyncMock, ) as mock_smart_pagination, ): mock_get_url.return_value = mock_base_url mock_smart_pagination.return_value = (mock_filtered_items, mock_has_more_pages) # ACT - Only provide required parameters result = await get_transactions_by_address(chain_id=chain_id, address=address, ctx=mock_ctx) # ASSERT assert isinstance(result, ToolResponse) assert isinstance(result.data, list) assert len(result.data) == 1 assert isinstance(result.data[0], AdvancedFilterItem) assert result.data[0].model_dump(by_alias=True)["hash"] == "0xabc123" mock_get_url.assert_called_once_with(chain_id) mock_smart_pagination.assert_called_once() # Check that the initial_params only include the required parameters call_args, call_kwargs = mock_smart_pagination.call_args expected_params = { "to_address_hashes_to_include": address, "from_address_hashes_to_include": address, # No optional parameters should be included } assert call_kwargs["initial_params"] == expected_params @pytest.mark.asyncio async def test_get_transactions_by_address_transforms_response(mock_ctx): """Verify that get_transactions_by_address correctly transforms its response.""" chain_id = "1" address = "0x123" mock_base_url = "https://eth.blockscout.com" # Mock the filtered items returned by smart pagination (ERC-20 transactions already filtered out) mock_filtered_items = [ { "type": "call", "from": {"hash": "0xfrom_hash_1"}, "to": {"hash": "0xto_hash_1"}, "value": "kept1", "token": "should be removed", "total": "should be removed", }, { "type": "creation", "from": {"hash": "0xfrom_hash_3"}, "to": None, "value": "kept2", }, ] mock_has_more_pages = False expected_items = [ { "from": "0xfrom_hash_1", "to": "0xto_hash_1", "value": "kept1", }, { "from": "0xfrom_hash_3", "to": None, "value": "kept2", }, ] with ( patch( "blockscout_mcp_server.tools.transaction.get_transactions_by_address.get_blockscout_base_url", new_callable=AsyncMock, ) as mock_get_url, patch( "blockscout_mcp_server.tools.transaction.get_transactions_by_address." "_fetch_filtered_transactions_with_smart_pagination", new_callable=AsyncMock, ) as mock_smart_pagination, ): mock_get_url.return_value = mock_base_url mock_smart_pagination.return_value = (mock_filtered_items, mock_has_more_pages) result = await get_transactions_by_address(chain_id=chain_id, address=address, ctx=mock_ctx) assert isinstance(result, ToolResponse) assert isinstance(result.data, list) assert len(result.data) == 2 for idx, expected in enumerate(expected_items): item_model = result.data[idx] assert isinstance(item_model, AdvancedFilterItem) assert item_model.from_address == expected["from"] assert item_model.to_address == expected["to"] item_dict = item_model.model_dump(by_alias=True) assert item_dict.get("value") == expected["value"] # removed fields should not be present after transformation assert "token" not in item_dict assert "total" not in item_dict @pytest.mark.asyncio async def test_get_transactions_by_address_invalid_cursor(mock_ctx): """Verify ValueError is raised when the cursor is invalid.""" with patch( "blockscout_mcp_server.tools.transaction.get_transactions_by_address.apply_cursor_to_params", side_effect=ValueError("Invalid cursor"), ) as mock_apply: with pytest.raises(ValueError, match="Invalid cursor"): await get_transactions_by_address(chain_id="1", address="0x123", cursor="bad", ctx=mock_ctx) mock_apply.assert_called_once()

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/blockscout/mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server