From 0c48cc87d9e76c5a6fd30492d5ec72b3b3ff4af0 Mon Sep 17 00:00:00 2001 From: Milad Nekofar Date: Thu, 19 Oct 2023 12:08:35 +0330 Subject: [PATCH 1/4] refactor: add `warpcast_url` to `FarcasterHandler` in all modules The warpcast_url field was added to the FarcasterHandler structure in all modules to provide flexibility in API interactions. This change allows the warpcast API base URL to be sourced from environment variables, rather than being hardcoded as previously. This improves the code's ability to adapt to future changes and enhances its structure and maintainability." fixup! refactor: add `warpcast_url` to `FarcasterHandler` in all modules --- src/lil_nouns/handler/farcaster.rs | 7 ++++++- src/meta_gov/handler/farcaster.rs | 11 ++++++++--- src/prop_house/handler/farcaster.rs | 16 +++++++++++++--- src/prop_lot/handler/farcaster.rs | 11 ++++++++--- wrangler.toml | 6 ++++++ 5 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/lil_nouns/handler/farcaster.rs b/src/lil_nouns/handler/farcaster.rs index 3685eea..b06847b 100644 --- a/src/lil_nouns/handler/farcaster.rs +++ b/src/lil_nouns/handler/farcaster.rs @@ -18,6 +18,7 @@ use crate::{ pub(crate) struct FarcasterHandler { base_url: String, + warpcast_url: String, bearer_token: String, channel_key: String, cache: Cache, @@ -28,6 +29,7 @@ pub(crate) struct FarcasterHandler { impl FarcasterHandler { pub fn new( base_url: String, + warpcast_url: String, bearer_token: String, channel_key: String, cache: Cache, @@ -36,6 +38,7 @@ impl FarcasterHandler { ) -> Self { Self { base_url, + warpcast_url, bearer_token, channel_key, cache, @@ -46,6 +49,7 @@ impl FarcasterHandler { pub fn new_from_env(env: &Env) -> Result { let base_url = env.var("LIL_NOUNS_BASE_URL")?.to_string(); + let warpcast_url = env.var("WARP_CAST_API_BASE_URL")?.to_string(); let bearer_token = env.secret("LIL_NOUNS_WARP_CAST_TOKEN")?.to_string(); let channel_key = env.var("LIL_NOUNS_WARP_CAST_CHANNEL")?.to_string(); @@ -55,6 +59,7 @@ impl FarcasterHandler { Ok(Self::new( base_url, + warpcast_url, bearer_token, channel_key, cache, @@ -64,7 +69,7 @@ impl FarcasterHandler { } async fn make_http_request(&self, request_data: Value) -> Result { - let url = "https://api.warpcast.com/v2/casts"; + let url = format!("{}/casts", self.warpcast_url); let token = format!("Bearer {}", self.bearer_token); let mut headers = HeaderMap::new(); diff --git a/src/meta_gov/handler/farcaster.rs b/src/meta_gov/handler/farcaster.rs index 8676086..c5fccd7 100644 --- a/src/meta_gov/handler/farcaster.rs +++ b/src/meta_gov/handler/farcaster.rs @@ -17,8 +17,9 @@ use crate::{ utils::{ens::get_wallet_handle, link::Link}, }; -pub struct FarcasterHandler { +pub(crate) struct FarcasterHandler { base_url: String, + warpcast_url: String, bearer_token: String, channel_key: String, cache: Cache, @@ -29,6 +30,7 @@ pub struct FarcasterHandler { impl FarcasterHandler { pub fn new( base_url: String, + warpcast_url: String, bearer_token: String, channel_key: String, cache: Cache, @@ -37,6 +39,7 @@ impl FarcasterHandler { ) -> Self { Self { base_url, + warpcast_url, bearer_token, channel_key, cache, @@ -47,8 +50,9 @@ impl FarcasterHandler { pub fn new_from_env(env: &Env) -> Result { let base_url = env.var("META_GOV_BASE_URL")?.to_string(); + let warpcast_url = env.var("WARP_CAST_API_BASE_URL")?.to_string(); let bearer_token = env.secret("META_GOV_WARP_CAST_TOKEN")?.to_string(); - let channel_key = env.secret("META_GOV_WARP_CAST_CHANNEL")?.to_string(); + let channel_key = env.var("META_GOV_WARP_CAST_CHANNEL")?.to_string(); let cache = Cache::new_from_env(env); let client = Client::new(); @@ -56,6 +60,7 @@ impl FarcasterHandler { Ok(Self::new( base_url, + warpcast_url, bearer_token, channel_key, cache, @@ -65,7 +70,7 @@ impl FarcasterHandler { } async fn make_http_request(&self, request_data: Value) -> Result { - let url = "https://api.warpcast.com/v2/casts"; + let url = format!("{}/casts", self.warpcast_url); let token = format!("Bearer {}", self.bearer_token); let mut headers = HeaderMap::new(); diff --git a/src/prop_house/handler/farcaster.rs b/src/prop_house/handler/farcaster.rs index dd75332..7c96c48 100644 --- a/src/prop_house/handler/farcaster.rs +++ b/src/prop_house/handler/farcaster.rs @@ -13,53 +13,63 @@ use worker::{Env, Error, Result}; use crate::{ cache::Cache, prop_house::{handler::Handler, Auction, Proposal, Vote}, - utils::ens::get_wallet_handle, + utils::{ens::get_wallet_handle, link::Link}, }; -pub struct FarcasterHandler { +pub(crate) struct FarcasterHandler { base_url: String, + warpcast_url: String, bearer_token: String, channel_key: String, cache: Cache, client: Client, + link: Link, } impl FarcasterHandler { pub fn new( base_url: String, + warpcast_url: String, bearer_token: String, channel_key: String, cache: Cache, client: Client, + link: Link, ) -> Self { Self { base_url, + warpcast_url, bearer_token, channel_key, cache, client, + link, } } pub fn new_from_env(env: &Env) -> Result { let base_url = env.var("PROP_HOUSE_BASE_URL")?.to_string(); + let warpcast_url = env.var("WARP_CAST_API_BASE_URL")?.to_string(); let bearer_token = env.secret("PROP_HOUSE_WARP_CAST_TOKEN")?.to_string(); let channel_key = env.var("PROP_HOUSE_WARP_CAST_CHANNEL")?.to_string(); let cache = Cache::new_from_env(env); let client = Client::new(); + let link = Link::new_from_env(&env); Ok(Self::new( base_url, + warpcast_url, bearer_token, channel_key, cache, client, + link, )) } async fn make_http_request(&self, request_data: Value) -> Result { - let url = "https://api.warpcast.com/v2/casts"; + let url = format!("{}/casts", self.warpcast_url); let token = format!("Bearer {}", self.bearer_token); let mut headers = HeaderMap::new(); diff --git a/src/prop_lot/handler/farcaster.rs b/src/prop_lot/handler/farcaster.rs index 8f13688..8ecdca4 100644 --- a/src/prop_lot/handler/farcaster.rs +++ b/src/prop_lot/handler/farcaster.rs @@ -18,18 +18,20 @@ use crate::{ utils::ens::get_wallet_handle, }; -pub struct FarcasterHandler { +pub(crate) struct FarcasterHandler { base_url: String, + warpcast_url: String, bearer_token: String, channel_key: String, cache: Cache, client: Client, - pub link: Link, + link: Link, } impl FarcasterHandler { pub fn new( base_url: String, + warpcast_url: String, bearer_token: String, channel_key: String, cache: Cache, @@ -38,6 +40,7 @@ impl FarcasterHandler { ) -> Self { Self { base_url, + warpcast_url, bearer_token, channel_key, cache, @@ -48,6 +51,7 @@ impl FarcasterHandler { pub fn new_from_env(env: &Env) -> Result { let base_url = env.var("PROP_LOT_BASE_URL")?.to_string(); + let warpcast_url = env.var("WARP_CAST_API_BASE_URL")?.to_string(); let bearer_token = env.secret("PROP_LOT_WARP_CAST_TOKEN")?.to_string(); let channel_key = env.var("PROP_LOT_WARP_CAST_CHANNEL")?.to_string(); @@ -57,6 +61,7 @@ impl FarcasterHandler { Ok(Self::new( base_url, + warpcast_url, bearer_token, channel_key, cache, @@ -66,7 +71,7 @@ impl FarcasterHandler { } async fn make_http_request(&self, request_data: Value) -> Result { - let url = "https://api.warpcast.com/v2/casts"; + let url = format!("{}/casts", self.warpcast_url); let token = format!("Bearer {}", self.bearer_token); let mut headers = HeaderMap::new(); diff --git a/wrangler.toml b/wrangler.toml index d7e2155..97a10b1 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -29,6 +29,9 @@ ETHEREUM_MAINNET_RPC_URL = "https://eth.llamarpc.com" # Link Generator Settings LINK_GENERATOR_ENDPOINT = "https://lilnouns.click" +# Warpccast API Settings +WARP_CAST_API_BASE_URL = "https://api.warpcast.com/v2" + # Lil Nouns Settings LIL_NOUNS_ENABLED = "false" LIL_NOUNS_DISCORD_ENABLED = "true" @@ -82,6 +85,9 @@ ETHEREUM_MAINNET_RPC_URL = "https://eth.llamarpc.com" # Link Generator Settings LINK_GENERATOR_ENDPOINT = "https://lilnouns.click" +# Warpccast API Settings +WARP_CAST_API_BASE_URL = "https://api.warpcast.com/v2" + # Lil Nouns Settings LIL_NOUNS_ENABLED = "true" LIL_NOUNS_DISCORD_ENABLED = "true" From 40e8320864e31afb1ca852075ab6523bde0a20b4 Mon Sep 17 00:00:00 2001 From: Milad Nekofar Date: Thu, 19 Oct 2023 14:34:38 +0330 Subject: [PATCH 2/4] refactor: extract proposal logic in meta gov farcaster The logic to extract proposal information in farcaster.rs has been refactored. Previously, the extract_proposal_info method was called within a match statement, making error handling cumbersome and the flow control difficult to follow. Now, the function call and error handling have been streamlined, improving readability and maintainability of the code. --- src/meta_gov/handler/farcaster.rs | 186 ++++++++++++++---------------- 1 file changed, 88 insertions(+), 98 deletions(-) diff --git a/src/meta_gov/handler/farcaster.rs b/src/meta_gov/handler/farcaster.rs index c5fccd7..c44444c 100644 --- a/src/meta_gov/handler/farcaster.rs +++ b/src/meta_gov/handler/farcaster.rs @@ -120,68 +120,63 @@ impl FarcasterHandler { #[async_trait(? Send)] impl Handler for FarcasterHandler { async fn handle_new_proposal(&self, proposal: &Proposal) -> Result<()> { - match self.extract_proposal_info(proposal.clone()).await { - Ok((proposal_id, proposal_title)) => { - info!("Handling new proposal: {}", proposal_title); - - let url = &self - .link - .generate(format!("{}/{}", self.base_url, proposal_id)) - .await - .unwrap_or_else(|_| format!("{}/{}", self.base_url, proposal_id)); - - let description = format!( - "A new Meta Gov proposal has been created: “{}”", - proposal_title - ); - - let request_data = json!({ - "text": description, - "embeds": [url], - "channelKey": self.channel_key - }); - - let response = self.make_http_request(request_data).await.map_err(|e| { - error!("Failed to make HTTP request: {}", e); - return e; - })?; - - let response_body = response.text().await.map_err(|e| { - error!("Failed to get text from response: {}", e); - Error::from(format!("Failed to get text from response: {}", e)) - })?; - - let parsed_body: serde_json::Result = serde_json::from_str(&response_body); - - let response_body: Value = match parsed_body { - Ok(body) => body, - Err(e) => { - error!("Failed to parse JSON: {}", e); - return Err(e.into()); - } - }; - - let cast_hash = response_body["result"]["cast"]["hash"] - .as_str() - .unwrap_or_default(); - - let mut proposals_casts = self - .cache - .get::>("meta_gov:proposals:casts") - .await? - .unwrap_or_default(); - - proposals_casts.insert(proposal_id, cast_hash.to_string()); - - self - .cache - .put("meta_gov:proposals:casts", &proposals_casts) - .await; - } + let (proposal_id, proposal_title) = self.extract_proposal_info(proposal.clone()).await?; + + info!("Handling new proposal: {}", proposal_title); + + let url = &self + .link + .generate(format!("{}/{}", self.base_url, proposal_id)) + .await + .unwrap_or_else(|_| format!("{}/{}", self.base_url, proposal_id)); + + let description = format!( + "A new Meta Gov proposal has been created: “{}”", + proposal_title + ); + + let request_data = json!({ + "text": description, + "embeds": [url], + "channelKey": self.channel_key + }); + + let response = self.make_http_request(request_data).await.map_err(|e| { + error!("Failed to make HTTP request: {}", e); + return e; + })?; + + let response_body = response.text().await.map_err(|e| { + error!("Failed to get text from response: {}", e); + Error::from(format!("Failed to get text from response: {}", e)) + })?; + + let parsed_body: serde_json::Result = serde_json::from_str(&response_body); + + let response_body: Value = match parsed_body { + Ok(body) => body, Err(e) => { - error!("Failed to extract proposal info: {}", e); + error!("Failed to parse JSON: {}", e); + return Err(e.into()); } - } + }; + + let cast_hash = response_body["result"]["cast"]["hash"] + .as_str() + .unwrap_or_default(); + + let mut proposals_casts = self + .cache + .get::>("meta_gov:proposals:casts") + .await? + .unwrap_or_default(); + + proposals_casts.insert(proposal_id, cast_hash.to_string()); + + self + .cache + .put("meta_gov:proposals:casts", &proposals_casts) + .await; Ok(()) } @@ -201,44 +196,39 @@ impl Handler for FarcasterHandler { .clone() .ok_or("Proposal not found in the funding list.")?; - match self.extract_proposal_info(proposal.clone()).await { - Ok((proposal_id, proposal_title)) => { - let proposals_casts = self - .cache - .get::>("meta_gov:proposals:casts") - .await? - .unwrap_or_default(); - - let cast_hash = proposals_casts - .get(&proposal_id) - .ok_or("Cast hash not found")?; - - let wallet = get_wallet_handle(&vote.voter, "xyz.farcaster").await; - - let description = format!( - "{} has voted {} “{}” proposal.", - wallet, - match vote.choice { - 1 => "for", - 2 => "against", - 3 => "abstain on", - _ => "unknown", - }, - proposal_title - ); - - let request_data = json!({ - "text": description, - "channelKey": self.channel_key, - "parent": {"hash": cast_hash}, - }); - - self.make_http_request(request_data).await?; - } - Err(e) => { - error!("Failed to extract proposal info: {}", e); - } - } + let (proposal_id, proposal_title) = self.extract_proposal_info(proposal.clone()).await?; + + let proposals_casts = self + .cache + .get::>("meta_gov:proposals:casts") + .await? + .unwrap_or_default(); + + let cast_hash = proposals_casts + .get(&proposal_id) + .ok_or("Cast hash not found")?; + + let wallet = get_wallet_handle(&vote.voter, "xyz.farcaster").await; + + let description = format!( + "{} has voted {} “{}” proposal.", + wallet, + match vote.choice { + 1 => "for", + 2 => "against", + 3 => "abstain on", + _ => "unknown", + }, + proposal_title + ); + + let request_data = json!({ + "text": description, + "channelKey": self.channel_key, + "parent": {"hash": cast_hash}, + }); + + self.make_http_request(request_data).await?; Ok(()) } From fd8c152b84bb40c96cfbf281c2764d07d981f513 Mon Sep 17 00:00:00 2001 From: Milad Nekofar Date: Thu, 19 Oct 2023 17:52:51 +0330 Subject: [PATCH 3/4] chore: update warpcast channel for meta gov to nouns The earlier absence of Warp Cast Channel information was causing operational issues. The field has now been set to "nouns" in wrangler.toml file to ensure smooth functioning. --- wrangler.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wrangler.toml b/wrangler.toml index 97a10b1..ad25c42 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -103,7 +103,7 @@ META_GOV_FARCASTER_ENABLED = "true" META_GOV_BASE_URL = "https://lilnouns.wtf/vote/nounsdao" META_GOV_SNAPSHOT_GRAPHQL_URL = "https://hub.snapshot.org/graphql" META_GOV_SNAPSHOT_SPACE_ID = "leagueoflils.eth" -META_GOV_WARP_CAST_CHANNEL = "" +META_GOV_WARP_CAST_CHANNEL = "nouns" # Prop House Settings PROP_HOUSE_ENABLED = "true" From ea12e44f2fafb675b357a36ef85a5396e14316bd Mon Sep 17 00:00:00 2001 From: Milad Nekofar Date: Thu, 19 Oct 2023 17:55:01 +0330 Subject: [PATCH 4/4] chore(release): prepare for version 1.1.0-alpha.0 --- CHANGELOG.md | 11 +++++++++++ Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a423ad1..ba868be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ All notable changes to this project will be documented in this file. +## [1.1.0-alpha.0] - 2023-10-19 + +### Refactor + +- Add `warpcast_url` to `FarcasterHandler` in all modules +- Extract proposal logic in meta gov farcaster + +### Miscellaneous Tasks + +- Update warpcast channel for meta gov to nouns + ## [1.0.4-alpha.0] - 2023-10-18 ### Refactor diff --git a/Cargo.lock b/Cargo.lock index f3a82d9..6e63f64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1553,7 +1553,7 @@ checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "lilnouns-bots" -version = "1.0.4-alpha.0" +version = "1.1.0-alpha.0" dependencies = [ "anyhow", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index bd6eed1..53df3b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lilnouns-bots" -version = "1.0.4-alpha.0" +version = "1.1.0-alpha.0" authors = ["Milad Nekofar "] edition = "2021" description = "Our bots are designed to keep the Lil Nouns DAO community informed and engaged."