This document provides a number of usable examples that you can use to obtain any information from the SSVNetwork smart contract using the subgraph.
The examples are provided in GraphQL to be used directly on the subgraph, Javascript to be used within code, or Curl to be used in any terminal.
These can be used on one of the two official Subgraphs deployed, Ethereum Mainnet or Holesky testnet .
In the below Javascript and Curl examples we are using the Holesky end point, to use the same queries on the Mainnet subgraph please use this endpoint:
https://api.studio.thegraph.com/query/71118/ssv-network-ethereum/version/latest
Account Nonce
Returns the nonce of an account.
GraphQL Javascript Curl
Copy query AccountNonceQuery {
account(id: "0x004f13516f00ccc4aca6560c115bee5aaf5f758b" ) {
nonce
}
}
Copy const url = "https://api.studio.thegraph.com/query/71118/ssv-network-holesky/version/latest" ;
const query = `
query AccountNonceQuery {
account(id: "0x004f13516f00ccc4aca6560c115bee5aaf5f758b") {
nonce
}
}` ;
const response = await fetch (url , {
method : 'POST' ,
headers : {
'Content-Type' : 'application/json' ,
} ,
body : JSON .stringify ({ query })
});
const responseData = await response .json ();
console .log (responseData);
Copy curl -X POST "https://api.studio.thegraph.com/proxy/71118/ssv-network-holesky/version/latest" -H "Content-Type: application/json" -d '{
"query": "query AccountNonceQuery { account(id: \"0x004f13516f00ccc4aca6560c115bee5aaf5f758b\") { nonce }}"
}'
Output
Copy {
"data" : {
"account" : {
"nonce" : "5"
}
}
}
Cluster Snapshot
Returns the Cluster Snapshot needed in many smart contracts functions, like registering a validator .
Note: the cluster's id
is generated by concatenating the owner address and the operator IDs using a dash (-
) separator.
GraphQL Javascript Curl
Copy query ClusterSnapshot {
cluster(id: "0x000b4369b71b6634f27f5de9cbaaabb0d21b8be5-399-429-694-699" ) {
active
balance
index
lastUpdateBlockNumber
networkFeeIndex
validatorCount
}
}
Copy const url = "https://api.studio.thegraph.com/query/71118/ssv-network-holesky/version/latest" ;
const query = `
query ClusterSnapshot {
cluster(id: "0x000b4369b71b6634f27f5de9cbaaabb0d21b8be5-399-429-694-699") {
active
balance
index
lastUpdateBlockNumber
networkFeeIndex
validatorCount
}
}` ;
const response = await fetch (url , {
method : 'POST' ,
headers : {
'Content-Type' : 'application/json' ,
} ,
body : JSON .stringify ({ query })
});
const responseData = await response .json ();
console .log (responseData);
Copy curl -X POST "https://api.studio.thegraph.com/proxy/71118/ssv-network-holesky/version/latest" -H "Content-Type: application/json" -d '{
"query": "query ClusterSnapshot { cluster(id: \"0x000b4369b71b6634f27f5de9cbaaabb0d21b8be5-399-429-694-699\") { active balance index lastUpdateBlockNumber networkFeeIndex validatorCount}}"
}'
Output
Copy {
"data" : {
"cluster" : {
"active" : true ,
"balance" : "19479447888000000000" ,
"index" : "46367642388" ,
"lastUpdateBlockNumber" : "1766313" ,
"networkFeeIndex" : "59597136600" ,
"validatorCount" : "1"
}
}
}
DAO constants and protocol network fee index
Returns the value of important values set by the DAO (such as Minimum Liquidation Collatera, and Liquidation Threshold Period), as well as the protocol-wide Network Fee Index, needed to calculate the balance of clusters and verify their risk of liquidation.
Note: the id
of daovalues
is the address of the SSVNetwork smart contract deployed on the current chain. So in the case of Holesky it's 0x38A4794cCEd47d3baf7370CcC43B560D3a1beEFA
GraphQL Javascript Curl
Copy query daoValues {
daovalues(id: "0x38A4794cCEd47d3baf7370CcC43B560D3a1beEFA" ) {
declareOperatorFeePeriod
executeOperatorFeePeriod
liquidationThreshold
minimumLiquidationCollateral
networkFee
networkFeeIndex
networkFeeIndexBlockNumber
operatorFeeIncreaseLimit
operatorMaximumFee
}
}
Copy const url = "https://api.studio.thegraph.com/query/71118/ssv-network-holesky/version/latest" ;
const query = `
query daoValues {
daovalues(id: "0x38A4794cCEd47d3baf7370CcC43B560D3a1beEFA") {
declareOperatorFeePeriod
executeOperatorFeePeriod
liquidationThreshold
minimumLiquidationCollateral
networkFee
networkFeeIndex
networkFeeIndexBlockNumber
operatorFeeIncreaseLimit
operatorMaximumFee
}
}` ;
const response = await fetch (url , {
method : 'POST' ,
headers : {
'Content-Type' : 'application/json' ,
} ,
body : JSON .stringify ({ query })
});
const responseData = await response .json ();
console .log (responseData);
Copy curl -X POST "https://api.studio.thegraph.com/proxy/71118/ssv-network-holesky/version/latest" -H "Content-Type: application/json" -d '{
"query": "query daoValues { daovalues(id: \"0x38A4794cCEd47d3baf7370CcC43B560D3a1beEFA\") { declareOperatorFeePeriod executeOperatorFeePeriod liquidationThreshold minimumLiquidationCollateral networkFee networkFeeIndex networkFeeIndexBlockNumber operatorFeeIncreaseLimit operatorMaximumFee }}"
}'
Output
Copy {
"data" : {
"daovalues" : {
"declareOperatorFeePeriod" : "604800" ,
"executeOperatorFeePeriod" : "604800" ,
"liquidationThreshold" : "0" ,
"minimumLiquidationCollateral" : "0" ,
"networkFee" : "382640000000" ,
"networkFeeIndex" : "0" ,
"networkFeeIndexBlockNumber" : "208788" ,
"operatorFeeIncreaseLimit" : "0" ,
"operatorMaximumFee" : "76528650000000"
}
}
}
Cluster Balance Values
Returns all necessary data needed to compute the Cluster Balance .
GraphQL Javascript Curl
Copy query clusterBalanceValues {
_meta {
block {
number
}
}
daovalues(id: "0x38A4794cCEd47d3baf7370CcC43B560D3a1beEFA" ) {
networkFee
networkFeeIndex
networkFeeIndexBlockNumber
}
operators(where: { id_in : [ "11" , "13" , "24" , "29" ]}) {
fee
feeIndex
feeIndexBlockNumber
}
cluster(id: "0xaa184b86b4cdb747f4a3bf6e6fcd5e27c1d92c5c-11-13-24-29" ) {
validatorCount
networkFeeIndex
index
balance
}
}
Copy const url = "https://api.studio.thegraph.com/query/71118/ssv-network-holesky/version/latest" ;
const query = `
query clusterBalanceValues {
_meta {
block {
number
}
}
daovalues(id: "0x38A4794cCEd47d3baf7370CcC43B560D3a1beEFA") {
networkFee
networkFeeIndex
networkFeeIndexBlockNumber
}
operators(where: {id_in: ["11", "13", "24", "29"]}) {
fee
feeIndex
feeIndexBlockNumber
}
cluster(id: "0xaa184b86b4cdb747f4a3bf6e6fcd5e27c1d92c5c-11-13-24-29") {
validatorCount
networkFeeIndex
index
balance
}
}` ;
const response = await fetch (url , {
method : 'POST' ,
headers : {
'Content-Type' : 'application/json' ,
} ,
body : JSON .stringify ({ query })
});
const responseData = await response .json ();
console .log (responseData);
Copy curl -X POST "https://api.studio.thegraph.com/proxy/71118/ssv-network-holesky/version/latest" -H "Content-Type: application/json" -d '{
"query": "query clusterBalanceValues { _meta { block { number }} daovalues(id: \"0x38A4794cCEd47d3baf7370CcC43B560D3a1beEFA\") { networkFee networkFeeIndex networkFeeIndexBlockNumber } operators(where: {id_in: [\"11\", \"13\", \"24\", \"29\"]}) { fee feeIndex feeIndexBlockNumber } cluster(id: \"0xaa184b86b4cdb747f4a3bf6e6fcd5e27c1d92c5c-11-13-24-29\") { validatorCount networkFeeIndex index balance }}"
}'
Output
Copy {
"data" : {
"daovalues" : {
"networkFee" : "382640000000" ,
"networkFeeIndex" : "0" ,
"networkFeeIndexBlockNumber" : "208788"
} ,
"operators" : [
{
"fee" : "0" ,
"feeIndex" : "0" ,
"feeIndexBlockNumber" : "377585"
} ,
{
"fee" : "382640000000" ,
"feeIndex" : "0" ,
"feeIndexBlockNumber" : "412415"
} ,
{
"fee" : "0" ,
"feeIndex" : "0" ,
"feeIndexBlockNumber" : "424818"
} ,
{
"fee" : "0" ,
"feeIndex" : "0" ,
"feeIndexBlockNumber" : "426254"
}
] ,
"cluster" : {
"validatorCount" : "1" ,
"networkFeeIndex" : "54511123984" ,
"index" : "46719540456" ,
"active" : true ,
"balance" : "10000000000000000000"
} ,
"_meta" : {
"block" : {
"number" : 2373410
}
}
}
}
List of Validators for an owner
Returns a list of validators for an owner and displays whether they are active or not. Queries the first
5 validators owned by this address.
Note: it's always best to limit the query, to avoid flooding the API, reduce performance issues, and in case of production API, spend too many credits.
GraphQL Javascript Curl
Copy query ListOfValidatorsPerOwner {
validators(
where: { owner : "0xcdb35fe42e19860b061ba6d1d85ce12c8f491ddf" }
first: 5
) {
id
owner {
id
}
active
}
}
Copy const url = "https://api.studio.thegraph.com/query/71118/ssv-network-holesky/version/latest" ;
const query = `
query ListOfValidatorsPerOwner {
validators(
where: {owner: "0xcdb35fe42e19860b061ba6d1d85ce12c8f491ddf"}
first: 5
) {
id
owner {
id
}
active
}
}` ;
const response = await fetch (url , {
method : 'POST' ,
headers : {
'Content-Type' : 'application/json' ,
} ,
body : JSON .stringify ({ query })
});
const responseData = await response .json ();
console .log (responseData);
Copy curl -X POST "https://api.studio.thegraph.com/proxy/71118/ssv-network-holesky/version/latest" -H "Content-Type: application/json" -d '{
"query": "query ListOfValidatorsPerOwner { validators(where: {owner: \"0xcdb35fe42e19860b061ba6d1d85ce12c8f491ddf\"}) { id owner { id }}}"
}'
Output
Copy {
"data" : {
"validators" : [
{
"active" : false ,
"id" : "0x80004ce97fc4747bcae7e061153deba256628f03825c431eccede3f588bd93aaa9b3486948f3c713e847f00bd7e01d08" ,
"owner" : {
"id" : "0x225702e8e1f34d2203857dd2bb8805c8b58c5cf8"
}
} ,
{
"active" : true ,
"id" : "0x80008df886d57efe8906d7204b4e3c05d5983b22b34a1e3782557e492925fea7e7ff5edbfce46405a5e3714296eacac4" ,
"owner" : {
"id" : "0xd463eab729e4475620a9708428639948c7585227"
}
}
}
}
Validator Data by ID (Active status and Operator IDs)
Returns operator IDs and active status for a validator.
GraphQL Javascript Curl
Copy query ValidatorData {
validator(
id: "0x80006ff500fc36a6ae4ce7b643be3856ffe052ef36e5a6223dc9f7021b1dae02539c919751bba870f7ac9fccb86e06cf"
) {
removed
operators(first: 10 ) {
operatorId
}
}
}
Copy const url = "https://api.studio.thegraph.com/query/71118/ssv-network-holesky/version/latest" ;
const query = `
query ValidatorData {
validator(
id: "0x80006ff500fc36a6ae4ce7b643be3856ffe052ef36e5a6223dc9f7021b1dae02539c919751bba870f7ac9fccb86e06cf"
) {
removed
operators(first: 10) {
operatorId
}
}
}` ;
const response = await fetch (url , {
method : 'POST' ,
headers : {
'Content-Type' : 'application/json' ,
} ,
body : JSON .stringify ({ query })
});
const responseData = await response .json ();
console .log (responseData);
Copy curl -X POST "https://api.studio.thegraph.com/proxy/71118/ssv-network-holesky/version/latest" -H "Content-Type: application/json" -d '{
"query": "query ValidatorData { validator(id: \"0x80006ff500fc36a6ae4ce7b643be3856ffe052ef36e5a6223dc9f7021b1dae02539c919751bba870f7ac9fccb86e06cf\") { removed operators(first: 10) { operatorId }}}"
}'
Output
Copy {
"data" : {
"validator" : {
"removed" : true ,
"operators" : [
{
"operatorId" : "10"
} ,
{
"operatorId" : "5"
} ,
{
"operatorId" : "8"
} ,
{
"operatorId" : "9"
}
]
}
}
}
Cluster Data by ID (Balance, Active status and Operator IDs)
Returns balance, active status and operator IDs for a cluster.
Note: the cluster's id
is generated by concatenating the owner address and the operator IDs using a dash (-
) separator.
GraphQL Javascript Curl
Copy query ClusterData {
cluster(id: "0x000b4369b71b6634f27f5de9cbaaabb0d21b8be5-399-429-694-699" ) {
active
validators {
id
owner {
id
}
}
validatorCount
}
}
Copy const url = "https://api.studio.thegraph.com/query/71118/ssv-network-holesky/version/latest" ;
const query = `
query ClusterData {
cluster(id: "0x000b4369b71b6634f27f5de9cbaaabb0d21b8be5-399-429-694-699") {
active
validators {
id
owner {
id
}
}
validatorCount
}
}` ;
const response = await fetch (url , {
method : 'POST' ,
headers : {
'Content-Type' : 'application/json' ,
} ,
body : JSON .stringify ({ query })
});
const responseData = await response .json ();
console .log (responseData);
Copy curl -X POST "https://api.studio.thegraph.com/proxy/71118/ssv-network-holesky/version/latest" -H "Content-Type: application/json" -d '{
"query": "query ClusterData { cluster(id: \"0x000b4369b71b6634f27f5de9cbaaabb0d21b8be5-399-429-694-699\") { active validators { id owner { id } } validatorCount}}"
}'
Output
Copy {
"data" : {
"cluster" : {
"active" : true ,
"validatorCount" : "1" ,
"validators" : [
{
"id" : "0x96c29ab308dff8553ae70479fff1ec8c6d4d558ee30a8a2501d64e87fec895af73afe42cb811c65165d8e3e6d7a0fbfd" ,
"owner" : {
"id" : "0x000b4369b71b6634f27f5de9cbaaabb0d21b8be5"
}
}
]
}
}
}
Operator data by ID (Validator count, Fee, private and active status)
Returns validator count, fee, and active status.
GraphQL Javascript Curl
Copy query ValidatorCountPerOperator {
operator(id: "10" ) {
fee
removed
totalWithdrawn
isPrivate
validatorCount
whitelisted {
id
}
}
}
Copy const url = "https://api.studio.thegraph.com/query/71118/ssv-network-holesky/version/latest" ;
const query = `
query ValidatorCountPerOperator {
operator(id: "10") {
fee
removed
totalWithdrawn
isPrivate
validatorCount
whitelisted {
id
}
}
}` ;
const response = await fetch (url , {
method : 'POST' ,
headers : {
'Content-Type' : 'application/json' ,
} ,
body : JSON .stringify ({ query })
});
const responseData = await response .json ();
console .log (responseData);
Copy curl -X POST "https://api.studio.thegraph.com/proxy/71118/ssv-network-holesky/version/latest" -H "Content-Type: application/json" -d '{
"query": "query ValidatorCountPerOperator { operator(id: "10") { fee removed totalWithdrawn validatorCount isPrivate whitelisted { id } }}"
}'
Output
Copy {
"data" : {
"operator" : {
"fee" : "1913210000000" ,
"removed" : false ,
"totalWithdrawn" : "0" ,
"isPrivate" : false ,
"validatorCount" : "197" ,
"whitelisted" : []
}
}
}
10 most recent clusters with a validator count of 4
Returns data on the 10 most recent clusters, we get this by the last updated blocks and using orderBy: lastUpdateBlockNumber
and sort it by descending using orderDirection: desc
GraphQL Javascript Curl
Copy query ClusterQuery {
clusters(
first: 10
where: { validatorCount : "4" }
orderBy: lastUpdateBlockNumber
orderDirection: desc
) {
validatorCount
lastUpdateBlockNumber
id
}
}
Copy const url = "https://api.studio.thegraph.com/query/71118/ssv-network-holesky/version/latest" ;
const query = `
query ClusterQuery {
clusters(
first: 10
where: {validatorCount: "4"}
orderBy: lastUpdateBlockNumber
orderDirection: desc
) {
validatorCount
lastUpdateBlockNumber
id
}
}` ;
const response = await fetch (url , {
method : 'POST' ,
headers : {
'Content-Type' : 'application/json' ,
} ,
body : JSON .stringify ({ query })
});
const responseData = await response .json ();
console .log (responseData);
Copy curl -X POST "https://api.studio.thegraph.com/proxy/71118/ssv-network-holesky/version/latest" -H "Content-Type: application/json" -d '{
"query": "query ClusterQuery { clusters( first: 10 where: {validatorCount: \"4\"} orderBy: lastUpdateBlockNumber orderDirection: desc) { validatorCount lastUpdateBlockNumber id}}"
}'
Output
Copy {
"data" : {
"clusters" : [
{
"id" : "0xcdb35fe42e19860b061ba6d1d85ce12c8f491ddf-4-11-24-29" ,
"lastUpdateBlockNumber" : "1906102" ,
"validatorCount" : "4"
} ,
{
"id" : "0x27aabee07e0dbc8b0de20f42b1a1980871314ef5-113-137-395-502" ,
"lastUpdateBlockNumber" : "1894393" ,
"validatorCount" : "4"
} ,
{
"id" : "0xbb7d86599d35d0ede20487821d1eda0a88332747-4-5-334-370" ,
"lastUpdateBlockNumber" : "1893911" ,
"validatorCount" : "4"
} ,
{
"id" : "0xe0891aac5dffcbb58b2035a0dbc9e79e1faaaee0-376-380-381-383" ,
"lastUpdateBlockNumber" : "1843888" ,
"validatorCount" : "4"
} ,
{
"id" : "0x0516209ec333d01da1ca3ebbd22d4977556b73bf-236-306-315-400" ,
"lastUpdateBlockNumber" : "1835246" ,
"validatorCount" : "4"
} ,
{
"id" : "0xb0e4e86734641a85f97d39b6982a5fb2612659df-11-91-209-585" ,
"lastUpdateBlockNumber" : "1789338" ,
"validatorCount" : "4"
} ,
{
"id" : "0x27aabee07e0dbc8b0de20f42b1a1980871314ef5-91-113-137-502" ,
"lastUpdateBlockNumber" : "1772842" ,
"validatorCount" : "4"
} ,
{
"id" : "0xd1dc869556f1f3027def029d23cd0968cf08cb0e-7-8-9-10" ,
"lastUpdateBlockNumber" : "1745895" ,
"validatorCount" : "4"
} ,
{
"id" : "0xeedbb6ebb0b2f5464e14aaea2591c4c5fea5f853-220-558-559-560" ,
"lastUpdateBlockNumber" : "1662137" ,
"validatorCount" : "4"
} ,
{
"id" : "0xff79fa88412e7e81a95f8824b8f9bd2cafcd7e62-619-620-621-622" ,
"lastUpdateBlockNumber" : "1616914" ,
"validatorCount" : "4"
}
]
}
}