use super::WebhookType;
use crate::{
cores::endpoint::Endpoint,
types::{chain::AlchemyChain, common::NftFilter},
};
use derive_builder::Builder;
use ethers_core::types::Address;
use http::Method;
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, skip_serializing_none};
#[serde_as]
#[skip_serializing_none]
#[derive(Builder, Default, Debug, Clone, Serialize, Deserialize)]
#[builder(setter(into, strip_option), build_fn(validate = "Self::validate"))]
pub struct CreateWebhook {
#[builder(setter(skip))]
network: AlchemyChain,
#[builder(setter)]
webhook_type: WebhookType,
#[builder(setter)]
webhook_url: String,
#[builder(default)]
app_id: Option<String>,
#[builder(default)]
addresses: Vec<Address>,
#[builder(default)]
nft_filters: Option<Vec<NftFilter>>,
#[builder(default)]
nft_metadata_filters: Option<Vec<NftFilter>>,
}
impl CreateWebhook {
pub fn builder() -> CreateWebhookBuilder {
CreateWebhookBuilder::default()
}
}
impl CreateWebhookBuilder {
fn validate(&self) -> Result<(), String> {
if let Some(whtype) = self.webhook_type {
match whtype {
WebhookType::MinedTransaction | WebhookType::DroppedTransaction
if self.app_id.is_none() =>
{
Err("app_id is required for mined and dropped webhooks".to_string())
}
WebhookType::AddressActivity
if self.addresses.is_none() || self.addresses.as_ref().unwrap().is_empty() =>
{
Err("addresses is required for address activity webhooks".to_string())
}
_ => Ok(()),
}
} else {
Err("webhook_type is required".to_string())
}
}
}
impl Endpoint for CreateWebhook {
fn method(&self) -> http::Method {
Method::POST
}
fn endpoint(&self) -> std::borrow::Cow<'static, str> {
"api/create-webhook".into()
}
fn body(&self) -> anyhow::Result<Option<(&'static str, Vec<u8>)>> {
let body = serde_json::to_vec(self)?;
Ok(Some(("application/json", body)))
}
}