123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- use anyhow::{anyhow, Result};
- use serde::{Deserialize, Serialize};
- use std::str::FromStr;
- use url::Url;
- #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
- pub enum Cluster {
- Testnet,
- Mainnet,
- Devnet,
- Localnet,
- Debug,
- Custom(String, String),
- }
- impl Default for Cluster {
- fn default() -> Self {
- Cluster::Localnet
- }
- }
- impl FromStr for Cluster {
- type Err = anyhow::Error;
- fn from_str(s: &str) -> Result<Cluster> {
- match s.to_lowercase().as_str() {
- "t" | "testnet" => Ok(Cluster::Testnet),
- "m" | "mainnet" => Ok(Cluster::Mainnet),
- "d" | "devnet" => Ok(Cluster::Devnet),
- "l" | "localnet" => Ok(Cluster::Localnet),
- "g" | "debug" => Ok(Cluster::Debug),
- _ if s.starts_with("http") => {
- let http_url = s;
- // Taken from:
- // https://github.com/solana-labs/solana/blob/aea8f0df1610248d29d8ca3bc0d60e9fabc99e31/web3.js/src/util/url.ts
- let mut ws_url = Url::parse(http_url)?;
- if let Some(port) = ws_url.port() {
- ws_url.set_port(Some(port + 1))
- .map_err(|_| anyhow!("Unable to set port"))?;
- }
- if ws_url.scheme() == "https" {
- ws_url.set_scheme("wss")
- .map_err(|_| anyhow!("Unable to set scheme"))?;
- } else {
- ws_url.set_scheme("ws")
- .map_err(|_| anyhow!("Unable to set scheme"))?;
- }
- Ok(Cluster::Custom(http_url.to_string(), ws_url.to_string()))
- }
- _ => Err(anyhow::Error::msg(
- "Cluster must be one of [localnet, testnet, mainnet, devnet] or be an http or https url\n",
- )),
- }
- }
- }
- impl std::fmt::Display for Cluster {
- fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
- let clust_str = match self {
- Cluster::Testnet => "testnet",
- Cluster::Mainnet => "mainnet",
- Cluster::Devnet => "devnet",
- Cluster::Localnet => "localnet",
- Cluster::Debug => "debug",
- Cluster::Custom(url, _ws_url) => url,
- };
- write!(f, "{}", clust_str)
- }
- }
- impl Cluster {
- pub fn url(&self) -> &str {
- match self {
- Cluster::Devnet => "https://api.devnet.solana.com",
- Cluster::Testnet => "https://api.testnet.solana.com",
- Cluster::Mainnet => "https://api.mainnet-beta.solana.com",
- Cluster::Localnet => "http://127.0.0.1:8899",
- Cluster::Debug => "http://34.90.18.145:8899",
- Cluster::Custom(url, _ws_url) => url,
- }
- }
- pub fn ws_url(&self) -> &str {
- match self {
- Cluster::Devnet => "wss://api.devnet.solana.com",
- Cluster::Testnet => "wss://api.testnet.solana.com",
- Cluster::Mainnet => "wss://api.mainnet-beta.solana.com",
- Cluster::Localnet => "ws://127.0.0.1:9000",
- Cluster::Debug => "ws://34.90.18.145:9000",
- Cluster::Custom(_url, ws_url) => ws_url,
- }
- }
- }
- #[cfg(test)]
- mod tests {
- use super::*;
- fn test_cluster(name: &str, cluster: Cluster) {
- assert_eq!(Cluster::from_str(name).unwrap(), cluster);
- }
- #[test]
- fn test_cluster_parse() {
- test_cluster("testnet", Cluster::Testnet);
- test_cluster("mainnet", Cluster::Mainnet);
- test_cluster("devnet", Cluster::Devnet);
- test_cluster("localnet", Cluster::Localnet);
- test_cluster("debug", Cluster::Debug);
- }
- #[test]
- #[should_panic]
- fn test_cluster_bad_parse() {
- let bad_url = "httq://my_custom_url.test.net";
- Cluster::from_str(bad_url).unwrap();
- }
- #[test]
- fn test_http_port() {
- let url = "http://my-url.com:7000/";
- let cluster = Cluster::from_str(url).unwrap();
- assert_eq!(
- Cluster::Custom(url.to_string(), "ws://my-url.com:7001/".to_string()),
- cluster
- );
- }
- #[test]
- fn test_http_no_port() {
- let url = "http://my-url.com/";
- let cluster = Cluster::from_str(url).unwrap();
- assert_eq!(
- Cluster::Custom(url.to_string(), "ws://my-url.com/".to_string()),
- cluster
- );
- }
- #[test]
- fn test_https_port() {
- let url = "https://my-url.com:7000/";
- let cluster = Cluster::from_str(url).unwrap();
- assert_eq!(
- Cluster::Custom(url.to_string(), "wss://my-url.com:7001/".to_string()),
- cluster
- );
- }
- #[test]
- fn test_https_no_port() {
- let url = "https://my-url.com/";
- let cluster = Cluster::from_str(url).unwrap();
- assert_eq!(
- Cluster::Custom(url.to_string(), "wss://my-url.com/".to_string()),
- cluster
- );
- }
- #[test]
- fn test_upper_case() {
- let url = "http://my-url.com/FooBar";
- let cluster = Cluster::from_str(url).unwrap();
- assert_eq!(
- Cluster::Custom(url.to_string(), "ws://my-url.com/FooBar".to_string()),
- cluster
- );
- }
- }
|