Skip to content

Commit

Permalink
591 add mas object (#593)
Browse files Browse the repository at this point in the history
Co-authored-by: AurelienFT <[email protected]>
Co-authored-by: BenRey <[email protected]>
Co-authored-by: ASAPSegfault <[email protected]>
Co-authored-by: BenRey <[email protected]>
  • Loading branch information
5 people authored May 3, 2024
1 parent 04b3e14 commit e0f6fcf
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 5 deletions.
13 changes: 8 additions & 5 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
*.config.js
*.config.ts
package*.json
.eslintrc.cjs
bundle*.js

packages/web3-utils
packages/massa-web3/examples
packages/massa-web3/code-snippets
Expand All @@ -6,10 +12,7 @@ packages/massa-web3/src/utils
packages/massa-web3/src/web3
packages/massa-web3/src/index.ts
packages/massa-web3/test

**/generated/**
**/dist/**
**/docs/**
*.config.js
*.config.ts
package*.json
.eslintrc.cjs
**/docs/**
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from './operationManager'
export * from './operation'
export * from './storage'
export * from './args'
export * as Mas from './mas'
131 changes: 131 additions & 0 deletions packages/massa-web3/src/experimental/basicElements/mas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import { FIRST, ONE } from '../utils'

const NB_DECIMALS = 9
const POWER_TEN = 10
const SIZE_U256_BIT = 256

export const ERROR_NOT_SAFE_INTEGER = 'value is not a safe integer.'
export const ERROR_VALUE_TOO_LARGE = 'value is too large.'

export type Mas = bigint

/**
* Converts an integer value to the smallest unit of the Massa currency.
*
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger#description
*
* @param value - The integer value.
* @returns The value in the smallest unit of the Massa currency.
*
* @throws An error if the value is not a safe integer.
*/
export function fromMas(value: number): Mas {
if (!Number.isSafeInteger(value)) {
throw new Error(ERROR_NOT_SAFE_INTEGER)
}

return BigInt(value * POWER_TEN ** NB_DECIMALS)
}

/**
* Converts an integer value in milli Massa to the smallest unit of the Massa currency.
*
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger#description
*
* @param value - The value in milli Massa.
* @returns The value in the smallest unit of the Massa currency.
*
* @throws An error if the value is not a safe integer.
*/
export function fromMilliMas(value: number): Mas {
if (!Number.isSafeInteger(value)) {
throw new Error(ERROR_NOT_SAFE_INTEGER)
}
const milli = 3
return BigInt(value * POWER_TEN ** (NB_DECIMALS - milli))
}

/**
* Converts an integer value in micro Massa to the smallest unit of the Massa currency.
*
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger#description
*
* @param value - The value in micro Massa.
* @returns The value in the smallest unit of the Massa currency.
*
* @throws An error if the value is not a safe integer.
*/
export function fromMicroMas(value: number): Mas {
if (!Number.isSafeInteger(value)) {
throw new Error(ERROR_NOT_SAFE_INTEGER)
}
const micro = 6
return BigInt(value * POWER_TEN ** (NB_DECIMALS - micro))
}

/**
* Converts an integer value in nano Massa to the smallest unit of the Massa currency.
*
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger#description
*
* @param value - The value in nano Massa.
* @returns The value in the smallest unit of the Massa currency.
*
* @throws An error if the value is not a safe integer.
*/
export function fromNanoMas(value: number): Mas {
if (!Number.isSafeInteger(value)) {
throw new Error(ERROR_NOT_SAFE_INTEGER)
}

const nano = 9
return BigInt(value * POWER_TEN ** (NB_DECIMALS - nano))
}

/**
* Converts a decimal value to the smallest unit of the Massa currency.
*
* @param value - The decimal value.
* @returns The value in the smallest unit of the Massa currency.
*
* @throws An error if the format is not a decimal.
* @throws An error if the value is too large to be represented by an U256 or has too many decimals.
*/
export function fromString(value: string): Mas {
const parts = value.split('.')
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
if (parts.length > 2) {
throw new Error('invalid format')
}

const integerPart = parts[FIRST]
const decimalPart = parts[ONE] || ''
if (decimalPart.length > NB_DECIMALS) {
throw new Error(ERROR_VALUE_TOO_LARGE)
}

const mas = BigInt(integerPart + decimalPart.padEnd(NB_DECIMALS, '0'))
if (mas >= BigInt(ONE) << BigInt(SIZE_U256_BIT)) {
throw new Error(ERROR_VALUE_TOO_LARGE)
}

return mas
}

/**
* Converts a value in the smallest unit of the Massa currency to a decimal value.
*
* @param value - The value in the smallest unit of the Massa currency.
* @returns The decimal value.
*
* @throws An error if the value is too large to be represented by an U256.
*/
export function toString(value: Mas): string {
if (value >= BigInt(ONE) << BigInt(SIZE_U256_BIT)) {
throw new Error(ERROR_VALUE_TOO_LARGE)
}
const valueString = value.toString()
const integerPart = valueString.slice(FIRST, -NB_DECIMALS) || '0'
const decimalPart = valueString.slice(-NB_DECIMALS).replace(/0+$/, '')
return `${integerPart}${decimalPart.length ? '.' + decimalPart : ''}`
}
40 changes: 40 additions & 0 deletions packages/massa-web3/test/experimental/unit/mas.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Mas } from '../../../src/experimental/basicElements'

describe('amount conversion', () => {
it('converts from integer', () => {
expect(Mas.fromMas(1)).toStrictEqual(1_000_000_000n)
expect(Mas.fromMas(1234)).toStrictEqual(1_234_000_000_000n)
expect(() => Mas.fromMas(1.1)).toThrow(Mas.ERROR_NOT_SAFE_INTEGER)

expect(Mas.fromMilliMas(1)).toStrictEqual(1_000_000n)
expect(Mas.fromMilliMas(1234)).toStrictEqual(1_234_000_000n)
expect(() => Mas.fromMilliMas(1.1)).toThrow(Mas.ERROR_NOT_SAFE_INTEGER)

expect(Mas.fromMicroMas(1)).toStrictEqual(1_000n)
expect(Mas.fromMicroMas(1234)).toStrictEqual(1_234_000n)
expect(() => Mas.fromMicroMas(1.1)).toThrow(Mas.ERROR_NOT_SAFE_INTEGER)

expect(Mas.fromNanoMas(1)).toStrictEqual(1n)
expect(Mas.fromNanoMas(1234)).toStrictEqual(1_234n)
expect(() => Mas.fromNanoMas(1.1)).toThrow(Mas.ERROR_NOT_SAFE_INTEGER)
})

it('converts from string', () => {
expect(Mas.fromString('1')).toStrictEqual(1_000_000_000n)
expect(Mas.fromString('1.1')).toStrictEqual(1_100_000_000n)
expect(Mas.fromString('01234.56789')).toStrictEqual(1_234_567_890_000n)
expect(Mas.fromString('01234.567890000')).toStrictEqual(1_234_567_890_000n)
expect(() => Mas.fromString('1.1.1')).toThrow()
expect(() => Mas.fromString('0.1234567890')).toThrow()
expect(() =>
Mas.fromString((BigInt(1) << BigInt(256)).toString())
).toThrow()
})

it('converts to string', () => {
expect(Mas.toString(1_000_000_000n)).toStrictEqual('1')
expect(Mas.toString(1_100_000_000n)).toStrictEqual('1.1')
expect(Mas.toString(1_234_567_890_000n)).toStrictEqual('1234.56789')
expect(() => Mas.toString(BigInt(1) << BigInt(256))).toThrow()
})
})

2 comments on commit e0f6fcf

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage report for experimental massa-web3

St.❔
Category Percentage Covered / Total
πŸ”΄ Statements 58.6% 603/1029
πŸ”΄ Branches 37.23% 86/231
πŸ”΄ Functions 57.22% 111/194
πŸ”΄ Lines 58.71% 603/1027

Test suite run success

57 tests passing in 10 suites.

Report generated by πŸ§ͺjest coverage report action from e0f6fcf

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage report for experimental massa-web3

St.❔
Category Percentage Covered / Total
πŸ”΄ Statements 58.6% 603/1029
πŸ”΄ Branches 37.23% 86/231
πŸ”΄ Functions 57.22% 111/194
πŸ”΄ Lines 58.71% 603/1027

Test suite run success

57 tests passing in 10 suites.

Report generated by πŸ§ͺjest coverage report action from e0f6fcf

Please sign in to comment.