Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add additional boost endpoints #142

Merged
merged 5 commits into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/endpoints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub mod get_quests;
pub mod get_quiz;
pub mod get_tasks;
pub mod get_trending_quests;
pub mod quests;
pub mod has_completed_quest;
pub mod leaderboard;
pub mod quest_boost;
pub mod has_completed_quest;
pub mod quests;
52 changes: 52 additions & 0 deletions src/endpoints/quest_boost/get_boost.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use crate::{
models::{AppState, QuestDocument},
utils::get_error,
};
use axum::{
extract::{Query, State},
http::StatusCode,
response::{IntoResponse, Json},
};
use futures::StreamExt;
use mongodb::bson::doc;
use serde::Deserialize;
use std::sync::Arc;

#[derive(Deserialize)]
pub struct GetQuestsQuery {
id: u32,
}

pub async fn handler(
State(state): State<Arc<AppState>>,
Query(query): Query<GetQuestsQuery>,
) -> impl IntoResponse {
let collection = state.db.collection::<QuestDocument>("boosts");
let pipeline = [
doc! {
"$match": {
"id": query.id
}
},
doc! {
"$project":{
"_id":0
}
},
];

match collection.aggregate(pipeline, None).await {
Ok(mut cursor) => {
while let Some(result) = cursor.next().await {
match result {
Ok(document) => {
return (StatusCode::OK, Json(document)).into_response();
}
_ => continue,
}
}
get_error("Quest not found".to_string())
}
Err(_) => get_error("Error querying quest".to_string()),
}
}
44 changes: 44 additions & 0 deletions src/endpoints/quest_boost/get_boosts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use crate::models::BoostTable;
use crate::{models::AppState, utils::get_error};
use axum::{
extract::State,
http::StatusCode,
response::{IntoResponse, Json},
};
use chrono::Utc;
use futures::StreamExt;
use mongodb::bson::doc;
use mongodb::bson::from_document;
use std::sync::Arc;

pub async fn handler(State(state): State<Arc<AppState>>) -> impl IntoResponse {
let pipeline = vec![doc! {
"$match": {
"expiry":{
"$gt": Utc::now().timestamp_millis()
},
"winner": {
"$eq": null,
},
}
}];
let collection = state.db.collection::<BoostTable>("boosts");
match collection.aggregate(pipeline, None).await {
Ok(mut cursor) => {
let mut quests: Vec<BoostTable> = Vec::new();
while let Some(result) = cursor.next().await {
match result {
Ok(document) => {
quests.push(from_document(document).unwrap());
}
_ => continue,
}
}
if quests.len() == 0 {
return get_error("No boosts found".to_string());
}
(StatusCode::OK, Json(quests)).into_response()
}
Err(_) => get_error("Error querying boosts".to_string()),
}
}
126 changes: 126 additions & 0 deletions src/endpoints/quest_boost/get_quests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
use crate::models::{BoostTable, QuestDocument};
use crate::{models::AppState, utils::get_error};
use axum::extract::Query;
use axum::{
extract::State,
http::StatusCode,
response::{IntoResponse, Json},
};
use futures::{StreamExt};
use mongodb::bson::doc;
use mongodb::bson::from_document;
use serde::{Deserialize, Serialize};
use std::sync::Arc;

#[derive(Debug, Serialize, Deserialize)]
pub struct GetQuestForBoostQuery {
boost_id: u32,
}

pub async fn handler(
State(state): State<Arc<AppState>>,
Query(query): Query<GetQuestForBoostQuery>,
) -> impl IntoResponse {
let boost_id = query.boost_id;
let pipeline = vec![
doc! {
"$match": doc! {
"id": boost_id
}
},
doc! {
"$unwind": doc! {
"path": "$quests"
}
},
doc! {
"$lookup": doc! {
"from": "quests",
"let": doc! {
"task_id": "$quests"
},
"pipeline": [
doc! {
"$match": doc! {
"$expr": doc! {
"$eq": [
"$id",
"$$task_id"
]
}
}
}
],
"as": "quest"
}
},
doc! {
"$group": doc! {
"_id": 0,
"quest_list": doc! {
"$push": doc! {
"$arrayElemAt": [
"$quest",
0
]
}
}
}
},
doc! {
"$project": doc! {
"_id": 0
}
},
doc! {
"$project": doc! {
"quests": doc! {
"$map": doc! {
"input": "$quest_list",
"as": "item",
"in": doc! {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If those are the same, could you try to use "$mergeObjects": ["$$item"]?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

"id": "$$item.id",
"category": "$$item.category",
"name": "$$item.name",
"desc": "$$item.desc",
"issuer": "$$item.issuer",
"logo": "$$item.logo",
"rewards_img": "$$item.rewards_img",
"rewards_title": "$$item.rewards_title",
"img_card": "$$item.img_card",
"title_card": "$$item.title_card",
"hidden": "$$item.hidden",
"disabled": "$$item.disabled",
"expiry": "$$item.expiry",
"expiry_timestamp": "$$item.expiry_timestamp",
"mandatory_domain": "$$item.mandatory_domain",
"expired": "$$item.expired",
"experience": "$$item.experience",
"rewards_title": "$$item.rewards_title",
"rewards_nfts": "$$item.rewards_nfts",
"rewards_description": "$$item.rewards_description",
"rewards_endpoint": "$$item.rewards_endpoint",
}
}
}
}
},
];
let collection = state.db.collection::<BoostTable>("boosts");
match collection.aggregate(pipeline, None).await {
Ok(mut cursor) => {
let mut res: Vec<QuestDocument> = Vec::new();
while let Some(result) = cursor.next().await {
let document = result.unwrap();
let quest_list = document.get_array("quests").unwrap();
for quest in quest_list {
let quest_doc = quest.as_document().unwrap();
let quest = from_document::<QuestDocument>(quest_doc.clone()).unwrap();
res.push(quest);
}
}
(StatusCode::OK, Json(res)).into_response()
}
Err(_) => get_error("Error querying boosts".to_string()),
}
}
5 changes: 4 additions & 1 deletion src/endpoints/quest_boost/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
pub mod get_claim_params;
pub mod get_boost;
pub mod get_boosts;
pub mod get_claim_params;
pub mod get_quests;
17 changes: 14 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ use starknet::providers::{jsonrpc::HttpTransport, JsonRpcClient};
use std::net::SocketAddr;
use std::sync::Arc;

use crate::utils::{add_leaderboard_table, run_boosts_raffle};
use tower_http::cors::{Any, CorsLayer};
use crate::utils::{ add_leaderboard_table, run_boosts_raffle};

#[tokio::main]
async fn main() {
Expand All @@ -27,7 +27,6 @@ async fn main() {
.await
.unwrap();


let shared_state = Arc::new(models::AppState {
conf: conf.clone(),
provider: JsonRpcClient::new(HttpTransport::new(
Expand All @@ -50,7 +49,7 @@ async fn main() {
}

let db_instance = shared_state.db.clone();
run_boosts_raffle(&db_instance,conf.quest_boost.update_interval);
run_boosts_raffle(&db_instance, conf.quest_boost.update_interval);
add_leaderboard_table(&shared_state.db).await;

let cors = CorsLayer::new().allow_headers(Any).allow_origin(Any);
Expand Down Expand Up @@ -441,6 +440,18 @@ async fn main() {
"/boost/get_claim_params",
get(endpoints::quest_boost::get_claim_params::handler),
)
.route(
"/boost/get_boosts",
get(endpoints::quest_boost::get_boosts::handler),
)
.route(
"/boost/get_quests",
get(endpoints::quest_boost::get_quests::handler),
)
.route(
"/boost/get_boost",
get(endpoints::quest_boost::get_boost::handler),
)
.with_state(shared_state)
.layer(cors);

Expand Down
3 changes: 1 addition & 2 deletions src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ pub_struct!(Debug, Serialize, Deserialize; LeaderboardTable {
timestamp:f64,
});


pub_struct!(Debug, Serialize, Deserialize; BoostTable {
amount: i32,
token: String,
Expand All @@ -156,8 +155,8 @@ pub_struct!(Debug, Serialize, Deserialize; BoostTable {
claimed: bool,
winner: Option<String>,
id: i32,
boost_description: String,
img_url: String,
name: String,
});

pub_struct!(Debug, Serialize, Deserialize; NftBalance {
Expand Down