Fixes for amount conversion & BigNumber lib de-duping (#2913)
### Description - Bring BigNumber de-duping improvements from @ottbunn into v3 - Fixes for amount conversion - Create unit tests for some amount fns - Run utils unit tests in CI ### Related issues https://github.com/hyperlane-xyz/issues/issues/690 https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/2751 https://github.com/hyperlane-xyz/hyperlane-monorepo/pull/2828 ### Backward compatibility No, minor breaking changes to signatures of amount util fns ### Testing Unit tests3.1.4
parent
66d064a324
commit
bd70a599e9
@ -0,0 +1,3 @@ |
||||
{ |
||||
"require": ["ts-node/register"] |
||||
} |
@ -0,0 +1,54 @@ |
||||
import { expect } from 'chai'; |
||||
|
||||
import { eqAmountApproximate, fromWei, fromWeiRounded, toWei } from './amount'; |
||||
|
||||
describe('fromWei', () => { |
||||
it('parses and converts correctly', () => { |
||||
expect(fromWei(1, 0)).to.equal('1'); |
||||
expect(fromWei('1000000', 6)).to.equal('1'); |
||||
expect(fromWei('1000000000000000000')).to.equal('1'); |
||||
expect(fromWei('1000000000000000000.1234')).to.equal('1'); |
||||
}); |
||||
}); |
||||
|
||||
describe('fromWeiRounded', () => { |
||||
it('parses and converts correctly', () => { |
||||
expect(fromWeiRounded(1, 0)).to.equal('1.0000'); |
||||
expect(fromWeiRounded('1000000', 6)).to.equal('1.0000'); |
||||
expect(fromWeiRounded('1000000000000000000')).to.equal('1.0000'); |
||||
expect(fromWeiRounded('1000000000000000000.1234')).to.equal('1.0000'); |
||||
}); |
||||
|
||||
it('rounds correctly', () => { |
||||
expect(fromWeiRounded(1234567890, 6, 2)).to.equal('1234.56'); |
||||
expect(fromWeiRounded('1234567890', 6, 4)).to.equal('1234.5678'); |
||||
expect(fromWeiRounded('10000000000000000000')).to.equal('10.0000'); |
||||
expect(fromWeiRounded('10000000000000000000', 18, 0)).to.equal('10'); |
||||
}); |
||||
|
||||
it('can drop decimals for large numbers', () => { |
||||
expect(fromWeiRounded('10001000000000000000000')).to.equal('10001.00'); |
||||
expect(fromWeiRounded('10001000000000000000', 15, 4)).to.equal( |
||||
'10001.0000', |
||||
); |
||||
}); |
||||
}); |
||||
|
||||
describe('toWei', () => { |
||||
it('parses and converts correctly', () => { |
||||
expect(toWei(1, 0)).to.equal('1'); |
||||
expect(toWei('1', 6)).to.equal('1000000'); |
||||
expect(toWei('123.456')).to.equal('123456000000000000000'); |
||||
expect(toWei('1.00000000000000000001')).to.equal('1000000000000000000'); |
||||
expect(toWei('1.00000000000000000001', 6)).to.equal('1000000'); |
||||
}); |
||||
}); |
||||
|
||||
describe('eqAmountApproximate', () => { |
||||
it('compares correctly', () => { |
||||
expect(eqAmountApproximate(1, 1.001, 0.001)).to.be.true; |
||||
expect(eqAmountApproximate(9, 9.001, 0.01)).to.be.true; |
||||
expect(eqAmountApproximate('9876543210', '9876543210', '1')).to.be.true; |
||||
expect(eqAmountApproximate('9876543210', '9876543212', '1')).to.be.false; |
||||
}); |
||||
}); |
@ -1,49 +1,118 @@ |
||||
import BigNumber from 'bignumber.js'; |
||||
import { expect } from 'chai'; |
||||
import { BigNumber, FixedNumber } from 'ethers'; |
||||
import { FixedNumber } from 'ethers'; |
||||
|
||||
import { bigToFixed, fixedToBig, mulBigAndFixed } from './big-numbers'; |
||||
import { |
||||
BigNumberMax, |
||||
BigNumberMin, |
||||
bigToFixed, |
||||
fixedToBig, |
||||
isBigNumberish, |
||||
isZeroish, |
||||
mulBigAndFixed, |
||||
} from './big-numbers'; |
||||
|
||||
describe('utils', () => { |
||||
describe('bigToFixed', () => { |
||||
it('converts a BigNumber to a FixedNumber', () => { |
||||
const big = BigNumber.from('1234'); |
||||
const fixed = bigToFixed(big); |
||||
describe('isBigNumberish', () => { |
||||
const testCases = [ |
||||
{ expect: false, context: 'invalid number', case: 'invalidNumber' }, |
||||
{ expect: false, context: 'NaN', case: NaN }, |
||||
{ expect: false, context: 'undefined', case: undefined }, |
||||
{ expect: false, context: 'null', case: null }, |
||||
{ expect: true, context: 'decimal', case: 123.123 }, |
||||
{ expect: true, context: 'integer', case: 300_000 }, |
||||
{ expect: true, context: 'hex 0', case: 0x00 }, |
||||
{ expect: true, context: 'hex 0', case: 0x000 }, |
||||
{ |
||||
expect: true, |
||||
context: 'address 0', |
||||
case: 0x0000000000000000000000000000000000000000, |
||||
}, |
||||
]; |
||||
testCases.forEach((tc) => { |
||||
it(`returns ${tc.expect} for ${tc.case}`, () => { |
||||
expect(isBigNumberish(tc.case!)).to.equal(tc.expect); |
||||
}); |
||||
}); |
||||
}); |
||||
|
||||
expect(fixed.toUnsafeFloat()).to.equal(1234); |
||||
describe('isZeroish', () => { |
||||
const testCases = [ |
||||
{ expect: false, context: 'invalid number', case: 'invalidNumber' }, |
||||
{ expect: false, context: 'NaN', case: NaN }, |
||||
{ expect: false, context: 'undefined', case: undefined }, |
||||
{ expect: false, context: 'null', case: null }, |
||||
{ expect: false, context: 'non 0 decimal', case: 123.123 }, |
||||
{ expect: false, context: 'non 0 integer', case: 123 }, |
||||
{ expect: true, context: 'hex 0', case: 0x00 }, |
||||
{ expect: true, context: 'hex 0', case: 0x000 }, |
||||
{ |
||||
expect: true, |
||||
context: 'address 0', |
||||
case: 0x0000000000000000000000000000000000000000, |
||||
}, |
||||
]; |
||||
testCases.forEach((tc) => { |
||||
it(`returns ${tc.expect} for ${tc.case}`, () => { |
||||
expect(isZeroish(tc.case!)).to.equal(tc.expect); |
||||
}); |
||||
}); |
||||
}); |
||||
|
||||
describe('fixedToBig', () => { |
||||
it('converts a FixedNumber to a floored BigNumber', () => { |
||||
const fixed = FixedNumber.from('12.34'); |
||||
const big = fixedToBig(fixed); |
||||
describe('bigToFixed', () => { |
||||
it('converts a BigNumber to a FixedNumber', () => { |
||||
const big = BigNumber('7.5e-10'); |
||||
const fixed = bigToFixed(big); |
||||
|
||||
expect(big.toNumber()).to.equal(12); |
||||
}); |
||||
expect(fixed.toUnsafeFloat()).to.equal(7.5e-10); |
||||
}); |
||||
}); |
||||
|
||||
it('converts a FixedNumber to a ceilinged BigNumber', () => { |
||||
const fixed = FixedNumber.from('12.34'); |
||||
const big = fixedToBig(fixed, true); |
||||
describe('fixedToBig', () => { |
||||
it('converts a FixedNumber to a floored BigNumber', () => { |
||||
const fixed = FixedNumber.from('12.34'); |
||||
const big = fixedToBig(fixed); |
||||
|
||||
expect(big.toNumber()).to.equal(13); |
||||
}); |
||||
expect(big.toNumber()).to.equal(12); |
||||
}); |
||||
|
||||
describe('mulBigAndFixed', () => { |
||||
it('gets the floored product of a BigNumber and FixedNumber', () => { |
||||
const big = BigNumber.from('1000'); |
||||
const fixed = FixedNumber.from('1.2345'); |
||||
const product = mulBigAndFixed(big, fixed); |
||||
it('converts a FixedNumber to a ceilinged BigNumber', () => { |
||||
const fixed = FixedNumber.from('12.34'); |
||||
const big = fixedToBig(fixed, true); |
||||
|
||||
expect(product.toNumber()).to.equal(1234); |
||||
}); |
||||
expect(big.toNumber()).to.equal(13); |
||||
}); |
||||
}); |
||||
|
||||
it('gets the ceilinged product of a BigNumber and FixedNumber', () => { |
||||
const big = BigNumber.from('1000'); |
||||
const fixed = FixedNumber.from('1.2345'); |
||||
const product = mulBigAndFixed(big, fixed, true); |
||||
describe('mulBigAndFixed', () => { |
||||
it('gets the floored product of a BigNumber and FixedNumber', () => { |
||||
const big = BigNumber('1000'); |
||||
const fixed = FixedNumber.from('1.2345'); |
||||
const product = mulBigAndFixed(big, fixed); |
||||
|
||||
expect(product.toNumber()).to.equal(1235); |
||||
}); |
||||
expect(product).to.equal((1234).toString()); |
||||
}); |
||||
|
||||
it('gets the ceilinged product of a BigNumber and FixedNumber', () => { |
||||
const big = BigNumber('1000'); |
||||
const fixed = FixedNumber.from('1.2345'); |
||||
const product = mulBigAndFixed(big, fixed, true); |
||||
|
||||
expect(product).to.equal((1235).toString()); |
||||
}); |
||||
}); |
||||
|
||||
describe('BigNumberMin', () => { |
||||
it('gets the min between the two BigNumber', () => { |
||||
const big = BigNumber('1000'); |
||||
const bigger = BigNumber('10000'); |
||||
expect(BigNumberMin(big, bigger)).to.equal(big.toString()); |
||||
}); |
||||
}); |
||||
|
||||
describe('BigNumberMax', () => { |
||||
it('gets the max between the two BigNumber', () => { |
||||
const big = BigNumber('1000'); |
||||
const bigger = BigNumber('10000'); |
||||
expect(BigNumberMax(big, bigger)).to.equal(bigger.toString()); |
||||
}); |
||||
}); |
||||
|
Loading…
Reference in new issue