1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
use error::{Error, Result};
use crypto::PublicKey;

const MAX_CODE_LEN: usize = 12;

/// Enum representing an asset.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Asset {
    /// The native asset (XLM).
    Native,
    /// A non-native asset, identified by asset code/issuer id.
    Credit(CreditAsset),
}

impl Asset {
    /// Create the native asset: Lumens.
    pub fn native() -> Asset {
        Asset::Native
    }

    /// Create the asset with `code` issued by `issuer`.
    pub fn credit<S>(code: S, issuer: PublicKey) -> Result<Asset>
    where
        S: Into<String>,
    {
        let code = code.into();
        let inner = CreditAsset::new(code, issuer)?;
        Ok(Asset::Credit(inner))
    }
}

/// A non-native asset, identified by asset code/issuer id.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CreditAsset {
    code: String,
    issuer: PublicKey,
}

impl CreditAsset {
    /// Create new credit asset with `code` and `issuer.
    ///
    /// Code must be shorter than 12 characters.
    pub fn new(code: String, issuer: PublicKey) -> Result<CreditAsset> {
        if code.len() > MAX_CODE_LEN {
            Err(Error::InvalidAssetCode)
        } else {
            Ok(CreditAsset { code, issuer })
        }
    }

    /// Return the asset code.
    pub fn code(&self) -> &str {
        &self.code
    }

    /// Return the asset issuer.
    pub fn issuer(&self) -> &PublicKey {
        &self.issuer
    }
}

#[cfg(test)]
mod tests {
    use super::CreditAsset;
    use crypto::PublicKey;

    #[test]
    fn test_error_code_too_long() {
        let code = "1234567890123".to_string();
        let pk = PublicKey::from_account_id(
            "GCZHXL5HXQX5ABDM26LHYRCQZ5OJFHLOPLZX47WEBP3V2PF5AVFK2A5D",
        ).unwrap();
        let asset = CreditAsset::new(code, pk);
        assert!(asset.is_err());
    }
}