decred.org/dcrdex@v1.0.3/dex/networks/bch/cashaddr.go (about) 1 // This code is available on the terms of the project LICENSE.md file, 2 // also available online at https://blueoakcouncil.org 3 4 package bch 5 6 import ( 7 "fmt" 8 9 "github.com/btcsuite/btcd/btcutil" 10 "github.com/btcsuite/btcd/chaincfg" 11 bchchaincfg "github.com/gcash/bchd/chaincfg" 12 "github.com/gcash/bchutil" 13 ) 14 15 // RecodeCashAddress takes a BTC base-58 encoded address and converts it into a 16 // Cash Address. 17 func RecodeCashAddress(addr string, net *chaincfg.Params) (string, error) { 18 btcAddr, err := btcutil.DecodeAddress(addr, net) 19 if err != nil { 20 return "", err 21 } 22 return EncodeCashAddress(btcAddr, net) 23 } 24 25 func BTCAddrToBCHAddr(btcAddr btcutil.Address, net *chaincfg.Params) (bchutil.Address, error) { 26 switch at := btcAddr.(type) { 27 case *btcutil.AddressPubKeyHash: 28 return bchutil.NewAddressPubKeyHash(btcAddr.ScriptAddress(), convertParams(net)) 29 case *btcutil.AddressScriptHash: 30 return bchutil.NewAddressScriptHashFromHash(btcAddr.ScriptAddress(), convertParams(net)) 31 case *btcutil.AddressPubKey: 32 return bchutil.NewAddressPubKey(btcAddr.ScriptAddress(), convertParams(net)) 33 default: 34 return nil, fmt.Errorf("unsupported address type %T", at) 35 } 36 } 37 38 // EncodeCashAddress converts a btcutil.Address that the BTC backend into a Cash 39 // Address string. For example, if a pkScript was decoded to a btcutil.Address, 40 // the correct address string would not be from the Address' String method, but 41 // from EncodeCashAddress. This is more direct than doing 42 // RecodeCashAddress(addr.String()), which needlessly decodes the string. 43 func EncodeCashAddress(btcAddr btcutil.Address, net *chaincfg.Params) (string, error) { 44 bchAddr, err := BTCAddrToBCHAddr(btcAddr, net) 45 if err != nil { 46 return "", err 47 } 48 49 return withPrefix(bchAddr, net), nil 50 } 51 52 func BCHAddrtoBTCAddr(bchAddr bchutil.Address, net *chaincfg.Params) (btcutil.Address, error) { 53 switch at := bchAddr.(type) { 54 // From what I can tell, the legacy address formats are probably 55 // unnecessary, but I'd hate to be wrong. 56 case *bchutil.AddressPubKeyHash, *bchutil.LegacyAddressPubKeyHash: 57 return btcutil.NewAddressPubKeyHash(bchAddr.ScriptAddress(), net) 58 case *bchutil.AddressScriptHash, *bchutil.LegacyAddressScriptHash: 59 return btcutil.NewAddressScriptHashFromHash(bchAddr.ScriptAddress(), net) 60 case *bchutil.AddressPubKey: 61 return btcutil.NewAddressPubKey(bchAddr.ScriptAddress(), net) 62 default: 63 return nil, fmt.Errorf("unsupported address type %T", at) 64 } 65 } 66 67 // DecodeCashAddress decodes a Cash Address string into a btcutil.Address 68 // that the BTC backend can use internally. 69 func DecodeCashAddress(addr string, net *chaincfg.Params) (btcutil.Address, error) { 70 bchAddr, err := bchutil.DecodeAddress(addr, convertParams(net)) 71 if err != nil { 72 return nil, fmt.Errorf("error decoding CashAddr address: %v", err) 73 } 74 75 return BCHAddrtoBTCAddr(bchAddr, net) 76 } 77 78 // convertParams converts the btcd/*chaincfg.Params to a bchd/*chaincfg.Params. 79 func convertParams(btcParams *chaincfg.Params) *bchchaincfg.Params { 80 switch btcParams.Net { 81 case MainNetParams.Net: 82 return &bchchaincfg.MainNetParams 83 case TestNet4Params.Net: 84 return &bchchaincfg.TestNet4Params 85 case RegressionNetParams.Net: 86 return &bchchaincfg.RegressionNetParams 87 } 88 panic(fmt.Sprintf("unknown network for %s chain: %v", btcParams.Name, btcParams.Net)) 89 } 90 91 // withPrefix adds the Bech32 prefix to the bchutil.Address, since the stringers 92 // don't, for some reason. 93 func withPrefix(bchAddr bchutil.Address, net *chaincfg.Params) string { 94 switch bchAddr.(type) { 95 case *bchutil.AddressPubKeyHash, *bchutil.AddressScriptHash: 96 return net.Bech32HRPSegwit + ":" + bchAddr.String() 97 } 98 // Must be a pubkey address, which gets no prefix. 99 return bchAddr.String() 100 }