replace web3-utils methods usage by status-go (#2840)
This commit is contained in:
parent
69e84b5673
commit
94fea4725d
|
@ -74,7 +74,7 @@ func TestEncode(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, "0xb3de648bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", result)
|
require.Equal(t, "0xb3de648bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", result)
|
||||||
|
|
||||||
//TODO following case would fail cause go-ethereum does not support type uint
|
//TODO following case would fail cause go-ethereum does not support type uint, should we fix this?
|
||||||
//result, err = Encode("g(uint[][],string[])", `[[[1,2],[3]],["one","two","three"]]`)
|
//result, err = Encode("g(uint[][],string[])", `[[[1,2],[3]],["one","two","three"]]`)
|
||||||
//require.NoError(t, err)
|
//require.NoError(t, err)
|
||||||
//require.Equal(t, "0xad6a3446000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000036f6e650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000374776f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000057468726565000000000000000000000000000000000000000000000000000000", result)
|
//require.Equal(t, "0xad6a3446000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000036f6e650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000374776f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000057468726565000000000000000000000000000000000000000000000000000000", result)
|
||||||
|
|
|
@ -0,0 +1,255 @@
|
||||||
|
package abispec
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func stringToRunes(str string) []rune {
|
||||||
|
var runes []rune
|
||||||
|
bytes := []byte(str)
|
||||||
|
for len(bytes) > 0 {
|
||||||
|
r, size := utf8.DecodeRune(bytes)
|
||||||
|
if r == utf8.RuneError {
|
||||||
|
for i := 0; i < size; i++ {
|
||||||
|
runes = append(runes, rune(bytes[i]))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
runes = append(runes, r)
|
||||||
|
}
|
||||||
|
bytes = bytes[size:]
|
||||||
|
}
|
||||||
|
return runes
|
||||||
|
}
|
||||||
|
|
||||||
|
// Taken from https://mths.be/punycode
|
||||||
|
func ucs2decode(str string) []rune {
|
||||||
|
var runes = stringToRunes(str)
|
||||||
|
var output []rune
|
||||||
|
var counter = 0
|
||||||
|
var length = len(runes)
|
||||||
|
var value rune
|
||||||
|
var extra rune
|
||||||
|
for counter < length {
|
||||||
|
value = runes[counter]
|
||||||
|
counter++
|
||||||
|
if value >= 0xD800 && value <= 0xDBFF && counter < length {
|
||||||
|
// high surrogate, and there is a next character
|
||||||
|
extra = runes[counter]
|
||||||
|
counter++
|
||||||
|
if (extra & 0xFC00) == 0xDC00 { // low surrogate
|
||||||
|
output = append(output, ((value&0x3FF)<<10)+(extra&0x3FF)+0x10000)
|
||||||
|
} else {
|
||||||
|
// unmatched surrogate; only append this code unit, in case the next
|
||||||
|
// code unit is the high surrogate of a surrogate pair
|
||||||
|
output = append(output, value)
|
||||||
|
counter--
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output = append(output, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
// Taken from https://mths.be/punycode
|
||||||
|
func ucs2encode(array []rune) []byte {
|
||||||
|
var length = len(array)
|
||||||
|
var index = 0
|
||||||
|
var value rune
|
||||||
|
var output []byte
|
||||||
|
for index < length {
|
||||||
|
value = array[index]
|
||||||
|
if value > 0xFFFF {
|
||||||
|
value -= 0x10000
|
||||||
|
codePoint := rune(uint32(value)>>10&0x3FF | 0xD800)
|
||||||
|
output = appendBytes(output, stringFromCharCode(codePoint))
|
||||||
|
value = 0xDC00 | value&0x3FF
|
||||||
|
}
|
||||||
|
output = appendBytes(output, stringFromCharCode(value))
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendBytes(dest []byte, bytes []byte) []byte {
|
||||||
|
for i := 0; i < len(bytes); i++ {
|
||||||
|
dest = append(dest, bytes[i])
|
||||||
|
}
|
||||||
|
return dest
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkScalarValue(codePoint rune) error {
|
||||||
|
if codePoint >= 0xD800 && codePoint <= 0xDFFF {
|
||||||
|
return fmt.Errorf("lone surrogate U+%s is not a scalar value", hexutil.EncodeUint64(uint64(codePoint)))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringFromCharCode(codePoint rune) []byte {
|
||||||
|
var buf = make([]byte, 4)
|
||||||
|
n := utf8.EncodeRune(buf, codePoint)
|
||||||
|
return buf[0:n]
|
||||||
|
}
|
||||||
|
|
||||||
|
func createByte(codePoint rune, shift uint32) []byte {
|
||||||
|
return stringFromCharCode(((codePoint >> shift) & 0x3F) | 0x80)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeCodePoint(codePoint rune) ([]byte, error) {
|
||||||
|
if (uint32(codePoint) & uint32(0xFFFFFF80)) == 0 { // 1-byte sequence
|
||||||
|
return stringFromCharCode(codePoint), nil
|
||||||
|
}
|
||||||
|
var symbol []byte
|
||||||
|
if uint32(codePoint)&0xFFFFF800 == 0 { // 2-byte sequence
|
||||||
|
symbol = stringFromCharCode(((codePoint >> 6) & 0x1F) | 0xC0)
|
||||||
|
} else if (uint32(codePoint) & 0xFFFF0000) == 0 { // 3-byte sequence
|
||||||
|
err := checkScalarValue(codePoint)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
symbol = stringFromCharCode(((codePoint >> 12) & 0x0F) | 0xE0)
|
||||||
|
symbol = appendBytes(symbol, createByte(codePoint, 6))
|
||||||
|
} else if (uint32(codePoint) & 0xFFE00000) == 0 { // 4-byte sequence
|
||||||
|
symbol = stringFromCharCode(((codePoint >> 18) & 0x07) | 0xF0)
|
||||||
|
symbol = appendBytes(symbol, createByte(codePoint, 12))
|
||||||
|
symbol = appendBytes(symbol, createByte(codePoint, 6))
|
||||||
|
}
|
||||||
|
symbol = appendBytes(symbol, stringFromCharCode((codePoint&0x3F)|0x80))
|
||||||
|
return symbol, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// implementation referenced from https://github.com/mathiasbynens/utf8.js/blob/2ce09544b62f2a274dbcd249473c0986e3660849/utf8.js
|
||||||
|
func Utf8encode(str string) (string, error) {
|
||||||
|
var codePoints = ucs2decode(str)
|
||||||
|
var length = len(codePoints)
|
||||||
|
var index = 0
|
||||||
|
var codePoint rune
|
||||||
|
var bytes []byte
|
||||||
|
for index < length {
|
||||||
|
codePoint = codePoints[index]
|
||||||
|
cps, err := encodeCodePoint(codePoint)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
bytes = appendBytes(bytes, cps)
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
return string(bytes), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func readContinuationByte(byteArray []rune, byteCount int, pByteIndex *int) (rune, error) {
|
||||||
|
if *pByteIndex >= byteCount {
|
||||||
|
return utf8.RuneError, fmt.Errorf("invalid byte index")
|
||||||
|
}
|
||||||
|
|
||||||
|
var continuationByte = byteArray[*pByteIndex] & 0xFF
|
||||||
|
*pByteIndex = *pByteIndex + 1
|
||||||
|
|
||||||
|
if (continuationByte & 0xC0) == 0x80 {
|
||||||
|
return continuationByte & 0x3F, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we end up here, it’s not a continuation byte
|
||||||
|
return utf8.RuneError, fmt.Errorf("invalid continuation byte")
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeSymbol(byteArray []rune, byteCount int, pByteIndex *int) (rune, bool, error) {
|
||||||
|
var byte1 rune
|
||||||
|
var codePoint rune
|
||||||
|
|
||||||
|
if *pByteIndex > byteCount {
|
||||||
|
return utf8.RuneError, false, fmt.Errorf("invalid byte index")
|
||||||
|
}
|
||||||
|
|
||||||
|
if *pByteIndex == byteCount {
|
||||||
|
return utf8.RuneError, false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read first byte
|
||||||
|
byte1 = byteArray[*pByteIndex] & 0xFF
|
||||||
|
*pByteIndex = *pByteIndex + 1
|
||||||
|
|
||||||
|
// 1-byte sequence (no continuation bytes)
|
||||||
|
if (byte1 & 0x80) == 0 {
|
||||||
|
return byte1, true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2-byte sequence
|
||||||
|
if (byte1 & 0xE0) == 0xC0 {
|
||||||
|
byte2, err := readContinuationByte(byteArray, byteCount, pByteIndex)
|
||||||
|
if err != nil {
|
||||||
|
return utf8.RuneError, false, err
|
||||||
|
}
|
||||||
|
codePoint = ((byte1 & 0x1F) << 6) | byte2
|
||||||
|
if codePoint >= 0x80 {
|
||||||
|
return codePoint, true, nil
|
||||||
|
}
|
||||||
|
return utf8.RuneError, false, fmt.Errorf("invalid continuation byte")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3-byte sequence (may include unpaired surrogates)
|
||||||
|
if (byte1 & 0xF0) == 0xE0 {
|
||||||
|
byte2, err := readContinuationByte(byteArray, byteCount, pByteIndex)
|
||||||
|
if err != nil {
|
||||||
|
return utf8.RuneError, false, err
|
||||||
|
}
|
||||||
|
byte3, err := readContinuationByte(byteArray, byteCount, pByteIndex)
|
||||||
|
if err != nil {
|
||||||
|
return utf8.RuneError, false, err
|
||||||
|
}
|
||||||
|
codePoint = ((byte1 & 0x0F) << 12) | (byte2 << 6) | byte3
|
||||||
|
if codePoint >= 0x0800 {
|
||||||
|
err := checkScalarValue(codePoint)
|
||||||
|
if err != nil {
|
||||||
|
return utf8.RuneError, false, err
|
||||||
|
}
|
||||||
|
return codePoint, true, nil
|
||||||
|
}
|
||||||
|
return utf8.RuneError, false, fmt.Errorf("invalid continuation byte")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4-byte sequence
|
||||||
|
if (byte1 & 0xF8) == 0xF0 {
|
||||||
|
byte2, err := readContinuationByte(byteArray, byteCount, pByteIndex)
|
||||||
|
if err != nil {
|
||||||
|
return utf8.RuneError, false, err
|
||||||
|
}
|
||||||
|
byte3, err := readContinuationByte(byteArray, byteCount, pByteIndex)
|
||||||
|
if err != nil {
|
||||||
|
return utf8.RuneError, false, err
|
||||||
|
}
|
||||||
|
byte4, err := readContinuationByte(byteArray, byteCount, pByteIndex)
|
||||||
|
if err != nil {
|
||||||
|
return utf8.RuneError, false, err
|
||||||
|
}
|
||||||
|
codePoint = ((byte1 & 0x07) << 0x12) | (byte2 << 0x0C) |
|
||||||
|
(byte3 << 0x06) | byte4
|
||||||
|
if codePoint >= 0x010000 && codePoint <= 0x10FFFF {
|
||||||
|
return codePoint, true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return utf8.RuneError, false, fmt.Errorf("invalid UTF-8 detected")
|
||||||
|
}
|
||||||
|
|
||||||
|
// implementation referenced from https://github.com/mathiasbynens/utf8.js/blob/2ce09544b62f2a274dbcd249473c0986e3660849/utf8.js
|
||||||
|
func Utf8decode(str string) ([]byte, error) {
|
||||||
|
byteArray := ucs2decode(str)
|
||||||
|
byteCount := len(byteArray)
|
||||||
|
byteIndex := 0
|
||||||
|
var codePoints []rune
|
||||||
|
for true {
|
||||||
|
codePoint, goOn, err := decodeSymbol(byteArray, byteCount, &byteIndex)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !goOn {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
codePoints = append(codePoints, codePoint)
|
||||||
|
}
|
||||||
|
return ucs2encode(codePoints), nil
|
||||||
|
}
|
|
@ -3,8 +3,23 @@ package abispec
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/status-im/status-go/eth-node/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var unicodeZeroPattern = regexp.MustCompile("^(?:\u0000)*")
|
||||||
|
var hexZeroPattern = regexp.MustCompile("^(?:00)*")
|
||||||
|
var hexStringPattern = regexp.MustCompile("(?i)^[0-9a-f]+$")
|
||||||
|
var hexPrefixPattern = regexp.MustCompile("(?i)^0x")
|
||||||
|
|
||||||
|
var addressBasicPattern = regexp.MustCompile("(?i)^(0x)?[0-9a-f]{40}$")
|
||||||
|
var addressLowerCasePattern = regexp.MustCompile("^(0x|0X)?[0-9a-f]{40}$")
|
||||||
|
var addressUpperCasePattern = regexp.MustCompile("^(0x|0X)?[0-9A-F]{40}$")
|
||||||
|
|
||||||
func HexToNumber(hex string) string {
|
func HexToNumber(hex string) string {
|
||||||
num, success := big.NewInt(0).SetString(hex, 16)
|
num, success := big.NewInt(0).SetString(hex, 16)
|
||||||
if success {
|
if success {
|
||||||
|
@ -20,3 +35,158 @@ func NumberToHex(numString string) string {
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Sha3(str string) string {
|
||||||
|
bytes := crypto.Keccak256([]byte(str))
|
||||||
|
return common.Bytes2Hex(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func reverse(str string) string {
|
||||||
|
bytes := []byte(str)
|
||||||
|
var out []byte
|
||||||
|
for i := len(bytes) - 1; i >= 0; i-- {
|
||||||
|
out = append(out, bytes[i])
|
||||||
|
}
|
||||||
|
return string(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove \u0000 padding from either side
|
||||||
|
func removeUnicodeZeroPadding(str string) string {
|
||||||
|
found := unicodeZeroPattern.FindString(str)
|
||||||
|
str = strings.Replace(str, found, "", 1)
|
||||||
|
str = reverse(str)
|
||||||
|
found = unicodeZeroPattern.FindString(str)
|
||||||
|
str = strings.Replace(str, found, "", 1)
|
||||||
|
return reverse(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove 00 padding from either side
|
||||||
|
func removeHexZeroPadding(str string) string {
|
||||||
|
found := hexZeroPattern.FindString(str)
|
||||||
|
str = strings.Replace(str, found, "", 1)
|
||||||
|
str = reverse(str)
|
||||||
|
found = hexZeroPattern.FindString(str)
|
||||||
|
str = strings.Replace(str, found, "", 1)
|
||||||
|
return reverse(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// implementation referenced from https://github.com/ChainSafe/web3.js/blob/edcd215bf657a4bba62fabaafd08e6e70040976e/packages/web3-utils/src/utils.js#L165
|
||||||
|
func Utf8ToHex(str string) (string, error) {
|
||||||
|
str, err := Utf8encode(str)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
str = removeUnicodeZeroPadding(str)
|
||||||
|
|
||||||
|
var hex = ""
|
||||||
|
for _, r := range str {
|
||||||
|
n := fmt.Sprintf("%x", r)
|
||||||
|
if len(n) < 2 {
|
||||||
|
hex += "0" + n
|
||||||
|
} else {
|
||||||
|
hex += n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "0x" + hex, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// implementation referenced from https://github.com/ChainSafe/web3.js/blob/edcd215bf657a4bba62fabaafd08e6e70040976e/packages/web3-utils/src/utils.js#L193
|
||||||
|
func HexToUtf8(hexString string) (string, error) {
|
||||||
|
hexString = removeHexPrefix(hexString)
|
||||||
|
if !hexStringPattern.MatchString(hexString) {
|
||||||
|
return "", fmt.Errorf("the parameter '%s' must be a valid HEX string", hexString)
|
||||||
|
}
|
||||||
|
if len(hexString)%2 != 0 {
|
||||||
|
return "", fmt.Errorf("the parameter '%s' must have a even number of digits", hexString)
|
||||||
|
}
|
||||||
|
|
||||||
|
hexString = removeHexZeroPadding(hexString)
|
||||||
|
|
||||||
|
n := big.NewInt(0)
|
||||||
|
var bytes []byte
|
||||||
|
for i := 0; i < len(hexString); i += 2 {
|
||||||
|
hex := hexString[i : i+2]
|
||||||
|
n, success := n.SetString(hex, 16)
|
||||||
|
if !success {
|
||||||
|
return "", fmt.Errorf("invalid hex value %s", hex)
|
||||||
|
}
|
||||||
|
r := rune(n.Int64())
|
||||||
|
bs := stringFromCharCode(r)
|
||||||
|
bytes = appendBytes(bytes, bs)
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes, err := Utf8decode(string(bytes))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(bytes), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeHexPrefix(str string) string {
|
||||||
|
found := hexPrefixPattern.FindString(str)
|
||||||
|
return strings.Replace(str, found, "", 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// implementation referenced from https://github.com/ChainSafe/web3.js/blob/edcd215bf657a4bba62fabaafd08e6e70040976e/packages/web3-utils/src/utils.js#L107
|
||||||
|
func CheckAddressChecksum(address string) (bool, error) {
|
||||||
|
address = removeHexPrefix(address)
|
||||||
|
addressHash := Sha3(strings.ToLower(address))
|
||||||
|
|
||||||
|
n := big.NewInt(0)
|
||||||
|
for i := 0; i < 40; i++ {
|
||||||
|
// the nth letter should be uppercase if the nth digit of casemap is 1
|
||||||
|
n, success := n.SetString(addressHash[i:i+1], 16)
|
||||||
|
if !success {
|
||||||
|
return false, fmt.Errorf("failed to convert hex value '%s' to int", addressHash[i:i+1])
|
||||||
|
}
|
||||||
|
v := n.Int64()
|
||||||
|
|
||||||
|
if (v > 7 && uint8(unicode.ToUpper(rune(address[i]))) != address[i]) || (v <= 7 && uint8(unicode.ToLower(rune(address[i]))) != address[i]) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// implementation referenced from https://github.com/ChainSafe/web3.js/blob/edcd215bf657a4bba62fabaafd08e6e70040976e/packages/web3-utils/src/utils.js#L85
|
||||||
|
func IsAddress(address string) (bool, error) {
|
||||||
|
// check if it has the basic requirements of an address
|
||||||
|
if !addressBasicPattern.MatchString(address) {
|
||||||
|
return false, nil
|
||||||
|
} else if addressLowerCasePattern.MatchString(address) || addressUpperCasePattern.MatchString(address) {
|
||||||
|
return true, nil
|
||||||
|
} else {
|
||||||
|
return CheckAddressChecksum(address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// implementation referenced from https://github.com/ChainSafe/web3.js/blob/2022b17d52d31ce95559d18d5530d18c83eb4d1c/packages/web3-utils/src/index.js#L283
|
||||||
|
func ToChecksumAddress(address string) (string, error) {
|
||||||
|
if strings.Trim(address, "") == "" {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
if !addressBasicPattern.MatchString(address) {
|
||||||
|
return "", fmt.Errorf("given address '%s' is not a valid Ethereum address", address)
|
||||||
|
}
|
||||||
|
|
||||||
|
address = strings.ToLower(address)
|
||||||
|
address = removeHexPrefix(address)
|
||||||
|
addressHash := Sha3(address)
|
||||||
|
|
||||||
|
var checksumAddress = []rune("0x")
|
||||||
|
var n = big.NewInt(0)
|
||||||
|
for i := 0; i < len(address); i++ {
|
||||||
|
// If ith character is 9 to f then make it uppercase
|
||||||
|
n, success := n.SetString(addressHash[i:i+1], 16)
|
||||||
|
if !success {
|
||||||
|
return "", fmt.Errorf("failed to convert hex value '%s' to int", addressHash[i:i+1])
|
||||||
|
}
|
||||||
|
if n.Int64() > 7 {
|
||||||
|
upper := unicode.ToUpper(rune(address[i]))
|
||||||
|
checksumAddress = append(checksumAddress, upper)
|
||||||
|
} else {
|
||||||
|
checksumAddress = append(checksumAddress, rune(address[i]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string(checksumAddress), nil
|
||||||
|
}
|
||||||
|
|
|
@ -33,3 +33,75 @@ func TestHexToNumber(t *testing.T) {
|
||||||
func TestNumberToHex(t *testing.T) {
|
func TestNumberToHex(t *testing.T) {
|
||||||
require.Equal(t, "20000000000002", NumberToHex("9007199254740994"))
|
require.Equal(t, "20000000000002", NumberToHex("9007199254740994"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSha3(t *testing.T) {
|
||||||
|
require.Equal(t, "48bed44d1bcd124a28c27f343a817e5f5243190d3c52bf347daf876de1dbbf77", Sha3("abcd"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHexToUtf8(t *testing.T) {
|
||||||
|
str, err := HexToUtf8("0x49206861766520313030e282ac")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "I have 100€", str)
|
||||||
|
|
||||||
|
str, err = HexToUtf8("0xe4bda0e5a5bd")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "你好", str)
|
||||||
|
|
||||||
|
_, err = HexToUtf8("0xfffefd")
|
||||||
|
require.ErrorContains(t, err, "invalid UTF-8 detected")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUtf8ToHex(t *testing.T) {
|
||||||
|
str, err := Utf8ToHex("\xff")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "0xc3bf", str)
|
||||||
|
|
||||||
|
str, err = Utf8ToHex("你好")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "0xe4bda0e5a5bd", str)
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
address1 = "0x0eD343df16A5327aC13B689072804A2705a26F47"
|
||||||
|
address2 = "0x0eD343df16A5327aC13B689072804A2705a26F47a"
|
||||||
|
address3 = "0x0eD343df16A5327aC13B689072804A2705a26f47"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIsAddress(t *testing.T) {
|
||||||
|
valid, err := IsAddress(address1)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.True(t, valid)
|
||||||
|
|
||||||
|
valid, err = IsAddress(address2)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.False(t, valid)
|
||||||
|
|
||||||
|
valid, err = IsAddress(address3)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.False(t, valid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCheckAddressChecksum(t *testing.T) {
|
||||||
|
valid, err := CheckAddressChecksum(address1)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.True(t, valid)
|
||||||
|
|
||||||
|
valid, err = CheckAddressChecksum(address2)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.False(t, valid)
|
||||||
|
|
||||||
|
valid, err = CheckAddressChecksum(address3)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.False(t, valid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToChecksumAddress(t *testing.T) {
|
||||||
|
checksumAddress, err := ToChecksumAddress(address3)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, address1, checksumAddress)
|
||||||
|
|
||||||
|
address := "0x0ed343df16A5327aC13B689072804A2705A26f47"
|
||||||
|
checksumAddress, err = ToChecksumAddress(address)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, address1, checksumAddress)
|
||||||
|
}
|
||||||
|
|
|
@ -986,3 +986,49 @@ func HexToNumber(hex string) string {
|
||||||
func NumberToHex(numString string) string {
|
func NumberToHex(numString string) string {
|
||||||
return abi_spec.NumberToHex(numString)
|
return abi_spec.NumberToHex(numString)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Sha3(str string) string {
|
||||||
|
return "0x" + abi_spec.Sha3(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Utf8ToHex(str string) string {
|
||||||
|
hexString, err := abi_spec.Utf8ToHex(str)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("failed to convert utf8 to hex", "str", str, "error", err)
|
||||||
|
}
|
||||||
|
return hexString
|
||||||
|
}
|
||||||
|
|
||||||
|
func HexToUtf8(hexString string) string {
|
||||||
|
str, err := abi_spec.HexToUtf8(hexString)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("failed to convert hex to utf8", "hexString", hexString, "error", err)
|
||||||
|
}
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckAddressChecksum(address string) string {
|
||||||
|
valid, err := abi_spec.CheckAddressChecksum(address)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("failed to invoke check address checksum", "address", address, "error", err)
|
||||||
|
}
|
||||||
|
result, _ := json.Marshal(valid)
|
||||||
|
return string(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsAddress(address string) string {
|
||||||
|
valid, err := abi_spec.IsAddress(address)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("failed to invoke IsAddress", "address", address, "error", err)
|
||||||
|
}
|
||||||
|
result, _ := json.Marshal(valid)
|
||||||
|
return string(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToChecksumAddress(address string) string {
|
||||||
|
address, err := abi_spec.ToChecksumAddress(address)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("failed to convert to checksum address", "address", address, "error", err)
|
||||||
|
}
|
||||||
|
return address
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue