블록체인

22.05.16 [ethers] 빅넘버와의 싸움을 끝낼 때가 왔다 (1)

슈팅스타제제 2022. 5. 16. 21:11

개발하면서 나를 힘들게 하는 몇가지가 있다.

BigNumber 타입 처리,

DateTime 정제,

비동기처리,

복잡한 객체 처리(js 메소드 공부하면서 좀 재밌어졌음.)

힘든 이유는 아마 내가 원리도 모르고 그냥 되면 쓰기 때문일 것이다. 

 

오늘은 빅넘버와의 싸움을 끝내기 위해서 빅넘버 처리에 관해서 알아보겠다. 

 

일단 decimals 는 소숫점 자리까지 정수로 표현하기 위한 자릿수이다. float 과의 차이는 여기서는 안다루겠다.

 

데시멀과 빅넘버와의 관계는 다음과 같다. 

1. 0.0000001 을 decimal 8인 수로 표현하면 10이 된다. 

2. 10을 decimal 이 8인 수로 표현했을 때 1000000000 이 된다. 

3. 10을 decimal 이 18로 표현했을 때 10000000000000000000 이 된다. 

 

+조금 짚고 넘어가야 할 점은 "4e6"으로 표시되는 부분!

 

내가 하고 싶은 작업은 데시멀 8인 수에서 데시멀 18인 수로 바로 바꾸는 것이다. 

 

먼저 ethers 라이브러리에서 Bignumber 메소드를 하나씩 살펴보겠다. 

참고로 각 단위에 대한 데시멀은  wei  0, Gwei  9, ether  18이다. 

 

BigNumber.from

input => BigNumber

BigNumber.from("42")
// expected: { BigNumber: "42" }

 

formatUnits

BigNumber => string

const oneGwei = BigNumber.from("1000000000")
const oneEther = BigNumber.from("1000000000000000000")

아래 코드들은 다음과 같은 의미이다. 

ethers.utils.formatUnits(oneGwei, 0)
// expected: '1000000000'

=> 빅넘버 oneGwei 를 데시멀 0의 관점으로 볼 수 있게 나타내겠습니다. 

ethers.utils.formatUnits(oneGwei, 9)
// expected: '1.0'

=> 빅넘버 oneGwei 를 데시멀 9의 관점으로 볼 수 있게 나타내겠습니다. 

 

 

 

parseUnits

string => BigNumber

ethers.utils.parseUnits("1.0", 18)
// expected: {BigNumber: "1000000000000000000"}

=> 문자 타입의 수 1.0 을 소숫점 18째 자리까지 볼 수 있게 빅넘버 타입으로 나타내겠습니다. 

 

 

이제 내가 하고 싶은 작업을 쪼개보면 다음과 같다.

1. 데시멀 18인 빅넘버 a를 데시멀 0인 수 b로 변환하고

2. b에 어떤 실수 c 를 곱해서

3. 데시멀 8인 빅넘버 d 로 변환

 

여기서 나의 질문

각각 데시멀이 다른 빅넘버를 빅넘버로 바로 바꾸는 메소드는 있을까??

a -> b -> c -> d 가 아니라

a -> d 로 바꿀 수 있는 방법!!

 

formatUnits => 연산 => parseUnits 말고 더 간단한 로직은 없을까

소스코드 보고 수정해서 만들거나 ethers 에서 다시 찾거나

// source code
export function formatUnits(value: BigNumberish, unitName?: string | BigNumberish): string {
    if (typeof(unitName) === "string") {
        const index = names.indexOf(unitName);
        if (index !== -1) { unitName = 3 * index; }
    }
    return formatFixed(value, (unitName != null) ? unitName: 18);
}
// source code
export function parseUnits(value: string, unitName?: BigNumberish): BigNumber {
    if (typeof(value) !== "string") {
        logger.throwArgumentError("value must be a string", "value", value);
    }
    if (typeof(unitName) === "string") {
        const index = names.indexOf(unitName);
        if (index !== -1) { unitName = 3 * index; }
    }
    return parseFixed(value, (unitName != null) ? unitName: 18);
}

 

 

참고문서링크 

https://docs.ethers.io/v5/api/utils/bignumber/

 

BigNumber

Documentation for ethers, a complete, tiny and simple Ethereum library.

docs.ethers.io

https://docs.ethers.io/v5/api/utils/display-logic/#utils-parseUnits

 

Display Logic and Input

Documentation for ethers, a complete, tiny and simple Ethereum library.

docs.ethers.io

https://github.com/ethers-io/ethers.js/blob/master/packages/units/src.ts/index.ts#L64

 

GitHub - ethers-io/ethers.js: Complete Ethereum library and wallet implementation in JavaScript.

Complete Ethereum library and wallet implementation in JavaScript. - GitHub - ethers-io/ethers.js: Complete Ethereum library and wallet implementation in JavaScript.

github.com