Skip to content

Commit

Permalink
Merge pull request #273 from Ugo-X/testnet
Browse files Browse the repository at this point in the history
created advanced contract task type
  • Loading branch information
Marchand-Nicolas authored Sep 28, 2024
2 parents da7fe81 + c1367a8 commit ca27945
Show file tree
Hide file tree
Showing 11 changed files with 124 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/endpoints/admin/balance/create_balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ pub async fn handler(
contracts: Some(parsed_contracts),
api_url: None,
regex: None,
calls: None,
};

// insert document to boost collection
Expand Down
1 change: 1 addition & 0 deletions src/endpoints/admin/custom/create_custom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ pub async fn handler(
contracts: None,
api_url: None,
regex: None,
calls: None,
};

// insert document to boost collection
Expand Down
1 change: 1 addition & 0 deletions src/endpoints/admin/discord/create_discord.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ pub async fn handler(
contracts: None,
api_url: None,
regex: None,
calls: None,
};

// insert document to boost collection
Expand Down
1 change: 1 addition & 0 deletions src/endpoints/admin/domain/create_domain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ pub async fn handler(
contracts: None,
api_url: None,
regex: None,
calls: None,
};

// insert document to boost collection
Expand Down
1 change: 1 addition & 0 deletions src/endpoints/admin/quiz/create_quiz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ pub async fn handler(
contracts: None,
api_url: None,
regex: None,
calls: None,
};

return match tasks_collection.insert_one(new_document, None).await {
Expand Down
1 change: 1 addition & 0 deletions src/endpoints/admin/twitter/create_twitter_fw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ pub async fn handler(
contracts: None,
api_url: None,
regex: None,
calls: None,
};

// insert document to boost collection
Expand Down
1 change: 1 addition & 0 deletions src/endpoints/admin/twitter/create_twitter_rw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ pub async fn handler(
contracts: None,
api_url: None,
regex: None,
calls: None,
};

// insert document to boost collection
Expand Down
1 change: 1 addition & 0 deletions src/endpoints/quests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ pub mod verify_custom_api;
pub mod verify_quiz;
pub mod verify_twitter_fw;
pub mod verify_twitter_rw;
pub mod verify_contract;
2 changes: 1 addition & 1 deletion src/endpoints/quests/verify_balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,4 @@ pub async fn handler(
}
Err(e) => get_error(format!("{}", e)),
}
}
}
106 changes: 106 additions & 0 deletions src/endpoints/quests/verify_contract.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
use std::sync::Arc;

use crate::{
models::{AppState, QuestTaskDocument},
utils::{get_error, CompletedTasksTrait},
};
use axum::{
extract::{Query, State},
http::StatusCode,
response::IntoResponse,
Json,
};
use axum_auto_routes::route;
use mongodb::bson::doc;
use serde::{Deserialize, Serialize};
use serde_json::json;
use starknet::{
core::types::{BlockId, BlockTag, FieldElement, FunctionCall},
providers::Provider,
};
use regex::Regex;

#[derive(Debug, Serialize, Deserialize, Default)]
pub struct VerifyContractQuery {
pub addr: FieldElement,
pub task_id: u32,
}

#[route(get, "/quests/verify_contract")]
pub async fn handler(
State(state): State<Arc<AppState>>,
Query(query): Query<VerifyContractQuery>,
) -> impl IntoResponse {
let task_id = query.task_id;
// Get task from db
let task_collection = state.db.collection::<QuestTaskDocument>("tasks");
let task = match task_collection.find_one(doc! {"id": task_id}, None).await {
Ok(Some(task)) => task,
Ok(None) => return get_error("Task not found".to_string()),
Err(e) => return get_error(format!("Database error: {}", e)),
};

if task.task_type != Some("contract".to_string()) {
return get_error("Invalid task type.".to_string());
}

let addr = &query.addr;

if let Some(calls) = task.calls {
for call in calls {
let contract_address = match FieldElement::from_hex_be(&call.contract) {
Ok(address) => address,
Err(e) => return get_error(format!("Invalid contract address: {}", e)),
};

let calldata: Vec<FieldElement> = match call.call_data
.iter()
.map(|s| FieldElement::from_hex_be(s))
.collect::<Result<Vec<FieldElement>, _>>()
{
Ok(data) => data,
Err(e) => return get_error(format!("Invalid calldata: {}", e)),
};

let entry_point_selector = match FieldElement::from_hex_be(&call.entry_point) {
Ok(selector) => selector,
Err(e) => return get_error(format!("Invalid entry point: {}", e)),
};

let call_result = state
.provider
.call(
FunctionCall {
contract_address,
entry_point_selector,
calldata,
},
BlockId::Tag(BlockTag::Latest),
)
.await;

match call_result {
Ok(result) => {
let regex = match Regex::new(&call.regex) {
Ok(re) => re,
Err(e) => return get_error(format!("Invalid regex: {}", e)),
};
let result_str = result.iter().map(|&r| r.to_string()).collect::<Vec<String>>().join(",");

if !regex.is_match(&result_str) {
return get_error("Contract call result does not match the expected pattern.".to_string());
}
}
Err(e) => return get_error(format!("Contract call failed: {}", e)),
}
}

// All calls succeeded and matched their regexes
match state.upsert_completed_task(*addr, task_id).await {
Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(),
Err(e) => get_error(format!("Failed to update completed task: {}", e)),
}
} else {
get_error("No calls specified for this task.".to_string())
}
}
9 changes: 9 additions & 0 deletions src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,14 @@ pub struct CompletedTaskDocument {
timestamp: i64,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Call {
pub contract: String,
pub call_data: Vec<String>,
pub entry_point: String,
pub regex: String,
}

#[derive(Debug, Serialize, Deserialize, Default)]
pub struct QuestTaskDocument {
pub(crate) id: i32,
Expand All @@ -120,6 +128,7 @@ pub struct QuestTaskDocument {
pub verify_endpoint_type: String,
pub api_url: Option<String>,
pub regex: Option<String>,
pub calls: Option<Vec<Call>>,
#[serde(default)]
pub verify_redirect: Option<String>,
#[serde(default)]
Expand Down

0 comments on commit ca27945

Please sign in to comment.