Skip to content

Commit

Permalink
create functions for formatting token and usd values
Browse files Browse the repository at this point in the history
  • Loading branch information
rodrigoncalves committed Feb 20, 2024
1 parent c316522 commit fb8d992
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 0 deletions.
62 changes: 62 additions & 0 deletions src/shared/utils/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { formatUsdValue, formatTokenValue } from './index'

describe('formatUsdValue', () => {
test('formats basic USD values correctly', () => {
expect(formatUsdValue('5678.90')).toBe('5,678.90')
expect(formatUsdValue(1234567.89123)).toBe('1,234,567.89')
expect(formatUsdValue(1234567.89)).toBe('1,234,567.89')
expect(formatUsdValue(1234567)).toBe('1,234,567.00')
expect(formatUsdValue(1234.5)).toBe('1,234.50')
expect(formatUsdValue(1234)).toBe('1,234.00')
})

test('handles zero as a special case', () => {
expect(formatUsdValue(0)).toBe('0.00')
expect(formatUsdValue('0')).toBe('0.00')
})

test('formats negative USD values correctly', () => {
expect(formatUsdValue(-1234.56)).toBe('-1,234.56')
})

test('rounds to two decimal places', () => {
expect(formatUsdValue(1234.567)).toBe('1,234.57')
})

test('small amounts', () => {
expect(formatUsdValue(0.0000000099)).toBe('<0.01')
expect(formatUsdValue(0.009)).toBe('<0.01')
expect(formatUsdValue(0.0100000001)).toBe('0.01')
expect(formatUsdValue(0.01)).toBe('0.01')
expect(formatUsdValue(0.1)).toBe('0.10')
})
})

describe('formatTokenValue', () => {
test('formats basic token values correctly', () => {
expect(formatTokenValue(1234)).toBe('1,234')
expect(formatTokenValue('5678.901234')).toBe('5,678.901234')
})

test('removes unnecessary trailing zeros', () => {
expect(formatTokenValue(1234.5)).toBe('1,234.5')
})

test('handles zero as a special case', () => {
expect(formatTokenValue(0)).toBe('0.00')
expect(formatTokenValue('0')).toBe('0.00')
})

test('formats very small token values correctly', () => {
expect(formatTokenValue(0.0000000099)).toBe('<0.00000001')
expect(formatTokenValue(0.000123)).toBe('0.000123')
})

test('formats negative token values correctly', () => {
expect(formatTokenValue(-1234.56789)).toBe('-1,234.56789')
})

test('rounds to six decimal places where applicable', () => {
expect(formatTokenValue(1234.567890123)).toBe('1,234.56789012')
})
})
91 changes: 91 additions & 0 deletions src/shared/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,97 @@ export const formatTokenValues = (number: string | number) => {
return longNumberArr.join('')
}

interface FormatNumberOptions {
decimalPlaces?: number
useThousandSeparator?: boolean
isCurrency?: boolean
}

/**
* Formats a number or a numeric string with the given options.
* @param num The number or string to format.
* @param options The formatting options to use.
* @returns The formatted number as a string.
*/
const formatNumber = (
num: number | string,
options: FormatNumberOptions = {},
): string => {
// Attempt to parse if num is a string
if (typeof num === 'string') {
const parsedNum = parseFloat(num)
if (isNaN(parsedNum)) {
return num
}
num = parsedNum
}

// Immediately return "0.00" for zero values
if (num === 0) {
return '0.00'
}

// Destructure with default values
const {
decimalPlaces = 8,
useThousandSeparator = true,
isCurrency = false,
} = options

// Calculate the minimum value that can be displayed given the number of decimal places
const minValue = 1 / Math.pow(10, decimalPlaces)

// Check for small positive amounts less than the minimum value
if (num > 0 && num < minValue) {
const smallAmountDisplay = `<0.${'0'.repeat(decimalPlaces - 1)}1`
return smallAmountDisplay
}

// Format the number with fixed decimal places
let result = num.toFixed(isCurrency ? 2 : decimalPlaces)

// For non-currency numbers, remove unnecessary trailing zeros
if (!isCurrency) {
result = result.replace(/(\.\d*?[1-9])0+$|\.0*$/, '$1')
}

// Add thousand separators if enabled
if (useThousandSeparator) {
const parts = result.split('.')
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',')
result = parts.join('.')
}

return result
}

/**
* Formats a number or a numeric string as a USD value.
* @param value The number or string to format.
* @returns The formatted USD value as a string.
*/
export const formatUsdValue = (value: number | string): string =>
formatNumber(value, {
decimalPlaces: 2,
useThousandSeparator: true,
isCurrency: true,
})

/**
* Formats a number or a numeric string as a token value.
* @param value The number or string to format.
* @returns The formatted token value as a string.
*/
export const formatTokenValue = (
value: number | string,
precision = 8,
): string =>
formatNumber(value, {
decimalPlaces: precision,
useThousandSeparator: true,
isCurrency: false,
})

export const errorHandler = (error: unknown) => {
if (typeof error === 'object' && Object.hasOwn(error as object, 'message')) {
const err = error as ErrorWithMessage
Expand Down

0 comments on commit fb8d992

Please sign in to comment.