Skip to content

Commit ccd6095

Browse files
committed
feat: add dips graphql
1 parent 5edf6cf commit ccd6095

File tree

5 files changed

+206
-4
lines changed

5 files changed

+206
-4
lines changed

service/src/database/dips.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright 2023-, Edge & Node, GraphOps, and Semiotic Labs.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use std::collections::HashMap;
5+
6+
use axum::async_trait;
7+
8+
use crate::routes::dips::Agreement;
9+
10+
#[async_trait]
11+
pub trait AgreementStore: Sync + Send {
12+
async fn get_by_signature(&self, signature: &String) -> anyhow::Result<Option<Agreement>>;
13+
async fn create_agreement(
14+
&self,
15+
signature: String,
16+
data: Agreement,
17+
) -> anyhow::Result<Agreement>;
18+
async fn cancel_agreement(&self, signature: &String) -> anyhow::Result<String>;
19+
}
20+
21+
pub struct InMemoryAgreementStore {
22+
pub data: tokio::sync::RwLock<HashMap<String, Agreement>>,
23+
}
24+
25+
#[async_trait]
26+
impl AgreementStore for InMemoryAgreementStore {
27+
async fn get_by_signature(&self, signature: &String) -> anyhow::Result<Option<Agreement>> {
28+
Ok(self.data.try_read()?.get(signature).cloned())
29+
}
30+
async fn create_agreement(
31+
&self,
32+
signature: String,
33+
agreement: Agreement,
34+
) -> anyhow::Result<Agreement> {
35+
self.data.try_write()?.insert(signature, agreement.clone());
36+
37+
Ok(agreement)
38+
}
39+
async fn cancel_agreement(&self, signature: &String) -> anyhow::Result<String> {
40+
self.data.try_write()?.remove(signature);
41+
42+
Ok(signature.clone())
43+
}
44+
}

service/src/database.rs renamed to service/src/database/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright 2023-, Edge & Node, GraphOps, and Semiotic Labs.
22
// SPDX-License-Identifier: Apache-2.0
33

4+
pub mod dips;
5+
46
use std::time::Duration;
57
use std::{collections::HashSet, str::FromStr};
68

service/src/routes/dips.rs

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
use std::{str::FromStr, sync::Arc};
2+
3+
use anyhow::bail;
4+
use async_graphql::{Context, FieldResult, Object, SimpleObject};
5+
6+
use crate::database::dips::AgreementStore;
7+
8+
// pub struct ChainId(Box<str>);
9+
10+
// impl From<String> for ChainId {
11+
// fn from(value: String) -> Self {
12+
// Self(value.into_boxed_str())
13+
// }
14+
// }
15+
16+
pub enum NetworkProtocol {
17+
ArbitrumMainnet,
18+
}
19+
20+
impl FromStr for NetworkProtocol {
21+
type Err = anyhow::Error;
22+
23+
fn from_str(s: &str) -> Result<Self, Self::Err> {
24+
let p = match s {
25+
"arbitrum-mainnet" => NetworkProtocol::ArbitrumMainnet,
26+
_ => bail!("unknown network protocol"),
27+
};
28+
29+
Ok(p)
30+
}
31+
}
32+
33+
#[derive(SimpleObject, Debug, Clone)]
34+
pub struct Agreement {
35+
signature: String,
36+
data: String,
37+
protocol_network: String,
38+
}
39+
40+
#[derive(SimpleObject, Debug, Clone)]
41+
pub struct Price {
42+
price_per_block: String,
43+
chain_id: String,
44+
protocol_network: String,
45+
}
46+
47+
#[derive(Debug)]
48+
pub struct AgreementQuery {}
49+
50+
#[Object]
51+
impl AgreementQuery {
52+
pub async fn get_agreement<'a>(
53+
&self,
54+
ctx: &'a Context<'_>,
55+
signature: String,
56+
) -> FieldResult<Option<Agreement>> {
57+
let store: &Arc<dyn AgreementStore> = ctx.data()?;
58+
59+
store
60+
.get_by_signature(&signature)
61+
.await
62+
.map_err(async_graphql::Error::from)
63+
}
64+
65+
pub async fn get_price<'a>(
66+
&self,
67+
ctx: &'a Context<'_>,
68+
protocol_network: String,
69+
chain_id: String,
70+
) -> FieldResult<Option<Price>> {
71+
let prices: &Vec<Price> = ctx.data()?;
72+
73+
let p = prices
74+
.iter()
75+
.find(|p| p.protocol_network.eq(&protocol_network) && p.chain_id.eq(&chain_id));
76+
77+
Ok(p.cloned())
78+
}
79+
80+
pub async fn get_all_prices<'a>(&self, ctx: &'a Context<'_>) -> FieldResult<Vec<Price>> {
81+
let prices: &Vec<Price> = ctx.data()?;
82+
83+
Ok(prices.clone())
84+
}
85+
}
86+
87+
#[derive(Debug)]
88+
pub struct AgreementMutation {}
89+
90+
#[Object]
91+
impl AgreementMutation {
92+
pub async fn create_agreement<'a>(
93+
&self,
94+
ctx: &'a Context<'_>,
95+
signature: String,
96+
data: String,
97+
protocol_network: String,
98+
) -> FieldResult<Agreement> {
99+
let store: &Arc<dyn AgreementStore> = ctx.data()?;
100+
101+
store
102+
.create_agreement(
103+
signature.clone(),
104+
Agreement {
105+
signature,
106+
data,
107+
protocol_network,
108+
},
109+
)
110+
.await
111+
.map_err(async_graphql::Error::from)
112+
}
113+
114+
pub async fn cancel_agreement<'a>(
115+
&self,
116+
ctx: &'a Context<'_>,
117+
signature: String,
118+
) -> FieldResult<String> {
119+
let store: &Arc<dyn AgreementStore> = ctx.data()?;
120+
121+
store
122+
.cancel_agreement(&signature)
123+
.await
124+
.map_err(async_graphql::Error::from)
125+
}
126+
}

service/src/routes/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0
33

44
pub mod cost;
5+
pub mod dips;
56
mod status;
67

78
pub use status::status;

service/src/service.rs

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
// Copyright 2023-, Edge & Node, GraphOps, and Semiotic Labs.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
use std::sync::Arc;
54
use std::time::Duration;
5+
use std::{collections::HashMap, sync::Arc};
66

77
use super::{config::Config, error::SubgraphServiceError, routes};
88
use anyhow::anyhow;
9-
use axum::{async_trait, routing::post, Json, Router};
9+
use async_graphql::{EmptySubscription, Schema};
10+
use async_graphql_axum::GraphQL;
11+
use axum::{
12+
async_trait,
13+
routing::{post, post_service},
14+
Json, Router,
15+
};
1016
use indexer_common::indexer_service::http::{
1117
AttestationOutput, IndexerServiceImpl, IndexerServiceResponse,
1218
};
@@ -15,8 +21,16 @@ use reqwest::Url;
1521
use serde_json::{json, Value};
1622
use sqlx::PgPool;
1723
use thegraph_core::DeploymentId;
18-
19-
use crate::{cli::Cli, database};
24+
use tokio::sync::RwLock;
25+
26+
use crate::{
27+
cli::Cli,
28+
database::{
29+
self,
30+
dips::{AgreementStore, InMemoryAgreementStore},
31+
},
32+
routes::dips::Price,
33+
};
2034

2135
use clap::Parser;
2236
use indexer_common::indexer_service::http::{
@@ -173,6 +187,20 @@ pub async fn run() -> anyhow::Result<()> {
173187
.clone(),
174188
});
175189

190+
let agreement_store: Arc<dyn AgreementStore> = Arc::new(InMemoryAgreementStore {
191+
data: RwLock::new(HashMap::new()),
192+
});
193+
let prices: Vec<Price> = vec![];
194+
195+
let schema = Schema::build(
196+
routes::dips::AgreementQuery {},
197+
routes::dips::AgreementMutation {},
198+
EmptySubscription,
199+
)
200+
.data(agreement_store)
201+
.data(prices)
202+
.finish();
203+
176204
IndexerService::run(IndexerServiceOptions {
177205
release,
178206
config: config.0.clone(),
@@ -182,6 +210,7 @@ pub async fn run() -> anyhow::Result<()> {
182210
extra_routes: Router::new()
183211
.route("/cost", post(routes::cost::cost))
184212
.route("/status", post(routes::status))
213+
.route("/dips", post_service(GraphQL::new(schema)))
185214
.with_state(state),
186215
})
187216
.await

0 commit comments

Comments
 (0)