github.com/diadata-org/diadata@v1.4.593/pkg/dia/helpers/alephium-helper/utils.go (about)

     1  package alephiumhelper
     2  
     3  import (
     4  	"encoding/hex"
     5  	"errors"
     6  
     7  	"github.com/btcsuite/btcutil/base58"
     8  )
     9  
    10  const (
    11  	AddressTypeP2PKH  = 0x00
    12  	AddressTypeP2MPKH = 0x01
    13  	AddressTypeP2SH   = 0x02
    14  	AddressTypeP2C    = 0x03
    15  
    16  	TotalNumberOfGroups = 4
    17  )
    18  
    19  func DecodeHex(hexString string) (string, error) {
    20  	bytes, err := hex.DecodeString(hexString)
    21  	if err != nil {
    22  		return "", err
    23  	}
    24  
    25  	str := string(bytes)
    26  	return str, nil
    27  }
    28  
    29  func AddressFromTokenId(tokenId string) (string, error) {
    30  	hash, err := hex.DecodeString(tokenId)
    31  	if err != nil {
    32  		return "", err
    33  	}
    34  	addressType := []byte{AddressTypeP2C}
    35  
    36  	addressType = append(addressType, hash...)
    37  
    38  	result := base58.Encode(addressType)
    39  
    40  	return result, nil
    41  }
    42  
    43  func groupOfAddress(address string) (uint32, error) {
    44  	decoded, err := decodeAndValidateAddress(address)
    45  	if err != nil {
    46  		return 0, err
    47  	}
    48  	addressType := decoded[0]
    49  	addressBody := decoded[1:]
    50  
    51  	if addressType == AddressTypeP2PKH {
    52  		return groupOfP2pkhAddress(addressBody), nil
    53  	} else if addressType == AddressTypeP2MPKH {
    54  		return groupOfP2mpkhAddress(addressBody), nil
    55  	} else if addressType == AddressTypeP2SH {
    56  		return groupOfP2shAddress(addressBody), nil
    57  	} else {
    58  		id, err := groupFromAddress(address)
    59  		return uint32(id[len(id)-1]), err
    60  	}
    61  }
    62  
    63  func djb2(bytes []byte) uint32 {
    64  	var hash uint32 = 5381
    65  	for i := 0; i < len(bytes); i++ {
    66  		hash = ((hash << 5) + hash) + uint32(bytes[i]&0xff)
    67  	}
    68  	return hash
    69  }
    70  
    71  func xorByte(intValue uint32) uint8 {
    72  	byte0 := (intValue >> 24) & 0xff
    73  	byte1 := (intValue >> 16) & 0xff
    74  	byte2 := (intValue >> 8) & 0xff
    75  	byte3 := intValue & 0xff
    76  	return uint8(byte0^byte1^byte2^byte3) & 0xff
    77  }
    78  
    79  func groupOfAddressBytes(bytes []byte) uint32 {
    80  	hint := djb2(bytes) | 1
    81  	hash := xorByte(hint)
    82  	group := hash % TotalNumberOfGroups
    83  	return uint32(group)
    84  }
    85  
    86  func groupOfP2pkhAddress(address []byte) uint32 {
    87  	return groupOfAddressBytes(address)
    88  }
    89  
    90  func groupOfP2mpkhAddress(address []byte) uint32 {
    91  	return groupOfAddressBytes(address[1:33])
    92  }
    93  
    94  func groupOfP2shAddress(address []byte) uint32 {
    95  	return groupOfAddressBytes(address)
    96  }
    97  
    98  func groupFromAddress(address string) ([]byte, error) {
    99  	return idFromAddress(address)
   100  }
   101  
   102  func idFromAddress(address string) ([]byte, error) {
   103  	decoded := base58.Decode(address)
   104  	if len(decoded) == 0 {
   105  		return nil, errors.New("address string is empty")
   106  	}
   107  	addressType := decoded[0]
   108  	addressBody := decoded[1:]
   109  
   110  	if addressType == AddressTypeP2C {
   111  		return addressBody, nil
   112  	} else {
   113  		return nil, errors.New("invalid contract address type")
   114  	}
   115  }
   116  
   117  func decodeAndValidateAddress(address string) ([]byte, error) {
   118  	decoded := base58.Decode(address)
   119  	if len(decoded) == 0 {
   120  		return nil, errors.New("decodeAndValidateAddress.Address is empty")
   121  	}
   122  	addressType := decoded[0]
   123  
   124  	if addressType == AddressTypeP2MPKH && ((len(decoded)-3)%32 == 0) {
   125  		return decoded, nil
   126  	}
   127  	if (addressType == AddressTypeP2PKH || addressType == AddressTypeP2SH || addressType == AddressTypeP2C) && (len(decoded) == 33) {
   128  		return decoded, nil
   129  	}
   130  	return nil, errors.New("invalid address")
   131  }