@ledgerhq/live-common
Version:
Common ground for the Ledger Live apps
99 lines (86 loc) • 3.24 kB
text/typescript
import { BigNumber } from "bignumber.js";
import type { Unit } from "@ledgerhq/types-cryptoassets";
import { formatCurrencyUnit } from "@ledgerhq/coin-framework/currencies/formatCurrencyUnit";
import { sanitizeValueString } from "@ledgerhq/ledger-wallet-framework/currencies/sanitizeValueString";
import { clampDecimals, isOverDecimalLimit, trimTrailingZeros } from "./decimals";
export type FormattedAmount = Readonly<{
display: string;
value: BigNumber;
}>;
const formatUnitForInput = (unit: Unit, amount: BigNumber, locale: string): string =>
formatCurrencyUnit(unit, amount, {
showCode: false,
disableRounding: true,
useGrouping: false,
locale,
});
export function formatAmountForInput(unit: Unit, amount: BigNumber, locale: string): string {
if (amount.isZero()) return "";
return formatUnitForInput(unit, amount, locale);
}
export function formatFiatForInput(unit: Unit, amount: BigNumber, locale: string): string {
if (amount.isZero()) return "";
const formatted = formatUnitForInput(unit, amount, locale);
return trimTrailingZeros(clampDecimals(formatted));
}
export function processRawInput(rawValue: string, unit: Unit, locale: string): FormattedAmount {
const sanitized = sanitizeValueString(unit, rawValue, locale);
const value = sanitized.value ? new BigNumber(sanitized.value) : new BigNumber(0);
return {
display: sanitized.display,
value: value.isFinite() && !value.isNaN() ? value : new BigNumber(0),
};
}
export function processFiatInput(
rawValue: string,
fiatUnit: Unit,
locale: string,
): Readonly<{
display: string;
clampedDisplay: string;
value: BigNumber;
isOverLimit: boolean;
}> {
const sanitized = sanitizeValueString(fiatUnit, rawValue, locale);
const clampedDisplay = clampDecimals(sanitized.display);
const nextSanitized = sanitizeValueString(fiatUnit, clampedDisplay, locale);
const value = nextSanitized.value ? new BigNumber(nextSanitized.value) : new BigNumber(0);
// Keep the same behavior as the hook did previously:
// - we clamp what is displayed,
// - and we avoid pushing transaction updates while the user is typing > 2 decimals.
const isOverLimit = isOverDecimalLimit(sanitized.display);
return {
display: sanitized.display,
clampedDisplay,
value,
isOverLimit,
};
}
export function calculateFiatEquivalent(params: {
amount: BigNumber;
lastTransactionAmount: BigNumber;
lastFiatAmount: BigNumber;
calculateFiatFromCrypto: (amount: BigNumber) => BigNumber | null | undefined;
}): BigNumber | null {
const directFiat = params.calculateFiatFromCrypto(params.amount);
const ratioFiat =
params.lastTransactionAmount &&
!params.lastTransactionAmount.isZero() &&
params.lastFiatAmount &&
!params.lastFiatAmount.isZero()
? params.lastFiatAmount.multipliedBy(params.amount).dividedBy(params.lastTransactionAmount)
: null;
return directFiat ?? ratioFiat;
}
export function shouldSyncInput(params: {
isQuickAction: boolean;
useAllAmountChanged: boolean;
isActiveInput: boolean;
hasInputValue: boolean;
}): boolean {
return (
params.isQuickAction ||
params.useAllAmountChanged ||
!(params.isActiveInput && params.hasInputValue)
);
}