-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
95 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { expect, test } from 'vitest' | ||
import { isMultipleOfMinimum, reduceByRemainder } from './multiple' | ||
|
||
test('is given value is multiple of given minimum', () => { | ||
expect(isMultipleOfMinimum('1000000000000000000', '1000000000000000000')).toMatchInlineSnapshot('true') | ||
expect(isMultipleOfMinimum('1000000000000000000', '1000000000000000001')).toMatchInlineSnapshot('false') | ||
expect(isMultipleOfMinimum('1000000000000000001', '1000000000000000000')).toMatchInlineSnapshot('false') | ||
expect(isMultipleOfMinimum('0', '1000000000000000000')).toMatchInlineSnapshot('false') | ||
expect(isMultipleOfMinimum('1000000000000000000', '0')).toMatchInlineSnapshot('false') | ||
expect(isMultipleOfMinimum('0', '0')).toMatchInlineSnapshot('false') | ||
expect(isMultipleOfMinimum('100', '1')).toMatchInlineSnapshot('true') | ||
expect(isMultipleOfMinimum('12356', '1')).toMatchInlineSnapshot('true') | ||
expect(isMultipleOfMinimum('123560', '10')).toMatchInlineSnapshot('true') | ||
expect(isMultipleOfMinimum('123560', '11')).toMatchInlineSnapshot('false') | ||
expect(isMultipleOfMinimum('55555555555555555555555555555555555555555555', '11')).toMatchInlineSnapshot('true') | ||
}) | ||
|
||
test('reduce value till multiple of minimum', () => { | ||
expect(reduceByRemainder('1000000000000000000', '1000000000000000000')).toMatchInlineSnapshot('1000000000000000000n') | ||
expect(reduceByRemainder('1000000000000000001', '1000000000000000000')).toMatchInlineSnapshot('1000000000000000000n') | ||
expect(reduceByRemainder('1000000000000000000', '1000000000000000001')).toMatchInlineSnapshot('0n') | ||
expect(reduceByRemainder('0', '1000000000000000000')).toMatchInlineSnapshot('0n') | ||
expect(reduceByRemainder('1000000000000000000', '0')).toMatchInlineSnapshot('0n') | ||
expect(reduceByRemainder('0', '0')).toMatchInlineSnapshot('0n') | ||
expect(reduceByRemainder('100', '1')).toMatchInlineSnapshot('100n') | ||
expect(reduceByRemainder('12356', '1')).toMatchInlineSnapshot('12356n') | ||
expect(reduceByRemainder('123560', '10')).toMatchInlineSnapshot('123560n') | ||
expect(reduceByRemainder('123560', '11')).toMatchInlineSnapshot('123552n') | ||
expect(reduceByRemainder('55555555555555555555555555555555555555555555', '11')) | ||
.toMatchInlineSnapshot('55555555555555555555555555555555555555555555n') | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { absBig } from './bigUtils' | ||
|
||
/** | ||
* Checks if the given value is a multiple of the specified minimum value. | ||
* Both the value and the minimum should be represented as strings to maintain precision | ||
* and should have the same scale (e.g., both represented in wei for Ethereum transactions). | ||
* | ||
* @param {string} value - The value to validate, as a string. | ||
* @param {string} minimum - The minimum value to validate against, as a string. | ||
* @returns {boolean} - True if the value is a multiple of the minimum and greater than or equal to the minimum value; otherwise, false. | ||
* | ||
* @example | ||
* isMultipleOfMinimum('123560', '10') // true | ||
* isMultipleOfMinimum('123560', '11') // false | ||
*/ | ||
export function isMultipleOfMinimum(value: string | bigint, minimum: string | bigint) { | ||
// (x != 0 && x % y == 0) | ||
value = absBig(value) | ||
minimum = absBig(minimum) | ||
const zero = BigInt(0) | ||
|
||
return value !== zero && minimum !== zero && value % minimum === zero && value >= minimum | ||
} | ||
|
||
/** | ||
* Returns the adjusted value to be a multiple of the minimum value. | ||
* Both `value` and `minimum` are expected to be strings representing numbers | ||
* with the same number of decimal places. The adjustment ensures that the returned | ||
* value is a multiple of the `minimum` and is less than or equal to the original `value`. | ||
* | ||
* @param {string} value - The value to adjust, should be in the same decimals as `minimum`. | ||
* @param {string} minimum - The minimum value to adjust against, should be in the same decimals as `value`. | ||
* @returns {string} - The adjusted value, in the same decimals as `value`, ensuring it's a multiple of `minimum`. | ||
* | ||
* @example | ||
* reduceByRemainder('123560', '10') // '123560' | ||
* reduceByRemainder('123560', '11') // '123552' | ||
*/ | ||
export function reduceByRemainder(value: string | bigint, minimum: string | bigint) { | ||
// Convert strings to BigInt for calculation | ||
value = BigInt(value) | ||
minimum = BigInt(minimum) | ||
const zero = BigInt(0) | ||
|
||
if (value === zero || minimum === zero) | ||
return zero | ||
|
||
// Check if value is already a multiple of minimum | ||
const remainder = value % minimum | ||
if (remainder === zero) | ||
return value | ||
|
||
return value - remainder | ||
} |