bch_addr/
lib.rs

1#![warn(missing_docs)]
2#![warn(missing_debug_implementations)]
3#![warn(unused)]
4#![warn(nonstandard_style)]
5#![warn(rust_2018_idioms)]
6
7//! cash_addr format implementation inspired by bchaddrjs.
8//! # Example
9//! ```
10//! use bch_addr::Converter;
11//! let converter = Converter::new();
12//! let cash_addr = converter.to_cash_addr("1B9UNtBfkkpgt8kVbwLN9ktE62QKnMbDzR").unwrap();
13//! assert_eq!(cash_addr, "bitcoincash:qph5kuz78czq00e3t85ugpgd7xmer5kr7c5f6jdpwk");
14//! 
15//! let legacy_addr = converter.to_legacy_addr(&cash_addr).unwrap();
16//! assert_eq!(legacy_addr, "1B9UNtBfkkpgt8kVbwLN9ktE62QKnMbDzR");
17//! ```
18
19mod error;
20mod cash_converter;
21mod legacy_converter;
22
23pub use cash_addr::AddressType as AddressType;
24pub use error::{Error, Result};
25use cash_converter::CashConverter;
26
27/// Type of bitcoin network
28#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
29pub enum Network {
30    /// mainnet
31    Mainnet,
32    /// testnet
33    Testnet,
34    /// regtest
35    Regtest,
36}
37
38/// Type of address format
39#[derive(Clone, Debug, PartialEq, Eq, Hash)]
40pub enum AddressFormat {
41    /// Legacy format.
42    /// Same as bitcoin core address.
43    Legacy,
44    /// cash_addr format
45    /// spec: https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec/cashaddr.md
46    CashAddr,
47    /// other user-defiend format like cash_addr format
48    /// e.g.) slp addr for simpleledger protocol
49    ///     https://github.com/simpleledger/slp-specifications/blob/master/slp-token-type-1.md#slp-addr
50    /// # Arguments
51    /// * `String` - format name
52    /// 
53    /// # Exapmle
54    /// ```
55    /// # use bch_addr::AddressFormat;
56    /// let format = AddressFormat::Other("SLPAddr".to_string());
57    /// ```
58    Other(String),
59}
60
61/// Address converter.
62#[derive(Debug)]
63pub struct Converter {
64    cash_converter: CashConverter,
65}
66
67impl Default for Converter {
68    fn default() -> Self {
69        Self::new()
70    }
71}
72
73impl Converter {
74    /// Construct `Converter`.
75    /// # Returns
76    /// * Object for address conversion.
77    /// # Example
78    /// ```
79    /// # use bch_addr::Converter;
80    /// let converter = Converter::new();
81    /// ```
82    pub fn new() -> Converter {
83        Converter {
84            cash_converter: CashConverter::new()
85        }
86    }
87
88    /// Add user-defined address prefix.
89    /// By calling this function, you can use other address formats.
90    /// # Arguments
91    /// * `prefixes` - Slice of tuple of prefix and `Network`.
92    /// * `format_name` - Format name you want to add.
93    /// # Returns
94    /// * Object for address conversion.
95    /// # Example
96    /// ```
97    /// # use bch_addr::{Converter, Network};
98    /// let converter = Converter::new().add_prefixes(
99    ///     &[("simpleledger", Network::Mainnet), ("slptest", Network::Testnet)],
100    ///     "SLPAddr",
101    /// );
102    /// ```
103    pub fn add_prefixes(mut self, prefixes: &[(&str, Network)], format_name: &str) -> Converter {
104        self.cash_converter = self.cash_converter.add_prefixes(prefixes, format_name);
105        self
106    }
107
108    /// Convert to cash_addr format with some options.
109    /// # Arguments
110    /// * `legacy` - Address to be converted. Usually legacy format but cash_addr format is acceptable.
111    /// * `format` - (option) Address format. `AddressFormat::CashAddr` or `AddressFormat::Other("other format")` is required.
112    /// * `network` - (option) Address network.
113    /// # Returns
114    /// * Converted address.
115    /// # Example
116    /// ```
117    /// # use bch_addr::{Converter, Network, AddressFormat};
118    /// # let converter = Converter::new().add_prefixes(
119    /// #     &[("simpleledger", Network::Mainnet), ("slptest", Network::Testnet)],
120    /// #     "SLPAddr",
121    /// # );
122    /// let regtest_addr = converter.to_cash_addr_with_options(
123    ///     "mqfRfwGeZnFwfFE7KWJjyg6Yx212iGi6Fi",
124    ///     None,
125    ///     Some(Network::Regtest)
126    /// ).unwrap();
127    /// assert_eq!(regtest_addr, "bchreg:qph5kuz78czq00e3t85ugpgd7xmer5kr7c28g5v92v");
128    /// 
129    /// let slp_addr = converter.to_cash_addr_with_options(
130    ///     "1B9UNtBfkkpgt8kVbwLN9ktE62QKnMbDzR",
131    ///     Some(AddressFormat::Other("SLPAddr".to_string())),
132    ///     None
133    /// ).unwrap();
134    /// assert_eq!(slp_addr, "simpleledger:qph5kuz78czq00e3t85ugpgd7xmer5kr7ccj3fcpsg");
135    /// ```
136    pub fn to_cash_addr_with_options(&self, legacy: &str, format: Option<AddressFormat>, network: Option<Network>) -> Result<String> {
137        let format = format.unwrap_or(AddressFormat::CashAddr);
138
139        if let Ok((_, current_network, addr_type, hash)) = legacy_converter::parse(legacy) {
140            let network = network.unwrap_or(current_network);
141            return Ok(self.cash_converter.build(&format, network, addr_type, &hash)?);
142        }
143
144        // actually `legacy` may be cash_addr
145        if let Ok(current_format) = self.detect_addr_format(legacy) {
146            if format == current_format {
147                return Ok(legacy.to_string());
148            } else {
149                let (_, current_network, addr_type, hash) = self.cash_converter.parse(legacy)?;
150                let network = network.unwrap_or(current_network);
151                return Ok(self.cash_converter.build(&format, network, addr_type, &hash)?);
152            }
153        }
154
155        Err(Error::InvalidAddress(legacy.to_string()))
156    }
157
158    /// Convert to cash_addr format.
159    /// # Arguments
160    /// * `legacy` - Address to be converted. Usually legacy format but cash_addr format is acceptable.
161    /// # Returns
162    /// * Converted address.
163    /// # Example
164    /// ```
165    /// # use bch_addr::Converter;
166    /// # let converter = Converter::new();
167    /// let cash_addr = converter.to_cash_addr("1B9UNtBfkkpgt8kVbwLN9ktE62QKnMbDzR").unwrap();
168    /// assert_eq!(cash_addr, "bitcoincash:qph5kuz78czq00e3t85ugpgd7xmer5kr7c5f6jdpwk");
169    /// ```
170    pub fn to_cash_addr(&self, legacy: &str) -> Result<String> {
171        self.to_cash_addr_with_options(legacy, None, None)
172    }
173
174    /// Convert to legacy format.
175    /// # Arguments
176    /// * `cash` - Address to be converted. Usually cash_addr format but legacy format is acceptable.
177    /// # Returns
178    /// * Converted address.
179    /// # Example
180    /// ```
181    /// # use bch_addr::Converter;
182    /// # let converter = Converter::new();
183    /// let cash_addr = converter.to_legacy_addr("bitcoincash:qph5kuz78czq00e3t85ugpgd7xmer5kr7c5f6jdpwk").unwrap();
184    /// assert_eq!(cash_addr, "1B9UNtBfkkpgt8kVbwLN9ktE62QKnMbDzR");
185    /// ```
186    pub fn to_legacy_addr(&self, cash: &str) -> Result<String> {
187        if let Ok((_, network, addr_type, hash)) = self.cash_converter.parse(cash) {
188            return Ok(legacy_converter::build(network, addr_type, &hash)?);
189        }
190
191        if self.is_legacy_addr(cash) {
192            // actually `cash` is legacy_addr
193            return Ok(cash.to_string());
194        }
195
196        Err(Error::InvalidAddress(cash.to_string()))
197    }
198
199    /// Parse address.
200    /// # Arguments
201    /// * `addr` - Address to be parsed.
202    /// # Returns
203    /// * Address format.
204    /// * Address network.
205    /// * Address type.
206    /// * hashed pubilckey.
207    /// # Example
208    /// ```
209    /// # use bch_addr::{Converter, AddressFormat, Network, AddressType};
210    /// # let converter = Converter::new();
211    /// let (format, network, addr_type, hash) = converter.parse("bitcoincash:qph5kuz78czq00e3t85ugpgd7xmer5kr7c5f6jdpwk").unwrap();
212    /// assert_eq!(format, AddressFormat::CashAddr);
213    /// assert_eq!(network, Network::Mainnet);
214    /// assert_eq!(addr_type, AddressType::P2PKH);
215    /// assert_eq!(hash.len(), 20);
216    /// ```
217    pub fn parse(&self, addr: &str) -> Result<(AddressFormat, Network, AddressType, Vec<u8>)> {
218        legacy_converter::parse(addr)
219        .or_else(|_| self.cash_converter.parse(addr))
220        .or_else(|_| Err(Error::InvalidAddress(addr.to_string())))
221    }
222
223    /// Detect address format.
224    /// # Arguments
225    /// * `addr` - Address in any format.
226    /// # Returns
227    /// * Address format.
228    /// ```
229    /// # use bch_addr::{Converter, AddressFormat};
230    /// # let converter = Converter::new();
231    /// let format = converter.detect_addr_format("bitcoincash:qph5kuz78czq00e3t85ugpgd7xmer5kr7c5f6jdpwk").unwrap();
232    /// assert_eq!(format, AddressFormat::CashAddr);
233    /// ```
234    pub fn detect_addr_format(&self, addr: &str) -> Result<AddressFormat> {
235        let (format, _, _, _) = self.parse(addr)?;
236        Ok(format)
237    }
238
239    /// Return `true` if the given address is in cash_addr format.
240    /// # Arguments
241    /// * `addr` - Address in any format.
242    /// # Returns
243    /// * `true` if the given address is in cash_addr format, `false` otherwise.
244    /// ```
245    /// # use bch_addr::Converter;
246    /// # let converter = Converter::new();
247    /// let is_cash = converter.is_cash_addr("bitcoincash:qph5kuz78czq00e3t85ugpgd7xmer5kr7c5f6jdpwk");
248    /// assert_eq!(is_cash, true);
249    /// ```
250    pub fn is_cash_addr(&self, addr: &str) -> bool {
251        self.cash_converter.parse(addr).is_ok()
252    }
253
254    /// Return `true` if the given address is in legacy format.
255    /// # Arguments
256    /// * `addr` - Address in any format.
257    /// # Returns
258    /// * `true` if the given address is in legacy format, `false` otherwise.
259    /// ```
260    /// # use bch_addr::Converter;
261    /// # let converter = Converter::new();
262    /// let is_legacy = converter.is_legacy_addr("1B9UNtBfkkpgt8kVbwLN9ktE62QKnMbDzR");
263    /// assert_eq!(is_legacy, true);
264    /// ```
265    pub fn is_legacy_addr(&self, addr: &str) -> bool {
266        legacy_converter::parse(addr).is_ok()
267    }
268
269    /// Detect address network.
270    /// # Arguments
271    /// * `addr` - Address in any format.
272    /// # Returns
273    /// * Address network.
274    /// ```
275    /// # use bch_addr::{Converter, Network};
276    /// # let converter = Converter::new();
277    /// let network = converter.detect_addr_network("bitcoincash:qph5kuz78czq00e3t85ugpgd7xmer5kr7c5f6jdpwk").unwrap();
278    /// assert_eq!(network, Network::Mainnet);
279    /// ```
280    pub fn detect_addr_network(&self, addr: &str) -> Result<Network> {
281        let (_, network, _, _) = self.parse(addr)?;
282        Ok(network)
283    }
284
285    /// Return `true` if the given address is in mainnet address.
286    /// # Arguments
287    /// * `addr` - Address in any format.
288    /// # Returns
289    /// * `true` if the given address is in mainnet address, `false` otherwise.
290    /// ```
291    /// # use bch_addr::Converter;
292    /// # let converter = Converter::new();
293    /// let is_mainnet = converter.is_mainnet_addr("bitcoincash:qph5kuz78czq00e3t85ugpgd7xmer5kr7c5f6jdpwk");
294    /// assert_eq!(is_mainnet, true);
295    /// ```
296    pub fn is_mainnet_addr(&self, addr: &str) -> bool {
297        match self.detect_addr_network(addr) {
298            Ok(network) => network == Network::Mainnet,
299            Err(_)      => false,
300        }
301    }
302
303    /// Return `true` if the given address is in testnet address.
304    /// # Arguments
305    /// * `addr` - Address in any format.
306    /// # Returns
307    /// * `true` if the given address is in testnet address, `false` otherwise.
308    /// ```
309    /// # use bch_addr::Converter;
310    /// # let converter = Converter::new();
311    /// let is_testnet = converter.is_testnet_addr("mqfRfwGeZnFwfFE7KWJjyg6Yx212iGi6Fi");
312    /// assert_eq!(is_testnet, true);
313    /// ```
314    pub fn is_testnet_addr(&self, addr: &str) -> bool {
315        match self.detect_addr_network(addr) {
316            Ok(network) => network == Network::Testnet,
317            Err(_)      => false,
318        }
319    }
320
321    /// Return `true` if the given address is in regtest address.
322    /// # Arguments
323    /// * `addr` - Address in any format.
324    /// # Returns
325    /// * `true` if the given address is in regtest address, `false` otherwise.
326    /// ```
327    /// # use bch_addr::Converter;
328    /// # let converter = Converter::new();
329    /// let is_regtest = converter.is_regtest_addr("bchreg:qph5kuz78czq00e3t85ugpgd7xmer5kr7c28g5v92v");
330    /// assert_eq!(is_regtest, true);
331    /// ```
332    pub fn is_regtest_addr(&self, addr: &str) -> bool {
333        match self.detect_addr_network(addr) {
334            Ok(network) => network == Network::Regtest,
335            Err(_)      => false,
336        }
337    }
338
339    /// Detect address type.
340    /// # Arguments
341    /// * `addr` - Address in any format.
342    /// # Returns
343    /// * Address type.
344    /// ```
345    /// # use bch_addr::{Converter, AddressType};
346    /// # let converter = Converter::new();
347    /// let addr_type = converter.detect_addr_type("bitcoincash:qph5kuz78czq00e3t85ugpgd7xmer5kr7c5f6jdpwk").unwrap();
348    /// assert_eq!(addr_type, AddressType::P2PKH);
349    /// ```
350    pub fn detect_addr_type(&self, addr: &str) -> Result<AddressType> {
351        let (_, _, addr_type, _) = self.parse(addr)?;
352        Ok(addr_type)
353    }
354
355    /// Return `true` if the given address is in P2PKH address.
356    /// # Arguments
357    /// * `addr` - Address in any format.
358    /// # Returns
359    /// * `true` if the given address is in P2PKH address, `false` otherwise.
360    /// ```
361    /// # use bch_addr::Converter;
362    /// # let converter = Converter::new();
363    /// let is_p2pkh = converter.is_p2pkh_addr("bitcoincash:qph5kuz78czq00e3t85ugpgd7xmer5kr7c5f6jdpwk");
364    /// assert_eq!(is_p2pkh, true);
365    /// ```
366    pub fn is_p2pkh_addr(&self, addr: &str) -> bool {
367        match self.detect_addr_type(addr) {
368            Ok(format) => format == AddressType::P2PKH,
369            Err(_)     => false,
370        }
371    }
372
373    /// Return `true` if the given address is in P2SH address.
374    /// # Arguments
375    /// * `addr` - Address in any format.
376    /// # Returns
377    /// * `true` if the given address is in P2SH address, `false` otherwise.
378    /// ```
379    /// # use bch_addr::Converter;
380    /// # let converter = Converter::new();
381    /// let is_p2sh = converter.is_p2sh_addr("3BqVJRg7Jf94yJSvj2zxaPFAEYh3MAyyw9");
382    /// assert_eq!(is_p2sh, true);
383    /// ```
384    pub fn is_p2sh_addr(&self, addr: &str) -> bool {
385        match self.detect_addr_type(addr) {
386            Ok(format) => format == AddressType::P2SH,
387            Err(_)     => false,
388        }
389    }
390}
391
392#[cfg(test)]
393mod tests {
394    use super::*;
395
396    // https://github.com/bitcoincashjs/bchaddrjs/blob/master/test/bchaddr.js
397    static LEGACY_MAINNET_P2PKH_ADDRESSES: [&str; 20] = [
398        "1B9UNtBfkkpgt8kVbwLN9ktE62QKnMbDzR",
399        "185K5yAfcrARrHjNVt4iAUHtkYqcogF4km",
400        "1EUrmffDt4SQQkGVfmDTyFcp57PuByeadW",
401        "1H6YWsFBxvDx6Ce9dyUFZvjG29npxQpBpR",
402        "15z9kQvBaZmTGRTRbP3K1VBM3BQvRsj4U4",
403        "1P238gziZdeS5Wj9nqLhQHSBK2Lz6zPSke",
404        "13WamBttqMB9AHNovKBCeLFGC5sbN4iZkh",
405        "17Sa1fdVXh2NVgcn5xoWzTLGNivg9gUDQ7",
406        "1tQ2P2q5cVERY8AkGD4K8RGc6NmZQVTKN",
407        "1FJSGaq7Wip2ADSJboxMXniPhnYM8ym5Ri",
408        "1GxjvJnjF6t29gDnX4jF3u25u5JRqANYPV",
409        "1N7gqB2GtgJG8ap3uwRoKyrcrrSTa4qfXu",
410        "1JG6fXqEiu9H2fktGxqpFfGGLdy6ie7QgY",
411        "14ipzRgYAbSZUnmeRNhhrPMQ8XQrzGg4wo",
412        "185FScTRCtVXRoy5gSDbuLnnQaQWqCK4A1",
413        "1NPRQpCNaeVvZLYw6Z3Y1XkKxLt9BrFTn5",
414        "1Pa8bRApFwCZ8rkgCJh9mfUmj4XJMUYdom",
415        "13HmTnwyKacGJCt2WseTReCeEAtG5ZAyci",
416        "1Mdob5JY1yuwoj6y76Vf3AQpoqUH5Aft8z",
417        "1D8zGeRj3Vkns6VwKxwNoW2mDsxF25w2Zy",
418    ];
419
420    static LEGACY_MAINNET_P2SH_ADDRESSES: [&str; 20] = [
421        "3BqVJRg7Jf94yJSvj2zxaPFAEYh3MAyyw9",
422        "38mL1Wf7AkUowTRocyjJb6epu58LSafEYf",
423        "3FAshD9fRxknVuxvnrt4PsykDdgckmK7xD",
424        "3HnZSQjdWpYLBNLam58qzZ6CAg5YXBddBW",
425        "36gAfxQd8U5qMb9riUhuS7YHBhhdvjr8u1",
426        "3Pi44EVA7XxpAgRauw1Hpuo7TYdhd7WMon",
427        "34CbgjPLPFVXFT5F3Qqo4xcCLcAJwvkM85",
428        "388awD7w5bLkarKDD4U7R5hCXFDPmHuWW7",
429        "32aQwvXGdWocWhpbsMsejknCkcfVB4ivTM",
430        "3FzTC8KZ4d8QFP8jiucwxR5KrJq4bcevn7",
431        "3HekqrHAo1CQEqvDeAPqUXP23bb9Sf9WoA",
432        "3NohkiWiSaceDkWV336PkcDZ1NjBBWBewT",
433        "3Jx7b5KgGoTf7qTKQ4WQgHdCVAFpCKiqsB",
434        "35QquyAyiVkwZxU5YUNJH1iLH3haZ5TEfC",
435        "38mGN9wrknouWyfWoXtCKy9iZ6hEMRGsyp",
436        "3P5SLMgp8YpJeWFNDei8SA7G6sArkNKQKL",
437        "3QG9WxfFoqWwE2T7KQMkCHqhsap1waSfDu",
438        "33ynPLSQsUvePNaTdyK3rGZaNhAyfeAmbT",
439        "3NKpWcnyZtEKttoQECAFTnmkxMkzgbT4WX",
440        "3Dq1CBvAbQ5AxGCNT4byE8PhNQExZcR6Q2",
441    ];
442
443    static LEGACY_TESTNET_P2PKH_ADDRESSES: [&str; 20] = [
444        "mqfRfwGeZnFwfFE7KWJjyg6Yx212iGi6Fi",
445        "mnbGP2FeRsbgdQCzDT35zPWDcYSKm4wrcg",
446        "mtzp4ikCh5sfBrk7PLBqoAq8w6zc48PsGn",
447        "mwcVovLAmwfCsK7mMYSdPqwat9PXqcMiFt",
448        "mkW73U1APbCi3Xw3Jx1gqQPfuB1dHFDiEU",
449        "n3XzRk5hNf5grdCmWQK5ECeWB1wgzzYzZd",
450        "mi2Y4EyseNcPwPrRdt9aUFTb45UJHNgtbL",
451        "mmxXJiiULiTdGo6PoXmtpNYbEiXP2v746S",
452        "mgQMKS7otdvVCebnTqBS93dbU5yUZPsANB",
453        "mupPZdv6KkFGwKuvKNvjMhviZn93yznq73",
454        "mwUhDMsi48KGvnhQEdhcspEQm4u8o754bx",
455        "n2de8E7FhhjWuhHfdWQB9u4wir3AXqspCt",
456        "mxn3xavDXvaXonEVzXpC5aUbCdZoaTEB2g",
457        "mjEnHUmWycspFuFG8wg5gJZizX1ZtEF1XN",
458        "mnbCjfYQ1uvnCvShQ1ByjG17Ga1Dk3RTXN",
459        "n2uNhsHMPfwBLT2Yp81uqSxepLUr6zCnCz",
460        "n465tUFo4xdouyEHusfXbah6b481K5Nivk",
461        "mhoikr2x8c3X5KMeEScqFZQy6AUy4GeR4M",
462        "n29kt8PWq1MCaqaapfU2s5d9fq4yytS1xJ",
463        "msewZhWhrXC3eCyZ3XukdRF65sYwtbmARy",
464    ];
465
466    static LEGACY_TESTNET_P2SH_ADDRESSES: [&str; 20] = [
467        "2N3PhNAc8v7eRB65UQAcqCLERStuD93JXLD",
468        "2MzKY5Fb8nCzA9F4MJ7MBD3e67RLWFE1ciP",
469        "2N6j5kx5h3RG8hhbUTzVw1py1RytnZNYoXo",
470        "2N9LmW9ff8H3gP9y8SCkicW5TP2HiFpeK4z",
471        "2MxENjhLejvbBZNnQPcKn44XYQ3uoiBT3fF",
472        "2NFGG7yRBizUANU48b4dASrnNftqsNwzSM1",
473        "2MukokUKMzhzsTEhniYTfgubTYxNUi6PtTX",
474        "2Mygnzx3xh3r6ndwktC5z32gTjbRZXkJpFr",
475        "2Mt8d1fTJEyJxiVT9YVVXMhmTxxsexLdJiE",
476        "2N7YfFsFag5dkTAmHQ3EpaN4b4f3EPkwQkk",
477        "2N9CxubDCQThkSdYmKJ1i6UNHFwoKBxp2Hj",
478        "2NEMupTSk437zRY92iAiGNZCpDiwLvwnZEL",
479        "2NAWKepFhtFy1Kd5s5C8HJEcThWTyzKiNGA",
480        "2Mvy3yi71KxGHmk6dDbzAtxhbVPukK6MD5u",
481        "2MzKURtstNFKFimJ4UfW4wv8ymSuQCcZPN2",
482        "2NEdeQ6cqk1KerHsutnL1476XKDP2agcCh5",
483        "2NFpMahbHRJ2HRp5ezXycpEpy5w2BmnVM9W",
484        "2MuXzT5NSUwRzbAD1K6vvUDYqb3P9RUvPgK",
485        "2NDt2aMj1BLjg6gRwuKn85jm2AhyAV8e2VF",
486        "2N5PDFvrCCraXA3pv8CDqr5NxakT8KJb3Gg",
487    ];
488
489    static CASHADDR_MAINNET_P2PKH_ADDRESSES: [&str; 20] = [
490        "bitcoincash:qph5kuz78czq00e3t85ugpgd7xmer5kr7c5f6jdpwk",
491        "bitcoincash:qpxenfpcf975gxdjmq9pk3xm6hjmfj6re56t60smsm",
492        "bitcoincash:qzfau6vrq980qntgp5e7l6cpfsf7jw88c5u7y85qx6",
493        "bitcoincash:qzcguejjfxld867ck4zudc9a6y8mf6ftgqqrxzfmlh",
494        "bitcoincash:qqm2lpqdfjsg8kkhwk0a3e3gypyswkd69urny99j70",
495        "bitcoincash:qrccfa4qm3xfcrta78v7du75jjaww0ylnss5nxsy9s",
496        "bitcoincash:qqdcsl6c879esyxyacmz7g6vtzwjjwtznsv65x6znz",
497        "bitcoincash:qpr2ddwe8qnnh8h20mmn4zgrharmy0vuy5y4gr8gl2",
498        "bitcoincash:qqymsmh0nhfhs9k5whhnjwfxyaumvtxm8g2z0s4f9y",
499        "bitcoincash:qzwdmm83qjx7372wxgszaukan73ffn8ct54v6hs3dl",
500        "bitcoincash:qzh3f9me5z5sn2w8euap2gyrp6kr7gf6my5mhjey6s",
501        "bitcoincash:qrneuckcx69clprn4nnr82tf8sycqrs3ac4tr8m86f",
502        "bitcoincash:qz742xef07g9w8q52mx0q6m9hp05hnzm657wqd0ce2",
503        "bitcoincash:qq5dzl0drx8v0layyyuh5aupvxfs80ydmsp5444280",
504        "bitcoincash:qpxedxtug7kpwd6tgf5vx08gjamel7sldsc40mxew8",
505        "bitcoincash:qr4fs2m8tjmw54r2aqmadggzuagttkujgyrjs5d769",
506        "bitcoincash:qrmed4fxlhkgay9nxw7zn9muew5ktkyjnuuawvycze",
507        "bitcoincash:qqv3cpvmu4h0vqa6aly0urec7kwtuhe49yz6e7922v",
508        "bitcoincash:qr39scfteeu5l573lzerchh6wc4cqkxeturafzfkk9",
509        "bitcoincash:qzzjgw37vwls805c9fw6g9vqyupadst6wgmane0s4l",
510    ];
511
512    static CASHADDR_MAINNET_P2SH_ADDRESSES: [&str; 20] = [
513        "bitcoincash:pph5kuz78czq00e3t85ugpgd7xmer5kr7crv8a2z4t",
514        "bitcoincash:ppxenfpcf975gxdjmq9pk3xm6hjmfj6re5dw8qhctx",
515        "bitcoincash:pzfau6vrq980qntgp5e7l6cpfsf7jw88c5tmegnra8",
516        "bitcoincash:pzcguejjfxld867ck4zudc9a6y8mf6ftgqhxmdwcy2",
517        "bitcoincash:pqm2lpqdfjsg8kkhwk0a3e3gypyswkd69u5ke2z39j",
518        "bitcoincash:prccfa4qm3xfcrta78v7du75jjaww0ylns83wfh87d",
519        "bitcoincash:pqdcsl6c879esyxyacmz7g6vtzwjjwtznsmlffapgl",
520        "bitcoincash:ppr2ddwe8qnnh8h20mmn4zgrharmy0vuy5ns4vqtyh",
521        "bitcoincash:pqymsmh0nhfhs9k5whhnjwfxyaumvtxm8ga8jlj27e",
522        "bitcoincash:pzwdmm83qjx7372wxgszaukan73ffn8ct5zf8chjkz",
523        "bitcoincash:pzh3f9me5z5sn2w8euap2gyrp6kr7gf6myr72a78pd",
524        "bitcoincash:prneuckcx69clprn4nnr82tf8sycqrs3aczw7guyp5",
525        "bitcoincash:pz742xef07g9w8q52mx0q6m9hp05hnzm65ftazgmzh",
526        "bitcoincash:pq5dzl0drx8v0layyyuh5aupvxfs80ydmsk3g6jfuj",
527        "bitcoincash:ppxedxtug7kpwd6tgf5vx08gjamel7slds0sj5p646",
528        "bitcoincash:pr4fs2m8tjmw54r2aqmadggzuagttkujgy5hdm2apc",
529        "bitcoincash:prmed4fxlhkgay9nxw7zn9muew5ktkyjnutcnrrmey",
530        "bitcoincash:pqv3cpvmu4h0vqa6aly0urec7kwtuhe49y4ly3zf33",
531        "bitcoincash:pr39scfteeu5l573lzerchh6wc4cqkxetu5c5dw4dc",
532        "bitcoincash:pzzjgw37vwls805c9fw6g9vqyupadst6wgvcwkgnwz",
533    ];
534
535    static CASHADDR_TESTNET_P2PKH_ADDRESSES: [&str; 20] = [
536        "bchtest:qph5kuz78czq00e3t85ugpgd7xmer5kr7csm740kf2",
537        "bchtest:qpxenfpcf975gxdjmq9pk3xm6hjmfj6re57e7gjvh8",
538        "bchtest:qzfau6vrq980qntgp5e7l6cpfsf7jw88c5cvqqkhpx",
539        "bchtest:qzcguejjfxld867ck4zudc9a6y8mf6ftgqy3z9tvct",
540        "bchtest:qqm2lpqdfjsg8kkhwk0a3e3gypyswkd69u8pqz89en",
541        "bchtest:qrccfa4qm3xfcrta78v7du75jjaww0ylns5xhpjnzv",
542        "bchtest:qqdcsl6c879esyxyacmz7g6vtzwjjwtznsggspc457",
543        "bchtest:qpr2ddwe8qnnh8h20mmn4zgrharmy0vuy5q8vy9lck",
544        "bchtest:qqymsmh0nhfhs9k5whhnjwfxyaumvtxm8gwsthh7zc",
545        "bchtest:qzwdmm83qjx7372wxgszaukan73ffn8ct5377sjx2r",
546        "bchtest:qzh3f9me5z5sn2w8euap2gyrp6kr7gf6mysfn4mnav",
547        "bchtest:qrneuckcx69clprn4nnr82tf8sycqrs3ac3e8qesa4",
548        "bchtest:qz742xef07g9w8q52mx0q6m9hp05hnzm656uy2d07k",
549        "bchtest:qq5dzl0drx8v0layyyuh5aupvxfs80ydms9x3jhaqn",
550        "bchtest:qpxedxtug7kpwd6tgf5vx08gjamel7sldsu8tuywfm",
551        "bchtest:qr4fs2m8tjmw54r2aqmadggzuagttkujgy8q5n0fae",
552        "bchtest:qrmed4fxlhkgay9nxw7zn9muew5ktkyjnuc02tx099",
553        "bchtest:qqv3cpvmu4h0vqa6aly0urec7kwtuhe49yxgae8ads",
554        "bchtest:qr39scfteeu5l573lzerchh6wc4cqkxetu80d9tp3e",
555        "bchtest:qzzjgw37vwls805c9fw6g9vqyupadst6wgl0h7d8jr",
556    ];
557
558    static CASHADDR_TESTNET_P2SH_ADDRESSES: [&str; 20] = [
559        "bchtest:pph5kuz78czq00e3t85ugpgd7xmer5kr7c87r6g4jh",
560        "bchtest:ppxenfpcf975gxdjmq9pk3xm6hjmfj6re5fur840v6",
561        "bchtest:pzfau6vrq980qntgp5e7l6cpfsf7jw88c50fa0356m",
562        "bchtest:pzcguejjfxld867ck4zudc9a6y8mf6ftgqn5l2v0rk",
563        "bchtest:pqm2lpqdfjsg8kkhwk0a3e3gypyswkd69usyadqxzw",
564        "bchtest:prccfa4qm3xfcrta78v7du75jjaww0ylnsrr2w4se3",
565        "bchtest:pqdcsl6c879esyxyacmz7g6vtzwjjwtznslddwlk0r",
566        "bchtest:ppr2ddwe8qnnh8h20mmn4zgrharmy0vuy5hz3tzurt",
567        "bchtest:pqymsmh0nhfhs9k5whhnjwfxyaumvtxm8ge4kcsae9",
568        "bchtest:pzwdmm83qjx7372wxgszaukan73ffn8ct5xmrl4937",
569        "bchtest:pzh3f9me5z5sn2w8euap2gyrp6kr7gf6my8vw6usx3",
570        "bchtest:prneuckcx69clprn4nnr82tf8sycqrs3acxu607nxg",
571        "bchtest:pz742xef07g9w8q52mx0q6m9hp05hnzm65dee92v9t",
572        "bchtest:pq5dzl0drx8v0layyyuh5aupvxfs80ydmsjrvas7mw",
573        "bchtest:ppxedxtug7kpwd6tgf5vx08gjamel7sldstzknrdjx",
574        "bchtest:pr4fs2m8tjmw54r2aqmadggzuagttkujgys9fug2xy",
575        "bchtest:prmed4fxlhkgay9nxw7zn9muew5ktkyjnu02hypv7c",
576        "bchtest:pqv3cpvmu4h0vqa6aly0urec7kwtuhe49y3dqkq7kd",
577        "bchtest:pr39scfteeu5l573lzerchh6wc4cqkxetus2s2vz2y",
578        "bchtest:pzzjgw37vwls805c9fw6g9vqyupadst6wgg2232yf7",
579    ];
580
581    static CASHADDR_REGTEST_P2PKH_ADDRESSES: [&str; 20] = [
582        "bchreg:qph5kuz78czq00e3t85ugpgd7xmer5kr7c28g5v92v",
583        "bchreg:qpxenfpcf975gxdjmq9pk3xm6hjmfj6re5y9gf3l5p",
584        "bchreg:qzfau6vrq980qntgp5e7l6cpfsf7jw88c5zskp4yzq",
585        "bchreg:qzcguejjfxld867ck4zudc9a6y8mf6ftgq7d5yglmd",
586        "bchreg:qqm2lpqdfjsg8kkhwk0a3e3gypyswkd69uaakryk64",
587        "bchreg:qrccfa4qm3xfcrta78v7du75jjaww0ylnsw6pq3qp2",
588        "bchreg:qqdcsl6c879esyxyacmz7g6vtzwjjwtznsj5xqmxhc",
589        "bchreg:qpr2ddwe8qnnh8h20mmn4zgrharmy0vuy56m69xvms",
590        "bchreg:qqymsmh0nhfhs9k5whhnjwfxyaumvtxm8g5vak5dp7",
591        "bchreg:qzwdmm83qjx7372wxgszaukan73ffn8ct5tzg334f9",
592        "bchreg:qzh3f9me5z5sn2w8euap2gyrp6kr7gf6my2495cq72",
593        "bchreg:qrneuckcx69clprn4nnr82tf8sycqrs3act93p6r7n",
594        "bchreg:qz742xef07g9w8q52mx0q6m9hp05hnzm65qqjtwuas",
595        "bchreg:qq5dzl0drx8v0layyyuh5aupvxfs80ydmsl68n5wr4",
596        "bchreg:qpxedxtug7kpwd6tgf5vx08gjamel7sldsxmaa8a2a",
597        "bchreg:qr4fs2m8tjmw54r2aqmadggzuagttkujgyauzjv67l",
598        "bchreg:qrmed4fxlhkgay9nxw7zn9muew5ktkyjnuznu29uxr",
599        "bchreg:qqv3cpvmu4h0vqa6aly0urec7kwtuhe49yu5tcywwk",
600        "bchreg:qr39scfteeu5l573lzerchh6wc4cqkxetuanmygjjl",
601        "bchreg:qzzjgw37vwls805c9fw6g9vqyupadst6wg9nplw539"
602    ];
603
604    static CASHADDR_REGTEST_P2SH_ADDRESSES: [&str; 20] = [
605        "bchreg:pph5kuz78czq00e3t85ugpgd7xmer5kr7caz4mtx33",
606        "bchreg:ppxenfpcf975gxdjmq9pk3xm6hjmfj6re5nq4xku0u",
607        "bchreg:pzfau6vrq980qntgp5e7l6cpfsf7jw88c544twj8ea",
608        "bchreg:pzcguejjfxld867ck4zudc9a6y8mf6ftgqfgft0uqs",
609        "bchreg:pqm2lpqdfjsg8kkhwk0a3e3gypyswkd69u2ctvr4pg",
610        "bchreg:prccfa4qm3xfcrta78v7du75jjaww0ylnselu0kr6h",
611        "bchreg:pqdcsl6c879esyxyacmz7g6vtzwjjwtzns93m0u9v9",
612        "bchreg:ppr2ddwe8qnnh8h20mmn4zgrharmy0vuy5d782p0qd",
613        "bchreg:pqymsmh0nhfhs9k5whhnjwfxyaumvtxm8grfqenw6r",
614        "bchreg:pzwdmm83qjx7372wxgszaukan73ffn8ct5u847kkjc",
615        "bchreg:pzh3f9me5z5sn2w8euap2gyrp6kr7gf6myascmlr9h",
616        "bchreg:prneuckcx69clprn4nnr82tf8sycqrs3acuqvwaq9w",
617        "bchreg:pz742xef07g9w8q52mx0q6m9hp05hnzm65h90yflxd",
618        "bchreg:pq5dzl0drx8v0layyyuh5aupvxfs80ydmsgl6undcg",
619        "bchreg:ppxedxtug7kpwd6tgf5vx08gjamel7slds37qjq73q",
620        "bchreg:pr4fs2m8tjmw54r2aqmadggzuagttkujgy2elate9z",
621        "bchreg:prmed4fxlhkgay9nxw7zn9muew5ktkyjnu4kp9zla7",
622        "bchreg:pqv3cpvmu4h0vqa6aly0urec7kwtuhe49yt3khrd4t",
623        "bchreg:pr39scfteeu5l573lzerchh6wc4cqkxetu2kxt03fz",
624        "bchreg:pzzjgw37vwls805c9fw6g9vqyupadst6wgjkusfh2c"
625    ];
626
627    static SLPADDR_MAINNET_P2PKH_ADDRESSES: [&str; 20] = [
628        "simpleledger:qph5kuz78czq00e3t85ugpgd7xmer5kr7ccj3fcpsg",
629        "simpleledger:qpxenfpcf975gxdjmq9pk3xm6hjmfj6re5ks359mw9",
630        "simpleledger:qzfau6vrq980qntgp5e7l6cpfsf7jw88c5s90upqcy",
631        "simpleledger:qzcguejjfxld867ck4zudc9a6y8mf6ftgqvcdeumpf",
632        "simpleledger:qqm2lpqdfjsg8kkhwk0a3e3gypyswkd69u0g07sjq3",
633        "simpleledger:qrccfa4qm3xfcrta78v7du75jjaww0ylnsu0ca9ymw",
634        "simpleledger:qqdcsl6c879esyxyacmz7g6vtzwjjwtznsqpla0zdu",
635        "simpleledger:qpr2ddwe8qnnh8h20mmn4zgrharmy0vuy5gwrcjgp5",
636        "simpleledger:qqymsmh0nhfhs9k5whhnjwfxyaumvtxm8gxeytqfm6",
637        "simpleledger:qzwdmm83qjx7372wxgszaukan73ffn8ct5eh3v93np",
638        "simpleledger:qzh3f9me5z5sn2w8euap2gyrp6kr7gf6mycqufvyyw",
639        "simpleledger:qrneuckcx69clprn4nnr82tf8sycqrs3acesguw8yh",
640        "simpleledger:qz742xef07g9w8q52mx0q6m9hp05hnzm65j4tk6c85",
641        "simpleledger:qq5dzl0drx8v0layyyuh5aupvxfs80ydmsd07wq2e3",
642        "simpleledger:qpxedxtug7kpwd6tgf5vx08gjamel7slds5wyqnese",
643        "simpleledger:qr4fs2m8tjmw54r2aqmadggzuagttkujgy0fm0c7ym",
644        "simpleledger:qrmed4fxlhkgay9nxw7zn9muew5ktkyjnusx9h3cu8",
645        "simpleledger:qqv3cpvmu4h0vqa6aly0urec7kwtuhe49ywpj9s25j",
646        "simpleledger:qr39scfteeu5l573lzerchh6wc4cqkxetu0xzeukgm",
647        "simpleledger:qzzjgw37vwls805c9fw6g9vqyupadst6wghxcz6stp"
648    ];
649
650    static SLPADDR_MAINNET_P2SH_ADDRESSES: [&str; 20] = [
651        "simpleledger:pph5kuz78czq00e3t85ugpgd7xmer5kr7c0hvxlzt4",
652        "simpleledger:ppxenfpcf975gxdjmq9pk3xm6hjmfj6re5p4vmzc4c",
653        "simpleledger:pzfau6vrq980qntgp5e7l6cpfsf7jw88c58qjnxrre",
654        "simpleledger:pzcguejjfxld867ck4zudc9a6y8mf6ftgqmaskmc65",
655        "simpleledger:pqm2lpqdfjsg8kkhwk0a3e3gypyswkd69ucdj3h3mv",
656        "simpleledger:prccfa4qm3xfcrta78v7du75jjaww0ylnst29jz8qn",
657        "simpleledger:pqdcsl6c879esyxyacmz7g6vtzwjjwtznshyzjgpkp",
658        "simpleledger:ppr2ddwe8qnnh8h20mmn4zgrharmy0vuy5lt7h4t6f",
659        "simpleledger:pqymsmh0nhfhs9k5whhnjwfxyaumvtxm8g3uey82q8",
660        "simpleledger:pzwdmm83qjx7372wxgszaukan73ffn8ct5wjvrzjgu",
661        "simpleledger:pzh3f9me5z5sn2w8euap2gyrp6kr7gf6my09pxt8ln",
662        "simpleledger:prneuckcx69clprn4nnr82tf8sycqrs3acw44nfyl2",
663        "simpleledger:pz742xef07g9w8q52mx0q6m9hp05hnzm659skeamuf",
664        "simpleledger:pq5dzl0drx8v0layyyuh5aupvxfs80ydms62rp8fzv",
665        "simpleledger:ppxedxtug7kpwd6tgf5vx08gjamel7sldsrte056ty",
666        "simpleledger:pr4fs2m8tjmw54r2aqmadggzuagttkujgycvxqlalx",
667        "simpleledger:prmed4fxlhkgay9nxw7zn9muew5ktkyjnu8rcckm86",
668        "simpleledger:pqv3cpvmu4h0vqa6aly0urec7kwtuhe49yey02hf00",
669        "simpleledger:pr39scfteeu5l573lzerchh6wc4cqkxetucrlkm4nx",
670        "simpleledger:pzzjgw37vwls805c9fw6g9vqyupadst6wgqr9dansu"
671    ];
672
673    static SLPADDR_TESTNET_P2PKH_ADDRESSES: [&str; 20] = [
674        "slptest:qph5kuz78czq00e3t85ugpgd7xmer5kr7ct0ew4pmh",
675        "slptest:qpxenfpcf975gxdjmq9pk3xm6hjmfj6re59dengm96",
676        "slptest:qzfau6vrq980qntgp5e7l6cpfsf7jw88c5rc8mvqnm",
677        "slptest:qzcguejjfxld867ck4zudc9a6y8mf6ftgql9973m2k",
678        "slptest:qqm2lpqdfjsg8kkhwk0a3e3gypyswkd69uu48eajtw",
679        "slptest:qrccfa4qm3xfcrta78v7du75jjaww0ylns0js6gys3",
680        "slptest:qqdcsl6c879esyxyacmz7g6vtzwjjwtznsnuh6zzxr",
681        "slptest:qpr2ddwe8qnnh8h20mmn4zgrharmy0vuy5mntllg2t",
682        "slptest:qqymsmh0nhfhs9k5whhnjwfxyaumvtxm8g4yvvdfs9",
683        "slptest:qzwdmm83qjx7372wxgszaukan73ffn8ct522etg3c7",
684        "slptest:qzh3f9me5z5sn2w8euap2gyrp6kr7gf6myta5wpy03",
685        "slptest:qrneuckcx69clprn4nnr82tf8sycqrs3ac2dqmr80g",
686        "slptest:qz742xef07g9w8q52mx0q6m9hp05hnzm65pgr3hcvt",
687        "slptest:qq5dzl0drx8v0layyyuh5aupvxfs80ydms7jkfd2jw",
688        "slptest:qpxedxtug7kpwd6tgf5vx08gjamel7slds8nv87emx",
689        "slptest:qr4fs2m8tjmw54r2aqmadggzuagttkujgyu5ng470y",
690        "slptest:qrmed4fxlhkgay9nxw7zn9muew5ktkyjnurmdsuchc",
691        "slptest:qqv3cpvmu4h0vqa6aly0urec7kwtuhe49yau6za2ld",
692        "slptest:qr39scfteeu5l573lzerchh6wc4cqkxetuum273kry",
693        "slptest:qzzjgw37vwls805c9fw6g9vqyupadst6wgyms9hsq7"
694    ];
695
696    static SLPADDR_TESTNET_P2SH_ADDRESSES: [&str; 20] = [
697        "slptest:pph5kuz78czq00e3t85ugpgd7xmer5kr7cu2ypjzq2",
698        "slptest:ppxenfpcf975gxdjmq9pk3xm6hjmfj6re5jgyu0c78",
699        "slptest:pzfau6vrq980qntgp5e7l6cpfsf7jw88c55a65trgx",
700        "slptest:pzcguejjfxld867ck4zudc9a6y8mf6ftgqgqc3kc3t",
701        "slptest:pqm2lpqdfjsg8kkhwk0a3e3gypyswkd69uts6k63sn",
702        "slptest:prccfa4qm3xfcrta78v7du75jjaww0ylnschd408tv",
703        "slptest:pqdcsl6c879esyxyacmz7g6vtzwjjwtznsye249pa7",
704        "slptest:ppr2ddwe8qnnh8h20mmn4zgrharmy0vuy5vkksct3k",
705        "slptest:pqymsmh0nhfhs9k5whhnjwfxyaumvtxm8gzp3r22tc",
706        "slptest:pzwdmm83qjx7372wxgszaukan73ffn8ct5a0yy0jrr",
707        "slptest:pzh3f9me5z5sn2w8euap2gyrp6kr7gf6myucfpx85v",
708        "slptest:prneuckcx69clprn4nnr82tf8sycqrs3acaga5yy54",
709        "slptest:pz742xef07g9w8q52mx0q6m9hp05hnzm65kd77smhk",
710        "slptest:pq5dzl0drx8v0layyyuh5aupvxfs80ydmsfhtx2ffn",
711        "slptest:ppxedxtug7kpwd6tgf5vx08gjamel7sldssk3ge6qm",
712        "slptest:pr4fs2m8tjmw54r2aqmadggzuagttkujgyt3w8ja5e",
713        "slptest:prmed4fxlhkgay9nxw7zn9muew5ktkyjnu57slmmv9",
714        "slptest:pqv3cpvmu4h0vqa6aly0urec7kwtuhe49y2e8d6fys",
715        "slptest:pr39scfteeu5l573lzerchh6wc4cqkxetut7h3k4ce",
716        "slptest:pzzjgw37vwls805c9fw6g9vqyupadst6wgn7d2snmr"
717    ];
718
719    fn legacy_addresses() -> Vec<&'static str> {
720        [
721            LEGACY_MAINNET_P2PKH_ADDRESSES,
722            LEGACY_MAINNET_P2SH_ADDRESSES,
723            LEGACY_TESTNET_P2PKH_ADDRESSES,
724            LEGACY_TESTNET_P2SH_ADDRESSES,
725        ].concat()
726    }
727
728    fn legacy_testnet_addresses() -> Vec<&'static str> {
729        [
730            LEGACY_TESTNET_P2PKH_ADDRESSES,
731            LEGACY_TESTNET_P2SH_ADDRESSES,
732        ].concat()
733    }
734
735    fn cash_addresses() -> Vec<&'static str> {
736        [
737            CASHADDR_MAINNET_P2PKH_ADDRESSES,
738            CASHADDR_MAINNET_P2SH_ADDRESSES,
739            CASHADDR_TESTNET_P2PKH_ADDRESSES,
740            CASHADDR_TESTNET_P2SH_ADDRESSES,
741        ].concat()
742    }
743
744    fn cash_addresses_no_prefix() -> Vec<&'static str> {
745        no_prefix(cash_addresses())
746    }
747
748    fn regtest_addresses() -> Vec<&'static str> {
749        [
750            CASHADDR_REGTEST_P2PKH_ADDRESSES,
751            CASHADDR_REGTEST_P2SH_ADDRESSES,
752        ].concat()
753    }
754
755    fn regtest_addresses_no_prefix() -> Vec<&'static str> {
756        no_prefix(regtest_addresses())
757    }
758
759    fn slp_addresses() -> Vec<&'static str> {
760        [
761            SLPADDR_MAINNET_P2PKH_ADDRESSES,
762            SLPADDR_MAINNET_P2SH_ADDRESSES,
763            SLPADDR_TESTNET_P2PKH_ADDRESSES,
764            SLPADDR_TESTNET_P2SH_ADDRESSES,
765        ].concat()
766    }
767
768    fn slp_addresses_no_prefix() -> Vec<&'static str> {
769        no_prefix(slp_addresses())
770    }
771
772    fn no_prefix(data: Vec<&'static str>) -> Vec<&'static str> {
773        data.into_iter().map(|el| {
774            el.splitn(2, ':').nth(1).unwrap()
775        }).collect()
776    }
777
778    fn convert_test_base(converter: &Converter) {
779        for (i, addr) in legacy_addresses().iter().enumerate() {
780            let conv_cash = converter.to_cash_addr(addr).unwrap();
781            let conv_legacy = converter.to_legacy_addr(addr).unwrap();
782
783            assert_eq!(conv_cash, cash_addresses()[i]);
784            assert_eq!(conv_legacy, addr.to_string());
785        }
786
787        for (i, addr) in cash_addresses().iter().enumerate() {
788            let conv_legacy = converter.to_legacy_addr(addr).unwrap();
789            let conv_cash = converter.to_cash_addr(addr).unwrap();
790
791            assert_eq!(conv_legacy, legacy_addresses()[i]);
792            assert_eq!(conv_cash, addr.to_string());
793        }
794
795        for (i, addr) in cash_addresses_no_prefix().iter().enumerate() {
796            let conv_legacy = converter.to_legacy_addr(addr).unwrap();
797            let conv_cash = converter.to_cash_addr(addr).unwrap();
798
799            assert_eq!(conv_legacy, legacy_addresses()[i]);
800            assert_eq!(conv_cash, cash_addresses_no_prefix()[i]);
801        }
802    }
803
804    #[test]
805    fn convert_test() {
806        let converter = Converter::new();
807
808        convert_test_base(&converter);
809    }
810
811    #[test]
812    fn regtest_addr() {
813        let converter = Converter::new();
814
815        for (i, addr) in legacy_testnet_addresses().iter().enumerate() {
816            let conv_cash = converter.to_cash_addr_with_options(addr, None, Some(Network::Regtest)).unwrap();
817
818            assert_eq!(conv_cash, regtest_addresses()[i]);
819        }
820
821        for (i, addr) in regtest_addresses().iter().enumerate() {
822            let conv_legacy = converter.to_legacy_addr(addr).unwrap();
823            let conv_cash = converter.to_cash_addr_with_options(addr, None, Some(Network::Regtest)).unwrap();
824
825            assert_eq!(conv_legacy, legacy_testnet_addresses()[i]);
826            assert_eq!(conv_cash, addr.to_string());
827        }
828
829        for (i, addr) in regtest_addresses_no_prefix().iter().enumerate() {
830            let conv_legacy = converter.to_legacy_addr(addr).unwrap();
831            let conv_cash = converter.to_cash_addr_with_options(addr, None, Some(Network::Regtest)).unwrap();
832
833            assert_eq!(conv_legacy, legacy_testnet_addresses()[i]);
834            assert_eq!(conv_cash, regtest_addresses_no_prefix()[i]);
835        }
836    }
837
838    #[test]
839    fn slp_convert() {
840        let converter = Converter::new().add_prefixes(
841            &[
842                ("simpleledger", Network::Mainnet),
843                ("slptest", Network::Testnet),
844            ],
845            "SLP"
846        );
847
848        convert_test_base(&converter);
849
850        for (i, addr) in legacy_addresses().iter().enumerate() {
851            let conv_cash = converter.to_cash_addr_with_options(addr, Some(AddressFormat::Other("SLP".to_string())), None).unwrap();
852
853            assert_eq!(conv_cash, slp_addresses()[i]);
854        }
855
856        for (i, addr) in slp_addresses().iter().enumerate() {
857            let conv_legacy = converter.to_legacy_addr(addr).unwrap();
858            let conv_cash = converter.to_cash_addr_with_options(addr, Some(AddressFormat::Other("SLP".to_string())), None).unwrap();
859
860            assert_eq!(conv_legacy, legacy_addresses()[i]);
861            assert_eq!(conv_cash, addr.to_string());
862        }
863
864        for (i, addr) in slp_addresses_no_prefix().iter().enumerate() {
865            let conv_legacy = converter.to_legacy_addr(addr).unwrap();
866            let conv_cash = converter.to_cash_addr_with_options(addr, Some(AddressFormat::Other("SLP".to_string())), None).unwrap();
867
868            assert_eq!(conv_legacy, legacy_addresses()[i]);
869            assert_eq!(conv_cash, slp_addresses_no_prefix()[i]);
870        }
871    }
872}