Skip to content

Commit bef45c8

Browse files
committed
docs(tap): update GraphTally guide for post-Horizon
- Remove legacy V1 content (contracts, separate escrow subgraph) - Add Graph Horizon context and link to overview - Simplify to Horizon-first configuration with horizon.enabled = true - Add GraphOps gateway aggregator endpoint - Document operator_mnemonics for key rotation - Streamline architecture overview and getting started - Remove migration framing in favor of current setup guide
1 parent 8b724c2 commit bef45c8

1 file changed

Lines changed: 68 additions & 106 deletions

File tree

  • website/src/pages/en/indexing

website/src/pages/en/indexing/tap.mdx

Lines changed: 68 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -2,182 +2,149 @@
22
title: GraphTally Guide
33
---
44

5-
Learn about The Graph's new payment system, **GraphTally** [(previously Timeline Aggregation Protocol)](https://docs.rs/tap_core/latest/tap_core/index.html). This system provides fast, efficient microtransactions with minimized trust.
5+
Learn about The Graph's payment system, **GraphTally** [(previously Timeline Aggregation Protocol)](https://docs.rs/tap_core/latest/tap_core/index.html). GraphTally provides fast, efficient microtransactions with minimized trust.
66

77
## Overview
88

9-
GraphTally provides the following key features:
9+
GraphTally is the payment system for The Graph, integrated into the core protocol through [Graph Horizon](/graph-horizon/overview). It enables efficient pay-per-query payments between gateways and indexers.
1010

11-
- Efficiently handles micropayments.
12-
- Adds a layer of consolidations to onchain transactions and costs.
13-
- Allows Indexers control of receipts and payments, guaranteeing payment for queries.
14-
- Enables decentralized, trustless gateways and improves indexer service performance for multiple senders.
11+
Key benefits:
1512

16-
### How It Works
13+
- **Efficient micropayments**: Pay-per-query without high transaction costs
14+
- **Reduced onchain costs**: Receipts aggregate into single blockchain transactions
15+
- **Payment guarantees**: Indexers control receipt aggregation, ensuring payment for served queries
16+
- **Trustless operation**: Decentralized gateways with cryptographic verification
1717

18-
GraphTally allows a sender to make multiple payments to a receiver through **Receipts**, which are then aggregated into a single payment called a **Receipt Aggregate Voucher (RAV)**. This aggregated payment can be verified on the blockchain, reducing the number of transactions and simplifying the payment process.
18+
## How It Works
1919

20-
For each query, the gateway sends a signed receipt that is stored in your database. The `indexer-tap-agent` aggregates these receipts into RAVs through periodic requests. You can update a RAV by sending it with newer receipts, which generates a new RAV with an increased value.
20+
GraphTally enables a sender (gateway) to make multiple payments to a receiver (indexer) through **Receipts**, which aggregate into a **Receipt Aggregate Voucher (RAV)**. RAVs can be verified and redeemed on the blockchain.
21+
22+
**Payment flow:**
23+
24+
1. Gateway sends a signed receipt with each query
25+
2. `indexer-service-rs` validates and stores receipts in your database
26+
3. `indexer-tap-agent` periodically aggregates receipts into RAVs
27+
4. RAVs accumulate value as new receipts arrive
28+
5. After allocation closure, the final RAV is redeemed onchain
2129

2230
### RAV Details
2331

24-
- RAVs represent money waiting to be sent to the blockchain.
25-
- The system continuously aggregates receipts to ensure that the total value of non-aggregated receipts does not exceed the configured `max_amount_willing_to_lose_grt`.
26-
- Each RAV can be redeemed once in the contracts, which is why they are sent after the allocation is closed.
32+
- RAVs represent pending payments waiting for blockchain redemption
33+
- The system aggregates receipts continuously, keeping unaggregated value below `max_amount_willing_to_lose_grt`
34+
- Each RAV redeems once onchain, so final RAVs are created after allocation closure
2735

2836
### Redeeming RAVs
2937

30-
The redemption process is fully automated when running both `indexer-tap-agent` and `indexer-agent`:
38+
RAV redemption is fully automated when running `indexer-tap-agent` and `indexer-agent`:
3139

32-
1. An Indexer closes an allocation.
33-
2. After the `recently-closed-allocation-buffer` period, `indexer-tap-agent` takes all pending receipts for that allocation and requests aggregation into a final RAV, marking it as `last`.
34-
3. `indexer-agent` takes all the last RAVs and sends redeem requests to the blockchain, updating the `redeem_at` value.
40+
1. Indexer closes an allocation
41+
2. After the `recently-closed-allocation-buffer` period, `indexer-tap-agent` aggregates remaining receipts into a final RAV marked as `last`
42+
3. `indexer-agent` submits redeem transactions to the blockchain
3543
4. During the `finality-time` period, `indexer-agent` monitors for blockchain reorganizations:
36-
- If the transaction was reverted, the RAV is resent to the blockchain.
37-
- If not reverted, it gets marked as `final`.
38-
39-
## Blockchain Addresses
44+
- Reverted transactions are resubmitted
45+
- Confirmed transactions are marked `final`
4046

41-
### Contracts
47+
## Gateway Addresses
4248

43-
| Contract | Arbitrum Mainnet (42161) | Arbitrum Sepolia (421614) |
44-
| ------------------- | -------------------------------------------- | -------------------------------------------- |
45-
| TAP Verifier | `0x33f9E93266ce0E108fc85DdE2f71dab555A0F05a` | `0xfC24cE7a4428A6B89B52645243662A02BA734ECF` |
46-
| AllocationIDTracker | `0x5B2F33d7Ca6Ec88f5586f2528f58c20843D9FE7c` | `0xAaC28a10d707bbc6e02029f1bfDAEB5084b2aD11` |
47-
| Escrow | `0x8f477709eF277d4A880801D01A140a9CF88bA0d3` | `0x1e4dC4f9F95E102635D8F7ED71c5CdbFa20e2d02` |
48-
49-
### Gateway
50-
51-
| Component | Edge and Node Mainnet (Arbitrum Mainnet) | Edge and Node Testnet (Arbitrum Sepolia) |
49+
| Component | Arbitrum Mainnet | Arbitrum Sepolia (Testnet) |
5250
| ---------- | --------------------------------------------- | --------------------------------------------- |
5351
| Sender | `0xDDE4cfFd3D9052A9cb618fC05a1Cd02be1f2F467` | `0xC3dDf37906724732FfD748057FEBe23379b0710D` |
5452
| Signers | `0xfF4B7A5EfD00Ff2EC3518D4F250A27e4c29A2211` | `0xFb142dE83E261e43a81e9ACEADd1c66A0DB121FE` |
5553
| Aggregator | `https://tap-aggregator.network.thegraph.com` | `https://tap-aggregator.testnet.thegraph.com` |
5654

57-
## Prerequisites
58-
59-
In addition to typical indexer requirements, you'll need a `tap-escrow-subgraph` endpoint to query escrow information. You can use The Graph Network to query or self-host on your `graph-node`:
60-
61-
- [Graph TAP Arbitrum Sepolia Subgraph (for The Graph testnet)](https://thegraph.com/explorer/subgraphs/7ubx365MiqBH5iUz6XWXWT8PTof5BVAyEzdb8m17RvbD)
62-
- [Graph TAP Arbitrum One Subgraph (for The Graph mainnet)](https://thegraph.com/explorer/subgraphs/4sukbNVTzGELnhdnpyPqsf1QqtzNHEYKKmJkgaT8z6M1)
63-
64-
> Note: `indexer-agent` does not currently handle the indexing of this Subgraph like it does for the Network Subgraph deployment. You must index it manually.
65-
66-
## Migration Guide
55+
## Getting Started
6756

6857
### Software Requirements
6958

70-
#### Required Versions
71-
72-
- **indexer-agent**: [Latest version supporting TAP](https://github.com/graphprotocol/indexer/releases)
59+
- **indexer-agent**: [Latest version](https://github.com/graphprotocol/indexer/releases)
7360
- **indexer-service-rs**: [Latest release](https://github.com/graphprotocol/indexer-rs/releases?q=indexer-service-rs)
7461
- **indexer-tap-agent**: [Latest release](https://github.com/graphprotocol/indexer-rs/releases?q=indexer-tap-agent)
7562

76-
#### Docker Images
63+
### Docker Images
7764

7865
```bash
79-
# Indexer Service
8066
docker pull ghcr.io/graphprotocol/indexer-service-rs:latest
81-
82-
# TAP Agent
8367
docker pull ghcr.io/graphprotocol/indexer-tap-agent:latest
8468
```
8569

86-
### Migration Steps
70+
### Architecture Overview
8771

88-
#### 1. Update Indexer Agent
72+
Your indexer stack consists of:
8973

90-
- Continue using your existing `indexer-agent`
91-
- Add the `--tap-subgraph-endpoint` argument to enable TAP functionality and RAV redemption
92-
- Example: `--tap-subgraph-endpoint https://api.thegraph.com/subgraphs/name/graphprotocol/tap-mainnet`
74+
- **indexer-service-rs**: Handles incoming queries, validates receipts, routes to graph-node. Stateless and horizontally scalable.
75+
- **indexer-tap-agent**: Aggregates receipts into RAVs. Run exactly **one instance**.
76+
- **indexer-agent**: Manages allocations and redeems RAVs onchain.
9377

94-
#### 2. Replace Indexer Service
78+
All three components share the same PostgreSQL database.
9579

96-
- Fully replace your TypeScript indexer-service with `indexer-service-rs`
97-
- The new service is stateless and can be scaled horizontally
98-
- Use the same database as your existing setup
80+
### Configuration
9981

100-
#### 3. Deploy TAP Agent
82+
Both `indexer-service-rs` and `indexer-tap-agent` use a shared TOML configuration file. Pass it with `--config /path/to/config.toml`.
10183

102-
- Run exactly **one instance** of `indexer-tap-agent`
103-
- This component manages receipt aggregation and RAV creation
104-
- It must have access to the same database as other indexer components
105-
106-
#### 4. Configuration
107-
108-
Both `indexer-service-rs` and `indexer-tap-agent` share a TOML configuration file. Create a configuration file and pass it with `--config /path/to/config.toml`.
109-
110-
##### Minimal Configuration Example
84+
#### Configuration Example
11185

11286
```toml
113-
# Essential configuration for indexer-rs components
114-
# All values below must be updated to match your setup
115-
11687
[indexer]
11788
indexer_address = "0x1111111111111111111111111111111111111111"
11889
operator_mnemonic = "your twelve word mnemonic phrase here ..."
11990

91+
# For key rotation, you can specify multiple mnemonics:
92+
# operator_mnemonics = [
93+
# "current mnemonic phrase here",
94+
# "previous mnemonic if you rotated keys"
95+
# ]
96+
12097
[database]
121-
# Use the same database as your indexer-agent
12298
postgres_url = "postgresql://user:password@localhost:5432/indexer_db"
12399

124100
[graph_node]
125-
# Your graph-node endpoints
126101
query_url = "http://graph-node:8000"
127102
status_url = "http://graph-node:8000/graphql"
128103

129104
[subgraphs.network]
130-
# The Graph Network Subgraph (use query_url OR deployment_id, not both)
105+
# The Graph Network Subgraph (includes escrow data)
106+
# Use query_url for hosted service, or deployment_id for local indexing (recommended)
131107
query_url = "https://api.thegraph.com/subgraphs/name/graphprotocol/graph-network-arbitrum"
132108
# deployment_id = "QmUVskWrz1ZiQZ76AtyhcfFDEH1ELnRpoyEhVL8p6NFTbR"
133109

134-
[subgraphs.escrow]
135-
# TAP Escrow Subgraph (use query_url OR deployment_id, not both)
136-
query_url = "https://api.thegraph.com/subgraphs/name/graphprotocol/tap-arbitrum-one"
137-
# deployment_id = "QmPcbDomKwfsmVBNbvncU8gdWTvUiH9zVFYxDMc5ohpjvU"
138-
139110
[blockchain]
140-
# For Arbitrum mainnet
141111
chain_id = 42161
142112
receipts_verifier_address = "0x33f9E93266ce0E108fc85DdE2f71dab555A0F05a"
143113

144-
# For Arbitrum Sepolia testnet, use:
114+
# For testnet:
145115
# chain_id = 421614
146116
# receipts_verifier_address = "0xfC24cE7a4428A6B89B52645243662A02BA734ECF"
147117

148118
[tap]
149-
# Maximum GRT amount to risk before requiring aggregation
150-
# Use string format to prevent rounding errors
151119
max_amount_willing_to_lose_grt = "0.1"
152120

153121
[tap.sender_aggregator_endpoints]
154-
# Gateway endpoints for RAV aggregation
155-
# Mainnet
122+
# Mainnet gateways
156123
"0xDDE4cfFd3D9052A9cb618fC05a1Cd02be1f2F467" = "https://tap-aggregator.network.thegraph.com"
124+
"0xDD6a6f76eb36B873C1C184e8b9b9e762FE216490" = "https://tap-aggregator-arbitrum-one.graphops.xyz"
157125

158-
# For testnet, use:
126+
# For testnet:
159127
# "0xC3dDf37906724732FfD748057FEBe23379b0710D" = "https://tap-aggregator.testnet.thegraph.com"
128+
129+
[horizon]
130+
enabled = true
160131
```
161132

162-
##### Environment Variable Overrides
133+
#### Environment Variable Overrides
163134

164-
You can override any configuration value using environment variables:
135+
Override any configuration value using environment variables:
165136

166137
```bash
167138
# Pattern: [PREFIX]__[SECTION]__[KEY]
168-
# PREFIX can be INDEXER_SERVICE or TAP_AGENT
139+
# PREFIX: INDEXER_SERVICE or TAP_AGENT
169140

170-
# Examples:
171141
export INDEXER_SERVICE__DATABASE__POSTGRES_URL="postgresql://..."
172142
export TAP_AGENT__TAP__MAX_AMOUNT_WILLING_TO_LOSE_GRT="0.5"
173-
export INDEXER_SERVICE__BLOCKCHAIN__RECEIPTS_VERIFIER_ADDRESS="0x..."
174143
```
175144

176-
##### Advanced Configuration
177-
178-
For all configuration options, see:
145+
#### Advanced Configuration
179146

180-
- [Full configuration example](https://github.com/graphprotocol/indexer-rs/blob/main/crates/config/maximal-config-example.toml)
147+
- [Full configuration reference](https://github.com/graphprotocol/indexer-rs/blob/main/crates/config/maximal-config-example.toml)
181148
- [Default values](https://github.com/graphprotocol/indexer-rs/blob/main/crates/config/default_values.toml)
182149

183150
### Logging
@@ -190,9 +157,6 @@ export RUST_LOG=indexer_service=info,indexer_tap_agent=info
190157

191158
# For debugging
192159
export RUST_LOG=indexer_service=debug,indexer_tap_agent=debug
193-
194-
# TAP-specific debugging
195-
export RUST_LOG=indexer_tap_agent=debug,info
196160
```
197161

198162
## Monitoring
@@ -213,9 +177,9 @@ Key metrics to monitor:
213177

214178
### Grafana Dashboard
215179

216-
Import the [official Grafana dashboard](https://github.com/graphprotocol/indexer-rs/blob/main/docs/dashboard.json) for comprehensive monitoring of:
180+
Import the [official Grafana dashboard](https://github.com/graphprotocol/indexer-rs/blob/main/docs/dashboard.json) for monitoring:
217181

218-
- TAP receipt flow and aggregation status
182+
- Receipt flow and aggregation status
219183
- RAV creation and redemption lifecycle
220184
- System performance and error rates
221185
- Database query performance
@@ -230,7 +194,7 @@ Common issues and solutions:
230194
- Review debug logs for specific error messages
231195

232196
2. **Receipts not aggregating**:
233-
- Ensure `tap-agent` is running (only one instance)
197+
- Ensure `indexer-tap-agent` is running (only one instance)
234198
- Check database connectivity
235199
- Verify `max_amount_willing_to_lose_grt` is not too high
236200

@@ -243,17 +207,15 @@ Common issues and solutions:
243207

244208
### Docker Compose
245209

246-
Example compose configuration for both services:
210+
Example compose configuration:
247211

248212
```yaml
249-
version: '3.8'
250-
251213
services:
252214
indexer-service:
253215
image: ghcr.io/graphprotocol/indexer-service-rs:latest
254216
ports:
255-
- '7600:7600' # Service port
256-
- '7300:7300' # Metrics port
217+
- '7600:7600'
218+
- '7300:7300'
257219
volumes:
258220
- ./config.toml:/config.toml
259221
command: ['--config', '/config.toml']
@@ -264,7 +226,7 @@ services:
264226
tap-agent:
265227
image: ghcr.io/graphprotocol/indexer-tap-agent:latest
266228
ports:
267-
- '7301:7300' # Metrics port (different host port)
229+
- '7301:7300'
268230
volumes:
269231
- ./config.toml:/config.toml
270232
command: ['--config', '/config.toml']
@@ -291,7 +253,7 @@ For Kubernetes deployments, see the [Graph Launchpad charts](https://github.com/
291253

292254
2. **High Availability**:
293255
- Run multiple `indexer-service-rs` instances behind a load balancer
294-
- Keep `tap-agent` as a single instance with proper monitoring
256+
- Keep `indexer-tap-agent` as a single instance with proper monitoring
295257
- Use database connection pooling
296258

297259
3. **Security**:

0 commit comments

Comments
 (0)