Skip to content

feat: expose indexer service URLs alongside agreements - #15

Merged
MoonBoi9001 merged 6 commits into
mainfrom
mb9/index-indexer-urls
Jun 10, 2026
Merged

MoonBoi9001 merged 6 commits into
mainfrom
mb9/index-indexer-urls

Conversation

@MoonBoi9001

@MoonBoi9001 MoonBoi9001 commented Jun 4, 2026 •

Copy link
Copy Markdown
Member

TL;DR

Reading an indexing agreement today gives you the indexer's address but not its service URL, so consumers run a second query against the network subgraph to look it up. This indexes the URL from the same contract the subgraph already watches and links it to each agreement, so it comes back in one query.

Motivation

The indexing payments subgraph records each indexing agreement with the indexer's on-chain address, but not the indexer's service URL. Consumers that need the URL, such as to check an indexer's indexing status, must take that address and run a separate query against the network subgraph to resolve it.

The same SubgraphService contract this subgraph already indexes also publishes the indexer's URL on-chain, so that round-trip is avoidable. Pulling the URL into this subgraph lets consumers read it next to the agreement in a single query and drops the dependency on the network subgraph just to turn an address into a URL.

Summary

  • Add an Indexer record holding each indexer's service URL, taken from its on-chain registration.
  • Link every indexing agreement to its indexer record so the URL is available in one query.
  • Refresh the stored URL whenever an indexer re-registers, keeping the latest value.
  • Point the local hardhat config at the real SubgraphService address so local builds index.
  • Fill the Arbitrum One and Sepolia configs with live contract addresses and start blocks.
  • Anchor each network's start block to its contract deployment so no early registrations are missed.
  • Leave Arbitrum One's recurring payments contract unset, as it isn't deployed on mainnet yet.
  • Add unit tests for URL decoding, re-registration updates, and the agreement-to-indexer link.

MoonBoi9001 and others added 3 commits June 4, 2026 19:32
A consumer holding an agreement's indexer address must cross-query the network subgraph today
to resolve it into a service URL. Index that URL from the SubgraphService registration event
into a new Indexer entity, linked from each agreement, so it can be read in the same query.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The local config held a zero contract address, so local builds wired every data source to
0x0 and indexed nothing. Use the documented local SubgraphService address so a local build
indexes real events. The RecurringCollector address stays unset pending its local value.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The arbitrum configs held zero-address placeholders, so the subgraph could not index real
networks. Set the deployed SubgraphService address on Arbitrum One and Sepolia (plus Sepolia's
RecurringCollector) and anchor start blocks to deployment. Arbitrum One has no collector yet.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@MoonBoi9001
MoonBoi9001 marked this pull request as draft June 4, 2026 14:01
@nasmr

nasmr commented Jun 4, 2026

Copy link
Copy Markdown

@MoonBoi9001 Thanks for adding the indexer url that Studio can pull together with the indexing agreements status. I was looking through the Explorer UI again (which we were planning to follow) and noticed a few other details under the indexer entity from the network subgraph like account.defaultDisplayName, account.ens and account.metadata.image that we also display in the indexing progress bar (see screenshot and schema below).

Wanted to just check if there's a technically reasonable way to also include those alongside the indexer url in this subgraph instead?

          indexer {                                                                                                                                                                                   
            id                                                                                                                                                                                        
            url                                                                                                                                                                                       
            account {                                                                                                                                                                                 
              id                                                                                                                                                                                      
              defaultDisplayName                                                                                                                                                                      
              ens                                                                                                                                                                                     
              metadata {                                                                                                                                                                              
                id                                                                                                                                                                                    
                image                                                                                                                                                                                 
              }                                                                                                                                                                                       
            }                                                                                                                                                                                         
          }
explorer-indexingProgress-Hover

ethereum.decode of a tuple type only ever returns null or a tuple-kind value, so the kind
check could never fire; reduce it to a null check matching the other decode sites. Add a
test that two distinct indexers stay separate records keyed by their address.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@MoonBoi9001

Copy link
Copy Markdown
Member Author

@nasmr I looked into this and created #16. Not everything is feasible afaics. Not sure how valuble #16 is in this case. Let me know what you think.


  • account.defaultDisplayName - not feasible from this subgraph. It's empty for every indexer on Arbitrum. ENS lives on Ethereum L1, and a subgraph can only read its own chain. Presumably the name Explorer shows is resolved against L1 ENS.
  • account.ens - same as above: it's L1 ENS data, which the Arbitrum subgraph can't reach.

@MoonBoi9001
MoonBoi9001 marked this pull request as ready for review June 5, 2026 10:42
@cmwhited

Copy link
Copy Markdown

@nasmr I looked into this and created #16. Not everything is feasible afaics. Not sure how valuble #16 is in this case. Let me know what you think.

  • account.metadata.image - feat: index indexer avatar and profile metadata #16 introduces indexing of this, but not for historical values, we're also indexing both description and website. Something like 55% of indexers have those set.

  • account.defaultDisplayName - not feasible from this subgraph. It's empty for every indexer on Arbitrum. ENS lives on Ethereum L1, and a subgraph can only read its own chain. Presumably the name Explorer shows is resolved against L1 ENS.

  • account.ens - same as above: it's L1 ENS data, which the Arbitrum subgraph can't reach.

That is fine. WE can resolve from their address, we do that currently on L2. Again, the URL to query for the status is the key piece we need

MoonBoi9001 and others added 2 commits June 11, 2026 11:47
The registration handler had its own data source so it could start earlier than agreements,
but both read the same contract and every network anchors both at its deployment block.
Merge the handler into the agreements data source and drop the registrationStartBlock key.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The indexer, payer and indexer-URL link were only written by the RecurringCollector handler.
Both events fire in the same transaction, but a misconfigured collector address would leave
agreements missing the indexer link consumers rely on to read the URL.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@MoonBoi9001

Copy link
Copy Markdown
Member Author

@cmwhited

That is fine. WE can resolve from their address, we do that currently on L2. Again, the URL to query for the status is the key piece we need

Okay great, I've closed #16, if needed we can reopen and take another look, but for now going with this PR on its own. I'll merge this PR now to unblock. cc. @Maikol

@MoonBoi9001
MoonBoi9001 merged commit 852563c into main Jun 10, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants