Node.js의 이더리움 라이브러리 ethers
는 wei와 ether 단위 변환 기능을 제공한다.
// convert wei <-> ether
const weiOf1Eth = ethers.utils.parseEther('1');
const eth1 = ethers.utils.formatEther(weiOf1Eth);
// convert wei <-> gwei
const weiOf1Gwei = ethers.utils.parseUnits('1', 'gwei');
const gwei1 = ethers.utils.formatUnits(weiOf1Gwei, 'gwei');
그런데 geth
에서는 그런 기능을 제공하지 않는다.
그래서 아래처럼 간략하게 만들어보았다.
var WEI_ZEROS = 18
var regexNumber = regexp.MustCompile("[^0-9.-]+")
func Wei2Ether(wei *big.Int) string {
var negative bool
s := wei.String()
if strings.HasPrefix(s, "-") {
negative = true
s = s[1:]
}
l := len(s)
e := WEI_ZEROS
if l > e {
s = s[:l-e] + "." + s[l-e:]
} else {
s = "0." + strings.Repeat("0", e-l) + s
}
s = strings.TrimRight(s, "0")
s = strings.TrimRight(s, ".")
if negative {
s = "-" + s
}
return s
}
func Ether2Wei(ether string) (*big.Int, error) {
s := regexNumber.ReplaceAllString(ether, "")
if s == "" {
return nil, errors.New(ether + " is not numeric")
}
zeros := WEI_ZEROS
if i := strings.Index(s, "."); i != -1 {
zeros = zeros - len(s) + i + 1
}
s = strings.Replace(s, ".", "", 1) + strings.Repeat("0", zeros)
i := new(big.Int)
i.SetString(s, 10)
return i, nil
}
위 코드는 문자열을 조작하여 만들었는데, 이렇게 문자열을 다루지 않고 bigNumber를 계산하여 결과를 낼 수도 있다.
ref: https://github.com/ethereum/go-ethereum/issues/21221
import "github.com/ethereum/go-ethereum/params"
func weiToEther(wei *big.Int) *big.Float {
return new(big.Float).Quo(new(big.Float).SetInt(wei), big.NewFloat(params.Ether))
}
func etherToWei(eth *big.Float) *big.Int {
truncInt, _ := eth.Int(nil)
truncInt = new(big.Int).Mul(truncInt, big.NewInt(params.Ether))
fracStr := strings.Split(fmt.Sprintf("%.18f", eth), ".")[1]
fracStr += strings.Repeat("0", 18 - len(fracStr))
fracInt, _ := new(big.Int).SetString(fracStr, 10)
wei := new(big.Int).Add(truncInt, fracInt)
return wei;
}
왜 공식적으로 geth
에서 제공 안하는지는 모르겠다.