Skip to content

Commit 2f0cd1d

Browse files
authored
Merge pull request #474 from Concordium/fix-token-amount-parsing
Fix token amount parsing
2 parents b8e6589 + b0512bc commit 2f0cd1d

File tree

3 files changed

+32
-2
lines changed

3 files changed

+32
-2
lines changed

packages/sdk/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@
4949

5050
## 10.0.0-alpha.? (Unreleased)
5151

52+
### Fixed
53+
54+
- Fix conversion in `TokenAmount.fromDecimals` function when used with large `tokenAmount` values with small `decimal` values.
55+
5256
## 10.0.0-alpha.15
5357

5458
### Fixed

packages/sdk/src/plt/TokenAmount.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,18 @@ export function instanceOf(value: unknown): value is TokenAmount {
146146
return value instanceof TokenAmount;
147147
}
148148

149+
/**
150+
* Get decimal places from a Big {@linkcode Big}.
151+
*
152+
* @param big The number to get the decimal places.
153+
* @returns {number} The number of decimal places in above number.
154+
*/
155+
function getDecimalPlaces(big: Big): number {
156+
// `b.c` is an array of single digits (coefficient), `b.e` is the exponent (0-based index of highest digit)
157+
const decimals = big.c.length - (big.e + 1);
158+
return decimals > 0 ? decimals : 0;
159+
}
160+
149161
/**
150162
* Creates a TokenAmount from a number, string, {@linkcode Big}, or bigint.
151163
*
@@ -163,8 +175,7 @@ export function fromDecimal(amount: BigSource | bigint, decimals: number): Token
163175
}
164176

165177
const bigAmount = Big(parsed);
166-
const parsedDecimals = bigAmount.toString().split('.')[1]?.length ?? 0;
167-
178+
const parsedDecimals = getDecimalPlaces(bigAmount);
168179
if (parsedDecimals > decimals) {
169180
throw new Error('The amount has more decimal places than the specified decimals.');
170181
}

packages/sdk/test/ci/plt/TokenAmount.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ describe('PLT TokenAmount', () => {
1212
expect(TokenAmount.fromDecimal('15.002456687544126548', 18)).toEqual(
1313
TokenAmount.create(15002456687544126548n, 18)
1414
);
15+
expect(TokenAmount.fromDecimal(MAX_U64, 0)).toEqual(TokenAmount.create(MAX_U64, 0));
1516
});
1617

1718
test('Parses large decimal values correctly', () => {
@@ -26,7 +27,21 @@ describe('PLT TokenAmount', () => {
2627

2728
test('Token amounts with invalid values throws', () => {
2829
expect(() => TokenAmount.create(-504n, 0)).toThrow(TokenAmount.Err.negative());
30+
expect(() => TokenAmount.create(-504n, 1)).toThrow(TokenAmount.Err.negative());
31+
expect(() => TokenAmount.fromDecimal(-504n, 0)).toThrow(TokenAmount.Err.negative());
32+
expect(() => TokenAmount.fromDecimal(-504n, 1)).toThrow(TokenAmount.Err.negative());
2933
expect(() => TokenAmount.create(MAX_U64 + 1n, 0)).toThrow(TokenAmount.Err.exceedsMaxValue());
34+
expect(() => TokenAmount.create(99999999999999999999999999n, 1)).toThrow(TokenAmount.Err.exceedsMaxValue());
35+
expect(() => TokenAmount.fromDecimal(MAX_U64 + 1n, 0)).toThrow(TokenAmount.Err.exceedsMaxValue());
36+
expect(() => TokenAmount.fromDecimal(99999999999999999999999999n, 1)).toThrow(
37+
TokenAmount.Err.exceedsMaxValue()
38+
);
39+
});
40+
41+
test('Token amounts with more decimals than specified throws', () => {
42+
expect(() => TokenAmount.fromDecimal('1.000003', 0)).toThrow(
43+
'The amount has more decimal places than the specified decimals.'
44+
);
3045
});
3146

3247
test('Returns expected amount', () => {

0 commit comments

Comments
 (0)