add ETH Swarm support for token metadata
Bálint USA
## 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 -->