-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
475 additions
and
509 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,57 @@ | ||
pub use query::*; | ||
use graphql_http::graphql::{Document, IntoDocument, IntoDocumentWithVariables}; | ||
use graphql_http::http_client::ReqwestExt; | ||
use indoc::indoc; | ||
use serde::{Deserialize, Serialize}; | ||
use serde_with::{serde_as, DisplayFromStr}; | ||
use thegraph::types::DeploymentId; | ||
use toolshed::url::Url; | ||
|
||
pub mod client; | ||
mod query; | ||
pub async fn query( | ||
client: reqwest::Client, | ||
status_url: Url, | ||
query: CostModelQuery, | ||
) -> anyhow::Result<CostModelResponse> { | ||
let res = client.post(status_url.0).send_graphql(query).await; | ||
match res { | ||
Ok(res) => Ok(res?), | ||
Err(e) => Err(anyhow::anyhow!("Error sending cost model query: {}", e)), | ||
} | ||
} | ||
|
||
pub(super) const COST_MODEL_QUERY_DOCUMENT: &str = indoc! { | ||
r#"query ($deployments: [String!]!) { | ||
costModels(deployments: $deployments) { | ||
deployment | ||
model | ||
variables | ||
} | ||
}"# | ||
}; | ||
|
||
#[serde_as] | ||
#[derive(Clone, Debug, Serialize)] | ||
pub struct CostModelQuery { | ||
#[serde_as(as = "Vec<DisplayFromStr>")] | ||
pub deployments: Vec<DeploymentId>, | ||
} | ||
|
||
impl IntoDocumentWithVariables for CostModelQuery { | ||
type Variables = Self; | ||
|
||
fn into_document_with_variables(self) -> (Document, Self::Variables) { | ||
(COST_MODEL_QUERY_DOCUMENT.into_document(), self) | ||
} | ||
} | ||
|
||
#[derive(Deserialize)] | ||
#[serde(rename_all = "camelCase")] | ||
pub struct CostModelResponse { | ||
pub cost_models: Vec<CostModelSourceResponse>, | ||
} | ||
|
||
#[derive(Deserialize)] | ||
pub struct CostModelSourceResponse { | ||
pub deployment: DeploymentId, | ||
pub model: String, | ||
pub variables: Option<String>, | ||
} |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,151 @@ | ||
pub use query::*; | ||
use std::borrow::Cow; | ||
|
||
pub mod client; | ||
mod query; | ||
use alloy_primitives::BlockHash; | ||
use graphql_http::http_client::ReqwestExt; | ||
use indoc::indoc; | ||
use serde::{Deserialize, Deserializer}; | ||
use thegraph::types::DeploymentId; | ||
use toolshed::url::Url; | ||
|
||
pub async fn query( | ||
client: reqwest::Client, | ||
status_url: Url, | ||
) -> anyhow::Result<IndexingStatusesResponse> { | ||
let res = client | ||
.post(status_url.0) | ||
.send_graphql(INDEXING_STATUSES_QUERY_DOCUMENT) | ||
.await; | ||
match res { | ||
Ok(res) => Ok(res?), | ||
Err(e) => Err(anyhow::anyhow!( | ||
"Error sending indexing statuses query: {}", | ||
e | ||
)), | ||
} | ||
} | ||
|
||
pub const INDEXING_STATUSES_QUERY_DOCUMENT: &str = indoc! { | ||
r#"{ | ||
indexingStatuses(subgraphs: []) { | ||
subgraph | ||
chains { | ||
network | ||
latestBlock { | ||
number | ||
hash | ||
} | ||
earliestBlock { | ||
number | ||
hash | ||
} | ||
} | ||
} | ||
}"# | ||
}; | ||
|
||
#[derive(Debug, Deserialize)] | ||
#[serde(rename_all = "camelCase")] | ||
pub struct IndexingStatusesResponse { | ||
pub indexing_statuses: Vec<IndexingStatusResponse>, | ||
} | ||
|
||
#[derive(Debug, Deserialize)] | ||
pub struct IndexingStatusResponse { | ||
pub subgraph: DeploymentId, | ||
pub chains: Vec<ChainStatus>, | ||
} | ||
|
||
#[derive(Debug, Deserialize)] | ||
#[serde(rename_all = "camelCase")] | ||
pub struct ChainStatus { | ||
pub network: String, | ||
pub latest_block: Option<BlockStatus>, | ||
pub earliest_block: Option<BlockStatus>, | ||
} | ||
|
||
#[derive(Debug, Deserialize)] | ||
pub struct BlockStatus { | ||
pub number: String, | ||
#[serde(deserialize_with = "deserialize_bad_hex")] | ||
pub hash: BlockHash, | ||
} | ||
|
||
fn deserialize_bad_hex<'de, D>(deserializer: D) -> Result<BlockHash, D::Error> | ||
where | ||
D: Deserializer<'de>, | ||
{ | ||
let s = Cow::<str>::deserialize(deserializer)?; | ||
if s == "0x0" { | ||
return Ok(BlockHash::ZERO); | ||
} | ||
s.parse().map_err(serde::de::Error::custom) | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
mod response { | ||
use super::*; | ||
|
||
#[test] | ||
fn deserialize_indexing_statuses_response() { | ||
//// Given | ||
let response = indoc! { | ||
r#"{ | ||
"indexingStatuses": [ | ||
{ | ||
"subgraph": "QmZTy9EJHu8rfY9QbEk3z1epmmvh5XHhT2Wqhkfbyt8k9Z", | ||
"chains": [ | ||
{ | ||
"network": "rinkeby", | ||
"latestBlock": { | ||
"number": "10164818", | ||
"hash": "0xaa94881130ba16c28cc90a5a880b117bdc90b6b11e9cde0c78804cdb93cc9e85" | ||
}, | ||
"earliestBlock": { | ||
"number": "7559999", | ||
"hash": "0x0" | ||
} | ||
} | ||
] | ||
}, | ||
{ | ||
"subgraph": "QmSLQfPFcz2pKRJZUH16Sk26EFpRgdxTYGnMiKvWgKRM2a", | ||
"chains": [ | ||
{ | ||
"network": "rinkeby" | ||
} | ||
] | ||
} | ||
] | ||
}"# | ||
}; | ||
|
||
//// When | ||
let response: IndexingStatusesResponse = | ||
serde_json::from_str(response).expect("Failed to deserialize response"); | ||
|
||
//// Then | ||
assert_eq!(response.indexing_statuses.len(), 2); | ||
|
||
assert_eq!(response.indexing_statuses[0].chains.len(), 1); | ||
assert_eq!(response.indexing_statuses[0].chains[0].network, "rinkeby"); | ||
assert!(response.indexing_statuses[0].chains[0] | ||
.latest_block | ||
.is_some()); | ||
assert!(response.indexing_statuses[0].chains[0] | ||
.earliest_block | ||
.is_some()); | ||
|
||
assert_eq!(response.indexing_statuses[1].chains.len(), 1); | ||
assert_eq!(response.indexing_statuses[1].chains[0].network, "rinkeby"); | ||
assert!(response.indexing_statuses[1].chains[0] | ||
.latest_block | ||
.is_none()); | ||
assert!(response.indexing_statuses[1].chains[0] | ||
.earliest_block | ||
.is_none()); | ||
} | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.