UNPKG

@ledgerhq/live-common

Version:
126 lines (106 loc) 4.61 kB
import type { Dispatch, MutableRefObject, SetStateAction } from "react"; import type { BigNumber } from "bignumber.js"; import type { Unit } from "@ledgerhq/types-cryptoassets"; import { formatAmountForInput, formatFiatForInput, shouldSyncInput } from "./amountInput"; type SyncAmountInputsParams = { cryptoAmount: BigNumber; fiatAmount: BigNumber; transactionUseAllAmount: boolean; inputMode: "fiat" | "crypto"; cryptoInputValue: string; fiatInputValue: string; locale: string; accountUnit: Unit; fiatUnit: Unit; lastTransactionAmountRef: MutableRefObject<BigNumber | null>; lastFiatAmountRef: MutableRefObject<BigNumber | null>; lastUseAllAmountRef: MutableRefObject<boolean>; lastUserInputTimeRef: MutableRefObject<number>; setCryptoInputValue: Dispatch<SetStateAction<string>>; setFiatInputValue: Dispatch<SetStateAction<string>>; }; type SyncFlags = { useAllAmountChanged: boolean; cryptoAmountChanged: boolean; fiatAmountChanged: boolean; canSyncWithBridge: boolean; isQuickAction: boolean; inputsEmptyButHaveAmount: boolean; }; const INPUT_SYNC_DELAY_MS = 200; const shouldRunCryptoSync = ({ cryptoAmountChanged, canSyncWithBridge, inputsEmptyButHaveAmount, }: SyncFlags) => (cryptoAmountChanged && canSyncWithBridge) || inputsEmptyButHaveAmount; const shouldRunFiatSync = ({ cryptoAmountChanged, fiatAmountChanged, canSyncWithBridge, inputsEmptyButHaveAmount, }: SyncFlags) => ((cryptoAmountChanged || fiatAmountChanged) && canSyncWithBridge) || inputsEmptyButHaveAmount; function syncCryptoInput(params: SyncAmountInputsParams, flags: SyncFlags): void { if (!shouldRunCryptoSync(flags)) return; params.lastTransactionAmountRef.current = params.cryptoAmount; const shouldSyncCrypto = shouldSyncInput({ isQuickAction: flags.isQuickAction, useAllAmountChanged: flags.useAllAmountChanged, isActiveInput: params.inputMode === "crypto", hasInputValue: params.cryptoInputValue.length > 0, }); if (shouldSyncCrypto || flags.inputsEmptyButHaveAmount) { const formatted = formatAmountForInput(params.accountUnit, params.cryptoAmount, params.locale); params.setCryptoInputValue(formatted); } } function syncFiatInput(params: SyncAmountInputsParams, flags: SyncFlags): void { if (!shouldRunFiatSync(flags)) return; params.lastFiatAmountRef.current = params.fiatAmount; const shouldSyncFiat = shouldSyncInput({ isQuickAction: flags.isQuickAction, useAllAmountChanged: flags.useAllAmountChanged, isActiveInput: params.inputMode === "fiat", hasInputValue: params.fiatInputValue.length > 0, }); if (shouldSyncFiat || flags.inputsEmptyButHaveAmount) { const formatted = formatFiatForInput(params.fiatUnit, params.fiatAmount, params.locale); params.setFiatInputValue(formatted); } } export function syncAmountInputs(params: SyncAmountInputsParams): void { const useAllAmountChanged = params.transactionUseAllAmount !== params.lastUseAllAmountRef.current; const lastCrypto = params.lastTransactionAmountRef.current; const lastFiat = params.lastFiatAmountRef.current; const cryptoAmountChanged = lastCrypto === null || !params.cryptoAmount.eq(lastCrypto) || useAllAmountChanged; const fiatAmountChanged = lastFiat === null || !params.fiatAmount.eq(lastFiat); const timeSinceUserInput = Date.now() - (params.lastUserInputTimeRef.current ?? 0); // When useAllAmount is active and amount changes, always sync immediately // This handles fee changes that affect the max amount (e.g., switching from medium to fast fees) const isUseAllAmountActive = params.transactionUseAllAmount && cryptoAmountChanged; const canSyncWithBridge = useAllAmountChanged || isUseAllAmountActive || timeSinceUserInput > INPUT_SYNC_DELAY_MS; const isQuickAction = params.lastUserInputTimeRef.current === 0; // After remount (e.g. back from CustomFees), repopulate inputs explicitly const inputsEmptyButHaveAmount = params.cryptoAmount.gt(0) && params.cryptoInputValue.length === 0 && params.fiatInputValue.length === 0 && canSyncWithBridge; const flags: SyncFlags = { useAllAmountChanged, cryptoAmountChanged, fiatAmountChanged, canSyncWithBridge, isQuickAction, inputsEmptyButHaveAmount, }; // Consume useAllAmount toggle so it doesn't stay true across renders and bypass typing-delay guards if (flags.useAllAmountChanged) { params.lastUseAllAmountRef.current = params.transactionUseAllAmount; params.lastUserInputTimeRef.current = 0; } syncCryptoInput(params, flags); syncFiatInput(params, flags); }