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 }