Skip to content

Commit

Permalink
feat: percent utils now uses bigint
Browse files Browse the repository at this point in the history
  • Loading branch information
itsmnthn committed Mar 22, 2024
1 parent 71d3453 commit 5025e44
Show file tree
Hide file tree
Showing 10 changed files with 163 additions and 175 deletions.
3 changes: 2 additions & 1 deletion packages/elements/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
import { defineNuxtConfig } from 'nuxt/config'

export default defineNuxtConfig({
components: [{ path: './components' }],
})
3 changes: 2 additions & 1 deletion packages/meta/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
import { defineNuxtConfig } from 'nuxt/config'

export default defineNuxtConfig({

})
3 changes: 2 additions & 1 deletion packages/statics/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
import { defineNuxtConfig } from 'nuxt/config'

export default defineNuxtConfig({

})
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { describe, expect, it } from 'vitest'
import {
formatTime,
getTimestampedID,
range,
shortenString,
} from '../src'
import { formatTime, getTimestampedID, range, shortenString } from '../src'

describe('shortenString', () => {
it('shorten string by 4 character from both side and concat with ...', () => {
Expand Down
16 changes: 15 additions & 1 deletion packages/utils/src/formatter.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
/**
* Shortens a string by removing characters from the middle and replacing them with an ellipse.
*
* @param value The string to shorten
* @param startCount The number of characters to keep at the start of the string
* @param endCount The number of characters to keep at the end of the string
* @param ellipse The string to use as the ellipse (default: '...')
*
* @returns The shortened string
*
* @example
* shortenString('0x7a7a7229292286592739473748234343434532345', 4, 4) // '0x7a...2345'
* shortenString('0x7a7a7229292286592739473748234343434532345', 4, 4, '***') // '0x7a***2345'
Expand All @@ -13,14 +21,20 @@ export function shortenString(value: string, startCount = 4, endCount = 4, ellip
}

/**
* timestamped id with random string with timestamp
* Timestamped id with random string with timestamp
*/
export function getTimestampedID() {
return (Math.random().toString(36) + Date.now().toString(36)).slice(2)
}

/**
* formats time object to string with days, hours, minutes and seconds
*
* @param time { days, hours, mins, secs } time object defaults to 0
* @param negative pass `true` to allow negative results (default: false)
*
* @returns formatted time string
*
* @example
* formatTime({ days: 1, hours: 2, mins: 3, secs: 4 }) // '1d 2h 3m 4s'
* formatTime({ days: 1, hours: 2, mins: 3, secs: 4 }, true) // '-1d 2h 3m 4s'
Expand Down
46 changes: 46 additions & 0 deletions packages/utils/src/units/percent.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { expect, test } from 'vitest'
import { calcPercentValue, calcPercentage, decreaseByPercentage, increaseByPercentage } from './percent'

test('calc percent of the given value', () => {
expect(calcPercentValue('100', 10, 2)).toMatchInlineSnapshot('10n')
expect(calcPercentValue('100', 25, 2)).toMatchInlineSnapshot('25n')
expect(calcPercentValue(BigInt(125e9), 50, 9)).toMatchInlineSnapshot('62500000000n')
expect(calcPercentValue('1234567898765432123456789', 50, 18)).toMatchInlineSnapshot('617283949382716061728394n')
expect(calcPercentValue('1248933', 25.5, 6)).toMatchInlineSnapshot('318477n')
expect(calcPercentValue('1248933', 45.324624, 6)).toMatchInlineSnapshot('566074n')
expect(calcPercentValue(1000000, 60, 6)).toMatchInlineSnapshot('600000n')
expect(calcPercentValue(BigInt(100e18), 50, 18)).toMatchInlineSnapshot('50000000000000000000n')
expect(calcPercentValue(1e6, 0, 6)).toMatchInlineSnapshot('0n')
expect(calcPercentValue(50, 150, 0)).toMatchInlineSnapshot('75n')
expect(calcPercentValue(50, 1500000000000000, 0)).toMatchInlineSnapshot('750000000000000n')
})

test('calc percentage of the second value from the main value', () => {
expect(calcPercentage('100', '10', 2)).toMatchInlineSnapshot('10')
expect(calcPercentage('100', '25', 2)).toMatchInlineSnapshot('25')
expect(calcPercentage(BigInt(125e9), '62500000000', 9)).toMatchInlineSnapshot('50')
expect(calcPercentage('1234567898765432123456789', '617283949382716061728394', 18)).toMatchInlineSnapshot('50') // 49.9999999999999999999999594999999190000006
expect(calcPercentage('1248933', '318477', 6)).toMatchInlineSnapshot('25.5')
expect(calcPercentage('1248933', 566074, 6)).toMatchInlineSnapshot('45.325') // 45.3246090863160794
expect(calcPercentage('1248933', 566074, 6, 5)).toMatchInlineSnapshot('45.32461') // 45.3246090863160794
expect(calcPercentage(1000000, 600000, 6)).toMatchInlineSnapshot('60')
expect(calcPercentage(BigInt(100e18), '50000000000000000000', 18)).toMatchInlineSnapshot('50')
expect(calcPercentage(10000000000, 10000000, 10)).toMatchInlineSnapshot('0.1')
expect(calcPercentage(50, 75, 0)).toMatchInlineSnapshot('150')
expect(calcPercentage(50, 750, 0)).toMatchInlineSnapshot('1500')
expect(calcPercentage(1e6, 0, 6)).toMatchInlineSnapshot('0')
})

test('increase a number by given percentage', () => {
expect(increaseByPercentage('100', 10, 2)).toMatchInlineSnapshot('110n')
expect(increaseByPercentage('100', 25, 2)).toMatchInlineSnapshot('125n')
expect(increaseByPercentage('100', 0, 2)).toMatchInlineSnapshot('100n')
expect(increaseByPercentage(-100, 50, 9)).toMatchInlineSnapshot('-50n')
})

test('decease a number by given percentage', () => {
expect(decreaseByPercentage('100', 10, 2)).toMatchInlineSnapshot('90n')
expect(decreaseByPercentage('100', 25, 2)).toMatchInlineSnapshot('75n')
expect(decreaseByPercentage('100', 0, 2)).toMatchInlineSnapshot('100n')
expect(decreaseByPercentage(-100, 50, 9)).toMatchInlineSnapshot('-150n')
})
94 changes: 94 additions & 0 deletions packages/utils/src/units/percent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { scale } from './scale'
import { unScale, unScaleToBase } from './unscale'

/**
* Calculates the specified percentage of a given value.
*
* @param value - The value to calculate the percentage of
* @param percentage - The percentage to calculate
* @param valueDecimals - The decimals of the value.
*
* @returns The percentage of the given value scaled according to the specified decimals
*
* @example
* calcPercentValue(100, 10, 6) // 10
* calcPercentValue(100, 25, 6) // 25
* calcPercentValue(100e18, 50, 18) // 50000000000000000000n || 50e18
*/
export function calcPercentValue(
value: string | number | bigint, percentage: number | string | bigint, valueDecimals: number,
) {
return unScaleToBase(
BigInt(value) * scale(percentage, valueDecimals),
valueDecimals + valueDecimals + 2, // 2 is percentage decimals (100)
valueDecimals,
)
}

/**
* To avoid total loss of precision if the given decimals are not enough in case of more than 100%
*/
const percentCatalyst = 6

/**
* Calculates the percentage of the given secondary value from the main value
*
* @param value - The main value
* @param secondValue - The secondary value
* @param decimals - The decimals of the value.
* @param precision - The precision of the result. Default is 3.
*
* @returns The percentage with the given precision
*
* @example
* calcPercentage('100', '10', 2) // 10
* calcPercentage(50, 75, 0) // 150
* calcPercentage(BigInt(125e9), '62500000000', 9) // 50
* calcPercentage('1234567898765432123456789', '617283949382716061728394', 18) // 50
*/
export function calcPercentage(
value: string | number | bigint, secondValue: string | number | bigint, decimals: number, precision = 3,
) {
return Number(Number(unScale(
scale(BigInt(secondValue), decimals + decimals + percentCatalyst) / BigInt(value),
decimals + decimals + percentCatalyst - 2,
)).toFixed(precision))
}

/**
* Increase a number by given percentage
*
* @param value - The number to increase
* @param percentage - The percentage to increase by
* @param decimals - The decimals of the value.
*
* @returns The increased number (e.g. 100 + 10% of 100 = 110)
*
* @example
* increaseByPercentage('100', 10, 2) // 110
* increaseByPercentage('100', 25, 2) // 125
* increaseByPercentage(-100, 50, 9) // -50
*/
export function increaseByPercentage(value: string | bigint | number, percentage: number | string, decimals: number) {
value = BigInt(value)
return value + (calcPercentValue(value, percentage, decimals) * (value < BigInt(0) ? BigInt(-1) : BigInt(1)))
}

/**
* Decrease a number by given percentage
*
* @param value - The number to decrease
* @param percentage - The percentage to decrease by
* @param decimals - The decimals of the value.
*
* @returns The decreased number (e.g. 100 - 30% of 100 = 70)
*
* @example
* decreaseByPercentage('100', 10, 2) // 90
* decreaseByPercentage('100', 25, 2) // 75
* decreaseByPercentage(-100, 50, 9) // -150
*/
export function decreaseByPercentage(value: string | bigint | number, percentage: number | string, decimals: number) {
value = BigInt(value)
return value - (calcPercentValue(value, percentage, decimals) * (value < BigInt(0) ? BigInt(-1) : BigInt(1)))
}
1 change: 1 addition & 0 deletions packages/utils/src/units/scale.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ test('converts number to unit of a given length', () => {
expect(scale(1.2345, 4)).toMatchInlineSnapshot('12345n')
expect(scale(1.0045, 4)).toMatchInlineSnapshot('10045n')
expect(scale(1.2345000, 4)).toMatchInlineSnapshot('12345n')
expect(scale(1.2345000, 2)).toMatchInlineSnapshot('123n')
expect(scale('6942069420.12345678912345', 18)).toMatchInlineSnapshot('6942069420123456789123450000n')
expect(scale('6942069420.00045678912345', 18)).toMatchInlineSnapshot('6942069420000456789123450000n')
expect(scale('6942123123123069420.1234544444678912345', 50))
Expand Down
83 changes: 0 additions & 83 deletions packages/utils/src/web3.ts

This file was deleted.

82 changes: 0 additions & 82 deletions packages/utils/test/web3.test.ts

This file was deleted.

0 comments on commit 5025e44

Please sign in to comment.