Golang에서 wei <-> ether

박재훈·2023년 3월 18일
0

GO

목록 보기
12/23
post-custom-banner

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에서 제공 안하는지는 모르겠다.

profile
생각대로 되지 않을 때, 비로소 코딩은 재미있는 법.
post-custom-banner

0개의 댓글