github.com/MetalBlockchain/metalgo@v1.11.9/utils/formatting/address/address.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package address
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  	"strings"
    10  
    11  	"github.com/btcsuite/btcd/btcutil/bech32"
    12  )
    13  
    14  const addressSep = "-"
    15  
    16  var (
    17  	ErrNoSeparator = errors.New("no separator found in address")
    18  	errBits5To8    = errors.New("unable to convert address from 5-bit to 8-bit formatting")
    19  	errBits8To5    = errors.New("unable to convert address from 8-bit to 5-bit formatting")
    20  )
    21  
    22  // Parse takes in an address string and splits returns the corresponding parts.
    23  // This returns the chain ID alias, bech32 HRP, address bytes, and an error if
    24  // it occurs.
    25  func Parse(addrStr string) (string, string, []byte, error) {
    26  	addressParts := strings.SplitN(addrStr, addressSep, 2)
    27  	if len(addressParts) < 2 {
    28  		return "", "", nil, ErrNoSeparator
    29  	}
    30  	chainID := addressParts[0]
    31  	rawAddr := addressParts[1]
    32  
    33  	hrp, addr, err := ParseBech32(rawAddr)
    34  	return chainID, hrp, addr, err
    35  }
    36  
    37  // Format takes in a chain prefix, HRP, and byte slice to produce a string for
    38  // an address.
    39  func Format(chainIDAlias string, hrp string, addr []byte) (string, error) {
    40  	addrStr, err := FormatBech32(hrp, addr)
    41  	if err != nil {
    42  		return "", err
    43  	}
    44  	return fmt.Sprintf("%s%s%s", chainIDAlias, addressSep, addrStr), nil
    45  }
    46  
    47  // ParseBech32 takes a bech32 address as input and returns the HRP and data
    48  // section of a bech32 address
    49  func ParseBech32(addrStr string) (string, []byte, error) {
    50  	rawHRP, decoded, err := bech32.Decode(addrStr)
    51  	if err != nil {
    52  		return "", nil, err
    53  	}
    54  	addrBytes, err := bech32.ConvertBits(decoded, 5, 8, true)
    55  	if err != nil {
    56  		return "", nil, errBits5To8
    57  	}
    58  	return rawHRP, addrBytes, nil
    59  }
    60  
    61  // FormatBech32 takes an address's bytes as input and returns a bech32 address
    62  func FormatBech32(hrp string, payload []byte) (string, error) {
    63  	fiveBits, err := bech32.ConvertBits(payload, 8, 5, true)
    64  	if err != nil {
    65  		return "", errBits8To5
    66  	}
    67  	return bech32.Encode(hrp, fiveBits)
    68  }