use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct AfterBlockHeight(pub u64);
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EpochNo(pub String);
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StakeAddress(pub String);
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TxHash(pub String);
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AssetPolicy(pub String);
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AssetName(pub String);
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AssetPolicyNft(pub String);
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AssetNameNft(pub String);
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VoterId(pub String);
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DrepId(pub String);
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CcHotId(pub String);
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct Extended(pub bool);
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct History(pub bool);
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct IncludeNextEpoch(pub bool);
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PoolBech32(pub String);
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ScriptHash(pub String);
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProposalId(pub String);
impl AfterBlockHeight {
pub fn new(height: u64) -> Self {
Self(height)
}
pub fn value(&self) -> u64 {
self.0
}
}
impl EpochNo {
pub fn new<S: Into<String>>(epoch: S) -> Self {
Self(epoch.into())
}
pub fn value(&self) -> &str {
&self.0
}
}
impl StakeAddress {
pub fn new<S: Into<String>>(address: S) -> Self {
Self(address.into())
}
pub fn value(&self) -> &str {
&self.0
}
pub fn validate(&self) -> bool {
self.0.starts_with("stake1")
}
}
impl TxHash {
pub fn new<S: Into<String>>(hash: S) -> Self {
Self(hash.into())
}
pub fn value(&self) -> &str {
&self.0
}
pub fn validate(&self) -> bool {
self.0.chars().all(|c| c.is_ascii_hexdigit())
}
}
impl AssetPolicy {
pub fn new<S: Into<String>>(policy: S) -> Self {
Self(policy.into())
}
pub fn value(&self) -> &str {
&self.0
}
pub fn validate(&self) -> bool {
self.0.chars().all(|c| c.is_ascii_hexdigit())
}
}
impl AssetName {
pub fn new<S: Into<String>>(name: S) -> Self {
Self(name.into())
}
pub fn value(&self) -> &str {
&self.0
}
pub fn validate(&self) -> bool {
self.0.chars().all(|c| c.is_ascii_hexdigit())
}
}
impl AssetPolicyNft {
pub fn new<S: Into<String>>(policy: S) -> Self {
Self(policy.into())
}
pub fn value(&self) -> &str {
&self.0
}
pub fn validate(&self) -> bool {
self.0.chars().all(|c| c.is_ascii_hexdigit())
}
}
impl AssetNameNft {
pub fn new<S: Into<String>>(name: S) -> Self {
Self(name.into())
}
pub fn value(&self) -> &str {
&self.0
}
pub fn validate(&self) -> bool {
self.0.chars().all(|c| c.is_ascii_hexdigit())
}
}
impl VoterId {
pub fn new<S: Into<String>>(voter_id: S) -> Self {
Self(voter_id.into())
}
pub fn value(&self) -> &str {
&self.0
}
pub fn validate(&self) -> bool {
self.0.starts_with("drep1") || self.0.starts_with("pool1") || self.0.starts_with("cc_hot1")
}
}
impl DrepId {
pub fn new<S: Into<String>>(drep_id: S) -> Self {
Self(drep_id.into())
}
pub fn value(&self) -> &str {
&self.0
}
pub fn validate(&self) -> bool {
self.0.starts_with("drep1")
}
}
impl CcHotId {
pub fn new<S: Into<String>>(cc_hot_id: S) -> Self {
Self(cc_hot_id.into())
}
pub fn value(&self) -> &str {
&self.0
}
pub fn validate(&self) -> bool {
self.0.starts_with("cc_hot1")
}
}
impl Extended {
pub fn new(extended: bool) -> Self {
Self(extended)
}
pub fn value(&self) -> bool {
self.0
}
}
impl History {
pub fn new(history: bool) -> Self {
Self(history)
}
pub fn value(&self) -> bool {
self.0
}
}
impl IncludeNextEpoch {
pub fn new(include: bool) -> Self {
Self(include)
}
pub fn value(&self) -> bool {
self.0
}
}
impl PoolBech32 {
pub fn new<S: Into<String>>(pool_id: S) -> Self {
Self(pool_id.into())
}
pub fn value(&self) -> &str {
&self.0
}
pub fn validate(&self) -> bool {
self.0.starts_with("pool1")
}
}
impl ScriptHash {
pub fn new<S: Into<String>>(hash: S) -> Self {
Self(hash.into())
}
pub fn value(&self) -> &str {
&self.0
}
pub fn validate(&self) -> bool {
self.0.chars().all(|c| c.is_ascii_hexdigit())
}
}
impl ProposalId {
pub fn new<S: Into<String>>(proposal_id: S) -> Self {
Self(proposal_id.into())
}
pub fn value(&self) -> &str {
&self.0
}
pub fn validate(&self) -> bool {
self.0.starts_with("gov_action1")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_stake_address_validation() {
let valid =
StakeAddress::new("stake1u8yxtugdv63wxafy9d00nuz6hjyyp4qnggvc9a3vxh8yl0ckml2uz");
let invalid = StakeAddress::new("invalid_address");
assert!(valid.validate());
assert!(!invalid.validate());
}
#[test]
fn test_tx_hash_validation() {
let valid = TxHash::new("f144a8264acf4bdfe2e1241170969c930d64ab6b0996a4a45237b623f1dd670e");
let invalid = TxHash::new("invalid_hash!");
assert!(valid.validate());
assert!(!invalid.validate());
}
}