Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: units submodule #5009

Merged
merged 3 commits into from
Oct 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/shared/components/inputs/AssetAmountInput.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
formatTokenAmountDefault,
visibleSelectedAccountAssets,
} from '@core/wallet'
import { UNIT_MAP } from '@lib/units'
import { IOTA_UNIT_MAP } from '@core/utils'

export let inputElement: HTMLInputElement = undefined
export let disabled = false
Expand All @@ -34,7 +34,7 @@
allowedDecimals = 0
}
} else if (asset?.metadata?.useMetricPrefix) {
allowedDecimals = UNIT_MAP?.[unit?.substring(0, 1)] ?? 0
allowedDecimals = IOTA_UNIT_MAP?.[unit?.substring(0, 1)] ?? 0
}

function onClickAvailableBalance(): void {
Expand Down
12 changes: 6 additions & 6 deletions packages/shared/components/inputs/UnitInput.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="typescript">
import { Dropdown2, DropdownItem } from 'shared/components'
import { ITokenMetadata } from '@core/wallet'
import { Unit } from '@lib/units'
import { IotaUnit } from '@core/utils'

export let unit: string
export let isFocused: boolean
Expand All @@ -24,11 +24,11 @@
} else if (tokenMetadata?.useMetricPrefix && tokenMetadata?.unit) {
items = [
{ label: tokenMetadata?.unit, value: tokenMetadata?.unit },
{ label: Unit.K + tokenMetadata?.unit, value: Unit.K + tokenMetadata?.unit },
{ label: Unit.M + tokenMetadata?.unit, value: Unit.M + tokenMetadata?.unit },
{ label: Unit.G + tokenMetadata?.unit, value: Unit.G + tokenMetadata?.unit },
{ label: Unit.T + tokenMetadata?.unit, value: Unit.T + tokenMetadata?.unit },
{ label: Unit.P + tokenMetadata?.unit, value: Unit.P + tokenMetadata?.unit },
{ label: IotaUnit.K + tokenMetadata?.unit, value: IotaUnit.K + tokenMetadata?.unit },
{ label: IotaUnit.M + tokenMetadata?.unit, value: IotaUnit.M + tokenMetadata?.unit },
{ label: IotaUnit.G + tokenMetadata?.unit, value: IotaUnit.G + tokenMetadata?.unit },
{ label: IotaUnit.T + tokenMetadata?.unit, value: IotaUnit.T + tokenMetadata?.unit },
{ label: IotaUnit.P + tokenMetadata?.unit, value: IotaUnit.P + tokenMetadata?.unit },
]
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Unit } from '@lib/units'
import { IotaUnit } from '@core/utils'

/**
* The parameters of a send operation.
*/
export type SendOperationParameters = {
address: string
amount: string
unit: Unit
unit: IotaUnit
message: string
}
2 changes: 2 additions & 0 deletions packages/shared/lib/core/utils/constants/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export * from './bech32-address-length.constant'
export * from './hex.constants'
export * from './iota-unit-map.constant'
export * from './max-number-of-iotas.constant'
export * from './pin-length.constant'
11 changes: 11 additions & 0 deletions packages/shared/lib/core/utils/constants/iota-unit-map.constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { IotaUnit } from '../enums'
import { IotaUnitMap } from '../types'

export const IOTA_UNIT_MAP: IotaUnitMap = {
[IotaUnit._]: { value: 1, decimalPlaces: 0 },
[IotaUnit.K]: { value: 1000, decimalPlaces: 3 },
[IotaUnit.M]: { value: 1000000, decimalPlaces: 6 },
[IotaUnit.G]: { value: 1000000000, decimalPlaces: 9 },
[IotaUnit.T]: { value: 1000000000000, decimalPlaces: 12 },
[IotaUnit.P]: { value: 1000000000000000, decimalPlaces: 15 },
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const MAX_NUM_IOTAS = 2_779_530_283_277_761
1 change: 1 addition & 0 deletions packages/shared/lib/core/utils/enums/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './expiration-time.enum'
export * from './iota-unit.enum'
8 changes: 8 additions & 0 deletions packages/shared/lib/core/utils/enums/iota-unit.enum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export enum IotaUnit {
_ = '_',
K = 'k',
M = 'M',
G = 'G',
T = 'T',
P = 'P',
}
3 changes: 2 additions & 1 deletion packages/shared/lib/core/utils/format.utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { HEXADECIMAL_PREFIX, HEXADECIMAL_REGEXP } from './constants'
import { formatDate } from '@core/i18n'

import { HEXADECIMAL_PREFIX, HEXADECIMAL_REGEXP } from './constants'

export function capitalizeString(str: string): string {
if (!str) return str
else return str[0].toUpperCase() + str.substr(1).toLowerCase()
Expand Down
1 change: 1 addition & 0 deletions packages/shared/lib/core/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ export * from './sort.utils'
export * from './string.utils'
export * from './time.utils'
export * from './ui.utils'
export * from './unit.utils'
export * from './validation.utils'
2 changes: 2 additions & 0 deletions packages/shared/lib/core/utils/types/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export * from './dropdown.interface'
export * from './iota-unit-map.type'
export * from './values-of.type'
8 changes: 8 additions & 0 deletions packages/shared/lib/core/utils/types/iota-unit-map.type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { IotaUnit } from '../enums'

export type IotaUnitMap = {
[unit in IotaUnit]: {
value: number
decimalPlaces: number
}
}
90 changes: 90 additions & 0 deletions packages/shared/lib/core/utils/unit.utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import Big from 'big.js'

import { formatNumber, getCurrencyPosition } from '@lib/currency'

import { IOTA_UNIT_MAP } from './constants'
import { IotaUnit } from './enums'

/**
* CAUTION: Set this to avoid small numbers switching to exponential format.
*/
Big.NE = -20

export function convertIotaUnit(value: number, fromUnit: IotaUnit, toUnit: IotaUnit): number {
if (value === 0) {
return 0
}

if (fromUnit === toUnit) {
return value
}

const scaledValue = Number(new Big(value).times(IOTA_UNIT_MAP[fromUnit].value).div(IOTA_UNIT_MAP[toUnit].value))

return toUnit === IotaUnit._ ? Math.round(scaledValue) : scaledValue
}

export function formatIotaUnitPrecision(
valueRaw: number,
unit: IotaUnit,
includeUnits: boolean = true,
grouped: boolean = false,
overrideDecimalPlaces?: number
): string {
// At the moment we have no symbol for IOTA so we always put the currency code
// at the end, in the future when we have a symbol this can be updated to position
// it correctly to the left when necessary
const currencyPosition = getCurrencyPosition()

if (!valueRaw) {
return includeUnits ? (currencyPosition === 'left' ? `0 ${unit}` : `0 ${unit}`) : '0'
}

const converted = convertIotaUnit(valueRaw, IotaUnit._, unit)

const formatted = formatNumber(
converted,
overrideDecimalPlaces ?? IOTA_UNIT_MAP[unit].decimalPlaces,
overrideDecimalPlaces ?? IOTA_UNIT_MAP[unit].decimalPlaces,
unit === IotaUnit._ ? 0 : 2,
grouped
)

if (includeUnits) {
return currencyPosition === 'left' ? `${formatted} ${unit}` : `${formatted} ${unit}`
} else {
return formatted
}
}

export function formatIotaUnitBestMatch(
value: number,
includeUnits: boolean = true,
overrideDecimalPlaces?: number
): string {
return formatIotaUnitPrecision(value, getIotaUnit(value), includeUnits, false, overrideDecimalPlaces)
}

export function getIotaUnit(value: number): IotaUnit {
let bestUnits: IotaUnit = IotaUnit._

if (!value || value === 0) {
return IotaUnit.M
}

const checkLength = Math.abs(value).toString().length

if (checkLength > IOTA_UNIT_MAP.P.decimalPlaces) {
bestUnits = IotaUnit.P
} else if (checkLength > IOTA_UNIT_MAP.T.decimalPlaces) {
bestUnits = IotaUnit.T
} else if (checkLength > IOTA_UNIT_MAP.G.decimalPlaces) {
bestUnits = IotaUnit.G
} else if (checkLength > IOTA_UNIT_MAP.M.decimalPlaces) {
bestUnits = IotaUnit.M
} else if (checkLength > IOTA_UNIT_MAP.k.decimalPlaces) {
bestUnits = IotaUnit.K
}

return bestUnits
}
4 changes: 2 additions & 2 deletions packages/shared/lib/core/wallet/utils/convertToRawAmount.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Big from 'big.js'
import { IOTA_UNIT_MAP } from '@core/utils'
import { parseCurrency } from '@lib/currency'
import { UNIT_MAP } from '@lib/units'
import { ITokenMetadata } from '../interfaces'
import { MAX_SUPPORTED_DECIMALS } from '../constants/max-supported-decimals.constants'

Expand All @@ -15,7 +15,7 @@ export function convertToRawAmount(amount: string, unit: string, tokenMetadata?:

function convertToRawAmountFromMetadata(amount: number, unit: string, tokenMetadata: ITokenMetadata): Big {
if (tokenMetadata.useMetricPrefix) {
return Big(amount * UNIT_MAP?.[unit?.substring(0, 1)] ?? 0)
return Big(amount * IOTA_UNIT_MAP?.[unit?.substring(0, 1)] ?? 0)
} else {
if (unit && unit === tokenMetadata.unit) {
const decimals = Math.min(tokenMetadata.decimals, MAX_SUPPORTED_DECIMALS)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { getIotaUnit, IOTA_UNIT_MAP } from '@core/utils'
import { formatNumber } from '@lib/currency'
import { getUnit, UNIT_MAP } from '@lib/units'

import { ITokenMetadata } from '../interfaces'
import { formatTokenAmountDefault } from './formatTokenAmountDefault'

Expand All @@ -13,9 +14,9 @@ export function formatTokenAmountBestMatch(
let amountWithUnit: string

if (tokenMetadata?.useMetricPrefix) {
const metricUnit = getUnit(amount)
const maxDecimals = overrideDecimalPlaces ?? UNIT_MAP[metricUnit].dp
const convertedAmount = amount / UNIT_MAP[metricUnit].val
const metricUnit = getIotaUnit(amount)
const maxDecimals = overrideDecimalPlaces ?? IOTA_UNIT_MAP[metricUnit].decimalPlaces
const convertedAmount = amount / IOTA_UNIT_MAP[metricUnit].value
amountWithoutUnit = formatNumber(convertedAmount, 0, maxDecimals, undefined, true)
amountWithUnit = amountWithoutUnit + ' ' + metricUnit + tokenMetadata.unit
} else {
Expand Down
4 changes: 2 additions & 2 deletions packages/shared/lib/currency.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { get, writable } from 'svelte/store'
import Big from 'big.js'
import { appSettings } from '@core/app'
import { activeProfile } from '@core/profile'
import { formatUnitBestMatch } from './units'
import { AvailableExchangeRates, Currencies, CurrencyTypes, ExchangeRates } from './typings/currency'
import { formatIotaUnitBestMatch } from '@core/utils'
/**
* Default exchange rates
*/
Expand Down Expand Up @@ -125,7 +125,7 @@ export const formatCurrencyValue = (
const parsedData: number = parseFloat(data.toString())
switch (currency.toLowerCase()) {
case CurrencyTypes.IOTA:
return formatUnitBestMatch(parsedData)
return formatIotaUnitBestMatch(parsedData)
case CurrencyTypes.BTC:
return replaceCurrencyDecimal(parsedData.toFixed(btcFixed), 'USD')
case CurrencyTypes.ETH:
Expand Down
6 changes: 3 additions & 3 deletions packages/shared/lib/transactionHistory.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { IAccountState } from '@core/account'
import { formatDate, localize } from '@core/i18n'
import { formatUnitBestMatch } from './units'
import { formatIotaUnitBestMatch } from '@core/utils'

interface ITransactionHistoryHeaderParameters {
id?: boolean
Expand Down Expand Up @@ -33,8 +33,8 @@ export function generateTransactionHistoryCsvFromAccount(
const { internal, incoming, value } = message.payload.data.essence.data
const valueString = incoming ? String(value) : '-' + value
const formattedValueString = incoming
? formatUnitBestMatch(value, true)
: '-' + formatUnitBestMatch(value, true)
? formatIotaUnitBestMatch(value, true)
: '-' + formatIotaUnitBestMatch(value, true)
let date
let time
try {
Expand Down
3 changes: 1 addition & 2 deletions packages/shared/lib/typings/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as currency from './currency'
import * as events from './events'
import * as message from './message'
import * as utils from './utils'
import * as wallet from './dateDifference'

export { currency, events, message, utils, wallet }
export { currency, events, message, wallet }