use crate::error::TaiError;
use crate::ids::ObjectId;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Network {
Testnet,
Mainnet,
Devnet,
Custom,
}
impl Network {
pub fn default_rpc_url(self) -> &'static str {
match self {
Network::Testnet => "https://fullnode.testnet.sui.io",
Network::Mainnet => "https://fullnode.mainnet.sui.io",
Network::Devnet => "https://fullnode.devnet.sui.io",
Network::Custom => "",
}
}
}
impl FromStr for Network {
type Err = TaiError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_ascii_lowercase().as_str() {
"testnet" => Ok(Network::Testnet),
"mainnet" => Ok(Network::Mainnet),
"devnet" => Ok(Network::Devnet),
"custom" => Ok(Network::Custom),
other => Err(TaiError::Config(format!("unknown network: {other}"))),
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TaiConfig {
pub network: Network,
pub rpc_url: String,
pub package_id: ObjectId,
pub config_id: ObjectId,
}
impl TaiConfig {
pub fn testnet_v1() -> Self {
TaiConfig {
network: Network::Testnet,
rpc_url: Network::Testnet.default_rpc_url().to_string(),
package_id: ObjectId::from_bytes(hex_lit(
"c5d0d885f6c652413034d3e44a1f9a7ab6ef6d94b6e951b6ee885e2edee3a421",
)),
config_id: ObjectId::from_bytes(hex_lit(
"4a8bdc697738df24f01f6161af29e70136b326db072e3d7e3630b3711f673c50",
)),
}
}
}
const fn hex_lit(s: &str) -> [u8; 32] {
let bytes = s.as_bytes();
assert!(bytes.len() == 64, "hex literal must be 64 chars");
let mut out = [0u8; 32];
let mut i = 0;
while i < 32 {
out[i] = nibble(bytes[2 * i]) * 16 + nibble(bytes[2 * i + 1]);
i += 1;
}
out
}
const fn nibble(c: u8) -> u8 {
match c {
b'0'..=b'9' => c - b'0',
b'a'..=b'f' => 10 + (c - b'a'),
b'A'..=b'F' => 10 + (c - b'A'),
_ => panic!("invalid hex char"),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn testnet_v1_has_known_ids() {
let cfg = TaiConfig::testnet_v1();
assert_eq!(cfg.network, Network::Testnet);
assert_eq!(
cfg.package_id.to_string(),
"0xc5d0d885f6c652413034d3e44a1f9a7ab6ef6d94b6e951b6ee885e2edee3a421"
);
assert_eq!(
cfg.config_id.to_string(),
"0x4a8bdc697738df24f01f6161af29e70136b326db072e3d7e3630b3711f673c50"
);
assert_eq!(cfg.rpc_url, "https://fullnode.testnet.sui.io");
}
#[test]
fn network_parses_case_insensitive() {
assert_eq!("Testnet".parse::<Network>().unwrap(), Network::Testnet);
assert_eq!("MAINNET".parse::<Network>().unwrap(), Network::Mainnet);
assert!("polygon".parse::<Network>().is_err());
}
}