A Rust impl for The Graph indexer service to provide data services as an Indexer, integrated with TAP which is a fast, efficient, and trustless unidirectional micro-payments system.
- Receive paid or free query requests and route to graph node
- Route "meta" queries on indexing statuses and deployment health
- Serve indexer information such as health, indexer version, and operator address
- Monitor allocations, attestation signers, and manage receipts using TAP, store receipts in the indexer database
- Record performance and service metrics
$ cargo run -p indexer-service-rs -- --help
Usage: indexer-service-rs --config <FILE>
Options:
--config <FILE> Path to the configuration file.
See https://github.com/graphprotocol/indexer-rs/tree/main/config for examples.
-h, --help Print help
All the configuration is done through a TOML file. Please see up-to-date TOML configuration templates:
- Minimal configuration template (recommended)
- Maximal configuration template (not recommended, dangerous settings)
We follow conventional semantics for package versioning. An indexer may set a minor version specification for automatic patch updates while preventing breaking changes. To safely upgrading the package, we recommend the following steps:
- Review Release Notes: Before upgrading, check the release notes for the new version to understand what changes, fixes, or new features are included.
- Review Documentation: Check the up-to-date documentation for an accurate reflection of the changes made during the upgrade.
- Backup Configuration: Save your current configuration files and any local modifications you've made to the existing codebase.
- Deploy: Replace the old executable or docker image with the new one and restart the service to apply the upgrade.
- Monitor and Validate: After the upgrade, monitor system behavior and performance metrics to validate that the service is running as expected.
These steps should ensure a smooth transition to the latest version of indexer-service-rs
, harnessing new capabilities while maintaining system integrity.
curl http://localhost:7600/
Service is up and running
curl http://localhost:7600/version
{ "version":"0.1.0", "dependencies": {..} }
curl http://localhost:7600/info
{ "publicKey": "0xacb05407d78129b5717bb51712d3e23a78a10929" }
curl -X POST \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer token-for-graph-node-query-endpoint' \
--data '{"query": "{_meta{block{number}}}"}' \
http://localhost:7600/subgraphs/id/QmacQnSgia4iDPWHpeY6aWxesRFdb8o5DKZUx96zZqEWrB
{
"attestable": true,
"graphQLResponse": "{\"data\":{\"_meta\":{\"block\":{\"number\":10666745}}}}"
}
curl -X POST \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer token-for-graph-node-query-endpoint' \
--data '{"query": "{_meta{block{number}}}"}' \
http://localhost:7600/subgraphs/id/0xb655ca6f49e73728a102219726ff678d61d8fb792874792e9f0d9887dc616600
{
"attestable": true,
"graphQLResponse": "{\"data\":{\"_meta\":{\"block\":{\"number\":10666745}}}}"
}
curl -X POST \
-H 'Content-Type: application/json' \
-H 'Authorization: blah' \
--data '{"query": "{_meta{block{number}}}"}' \
http://localhost:7600/subgraphs/id/0xb655ca6f49e73728a102219726ff678d61d8fb792874792e9f0d9887dc616600
{
"message":"No valid receipt or free query auth token provided"
}
curl http://localhost:7600/subgraphs/health/QmVhiE4nax9i86UBnBmQCYDzvjWuwHShYh7aspGPQhU5Sj
{
"health": "healthy"
}
curl http://localhost:7600/subgraphs/health/QmacQnSgia4iDPWHpeY6aWxesRFdb8o5DKZUx96zZqEWrB
{
"error": "Deployment not found"
}
curl http://localhost:7600/subgraphs/health/QmVGSJyvjEjkk5U9EdxyyB78NCXK3EAoFhrzm6LV7SxxAm
{
"fatalError": "transaction 21e77ed08fbc9df7be81101e9b03c2616494cee7cac2f6ad4f1ee387cf799e0c: error while executing at wasm backtrace:\t 0: 0x5972 - <unknown>!mappings/core/handleSwap: Mapping aborted at mappings/core.ts, line 73, column 16, with message: unexpected null in handler `handleSwap` at block #36654250 (5ab4d80c8e2cd628d5bf03abab4c302fd21d25d734e66afddff7a706b804fe13)",
"health": "failed"
}
curl -X POST \
-H 'Content-Type: application/json' \
-H 'Authorization: token-for-network-subgraph' \
--data '{"query": "{_meta{block{number}}}"}' \
http://localhost:7600/network
{
"message":"No valid receipt or free query auth token provided"
}
curl -X POST \
-H 'Content-Type: application/json' \
--data '{"query": "{blockHashFromNumber(network:\"mainnet\", blockNumber: 21033)}"}' \
http://localhost:7600/status
{
"data": {
"blockHashFromNumber": "0x6d8daae97a562b1fff22162515452acdd817c3d3c5cde1497b7d9eb6666a957e"
}
}
curl -X POST \
-H 'Content-Type: application/json' \
--data '{"query": "{indexingStatuses {subgraph health}}"}' \
http://localhost:7600/status
{
"data": {
"indexingStatuses": [
{
"subgraph": "QmVhiE4nax9i86UBnBmQCYDzvjWuwHShYh7aspGPQhU5Sj",
"health": "healthy"
},
{
"subgraph": "QmWVtsWk8Pqn3zY3czDjyoVreshRLmoz9jko3mQ4uvxQDj",
"health": "healthy"
},
{
"subgraph": "QmacQnSgia4iDPWHpeY6aWxesRFdb8o5DKZUx96zZqEWrB",
"health": "healthy"
}
]
}
}
curl -X POST \
-H 'Content-Type: application/json' \
--data '{"query": "{_meta{block{number}}}"}' \
http://localhost:7600/status
{
"errors": [
{
"locations": [
{
"line": 1,
"column": 2
}
],
"message": "Type `Query` has no field `_meta`"
}
]
}
curl -X GET \
-H 'Content-Type: application/json' \
--data '{"query": "{ costModels(deployments: [\"Qmb5Ysp5oCUXhLA8NmxmYKDAX2nCMnh7Vvb5uffb9n5vss\"]) { deployment model variables }} "}' \
http://localhost:7300/cost
{
"data": {
"costModels": [
{
"deployment": "0xbd499f7673ca32ef4a642207a8bebdd0fb03888cf2678b298438e3a1ae5206ea",
"model": "default => 0.00025;",
"variables": null
}
]
}
}
- switching from actix-web to
axum
for the service server - App profiling should utilize
perf
, flamegraphs or cpu profilers, and benches to track and collect performance data. The typescript implementation usesgcloud-profile
- Consider replacing and adding parts from TAP manager
postgres
database connection required to indexer management server database, shared with the indexer agent- No migration in indexer service as it might introduce conflicts to the database; indexer agent is solely responsible for database management.
Temporarily live inside the indexer-service package under src/common
.
Simple indexer management client to track NetworkSubgraph and postgres connection.
- NetworkSubgraph instance track both remote API endpoint and local deployment query endpoint.
- TODO: query indexing status of local deployment, only use remote API as fallback.
- Keeps cost model schema and resolvers with postgres and graphQL types:
costModel(deployment)
andcostModels(deployments)
. If deployments is empty, all cost models are returned.- Global cost model fallback used when specific deployments are queried
- No database migration in indexer service as it might introduce schema conflicts; indexer agent is solely responsible for database management.
Linked dependency could not be linked directly with git url "https://github.com/graphprotocol/indexer" and path "packages/indexer-native/native" at the same time, and could not access it on crates.io. So copid the folder to local repo with the version at https://github.com/graphprotocol/indexer/blob/972658b3ce8c512ad7b4dc575d29cd9d5377e3fe/packages/indexer-native/native.
Since indexer-service will be written in Rust and no need for typescript, indexer-native's neon build and util has been removed.
Component NativeSignatureVerifier
renamed to SignatureVerifier
.
Separate package in the workspace under 'native'.
Temporarily live inside the indexer-service package under src/types
- Address
- readNumber
- Server path routing
- basic structure
- CORS
- timeouts
- Rate limiting levels
- Logger stream
- Query processor
- graph node query endpoint at specific subgraph path
- wrap request to and response from graph node
- extract receipt header
- Free query
- Query struct
- Free query auth token check
- Query routes + responses
- set
graph-attestable
in response header totrue
- Network subgraph query
- Query struct
- serve network subgraph boolean + auth token check
- Query routes + responses
- set
graph-attestable
in response header tofalse
- Paid query
- receipts graphQL schema
- TAP manager to handle receipts logic
- derive, cache, and look up attestation signers
- contracts - connect by network chain id
- network provider
- contracts - connect by network chain id
- validate receipt format (need unit tests)
- parse receipt (need unit tests)
- validate signature (need unit tests)
- store
- derive, cache, and look up attestation signers
- extract graph-attestable from graph node response header
- monitor eligible allocations
- network subgraph
- operator wallet -> indexer address
- subgraph health check
- query timing logs
- Deployment health server
- query status endpoint and process result
- Status server
- indexing status resolver - to query indexingStatuses
- Filter for unsupported queries
- Cost server
- Simple indexer management client to track postgres connection and network subgraph endpoint.
- serve queries with defined graphQL schema and psql resolvers to database:
costModel(deployment)
andcostModels(deployments)
. If deployments is empty, all cost models are returned. - Global cost model fallback used when specific deployments are queried
- Constant service paths
- health
- ready to roll
- versions
- operator public key
- validate mnemonics to public key
- Import indexer native
- Metrics
- Metrics setup
- serve basic indexer service metrics
- Add cost model metrics
- CLI args
- App profiling
- No gcloud profiling, can use
perf
to collect performance data.
- No gcloud profiling, can use