graphprotocol / graphprotocol/dipper
Indexer agent on-chain acceptance and contract deployment
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 0
- Forks
- 1
- Avg merge
- 37m
- Merged PRs (30d)
- 3
Description
Context
Both the Dipper and indexer-rs sides of this feature are now complete. The remaining work is contract deployment and the indexer agent's on-chain acceptance implementation, both of which are outside these two codebases.
This issue tracked the migration from the epoch-based `IndexingAgreementVoucher` to the seconds-based `RecurringCollectionAgreement` (RCA) — the same type the contract consumes — and the end-to-end on-chain acceptance flow.
Architecture
The Dipper signs an RCA with a short deadline (~5 min) and sends it to indexer-rs via gRPC (fire-and-forget, no off-chain ACCEPT/REJECT). The indexer agent picks it up, validates, ensures an allocation, and calls `SubgraphService.acceptIndexingAgreement(allocationId, signedRCA)` on-chain. The Dipper monitors for the `IndexingAgreementAccepted` event and transitions the agreement to `AcceptedOnChain`. If the deadline passes with no on-chain acceptance, the Dipper expires the agreement and reassigns it.
If an indexer rejects the proposal off-chain but accepts on-chain anyway, the chain listener detects this and Dipper cancels the active agreement via `cancelIndexingAgreementByPayer`.
Dipper indexer-rs indexer-agent SubgraphService contract
| | | |
|-- SignedRCA (gRPC) --> | | |
| |-- store SignedRCA | |
| | |-- read pending |
| | |-- validate terms |
| | |-- ensure allocation |
| | |-- acceptIndexingAgreement(allocationId, SignedRCA) -->|
| | | |-- emit IndexingAgreementAccepted
|<-- monitor on-chain event ------------------------------------------------|
|-- mark ACCEPTED_ON_CHAIN | |
Agreement status flow:
Created -> AcceptedOnChain (on-chain event observed)
Created -> Expired (deadline passed, no on-chain acceptance)
Created -> DeliveryFailed (gRPC error sending to indexer-rs)
AcceptedOnChain -> CanceledByRequester (Dipper cancels adversarial on-chain acceptance)
AcceptedOnChain -> CanceledByIndexer (indexer cancels on-chain)
Phases
- Phase 1 - Dipper: Status cleanup -- Remove `Accepted` and `Rejected` statuses. `Created` is the only pre-confirmation active status, `AcceptedOnChain` is the confirmed one. Update active agreement queries, unique constraint, replace `at_epoch` with timestamp. (97af12b, PR #553)
- Phase 2 - Dipper: Switch to seconds-based pricing -- Replace epoch-based internal model (voucher fields, pricing config, DB schema) with seconds-based equivalents matching the contract. (22a648e, PR #555)
- Phase 3 - Dipper: Sign and send SignedRCA -- Replace voucher signing with RCA signing using the contract's EIP-712 domain. Fire-and-forget gRPC call. ABI-encode `AcceptIndexingAgreementMetadata` into the RCA metadata field. Configurable deadline (~5 min). (22a648e, PR #555)
- Phase 4 - indexer-rs: Store SignedRCA -- Simplified gRPC endpoint stores the `SignedRCA` blob in `pending_rca_proposals` with idempotent writes. Agent queries this table to pick up pending agreements. (indexer-rs PRs #942, #947, #948)
- Phase 5 - Indexer agent: On-chain acceptance -- New `AgreementAcceptor` background service (follows TapCollector pattern). Read pending agreements from indexer-rs DB, validate terms, ensure allocation, call `SubgraphService.acceptIndexingAgreement()`. Blocked on Phase 6.
- Phase 6 - Contract deployment -- The `IndexingAgreement.sol` contract has not been deployed yet. It needs to be deployed to Arbitrum Sepolia for testnet integration first, then to Arbitrum mainnet. Phases 5 and 7 depend on the contract being live.
- Phase 7 - Protocol subgraph: Create and deploy -- No subgraph currently exists that indexes the `IndexingAgreement.sol` contract events. A new subgraph needs to be written, covering `IndexingAgreementAccepted`, `IndexingAgreementCanceled`, and `IndexingFeesCollectedV1` events emitted by the SubgraphService contract. Once the contract is deployed, the subgraph can be published and indexed. This is a prerequisite for Phase 8.
- Phase 8 - Dipper: On-chain event monitoring -- Chain listener polls the protocol subgraph for agreement events, transitions `Created → AcceptedOnChain`, expires agreements past deadline, triggers reassignment. Also handles the adversarial case: if an indexer accepted on-chain after rejecting off-chain, Dipper cancels the agreement via `cancelIndexingAgreementByPayer`. (PRs #553, #555, #561)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with Phase 6 and the IndexingAgreement.sol deployment requirement for Arbitrum Sepolia, then review the proposed AgreementAcceptor background service and the pending_rca_proposals flow. Follow the TapCollector pattern and the SubgraphService.acceptIndexingAgreement entry point. Done requires the contract to be deployed and the indexer agent to validate, allocate, and accept pending SignedRCA proposals on-chain.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- grpc, rust, solidity
- Domain
- backend, blockchain
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100