diff --git a/CHANGELOG.md b/CHANGELOG.md index f209348aa..302173c7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ Releases prior to 7.0 has been removed from this file to declutter search result - database: Fix exception when creating connections with aiosqlite==0.22.0. - evm.node: Retry JSON-RPC requests on "invalid block range params" error. +- substrate.subscan: Pass `X-API-Key` header when `api_key` is configured. ## [8.5.1] - 2025-11-03 diff --git a/docs/3.datasources/9.substrate_subscan.md b/docs/3.datasources/9.substrate_subscan.md index ed98c9397..7ab2212f0 100644 --- a/docs/3.datasources/9.substrate_subscan.md +++ b/docs/3.datasources/9.substrate_subscan.md @@ -14,8 +14,8 @@ To use this datasource, add the following section in config: datasources: subscan: kind: substrate.subscan - url: ${ETHERSCAN_URL:-https://api.subscan.io/api} - api_key: ${ETHERSCAN_API_KEY:-''} + url: ${SUBSCAN_URL:-https://api.subscan.io/api} + api_key: ${SUBSCAN_API_KEY:-''} ``` During initialization, DipDup will use this datasource to fetch contract ABIs. If your config contains definitions for multiple networks, you can assign the datasource explicitly in `substrate.subsquid` index definitions: diff --git a/src/demo_substrate_events/dipdup.yaml b/src/demo_substrate_events/dipdup.yaml index f47c0bac9..4edd661a1 100644 --- a/src/demo_substrate_events/dipdup.yaml +++ b/src/demo_substrate_events/dipdup.yaml @@ -13,6 +13,7 @@ datasources: subscan: kind: substrate.subscan url: https://assethub-polkadot.api.subscan.io/api + api_key: ${SUBSCAN_API_KEY:-} node: kind: substrate.node url: https://statemint.api.onfinality.io/rpc?apikey=${ONFINALITY_API_KEY:-''} diff --git a/src/dipdup/datasources/substrate_subscan.py b/src/dipdup/datasources/substrate_subscan.py index 1901bc8d1..53249d510 100644 --- a/src/dipdup/datasources/substrate_subscan.py +++ b/src/dipdup/datasources/substrate_subscan.py @@ -14,10 +14,16 @@ async def get_abi(self, address: str) -> AbiJson: async def run(self) -> None: pass + def _api_key_headers(self) -> dict[str, str]: + if self._config.api_key: + return {'X-API-Key': self._config.api_key} + return {} + async def get_runtime_list(self) -> list[dict[str, Any]]: res = await self.request( 'post', 'scan/runtime/list', + headers=self._api_key_headers(), ) return cast('list[dict[str, Any]]', res['data']['list']) @@ -25,6 +31,7 @@ async def get_runtime_metadata(self, spec_version: int) -> list[dict[str, Any]]: res = await self.request( 'post', 'scan/runtime/metadata', + headers=self._api_key_headers(), json={'spec': spec_version}, ) return cast('list[dict[str, Any]]', res['data']['info']['metadata']) diff --git a/src/dipdup/projects/demo_substrate_events/dipdup.yaml.j2 b/src/dipdup/projects/demo_substrate_events/dipdup.yaml.j2 index 36ece806e..5f8549c1a 100644 --- a/src/dipdup/projects/demo_substrate_events/dipdup.yaml.j2 +++ b/src/dipdup/projects/demo_substrate_events/dipdup.yaml.j2 @@ -13,6 +13,7 @@ datasources: subscan: kind: substrate.subscan url: https://assethub-polkadot.api.subscan.io/api + api_key: ${SUBSCAN_API_KEY:-} node: kind: substrate.node url: https://statemint.api.onfinality.io/rpc?apikey=${ONFINALITY_API_KEY:-''} diff --git a/src/dipdup/test.py b/src/dipdup/test.py index 27df8498b..db6e803de 100644 --- a/src/dipdup/test.py +++ b/src/dipdup/test.py @@ -14,6 +14,7 @@ from shutil import which from typing import TYPE_CHECKING from typing import Any +from typing import cast from dipdup.config import DipDupConfig from dipdup.config import HasuraConfig @@ -98,7 +99,10 @@ async def run_postgres_container() -> PostgresDatabaseConfig: ) atexit.register(postgres_container.stop) postgres_container.reload() - postgres_ip = postgres_container.attrs['NetworkSettings']['IPAddress'] + + network_settings = postgres_container.attrs['NetworkSettings'] + ip = network_settings.get('IPAddress') or next(iter(network_settings['Networks'].values()))['IPAddress'] + postgres_ip = cast('str', ip) while not postgres_container.exec_run('pg_isready').exit_code == 0: await asyncio.sleep(0.1) @@ -126,7 +130,10 @@ async def run_hasura_container(postgres_ip: str) -> HasuraConfig: ) atexit.register(hasura_container.stop) hasura_container.reload() - hasura_ip = hasura_container.attrs['NetworkSettings']['IPAddress'] + + network_settings = hasura_container.attrs['NetworkSettings'] + ip = network_settings.get('IPAddress') or next(iter(network_settings['Networks'].values()))['IPAddress'] + hasura_ip = cast('str', ip) return HasuraConfig( url=f'http://{hasura_ip}:8080', diff --git a/tests/configs/common_substrate.yaml b/tests/configs/common_substrate.yaml index a9bdafff7..0dc0012f1 100644 --- a/tests/configs/common_substrate.yaml +++ b/tests/configs/common_substrate.yaml @@ -5,6 +5,7 @@ datasources: subscan: kind: substrate.subscan url: https://assethub-polkadot.api.subscan.io/api + api_key: ${SUBSCAN_API_KEY:-} node: kind: substrate.node url: https://statemint.api.onfinality.io/rpc?apikey=${ONFINALITY_API_KEY:-''} diff --git a/tests/test_demos.py b/tests/test_demos.py index e9acb4954..76799a89d 100644 --- a/tests/test_demos.py +++ b/tests/test_demos.py @@ -292,6 +292,8 @@ async def test_run_init( pytest.skip('Starknet tests require ALCHEMY_API_KEY environment variable') if 'substrate' in config and not {'ONFINALITY_API_KEY'} <= set(os.environ): pytest.skip('Substrate tests require ONFINALITY_API_KEY environment variable') + if 'substrate' in config and cmd == 'init' and not {'SUBSCAN_API_KEY'} <= set(os.environ): + pytest.skip('Substrate init tests require SUBSCAN_API_KEY environment variable') async with AsyncExitStack() as stack: tmp_package_path, env = await stack.enter_async_context(