Skip to content

Commit

Permalink
feat: add dips graphql
Browse files Browse the repository at this point in the history
  • Loading branch information
mangas committed Oct 4, 2024
1 parent f931744 commit 7966bee
Show file tree
Hide file tree
Showing 5 changed files with 201 additions and 4 deletions.
44 changes: 44 additions & 0 deletions service/src/database/dips.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2023-, Edge & Node, GraphOps, and Semiotic Labs.
// SPDX-License-Identifier: Apache-2.0

use std::collections::HashMap;

use axum::async_trait;

use crate::routes::dips::Agreement;

#[async_trait]
pub trait AgreementStore: Sync + Send {
async fn get_by_signature(&self, signature: String) -> anyhow::Result<Option<Agreement>>;
async fn create_agreement(
&self,
signature: String,
data: Agreement,
) -> anyhow::Result<Agreement>;
async fn cancel_agreement(&self, signature: String) -> anyhow::Result<String>;
}

pub struct InMemoryAgreementStore {
pub data: tokio::sync::RwLock<HashMap<String, Agreement>>,
}

#[async_trait]
impl AgreementStore for InMemoryAgreementStore {
async fn get_by_signature(&self, signature: String) -> anyhow::Result<Option<Agreement>> {
Ok(self.data.try_read()?.get(&signature).cloned())
}
async fn create_agreement(
&self,
signature: String,
agreement: Agreement,
) -> anyhow::Result<Agreement> {
self.data.try_write()?.insert(signature, agreement.clone());

Ok(agreement)
}
async fn cancel_agreement(&self, signature: String) -> anyhow::Result<String> {
self.data.try_write()?.remove(&signature);

Ok(signature.clone())
}
}
2 changes: 2 additions & 0 deletions service/src/database.rs → service/src/database/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright 2023-, Edge & Node, GraphOps, and Semiotic Labs.
// SPDX-License-Identifier: Apache-2.0

pub mod dips;

use std::time::Duration;
use std::{collections::HashSet, str::FromStr};

Expand Down
121 changes: 121 additions & 0 deletions service/src/routes/dips.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// Copyright 2023-, Edge & Node, GraphOps, and Semiotic Labs.
// SPDX-License-Identifier: Apache-2.0

use std::{str::FromStr, sync::Arc};

use anyhow::bail;
use async_graphql::{Context, FieldResult, Object, SimpleObject};

use crate::database::dips::AgreementStore;

pub enum NetworkProtocol {
ArbitrumMainnet,
}

impl FromStr for NetworkProtocol {
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let p = match s {
"arbitrum-mainnet" => NetworkProtocol::ArbitrumMainnet,
_ => bail!("unknown network protocol"),
};

Ok(p)
}
}

#[derive(SimpleObject, Debug, Clone)]
pub struct Agreement {
signature: String,
data: String,
protocol_network: String,
}

#[derive(SimpleObject, Debug, Clone)]
pub struct Price {
price_per_block: String,
chain_id: String,
protocol_network: String,
}

#[derive(Debug)]
pub struct AgreementQuery {}

#[Object]
impl AgreementQuery {
pub async fn get_agreement<'a>(
&self,
ctx: &'a Context<'_>,
signature: String,
) -> FieldResult<Option<Agreement>> {
let store: &Arc<dyn AgreementStore> = ctx.data()?;

store
.get_by_signature(signature)
.await
.map_err(async_graphql::Error::from)
}

pub async fn get_price<'a>(
&self,
ctx: &'a Context<'_>,
protocol_network: String,
chain_id: String,
) -> FieldResult<Option<Price>> {
let prices: &Vec<Price> = ctx.data()?;

let p = prices
.iter()
.find(|p| p.protocol_network.eq(&protocol_network) && p.chain_id.eq(&chain_id));

Ok(p.cloned())
}

pub async fn get_all_prices<'a>(&self, ctx: &'a Context<'_>) -> FieldResult<Vec<Price>> {
let prices: &Vec<Price> = ctx.data()?;

Ok(prices.clone())
}
}

#[derive(Debug)]
pub struct AgreementMutation {}

#[Object]
impl AgreementMutation {
pub async fn create_agreement<'a>(
&self,
ctx: &'a Context<'_>,
signature: String,
data: String,
protocol_network: String,
) -> FieldResult<Agreement> {
let store: &Arc<dyn AgreementStore> = ctx.data()?;

store
.create_agreement(
signature.clone(),
Agreement {
signature,
data,
protocol_network,
},
)
.await
.map_err(async_graphql::Error::from)
}

pub async fn cancel_agreement<'a>(
&self,
ctx: &'a Context<'_>,
signature: String,
) -> FieldResult<String> {
let store: &Arc<dyn AgreementStore> = ctx.data()?;

store
.cancel_agreement(signature)
.await
.map_err(async_graphql::Error::from)
}
}
1 change: 1 addition & 0 deletions service/src/routes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

pub mod cost;
pub mod dips;
mod status;

pub use status::status;
37 changes: 33 additions & 4 deletions service/src/service.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
// Copyright 2023-, Edge & Node, GraphOps, and Semiotic Labs.
// SPDX-License-Identifier: Apache-2.0

use std::sync::Arc;
use std::time::Duration;
use std::{collections::HashMap, sync::Arc};

use super::{config::Config, error::SubgraphServiceError, routes};
use anyhow::anyhow;
use axum::{async_trait, routing::post, Json, Router};
use async_graphql::{EmptySubscription, Schema};
use async_graphql_axum::GraphQL;
use axum::{
async_trait,
routing::{post, post_service},
Json, Router,
};
use indexer_common::indexer_service::http::{
AttestationOutput, IndexerServiceImpl, IndexerServiceResponse,
};
Expand All @@ -15,8 +21,16 @@ use reqwest::Url;
use serde_json::{json, Value};
use sqlx::PgPool;
use thegraph_core::DeploymentId;

use crate::{cli::Cli, database};
use tokio::sync::RwLock;

use crate::{
cli::Cli,
database::{
self,
dips::{AgreementStore, InMemoryAgreementStore},
},
routes::dips::Price,
};

use clap::Parser;
use indexer_common::indexer_service::http::{
Expand Down Expand Up @@ -173,6 +187,20 @@ pub async fn run() -> anyhow::Result<()> {
.clone(),
});

let agreement_store: Arc<dyn AgreementStore> = Arc::new(InMemoryAgreementStore {
data: RwLock::new(HashMap::new()),
});
let prices: Vec<Price> = vec![];

let schema = Schema::build(
routes::dips::AgreementQuery {},
routes::dips::AgreementMutation {},
EmptySubscription,
)
.data(agreement_store)
.data(prices)
.finish();

IndexerService::run(IndexerServiceOptions {
release,
config: config.0.clone(),
Expand All @@ -181,6 +209,7 @@ pub async fn run() -> anyhow::Result<()> {
extra_routes: Router::new()
.route("/cost", post(routes::cost::cost))
.route("/status", post(routes::status))
.route("/dips", post_service(GraphQL::new(schema)))
.with_state(state),
})
.await
Expand Down

0 comments on commit 7966bee

Please sign in to comment.