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
77
78
79
80
81
82
83
84
85
use self::super::{CryptoAddress, Error, alias_to_fqdn};
use resolve::{DnsResolver, DnsConfig, default_config};
use std::iter::FromIterator;
use std::time::Duration;
use resolve::record;


/// Ask a DNS server for addresses for the specified OpenAlias.
///
/// # Examples
///
/// ```
/// # use openalias::{CryptoAddress, addresses};
/// # use std::collections::BTreeMap;
/// # trait SortedForVec { fn sorted(self) -> Self; }
/// # impl<T: Ord> SortedForVec for Vec<T> { fn sorted(mut self) -> Self { self.sort(); self} }
/// assert_eq!(addresses("donate@getmonero.org").unwrap().sorted(),
///            vec![CryptoAddress {
///                     cryptocurrency: "btc".to_string(),
///                     address: "1KTexdemPdxSBcG55heUuTjDRYqbC5ZL8H".to_string(),
///
///                     recipient_name: Some("Monero Development".to_string()),
///                     tx_description: Some("Donation to Monero Core Team".to_string()),
///                     tx_amount: None,
///                     tx_payment_id: None,
///                     address_signature: None,
///                     checksum: None,
///
///                     additional_values: BTreeMap::new(),
///                 },
///                 CryptoAddress {
///                     cryptocurrency: "xmr".to_string(),
///                     address: "44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft\
///                               3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A".to_string(),
///
///                     recipient_name: Some("Monero Development".to_string()),
///                     tx_description: Some("Donation to Monero Core Team".to_string()),
///                     tx_amount: None,
///                     tx_payment_id: None,
///                     address_signature: None,
///                     checksum: None,
///
///                     additional_values: BTreeMap::new(),
///                 }]);
/// ```
pub fn addresses(address: &str) -> Result<Vec<CryptoAddress>, Error> {
    Ok(Result::from_iter(address_strings(address)?.into_iter().map(|s| s.parse()))?)
}

/// Ask a DNS server for "oa1:"-prefixed TXT records for the specified OpenAlias.
///
/// # Examples
///
/// ```
/// # use openalias::address_strings;
/// # trait SortedForVec { fn sorted(self) -> Self; }
/// # impl<T: Ord> SortedForVec for Vec<T> { fn sorted(mut self) -> Self { self.sort(); self} }
/// assert_eq!(address_strings("donate@getmonero.org").unwrap().sorted(),
///            vec!["oa1:btc recipient_address=1KTexdemPdxSBcG55heUuTjDRYqbC5ZL8H; \
///                  recipient_name=Monero Development; \
///                  tx_description=Donation to Monero Core Team;".to_string(),
///                 "oa1:xmr recipient_address=44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft\
///                  3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A; \
///                  recipient_name=Monero Development; \
///                  tx_description=Donation to Monero Core Team;".to_string()]);
/// ```
pub fn address_strings(address: &str) -> Result<Vec<String>, Error> {
    Ok(Result::from_iter(DnsResolver::new(default_config().unwrap_or_else(|_| {
            DnsConfig {
                name_servers: vec!["8.8.8.8:53".parse().unwrap(), "8.8.4.4:53".parse().unwrap()],
                search: vec![],
                n_dots: 0,
                timeout: Duration::from_secs(5),
                attempts: 5,
                rotate: true,
                use_inet6: false,
            }
        }))
        ?
        .resolve_record::<record::Txt>(&alias_to_fqdn(address).ok_or(Error::AddressParse)?)?
        .into_iter()
        .map(|r| r.data)
        .filter(|s| s.starts_with(b"oa1:"))
        .map(String::from_utf8))?)
}