From 198a9eed9b56e8d899eb9477767aa99cec1d7a94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Ag=C3=BCero?= <54730752+EmmanuelAR@users.noreply.github.com> Date: Sun, 25 Aug 2024 12:29:06 -0600 Subject: [PATCH] =?UTF-8?q?Remove=20unused=20quests:=E2=80=A81-=20avnu;=20?= =?UTF-8?q?2-=20bountive;=203-=20braavos;=204-=20carmine;=205-=20element;?= =?UTF-8?q?=206-=20haiko;=207-=20hashstack;=208-=20influence;=209-=20jedis?= =?UTF-8?q?wap;=2010-=20morphine;=2011-=20myswap;=2012-=20nimbora;=2013-?= =?UTF-8?q?=20orbiter;=2014-=20rango;=2015-=20rhino;=2016-=20sithswap;=201?= =?UTF-8?q?7-=20strk=5Ffarm;=2018-=20tribe;=2019-=20zklend=20Remove=20the?= =?UTF-8?q?=20remove=20modules=20in=20mod.rs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/endpoints/quests/avnu/claimable.rs | 105 -------- .../quests/avnu/discord_fw_callback.rs | 147 ------------ src/endpoints/quests/avnu/mod.rs | 3 - src/endpoints/quests/avnu/verify_swap.rs | 60 ----- src/endpoints/quests/bountive/claimable.rs | 105 -------- src/endpoints/quests/bountive/mod.rs | 4 - .../quests/bountive/verify_deposit.rs | 55 ----- .../quests/bountive/verify_twitter_fw.rs | 26 -- .../quests/bountive/verify_twitter_rt.rs | 26 -- .../quests/braavos/avnu/claimable.rs | 105 -------- src/endpoints/quests/braavos/avnu/mod.rs | 6 - .../quests/braavos/avnu/verify_has_domain.rs | 18 -- .../quests/braavos/avnu/verify_swap.rs | 60 ----- .../braavos/avnu/verify_twitter_fw_avnu.rs | 26 -- .../braavos/avnu/verify_twitter_fw_braavos.rs | 26 -- .../quests/braavos/avnu/verify_twitter_rt.rs | 26 -- .../quests/braavos/carbonable/claimable.rs | 105 -------- .../quests/braavos/carbonable/mod.rs | 6 - .../braavos/carbonable/verify_deposit.rs | 55 ----- .../braavos/carbonable/verify_has_domain.rs | 18 -- .../carbonable/verify_twitter_fw_braavos.rs | 26 -- .../verify_twitter_fw_carbonable.rs | 26 -- .../braavos/carbonable/verify_twitter_rt.rs | 26 -- src/endpoints/quests/braavos/mod.rs | 8 - .../quests/braavos/myswap/claimable.rs | 105 -------- src/endpoints/quests/braavos/myswap/mod.rs | 5 - .../braavos/myswap/verify_added_liquidity.rs | 55 ----- .../braavos/myswap/verify_has_domain.rs | 18 -- .../myswap/verify_twitter_fw_braavos.rs | 26 -- .../myswap/verify_twitter_fw_myswap.rs | 26 -- .../quests/braavos/pyramid/claimable.rs | 105 -------- src/endpoints/quests/braavos/pyramid/mod.rs | 6 - .../braavos/pyramid/verify_buy_or_list.rs | 43 ---- .../braavos/pyramid/verify_has_domain.rs | 18 -- .../pyramid/verify_twitter_fw_braavos.rs | 26 -- .../pyramid/verify_twitter_fw_pyramid.rs | 26 -- .../braavos/pyramid/verify_twitter_rt.rs | 26 -- .../quests/braavos/realms/claimable.rs | 105 -------- src/endpoints/quests/braavos/realms/mod.rs | 6 - .../braavos/realms/verify_has_domain.rs | 18 -- .../braavos/realms/verify_has_played.rs | 26 -- .../realms/verify_twitter_fw_braavos.rs | 26 -- .../realms/verify_twitter_fw_realms.rs | 26 -- .../braavos/realms/verify_twitter_rt.rs | 26 -- .../quests/braavos/starknetid/claimable.rs | 105 -------- .../quests/braavos/starknetid/mod.rs | 6 - .../braavos/starknetid/verify_has_domain.rs | 18 -- .../braavos/starknetid/verify_has_mission.rs | 225 ------------------ .../starknetid/verify_twitter_fw_braavos.rs | 26 -- .../starknetid/verify_twitter_fw_sid.rs | 26 -- .../starknetid/verify_twitter_fw_sq.rs | 26 -- .../quests/braavos/wallet/claimable.rs | 105 -------- src/endpoints/quests/braavos/wallet/mod.rs | 4 - .../braavos/wallet/verify_has_domain.rs | 18 -- .../wallet/verify_twitter_fw_braavos.rs | 26 -- .../braavos/wallet/verify_twitter_rt.rs | 26 -- .../quests/braavos/zklend/claimable.rs | 105 -------- src/endpoints/quests/braavos/zklend/mod.rs | 6 - .../braavos/zklend/verify_added_liquidity.rs | 57 ----- .../braavos/zklend/verify_has_domain.rs | 18 -- .../zklend/verify_twitter_fw_braavos.rs | 26 -- .../zklend/verify_twitter_fw_zklend.rs | 26 -- .../braavos/zklend/verify_twitter_rt.rs | 26 -- src/endpoints/quests/carmine/claimable.rs | 105 -------- src/endpoints/quests/carmine/mod.rs | 1 - .../quests/element/briq/claimable.rs | 105 -------- src/endpoints/quests/element/briq/mod.rs | 3 - .../quests/element/briq/verify_own_briq.rs | 79 ------ .../quests/element/briq/verify_twitter_fw.rs | 30 --- .../quests/element/element/claimable.rs | 105 -------- src/endpoints/quests/element/element/mod.rs | 3 - .../element/element/verify_is_eligible.rs | 71 ------ .../element/element/verify_twitter_fw.rs | 30 --- .../quests/element/layerswap/claimable.rs | 105 -------- src/endpoints/quests/element/layerswap/mod.rs | 4 - .../element/layerswap/verify_has_bridged.rs | 79 ------ .../element/layerswap/verify_twitter_fw.rs | 30 --- .../element/layerswap/verify_twitter_rt.rs | 30 --- src/endpoints/quests/element/mod.rs | 4 - .../quests/element/starknetid/claimable.rs | 105 -------- .../quests/element/starknetid/mod.rs | 2 - .../starknetid/verify_has_root_domain.rs | 18 -- src/endpoints/quests/haiko/claimable.rs | 105 -------- src/endpoints/quests/haiko/mod.rs | 4 - src/endpoints/quests/haiko/verify_deposit.rs | 52 ---- .../quests/haiko/verify_twitter_fw.rs | 26 -- .../quests/haiko/verify_twitter_rw.rs | 26 -- src/endpoints/quests/hashstack/claimable.rs | 105 -------- .../quests/hashstack/discord_fw_callback.rs | 148 ------------ src/endpoints/quests/hashstack/mod.rs | 6 - .../quests/hashstack/verify_deposit.rs | 56 ----- .../quests/hashstack/verify_has_domain.rs | 18 -- .../hashstack/verify_twitter_fw_hashstack.rs | 26 -- .../quests/hashstack/verify_twitter_rw.rs | 26 -- src/endpoints/quests/influence/claimable.rs | 105 -------- .../quests/influence/discord_fw_callback.rs | 148 ------------ src/endpoints/quests/influence/mod.rs | 5 - .../quests/influence/verify_twitter_fw.rs | 26 -- .../quests/influence/verify_twitter_rw.rs | 26 -- .../quests/influence/verify_twitter_rw_2.rs | 26 -- src/endpoints/quests/jediswap/claimable.rs | 105 -------- src/endpoints/quests/jediswap/mod.rs | 4 - .../quests/jediswap/verify_added_liquidity.rs | 57 ----- .../quests/jediswap/verify_twitter_fw.rs | 26 -- .../quests/jediswap/verify_twitter_rt.rs | 26 -- src/endpoints/quests/mod.rs | 19 -- src/endpoints/quests/morphine/claimable.rs | 105 -------- src/endpoints/quests/morphine/mod.rs | 2 - .../quests/morphine/verify_added_liquidity.rs | 82 ------- src/endpoints/quests/myswap/claimable.rs | 105 -------- .../quests/myswap/discord_fw_callback.rs | 147 ------------ src/endpoints/quests/myswap/mod.rs | 3 - .../quests/myswap/verify_added_liquidity.rs | 55 ----- src/endpoints/quests/nimbora/check_balance.rs | 54 ----- src/endpoints/quests/nimbora/claimable.rs | 105 -------- .../quests/nimbora/discord_fw_callback.rs | 149 ------------ src/endpoints/quests/nimbora/mod.rs | 4 - .../quests/nimbora/verify_twitter_rt.rs | 26 -- src/endpoints/quests/orbiter/claimable.rs | 105 -------- src/endpoints/quests/orbiter/mod.rs | 6 - .../quests/orbiter/verify_has_bridged.rs | 79 ------ .../quests/orbiter/verify_has_root_domain.rs | 18 -- .../quests/orbiter/verify_twitter_fw.rs | 30 --- .../quests/orbiter/verify_twitter_fw_sq.rs | 30 --- .../quests/orbiter/verify_twitter_rt.rs | 30 --- src/endpoints/quests/rango/mod.rs | 2 - .../quests/rango/quest1/check_trade.rs | 52 ---- .../quests/rango/quest1/claimable.rs | 105 -------- .../rango/quest1/discord_fw_callback.rs | 147 ------------ src/endpoints/quests/rango/quest1/mod.rs | 4 - .../quests/rango/quest1/verify_twitter_fw.rs | 26 -- .../quests/rango/quest2/check_trade.rs | 81 ------- .../quests/rango/quest2/claimable.rs | 105 -------- .../rango/quest2/discord_fw_callback.rs | 147 ------------ src/endpoints/quests/rango/quest2/mod.rs | 5 - .../quests/rango/quest2/verify_twitter_fw.rs | 26 -- .../quests/rango/quest2/verify_twitter_rw.rs | 26 -- src/endpoints/quests/rhino/check_bridge.rs | 53 ----- src/endpoints/quests/rhino/claimable.rs | 105 -------- src/endpoints/quests/rhino/mod.rs | 4 - .../quests/rhino/verify_twitter_fw.rs | 26 -- .../quests/rhino/verify_twitter_rw.rs | 26 -- src/endpoints/quests/sithswap/mod.rs | 2 - .../quests/sithswap/quest1/claimable.rs | 105 -------- src/endpoints/quests/sithswap/quest1/mod.rs | 3 - .../sithswap/quest1/verify_added_liquidity.rs | 57 ----- .../sithswap/quest1/verify_twitter_fw.rs | 30 --- .../quests/sithswap/quest2/claimable.rs | 105 -------- src/endpoints/quests/sithswap/quest2/mod.rs | 5 - .../quests/sithswap/quest2/verify_deposit.rs | 111 --------- .../sithswap/quest2/verify_has_domain.rs | 18 -- .../sithswap/quest2/verify_twitter_fw.rs | 30 --- .../sithswap/quest2/verify_twitter_rw.rs | 30 --- .../quests/strk_farm/check_balance.rs | 43 ---- src/endpoints/quests/strk_farm/mod.rs | 1 - src/endpoints/quests/tribe/claimable.rs | 135 ----------- src/endpoints/quests/tribe/mod.rs | 4 - .../quests/tribe/verify_has_domain.rs | 64 ----- .../quests/tribe/verify_has_root_domain.rs | 18 -- .../quests/tribe/verify_three_years_expiry.rs | 96 -------- src/endpoints/quests/zklend/claimable.rs | 105 -------- src/endpoints/quests/zklend/mod.rs | 3 - src/endpoints/quests/zklend/verify_borrow.rs | 55 ----- .../quests/zklend/verify_twitter_fw.rs | 30 --- 164 files changed, 7866 deletions(-) delete mode 100644 src/endpoints/quests/avnu/claimable.rs delete mode 100644 src/endpoints/quests/avnu/discord_fw_callback.rs delete mode 100644 src/endpoints/quests/avnu/mod.rs delete mode 100644 src/endpoints/quests/avnu/verify_swap.rs delete mode 100644 src/endpoints/quests/bountive/claimable.rs delete mode 100644 src/endpoints/quests/bountive/mod.rs delete mode 100644 src/endpoints/quests/bountive/verify_deposit.rs delete mode 100644 src/endpoints/quests/bountive/verify_twitter_fw.rs delete mode 100644 src/endpoints/quests/bountive/verify_twitter_rt.rs delete mode 100644 src/endpoints/quests/braavos/avnu/claimable.rs delete mode 100644 src/endpoints/quests/braavos/avnu/mod.rs delete mode 100644 src/endpoints/quests/braavos/avnu/verify_has_domain.rs delete mode 100644 src/endpoints/quests/braavos/avnu/verify_swap.rs delete mode 100644 src/endpoints/quests/braavos/avnu/verify_twitter_fw_avnu.rs delete mode 100644 src/endpoints/quests/braavos/avnu/verify_twitter_fw_braavos.rs delete mode 100644 src/endpoints/quests/braavos/avnu/verify_twitter_rt.rs delete mode 100644 src/endpoints/quests/braavos/carbonable/claimable.rs delete mode 100644 src/endpoints/quests/braavos/carbonable/mod.rs delete mode 100644 src/endpoints/quests/braavos/carbonable/verify_deposit.rs delete mode 100644 src/endpoints/quests/braavos/carbonable/verify_has_domain.rs delete mode 100644 src/endpoints/quests/braavos/carbonable/verify_twitter_fw_braavos.rs delete mode 100644 src/endpoints/quests/braavos/carbonable/verify_twitter_fw_carbonable.rs delete mode 100644 src/endpoints/quests/braavos/carbonable/verify_twitter_rt.rs delete mode 100644 src/endpoints/quests/braavos/mod.rs delete mode 100644 src/endpoints/quests/braavos/myswap/claimable.rs delete mode 100644 src/endpoints/quests/braavos/myswap/mod.rs delete mode 100644 src/endpoints/quests/braavos/myswap/verify_added_liquidity.rs delete mode 100644 src/endpoints/quests/braavos/myswap/verify_has_domain.rs delete mode 100644 src/endpoints/quests/braavos/myswap/verify_twitter_fw_braavos.rs delete mode 100644 src/endpoints/quests/braavos/myswap/verify_twitter_fw_myswap.rs delete mode 100644 src/endpoints/quests/braavos/pyramid/claimable.rs delete mode 100644 src/endpoints/quests/braavos/pyramid/mod.rs delete mode 100644 src/endpoints/quests/braavos/pyramid/verify_buy_or_list.rs delete mode 100644 src/endpoints/quests/braavos/pyramid/verify_has_domain.rs delete mode 100644 src/endpoints/quests/braavos/pyramid/verify_twitter_fw_braavos.rs delete mode 100644 src/endpoints/quests/braavos/pyramid/verify_twitter_fw_pyramid.rs delete mode 100644 src/endpoints/quests/braavos/pyramid/verify_twitter_rt.rs delete mode 100644 src/endpoints/quests/braavos/realms/claimable.rs delete mode 100644 src/endpoints/quests/braavos/realms/mod.rs delete mode 100644 src/endpoints/quests/braavos/realms/verify_has_domain.rs delete mode 100644 src/endpoints/quests/braavos/realms/verify_has_played.rs delete mode 100644 src/endpoints/quests/braavos/realms/verify_twitter_fw_braavos.rs delete mode 100644 src/endpoints/quests/braavos/realms/verify_twitter_fw_realms.rs delete mode 100644 src/endpoints/quests/braavos/realms/verify_twitter_rt.rs delete mode 100644 src/endpoints/quests/braavos/starknetid/claimable.rs delete mode 100644 src/endpoints/quests/braavos/starknetid/mod.rs delete mode 100644 src/endpoints/quests/braavos/starknetid/verify_has_domain.rs delete mode 100644 src/endpoints/quests/braavos/starknetid/verify_has_mission.rs delete mode 100644 src/endpoints/quests/braavos/starknetid/verify_twitter_fw_braavos.rs delete mode 100644 src/endpoints/quests/braavos/starknetid/verify_twitter_fw_sid.rs delete mode 100644 src/endpoints/quests/braavos/starknetid/verify_twitter_fw_sq.rs delete mode 100644 src/endpoints/quests/braavos/wallet/claimable.rs delete mode 100644 src/endpoints/quests/braavos/wallet/mod.rs delete mode 100644 src/endpoints/quests/braavos/wallet/verify_has_domain.rs delete mode 100644 src/endpoints/quests/braavos/wallet/verify_twitter_fw_braavos.rs delete mode 100644 src/endpoints/quests/braavos/wallet/verify_twitter_rt.rs delete mode 100644 src/endpoints/quests/braavos/zklend/claimable.rs delete mode 100644 src/endpoints/quests/braavos/zklend/mod.rs delete mode 100644 src/endpoints/quests/braavos/zklend/verify_added_liquidity.rs delete mode 100644 src/endpoints/quests/braavos/zklend/verify_has_domain.rs delete mode 100644 src/endpoints/quests/braavos/zklend/verify_twitter_fw_braavos.rs delete mode 100644 src/endpoints/quests/braavos/zklend/verify_twitter_fw_zklend.rs delete mode 100644 src/endpoints/quests/braavos/zklend/verify_twitter_rt.rs delete mode 100644 src/endpoints/quests/carmine/claimable.rs delete mode 100644 src/endpoints/quests/carmine/mod.rs delete mode 100644 src/endpoints/quests/element/briq/claimable.rs delete mode 100644 src/endpoints/quests/element/briq/mod.rs delete mode 100644 src/endpoints/quests/element/briq/verify_own_briq.rs delete mode 100644 src/endpoints/quests/element/briq/verify_twitter_fw.rs delete mode 100644 src/endpoints/quests/element/element/claimable.rs delete mode 100644 src/endpoints/quests/element/element/mod.rs delete mode 100644 src/endpoints/quests/element/element/verify_is_eligible.rs delete mode 100644 src/endpoints/quests/element/element/verify_twitter_fw.rs delete mode 100644 src/endpoints/quests/element/layerswap/claimable.rs delete mode 100644 src/endpoints/quests/element/layerswap/mod.rs delete mode 100644 src/endpoints/quests/element/layerswap/verify_has_bridged.rs delete mode 100644 src/endpoints/quests/element/layerswap/verify_twitter_fw.rs delete mode 100644 src/endpoints/quests/element/layerswap/verify_twitter_rt.rs delete mode 100644 src/endpoints/quests/element/mod.rs delete mode 100644 src/endpoints/quests/element/starknetid/claimable.rs delete mode 100644 src/endpoints/quests/element/starknetid/mod.rs delete mode 100644 src/endpoints/quests/element/starknetid/verify_has_root_domain.rs delete mode 100644 src/endpoints/quests/haiko/claimable.rs delete mode 100644 src/endpoints/quests/haiko/mod.rs delete mode 100644 src/endpoints/quests/haiko/verify_deposit.rs delete mode 100644 src/endpoints/quests/haiko/verify_twitter_fw.rs delete mode 100644 src/endpoints/quests/haiko/verify_twitter_rw.rs delete mode 100644 src/endpoints/quests/hashstack/claimable.rs delete mode 100644 src/endpoints/quests/hashstack/discord_fw_callback.rs delete mode 100644 src/endpoints/quests/hashstack/mod.rs delete mode 100644 src/endpoints/quests/hashstack/verify_deposit.rs delete mode 100644 src/endpoints/quests/hashstack/verify_has_domain.rs delete mode 100644 src/endpoints/quests/hashstack/verify_twitter_fw_hashstack.rs delete mode 100644 src/endpoints/quests/hashstack/verify_twitter_rw.rs delete mode 100644 src/endpoints/quests/influence/claimable.rs delete mode 100644 src/endpoints/quests/influence/discord_fw_callback.rs delete mode 100644 src/endpoints/quests/influence/mod.rs delete mode 100644 src/endpoints/quests/influence/verify_twitter_fw.rs delete mode 100644 src/endpoints/quests/influence/verify_twitter_rw.rs delete mode 100644 src/endpoints/quests/influence/verify_twitter_rw_2.rs delete mode 100644 src/endpoints/quests/jediswap/claimable.rs delete mode 100644 src/endpoints/quests/jediswap/mod.rs delete mode 100644 src/endpoints/quests/jediswap/verify_added_liquidity.rs delete mode 100644 src/endpoints/quests/jediswap/verify_twitter_fw.rs delete mode 100644 src/endpoints/quests/jediswap/verify_twitter_rt.rs delete mode 100644 src/endpoints/quests/morphine/claimable.rs delete mode 100644 src/endpoints/quests/morphine/mod.rs delete mode 100644 src/endpoints/quests/morphine/verify_added_liquidity.rs delete mode 100644 src/endpoints/quests/myswap/claimable.rs delete mode 100644 src/endpoints/quests/myswap/discord_fw_callback.rs delete mode 100644 src/endpoints/quests/myswap/mod.rs delete mode 100644 src/endpoints/quests/myswap/verify_added_liquidity.rs delete mode 100644 src/endpoints/quests/nimbora/check_balance.rs delete mode 100644 src/endpoints/quests/nimbora/claimable.rs delete mode 100644 src/endpoints/quests/nimbora/discord_fw_callback.rs delete mode 100644 src/endpoints/quests/nimbora/mod.rs delete mode 100644 src/endpoints/quests/nimbora/verify_twitter_rt.rs delete mode 100644 src/endpoints/quests/orbiter/claimable.rs delete mode 100644 src/endpoints/quests/orbiter/mod.rs delete mode 100644 src/endpoints/quests/orbiter/verify_has_bridged.rs delete mode 100644 src/endpoints/quests/orbiter/verify_has_root_domain.rs delete mode 100644 src/endpoints/quests/orbiter/verify_twitter_fw.rs delete mode 100644 src/endpoints/quests/orbiter/verify_twitter_fw_sq.rs delete mode 100644 src/endpoints/quests/orbiter/verify_twitter_rt.rs delete mode 100644 src/endpoints/quests/rango/mod.rs delete mode 100644 src/endpoints/quests/rango/quest1/check_trade.rs delete mode 100644 src/endpoints/quests/rango/quest1/claimable.rs delete mode 100644 src/endpoints/quests/rango/quest1/discord_fw_callback.rs delete mode 100644 src/endpoints/quests/rango/quest1/mod.rs delete mode 100644 src/endpoints/quests/rango/quest1/verify_twitter_fw.rs delete mode 100644 src/endpoints/quests/rango/quest2/check_trade.rs delete mode 100644 src/endpoints/quests/rango/quest2/claimable.rs delete mode 100644 src/endpoints/quests/rango/quest2/discord_fw_callback.rs delete mode 100644 src/endpoints/quests/rango/quest2/mod.rs delete mode 100644 src/endpoints/quests/rango/quest2/verify_twitter_fw.rs delete mode 100644 src/endpoints/quests/rango/quest2/verify_twitter_rw.rs delete mode 100644 src/endpoints/quests/rhino/check_bridge.rs delete mode 100644 src/endpoints/quests/rhino/claimable.rs delete mode 100644 src/endpoints/quests/rhino/mod.rs delete mode 100644 src/endpoints/quests/rhino/verify_twitter_fw.rs delete mode 100644 src/endpoints/quests/rhino/verify_twitter_rw.rs delete mode 100644 src/endpoints/quests/sithswap/mod.rs delete mode 100644 src/endpoints/quests/sithswap/quest1/claimable.rs delete mode 100644 src/endpoints/quests/sithswap/quest1/mod.rs delete mode 100644 src/endpoints/quests/sithswap/quest1/verify_added_liquidity.rs delete mode 100644 src/endpoints/quests/sithswap/quest1/verify_twitter_fw.rs delete mode 100644 src/endpoints/quests/sithswap/quest2/claimable.rs delete mode 100644 src/endpoints/quests/sithswap/quest2/mod.rs delete mode 100644 src/endpoints/quests/sithswap/quest2/verify_deposit.rs delete mode 100644 src/endpoints/quests/sithswap/quest2/verify_has_domain.rs delete mode 100644 src/endpoints/quests/sithswap/quest2/verify_twitter_fw.rs delete mode 100644 src/endpoints/quests/sithswap/quest2/verify_twitter_rw.rs delete mode 100644 src/endpoints/quests/strk_farm/check_balance.rs delete mode 100644 src/endpoints/quests/strk_farm/mod.rs delete mode 100644 src/endpoints/quests/tribe/claimable.rs delete mode 100644 src/endpoints/quests/tribe/mod.rs delete mode 100644 src/endpoints/quests/tribe/verify_has_domain.rs delete mode 100644 src/endpoints/quests/tribe/verify_has_root_domain.rs delete mode 100644 src/endpoints/quests/tribe/verify_three_years_expiry.rs delete mode 100644 src/endpoints/quests/zklend/claimable.rs delete mode 100644 src/endpoints/quests/zklend/mod.rs delete mode 100644 src/endpoints/quests/zklend/verify_borrow.rs delete mode 100644 src/endpoints/quests/zklend/verify_twitter_fw.rs diff --git a/src/endpoints/quests/avnu/claimable.rs b/src/endpoints/quests/avnu/claimable.rs deleted file mode 100644 index 430fb73a..00000000 --- a/src/endpoints/quests/avnu/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 3; -const TASK_IDS: &[u32] = &[12, 13, 54]; -const LAST_TASK: u32 = TASK_IDS[2]; -const NFT_LEVEL: u32 = 6; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/avnu/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/avnu/discord_fw_callback.rs b/src/endpoints/quests/avnu/discord_fw_callback.rs deleted file mode 100644 index b18f55b5..00000000 --- a/src/endpoints/quests/avnu/discord_fw_callback.rs +++ /dev/null @@ -1,147 +0,0 @@ -use std::sync::Arc; - -use crate::utils::CompletedTasksTrait; -use crate::{ - models::AppState, - utils::{get_error_redirect, success_redirect}, -}; -use axum::{ - extract::{Query, State}, - response::IntoResponse, -}; -use axum_auto_routes::route; -use mongodb::bson::doc; -use reqwest::header::AUTHORIZATION; -use serde::Deserialize; -use starknet::core::types::FieldElement; - -#[derive(Deserialize)] -pub struct TwitterOAuthCallbackQuery { - code: String, - state: FieldElement, -} - -#[derive(Deserialize)] -pub struct Guild { - id: String, - #[allow(dead_code)] - name: String, -} - -#[route(get, "/quests/avnu/discord_fw_callback")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let quest_id = 3; - let task_id = 13; - let guild_id = "942355887270559774"; - let authorization_code = &query.code; - let error_redirect_uri = format!( - "{}/quest/{}?task_id={}&res=false", - state.conf.variables.app_link, quest_id, task_id - ); - - // Exchange the authorization code for an access token - let params = [ - ("client_id", &state.conf.discord.oauth2_clientid), - ("client_secret", &state.conf.discord.oauth2_secret), - ("code", &authorization_code.to_string()), - ( - "redirect_uri", - &format!( - "{}/quests/avnu/discord_fw_callback", - state.conf.variables.api_link - ), - ), - ("grant_type", &"authorization_code".to_string()), - ]; - let access_token = match exchange_authorization_code(params).await { - Ok(token) => token, - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!("Failed to exchange authorization code: {}", e), - ); - } - }; - - // Get user guild information - let client = reqwest::Client::new(); - let response_result = client - .get("https://discord.com/api/users/@me/guilds") - .header(AUTHORIZATION, format!("Bearer {}", access_token)) - .send() - .await; - let response: Vec = match response_result { - Ok(response) => { - let json_result = response.json().await; - match json_result { - Ok(json) => json, - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!( - "Failed to get JSON response while fetching user info: {}", - e - ), - ); - } - } - } - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!("Failed to send request to get user info: {}", e), - ); - } - }; - - for guild in response { - if guild.id == guild_id { - match state.upsert_completed_task(query.state, task_id).await { - Ok(_) => { - let redirect_uri = format!( - "{}/quest/{}?task_id={}&res=true", - state.conf.variables.app_link, quest_id, task_id - ); - return success_redirect(redirect_uri); - } - Err(e) => return get_error_redirect(error_redirect_uri, format!("{}", e)), - } - } - } - - get_error_redirect( - error_redirect_uri, - "You're not part of AVNU's Discord server".to_string(), - ) -} - -async fn exchange_authorization_code( - params: [(&str, &String); 5], -) -> Result> { - let client = reqwest::Client::new(); - let res = client - .post("https://discord.com/api/oauth2/token") - .form(¶ms) - .send() - .await?; - let json: serde_json::Value = res.json().await?; - match json["access_token"].as_str() { - Some(s) => Ok(s.to_string()), - None => { - println!( - "Failed to get 'access_token' from JSON response : {:?}", - json - ); - Err(Box::new(std::io::Error::new( - std::io::ErrorKind::Other, - format!( - "Failed to get 'access_token' from JSON response : {:?}", - json - ), - ))) - } - } -} diff --git a/src/endpoints/quests/avnu/mod.rs b/src/endpoints/quests/avnu/mod.rs deleted file mode 100644 index 1c19b08c..00000000 --- a/src/endpoints/quests/avnu/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod claimable; -pub mod discord_fw_callback; -pub mod verify_swap; diff --git a/src/endpoints/quests/avnu/verify_swap.rs b/src/endpoints/quests/avnu/verify_swap.rs deleted file mode 100644 index ea2bfb41..00000000 --- a/src/endpoints/quests/avnu/verify_swap.rs +++ /dev/null @@ -1,60 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/avnu/verify_swap")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 12; - let hex_addr = format!("{:#x}", query.addr); - - // Fetch AVNU endpoint to get user score - let url = format!("https://starknet.api.avnu.fi/v1/quest/takers/{}", hex_addr); - let client = reqwest::Client::new(); - let response_result = client.get(url).send().await; - let response = match response_result { - Ok(response) => { - let json_result = response.json::().await; - match json_result { - Ok(json) => json, - Err(e) => { - return get_error(format!( - "Failed to get JSON response while fetching user info: {}", - e - )); - } - } - } - Err(e) => { - return get_error(format!("Failed to send request to fetch user info: {}", e)); - } - }; - let score = match response["volumeInUSD"].as_f64() { - Some(s) => s, - None => { - return get_error("Failed to get user info from response data".to_string()); - } - }; - - if score == 0.0 { - get_error("You have not made a swap on AVNU yet.".to_string()) - } else { - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } - } -} diff --git a/src/endpoints/quests/bountive/claimable.rs b/src/endpoints/quests/bountive/claimable.rs deleted file mode 100644 index d41db696..00000000 --- a/src/endpoints/quests/bountive/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 30; -const TASK_IDS: &[u32] = &[145, 146, 147, 148]; -const LAST_TASK: u32 = TASK_IDS[3]; -const NFT_LEVEL: u32 = 42; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/bountive/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/bountive/mod.rs b/src/endpoints/quests/bountive/mod.rs deleted file mode 100644 index 80e5c8bb..00000000 --- a/src/endpoints/quests/bountive/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod verify_twitter_fw; -pub mod verify_twitter_rt; -pub mod verify_deposit; -pub mod claimable; \ No newline at end of file diff --git a/src/endpoints/quests/bountive/verify_deposit.rs b/src/endpoints/quests/bountive/verify_deposit.rs deleted file mode 100644 index 8ace7ed2..00000000 --- a/src/endpoints/quests/bountive/verify_deposit.rs +++ /dev/null @@ -1,55 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; -use starknet::{ - core::types::{BlockId, BlockTag, FieldElement, FunctionCall}, - macros::selector, - providers::Provider, -}; - -#[route(get, "/quests/bountive/verify_deposit")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 147; - let addr = &query.addr; - let calldata = vec![*addr]; - - let call_result = state - .provider - .call( - FunctionCall { - contract_address: state.conf.quests.bountive.contract, - entry_point_selector: selector!("shares"), - calldata, - }, - BlockId::Tag(BlockTag::Latest), - ) - .await; - - match call_result { - Ok(result) => { - if result[0] == FieldElement::ZERO { - get_error("You didn't invest on bountive.".to_string()) - } else { - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } - } - } - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/bountive/verify_twitter_fw.rs b/src/endpoints/quests/bountive/verify_twitter_fw.rs deleted file mode 100644 index d087833a..00000000 --- a/src/endpoints/quests/bountive/verify_twitter_fw.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/bountive/verify_twitter_fw")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 146; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/bountive/verify_twitter_rt.rs b/src/endpoints/quests/bountive/verify_twitter_rt.rs deleted file mode 100644 index 039ee1d7..00000000 --- a/src/endpoints/quests/bountive/verify_twitter_rt.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/bountive/verify_twitter_rt")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 148; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/avnu/claimable.rs b/src/endpoints/quests/braavos/avnu/claimable.rs deleted file mode 100644 index f13ff13b..00000000 --- a/src/endpoints/quests/braavos/avnu/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 102; -const TASK_IDS: &[u32] = &[82, 83, 84, 85, 86]; -const LAST_TASK: u32 = TASK_IDS[4]; -const NFT_LEVEL: u32 = 28; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/braavos/avnu/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/braavos/avnu/mod.rs b/src/endpoints/quests/braavos/avnu/mod.rs deleted file mode 100644 index 74848145..00000000 --- a/src/endpoints/quests/braavos/avnu/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod claimable; -pub mod verify_has_domain; -pub mod verify_swap; -pub mod verify_twitter_fw_avnu; -pub mod verify_twitter_fw_braavos; -pub mod verify_twitter_rt; diff --git a/src/endpoints/quests/braavos/avnu/verify_has_domain.rs b/src/endpoints/quests/braavos/avnu/verify_has_domain.rs deleted file mode 100644 index 5aa2714a..00000000 --- a/src/endpoints/quests/braavos/avnu/verify_has_domain.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::{ - common::verify_has_root_or_braavos_domain::verify_has_root_or_braavos_domain, - models::{AppState, VerifyQuery}, -}; -use axum::{ - extract::{Query, State}, - response::IntoResponse, -}; -use axum_auto_routes::route; -use std::sync::Arc; - -#[route(get, "/quests/braavos/avnu/verify_has_domain")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - verify_has_root_or_braavos_domain(state, &query.addr, 82).await -} diff --git a/src/endpoints/quests/braavos/avnu/verify_swap.rs b/src/endpoints/quests/braavos/avnu/verify_swap.rs deleted file mode 100644 index 8fc088a1..00000000 --- a/src/endpoints/quests/braavos/avnu/verify_swap.rs +++ /dev/null @@ -1,60 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/avnu/verify_swap")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 85; - let hex_addr = format!("{:#x}", query.addr); - - // Fetch AVNU endpoint to get user score - let url = format!("https://starknet.api.avnu.fi/v1/quest/takers/{}", hex_addr); - let client = reqwest::Client::new(); - let response_result = client.get(url).send().await; - let response = match response_result { - Ok(response) => { - let json_result = response.json::().await; - match json_result { - Ok(json) => json, - Err(e) => { - return get_error(format!( - "Failed to get JSON response while fetching user info: {}", - e - )); - } - } - } - Err(e) => { - return get_error(format!("Failed to send request to fetch user info: {}", e)); - } - }; - let score = match response["volumeInUSD"].as_f64() { - Some(s) => s, - None => { - return get_error("Failed to get user info from response data".to_string()); - } - }; - - if score == 0.0 { - get_error("You have not made a swap on AVNU yet.".to_string()) - } else { - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } - } -} diff --git a/src/endpoints/quests/braavos/avnu/verify_twitter_fw_avnu.rs b/src/endpoints/quests/braavos/avnu/verify_twitter_fw_avnu.rs deleted file mode 100644 index 7911ffea..00000000 --- a/src/endpoints/quests/braavos/avnu/verify_twitter_fw_avnu.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/avnu/verify_twitter_fw_avnu")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 84; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/avnu/verify_twitter_fw_braavos.rs b/src/endpoints/quests/braavos/avnu/verify_twitter_fw_braavos.rs deleted file mode 100644 index b07b20ba..00000000 --- a/src/endpoints/quests/braavos/avnu/verify_twitter_fw_braavos.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/avnu/verify_twitter_fw_braavos")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 83; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/avnu/verify_twitter_rt.rs b/src/endpoints/quests/braavos/avnu/verify_twitter_rt.rs deleted file mode 100644 index 30102302..00000000 --- a/src/endpoints/quests/braavos/avnu/verify_twitter_rt.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/avnu/verify_twitter_rt")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 86; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/carbonable/claimable.rs b/src/endpoints/quests/braavos/carbonable/claimable.rs deleted file mode 100644 index 9bb41f3e..00000000 --- a/src/endpoints/quests/braavos/carbonable/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 107; -const TASK_IDS: &[u32] = &[127, 128, 129, 130, 131]; -const LAST_TASK: u32 = TASK_IDS[4]; -const NFT_LEVEL: u32 = 38; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/braavos/carbonable/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/braavos/carbonable/mod.rs b/src/endpoints/quests/braavos/carbonable/mod.rs deleted file mode 100644 index 79f2451a..00000000 --- a/src/endpoints/quests/braavos/carbonable/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod verify_has_domain; -pub mod verify_twitter_fw_braavos; -pub mod verify_twitter_fw_carbonable; -pub mod verify_twitter_rt; -pub mod verify_deposit; -pub mod claimable; \ No newline at end of file diff --git a/src/endpoints/quests/braavos/carbonable/verify_deposit.rs b/src/endpoints/quests/braavos/carbonable/verify_deposit.rs deleted file mode 100644 index 6696204e..00000000 --- a/src/endpoints/quests/braavos/carbonable/verify_deposit.rs +++ /dev/null @@ -1,55 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; -use starknet::{ - core::types::{BlockId, BlockTag, FieldElement, FunctionCall}, - macros::selector, - providers::Provider, -}; - -#[route(get, "/quests/braavos/carbonable/verify_deposit")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 130; - let addr = &query.addr; - let calldata = vec![*addr]; - - let call_result = state - .provider - .call( - FunctionCall { - contract_address: state.conf.quests.carbonable.contract, - entry_point_selector: selector!("balanceOf"), - calldata, - }, - BlockId::Tag(BlockTag::Latest), - ) - .await; - - match call_result { - Ok(result) => { - if result[0] == FieldElement::ZERO { - get_error("You didn't invest on carbonable.".to_string()) - } else { - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } - } - } - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/carbonable/verify_has_domain.rs b/src/endpoints/quests/braavos/carbonable/verify_has_domain.rs deleted file mode 100644 index 11d3e6f9..00000000 --- a/src/endpoints/quests/braavos/carbonable/verify_has_domain.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::{ - common::verify_has_root_or_braavos_domain::verify_has_root_or_braavos_domain, - models::{AppState, VerifyQuery}, -}; -use axum::{ - extract::{Query, State}, - response::IntoResponse, -}; -use axum_auto_routes::route; -use std::sync::Arc; - -#[route(get, "/quests/braavos/carbonable/verify_has_domain")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - verify_has_root_or_braavos_domain(state, &query.addr, 127).await -} diff --git a/src/endpoints/quests/braavos/carbonable/verify_twitter_fw_braavos.rs b/src/endpoints/quests/braavos/carbonable/verify_twitter_fw_braavos.rs deleted file mode 100644 index 9a5e6c55..00000000 --- a/src/endpoints/quests/braavos/carbonable/verify_twitter_fw_braavos.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/carbonable/verify_twitter_fw_braavos")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 128; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/carbonable/verify_twitter_fw_carbonable.rs b/src/endpoints/quests/braavos/carbonable/verify_twitter_fw_carbonable.rs deleted file mode 100644 index 35a9bc19..00000000 --- a/src/endpoints/quests/braavos/carbonable/verify_twitter_fw_carbonable.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/carbonable/verify_twitter_fw_carbonable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 129; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/carbonable/verify_twitter_rt.rs b/src/endpoints/quests/braavos/carbonable/verify_twitter_rt.rs deleted file mode 100644 index a0f32fae..00000000 --- a/src/endpoints/quests/braavos/carbonable/verify_twitter_rt.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/carbonable/verify_twitter_rt")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 131; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/mod.rs b/src/endpoints/quests/braavos/mod.rs deleted file mode 100644 index 09d9b5dc..00000000 --- a/src/endpoints/quests/braavos/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -pub mod avnu; -pub mod myswap; -pub mod starknetid; -pub mod wallet; -pub mod pyramid; -pub mod zklend; -pub mod realms; -pub mod carbonable; diff --git a/src/endpoints/quests/braavos/myswap/claimable.rs b/src/endpoints/quests/braavos/myswap/claimable.rs deleted file mode 100644 index e9226d82..00000000 --- a/src/endpoints/quests/braavos/myswap/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 101; -const TASK_IDS: &[u32] = &[75, 76, 77, 78]; -const LAST_TASK: u32 = TASK_IDS[3]; -const NFT_LEVEL: u32 = 26; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/braavos/myswap/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/braavos/myswap/mod.rs b/src/endpoints/quests/braavos/myswap/mod.rs deleted file mode 100644 index b775ab28..00000000 --- a/src/endpoints/quests/braavos/myswap/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod claimable; -pub mod verify_added_liquidity; -pub mod verify_has_domain; -pub mod verify_twitter_fw_braavos; -pub mod verify_twitter_fw_myswap; diff --git a/src/endpoints/quests/braavos/myswap/verify_added_liquidity.rs b/src/endpoints/quests/braavos/myswap/verify_added_liquidity.rs deleted file mode 100644 index c49fff8b..00000000 --- a/src/endpoints/quests/braavos/myswap/verify_added_liquidity.rs +++ /dev/null @@ -1,55 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; -use starknet::{ - core::types::{BlockId, BlockTag, FieldElement, FunctionCall}, - macros::selector, - providers::Provider, -}; - -#[route(get, "/quests/braavos/myswap/verify_added_liquidity")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 76; - let addr = &query.addr; - - // check if user has provider liquidity - let call_result = state - .provider - .call( - FunctionCall { - contract_address: state.conf.quests.myswap.contract, - entry_point_selector: selector!("balance_of"), - calldata: vec![*addr], - }, - BlockId::Tag(BlockTag::Latest), - ) - .await; - - match call_result { - Ok(result) => { - if result[0] == FieldElement::ZERO && result[1] == FieldElement::ZERO { - get_error("You haven't provided any liquidity on MySwap.".to_string()) - } else { - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } - } - } - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/myswap/verify_has_domain.rs b/src/endpoints/quests/braavos/myswap/verify_has_domain.rs deleted file mode 100644 index 821bf6ed..00000000 --- a/src/endpoints/quests/braavos/myswap/verify_has_domain.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::{ - common::verify_has_root_or_braavos_domain::verify_has_root_or_braavos_domain, - models::{AppState, VerifyQuery}, -}; -use axum::{ - extract::{Query, State}, - response::IntoResponse, -}; -use axum_auto_routes::route; -use std::sync::Arc; - -#[route(get, "/quests/braavos/myswap/verify_has_domain")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - verify_has_root_or_braavos_domain(state, &query.addr, 75).await -} diff --git a/src/endpoints/quests/braavos/myswap/verify_twitter_fw_braavos.rs b/src/endpoints/quests/braavos/myswap/verify_twitter_fw_braavos.rs deleted file mode 100644 index bdbfd66a..00000000 --- a/src/endpoints/quests/braavos/myswap/verify_twitter_fw_braavos.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/myswap/verify_twitter_fw_braavos")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 78; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/myswap/verify_twitter_fw_myswap.rs b/src/endpoints/quests/braavos/myswap/verify_twitter_fw_myswap.rs deleted file mode 100644 index c8127d19..00000000 --- a/src/endpoints/quests/braavos/myswap/verify_twitter_fw_myswap.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/myswap/verify_twitter_fw_myswap")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 77; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/pyramid/claimable.rs b/src/endpoints/quests/braavos/pyramid/claimable.rs deleted file mode 100644 index 58798182..00000000 --- a/src/endpoints/quests/braavos/pyramid/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 104; -const TASK_IDS: &[u32] = &[104, 105, 106, 107, 108]; -const LAST_TASK: u32 = TASK_IDS[4]; -const NFT_LEVEL: u32 = 32; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/braavos/pyramid/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/braavos/pyramid/mod.rs b/src/endpoints/quests/braavos/pyramid/mod.rs deleted file mode 100644 index 01850705..00000000 --- a/src/endpoints/quests/braavos/pyramid/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod verify_has_domain; -pub mod verify_twitter_fw_braavos; -pub mod verify_twitter_fw_pyramid; -pub mod verify_twitter_rt; -pub mod verify_buy_or_list; -pub mod claimable; \ No newline at end of file diff --git a/src/endpoints/quests/braavos/pyramid/verify_buy_or_list.rs b/src/endpoints/quests/braavos/pyramid/verify_buy_or_list.rs deleted file mode 100644 index 5f031203..00000000 --- a/src/endpoints/quests/braavos/pyramid/verify_buy_or_list.rs +++ /dev/null @@ -1,43 +0,0 @@ -use std::sync::Arc; - -use crate::models::VerifyQuery; -use crate::utils::{fetch_json_from_url, to_hex, CompletedTasksTrait}; -use crate::{models::AppState, utils::get_error}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/pyramid/verify_buy_or_list")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 107; - - // make get request to pyramid api for verification - let url = format!( - "{}/{}/isEligibleForQuest", - state.conf.pyramid.api_endpoint, - to_hex(query.addr) - ); - - match fetch_json_from_url(url).await { - Ok(response) => { - let has_bought_or_listed_nft = response.get("result").unwrap().as_bool().unwrap(); - return if has_bought_or_listed_nft { - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } - } else { - get_error("NFT not bought/listed".to_string()) - }; - } - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/pyramid/verify_has_domain.rs b/src/endpoints/quests/braavos/pyramid/verify_has_domain.rs deleted file mode 100644 index 3beef652..00000000 --- a/src/endpoints/quests/braavos/pyramid/verify_has_domain.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::{ - common::verify_has_root_or_braavos_domain::verify_has_root_or_braavos_domain, - models::{AppState, VerifyQuery}, -}; -use axum::{ - extract::{Query, State}, - response::IntoResponse, -}; -use axum_auto_routes::route; -use std::sync::Arc; - -#[route(get, "/quests/braavos/pyramid/verify_has_domain")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - verify_has_root_or_braavos_domain(state, &query.addr, 104).await -} diff --git a/src/endpoints/quests/braavos/pyramid/verify_twitter_fw_braavos.rs b/src/endpoints/quests/braavos/pyramid/verify_twitter_fw_braavos.rs deleted file mode 100644 index ea2e4495..00000000 --- a/src/endpoints/quests/braavos/pyramid/verify_twitter_fw_braavos.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/pyramid/verify_twitter_fw_braavos")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 105; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/pyramid/verify_twitter_fw_pyramid.rs b/src/endpoints/quests/braavos/pyramid/verify_twitter_fw_pyramid.rs deleted file mode 100644 index e2cfb522..00000000 --- a/src/endpoints/quests/braavos/pyramid/verify_twitter_fw_pyramid.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/pyramid/verify_twitter_fw_pyramid")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 106; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/pyramid/verify_twitter_rt.rs b/src/endpoints/quests/braavos/pyramid/verify_twitter_rt.rs deleted file mode 100644 index 0e7c3dfe..00000000 --- a/src/endpoints/quests/braavos/pyramid/verify_twitter_rt.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/pyramid/verify_twitter_rt")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 108; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/realms/claimable.rs b/src/endpoints/quests/braavos/realms/claimable.rs deleted file mode 100644 index 5f02ebec..00000000 --- a/src/endpoints/quests/braavos/realms/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 106; -const TASK_IDS: &[u32] = &[118, 119, 120, 121, 122]; -const LAST_TASK: u32 = TASK_IDS[4]; -const NFT_LEVEL: u32 = 36; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/braavos/realms/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/braavos/realms/mod.rs b/src/endpoints/quests/braavos/realms/mod.rs deleted file mode 100644 index f22aeccc..00000000 --- a/src/endpoints/quests/braavos/realms/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod claimable; -pub mod verify_has_domain; -pub mod verify_has_played; -pub mod verify_twitter_fw_realms; -pub mod verify_twitter_fw_braavos; -pub mod verify_twitter_rt; diff --git a/src/endpoints/quests/braavos/realms/verify_has_domain.rs b/src/endpoints/quests/braavos/realms/verify_has_domain.rs deleted file mode 100644 index 98f86abb..00000000 --- a/src/endpoints/quests/braavos/realms/verify_has_domain.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::{ - common::verify_has_root_or_braavos_domain::verify_has_root_or_braavos_domain, - models::{AppState, VerifyQuery}, -}; -use axum::{ - extract::{Query, State}, - response::IntoResponse, -}; -use axum_auto_routes::route; -use std::sync::Arc; - -#[route(get, "/quests/braavos/realms/verify_has_domain")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - verify_has_root_or_braavos_domain(state, &query.addr, 118).await -} diff --git a/src/endpoints/quests/braavos/realms/verify_has_played.rs b/src/endpoints/quests/braavos/realms/verify_has_played.rs deleted file mode 100644 index 13bbeeb5..00000000 --- a/src/endpoints/quests/braavos/realms/verify_has_played.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/realms/verify_has_played")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 121; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/realms/verify_twitter_fw_braavos.rs b/src/endpoints/quests/braavos/realms/verify_twitter_fw_braavos.rs deleted file mode 100644 index c05ead00..00000000 --- a/src/endpoints/quests/braavos/realms/verify_twitter_fw_braavos.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/realms/verify_twitter_fw_braavos")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 119; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/realms/verify_twitter_fw_realms.rs b/src/endpoints/quests/braavos/realms/verify_twitter_fw_realms.rs deleted file mode 100644 index 413750c5..00000000 --- a/src/endpoints/quests/braavos/realms/verify_twitter_fw_realms.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/realms/verify_twitter_fw_realms")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 120; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/realms/verify_twitter_rt.rs b/src/endpoints/quests/braavos/realms/verify_twitter_rt.rs deleted file mode 100644 index 7bd2026a..00000000 --- a/src/endpoints/quests/braavos/realms/verify_twitter_rt.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/realms/verify_twitter_rt")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 122; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/starknetid/claimable.rs b/src/endpoints/quests/braavos/starknetid/claimable.rs deleted file mode 100644 index cb7bde15..00000000 --- a/src/endpoints/quests/braavos/starknetid/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 100; -const TASK_IDS: &[u32] = &[46, 47, 48, 49, 50]; -const LAST_TASK: u32 = TASK_IDS[4]; -const NFT_LEVEL: u32 = 18; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/braavos/starknetid/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/braavos/starknetid/mod.rs b/src/endpoints/quests/braavos/starknetid/mod.rs deleted file mode 100644 index ddc1caeb..00000000 --- a/src/endpoints/quests/braavos/starknetid/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod claimable; -pub mod verify_has_domain; -pub mod verify_has_mission; -pub mod verify_twitter_fw_braavos; -pub mod verify_twitter_fw_sid; -pub mod verify_twitter_fw_sq; diff --git a/src/endpoints/quests/braavos/starknetid/verify_has_domain.rs b/src/endpoints/quests/braavos/starknetid/verify_has_domain.rs deleted file mode 100644 index 957b5acf..00000000 --- a/src/endpoints/quests/braavos/starknetid/verify_has_domain.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::{ - common::verify_has_root_or_braavos_domain::verify_has_root_or_braavos_domain, - models::{AppState, VerifyQuery}, -}; -use axum::{ - extract::{Query, State}, - response::IntoResponse, -}; -use axum_auto_routes::route; -use std::sync::Arc; - -#[route(get, "/quests/braavos/starknetid/verify_has_domain")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - verify_has_root_or_braavos_domain(state, &query.addr, 46).await -} diff --git a/src/endpoints/quests/braavos/starknetid/verify_has_mission.rs b/src/endpoints/quests/braavos/starknetid/verify_has_mission.rs deleted file mode 100644 index 64b96921..00000000 --- a/src/endpoints/quests/braavos/starknetid/verify_has_mission.rs +++ /dev/null @@ -1,225 +0,0 @@ -use crate::{ - models::AppState, - utils::{get_error, get_error_redirect, success_redirect, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - response::IntoResponse, -}; -use axum_auto_routes::route; -use reqwest::header::{self, AUTHORIZATION}; -use serde::Deserialize; -use starknet::core::types::FieldElement; -use std::sync::Arc; - -#[derive(Deserialize)] -pub struct DiscordOAuthCallbackQuery { - code: String, - state: FieldElement, -} - -#[derive(Deserialize, Debug)] -pub struct DiscordUser { - id: String, - #[allow(dead_code)] - username: String, -} - -#[route(get, "/quests/braavos/starknetid/verify_has_mission")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let quest_id = 100; - let task_id = 50; - let mission_id = "2e1a9301-14da-4430-9ae0-b617e1c379f4"; - let authorization_code = &query.code; - let error_redirect_uri = format!( - "{}/quest/{}?task_id={}&res=false", - state.conf.variables.app_link, quest_id, task_id - ); - - // Exchange the authorization code for an access token - let params = [ - ("client_id", &state.conf.discord.oauth2_clientid), - ("client_secret", &state.conf.discord.oauth2_secret), - ("code", &authorization_code.to_string()), - ( - "redirect_uri", - &format!( - "{}/quests/braavos/starknetid/verify_has_mission", - state.conf.variables.api_link - ), - ), - ("grant_type", &"authorization_code".to_string()), - ]; - let access_token = match exchange_authorization_code(params).await { - Ok(token) => token, - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!("Failed to exchange authorization code: {}", e), - ); - } - }; - - // Get user information - let client = reqwest::Client::new(); - let response_result = client - .get("https://discord.com/api/users/@me") - .header(AUTHORIZATION, format!("Bearer {}", access_token)) - .send() - .await; - let response: DiscordUser = match response_result { - Ok(response) => { - let json_result = response.json().await; - match json_result { - Ok(json) => json, - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!( - "Failed to get JSON response while fetching user info: {}", - e - ), - ); - } - } - } - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!("Failed to send request to get user info: {}", e), - ); - } - }; - - // Get Zealy profile from Discord id - let discord_id = response.id; - let url = format!( - "https://api.zealy.io/communities/braavos/users?discordId={}", - discord_id - ); - let client = reqwest::Client::new(); - let response_result = client - .get(url) - .header( - header::HeaderName::from_static("x-api-key"), - header::HeaderValue::from_str(&state.conf.quests.braavos.api_key_user).unwrap(), - ) - .send() - .await; - let zealy_response = match response_result { - Ok(response) => { - let json_result = response.json::().await; - match json_result { - Ok(json) => json, - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!("Failed to get User info from Zealy's response: {:?}", e), - ); - } - } - } - Err(e) => { - return get_error(format!("Failed to send request to fetch user info: {}", e)); - } - }; - if let Some(id) = zealy_response.get("id") { - let zealy_id = id.as_str().unwrap(); - - // Get user completed mission from Zealy API - let url = format!( - "https://api.zealy.io/communities/braavos/claimed-quests?user_id={}&quest_id={}", - zealy_id, mission_id - ); - let client = reqwest::Client::new(); - let mission_response = client - .get(url) - .header( - header::HeaderName::from_static("x-api-key"), - header::HeaderValue::from_str(&state.conf.quests.braavos.api_key_claimed_mission) - .unwrap(), - ) - .send() - .await; - let missions = match mission_response { - Ok(response) => { - let json_result = response.json::().await; - match json_result { - Ok(json) => json, - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!("Failed to get user's mission from Zealy: {:?}", e), - ); - } - } - } - Err(e) => { - return get_error(format!( - "Failed to send request to fetch user missions: {}", - e - )); - } - }; - if let Some(mission_array) = missions.get("data").and_then(|v| v.as_array()) { - if !mission_array.is_empty() { - match state.upsert_completed_task(query.state, task_id).await { - Ok(_) => { - let redirect_uri = format!( - "{}/quest/{}?task_id={}&res=true", - state.conf.variables.app_link, quest_id, task_id - ); - return success_redirect(redirect_uri); - } - Err(e) => return get_error_redirect(error_redirect_uri, format!("{}", e)), - } - } else { - return get_error_redirect( - error_redirect_uri, - "You have not fulfilled this mission on Zealy".to_string(), - ); - } - } else { - return get_error_redirect( - error_redirect_uri, - format!("Failed to get Zealy ID from response: {:?}", zealy_response), - ); - } - } else { - return get_error_redirect( - error_redirect_uri, - format!("Failed to get Zealy ID from response: {:?}", zealy_response), - ); - }; -} - -async fn exchange_authorization_code( - params: [(&str, &String); 5], -) -> Result> { - let client = reqwest::Client::new(); - let res = client - .post("https://discord.com/api/oauth2/token") - .form(¶ms) - .send() - .await?; - let json: serde_json::Value = res.json().await?; - match json["access_token"].as_str() { - Some(s) => Ok(s.to_string()), - None => { - println!( - "Failed to get 'access_token' from JSON response : {:?}", - json - ); - Err(Box::new(std::io::Error::new( - std::io::ErrorKind::Other, - format!( - "Failed to get 'access_token' from JSON response : {:?}", - json - ), - ))) - } - } -} diff --git a/src/endpoints/quests/braavos/starknetid/verify_twitter_fw_braavos.rs b/src/endpoints/quests/braavos/starknetid/verify_twitter_fw_braavos.rs deleted file mode 100644 index 139f874a..00000000 --- a/src/endpoints/quests/braavos/starknetid/verify_twitter_fw_braavos.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/starknetid/verify_twitter_fw_braavos")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 47; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/starknetid/verify_twitter_fw_sid.rs b/src/endpoints/quests/braavos/starknetid/verify_twitter_fw_sid.rs deleted file mode 100644 index 843423d5..00000000 --- a/src/endpoints/quests/braavos/starknetid/verify_twitter_fw_sid.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/starknetid/verify_twitter_fw_sid")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 49; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/starknetid/verify_twitter_fw_sq.rs b/src/endpoints/quests/braavos/starknetid/verify_twitter_fw_sq.rs deleted file mode 100644 index 69c8883d..00000000 --- a/src/endpoints/quests/braavos/starknetid/verify_twitter_fw_sq.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/starknetid/verify_twitter_fw_sq")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 48; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/wallet/claimable.rs b/src/endpoints/quests/braavos/wallet/claimable.rs deleted file mode 100644 index 172f3511..00000000 --- a/src/endpoints/quests/braavos/wallet/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 103; -const TASK_IDS: &[u32] = &[96, 97, 98, 99]; -const LAST_TASK: u32 = TASK_IDS[3]; -const NFT_LEVEL: u32 = 29; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/braavos/wallet/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/braavos/wallet/mod.rs b/src/endpoints/quests/braavos/wallet/mod.rs deleted file mode 100644 index f8bd3dcc..00000000 --- a/src/endpoints/quests/braavos/wallet/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod claimable; -pub mod verify_has_domain; -pub mod verify_twitter_fw_braavos; -pub mod verify_twitter_rt; diff --git a/src/endpoints/quests/braavos/wallet/verify_has_domain.rs b/src/endpoints/quests/braavos/wallet/verify_has_domain.rs deleted file mode 100644 index 43a2910e..00000000 --- a/src/endpoints/quests/braavos/wallet/verify_has_domain.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::{ - common::verify_has_root_or_braavos_domain::verify_has_root_or_braavos_domain, - models::{AppState, VerifyQuery}, -}; -use axum::{ - extract::{Query, State}, - response::IntoResponse, -}; -use axum_auto_routes::route; -use std::sync::Arc; - -#[route(get, "/quests/braavos/wallet/verify_has_domain")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - verify_has_root_or_braavos_domain(state, &query.addr, 96).await -} diff --git a/src/endpoints/quests/braavos/wallet/verify_twitter_fw_braavos.rs b/src/endpoints/quests/braavos/wallet/verify_twitter_fw_braavos.rs deleted file mode 100644 index 03c33b86..00000000 --- a/src/endpoints/quests/braavos/wallet/verify_twitter_fw_braavos.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/wallet/verify_twitter_fw_braavos")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 97; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/wallet/verify_twitter_rt.rs b/src/endpoints/quests/braavos/wallet/verify_twitter_rt.rs deleted file mode 100644 index 3c539ff6..00000000 --- a/src/endpoints/quests/braavos/wallet/verify_twitter_rt.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/wallet/verify_twitter_rt")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 99; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/zklend/claimable.rs b/src/endpoints/quests/braavos/zklend/claimable.rs deleted file mode 100644 index e4c3ec3a..00000000 --- a/src/endpoints/quests/braavos/zklend/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 105; -const TASK_IDS: &[u32] = &[109, 110, 111, 112, 113]; -const LAST_TASK: u32 = TASK_IDS[4]; -const NFT_LEVEL: u32 = 33; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/braavos/zklend/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/braavos/zklend/mod.rs b/src/endpoints/quests/braavos/zklend/mod.rs deleted file mode 100644 index dbfec14d..00000000 --- a/src/endpoints/quests/braavos/zklend/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod verify_has_domain; -pub mod verify_twitter_fw_braavos; -pub mod verify_twitter_fw_zklend; -pub mod verify_twitter_rt; -pub mod verify_added_liquidity; -pub mod claimable; \ No newline at end of file diff --git a/src/endpoints/quests/braavos/zklend/verify_added_liquidity.rs b/src/endpoints/quests/braavos/zklend/verify_added_liquidity.rs deleted file mode 100644 index 0eca71b6..00000000 --- a/src/endpoints/quests/braavos/zklend/verify_added_liquidity.rs +++ /dev/null @@ -1,57 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; -use starknet::{ - core::types::{BlockId, BlockTag, FieldElement, FunctionCall}, - macros::selector, - providers::Provider, -}; - -#[route(get, "/quests/braavos/zklend/verify_added_liquidity")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 112; - let addr = &query.addr; - let mut calldata = vec![addr.clone(), state.conf.quests.zklend.pairs.len().into()]; - calldata.append(&mut state.conf.quests.zklend.pairs.clone()); - - // get starkname from address - let call_result = state - .provider - .call( - FunctionCall { - contract_address: state.conf.quests.zklend.utils_contract, - entry_point_selector: selector!("sum_balances"), - calldata, - }, - BlockId::Tag(BlockTag::Latest), - ) - .await; - - match call_result { - Ok(result) => { - if result[0] == FieldElement::ZERO { - get_error("You didn't deposit liquidity on zkLend.".to_string()) - } else { - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } - } - } - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/zklend/verify_has_domain.rs b/src/endpoints/quests/braavos/zklend/verify_has_domain.rs deleted file mode 100644 index 1f9e73b8..00000000 --- a/src/endpoints/quests/braavos/zklend/verify_has_domain.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::{ - common::verify_has_root_or_braavos_domain::verify_has_root_or_braavos_domain, - models::{AppState, VerifyQuery}, -}; -use axum::{ - extract::{Query, State}, - response::IntoResponse, -}; -use axum_auto_routes::route; -use std::sync::Arc; - -#[route(get, "/quests/braavos/zklend/verify_has_domain")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - verify_has_root_or_braavos_domain(state, &query.addr, 109).await -} diff --git a/src/endpoints/quests/braavos/zklend/verify_twitter_fw_braavos.rs b/src/endpoints/quests/braavos/zklend/verify_twitter_fw_braavos.rs deleted file mode 100644 index dc62005c..00000000 --- a/src/endpoints/quests/braavos/zklend/verify_twitter_fw_braavos.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/zklend/verify_twitter_fw_braavos")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 110; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/zklend/verify_twitter_fw_zklend.rs b/src/endpoints/quests/braavos/zklend/verify_twitter_fw_zklend.rs deleted file mode 100644 index fbcbe8b6..00000000 --- a/src/endpoints/quests/braavos/zklend/verify_twitter_fw_zklend.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/zklend/verify_twitter_fw_zklend")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 111; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/braavos/zklend/verify_twitter_rt.rs b/src/endpoints/quests/braavos/zklend/verify_twitter_rt.rs deleted file mode 100644 index df5fa8ef..00000000 --- a/src/endpoints/quests/braavos/zklend/verify_twitter_rt.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/braavos/zklend/verify_twitter_rt")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 113; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/carmine/claimable.rs b/src/endpoints/quests/carmine/claimable.rs deleted file mode 100644 index 016f2418..00000000 --- a/src/endpoints/quests/carmine/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 10; -const TASK_IDS: &[u32] = &[40, 41]; -const LAST_TASK: u32 = TASK_IDS[1]; -const NFT_LEVEL: u32 = 15; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/carmine/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/carmine/mod.rs b/src/endpoints/quests/carmine/mod.rs deleted file mode 100644 index e0c6c8fb..00000000 --- a/src/endpoints/quests/carmine/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod claimable; diff --git a/src/endpoints/quests/element/briq/claimable.rs b/src/endpoints/quests/element/briq/claimable.rs deleted file mode 100644 index c6942189..00000000 --- a/src/endpoints/quests/element/briq/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 17; -const TASK_IDS: &[u32] = &[67, 68, 69]; -const LAST_TASK: u32 = TASK_IDS[2]; -const NFT_LEVEL: u32 = 23; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/element/briq/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/element/briq/mod.rs b/src/endpoints/quests/element/briq/mod.rs deleted file mode 100644 index 1f33954a..00000000 --- a/src/endpoints/quests/element/briq/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod claimable; -pub mod verify_own_briq; -pub mod verify_twitter_fw; diff --git a/src/endpoints/quests/element/briq/verify_own_briq.rs b/src/endpoints/quests/element/briq/verify_own_briq.rs deleted file mode 100644 index 2d1b648c..00000000 --- a/src/endpoints/quests/element/briq/verify_own_briq.rs +++ /dev/null @@ -1,79 +0,0 @@ -use std::sync::Arc; - -use crate::utils::fetch_json_from_url; -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, to_hex, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; -use starknet::core::types::FieldElement; - -#[route(get, "/quests/element/briq/verify_own_briq")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 68; - if query.addr == FieldElement::ZERO { - return get_error("Please connect your wallet first".to_string()); - } - - let url = format!( - "https://api.briq.construction/v1/user/data/starknet-mainnet-dojo/{}", - to_hex(query.addr) - ); - match fetch_json_from_url(url).await { - Ok(response) => { - if let Some(sets) = response.get("sets") { - match sets { - serde_json::Value::Array(sets_array) => { - for set in sets_array.iter() { - if let serde_json::Value::String(set_str) = set { - let url = format!( - "https://api.briq.construction/v1/metadata/starknet-mainnet-dojo/{}", - set_str - ); - match fetch_json_from_url(url).await { - Ok(metadata_response) => { - if let Some(_properties) = - metadata_response.get("properties") - { - match state - .upsert_completed_task(query.addr, task_id) - .await - { - Ok(_) => { - return ( - StatusCode::OK, - Json(json!({"res": true})), - ) - .into_response(); - } - Err(e) => { - return get_error(format!("{}", e)); - } - } - } - } - Err(e) => return get_error(e), - } - } - } - } - _ => { - return get_error("No Briq sets founds".to_string()); - } - } - } - get_error("No Briq sets founds".to_string()) - } - Err(e) => get_error(e), - } -} diff --git a/src/endpoints/quests/element/briq/verify_twitter_fw.rs b/src/endpoints/quests/element/briq/verify_twitter_fw.rs deleted file mode 100644 index 09c40e23..00000000 --- a/src/endpoints/quests/element/briq/verify_twitter_fw.rs +++ /dev/null @@ -1,30 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; -use starknet::core::types::FieldElement; - -#[route(get, "/quests/element/briq/verify_twitter_fw")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 69; - if query.addr == FieldElement::ZERO { - return get_error("Please connect your wallet first".to_string()); - } - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/element/element/claimable.rs b/src/endpoints/quests/element/element/claimable.rs deleted file mode 100644 index 3f5803e8..00000000 --- a/src/endpoints/quests/element/element/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 16; -const TASK_IDS: &[u32] = &[64, 65, 66]; -const LAST_TASK: u32 = TASK_IDS[2]; -const NFT_LEVEL: u32 = 22; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/element/element/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/element/element/mod.rs b/src/endpoints/quests/element/element/mod.rs deleted file mode 100644 index 204183a9..00000000 --- a/src/endpoints/quests/element/element/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod claimable; -pub mod verify_is_eligible; -pub mod verify_twitter_fw; diff --git a/src/endpoints/quests/element/element/verify_is_eligible.rs b/src/endpoints/quests/element/element/verify_is_eligible.rs deleted file mode 100644 index 3d7e3888..00000000 --- a/src/endpoints/quests/element/element/verify_is_eligible.rs +++ /dev/null @@ -1,71 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, to_hex, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde::Deserialize; -use serde_json::json; -use starknet::core::types::FieldElement; - -#[derive(Debug, Deserialize)] -pub struct ElementResponse { - #[allow(dead_code)] - code: u32, - data: bool, -} - -#[route(get, "/quests/element/element/verify_is_eligible")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 65; - if query.addr == FieldElement::ZERO { - return get_error("Please connect your wallet first".to_string()); - } - - let url = format!( - "https://api.element.market/openapi/v1/qualify/check?address={}&taskId=100120231026231111", - to_hex(query.addr) - ); - let client = reqwest::Client::new(); - match client - .get(&url) - .header("accept", "application/json") - .header("x-api-key", state.conf.quests.element.api_key.clone()) - .send() - .await - { - Ok(response) => match response.text().await { - Ok(text) => match serde_json::from_str::(&text) { - Ok(res) => { - if res.data { - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } - } else { - get_error("You have not interacted with Element.".to_string()) - } - } - Err(e) => get_error(format!( - "Failed to deserialize result from Element API: {} for response: {}", - e, text - )), - }, - Err(e) => get_error(format!( - "Failed to get JSON response while fetching Element API: {}", - e - )), - }, - Err(e) => get_error(format!("Failed to fetch Element API: {}", e)), - } -} diff --git a/src/endpoints/quests/element/element/verify_twitter_fw.rs b/src/endpoints/quests/element/element/verify_twitter_fw.rs deleted file mode 100644 index 3bea9954..00000000 --- a/src/endpoints/quests/element/element/verify_twitter_fw.rs +++ /dev/null @@ -1,30 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; -use starknet::core::types::FieldElement; - -#[route(get, "/quests/element/element/verify_twitter_fw")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 66; - if query.addr == FieldElement::ZERO { - return get_error("Please connect your wallet first".to_string()); - } - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/element/layerswap/claimable.rs b/src/endpoints/quests/element/layerswap/claimable.rs deleted file mode 100644 index 35a1995a..00000000 --- a/src/endpoints/quests/element/layerswap/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 18; -const TASK_IDS: &[u32] = &[70, 71, 72]; -const LAST_TASK: u32 = TASK_IDS[2]; -const NFT_LEVEL: u32 = 24; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/element/layerswap/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/element/layerswap/mod.rs b/src/endpoints/quests/element/layerswap/mod.rs deleted file mode 100644 index 90105076..00000000 --- a/src/endpoints/quests/element/layerswap/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod claimable; -pub mod verify_has_bridged; -pub mod verify_twitter_fw; -pub mod verify_twitter_rt; diff --git a/src/endpoints/quests/element/layerswap/verify_has_bridged.rs b/src/endpoints/quests/element/layerswap/verify_has_bridged.rs deleted file mode 100644 index e4b49b08..00000000 --- a/src/endpoints/quests/element/layerswap/verify_has_bridged.rs +++ /dev/null @@ -1,79 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, to_hex, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde::Deserialize; -use serde_json::json; - -#[derive(Debug, Deserialize)] -struct LayerswapResponse { - data: Option>, - error: Option, -} - -#[derive(Debug, Deserialize)] -struct DataEntry { - status: String, -} - -#[derive(Debug, Deserialize)] -struct LayerswapError { - message: String, -} - -#[route(get, "/quests/element/layerswap/verify_has_bridged")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 70; - let url = format!( - "https://bridge-api.layerswap.io/api/explorer/{}", - to_hex(query.addr) - ); - - let client = reqwest::Client::new(); - let response_result = client.get(url).send().await; - match response_result { - Ok(response) => match response.json::().await { - Ok(res) => { - if let Some(err) = &res.error { - return get_error(format!("Received error from Layerswap: {}", err.message)); - } - - // Check if there is data and if any entry has "completed" status & was made in the last 3 months - if res - .data - .as_ref() - .unwrap_or(&vec![]) - .iter() - .any(|entry| entry.status == "completed") - { - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } - } else { - get_error( - "You haven't bridge any ETH or USDC to Starknet using Layerswap." - .to_string(), - ) - } - } - Err(e) => get_error(format!( - "Failed to get JSON response while fetching Layerswap data: {}", - e - )), - }, - Err(e) => get_error(format!("Failed to fetch Layerswap api: {}", e)), - } -} diff --git a/src/endpoints/quests/element/layerswap/verify_twitter_fw.rs b/src/endpoints/quests/element/layerswap/verify_twitter_fw.rs deleted file mode 100644 index d29bfa97..00000000 --- a/src/endpoints/quests/element/layerswap/verify_twitter_fw.rs +++ /dev/null @@ -1,30 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; -use starknet::core::types::FieldElement; - -#[route(get, "/quests/element/layerswap/verify_twitter_fw")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 71; - if query.addr == FieldElement::ZERO { - return get_error("Please connect your wallet first".to_string()); - } - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/element/layerswap/verify_twitter_rt.rs b/src/endpoints/quests/element/layerswap/verify_twitter_rt.rs deleted file mode 100644 index 43edc25a..00000000 --- a/src/endpoints/quests/element/layerswap/verify_twitter_rt.rs +++ /dev/null @@ -1,30 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; -use starknet::core::types::FieldElement; - -#[route(get, "/quests/element/layerswap/verify_twitter_rt")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 72; - if query.addr == FieldElement::ZERO { - return get_error("Please connect your wallet first".to_string()); - } - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/element/mod.rs b/src/endpoints/quests/element/mod.rs deleted file mode 100644 index 299382c1..00000000 --- a/src/endpoints/quests/element/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod briq; -pub mod element; -pub mod layerswap; -pub mod starknetid; diff --git a/src/endpoints/quests/element/starknetid/claimable.rs b/src/endpoints/quests/element/starknetid/claimable.rs deleted file mode 100644 index f0e500fd..00000000 --- a/src/endpoints/quests/element/starknetid/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 19; -const TASK_IDS: &[u32] = &[73, 74]; -const LAST_TASK: u32 = TASK_IDS[1]; -const NFT_LEVEL: u32 = 25; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/element/starknetid/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/element/starknetid/mod.rs b/src/endpoints/quests/element/starknetid/mod.rs deleted file mode 100644 index 6569eae6..00000000 --- a/src/endpoints/quests/element/starknetid/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod claimable; -pub mod verify_has_root_domain; diff --git a/src/endpoints/quests/element/starknetid/verify_has_root_domain.rs b/src/endpoints/quests/element/starknetid/verify_has_root_domain.rs deleted file mode 100644 index 15d57b20..00000000 --- a/src/endpoints/quests/element/starknetid/verify_has_root_domain.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::{ - common::verify_has_root_domain::execute_has_root_domain, - models::{AppState, VerifyQuery}, -}; -use axum::{ - extract::{Query, State}, - response::IntoResponse, -}; -use axum_auto_routes::route; -use std::sync::Arc; - -#[route(get, "/quests/element/starknetid/verify_has_root_domain")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - execute_has_root_domain(state, &query.addr, 74).await -} diff --git a/src/endpoints/quests/haiko/claimable.rs b/src/endpoints/quests/haiko/claimable.rs deleted file mode 100644 index 72cc9d4a..00000000 --- a/src/endpoints/quests/haiko/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 29; -const TASK_IDS: &[u32] = &[140, 141, 142, 143]; -const LAST_TASK: u32 = TASK_IDS[3]; -const NFT_LEVEL: u32 = 41; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/haiko/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/haiko/mod.rs b/src/endpoints/quests/haiko/mod.rs deleted file mode 100644 index 26278749..00000000 --- a/src/endpoints/quests/haiko/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod verify_deposit; -pub mod verify_twitter_fw; -pub mod verify_twitter_rw; -pub mod claimable; \ No newline at end of file diff --git a/src/endpoints/quests/haiko/verify_deposit.rs b/src/endpoints/quests/haiko/verify_deposit.rs deleted file mode 100644 index 375e46cb..00000000 --- a/src/endpoints/quests/haiko/verify_deposit.rs +++ /dev/null @@ -1,52 +0,0 @@ -use std::sync::Arc; - -use crate::utils::fetch_json_from_url; -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, to_hex, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/haiko/verify_deposit")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 142; - let addr = &query.addr; - - let url = format!( - "{}&user={}", - state.conf.quests.haiko.api_endpoint, - to_hex(*addr) - ); - - match fetch_json_from_url(url).await { - Ok(response) => { - // check if user has deposited his funds - let response_data = response - .get("data") - .unwrap() - .get("result") - .unwrap() - .as_bool() - .unwrap(); - return if response_data { - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } - } else { - get_error("Funds not deposited".to_string()) - }; - } - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/haiko/verify_twitter_fw.rs b/src/endpoints/quests/haiko/verify_twitter_fw.rs deleted file mode 100644 index d629ec05..00000000 --- a/src/endpoints/quests/haiko/verify_twitter_fw.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/haiko/verify_twitter_fw")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 141; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/haiko/verify_twitter_rw.rs b/src/endpoints/quests/haiko/verify_twitter_rw.rs deleted file mode 100644 index 3c1dc780..00000000 --- a/src/endpoints/quests/haiko/verify_twitter_rw.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/haiko/verify_twitter_rt")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 143; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/hashstack/claimable.rs b/src/endpoints/quests/hashstack/claimable.rs deleted file mode 100644 index 0a538fdd..00000000 --- a/src/endpoints/quests/hashstack/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 28; -const TASK_IDS: &[u32] = &[135, 136, 137, 138, 139]; -const LAST_TASK: u32 = TASK_IDS[4]; -const NFT_LEVEL: u32 = 40; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/hashstack/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/hashstack/discord_fw_callback.rs b/src/endpoints/quests/hashstack/discord_fw_callback.rs deleted file mode 100644 index 20e91ee9..00000000 --- a/src/endpoints/quests/hashstack/discord_fw_callback.rs +++ /dev/null @@ -1,148 +0,0 @@ -use std::sync::Arc; - -use crate::utils::CompletedTasksTrait; -use crate::{ - models::AppState, - utils::{get_error_redirect, success_redirect}, -}; -use axum::{ - extract::{Query, State}, - response::IntoResponse, -}; -use axum_auto_routes::route; -use mongodb::bson::doc; -use reqwest::header::AUTHORIZATION; -use serde::Deserialize; -use starknet::core::types::FieldElement; - -#[derive(Deserialize)] -pub struct DiscordOAuthCallbackQuery { - code: String, - state: FieldElement, -} - -#[derive(Deserialize, Debug)] -pub struct Guild { - id: String, - #[allow(dead_code)] - name: String, -} - -#[route(get, "/quests/hashstack/discord_fw_callback")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let quest_id = 28; - let task_id = 137; - let guild_id = "907151419650482217"; - let authorization_code = &query.code; - let error_redirect_uri = format!( - "{}/quest/{}?task_id={}&res=false", - state.conf.variables.app_link, quest_id, task_id - ); - - // Exchange the authorization code for an access token - let params = [ - ("client_id", &state.conf.discord.oauth2_clientid), - ("client_secret", &state.conf.discord.oauth2_secret), - ("code", &authorization_code.to_string()), - ( - "redirect_uri", - &format!( - "{}/quests/hashstack/discord_fw_callback", - state.conf.variables.api_link - ), - ), - ("grant_type", &"authorization_code".to_string()), - ("scope", &"guilds".to_string()), - ]; - let access_token = match exchange_authorization_code(params).await { - Ok(token) => token, - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!("Failed to exchange authorization code: {}", e), - ); - } - }; - - // Get user guild information - let client = reqwest::Client::new(); - let response_result = client - .get("https://discord.com/api/users/@me/guilds") - .header(AUTHORIZATION, format!("Bearer {}", access_token)) - .send() - .await; - let response: Vec = match response_result { - Ok(response) => { - let json_result = response.json().await; - match json_result { - Ok(json) => json, - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!( - "Failed to get JSON response while fetching user info: {}", - e - ), - ); - } - } - } - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!("Failed to send request to get user info: {}", e), - ); - } - }; - - for guild in response { - if guild.id == guild_id { - match state.upsert_completed_task(query.state, task_id).await { - Ok(_) => { - let redirect_uri = format!( - "{}/quest/{}?task_id={}&res=true", - state.conf.variables.app_link, quest_id, task_id - ); - return success_redirect(redirect_uri); - } - Err(e) => return get_error_redirect(error_redirect_uri, format!("{}", e)), - } - } - } - - get_error_redirect( - error_redirect_uri, - "You're not part of Hashstack's Discord server".to_string(), - ) -} - -async fn exchange_authorization_code( - params: [(&str, &String); 6], -) -> Result> { - let client = reqwest::Client::new(); - let res = client - .post("https://discord.com/api/oauth2/token") - .form(¶ms) - .send() - .await?; - let json: serde_json::Value = res.json().await?; - match json["access_token"].as_str() { - Some(s) => Ok(s.to_string()), - None => { - println!( - "Failed to get 'access_token' from JSON response : {:?}", - json - ); - Err(Box::new(std::io::Error::new( - std::io::ErrorKind::Other, - format!( - "Failed to get 'access_token' from JSON response : {:?}", - json - ), - ))) - } - } -} diff --git a/src/endpoints/quests/hashstack/mod.rs b/src/endpoints/quests/hashstack/mod.rs deleted file mode 100644 index 3eedf6d3..00000000 --- a/src/endpoints/quests/hashstack/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod claimable; -pub mod discord_fw_callback; -pub mod verify_has_domain; -pub mod verify_twitter_fw_hashstack; -pub mod verify_twitter_rw; -pub mod verify_deposit; \ No newline at end of file diff --git a/src/endpoints/quests/hashstack/verify_deposit.rs b/src/endpoints/quests/hashstack/verify_deposit.rs deleted file mode 100644 index 30434092..00000000 --- a/src/endpoints/quests/hashstack/verify_deposit.rs +++ /dev/null @@ -1,56 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; -use starknet::{ - core::types::{BlockId, BlockTag, FieldElement, FunctionCall}, - macros::selector, - providers::Provider, -}; - -#[route(get, "/quests/hashstack/verify_deposit")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 138; - let addr = &query.addr; - let token_id = state.conf.quests.hashstack.token_address; - let calldata = vec![token_id, *addr]; - - let call_result = state - .provider - .call( - FunctionCall { - contract_address: state.conf.quests.hashstack.contract, - entry_point_selector: selector!("get_user_deposit_stats_info"), - calldata, - }, - BlockId::Tag(BlockTag::Latest), - ) - .await; - - match call_result { - Ok(result) => { - if result[0] < FieldElement::from_dec_str("1000000000").unwrap() { - get_error("You didn't invest on hashstack.".to_string()) - } else { - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } - } - } - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/hashstack/verify_has_domain.rs b/src/endpoints/quests/hashstack/verify_has_domain.rs deleted file mode 100644 index a1a4d463..00000000 --- a/src/endpoints/quests/hashstack/verify_has_domain.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::{ - common::verify_has_root_or_braavos_domain::verify_has_root_or_braavos_domain, - models::{AppState, VerifyQuery}, -}; -use axum::{ - extract::{Query, State}, - response::IntoResponse, -}; -use axum_auto_routes::route; -use std::sync::Arc; - -#[route(get, "/quests/hashstack/verify_has_domain")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - verify_has_root_or_braavos_domain(state, &query.addr, 135).await -} diff --git a/src/endpoints/quests/hashstack/verify_twitter_fw_hashstack.rs b/src/endpoints/quests/hashstack/verify_twitter_fw_hashstack.rs deleted file mode 100644 index d84c3827..00000000 --- a/src/endpoints/quests/hashstack/verify_twitter_fw_hashstack.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/hashstack/verify_twitter_fw")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 136; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/hashstack/verify_twitter_rw.rs b/src/endpoints/quests/hashstack/verify_twitter_rw.rs deleted file mode 100644 index 639768c0..00000000 --- a/src/endpoints/quests/hashstack/verify_twitter_rw.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/hashstack/verify_twitter_rt")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 139; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/influence/claimable.rs b/src/endpoints/quests/influence/claimable.rs deleted file mode 100644 index 61a4d9ed..00000000 --- a/src/endpoints/quests/influence/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 32; -const TASK_IDS: &[u32] = &[153, 154, 155, 156]; -const LAST_TASK: u32 = TASK_IDS[3]; -const NFT_LEVEL: u32 = 44; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/influence/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/influence/discord_fw_callback.rs b/src/endpoints/quests/influence/discord_fw_callback.rs deleted file mode 100644 index b1e0731f..00000000 --- a/src/endpoints/quests/influence/discord_fw_callback.rs +++ /dev/null @@ -1,148 +0,0 @@ -use std::sync::Arc; - -use crate::utils::CompletedTasksTrait; -use crate::{ - models::AppState, - utils::{get_error_redirect, success_redirect}, -}; -use axum::{ - extract::{Query, State}, - response::IntoResponse, -}; -use axum_auto_routes::route; -use mongodb::bson::doc; -use reqwest::header::AUTHORIZATION; -use serde::Deserialize; -use starknet::core::types::FieldElement; - -#[derive(Deserialize)] -pub struct DiscordOAuthCallbackQuery { - code: String, - state: FieldElement, -} - -#[derive(Deserialize, Debug)] -pub struct Guild { - id: String, - #[allow(dead_code)] - name: String, -} - -#[route(get, "/quests/influence/discord_fw_callback")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let quest_id = 32; - let task_id = 155; - let guild_id = "814990637178290177"; - let authorization_code = &query.code; - let error_redirect_uri = format!( - "{}/quest/{}?task_id={}&res=false", - state.conf.variables.app_link, quest_id, task_id - ); - - // Exchange the authorization code for an access token - let params = [ - ("client_id", &state.conf.discord.oauth2_clientid), - ("client_secret", &state.conf.discord.oauth2_secret), - ("code", &authorization_code.to_string()), - ( - "redirect_uri", - &format!( - "{}/quests/influence/discord_fw_callback", - state.conf.variables.api_link - ), - ), - ("grant_type", &"authorization_code".to_string()), - ("scope", &"guilds".to_string()), - ]; - let access_token = match exchange_authorization_code(params).await { - Ok(token) => token, - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!("Failed to exchange authorization code: {}", e), - ); - } - }; - - // Get user guild information - let client = reqwest::Client::new(); - let response_result = client - .get("https://discord.com/api/users/@me/guilds") - .header(AUTHORIZATION, format!("Bearer {}", access_token)) - .send() - .await; - let response: Vec = match response_result { - Ok(response) => { - let json_result = response.json().await; - match json_result { - Ok(json) => json, - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!( - "Failed to get JSON response while fetching user info: {}", - e - ), - ); - } - } - } - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!("Failed to send request to get user info: {}", e), - ); - } - }; - - for guild in response { - if guild.id == guild_id { - match state.upsert_completed_task(query.state, task_id).await { - Ok(_) => { - let redirect_uri = format!( - "{}/quest/{}?task_id={}&res=true", - state.conf.variables.app_link, quest_id, task_id - ); - return success_redirect(redirect_uri); - } - Err(e) => return get_error_redirect(error_redirect_uri, format!("{}", e)), - } - } - } - - get_error_redirect( - error_redirect_uri, - "You're not part of Influence's Discord server".to_string(), - ) -} - -async fn exchange_authorization_code( - params: [(&str, &String); 6], -) -> Result> { - let client = reqwest::Client::new(); - let res = client - .post("https://discord.com/api/oauth2/token") - .form(¶ms) - .send() - .await?; - let json: serde_json::Value = res.json().await?; - match json["access_token"].as_str() { - Some(s) => Ok(s.to_string()), - None => { - println!( - "Failed to get 'access_token' from JSON response : {:?}", - json - ); - Err(Box::new(std::io::Error::new( - std::io::ErrorKind::Other, - format!( - "Failed to get 'access_token' from JSON response : {:?}", - json - ), - ))) - } - } -} diff --git a/src/endpoints/quests/influence/mod.rs b/src/endpoints/quests/influence/mod.rs deleted file mode 100644 index fed40de5..00000000 --- a/src/endpoints/quests/influence/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod discord_fw_callback; -pub mod verify_twitter_fw; -pub mod verify_twitter_rw; -pub mod verify_twitter_rw_2; -pub mod claimable; \ No newline at end of file diff --git a/src/endpoints/quests/influence/verify_twitter_fw.rs b/src/endpoints/quests/influence/verify_twitter_fw.rs deleted file mode 100644 index 574c3270..00000000 --- a/src/endpoints/quests/influence/verify_twitter_fw.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/influence/verify_twitter_fw")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 154; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/influence/verify_twitter_rw.rs b/src/endpoints/quests/influence/verify_twitter_rw.rs deleted file mode 100644 index 41a86c40..00000000 --- a/src/endpoints/quests/influence/verify_twitter_rw.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/influence/verify_twitter_rw")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 153; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/influence/verify_twitter_rw_2.rs b/src/endpoints/quests/influence/verify_twitter_rw_2.rs deleted file mode 100644 index f7c4e6c6..00000000 --- a/src/endpoints/quests/influence/verify_twitter_rw_2.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/influence/verify_twitter_rw_2")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 156; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/jediswap/claimable.rs b/src/endpoints/quests/jediswap/claimable.rs deleted file mode 100644 index f853722f..00000000 --- a/src/endpoints/quests/jediswap/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 2; -const TASK_IDS: &[u32] = &[9, 10, 11]; -const LAST_TASK: u32 = TASK_IDS[2]; -const NFT_LEVEL: u32 = 5; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/jediswap/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/jediswap/mod.rs b/src/endpoints/quests/jediswap/mod.rs deleted file mode 100644 index ee2c0dee..00000000 --- a/src/endpoints/quests/jediswap/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod claimable; -pub mod verify_added_liquidity; -pub mod verify_twitter_fw; -pub mod verify_twitter_rt; diff --git a/src/endpoints/quests/jediswap/verify_added_liquidity.rs b/src/endpoints/quests/jediswap/verify_added_liquidity.rs deleted file mode 100644 index 2bd9f1ca..00000000 --- a/src/endpoints/quests/jediswap/verify_added_liquidity.rs +++ /dev/null @@ -1,57 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; -use starknet::{ - core::types::{BlockId, BlockTag, FieldElement, FunctionCall}, - macros::selector, - providers::Provider, -}; - -#[route(get, "/quests/jediswap/verify_added_liquidity")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 9; - let addr = &query.addr; - let mut calldata = vec![addr.clone(), state.conf.quests.jediswap.pairs.len().into()]; - calldata.append(&mut state.conf.quests.jediswap.pairs.clone()); - - // get starkname from address - let call_result = state - .provider - .call( - FunctionCall { - contract_address: state.conf.quests.jediswap.utils_contract, - entry_point_selector: selector!("sum_balances"), - calldata, - }, - BlockId::Tag(BlockTag::Latest), - ) - .await; - - match call_result { - Ok(result) => { - if result[0] == FieldElement::ZERO { - get_error("You didn't deposit liquidity.".to_string()) - } else { - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } - } - } - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/jediswap/verify_twitter_fw.rs b/src/endpoints/quests/jediswap/verify_twitter_fw.rs deleted file mode 100644 index 50a99a10..00000000 --- a/src/endpoints/quests/jediswap/verify_twitter_fw.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/jediswap/verify_twitter_fw")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 10; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/jediswap/verify_twitter_rt.rs b/src/endpoints/quests/jediswap/verify_twitter_rt.rs deleted file mode 100644 index 9bbf1b83..00000000 --- a/src/endpoints/quests/jediswap/verify_twitter_rt.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/jediswap/verify_twitter_rt")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 11; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/mod.rs b/src/endpoints/quests/mod.rs index 4cc16c20..86fab169 100644 --- a/src/endpoints/quests/mod.rs +++ b/src/endpoints/quests/mod.rs @@ -1,32 +1,13 @@ -pub mod avnu; -pub mod bountive; -pub mod braavos; -pub mod carmine; pub mod claimable; pub mod contract_uri; pub mod discord_fw_callback; pub mod ekubo; -pub mod element; pub mod focustree; -pub mod haiko; -pub mod hashstack; -pub mod influence; -pub mod jediswap; -pub mod morphine; -pub mod myswap; -pub mod nimbora; pub mod nostra; -pub mod orbiter; -pub mod rango; -pub mod rhino; -pub mod sithswap; pub mod starknet; pub mod starknetid; -pub mod strk_farm; -pub mod tribe; pub mod uri; pub mod verify_balance; pub mod verify_quiz; pub mod verify_twitter_fw; pub mod verify_twitter_rw; -pub mod zklend; diff --git a/src/endpoints/quests/morphine/claimable.rs b/src/endpoints/quests/morphine/claimable.rs deleted file mode 100644 index 2b6e4750..00000000 --- a/src/endpoints/quests/morphine/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 11; -const TASK_IDS: &[u32] = &[42, 43]; -const LAST_TASK: u32 = TASK_IDS[1]; -const NFT_LEVEL: u32 = 16; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/morphine/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/morphine/mod.rs b/src/endpoints/quests/morphine/mod.rs deleted file mode 100644 index 4e642f70..00000000 --- a/src/endpoints/quests/morphine/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod claimable; -pub mod verify_added_liquidity; diff --git a/src/endpoints/quests/morphine/verify_added_liquidity.rs b/src/endpoints/quests/morphine/verify_added_liquidity.rs deleted file mode 100644 index cc7c9945..00000000 --- a/src/endpoints/quests/morphine/verify_added_liquidity.rs +++ /dev/null @@ -1,82 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; -use starknet::{ - core::types::{BlockId, BlockTag, FieldElement, FunctionCall}, - macros::selector, - providers::Provider, -}; - -lazy_static::lazy_static! { - static ref POOLS: Vec = vec![ - FieldElement::from_hex_be( - "0x78e348ee59bde05154a58ed149d289f0c80bc7c1dcd6aba6180f1845ea25ecc", - ).unwrap(), - FieldElement::from_hex_be( - "0x012afd5a0a79ac3d1ee157221c15c54f541f73c145457505875557b0515dedaf", - ).unwrap(), - FieldElement::from_hex_be( - "0x04f79B79aC514974c88A838Eb9fb180551A82D92fD01B2e02740bA3F1d382457", - ).unwrap(), - FieldElement::from_hex_be( - "0x0170C38DcB19677c12d29C2Db96080E20DDc7D07e0Cf7fC0F3a076845b5c54e5", - ).unwrap(), - ]; -} - -#[route(get, "/quests/morphine/verify_added_liquidity")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 41; - let addr = &query.addr; - - // For each available pool we check if the user has provided liquidity - let mut has_provided = false; - for pool in POOLS.iter() { - let call_result = state - .provider - .call( - FunctionCall { - contract_address: *pool, - entry_point_selector: selector!("balanceOf"), - calldata: vec![*addr], - }, - BlockId::Tag(BlockTag::Latest), - ) - .await; - - match call_result { - Ok(result) => { - if result[0] != FieldElement::ZERO { - has_provided = true; - break; - } - } - Err(e) => { - return get_error(format!("{}", e)); - } - } - } - - if has_provided { - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } - } else { - get_error("You didn't provide any liquidity on any pool.".to_string()) - } -} diff --git a/src/endpoints/quests/myswap/claimable.rs b/src/endpoints/quests/myswap/claimable.rs deleted file mode 100644 index 434d07e2..00000000 --- a/src/endpoints/quests/myswap/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 12; -const TASK_IDS: &[u32] = &[44, 45]; -const LAST_TASK: u32 = TASK_IDS[1]; -const NFT_LEVEL: u32 = 17; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/myswap/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/myswap/discord_fw_callback.rs b/src/endpoints/quests/myswap/discord_fw_callback.rs deleted file mode 100644 index 238acab9..00000000 --- a/src/endpoints/quests/myswap/discord_fw_callback.rs +++ /dev/null @@ -1,147 +0,0 @@ -use std::sync::Arc; - -use crate::utils::CompletedTasksTrait; -use crate::{ - models::AppState, - utils::{get_error_redirect, success_redirect}, -}; -use axum::{ - extract::{Query, State}, - response::IntoResponse, -}; -use axum_auto_routes::route; -use mongodb::bson::doc; -use reqwest::header::AUTHORIZATION; -use serde::Deserialize; -use starknet::core::types::FieldElement; - -#[derive(Deserialize)] -pub struct TwitterOAuthCallbackQuery { - code: String, - state: FieldElement, -} - -#[derive(Deserialize, Debug)] -pub struct Guild { - id: String, - #[allow(dead_code)] - name: String, -} - -#[route(get, "/quests/myswap/discord_fw_callback")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let quest_id = 12; - let task_id = 45; - let guild_id = "930031669065420820"; - let authorization_code = &query.code; - let error_redirect_uri = format!( - "{}/quest/{}?task_id={}&res=false", - state.conf.variables.app_link, quest_id, task_id - ); - - // Exchange the authorization code for an access token - let params = [ - ("client_id", &state.conf.discord.oauth2_clientid), - ("client_secret", &state.conf.discord.oauth2_secret), - ("code", &authorization_code.to_string()), - ( - "redirect_uri", - &format!( - "{}/quests/myswap/discord_fw_callback", - state.conf.variables.api_link - ), - ), - ("grant_type", &"authorization_code".to_string()), - ]; - let access_token = match exchange_authorization_code(params).await { - Ok(token) => token, - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!("Failed to exchange authorization code: {}", e), - ); - } - }; - - // Get user guild information - let client = reqwest::Client::new(); - let response_result = client - .get("https://discord.com/api/users/@me/guilds") - .header(AUTHORIZATION, format!("Bearer {}", access_token)) - .send() - .await; - let response: Vec = match response_result { - Ok(response) => { - let json_result = response.json().await; - match json_result { - Ok(json) => json, - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!( - "Failed to get JSON response while fetching user info: {}", - e - ), - ); - } - } - } - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!("Failed to send request to get user info: {}", e), - ); - } - }; - - for guild in response { - if guild.id == guild_id { - match state.upsert_completed_task(query.state, task_id).await { - Ok(_) => { - let redirect_uri = format!( - "{}/quest/{}?task_id={}&res=true", - state.conf.variables.app_link, quest_id, task_id - ); - return success_redirect(redirect_uri); - } - Err(e) => return get_error_redirect(error_redirect_uri, format!("{}", e)), - } - } - } - - get_error_redirect( - error_redirect_uri, - "You're not part of MySwap's Discord server".to_string(), - ) -} - -async fn exchange_authorization_code( - params: [(&str, &String); 5], -) -> Result> { - let client = reqwest::Client::new(); - let res = client - .post("https://discord.com/api/oauth2/token") - .form(¶ms) - .send() - .await?; - let json: serde_json::Value = res.json().await?; - match json["access_token"].as_str() { - Some(s) => Ok(s.to_string()), - None => { - println!( - "Failed to get 'access_token' from JSON response : {:?}", - json - ); - Err(Box::new(std::io::Error::new( - std::io::ErrorKind::Other, - format!( - "Failed to get 'access_token' from JSON response : {:?}", - json - ), - ))) - } - } -} diff --git a/src/endpoints/quests/myswap/mod.rs b/src/endpoints/quests/myswap/mod.rs deleted file mode 100644 index 57eade9b..00000000 --- a/src/endpoints/quests/myswap/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod claimable; -pub mod discord_fw_callback; -pub mod verify_added_liquidity; diff --git a/src/endpoints/quests/myswap/verify_added_liquidity.rs b/src/endpoints/quests/myswap/verify_added_liquidity.rs deleted file mode 100644 index d4b3a8ea..00000000 --- a/src/endpoints/quests/myswap/verify_added_liquidity.rs +++ /dev/null @@ -1,55 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; -use starknet::{ - core::types::{BlockId, BlockTag, FieldElement, FunctionCall}, - macros::selector, - providers::Provider, -}; - -#[route(get, "/quests/myswap/verify_added_liquidity")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 44; - let addr = &query.addr; - - // check if user has provider liquidity - let call_result = state - .provider - .call( - FunctionCall { - contract_address: state.conf.quests.myswap.contract, - entry_point_selector: selector!("balanceOf"), - calldata: vec![*addr], - }, - BlockId::Tag(BlockTag::Latest), - ) - .await; - - match call_result { - Ok(result) => { - if result[0] == FieldElement::ZERO { - get_error("You haven't provided any liquidity on MySwap.".to_string()) - } else { - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } - } - } - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/nimbora/check_balance.rs b/src/endpoints/quests/nimbora/check_balance.rs deleted file mode 100644 index 0c769f36..00000000 --- a/src/endpoints/quests/nimbora/check_balance.rs +++ /dev/null @@ -1,54 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; -use starknet::{ - core::types::{BlockId, BlockTag, FieldElement, FunctionCall}, - macros::selector, - providers::Provider, -}; - -#[route(get, "/quests/nimbora/check_balance")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 144; - let addr = &query.addr; - let calldata = vec![*addr]; - let call_result = state - .provider - .call( - FunctionCall { - contract_address: state.conf.quests.nimbora.contract, - entry_point_selector: selector!("balance_of"), - calldata, - }, - BlockId::Tag(BlockTag::Latest), - ) - .await; - - match call_result { - Ok(result) => { - if result[0] < FieldElement::from_dec_str("4000000000000000").unwrap() { - get_error("You didn't invest on nimbora.".to_string()) - } else { - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } - } - } - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/nimbora/claimable.rs b/src/endpoints/quests/nimbora/claimable.rs deleted file mode 100644 index 5ae2c1cf..00000000 --- a/src/endpoints/quests/nimbora/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 22; -const TASK_IDS: &[u32] = &[89, 90, 91, 144]; -const LAST_TASK: u32 = TASK_IDS[3]; -const NFT_LEVEL: u32 = 35; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/nimbora/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/nimbora/discord_fw_callback.rs b/src/endpoints/quests/nimbora/discord_fw_callback.rs deleted file mode 100644 index 9682e3ce..00000000 --- a/src/endpoints/quests/nimbora/discord_fw_callback.rs +++ /dev/null @@ -1,149 +0,0 @@ -use std::sync::Arc; - -use crate::utils::CompletedTasksTrait; -use crate::{ - models::AppState, - utils::{get_error_redirect, success_redirect}, -}; -use axum::{ - extract::{Query, State}, - response::IntoResponse, -}; -use axum_auto_routes::route; -use mongodb::bson::doc; -use reqwest::header::AUTHORIZATION; -use serde::Deserialize; -use starknet::core::types::FieldElement; - -#[derive(Deserialize)] -pub struct TwitterOAuthCallbackQuery { - code: String, - state: FieldElement, -} - -#[derive(Deserialize, Debug)] -pub struct Guild { - id: String, - #[allow(dead_code)] - name: String, -} - -#[route(get, "/quests/nimbora/discord_fw_callback")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let quest_id = 22; - let task_id = 90; - let guild_id = "1157580917917892640"; - let authorization_code = &query.code; - let error_redirect_uri = format!( - "{}/quest/{}?task_id={}&res=false", - state.conf.variables.app_link, quest_id, task_id - ); - - // Exchange the authorization code for an access token - let params = [ - ("client_id", &state.conf.discord.oauth2_clientid), - ("client_secret", &state.conf.discord.oauth2_secret), - ("code", &authorization_code.to_string()), - ( - "redirect_uri", - &format!( - "{}/quests/nimbora/discord_fw_callback", - state.conf.variables.api_link - ), - ), - ("grant_type", &"authorization_code".to_string()), - ("scope", &"guilds".to_string()), - ]; - let access_token = match exchange_authorization_code(params).await { - Ok(token) => token, - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!("Failed to exchange authorization code: {}", e), - ); - } - }; - - // Get user guild information - let client = reqwest::Client::new(); - let response_result = client - .get("https://discord.com/api/users/@me/guilds") - .header(AUTHORIZATION, format!("Bearer {}", access_token)) - .send() - .await; - let response: Vec = match response_result { - Ok(response) => { - let json_result = response.json().await; - match json_result { - Ok(json) => json, - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!( - "Failed to get JSON response while fetching user info: {}", - e - ), - ); - } - } - } - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!("Failed to send request to get user info: {}", e), - ); - } - }; - - for guild in response { - if guild.id == guild_id { - print!("Checking guild: {:?}", guild); - match state.upsert_completed_task(query.state, task_id).await { - Ok(_) => { - let redirect_uri = format!( - "{}/quest/{}?task_id={}&res=true", - state.conf.variables.app_link, quest_id, task_id - ); - return success_redirect(redirect_uri); - } - Err(e) => return get_error_redirect(error_redirect_uri, format!("{}", e)), - } - } - } - - get_error_redirect( - error_redirect_uri, - "You're not part of Nimbora's Discord server".to_string(), - ) -} - -async fn exchange_authorization_code( - params: [(&str, &String); 6], -) -> Result> { - let client = reqwest::Client::new(); - let res = client - .post("https://discord.com/api/oauth2/token") - .form(¶ms) - .send() - .await?; - let json: serde_json::Value = res.json().await?; - match json["access_token"].as_str() { - Some(s) => Ok(s.to_string()), - None => { - println!( - "Failed to get 'access_token' from JSON response : {:?}", - json - ); - Err(Box::new(std::io::Error::new( - std::io::ErrorKind::Other, - format!( - "Failed to get 'access_token' from JSON response : {:?}", - json - ), - ))) - } - } -} diff --git a/src/endpoints/quests/nimbora/mod.rs b/src/endpoints/quests/nimbora/mod.rs deleted file mode 100644 index 2b7bfe06..00000000 --- a/src/endpoints/quests/nimbora/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod check_balance; -pub mod claimable; -pub mod discord_fw_callback; -pub mod verify_twitter_rt; diff --git a/src/endpoints/quests/nimbora/verify_twitter_rt.rs b/src/endpoints/quests/nimbora/verify_twitter_rt.rs deleted file mode 100644 index aef54222..00000000 --- a/src/endpoints/quests/nimbora/verify_twitter_rt.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/nimbora/verify_twitter_rt")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 91; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/orbiter/claimable.rs b/src/endpoints/quests/orbiter/claimable.rs deleted file mode 100644 index fc13c732..00000000 --- a/src/endpoints/quests/orbiter/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 8; -const TASK_IDS: &[u32] = &[32, 33, 34, 35, 36]; -const LAST_TASK: u32 = TASK_IDS[4]; -const NFT_LEVEL: u32 = 13; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/orbiter/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/orbiter/mod.rs b/src/endpoints/quests/orbiter/mod.rs deleted file mode 100644 index 267f5e51..00000000 --- a/src/endpoints/quests/orbiter/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod claimable; -pub mod verify_has_bridged; -pub mod verify_has_root_domain; -pub mod verify_twitter_fw; -pub mod verify_twitter_fw_sq; -pub mod verify_twitter_rt; diff --git a/src/endpoints/quests/orbiter/verify_has_bridged.rs b/src/endpoints/quests/orbiter/verify_has_bridged.rs deleted file mode 100644 index a66b1b02..00000000 --- a/src/endpoints/quests/orbiter/verify_has_bridged.rs +++ /dev/null @@ -1,79 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, to_hex, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[derive(Debug, serde::Deserialize)] -struct UserTaskStatus { - address: Vec, -} - -#[derive(Debug, serde::Deserialize)] -#[allow(non_snake_case)] -struct Data { - userTaskStatus: UserTaskStatus, -} - -#[derive(Debug, serde::Deserialize)] -struct Response { - data: Data, -} - -#[route(get, "/quests/orbiter/verify_has_bridged")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 32; - let hex_addr = to_hex(query.addr); - - let graphql_url = "https://actapi.orbiter.finance/graphql/activity"; - let graphql_query = r#" - query info($address: String!) { - userTaskStatus(address: $address, taskId: "5", verify: "aIHcjkNqpcD") { - address - } - } - "#; - let variables = serde_json::json!({ "address": hex_addr }); - - let client = reqwest::Client::new(); - let response_result = client - .post(graphql_url) - .json(&serde_json::json!({ - "query": graphql_query, - "variables": variables - })) - .send() - .await; - - match response_result { - Ok(response) => match response.json::().await { - Ok(res) => { - if res.data.userTaskStatus.address.is_empty() { - get_error("You haven't bridge ETH to Starknet using Orbiter.".to_string()) - } else { - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } - } - } - Err(e) => get_error(format!( - "Failed to get JSON response while fetching user info: {}", - e - )), - }, - Err(e) => get_error(format!("Failed to fetch user info: {}", e)), - } -} diff --git a/src/endpoints/quests/orbiter/verify_has_root_domain.rs b/src/endpoints/quests/orbiter/verify_has_root_domain.rs deleted file mode 100644 index 892f47e1..00000000 --- a/src/endpoints/quests/orbiter/verify_has_root_domain.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::{ - common::verify_has_root_domain::execute_has_root_domain, - models::{AppState, VerifyQuery}, -}; -use axum::{ - extract::{Query, State}, - response::IntoResponse, -}; -use axum_auto_routes::route; -use std::sync::Arc; - -#[route(get, "/quests/orbiter/verify_has_root_domain")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - execute_has_root_domain(state, &query.addr, 33).await -} diff --git a/src/endpoints/quests/orbiter/verify_twitter_fw.rs b/src/endpoints/quests/orbiter/verify_twitter_fw.rs deleted file mode 100644 index 3c13075d..00000000 --- a/src/endpoints/quests/orbiter/verify_twitter_fw.rs +++ /dev/null @@ -1,30 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; -use starknet::core::types::FieldElement; - -#[route(get, "/quests/orbiter/verify_twitter_fw")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 34; - if query.addr == FieldElement::ZERO { - return get_error("Please connect your wallet first".to_string()); - } - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/orbiter/verify_twitter_fw_sq.rs b/src/endpoints/quests/orbiter/verify_twitter_fw_sq.rs deleted file mode 100644 index 7df24c79..00000000 --- a/src/endpoints/quests/orbiter/verify_twitter_fw_sq.rs +++ /dev/null @@ -1,30 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; -use starknet::core::types::FieldElement; - -#[route(get, "/quests/orbiter/verify_twitter_fw_sq")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 35; - if query.addr == FieldElement::ZERO { - return get_error("Please connect your wallet first".to_string()); - } - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/orbiter/verify_twitter_rt.rs b/src/endpoints/quests/orbiter/verify_twitter_rt.rs deleted file mode 100644 index be8b9cc8..00000000 --- a/src/endpoints/quests/orbiter/verify_twitter_rt.rs +++ /dev/null @@ -1,30 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; -use starknet::core::types::FieldElement; - -#[route(get, "/quests/orbiter/verify_twitter_rt")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 36; - if query.addr == FieldElement::ZERO { - return get_error("Please connect your wallet first".to_string()); - } - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/rango/mod.rs b/src/endpoints/quests/rango/mod.rs deleted file mode 100644 index 51892a08..00000000 --- a/src/endpoints/quests/rango/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod quest1; -pub mod quest2; \ No newline at end of file diff --git a/src/endpoints/quests/rango/quest1/check_trade.rs b/src/endpoints/quests/rango/quest1/check_trade.rs deleted file mode 100644 index b1c4c968..00000000 --- a/src/endpoints/quests/rango/quest1/check_trade.rs +++ /dev/null @@ -1,52 +0,0 @@ -use std::sync::Arc; - -use crate::models::VerifyQuery; -use crate::utils::{make_api_request, to_hex, CompletedTasksTrait}; -use crate::{models::AppState, utils::get_error}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/rango/check_trade")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 92; - let mut address_hex = to_hex(query.addr); - - // remove "0x" - address_hex.remove(0); - address_hex.remove(0); - - // remove leading zeroes - while address_hex.starts_with("0") { - address_hex.remove(0); - } - - // add "0x" back - address_hex.insert(0, 'x'); - address_hex.insert(0, '0'); - - let res = make_api_request( - &state.conf.rango.api_endpoint, - &address_hex, - Some(&state.conf.rango.api_key), - ) - .await; - - match res { - true => { - return match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - }; - } - false => get_error("User has not completed the task".to_string()), - } -} diff --git a/src/endpoints/quests/rango/quest1/claimable.rs b/src/endpoints/quests/rango/quest1/claimable.rs deleted file mode 100644 index ff95930a..00000000 --- a/src/endpoints/quests/rango/quest1/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 23; -const TASK_IDS: &[u32] = &[92, 93, 94, 95]; -const LAST_TASK: u32 = TASK_IDS[3]; -const NFT_LEVEL: u32 = 30; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/rango/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/rango/quest1/discord_fw_callback.rs b/src/endpoints/quests/rango/quest1/discord_fw_callback.rs deleted file mode 100644 index e69e6c36..00000000 --- a/src/endpoints/quests/rango/quest1/discord_fw_callback.rs +++ /dev/null @@ -1,147 +0,0 @@ -use std::sync::Arc; - -use crate::utils::CompletedTasksTrait; -use crate::{ - models::AppState, - utils::{get_error_redirect, success_redirect}, -}; -use axum::{ - extract::{Query, State}, - response::IntoResponse, -}; -use axum_auto_routes::route; -use mongodb::bson::doc; -use reqwest::header::AUTHORIZATION; -use serde::Deserialize; -use starknet::core::types::FieldElement; - -#[derive(Deserialize)] -pub struct TwitterOAuthCallbackQuery { - code: String, - state: FieldElement, -} - -#[derive(Deserialize)] -pub struct Guild { - id: String, - #[allow(dead_code)] - name: String, -} - -#[route(get, "/quests/rango/discord_fw_callback")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let quest_id = 23; - let task_id = 94; - let guild_id = "1079299393712300112"; - let authorization_code = &query.code; - let error_redirect_uri = format!( - "{}/quest/{}?task_id={}&res=false", - state.conf.variables.app_link, quest_id, task_id - ); - - // Exchange the authorization code for an access token - let params = [ - ("client_id", &state.conf.discord.oauth2_clientid), - ("client_secret", &state.conf.discord.oauth2_secret), - ("code", &authorization_code.to_string()), - ( - "redirect_uri", - &format!( - "{}/quests/rango/discord_fw_callback", - state.conf.variables.api_link - ), - ), - ("grant_type", &"authorization_code".to_string()), - ]; - let access_token = match exchange_authorization_code(params).await { - Ok(token) => token, - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!("Failed to exchange authorization code: {}", e), - ); - } - }; - - // Get user guild information - let client = reqwest::Client::new(); - let response_result = client - .get("https://discord.com/api/users/@me/guilds") - .header(AUTHORIZATION, format!("Bearer {}", access_token)) - .send() - .await; - let response: Vec = match response_result { - Ok(response) => { - let json_result = response.json().await; - match json_result { - Ok(json) => json, - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!( - "Failed to get JSON response while fetching user info: {}", - e - ), - ); - } - } - } - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!("Failed to send request to get user info: {}", e), - ); - } - }; - - for guild in response { - if guild.id == guild_id { - match state.upsert_completed_task(query.state, task_id).await { - Ok(_) => { - let redirect_uri = format!( - "{}/quest/{}?task_id={}&res=true", - state.conf.variables.app_link, quest_id, task_id - ); - return success_redirect(redirect_uri); - } - Err(e) => return get_error_redirect(error_redirect_uri, format!("{}", e)), - } - } - } - - get_error_redirect( - error_redirect_uri, - "You're not part of Rango's Discord server".to_string(), - ) -} - -async fn exchange_authorization_code( - params: [(&str, &String); 5], -) -> Result> { - let client = reqwest::Client::new(); - let res = client - .post("https://discord.com/api/oauth2/token") - .form(¶ms) - .send() - .await?; - let json: serde_json::Value = res.json().await?; - match json["access_token"].as_str() { - Some(s) => Ok(s.to_string()), - None => { - println!( - "Failed to get 'access_token' from JSON response : {:?}", - json - ); - Err(Box::new(std::io::Error::new( - std::io::ErrorKind::Other, - format!( - "Failed to get 'access_token' from JSON response : {:?}", - json - ), - ))) - } - } -} diff --git a/src/endpoints/quests/rango/quest1/mod.rs b/src/endpoints/quests/rango/quest1/mod.rs deleted file mode 100644 index 7d2a4c2e..00000000 --- a/src/endpoints/quests/rango/quest1/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod check_trade; -pub mod claimable; -pub mod discord_fw_callback; -pub mod verify_twitter_fw; \ No newline at end of file diff --git a/src/endpoints/quests/rango/quest1/verify_twitter_fw.rs b/src/endpoints/quests/rango/quest1/verify_twitter_fw.rs deleted file mode 100644 index af72764e..00000000 --- a/src/endpoints/quests/rango/quest1/verify_twitter_fw.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/rango/verify_twitter_fw")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 93; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/rango/quest2/check_trade.rs b/src/endpoints/quests/rango/quest2/check_trade.rs deleted file mode 100644 index c2ef1243..00000000 --- a/src/endpoints/quests/rango/quest2/check_trade.rs +++ /dev/null @@ -1,81 +0,0 @@ -use std::sync::Arc; - -use crate::models::VerifyQuery; -use crate::utils::{to_hex, CompletedTasksTrait}; -use crate::{models::AppState, utils::get_error}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/rango/quest2/check_trade")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 123; - let mut address_hex = to_hex(query.addr); - - // remove "0x" - address_hex.remove(0); - address_hex.remove(0); - - // remove leading zeroes - while address_hex.starts_with("0") { - address_hex.remove(0); - } - - // add "0x" back - address_hex.insert(0, 'x'); - address_hex.insert(0, '0'); - - let res = make_rango_request( - &state.conf.rango.api_endpoint, - &state.conf.rango.api_key, - &address_hex, - ) - .await; - let response = match res { - Ok(response) => response, - Err(_) => return get_error(format!("Try again later")), - }; - if let Some(_) = response.get("data") { - let data = response.get("data").unwrap(); - if let Some(res) = data.get("result") { - if res.as_bool().unwrap() { - return match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - }; - } - } - } - get_error("User has not completed the task".to_string()) -} - -async fn make_rango_request( - endpoint: &str, - api_key: &str, - addr: &str, -) -> Result { - let client = reqwest::Client::new(); - match client - .post(endpoint) - .json(&json!({ - "address": addr, - })) - .header("apiKey", api_key) - .send() - .await - { - Ok(response) => match response.json::().await { - Ok(json) => Ok(json), - Err(_) => Err(format!("Funds not bridged")), - }, - Err(_) => Err(format!("Funds not bridged")), - } -} diff --git a/src/endpoints/quests/rango/quest2/claimable.rs b/src/endpoints/quests/rango/quest2/claimable.rs deleted file mode 100644 index 4bee0685..00000000 --- a/src/endpoints/quests/rango/quest2/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 26; -const TASK_IDS: &[u32] = &[123, 124, 125, 126]; -const LAST_TASK: u32 = TASK_IDS[3]; -const NFT_LEVEL: u32 = 37; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/rango/quest2/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/rango/quest2/discord_fw_callback.rs b/src/endpoints/quests/rango/quest2/discord_fw_callback.rs deleted file mode 100644 index 1c59db12..00000000 --- a/src/endpoints/quests/rango/quest2/discord_fw_callback.rs +++ /dev/null @@ -1,147 +0,0 @@ -use std::sync::Arc; - -use crate::utils::CompletedTasksTrait; -use crate::{ - models::AppState, - utils::{get_error_redirect, success_redirect}, -}; -use axum::{ - extract::{Query, State}, - response::IntoResponse, -}; -use axum_auto_routes::route; -use mongodb::bson::doc; -use reqwest::header::AUTHORIZATION; -use serde::Deserialize; -use starknet::core::types::FieldElement; - -#[derive(Deserialize)] -pub struct TwitterOAuthCallbackQuery { - code: String, - state: FieldElement, -} - -#[derive(Deserialize)] -pub struct Guild { - id: String, - #[allow(dead_code)] - name: String, -} - -#[route(get, "/quests/rango/quest2/discord_fw_callback")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let quest_id = 26; - let task_id = 125; - let guild_id = "1079299393712300112"; - let authorization_code = &query.code; - let error_redirect_uri = format!( - "{}/quest/{}?task_id={}&res=false", - state.conf.variables.app_link, quest_id, task_id - ); - - // Exchange the authorization code for an access token - let params = [ - ("client_id", &state.conf.discord.oauth2_clientid), - ("client_secret", &state.conf.discord.oauth2_secret), - ("code", &authorization_code.to_string()), - ( - "redirect_uri", - &format!( - "{}/quests/rango/quest2/discord_fw_callback", - state.conf.variables.api_link - ), - ), - ("grant_type", &"authorization_code".to_string()), - ]; - let access_token = match exchange_authorization_code(params).await { - Ok(token) => token, - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!("Failed to exchange authorization code: {}", e), - ); - } - }; - - // Get user guild information - let client = reqwest::Client::new(); - let response_result = client - .get("https://discord.com/api/users/@me/guilds") - .header(AUTHORIZATION, format!("Bearer {}", access_token)) - .send() - .await; - let response: Vec = match response_result { - Ok(response) => { - let json_result = response.json().await; - match json_result { - Ok(json) => json, - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!( - "Failed to get JSON response while fetching user info: {}", - e - ), - ); - } - } - } - Err(e) => { - return get_error_redirect( - error_redirect_uri, - format!("Failed to send request to get user info: {}", e), - ); - } - }; - - for guild in response { - if guild.id == guild_id { - match state.upsert_completed_task(query.state, task_id).await { - Ok(_) => { - let redirect_uri = format!( - "{}/quest/{}?task_id={}&res=true", - state.conf.variables.app_link, quest_id, task_id - ); - return success_redirect(redirect_uri); - } - Err(e) => return get_error_redirect(error_redirect_uri, format!("{}", e)), - } - } - } - - get_error_redirect( - error_redirect_uri, - "You're not part of Rango's Discord server".to_string(), - ) -} - -async fn exchange_authorization_code( - params: [(&str, &String); 5], -) -> Result> { - let client = reqwest::Client::new(); - let res = client - .post("https://discord.com/api/oauth2/token") - .form(¶ms) - .send() - .await?; - let json: serde_json::Value = res.json().await?; - match json["access_token"].as_str() { - Some(s) => Ok(s.to_string()), - None => { - println!( - "Failed to get 'access_token' from JSON response : {:?}", - json - ); - Err(Box::new(std::io::Error::new( - std::io::ErrorKind::Other, - format!( - "Failed to get 'access_token' from JSON response : {:?}", - json - ), - ))) - } - } -} diff --git a/src/endpoints/quests/rango/quest2/mod.rs b/src/endpoints/quests/rango/quest2/mod.rs deleted file mode 100644 index 54e68fa9..00000000 --- a/src/endpoints/quests/rango/quest2/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod check_trade; -pub mod claimable; -pub mod discord_fw_callback; -pub mod verify_twitter_fw; -pub mod verify_twitter_rw; \ No newline at end of file diff --git a/src/endpoints/quests/rango/quest2/verify_twitter_fw.rs b/src/endpoints/quests/rango/quest2/verify_twitter_fw.rs deleted file mode 100644 index 9e4c53ae..00000000 --- a/src/endpoints/quests/rango/quest2/verify_twitter_fw.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/rango/quest2/verify_twitter_fw")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 124; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/rango/quest2/verify_twitter_rw.rs b/src/endpoints/quests/rango/quest2/verify_twitter_rw.rs deleted file mode 100644 index a75d196f..00000000 --- a/src/endpoints/quests/rango/quest2/verify_twitter_rw.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/rango/quest2/verify_twitter_rw")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 126; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/rhino/check_bridge.rs b/src/endpoints/quests/rhino/check_bridge.rs deleted file mode 100644 index e8f9686a..00000000 --- a/src/endpoints/quests/rhino/check_bridge.rs +++ /dev/null @@ -1,53 +0,0 @@ -use std::sync::Arc; - -use crate::utils::fetch_json_from_url; -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, to_hex, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/rhino/check_bridge")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 101; - let addr = &query.addr; - - // create get request to rhino api for verification - let url = format!( - "{}/?address={}", - state.conf.rhino.api_endpoint, - to_hex(*addr) - ); - - match fetch_json_from_url(url).await { - Ok(response) => { - /* - API response is in the format: - { - "result": true/false - } - */ - // check if user has bridged his funds - let has_bridged = response.get("result").unwrap().as_bool().unwrap(); - return if has_bridged { - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } - } else { - get_error("Funds not bridged".to_string()) - }; - } - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/rhino/claimable.rs b/src/endpoints/quests/rhino/claimable.rs deleted file mode 100644 index e4943262..00000000 --- a/src/endpoints/quests/rhino/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 24; -const TASK_IDS: &[u32] = &[101, 102, 103]; -const LAST_TASK: u32 = TASK_IDS[2]; -const NFT_LEVEL: u32 = 31; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/rhino/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/rhino/mod.rs b/src/endpoints/quests/rhino/mod.rs deleted file mode 100644 index 9f7af890..00000000 --- a/src/endpoints/quests/rhino/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod verify_twitter_fw; -pub mod claimable; -pub mod check_bridge; -pub mod verify_twitter_rw; \ No newline at end of file diff --git a/src/endpoints/quests/rhino/verify_twitter_fw.rs b/src/endpoints/quests/rhino/verify_twitter_fw.rs deleted file mode 100644 index 6345d62b..00000000 --- a/src/endpoints/quests/rhino/verify_twitter_fw.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/rhino/verify_twitter_fw")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 102; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/rhino/verify_twitter_rw.rs b/src/endpoints/quests/rhino/verify_twitter_rw.rs deleted file mode 100644 index 6f865989..00000000 --- a/src/endpoints/quests/rhino/verify_twitter_rw.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -#[route(get, "/quests/rhino/verify_twitter_rw")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 103; - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/sithswap/mod.rs b/src/endpoints/quests/sithswap/mod.rs deleted file mode 100644 index 27f02e0b..00000000 --- a/src/endpoints/quests/sithswap/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod quest2; -pub mod quest1; \ No newline at end of file diff --git a/src/endpoints/quests/sithswap/quest1/claimable.rs b/src/endpoints/quests/sithswap/quest1/claimable.rs deleted file mode 100644 index 2afcc5e7..00000000 --- a/src/endpoints/quests/sithswap/quest1/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 5; -const TASK_IDS: &[u32] = &[20, 21, 55]; -const LAST_TASK: u32 = TASK_IDS[2]; -const NFT_LEVEL: u32 = 7; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/sithswap/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/sithswap/quest1/mod.rs b/src/endpoints/quests/sithswap/quest1/mod.rs deleted file mode 100644 index 66d0a426..00000000 --- a/src/endpoints/quests/sithswap/quest1/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod claimable; -pub mod verify_added_liquidity; -pub mod verify_twitter_fw; diff --git a/src/endpoints/quests/sithswap/quest1/verify_added_liquidity.rs b/src/endpoints/quests/sithswap/quest1/verify_added_liquidity.rs deleted file mode 100644 index d764d475..00000000 --- a/src/endpoints/quests/sithswap/quest1/verify_added_liquidity.rs +++ /dev/null @@ -1,57 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; -use starknet::{ - core::types::{BlockId, BlockTag, FieldElement, FunctionCall}, - macros::selector, - providers::Provider, -}; - -#[route(get, "/quests/sithswap/verify_added_liquidity")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 20; - let addr = &query.addr; - let mut calldata = vec![addr.clone(), state.conf.quests.sithswap.pairs.len().into()]; - calldata.append(&mut state.conf.quests.sithswap.pairs.clone()); - - // get starkname from address - let call_result = state - .provider - .call( - FunctionCall { - contract_address: state.conf.quests.sithswap.utils_contract, - entry_point_selector: selector!("sum_balances"), - calldata, - }, - BlockId::Tag(BlockTag::Latest), - ) - .await; - - match call_result { - Ok(result) => { - if result[0] == FieldElement::ZERO { - get_error("You didn't deposit liquidity.".to_string()) - } else { - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } - } - } - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/sithswap/quest1/verify_twitter_fw.rs b/src/endpoints/quests/sithswap/quest1/verify_twitter_fw.rs deleted file mode 100644 index b0a1df18..00000000 --- a/src/endpoints/quests/sithswap/quest1/verify_twitter_fw.rs +++ /dev/null @@ -1,30 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; -use starknet::core::types::FieldElement; - -#[route(get, "/quests/sithswap/verify_twitter_fw")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 21; - if query.addr == FieldElement::ZERO { - return get_error("Please connect your wallet first".to_string()); - } - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/sithswap/quest2/claimable.rs b/src/endpoints/quests/sithswap/quest2/claimable.rs deleted file mode 100644 index ef19e008..00000000 --- a/src/endpoints/quests/sithswap/quest2/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 31; -const TASK_IDS: &[u32] = &[149, 150, 151, 152]; -const LAST_TASK: u32 = TASK_IDS[3]; -const NFT_LEVEL: u32 = 43; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/sithswap2/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/sithswap/quest2/mod.rs b/src/endpoints/quests/sithswap/quest2/mod.rs deleted file mode 100644 index 6d3690d7..00000000 --- a/src/endpoints/quests/sithswap/quest2/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod verify_deposit; -pub mod verify_has_domain; -pub mod verify_twitter_fw; -pub mod verify_twitter_rw; -pub mod claimable; \ No newline at end of file diff --git a/src/endpoints/quests/sithswap/quest2/verify_deposit.rs b/src/endpoints/quests/sithswap/quest2/verify_deposit.rs deleted file mode 100644 index 012cfd8b..00000000 --- a/src/endpoints/quests/sithswap/quest2/verify_deposit.rs +++ /dev/null @@ -1,111 +0,0 @@ -use std::sync::Arc; - -use crate::utils::to_hex; -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -fn string_to_float(s: &str) -> Result { - s.parse::() -} - -#[route(get, "/quests/sithswap2/verify_deposit")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 151; - let addr = &query.addr; - let mut hex_addr = to_hex(*addr); - // Define the GraphQL endpoint - let endpoint = &state.conf.quests.sithswap_2.api_endpoint; - - // remove "0x" - hex_addr.remove(0); - hex_addr.remove(0); - - // remove leading zeroes - while hex_addr.starts_with("0") { - hex_addr.remove(0); - } - - // add "0x" back - hex_addr.insert(0, 'x'); - hex_addr.insert(0, '0'); - - // Define the GraphQL query - let graphql_query = format!( - r#" - {{ - mints(where: {{to: "{}"}}) {{ - amountUSD - timestamp - to - pair {{ - id - }} - }} - }} - "#, - &hex_addr - ); - - // Send the GraphQL query - let response = reqwest::Client::new() - .post(endpoint) - .json(&json!({ "query": graphql_query })) - .send() - .await; - - // Check if the response is successful - let response = match response { - Ok(response) => response, - Err(_) => return get_error(format!("Try again later")), - }; - - // Parse the response - let response = response.json::().await; - let response = match response { - Ok(response) => response, - Err(_) => return get_error(format!("Try again later")), - }; - - let mut total_amount_usd = 0.0; - - // Check if the response contains the data field - if let Some(data) = response.get("data") { - // Check if the data field contains the mints field - if let Some(mints) = data.get("mints") { - // Iterate over the mints - for mint in mints.as_array().unwrap() { - // Check if the mint contains the amountUSD field - if let Some(amount_usd) = mint.get("amountUSD").and_then(|v| v.as_str()) { - match string_to_float(amount_usd) { - Ok(amount_usd) => total_amount_usd += amount_usd, - Err(_e) => return get_error(format!("Failed to get balance")), - } - } - } - } - } - - // Check if the total_amount_usd is greater than 10 - if total_amount_usd >= 10.0 { - // Update the completed task - match state.upsert_completed_task(*&query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(_e) => get_error(format!("Failed to get balance")), - } - } else { - get_error("User has not completed the task".to_string()) - } -} diff --git a/src/endpoints/quests/sithswap/quest2/verify_has_domain.rs b/src/endpoints/quests/sithswap/quest2/verify_has_domain.rs deleted file mode 100644 index e2bc6367..00000000 --- a/src/endpoints/quests/sithswap/quest2/verify_has_domain.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::{ - common::verify_has_root_or_braavos_domain::verify_has_root_or_braavos_domain, - models::{AppState, VerifyQuery}, -}; -use axum::{ - extract::{Query, State}, - response::IntoResponse, -}; -use axum_auto_routes::route; -use std::sync::Arc; - -#[route(get, "/quests/sithswap2/verify_has_domain")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - verify_has_root_or_braavos_domain(state, &query.addr, 149).await -} diff --git a/src/endpoints/quests/sithswap/quest2/verify_twitter_fw.rs b/src/endpoints/quests/sithswap/quest2/verify_twitter_fw.rs deleted file mode 100644 index 15be71cb..00000000 --- a/src/endpoints/quests/sithswap/quest2/verify_twitter_fw.rs +++ /dev/null @@ -1,30 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; -use starknet::core::types::FieldElement; - -#[route(get, "/quests/sithswap2/verify_twitter_fw")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 150; - if query.addr == FieldElement::ZERO { - return get_error("Please connect your wallet first".to_string()); - } - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/sithswap/quest2/verify_twitter_rw.rs b/src/endpoints/quests/sithswap/quest2/verify_twitter_rw.rs deleted file mode 100644 index 6c3453a2..00000000 --- a/src/endpoints/quests/sithswap/quest2/verify_twitter_rw.rs +++ /dev/null @@ -1,30 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; -use starknet::core::types::FieldElement; - -#[route(get, "/quests/sithswap2/verify_twitter_rw")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 152; - if query.addr == FieldElement::ZERO { - return get_error("Please connect your wallet first".to_string()); - } - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/strk_farm/check_balance.rs b/src/endpoints/quests/strk_farm/check_balance.rs deleted file mode 100644 index d3a18c57..00000000 --- a/src/endpoints/quests/strk_farm/check_balance.rs +++ /dev/null @@ -1,43 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; - -type StrkFarmAPIResponse = serde_json::Value; - -#[route(get, "/quests/strkFarm/check_balance")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 185; - let addr = &query.addr; - let url = format!("https://www.strkfarm.xyz/api/stats/{addr}"); - let res = reqwest::get(&url).await.unwrap().text().await.unwrap(); - // Res in a JSON containing the user's balance - let json: StrkFarmAPIResponse = serde_json::from_str(&res).unwrap(); - let usd = json["holdingsUSD"].as_f64().unwrap(); - if usd == 0.0 { - get_error("You didn't invest on StrkFarm.".to_string()) - } else if usd < 10.0 { - get_error(format!( - "You need to invest at least $10 on StrkFarm (You have ${}).", - usd - )) - } else { - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } - } -} diff --git a/src/endpoints/quests/strk_farm/mod.rs b/src/endpoints/quests/strk_farm/mod.rs deleted file mode 100644 index efaa97b9..00000000 --- a/src/endpoints/quests/strk_farm/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod check_balance; diff --git a/src/endpoints/quests/tribe/claimable.rs b/src/endpoints/quests/tribe/claimable.rs deleted file mode 100644 index 352e8f12..00000000 --- a/src/endpoints/quests/tribe/claimable.rs +++ /dev/null @@ -1,135 +0,0 @@ -use crate::models::RewardResponse; -use crate::utils::get_nft; -use crate::{ - models::{AppState, CompletedTaskDocument, Reward}, - utils::get_error, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::{Deserialize, Serialize}; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -#[derive(Debug, Serialize, Deserialize)] -pub struct UserTask { - id: u32, - quest_id: u32, - name: String, - desc: String, - href: String, - cta: Option, - verify_endpoint: Option, - completed: bool, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct RequestProps { - address: String, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct TwitterRequestProps { - id: String, -} - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -const QUEST_ID: u32 = 4; - -#[route(get, "/quests/tribe/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.0": { "$exists": true }, - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$project": { - "_id": 0, - "task_id": 1, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - while let Some(result) = tasks_cursor.next().await { - match result { - Ok(document) => { - if let Ok(task_id) = document.get_i32("task_id") { - if task_id >= 16 && task_id <= 18 { - match get_nft( - QUEST_ID, - task_id as u32, - &query.addr, - task_id as u32 - 1, - &signer, - ) - .await - { - Ok((token_id, sig)) => { - rewards.push(Reward { - task_id: task_id as u32, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - } - Err(_) => continue, - } - } - } - } - _ => continue, - } - } - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/tribe/mod.rs b/src/endpoints/quests/tribe/mod.rs deleted file mode 100644 index 8faaf0a2..00000000 --- a/src/endpoints/quests/tribe/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod claimable; -pub mod verify_has_domain; -pub mod verify_has_root_domain; -pub mod verify_three_years_expiry; diff --git a/src/endpoints/quests/tribe/verify_has_domain.rs b/src/endpoints/quests/tribe/verify_has_domain.rs deleted file mode 100644 index 3b97ed48..00000000 --- a/src/endpoints/quests/tribe/verify_has_domain.rs +++ /dev/null @@ -1,64 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::AppState, - 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; -use serde_json::json; -use starknet::{ - core::types::{BlockId, BlockTag, FieldElement, FunctionCall}, - macros::selector, - providers::Provider, -}; - -#[derive(Deserialize)] -pub struct StarknetIdQuery { - addr: FieldElement, -} - -#[route(get, "/quests/tribe/verify_has_domain")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 16; - let addr = &query.addr; - - // get starkname from address - let call_result = state - .provider - .call( - FunctionCall { - contract_address: state.conf.starknetid_contracts.naming_contract, - entry_point_selector: selector!("address_to_domain"), - calldata: vec![*addr, FieldElement::ZERO], - }, - BlockId::Tag(BlockTag::Latest), - ) - .await; - - match call_result { - Ok(result) => { - let domain_len = i64::from_str_radix(&FieldElement::to_string(&result[0]), 16).unwrap(); - - if domain_len > 0 { - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } - } else { - get_error("You don't own a stark domain".to_string()) - } - } - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/tribe/verify_has_root_domain.rs b/src/endpoints/quests/tribe/verify_has_root_domain.rs deleted file mode 100644 index 8cc471a7..00000000 --- a/src/endpoints/quests/tribe/verify_has_root_domain.rs +++ /dev/null @@ -1,18 +0,0 @@ -use crate::{ - common::verify_has_root_domain::execute_has_root_domain, - models::{AppState, VerifyQuery}, -}; -use axum::{ - extract::{Query, State}, - response::IntoResponse, -}; -use axum_auto_routes::route; -use std::sync::Arc; - -#[route(get, "/quests/tribe/verify_has_root_domain")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - execute_has_root_domain(state, &query.addr, 17).await -} diff --git a/src/endpoints/quests/tribe/verify_three_years_expiry.rs b/src/endpoints/quests/tribe/verify_three_years_expiry.rs deleted file mode 100644 index 22531e46..00000000 --- a/src/endpoints/quests/tribe/verify_three_years_expiry.rs +++ /dev/null @@ -1,96 +0,0 @@ -use std::{ - sync::Arc, - time::{SystemTime, UNIX_EPOCH}, -}; - -use crate::{ - models::AppState, - 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; -use serde_json::json; -use starknet::{ - core::types::{BlockId, BlockTag, FieldElement, FunctionCall}, - macros::selector, - providers::Provider, -}; - -#[derive(Deserialize)] -pub struct StarknetIdQuery { - addr: FieldElement, -} - -#[route(get, "/quests/tribe/verify_three_years_expiry")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 18; - let addr = &query.addr; - - // get starkname from address - let call_result = state - .provider - .call( - FunctionCall { - contract_address: state.conf.starknetid_contracts.naming_contract, - entry_point_selector: selector!("address_to_domain"), - calldata: vec![*addr, FieldElement::ZERO], - }, - BlockId::Tag(BlockTag::Latest), - ) - .await; - - match call_result { - Ok(result) => { - let domain_len: u64 = result[0].try_into().unwrap(); - if domain_len == 1 { - // check expiry date - let expiry_result = state - .provider - .call( - FunctionCall { - contract_address: state.conf.starknetid_contracts.naming_contract, - entry_point_selector: selector!("domain_to_expiry"), - calldata: result, - }, - BlockId::Tag(BlockTag::Latest), - ) - .await; - - match expiry_result { - Ok(expiry) => { - let expiry_timestamp: u32 = expiry[0].try_into().unwrap(); - let current_timestamp = SystemTime::now() - .duration_since(UNIX_EPOCH) - .expect("Time went backwards") - .as_secs() as u32; - let delay: f32 = 86400.0 * 365.0 * 2.5; - if expiry_timestamp >= current_timestamp + delay.round() as u32 { - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => { - (StatusCode::OK, Json(json!({"res": true}))).into_response() - } - Err(e) => get_error(format!("{}", e)), - } - } else { - get_error("Expiry date is less than 3 years".to_string()) - } - } - Err(e) => get_error(format!("{}", e)), - } - } else { - get_error("Invalid domain: subdomains are not eligible".to_string()) - } - } - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/zklend/claimable.rs b/src/endpoints/quests/zklend/claimable.rs deleted file mode 100644 index 7a57a922..00000000 --- a/src/endpoints/quests/zklend/claimable.rs +++ /dev/null @@ -1,105 +0,0 @@ -use crate::models::{AppState, CompletedTaskDocument, Reward, RewardResponse}; -use crate::utils::{get_error, get_nft}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use futures::StreamExt; -use mongodb::bson::doc; -use serde::Deserialize; -use starknet::{ - core::types::FieldElement, - signers::{LocalWallet, SigningKey}, -}; -use std::sync::Arc; - -const QUEST_ID: u32 = 6; -const TASK_IDS: &[u32] = &[24, 26, 53]; -const LAST_TASK: u32 = TASK_IDS[2]; -const NFT_LEVEL: u32 = 8; - -#[derive(Deserialize)] -pub struct ClaimableQuery { - addr: FieldElement, -} - -#[route(get, "/quests/zklend/claimable")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let collection = state - .db - .collection::("completed_tasks"); - - let pipeline = vec![ - doc! { - "$match": { - "address": &query.addr.to_string(), - "task_id": { "$in": TASK_IDS }, - }, - }, - doc! { - "$lookup": { - "from": "tasks", - "localField": "task_id", - "foreignField": "id", - "as": "task", - }, - }, - doc! { - "$match": { - "task.quest_id": QUEST_ID, - }, - }, - doc! { - "$group": { - "_id": "$address", - "completed_tasks": { "$push": "$task_id" }, - }, - }, - doc! { - "$match": { - "completed_tasks": { "$all": TASK_IDS }, - }, - }, - ]; - - let completed_tasks = collection.aggregate(pipeline, None).await; - match completed_tasks { - Ok(mut tasks_cursor) => { - if tasks_cursor.next().await.is_none() { - return get_error("User hasn't completed all tasks".into()); - } - - let signer = LocalWallet::from(SigningKey::from_secret_scalar( - state.conf.nft_contract.private_key, - )); - - let mut rewards = vec![]; - - let Ok((token_id, sig)) = - get_nft(QUEST_ID, LAST_TASK, &query.addr, NFT_LEVEL, &signer).await - else { - return get_error("Signature failed".into()); - }; - - rewards.push(Reward { - task_id: LAST_TASK, - nft_contract: state.conf.nft_contract.address.clone(), - token_id: token_id.to_string(), - sig: (sig.r, sig.s), - }); - - if rewards.is_empty() { - get_error("No rewards found for this user".into()) - } else { - (StatusCode::OK, Json(RewardResponse { rewards })).into_response() - } - } - Err(_) => get_error("Error querying rewards".into()), - } -} diff --git a/src/endpoints/quests/zklend/mod.rs b/src/endpoints/quests/zklend/mod.rs deleted file mode 100644 index a36ba1d6..00000000 --- a/src/endpoints/quests/zklend/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod claimable; -pub mod verify_borrow; -pub mod verify_twitter_fw; diff --git a/src/endpoints/quests/zklend/verify_borrow.rs b/src/endpoints/quests/zklend/verify_borrow.rs deleted file mode 100644 index fe07d7c6..00000000 --- a/src/endpoints/quests/zklend/verify_borrow.rs +++ /dev/null @@ -1,55 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; -use starknet::{ - core::types::{BlockId, BlockTag, FieldElement, FunctionCall}, - macros::selector, - providers::Provider, -}; - -#[route(get, "/quests/zklend/verify_borrow")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 24; - let addr = &query.addr; - - // check if user has debt - let call_result = state - .provider - .call( - FunctionCall { - contract_address: state.conf.quests.zklend.contract, - entry_point_selector: selector!("user_has_debt"), - calldata: vec![*addr], - }, - BlockId::Tag(BlockTag::Latest), - ) - .await; - - match call_result { - Ok(result) => { - if result[0] == FieldElement::ZERO { - get_error("You didn't borrow any liquidity.".to_string()) - } else { - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } - } - } - Err(e) => get_error(format!("{}", e)), - } -} diff --git a/src/endpoints/quests/zklend/verify_twitter_fw.rs b/src/endpoints/quests/zklend/verify_twitter_fw.rs deleted file mode 100644 index 9c6eee95..00000000 --- a/src/endpoints/quests/zklend/verify_twitter_fw.rs +++ /dev/null @@ -1,30 +0,0 @@ -use std::sync::Arc; - -use crate::{ - models::{AppState, VerifyQuery}, - utils::{get_error, CompletedTasksTrait}, -}; -use axum::{ - extract::{Query, State}, - http::StatusCode, - response::IntoResponse, - Json, -}; -use axum_auto_routes::route; -use serde_json::json; -use starknet::core::types::FieldElement; - -#[route(get, "/quests/zklend/verify_twitter_fw")] -pub async fn handler( - State(state): State>, - Query(query): Query, -) -> impl IntoResponse { - let task_id = 26; - if query.addr == FieldElement::ZERO { - return get_error("Please connect your wallet first".to_string()); - } - match state.upsert_completed_task(query.addr, task_id).await { - Ok(_) => (StatusCode::OK, Json(json!({"res": true}))).into_response(), - Err(e) => get_error(format!("{}", e)), - } -}