diff --git a/.vscode/settings.json b/.vscode/settings.json index 3d8caac0..4231f1a6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,10 +1,6 @@ { - "[javascriptreact][typescriptreact]": { + "[javascriptreact][typescriptreact][javascript][typescript]": { "editor.insertSpaces": true, - "editor.tabSize": 2 - }, - "[javascript][typescript]": { - "editor.insertSpaces": true, - "editor.tabSize": 2 - } + "editor.tabSize": 4 + } } \ No newline at end of file diff --git a/src/components/AmountInputHeader.tsx b/src/components/AmountInputHeader.tsx index 1b0875a8..a1a51d7e 100644 --- a/src/components/AmountInputHeader.tsx +++ b/src/components/AmountInputHeader.tsx @@ -1,121 +1,179 @@ -import React from 'react' -import { View, ViewStyle, TextInput } from 'react-native' -import { AmountInput } from "./AmountInput" -import { CurrencyAmount } from '../screens/Wallet/CurrencyAmount' -import { Text, Icon } from './' -import { spacing, useThemeColor } from '../theme' import { verticalScale } from '@gocodingnow/rn-size-matters' -import { TransactionStatus } from '../models/Transaction' -import { MintUnit, CurrencyCode, getCurrency, convertToFromSats } from '../services/wallet/currency' +import React, { useState } from 'react' +import { TextInput, TextStyle, TouchableOpacity, View, ViewStyle } from 'react-native' import { useStores } from '../models' +import type { Mint } from '../models/Mint' +import { TransactionStatus } from '../models/Transaction' +import { MintHeader } from '../screens/Mints/MintHeader' +import { CurrencyAmount } from '../screens/Wallet/CurrencyAmount' +import { convertToFromSats, convertToSatsFrom, CurrencyCode, getCurrency, getCurrencyByCode, MintUnit } from '../services/wallet/currency' +import { spacing, useThemeColor } from '../theme' import { round, toNumber } from '../utils/number' +import { AmountInput, Icon, Text } from './index' +import { log } from '../services' interface IAmountInputHeaderProps { - amountInputRef: React.RefObject - amountToSend: string - setAmountToSend: (amount: string) => void - unit: MintUnit - onAmountEndEditing?: () => void - transactionStatus?: TransactionStatus - isCashuPrWithAmount?: boolean - lockedPubkey?: string - unitRef: React.RefObject + amountInputRef: React.RefObject + amountToSend: string + setAmountToSend: (amount: string) => void + unit: MintUnit + onAmountEndEditing?: () => void + transactionStatus?: TransactionStatus + isCashuPrWithAmount?: boolean + lockedPubkey?: string + unitRef: React.RefObject + mintHeaderMint: Mint } const $amountContainer: ViewStyle = { - alignItems: 'center', - justifyContent: 'center', + alignItems: 'center', + justifyContent: 'center', +} + +const $headerContainer: TextStyle = { + alignItems: 'center', + padding: spacing.extraSmall, + paddingTop: 0, + height: spacing.screenHeight * 0.30, +} + +const $pubKey: ViewStyle = { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + marginTop: -spacing.extraSmall } export function AmountInputHeader(props: IAmountInputHeaderProps) { - const { userSettingsStore, walletStore } = useStores() + const { userSettingsStore, walletStore } = useStores() + const [isFiatMode, setIsFiatMode] = useState(false) - const amountInputColor = useThemeColor('amountInput'); - const convertedAmountColor = useThemeColor('headerSubTitle'); + const amountInputColor = useThemeColor('amountInput'); + const convertedAmountColor = useThemeColor('headerSubTitle'); + const headerBg = useThemeColor('header') - const { - amountInputRef, - amountToSend, - setAmountToSend, - unit, - onAmountEndEditing, - transactionStatus, - isCashuPrWithAmount, - lockedPubkey, - unitRef - } = props + const { + amountInputRef, + amountToSend, + setAmountToSend, + unit, + onAmountEndEditing, + transactionStatus, + isCashuPrWithAmount, + lockedPubkey, + unitRef, + mintHeaderMint + } = props - const isConvertedAmountVisible = () => { - return ( - walletStore.exchangeRate && - (userSettingsStore.exchangeCurrency === getCurrency(unit).code || - unit === 'sat') && - getConvertedAmount() !== undefined - ) - } + const fiatCurrency = userSettingsStore.exchangeCurrency + const isFiatSupported = fiatCurrency === CurrencyCode.USD || fiatCurrency === CurrencyCode.EUR + const canUseFiatMode = isFiatSupported && walletStore.exchangeRate && unit === 'sat' - const getConvertedAmount = () => { - if (!walletStore.exchangeRate) return undefined; + const getFiatUnit = () => { + const currencyData = getCurrencyByCode(fiatCurrency) + return currencyData?.mintUnit || 'sat' + } - const precision = getCurrency(unitRef.current).precision - return convertToFromSats( - round(toNumber(amountToSend) * precision, 0) || 0, - getCurrency(unitRef.current).code, - walletStore.exchangeRate - ) - } + // Convert FIAT amount to display units (e.g., sats to mBTC) + const FIATtoSATS = (inputAmount: string) => { + if (!walletStore.exchangeRate) return undefined; + log.trace("er:", walletStore.exchangeRate) - return - setAmountToSend(amount)} - unit={unit} - onEndEditing={transactionStatus !== TransactionStatus.PENDING ? onAmountEndEditing : undefined} - editable={!(transactionStatus === TransactionStatus.PENDING || isCashuPrWithAmount)} - style={{ color: amountInputColor }} - /> - {isConvertedAmountVisible() && ( - - )} - {lockedPubkey ? ( - - - { + if (!walletStore.exchangeRate) return undefined; + log.trace("er:", walletStore.exchangeRate) + + const precision = getCurrency(unitRef.current).precision + return convertToFromSats( + round(toNumber(inputAmount) * precision, 0) || 0, + getCurrency(unitRef.current).code, + walletStore.exchangeRate + ) + } + + const isConvertedAmountVisible = () => { + return canUseFiatMode && walletStore.exchangeRate + } + + const handleAmountChange = (amount: string) => { + if (isFiatMode) { + setAmountToSend(FIATtoSATS(amount).toString()) + } else { + setAmountToSend(amount) + } + } + + return + + + {isFiatMode && canUseFiatMode ? ( + setAmountToSend(FIATtoSATS(amount).toString())} + unit={getFiatUnit()} + onEndEditing={transactionStatus !== TransactionStatus.PENDING ? onAmountEndEditing : undefined} + style={{ color: amountInputColor }} + /> + ) : ( + + )} + {isConvertedAmountVisible() && ( + canUseFiatMode && setIsFiatMode(!isFiatMode)}> + + + )} + {lockedPubkey ? ( + + + - - ) : ( - - )} - + + ) : ( + + )} + + } \ No newline at end of file diff --git a/src/screens/SendScreen.tsx b/src/screens/SendScreen.tsx index da82b61f..3128ac28 100644 --- a/src/screens/SendScreen.tsx +++ b/src/screens/SendScreen.tsx @@ -1000,7 +1000,6 @@ export const SendScreen = observer(function SendScreen({ route }: Props) { setError(e) } - const headerBg = useThemeColor('header') const hintColor = useThemeColor('textDim') const inputText = useThemeColor('text') const inputBg = useThemeColor('background') @@ -1032,12 +1031,7 @@ export const SendScreen = observer(function SendScreen({ route }: Props) { return ( - - - - + mintHeaderMint={mintBalanceToSendFrom ? mintsStore.findByUrl(mintBalanceToSendFrom?.mintUrl) : undefined} + /> {!encodedTokenToSend && ( { return currencyData as CurrencyData } +export const getCurrencyByCode = (code: CurrencyCode): CurrencyData | undefined => { + for (const [currencyCode, currencyData] of Object.entries(Currencies)) { + if (currencyCode === code && currencyData) { + return currencyData satisfies CurrencyData + } + } + return void 0; +} + export const convertToFromSats = (amount: number, currencyFrom: CurrencyCode, satExchangeRate: ExchangeRate) => { // exchangeRate is always 1 fiat precision unit (cent) in SAT {currency: 'EUR', rate: 15.69} @@ -163,5 +172,15 @@ export const convertToFromSats = (amount: number, currencyFrom: CurrencyCode, sa } return amount * satExchangeRate.rate +} + +export const convertToSatsFrom = (amount: number, currencyFrom: CurrencyCode, satExchangeRate: ExchangeRate) => { + // exchangeRate is always 1 fiat precision unit (cent) in SAT {currency: 'EUR', rate: 15.69} + + if(currencyFrom === CurrencyCode.SAT) { + return amount * satExchangeRate.rate + } + + return amount / satExchangeRate.rate } \ No newline at end of file