PR: https://github.com/blockscout/blockscout/pull/14290 ## Summary Adds first-class support for ETH Swarm hashes in the token metadata pipeline, mirroring the existing Arweave integration. The implementation works with any content stored on Swarm , not just /bzz uploads — because the entry point is the 64-character keccak-256 hash (content address), which is shared by: /bzz/<hash> — regular chunk uploads SOC (Single Owner Chunks) references Feed manifests (which resolve to a content-address under the hood) A 200 response from the Swarm gateway is therefore sufficient proof that the content exists, regardless of how it was originally uploaded. --- ## Changes ### apps/explorer/lib/explorer/token/metadata_retriever.ex | Addition | Purpose | |---|---| | @invalid_swarm_path | Error constant (mirrors @invalid_ipfs_path ) | | swarm_link/1 | Builds <gateway>/bzz/<hash>/ ; defaults to https://gateway.ethswarm.org ; overridable via config :indexer, :swarm, gateway_url: | | swarm_headers/0 | Returns Authorization: Bearer <token> when config :indexer, :swarm, bearer_token: is set — supports private / paid gateway nodes | | valid_swarm_hash?/1 | Validates 64-char lowercase hex Swarm hash | | bzz:// clause in fetch_from_ipfs_or_ar?/5 | Routes bzz://<hash>[/path] URIs | | /bzz/<hash> clause in fetch_from_ipfs_or_ar?/5 | Routes plain HTTPS Swarm gateway URLs | | fetch_from_swarm/2 + fetch_from_swarm_if_valid_hash/2 | Fetcher (mirrors fetch_from_arweave/2 ) | | swarm?/1 predicate | Threaded through host-filtering bypass, header selection, and process_result/3 | ### apps/explorer/test/explorer/token/metadata_retriever_test.exs New describe blocks: swarm_link/1 — default gateway, custom gateway, trailing-slash stripping swarm_headers/0 — no token, bearer token configured valid_swarm_hash?/1 — valid, embedded path, uppercase, too short/long, empty, non-binary ETH Swarm URI routing — bzz:// scheme, plain HTTPS /bzz/ , invalid hash error --- ## Configuration (optional) ```elixir config/runtime.exs (or config.exs) config :indexer, :swarm, gateway_url: System.get_env("INDEXER_SWARM_GATEWAY_URL", " https://gateway.ethswarm.org "), bearer_token: System.get_env("INDEXER_SWARM_GATEWAY_BEARER_TOKEN") ``` Both keys are optional — the module works with zero configuration using the public Swarm gateway. --- ## Related Closes #<issue> (if any) Follows the same pattern as the Arweave integration introduced in this commit . <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * New Features * Added Swarm network support for token metadata retrieval * Support for bzz:// URI scheme and HTTP gateway-style paths * Automatic metadata validation and fetching from Swarm storage * Tests * Added comprehensive test coverage for Swarm metadata retrieval and URL handling <!-- end of auto-generated comment: release notes by coderabbit.ai -->