概述: 一组用Go的好用的工具函数。

工具函数集

函数的实现可以在这里. 它们一般接口比较通用. 这里我们先看几个例子。

检查地址是否是有效的以太坊地址:

  1. valid := util.IsValidAddress("0x323b5d4c32345ced77393b3530b1eed0f346429d")
  2. fmt.Println(valid) // true

检查地址是否为零地址:

  1. zeroed := util.IsZeroAddress("0x0")
  2. fmt.Println(zeroed) // true

将小数转换为wei(整数)。 第二个参数是小数位数。

  1. wei := util.ToWei(0.02, 18)
  2. fmt.Println(wei) // 20000000000000000

将wei(整数)转换为小数。 第二个参数是小数位数。

  1. wei := new(big.Int)
  2. wei.SetString("20000000000000000", 10)
  3. eth := util.ToDecimal(wei, 18)
  4. fmt.Println(eth) // 0.02

根据燃气上限和燃气价格计算燃气花费。

  1. gasLimit := uint64(21000)
  2. gasPrice := new(big.Int)
  3. gasPrice.SetString("2000000000", 10)
  4. gasCost := util.CalcGasCost(gasLimit, gasPrice)
  5. fmt.Println(gasCost) // 42000000000000

从签名中提取R,S和V值。

  1. sig := "0x789a80053e4927d0a898db8e065e948f5cf086e32f9ccaa54c1908e22ac430c62621578113ddbb62d509bf6049b8fb544ab06d36f916685a2eb8e57ffadde02301"
  2. r, s, v := util.SigRSV(sig)
  3. fmt.Println(hexutil.Encode(r[:])[2:]) // 789a80053e4927d0a898db8e065e948f5cf086e32f9ccaa54c1908e22ac430c6
  4. fmt.Println(hexutil.Encode(s[:])[2:]) // 2621578113ddbb62d509bf6049b8fb544ab06d36f916685a2eb8e57ffadde023
  5. fmt.Println(v) // 28

完整代码

util.go

  1. package util
  2. import (
  3. "math/big"
  4. "reflect"
  5. "regexp"
  6. "strconv"
  7. "github.com/ethereum/go-ethereum/common"
  8. "github.com/ethereum/go-ethereum/common/hexutil"
  9. "github.com/shopspring/decimal"
  10. )
  11. // IsValidAddress validate hex address
  12. func IsValidAddress(iaddress interface{}) bool {
  13. re := regexp.MustCompile("^0x[0-9a-fA-F]{40}$")
  14. switch v := iaddress.(type) {
  15. case string:
  16. return re.MatchString(v)
  17. case common.Address:
  18. return re.MatchString(v.Hex())
  19. default:
  20. return false
  21. }
  22. }
  23. // IsZeroAddress validate if it's a 0 address
  24. func IsZeroAddress(iaddress interface{}) bool {
  25. var address common.Address
  26. switch v := iaddress.(type) {
  27. case string:
  28. address = common.HexToAddress(v)
  29. case common.Address:
  30. address = v
  31. default:
  32. return false
  33. }
  34. zeroAddressBytes := common.FromHex("0x0000000000000000000000000000000000000000")
  35. addressBytes := address.Bytes()
  36. return reflect.DeepEqual(addressBytes, zeroAddressBytes)
  37. }
  38. // ToDecimal wei to decimals
  39. func ToDecimal(ivalue interface{}, decimals int) decimal.Decimal {
  40. value := new(big.Int)
  41. switch v := ivalue.(type) {
  42. case string:
  43. value.SetString(v, 10)
  44. case *big.Int:
  45. value = v
  46. }
  47. mul := decimal.NewFromFloat(float64(10)).Pow(decimal.NewFromFloat(float64(decimals)))
  48. num, _ := decimal.NewFromString(value.String())
  49. result := num.Div(mul)
  50. return result
  51. }
  52. // ToWei decimals to wei
  53. func ToWei(iamount interface{}, decimals int) *big.Int {
  54. amount := decimal.NewFromFloat(0)
  55. switch v := iamount.(type) {
  56. case string:
  57. amount, _ = decimal.NewFromString(v)
  58. case float64:
  59. amount = decimal.NewFromFloat(v)
  60. case int64:
  61. amount = decimal.NewFromFloat(float64(v))
  62. case decimal.Decimal:
  63. amount = v
  64. case *decimal.Decimal:
  65. amount = *v
  66. }
  67. mul := decimal.NewFromFloat(float64(10)).Pow(decimal.NewFromFloat(float64(decimals)))
  68. result := amount.Mul(mul)
  69. wei := new(big.Int)
  70. wei.SetString(result.String(), 10)
  71. return wei
  72. }
  73. // CalcGasCost calculate gas cost given gas limit (units) and gas price (wei)
  74. func CalcGasCost(gasLimit uint64, gasPrice *big.Int) *big.Int {
  75. gasLimitBig := big.NewInt(int64(gasLimit))
  76. return gasLimitBig.Mul(gasLimitBig, gasPrice)
  77. }
  78. // SigRSV signatures R S V returned as arrays
  79. func SigRSV(isig interface{}) ([32]byte, [32]byte, uint8) {
  80. var sig []byte
  81. switch v := isig.(type) {
  82. case []byte:
  83. sig = v
  84. case string:
  85. sig, _ = hexutil.Decode(v)
  86. }
  87. sigstr := common.Bytes2Hex(sig)
  88. rS := sigstr[0:64]
  89. sS := sigstr[64:128]
  90. R := [32]byte{}
  91. S := [32]byte{}
  92. copy(R[:], common.FromHex(rS))
  93. copy(S[:], common.FromHex(sS))
  94. vStr := sigstr[128:130]
  95. vI, _ := strconv.Atoi(vStr)
  96. V := uint8(vI + 27)
  97. return R, S, V
  98. }

test file: util_test.go