Skip to content

Commit 951ea32

Browse files
authored
feat: add formatting for scientific notation for Swap amounts (#1423)
1 parent 1de8212 commit 951ea32

File tree

4 files changed

+73
-1
lines changed

4 files changed

+73
-1
lines changed

.changeset/grumpy-weeks-smile.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@coinbase/onchainkit': patch
3+
---
4+
5+
**feat**: add formatting for scientific notation for Swap amounts. by @0xAlec #1423

src/swap/components/SwapAmountInput.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
import { TokenChip, TokenSelectDropdown } from '../../token';
1515
import type { Token } from '../../token';
1616
import type { SwapAmountInputReact } from '../types';
17+
import { formatAmount } from '../utils/formatAmount';
1718
import { useSwapContext } from './SwapProvider';
1819

1920
export function SwapAmountInput({
@@ -100,7 +101,7 @@ export function SwapAmountInput({
100101
)}
101102
placeholder="0.0"
102103
delayMs={delayMs}
103-
value={source.amount}
104+
value={formatAmount(source.amount)}
104105
setValue={source.setAmount}
105106
disabled={source.loading}
106107
onChange={handleChange}

src/swap/utils/formatAmount.test.ts

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { describe, expect, test } from 'vitest';
2+
import { formatAmount } from './formatAmount'; // Adjust the import path as necessary
3+
4+
describe('formatAmount', () => {
5+
test('should return non-scientific notation numbers as-is', () => {
6+
expect(formatAmount('123.45')).toBe('123.45');
7+
expect(formatAmount('0.0001')).toBe('0.0001');
8+
expect(formatAmount('-789')).toBe('-789');
9+
});
10+
11+
test('should format positive numbers in scientific notation', () => {
12+
expect(formatAmount('1e3')).toBe('1000');
13+
expect(formatAmount('1.23e4')).toBe('12300');
14+
expect(formatAmount('1.23e-4')).toBe('0.000123');
15+
expect(formatAmount('1.23e-6')).toBe('0.00000123');
16+
});
17+
18+
test('should handle large exponents', () => {
19+
expect(formatAmount('1e20')).toBe('100000000000000000000');
20+
expect(formatAmount('1e-20')).toBe('0.00000000000000000001');
21+
});
22+
23+
test('should handle numbers with decimal parts', () => {
24+
expect(formatAmount('1.23456e3')).toBe('1234.56');
25+
expect(formatAmount('1.23456e-3')).toBe('0.00123456');
26+
});
27+
28+
test('should handle numbers where exponent affects decimal placement', () => {
29+
expect(formatAmount('1.23e2')).toBe('123');
30+
expect(formatAmount('1.23e1')).toBe('12.3');
31+
expect(formatAmount('1.23e-1')).toBe('0.123');
32+
expect(formatAmount('1.23e-2')).toBe('0.0123');
33+
});
34+
});

src/swap/utils/formatAmount.ts

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
export function formatAmount(num: string): string {
2+
// If the number is not in scientific notation return it as it is
3+
if (!/\d+\.?\d*e[+-]*\d+/i.test(num)) {
4+
return num;
5+
}
6+
7+
// Parse into coefficient and exponent
8+
const [coefficient, exponent] = num.toLowerCase().split('e');
9+
const exp = Number.parseInt(exponent);
10+
11+
// Split coefficient into integer and decimal parts
12+
const [intPart, decPart = ''] = coefficient.split('.');
13+
14+
// Combine integer and decimal parts
15+
const fullNumber = intPart + decPart;
16+
17+
// Calculate the new decimal point position
18+
const newPosition = intPart.length + exp;
19+
20+
if (newPosition <= 0) {
21+
// If the new position is less than or equal to 0, we need to add leading zeros
22+
return `0.${'0'.repeat(Math.abs(newPosition))}${fullNumber}`;
23+
}
24+
25+
if (newPosition >= fullNumber.length) {
26+
// If the new position is greater than the number length, we need to add trailing zeros
27+
return fullNumber + '0'.repeat(newPosition - fullNumber.length);
28+
}
29+
30+
// Otherwise, we insert the decimal point at the new position
31+
return `${fullNumber.slice(0, newPosition)}.${fullNumber.slice(newPosition)}`;
32+
}

0 commit comments

Comments
 (0)