Skip to content

Commit

Permalink
Currency Converter
Browse files Browse the repository at this point in the history
  • Loading branch information
shubhamkmr04 committed Feb 2, 2024
1 parent 256f0b2 commit d55c28f
Show file tree
Hide file tree
Showing 4 changed files with 237 additions and 2 deletions.
4 changes: 4 additions & 0 deletions Navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ import LspExplanationFees from './views/Explanations/LspExplanationFees';
import LspExplanationRouting from './views/Explanations/LspExplanationRouting';
import LspExplanationWrappedInvoices from './views/Explanations/LspExplanationWrappedInvoices';
import LspExplanationOverview from './views/Explanations/LspExplanationOverview';
import CurrencyConverter from './views/Settings/CurrencyConverter';

const AppScenes = {
Wallet: {
Expand Down Expand Up @@ -419,6 +420,9 @@ const AppScenes = {
},
ContactQR: {
screen: ContactQR
},
CurrencyConverter: {
screen: CurrencyConverter
}
};

Expand Down
3 changes: 2 additions & 1 deletion locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -996,6 +996,7 @@
"views.Settings.Attestations.invalidAttestation": "Invalid attestation",
"views.Settings.Nostr.addRelay": "Add relay",
"views.Settings.Nostr.relays": "Relays",
"views.Settings.CurrencyConverter.title": "Currency Converter",
"views.LspExplanation.title": "What are these fees?",
"views.LspExplanation.text1": "Zeus is a self-custodial lightning wallet. In order to send or receive a lightning payment, you must open a lightning payment channel, which has a setup fee.",
"views.LspExplanation.text2": "Once the channel is set up, you'll only have to pay normal network fees until your channel exhausts its capacity.",
Expand All @@ -1021,4 +1022,4 @@
"views.Sweep.title": "Sweep on-chain wallet",
"views.Sweep.explainer": "Sweeping the on-chain wallet will send both the confirmed and unconfirmed balance to the destination address specified above.",
"pos.customItem": "Custom item"
}
}
18 changes: 17 additions & 1 deletion views/Settings/Currency.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import * as React from 'react';
import { View } from 'react-native';
import { TouchableOpacity, View } from 'react-native';
import { Icon, ListItem } from 'react-native-elements';
import { inject, observer } from 'mobx-react';

import Screen from '../../components/Screen';
import Header from '../../components/Header';

import Globe from '../../assets/images/SVG/Globe.svg';

import SettingsStore, {
CURRENCY_KEYS,
DEFAULT_FIAT,
Expand Down Expand Up @@ -79,11 +81,25 @@ export default class Currency extends React.Component<
const { fiatEnabled, selectedCurrency, fiatRatesSource } = this.state;
const { updateSettings }: any = SettingsStore;

const CurrencyConverterButton = () => (
<TouchableOpacity
onPress={() => navigation.navigate('CurrencyConverter')}
>
<Globe
fill={themeColor('text')}
style={{ alignSelf: 'center', marginTop: -10 }}
height="40"
width="40"
/>
</TouchableOpacity>
);

return (
<Screen>
<View style={{ flex: 1 }}>
<Header
leftComponent="Back"
rightComponent={<CurrencyConverterButton />}
centerComponent={{
text: localeString('views.Settings.Currency.title'),
style: {
Expand Down
214 changes: 214 additions & 0 deletions views/Settings/CurrencyConverter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
import * as React from 'react';
import Screen from '../../components/Screen';
import Header from '../../components/Header';
import TextInput from '../../components/TextInput';
import DropdownSetting from '../../components/DropdownSetting';
import { themeColor } from '../../utils/ThemeUtils';
import { ScrollView, View } from 'react-native';
import FiatStore from '../../stores/FiatStore';
import { observer, inject } from 'mobx-react';

interface CurrencyConverterProps {
navigation: any;
FiatStore?: FiatStore;
}

interface CurrencyConverterState {
inputValues: { [key: string]: string };
selectedCurrency: string;
}

@inject('FiatStore')
@observer
export default class CurrencyConverter extends React.Component<
CurrencyConverterProps,
CurrencyConverterState
> {
constructor(props: CurrencyConverterProps) {
super(props);
this.state = {
inputValues: {
BTC: '',
USD: ''
// Here we can add other default currencies as well
},
selectedCurrency: ''
};
}

handleInputChange = (value: string, currency: string) => {
const { inputValues } = this.state;
const { FiatStore } = this.props;
const fiatRates = FiatStore?.fiatRates || [];

const convertedValues: { [key: string]: string } = { ...inputValues };

// Set the input value
convertedValues[currency] = value;

// Convert the value to other currencies and BTC
Object.keys(convertedValues).forEach((key) => {
if (key !== currency) {
let conversionRate: number | null = null;

// Check if the value is empty
if (value === '') {
convertedValues[key] = ''; // Set the converted value to empty string
} else {
// Check if there's a direct conversion rate
const directRate = fiatRates.find(
(rate) => rate.currencyPair === `${currency}_${key}`
);
if (directRate) {
conversionRate = directRate.rate;
} else {
// Check if there's a conversion rate from BTC
const btcToRate = fiatRates.find(
(rate) => rate.currencyPair === `BTC_${key}`
)?.rate;
const btcFromRate = fiatRates.find(
(rate) => rate.currencyPair === `BTC_${currency}`
)?.rate;

if (btcToRate && btcFromRate) {
conversionRate = btcToRate / btcFromRate;
} else {
// Check if there's a conversion rate from the entered currency to BTC
const btcRateFrom = fiatRates.find(
(rate) =>
rate.currencyPair === `${currency}_BTC`
)?.rate;
const btcRateTo = fiatRates.find(
(rate) =>
rate.currencyPair === `BTC_${currency}`
)?.rate;

if (btcRateFrom && btcRateTo) {
conversionRate = 1 / btcRateFrom; // Invert the rate
}
}
}

if (conversionRate !== null) {
const convertedValue =
parseFloat(convertedValues[currency]) *
conversionRate;
convertedValues[key] = convertedValue.toFixed(2);
}
}
}
});

// Update the BTC value based on the entered currency
if (currency !== 'BTC') {
const btcConversionRate = fiatRates.find(
(rate) => rate.currencyPair === `BTC_${currency}`
)?.rate;
if (btcConversionRate) {
const btcValue = (
parseFloat(value) / btcConversionRate
).toFixed(8);
convertedValues['BTC'] = value === '' ? '' : btcValue; // Set to empty string if value is empty
}
} else {
// Check if the value is empty
convertedValues['BTC'] = value === '' ? '' : convertedValues['BTC']; // Preserve current BTC value if value is empty
}

// Update the state with the converted values
this.setState({ inputValues: convertedValues });
};

handleCurrencySelect = (currency: string) => {
const { inputValues } = this.state;

if (!inputValues.hasOwnProperty(currency)) {
const updatedInputValues = { ...inputValues, [currency]: '' };
this.setState({
inputValues: updatedInputValues,
selectedCurrency: currency
});
} else {
this.setState({ selectedCurrency: currency });
}
};

getConversionRate = (
fromCurrency: string,
toCurrency: string,
fiatRates: any[]
) => {
if (fromCurrency === toCurrency) return 1;

// Look for direct conversion rate
const directConversionRate = fiatRates.find(
(rate) => rate.currencyPair === `${fromCurrency}_${toCurrency}`
);

if (directConversionRate) return directConversionRate.rate;

// Look for BTC intermediary conversion
const btcRateFrom = fiatRates.find(
(rate) => rate.code === `BTC_${fromCurrency}`
)?.rate;
const btcRateTo = fiatRates.find(
(rate) => rate.code === `BTC_${toCurrency}`
)?.rate;

if (btcRateFrom && btcRateTo) {
return btcRateTo / btcRateFrom;
}

return null;
};

render() {
const { navigation, FiatStore } = this.props;
const fiatRates = FiatStore?.fiatRates || [];
const { inputValues, selectedCurrency } = this.state;

return (
<Screen>
<Header
leftComponent="Back"
centerComponent={{
text: themeColor(
'views.Settings.CurrencyConverter.title'
),
style: {
color: themeColor('text'),
fontFamily: 'PPNeueMontreal-Book'
}
}}
navigation={navigation}
/>
<ScrollView>
<View style={{ marginHorizontal: 22 }}>
{Object.keys(inputValues).map((currency) => (
<TextInput
suffix={currency}
key={currency}
placeholder={`Enter amount in ${currency}`}
value={inputValues[currency]}
onChangeText={(value) =>
this.handleInputChange(value, currency)
}
autoCapitalize="none"
/>
))}
<DropdownSetting
title="Select Currency"
selectedValue={selectedCurrency}
onValueChange={this.handleCurrencySelect}
values={fiatRates.map((rate) => ({
key: rate.code,
translateKey: rate.name,
value: rate.code
}))}
/>
</View>
</ScrollView>
</Screen>
);
}
}

0 comments on commit d55c28f

Please sign in to comment.