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  }