1#![warn(missing_docs)]
2#![warn(missing_debug_implementations)]
3#![warn(unused)]
4#![warn(nonstandard_style)]
5#![warn(rust_2018_idioms)]
6
7mod 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#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
29pub enum Network {
30 Mainnet,
32 Testnet,
34 Regtest,
36}
37
38#[derive(Clone, Debug, PartialEq, Eq, Hash)]
40pub enum AddressFormat {
41 Legacy,
44 CashAddr,
47 Other(String),
59}
60
61#[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 pub fn new() -> Converter {
83 Converter {
84 cash_converter: CashConverter::new()
85 }
86 }
87
88 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 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 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 pub fn to_cash_addr(&self, legacy: &str) -> Result<String> {
171 self.to_cash_addr_with_options(legacy, None, None)
172 }
173
174 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 return Ok(cash.to_string());
194 }
195
196 Err(Error::InvalidAddress(cash.to_string()))
197 }
198
199 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 pub fn detect_addr_format(&self, addr: &str) -> Result<AddressFormat> {
235 let (format, _, _, _) = self.parse(addr)?;
236 Ok(format)
237 }
238
239 pub fn is_cash_addr(&self, addr: &str) -> bool {
251 self.cash_converter.parse(addr).is_ok()
252 }
253
254 pub fn is_legacy_addr(&self, addr: &str) -> bool {
266 legacy_converter::parse(addr).is_ok()
267 }
268
269 pub fn detect_addr_network(&self, addr: &str) -> Result<Network> {
281 let (_, network, _, _) = self.parse(addr)?;
282 Ok(network)
283 }
284
285 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 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 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 pub fn detect_addr_type(&self, addr: &str) -> Result<AddressType> {
351 let (_, _, addr_type, _) = self.parse(addr)?;
352 Ok(addr_type)
353 }
354
355 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 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 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}