From a275c01628284293a123bf7b288488803ed4b878 Mon Sep 17 00:00:00 2001 From: Evan <0xIchigo@protonmail.com> Date: Mon, 6 May 2024 11:08:10 -0400 Subject: [PATCH] Start Adding Webhook Functionality --- src/types/enums.rs | 43 +++++++++++++++++ src/types/types.rs | 112 ++++++++++++++++++++++++++++++++++++++++++++- src/webhook.rs | 36 +++++++++++++++ 3 files changed, 190 insertions(+), 1 deletion(-) diff --git a/src/types/enums.rs b/src/types/enums.rs index 37592c2..10c297d 100644 --- a/src/types/enums.rs +++ b/src/types/enums.rs @@ -689,3 +689,46 @@ pub enum ProgramName { #[serde(other)] Other(String), } + +#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize, Default)] +#[serde(rename_all = "lowercase")] +pub enum TransactionStatus { + #[default] + All, + Success, + Failed, +} + +#[derive(Deserialize, Serialize, Eq, PartialEq, Clone, Debug, Default)] +pub enum WebhookType { + #[serde(rename = "enhanced")] + #[default] + Enhanced, + #[serde(rename = "enhancedDevnet")] + EnhancedDevnet, + #[serde(rename = "raw")] + Raw, + #[serde(rename = "rawDevnet")] + RawDevnet, + #[serde(rename = "discord")] + Discord, + #[serde(rename = "discordDevnet")] + DiscordDevnet, +} + +#[derive(Clone, Debug, Deserialize_enum_str, Serialize_enum_str, Default, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub enum AccountWebhookEncoding { + #[default] + JsonParsed, + #[serde(other)] + Other(String), +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub enum CollectionIdentifier { + #[serde(rename = "firstVerifiedCreators")] + FirstVerifiedCreators(Vec), + #[serde(rename = "verifiedCollectionAddress")] + VerifiedCollectionAddress(Vec), +} diff --git a/src/types/types.rs b/src/types/types.rs index c480f4d..b6b8f62 100644 --- a/src/types/types.rs +++ b/src/types/types.rs @@ -1,6 +1,7 @@ use super::{ enums::{AssetSortBy, AssetSortDirection, Context, Interface, OwnershipModel, RoyaltyModel, Scope, UseMethod}, - PriorityLevel, SearchAssetsOptions, SearchConditionType, TokenType, UiTransactionEncoding, + AccountWebhookEncoding, CollectionIdentifier, PriorityLevel, SearchAssetsOptions, SearchConditionType, TokenType, + TransactionStatus, TransactionType, UiTransactionEncoding, WebhookType, }; use crate::types::{DisplayOptions, GetAssetOptions}; // use chrono::{DateTime, Utc}; @@ -863,3 +864,112 @@ pub struct PolicyEngine { pub version: u32, pub closed: bool, } + +// #[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, Default)] +// #[serde(rename_all = "camelCase")] +// pub struct Webhook { +// #[serde(flatten)] +// pub webhook_data: WebhookData, +// } + +// #[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug, Default)] +// #[serde(rename_all(serialize = "camelCase", deserialize = "camelCase"))] +// pub struct WebhookData { +// #[serde(rename = "webhookURL")] +// pub webhook_url: String, +// #[serde(skip_serializing_if = "Vec::is_empty")] +// pub transaction_types: Vec, +// pub account_addresses: Vec, +// pub webhook_type: WebhookType, +// #[serde(skip_serializing_if = "Option::is_none")] +// pub auth_header: Option, +// #[serde(default)] +// pub txn_status: TransactionStatus, +// #[serde(default)] +// pub encoding: AccountWebhookEncoding, +// } + +// #[derive(Serialize, Deserialize, Clone, Debug, Default)] +// pub struct CreateWebhookRequest { +// #[serde(flatten)] +// pub webhook_data: WebhookData, +// #[serde(rename = "webhookID")] +// pub webhook_id: String, +// pub wallet: String, +// } + +// Just completely redo the types here for all the requests and responses - shits fucking borked rn + +#[derive(Serialize, Deserialize, Clone, Debug, Default)] +#[serde(rename_all = "camelCase")] +pub struct Webhook { + #[serde(rename = "webhookID")] + pub webhook_id: String, + pub wallet: String, + pub project: String, + #[serde(rename = "webhookURL")] + pub webhook_url: String, + #[serde(skip_serializing_if = "Vec::is_empty")] + pub transaction_types: Vec, + pub account_addresses: Vec, + pub webhook_type: WebhookType, + #[serde(skip_serializing_if = "Option::is_none")] + pub auth_header: Option, + #[serde(default)] + pub txn_status: TransactionStatus, + #[serde(default)] + pub encoding: AccountWebhookEncoding, +} + +#[derive(Serialize, Deserialize, Clone, Debug, Default)] +#[serde(rename_all = "camelCase")] +pub struct CreateWebhookRequest { + #[serde(rename = "webhookURL")] + pub webhook_url: String, + #[serde(skip_serializing_if = "Vec::is_empty")] + pub transaction_types: Vec, + pub account_addresses: Vec, + pub webhook_type: WebhookType, + #[serde(skip_serializing_if = "Option::is_none")] + pub auth_header: Option, + #[serde(default)] + pub txn_status: TransactionStatus, + #[serde(default)] + pub encoding: AccountWebhookEncoding, +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +#[serde(rename_all = "camelCase")] +pub struct CreateCollectionWebhookRequest { + pub collection_query: CollectionIdentifier, + #[serde(rename = "webhookURL")] + pub webhook_url: String, + #[serde(skip_serializing_if = "Vec::is_empty")] + pub transaction_types: Vec, + pub account_addresses: Vec, + pub webhook_type: WebhookType, + #[serde(skip_serializing_if = "Option::is_none")] + pub auth_header: Option, + #[serde(default)] + pub txn_status: TransactionStatus, + #[serde(default)] + pub encoding: AccountWebhookEncoding, +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct EditWebhookRequest { + #[serde(rename = "webhookID")] + pub webhook_id: String, + #[serde(rename = "webhookURL")] + pub webhook_url: String, + #[serde(skip_serializing_if = "Vec::is_empty")] + pub transaction_types: Vec, + pub account_addresses: Vec, + pub webhook_type: WebhookType, + #[serde(skip_serializing_if = "Option::is_none")] + pub auth_header: Option, + #[serde(default)] + pub txn_status: TransactionStatus, + #[serde(default)] + pub encoding: AccountWebhookEncoding, +} diff --git a/src/webhook.rs b/src/webhook.rs index 8b13789..45f2717 100644 --- a/src/webhook.rs +++ b/src/webhook.rs @@ -1 +1,37 @@ +use crate::error::Result; +use crate::types::{CreateWebhookRequest, EditWebhookRequest, Webhook}; +use crate::Helius; +use reqwest::{Method, Url}; + +impl Helius { + /// Creates a webhook given account addresses, + pub async fn create_webhook(&self, request: CreateWebhookRequest) -> Result { + let url: String = format!( + "{}v0/webhooks/?api-key={}", + self.config.endpoints.api, self.config.api_key + ); + + let parsed_url: Url = Url::parse(&url).expect("Failed to parse URL"); + println!("PARSED URL: {}", parsed_url); + + self.rpc_client + .handler + .send(Method::POST, parsed_url, Some(&request)) + .await + } + + /// Edits a Helius webhook programmatically + pub async fn edit_webhook(&self, request: EditWebhookRequest) -> Result { + let url: String = format!( + "{}v0/webhooks/{}/?api-key={}", + self.config.endpoints.api, request.webhook_id, self.config.api_key + ); + let parsed_url: Url = Url::parse(&url).expect("Failed to parse URL"); + + self.rpc_client + .handler + .send(Method::PUT, parsed_url, Some(&request)) + .await + } +}