From 2f7b290065b080338ca26db291826ed65f8f9d2e Mon Sep 17 00:00:00 2001 From: Douglas Chimento Date: Mon, 19 Feb 2024 12:58:02 +0200 Subject: [PATCH] adding more tests for proof assets --- Cargo.toml | 2 +- README.md | 2 +- codecov.yml | 1 + examples/create_webhook.rs | 10 +++++- examples/delete_webhooks.rs | 10 +++++- examples/get_assets.rs | 10 ++++++ examples/get_webhooks.rs | 10 +++++- src/api/mod.rs | 25 +++++++++---- src/api/webhook.rs | 4 +-- src/lib.rs | 72 +++++++++++++++++++++++-------------- src/util.rs | 26 +++++++++----- 11 files changed, 125 insertions(+), 47 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5d2c62f..c0f9e32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "selene-helius-sdk" -version = "0.1.0-beta.3" +version = "0.1.0-beta.4" edition = "2021" authors = ["dougefresh "] description = "Rust implementation of the Helius API & RPC" diff --git a/README.md b/README.md index 12feec6..a130f61 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ API reference documentation is available at [docs.helius.dev](https://docs.heliu | [get-webhook](https://docs.helius.dev/webhooks-and-websockets/api-reference/get-webhook) | ✓ | | [edit-webhook](https://docs.helius.dev/webhooks-and-websockets/api-reference/edit-webhook) | ✓ | | [delete-webhook](https://docs.helius.dev/webhooks-and-websockets/api-reference/delete-webhook) | ✓ | -| [appendAddressesToWebhook](https://docs.helius.dev/webhooks-and-websockets) | ✗ | +| [appendAddressesToWebhook](https://docs.helius.dev/webhooks-and-websockets) | ✓ | ### Mint API diff --git a/codecov.yml b/codecov.yml index 67387b3..d4d52c9 100644 --- a/codecov.yml +++ b/codecov.yml @@ -8,3 +8,4 @@ coverage: # https://docs.codecov.com/docs/codecovyml-reference#coverage threshold: 1% # Avoid false negatives ignore: - "examples" + - "src/error.rs" \ No newline at end of file diff --git a/examples/create_webhook.rs b/examples/create_webhook.rs index 0e57c9c..c46e6a0 100644 --- a/examples/create_webhook.rs +++ b/examples/create_webhook.rs @@ -3,9 +3,17 @@ use color_eyre::eyre::format_err; use color_eyre::Result; use selene_helius_sdk::api::types::{AccountWebhookEncoding, TxnStatus}; use selene_helius_sdk::api::webhook::{CreateWebhookRequest, WebhookData, WebhookType}; -use selene_helius_sdk::util::init_tracing; use selene_helius_sdk::{Cluster, HeliusBuilder}; use std::env; +use tracing_subscriber::EnvFilter; + +fn init_tracing() -> Result<()> { + color_eyre::install()?; + let filter = EnvFilter::from_default_env(); + let subscriber = tracing_subscriber::FmtSubscriber::builder().with_env_filter(filter).with_target(true).finish(); + tracing::subscriber::set_global_default(subscriber)?; + Ok(()) +} // get a webhook from https://webhook.site/ // cargo run --example --
... diff --git a/examples/delete_webhooks.rs b/examples/delete_webhooks.rs index e26fdbc..14a101e 100644 --- a/examples/delete_webhooks.rs +++ b/examples/delete_webhooks.rs @@ -1,8 +1,16 @@ extern crate selene_helius_sdk; use color_eyre::Result; use selene_helius_sdk::api::webhook::Webhook; -use selene_helius_sdk::util::init_tracing; use selene_helius_sdk::{Cluster, HeliusBuilder}; +use tracing_subscriber::EnvFilter; + +fn init_tracing() -> Result<()> { + color_eyre::install()?; + let filter = EnvFilter::from_default_env(); + let subscriber = tracing_subscriber::FmtSubscriber::builder().with_env_filter(filter).with_target(true).finish(); + tracing::subscriber::set_global_default(subscriber)?; + Ok(()) +} // delete webhook from https://webhook.site/ #[tokio::main] diff --git a/examples/get_assets.rs b/examples/get_assets.rs index 9e4ab9e..6fcadea 100644 --- a/examples/get_assets.rs +++ b/examples/get_assets.rs @@ -2,10 +2,20 @@ extern crate selene_helius_sdk; use color_eyre::Result; use selene_helius_sdk::api::das::{GetAssetsByOwnerParams, Pagination}; use selene_helius_sdk::HeliusBuilder; +use tracing_subscriber::EnvFilter; + +fn init_tracing() -> Result<()> { + color_eyre::install()?; + let filter = EnvFilter::from_default_env(); + let subscriber = tracing_subscriber::FmtSubscriber::builder().with_env_filter(filter).with_target(true).finish(); + tracing::subscriber::set_global_default(subscriber)?; + Ok(()) +} #[tokio::main] async fn main() -> Result<()> { let api_key = std::env::var("HELIUS_API_KEY").expect("env HELIUS_API_KEY is not defined!"); + init_tracing()?; let helius = HeliusBuilder::new(&api_key).build()?; let result = helius .get_assets_by_owner(&GetAssetsByOwnerParams { diff --git a/examples/get_webhooks.rs b/examples/get_webhooks.rs index bbd1c67..75ee7f5 100644 --- a/examples/get_webhooks.rs +++ b/examples/get_webhooks.rs @@ -1,8 +1,16 @@ extern crate selene_helius_sdk; use color_eyre::Result; use selene_helius_sdk::api::webhook::Webhook; -use selene_helius_sdk::util::init_tracing; use selene_helius_sdk::{Cluster, HeliusBuilder}; +use tracing_subscriber::EnvFilter; + +fn init_tracing() -> Result<()> { + color_eyre::install()?; + let filter = EnvFilter::from_default_env(); + let subscriber = tracing_subscriber::FmtSubscriber::builder().with_env_filter(filter).with_target(true).finish(); + tracing::subscriber::set_global_default(subscriber)?; + Ok(()) +} #[tokio::main] async fn main() -> Result<()> { diff --git a/src/api/mod.rs b/src/api/mod.rs index ef94c9f..69d130b 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -107,12 +107,6 @@ impl HeliusBuilder { } impl Helius { - pub fn new(api_key: &str, cluster: Cluster, client: reqwest::Client) -> Self { - let endpoint = rpc_url_from_cluster(api_key, cluster); - let connection = RpcClient::new(endpoint); - Self { api_key: String::from(api_key), cluster, rpc: Arc::new(connection), handler: RequestHandler::new(client) } - } - #[must_use] pub fn connection(&self) -> &RpcClient { &self.rpc @@ -135,3 +129,22 @@ impl Helius { Url::parse(&u).map_err(std::convert::Into::into) } } + +#[cfg(test)] +mod tests { + use crate::Cluster::Devnet; + use crate::HeliusBuilder; + use std::time::Duration; + + #[test] + fn helius_builder() { + let helius = HeliusBuilder::new("something") + .cluster(Devnet) + .connect_timeout(Duration::from_secs(1)) + .timeout(Duration::from_secs(1)) + .http_client(reqwest::Client::new()) + .build() + .expect("failed to create client"); + assert_eq!(helius.cluster, Devnet); + } +} diff --git a/src/api/webhook.rs b/src/api/webhook.rs index 201102f..fb98862 100644 --- a/src/api/webhook.rs +++ b/src/api/webhook.rs @@ -44,9 +44,9 @@ impl Helius { /// # Errors /// /// Will return `HeliusError` - pub async fn append_addresses_to_webhook(&self, webhook_id: &str, new_addresses: Vec) -> Result { + pub async fn append_addresses_to_webhook(&self, webhook_id: &str, new_addresses: &[String]) -> Result { let mut webhook = self.get_webhook_by_id(webhook_id).await?; - webhook.webhook_data.account_addresses.extend(new_addresses); + webhook.webhook_data.account_addresses.extend(new_addresses.to_vec()); let edit_request = EditWebhookRequest { webhook_id: webhook_id.to_string(), data: webhook.webhook_data }; self.edit_webhook(&edit_request).await } diff --git a/src/lib.rs b/src/lib.rs index fa93d1f..0df462a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,7 @@ pub type Result = std::result::Result; pub use api::{Helius, HeliusBuilder}; use serde::Serialize; -#[derive(Clone, Copy, Default, Serialize)] +#[derive(Clone, Copy, Default, Serialize, PartialEq, Eq, Debug)] pub enum Cluster { #[default] MainnetBeta, @@ -19,15 +19,14 @@ pub enum Cluster { #[allow(clippy::unwrap_used)] mod tests { use crate::api::das::{ - DisplayOptions, GetAssetBatchParams, GetAssetParams, GetAssetsByAuthorityParams, GetAssetsByCreatorParams, - GetAssetsByOwnerParams, Pagination, SearchAssetsParams, + DisplayOptions, GetAssetBatchParams, GetAssetParams, GetAssetProofBatchParams, GetAssetProofParams, + GetAssetsByAuthorityParams, GetAssetsByCreatorParams, GetAssetsByOwnerParams, Pagination, SearchAssetsParams, }; use crate::api::types::enhanced::ParseTransactionsRequest; use crate::api::types::{AccountWebhookEncoding, TokenType, TransactionType, TxnStatus}; use crate::api::webhook::{CreateWebhookRequest, EditWebhookRequest, WebhookData, WebhookType}; use crate::api::{Helius, HeliusBuilder}; use color_eyre::eyre::format_err; - use once_cell::sync::OnceCell; use solana_client::rpc_config::RpcBlockConfig; use solana_sdk::clock::Slot; use solana_sdk::commitment_config::CommitmentConfig; @@ -36,10 +35,9 @@ mod tests { use std::env; use std::sync::Once; use std::time::Duration; - use tracing::{error, info}; + use tracing::info; use tracing_subscriber::EnvFilter; static INIT: Once = Once::new(); - static INSTANCE: OnceCell = OnceCell::new(); fn setup() { INIT.call_once(|| { @@ -48,18 +46,13 @@ mod tests { let filter = EnvFilter::from_default_env(); let subscriber = tracing_subscriber::FmtSubscriber::builder().with_env_filter(filter).with_target(true).finish(); tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed"); - if INSTANCE.set(Config::new()).is_err() { - error!("failed to set test Config"); - } else { - info!("config setup"); - } }); } #[rstest::fixture] - fn config() -> &'static Config { + fn config() -> Config { setup(); - INSTANCE.get().unwrap() + Config::new() } struct Config { @@ -87,7 +80,7 @@ mod tests { #[rstest::rstest] #[tokio::test] #[allow(clippy::unwrap_used)] - async fn test_enhanced_txn(config: &Config) -> color_eyre::Result<()> { + async fn test_enhanced_txn(config: Config) -> color_eyre::Result<()> { if config.client.is_none() { return Ok(()); } @@ -126,7 +119,7 @@ mod tests { #[rstest::rstest] #[tokio::test] - async fn webhook(config: &Config) -> color_eyre::Result<()> { + async fn webhook(config: Config) -> color_eyre::Result<()> { if config.client.is_none() { return Ok(()); } @@ -153,20 +146,23 @@ mod tests { let hooks = client.get_all_webhooks().await?.len(); if hooks != current_hooks.len() + 1 { client.delete_webhook(&hook.webhook_id).await?; - return Err(color_eyre::eyre::format_err!("hook not created")); + return Err(format_err!("hook not created")); } let mut hooky = client.get_webhook_by_id(hook.webhook_id.as_str()).await?; hooky.webhook_data.transaction_types.push(TransactionType::Fuse); let edited_hook = client .edit_webhook(&EditWebhookRequest { webhook_id: hooky.webhook_id.clone(), data: hooky.webhook_data }) .await?; + + let add_addr = vec!["AKo9P7S8FE9NYeAcrtZEpimwQAXJMp8Lrt8p4dMkHkY2".to_owned()]; + client.append_addresses_to_webhook(&hooky.webhook_id, &add_addr).await?; client.delete_webhook(&edited_hook.webhook_id).await?; Ok(()) } #[rstest::rstest] #[tokio::test] - async fn test_get_names(config: &Config) -> color_eyre::Result<()> { + async fn test_get_names(config: Config) -> color_eyre::Result<()> { if config.client.is_none() { return Ok(()); } @@ -180,7 +176,7 @@ mod tests { #[rstest::rstest] #[tokio::test] - async fn test_get_asset_nft(config: &Config) -> color_eyre::Result<()> { + async fn test_get_asset_nft(config: Config) -> color_eyre::Result<()> { if config.client.is_none() { return Ok(()); } @@ -193,7 +189,7 @@ mod tests { #[rstest::rstest] #[tokio::test] - async fn get_asset_fungible(config: &Config) -> color_eyre::Result<()> { + async fn get_asset_fungible(config: Config) -> color_eyre::Result<()> { if config.client.is_none() { return Ok(()); } @@ -207,7 +203,7 @@ mod tests { #[rstest::rstest] #[tokio::test] - async fn get_asset_inscription(config: &Config) -> color_eyre::Result<()> { + async fn get_asset_inscription(config: Config) -> color_eyre::Result<()> { if config.client.is_none() { return Ok(()); } @@ -221,7 +217,7 @@ mod tests { #[rstest::rstest] #[tokio::test] - async fn get_asset_batch(config: &Config) -> color_eyre::Result<()> { + async fn get_asset_batch(config: Config) -> color_eyre::Result<()> { if config.client.is_none() { return Ok(()); } @@ -238,7 +234,7 @@ mod tests { #[rstest::rstest] #[tokio::test] - async fn get_asset_by_owner(config: &Config) -> color_eyre::Result<()> { + async fn get_asset_by_owner(config: Config) -> color_eyre::Result<()> { if config.client.is_none() { return Ok(()); } @@ -259,7 +255,7 @@ mod tests { #[rstest::rstest] #[tokio::test] - async fn asset_by_authority(config: &Config) -> color_eyre::Result<()> { + async fn asset_by_authority(config: Config) -> color_eyre::Result<()> { if config.client.is_none() { return Ok(()); } @@ -278,7 +274,7 @@ mod tests { #[rstest::rstest] #[tokio::test] - async fn get_asset_by_creator(config: &Config) -> color_eyre::Result<()> { + async fn get_asset_by_creator(config: Config) -> color_eyre::Result<()> { if config.client.is_none() { return Ok(()); } @@ -299,7 +295,7 @@ mod tests { #[rstest::rstest] #[tokio::test] - async fn search_asset(config: &Config) -> color_eyre::Result<()> { + async fn search_asset(config: Config) -> color_eyre::Result<()> { if config.client.is_none() { return Ok(()); } @@ -320,9 +316,33 @@ mod tests { Ok(()) } + #[rstest::rstest] + #[tokio::test] + async fn asset_proof(config: Config) -> color_eyre::Result<()> { + if config.client.is_none() { + return Ok(()); + } + let client = config.client(); + let rando = String::from("Bu1DEKeawy7txbnCEJE4BU3BKLXaNAKCYcHR4XhndGss"); + client.get_asset_proof(&GetAssetProofParams { id: rando }).await?; + Ok(()) + } + + #[rstest::rstest] + #[tokio::test] + async fn asset_proof_batch(config: Config) -> color_eyre::Result<()> { + if config.client.is_none() { + return Ok(()); + } + let client = config.client(); + let rando = String::from("Bu1DEKeawy7txbnCEJE4BU3BKLXaNAKCYcHR4XhndGss"); + client.get_asset_proof_batch(&GetAssetProofBatchParams { ids: vec![rando] }).await?; + Ok(()) + } + #[rstest::rstest] #[test] - fn check_ci(config: &Config) -> color_eyre::Result<()> { + fn check_ci(config: Config) -> color_eyre::Result<()> { match env::var("CI") { Err(_) => Ok(()), Ok(_) => match config.client { diff --git a/src/util.rs b/src/util.rs index 6f06015..c3873d4 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,7 +1,6 @@ use serde::de::Error as SerdeError; use serde::{Deserialize, Deserializer}; use serde_json::{Number, Value}; -use tracing_subscriber::EnvFilter; pub(crate) fn deserialize_str_to_number<'de, D>(deserializer: D) -> Result where @@ -15,11 +14,22 @@ where } } -#[allow(dead_code, clippy::missing_errors_doc)] -pub fn init_tracing() -> color_eyre::Result<()> { - color_eyre::install()?; - let filter = EnvFilter::from_default_env(); - let subscriber = tracing_subscriber::FmtSubscriber::builder().with_env_filter(filter).with_target(true).finish(); - tracing::subscriber::set_global_default(subscriber)?; - Ok(()) +#[cfg(test)] +mod tests { + use crate::util::deserialize_str_to_number; + use serde::Deserialize; + use serde_json::Number; + + #[derive(Deserialize, Debug)] + struct Blah { + #[serde(deserialize_with = "deserialize_str_to_number")] + num_str: Number, + } + + #[test] + fn str_to_number() -> color_eyre::Result<()> { + let blah: Blah = serde_json::from_str(r#"{"num_str": 2 }"#)?; + assert_eq!(blah.num_str.as_i64().unwrap_or(0), 2); + Ok(()) + } }