diff --git a/App.js b/App.js index e880c2e5c..4d999ecf8 100644 --- a/App.js +++ b/App.js @@ -1,17 +1,6 @@ import 'react-native-gesture-handler'; // should be on top import React, { useContext, useEffect, useRef, useState } from 'react'; -import { - Linking, - DeviceEventEmitter, - AppState, - StyleSheet, - KeyboardAvoidingView, - Platform, - View, - useColorScheme, - useWindowDimensions, -} from 'react-native'; -import Modal from 'react-native-modal'; +import { AppState, DeviceEventEmitter, KeyboardAvoidingView, Linking, Platform, StyleSheet, useColorScheme, View } from 'react-native'; import { NavigationContainer, CommonActions } from '@react-navigation/native'; import { SafeAreaProvider } from 'react-native-safe-area-context'; import { navigationRef } from './NavigationService'; @@ -25,6 +14,7 @@ import OnAppLaunch from './class/on-app-launch'; import DeeplinkSchemaMatch from './class/deeplink-schema-match'; import loc from './loc'; import { BlueDefaultTheme, BlueDarkTheme, BlueCurrentTheme } from './components/themes'; +import BottomModal from './components/BottomModal'; import InitRoot from './Navigation'; import BlueClipboard from './blue_modules/clipboard'; import { BlueStorageContext } from './blue_modules/storage-context'; @@ -36,22 +26,25 @@ import Biometric from './class/biometrics'; import WidgetCommunication from './blue_modules/WidgetCommunication'; import changeNavigationBarColor from 'react-native-navigation-bar-color'; const A = require('./blue_modules/analytics'); + if (process.env.NODE_ENV !== 'development') { Sentry.init({ dsn: 'https://23377936131848ca8003448a893cb622@sentry.io/1295736', }); } -const bitcoinModalString = 'Bitcoin address'; -const lightningModalString = 'Lightning Invoice'; + +const ClipboardContentType = Object.freeze({ + BITCOIN: 'BITCOIN', + LIGHTNING: 'LIGHTNING', +}); const App = () => { const { walletsInitialized, wallets, addWallet, saveToDisk, fetchAndSaveWalletTransactions } = useContext(BlueStorageContext); const appState = useRef(AppState.currentState); const [isClipboardContentModalVisible, setIsClipboardContentModalVisible] = useState(false); - const [clipboardContentModalAddressType, setClipboardContentModalAddressType] = useState(bitcoinModalString); + const [clipboardContentType, setClipboardContentType] = useState(); const [clipboardContent, setClipboardContent] = useState(''); const colorScheme = useColorScheme(); - const { height } = useWindowDimensions(); const stylesHook = StyleSheet.create({ modalContent: { backgroundColor: colorScheme === 'dark' ? BlueDarkTheme.colors.elevated : BlueDefaultTheme.colors.elevated, @@ -228,11 +221,11 @@ const App = () => { (isBitcoinAddress || isLightningInvoice || isLNURL || isBothBitcoinAndLightning) ) { if (isBitcoinAddress) { - setClipboardContentModalAddressType(bitcoinModalString); + setClipboardContentType(ClipboardContentType.BITCOIN); } else if (isLightningInvoice || isLNURL) { - setClipboardContentModalAddressType(lightningModalString); + setClipboardContentType(ClipboardContentType.LIGHTNING); } else if (isBothBitcoinAndLightning) { - setClipboardContentModalAddressType(bitcoinModalString); + setClipboardContentType(ClipboardContentType.BITCOIN); } setIsClipboardContentModalVisible(true); } @@ -254,18 +247,16 @@ const App = () => { const renderClipboardContentModal = () => { return ( - ReactNativeHapticFeedback.trigger('impactLight', { ignoreAndroidSystemSettings: false })} isVisible={isClipboardContentModalVisible} - style={styles.bottomModal} - deviceHeight={height} - onBackdropPress={hideClipboardContentModal} - onBackButtonPress={hideClipboardContentModal} + onClose={hideClipboardContentModal} > - You have a {clipboardContentModalAddressType} on your clipboard. Would you like to use it for a transaction? + {clipboardContentType === ClipboardContentType.BITCOIN && loc.wallets.clipboard_bitcoin} + {clipboardContentType === ClipboardContentType.LIGHTNING && loc.wallets.clipboard_lightning} @@ -282,7 +273,7 @@ const App = () => { - + ); }; return ( @@ -320,10 +311,6 @@ const styles = StyleSheet.create({ minHeight: 200, height: 200, }, - bottomModal: { - justifyContent: 'flex-end', - margin: 0, - }, modelContentButtonLayout: { flexDirection: 'row', margin: 16, diff --git a/Navigation.js b/Navigation.js index efce825f1..bd85be96e 100644 --- a/Navigation.js +++ b/Navigation.js @@ -70,7 +70,6 @@ import LnurlPay from './screen/lnd/lnurlPay'; import LnurlPaySuccess from './screen/lnd/lnurlPaySuccess'; import LoadingScreen from './LoadingScreen'; import UnlockWith from './UnlockWith'; -import { BlueNavigationStyle } from './BlueComponents'; import DrawerList from './screen/wallets/drawerList'; import { isTablet } from 'react-native-device-info'; import SettingsPrivacy from './screen/settings/SettingsPrivacy'; @@ -116,15 +115,7 @@ const WalletsRoot = () => ( - + diff --git a/blue_modules/currency.js b/blue_modules/currency.js index 467fd91a1..0c97ae3b0 100644 --- a/blue_modules/currency.js +++ b/blue_modules/currency.js @@ -1,7 +1,7 @@ import Frisbee from 'frisbee'; import AsyncStorage from '@react-native-community/async-storage'; import { AppStorage } from '../class'; -import { FiatUnit } from '../models/fiatUnit'; +import { FiatServerResponse, FiatUnit } from '../models/fiatUnit'; import DefaultPreference from 'react-native-default-preference'; import RNWidgetCenter from 'react-native-widget-center'; import * as RNLocalize from 'react-native-localize'; @@ -55,16 +55,14 @@ async function updateExchangeRate() { } } - let json; + let response; + const fiatServerResponse = new FiatServerResponse(preferredFiatCurrency); try { const api = new Frisbee({ - baseURI: 'https://api.coindesk.com', + baseURI: fiatServerResponse.baseURI(), }); - const response = await api.get('/v1/bpi/currentprice/' + preferredFiatCurrency.endPointKey + '.json'); - json = JSON.parse(response.body); - if (!json || !json.bpi || !json.bpi[preferredFiatCurrency.endPointKey] || !json.bpi[preferredFiatCurrency.endPointKey].rate_float) { - throw new Error('Could not update currency rate: ' + response.err); - } + response = await api.get(fiatServerResponse.endPoint()); + fiatServerResponse.isErrorFound(response); } catch (Err) { console.warn(Err); const lastSavedExchangeRate = JSON.parse(await AsyncStorage.getItem(AppStorage.EXCHANGE_RATES)); @@ -73,7 +71,7 @@ async function updateExchangeRate() { } exchangeRates[STRUCT.LAST_UPDATED] = +new Date(); - exchangeRates['BTC_' + preferredFiatCurrency.endPointKey] = json.bpi[preferredFiatCurrency.endPointKey].rate_float * 1; + exchangeRates['BTC_' + preferredFiatCurrency.endPointKey] = fiatServerResponse.rate(response); await AsyncStorage.setItem(AppStorage.EXCHANGE_RATES, JSON.stringify(exchangeRates)); await AsyncStorage.setItem(AppStorage.PREFERRED_CURRENCY, JSON.stringify(preferredFiatCurrency)); await setPrefferedCurrency(preferredFiatCurrency); diff --git a/ios/BlueWallet.xcodeproj/project.pbxproj b/ios/BlueWallet.xcodeproj/project.pbxproj index effc89376..43310111c 100644 --- a/ios/BlueWallet.xcodeproj/project.pbxproj +++ b/ios/BlueWallet.xcodeproj/project.pbxproj @@ -20,6 +20,14 @@ 32F0A29A2311DBB20095C559 /* ComplicationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32F0A2992311DBB20095C559 /* ComplicationController.swift */; }; 5875B7B2D85DC56E00F292FF /* libPods-WalletInformationWidgetExtension.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CC8A6C610EAE90F810EADCC /* libPods-WalletInformationWidgetExtension.a */; platformFilter = ios; }; 590C62D2ED8BF487C33945B0 /* libPods-WalletInformationAndMarketWidgetExtension.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 98455D960744E4E5DD50BA87 /* libPods-WalletInformationAndMarketWidgetExtension.a */; platformFilter = ios; }; + 6D2AA7FA2568B8750090B089 /* FiatUnits.plist in Resources */ = {isa = PBXBuildFile; fileRef = 6D2AA7F92568B8750090B089 /* FiatUnits.plist */; }; + 6D2AA7FB2568B8750090B089 /* FiatUnits.plist in Resources */ = {isa = PBXBuildFile; fileRef = 6D2AA7F92568B8750090B089 /* FiatUnits.plist */; }; + 6D2AA7FC2568B8750090B089 /* FiatUnits.plist in Resources */ = {isa = PBXBuildFile; fileRef = 6D2AA7F92568B8750090B089 /* FiatUnits.plist */; }; + 6D2AA7FD2568B8750090B089 /* FiatUnits.plist in Resources */ = {isa = PBXBuildFile; fileRef = 6D2AA7F92568B8750090B089 /* FiatUnits.plist */; }; + 6D2AA8082568B8F40090B089 /* FiatUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D2AA8072568B8F40090B089 /* FiatUnit.swift */; }; + 6D2AA8092568B8F40090B089 /* FiatUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D2AA8072568B8F40090B089 /* FiatUnit.swift */; }; + 6D2AA80A2568B8F40090B089 /* FiatUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D2AA8072568B8F40090B089 /* FiatUnit.swift */; }; + 6D2AA80B2568B8F40090B089 /* FiatUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D2AA8072568B8F40090B089 /* FiatUnit.swift */; }; 6D641F18255226DA003792DF /* MarketView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D641F17255226DA003792DF /* MarketView.swift */; }; 6D641F19255226DA003792DF /* MarketView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D641F17255226DA003792DF /* MarketView.swift */; }; 6D641F2325525054003792DF /* WalletInformationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D641F2225525053003792DF /* WalletInformationView.swift */; }; @@ -290,6 +298,8 @@ 6D294A9C24D512770039E22B /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/MainInterface.strings; sourceTree = ""; }; 6D294A9D24D5127F0039E22B /* xh */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = xh; path = xh.lproj/Interface.strings; sourceTree = ""; }; 6D294A9E24D512800039E22B /* xh */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = xh; path = xh.lproj/MainInterface.strings; sourceTree = ""; }; + 6D2AA7F92568B8750090B089 /* FiatUnits.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = FiatUnits.plist; sourceTree = ""; }; + 6D2AA8072568B8F40090B089 /* FiatUnit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FiatUnit.swift; sourceTree = ""; }; 6D333B3A252FE1A3004D72DF /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; }; 6D333B3C252FE1A3004D72DF /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; }; 6D641F17255226DA003792DF /* MarketView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketView.swift; sourceTree = ""; }; @@ -556,6 +566,15 @@ name = Resources; sourceTree = ""; }; + 6D2AA8062568B8E50090B089 /* Fiat */ = { + isa = PBXGroup; + children = ( + 6D2AA7F92568B8750090B089 /* FiatUnits.plist */, + 6D2AA8072568B8F40090B089 /* FiatUnit.swift */, + ); + path = Fiat; + sourceTree = ""; + }; 6D6CA4BB255872E3009312A5 /* PriceWidget */ = { isa = PBXGroup; children = ( @@ -609,6 +628,7 @@ 6DEB4BC1254FB98300E9F9AA /* Shared */ = { isa = PBXGroup; children = ( + 6D2AA8062568B8E50090B089 /* Fiat */, 6DEB4DD82552260200E9F9AA /* Views */, 6D9A2E6A254BAB1B007B5B82 /* WidgetAPI.swift */, 6D6CA5142558EBA3009312A5 /* WidgetAPI+Electrum.swift */, @@ -1046,6 +1066,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 6D2AA7FD2568B8750090B089 /* FiatUnits.plist in Resources */, 6D6CA4D725587397009312A5 /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1054,6 +1075,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 6D2AA7FA2568B8750090B089 /* FiatUnits.plist in Resources */, 6D9946832555A695000E52E8 /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1062,6 +1084,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 6D2AA7FC2568B8750090B089 /* FiatUnits.plist in Resources */, 6D9A2E09254BA348007B5B82 /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1070,6 +1093,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 6D2AA7FB2568B8750090B089 /* FiatUnits.plist in Resources */, 6DEB4B05254FB79100E9F9AA /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1259,6 +1283,7 @@ 6D6CA5322558ED4D009312A5 /* Colors.swift in Sources */, 6D6CA4BD255872E3009312A5 /* PriceWidget.swift in Sources */, 6D6CA5292558EC52009312A5 /* PriceView.swift in Sources */, + 6D2AA80B2568B8F40090B089 /* FiatUnit.swift in Sources */, 6D6CA53C2558F316009312A5 /* WidgetAPI.swift in Sources */, 6D6CA5332558ED54009312A5 /* Models.swift in Sources */, ); @@ -1274,6 +1299,7 @@ 6D9946882555A695000E52E8 /* SendReceiveButtons.swift in Sources */, 6D9946852555A695000E52E8 /* Colors.swift in Sources */, 6D99468A2555A695000E52E8 /* WidgetDataStore.swift in Sources */, + 6D2AA8082568B8F40090B089 /* FiatUnit.swift in Sources */, 6D99467B2555A68A000E52E8 /* MarketView.swift in Sources */, 6D9946872555A695000E52E8 /* UserDefaultsGroup.swift in Sources */, 6D9946632555A660000E52E8 /* MarketWidget.swift in Sources */, @@ -1286,6 +1312,7 @@ buildActionMask = 2147483647; files = ( 6D641F2325525054003792DF /* WalletInformationView.swift in Sources */, + 6D2AA80A2568B8F40090B089 /* FiatUnit.swift in Sources */, 6D9A2E6D254BAB1B007B5B82 /* WidgetAPI.swift in Sources */, 6DEB4C3B254FBF4800E9F9AA /* Colors.swift in Sources */, 6D6CA5282558EC52009312A5 /* PriceView.swift in Sources */, @@ -1309,6 +1336,7 @@ 6DEB4BDA254FB98E00E9F9AA /* WidgetAPI.swift in Sources */, 6DEB4BDB254FB98E00E9F9AA /* UserDefaultsGroup.swift in Sources */, 6DEB4BD9254FB98E00E9F9AA /* WidgetDataStore.swift in Sources */, + 6D2AA8092568B8F40090B089 /* FiatUnit.swift in Sources */, 6D641F3625526311003792DF /* SendReceiveButtons.swift in Sources */, 6DEB4BFC254FBA0E00E9F9AA /* Models.swift in Sources */, 6D641F19255226DA003792DF /* MarketView.swift in Sources */, diff --git a/ios/WalletInformationWidget/Widgets/Shared/Fiat/FiatUnit.swift b/ios/WalletInformationWidget/Widgets/Shared/Fiat/FiatUnit.swift new file mode 100644 index 000000000..c8e80320f --- /dev/null +++ b/ios/WalletInformationWidget/Widgets/Shared/Fiat/FiatUnit.swift @@ -0,0 +1,54 @@ +// +// FiatUnit.swift +// BlueWallet +// +// Created by Marcos Rodriguez on 11/20/20. +// Copyright © 2020 BlueWallet. All rights reserved. +// +import Foundation + +typealias FiatUnits = [FiatUnit] +struct FiatUnit: Codable { + let endPointKey: String + let symbol: String + let locale: String + let dataSource: String? + let rateKey: String? + + var rateURL: URL? { + if let dataSource = dataSource { + return URL(string: "\(dataSource)/\(endPointKey)") + } else { + return URL(string:"https://api.coindesk.com/v1/bpi/currentprice/\(endPointKey).json"); + } + } + func currentRate(json: Dictionary) -> WidgetDataStore? { + if dataSource == nil { + guard let bpi = json["bpi"] as? Dictionary, let preferredCurrency = bpi[endPointKey] as? Dictionary, let rateString = preferredCurrency["rate"] as? String, let rateDouble = preferredCurrency["rate_float"] as? Double, let time = json["time"] as? Dictionary, let lastUpdatedString = time["updatedISO"] as? String else { + return nil + } + return WidgetDataStore(rate: rateString, lastUpdate: lastUpdatedString, rateDouble: rateDouble) + } else { + guard let rateKey = rateKey, let rateDict = json[rateKey] as? [String: Any], let rateDouble = rateDict["price"] as? Double, let lastUpdated = json["timestamp"] as? Int else { + return nil + } + return WidgetDataStore(rate: String(rateDouble), lastUpdate: String(lastUpdated), rateDouble: rateDouble) + } + } +} + + +func fiatUnit(currency: String) -> FiatUnit? { + guard let file = Bundle.main.path(forResource: "FiatUnits", ofType: "plist") else { + return nil + } + let fileURL: URL = URL(fileURLWithPath: file) + var fiatUnits: FiatUnits? + + if let data = try? Data(contentsOf: fileURL) { + let decoder = PropertyListDecoder() + fiatUnits = try? decoder.decode(FiatUnits.self, from: data) + } + return fiatUnits?.first(where: {$0.endPointKey == currency}) + +} diff --git a/ios/WalletInformationWidget/Widgets/Shared/Fiat/FiatUnits.plist b/ios/WalletInformationWidget/Widgets/Shared/Fiat/FiatUnits.plist new file mode 100644 index 000000000..5d478fb2e --- /dev/null +++ b/ios/WalletInformationWidget/Widgets/Shared/Fiat/FiatUnits.plist @@ -0,0 +1,310 @@ + + + + + + endPointKey + USD + symbol + $ + locale + en-US + + + endPointKey + ARS + symbol + $ + locale + es-AR + dataSource + https://api.yadio.io/json + rateKey + ARS + + + endPointKey + AUD + symbol + $ + locale + en-AU + + + endPointKey + BRL + symbol + R$ + locale + pt-BR + + + endPointKey + CAD + symbol + $ + locale + en-CA + + + endPointKey + CHF + symbol + CHF + locale + de-CH + + + endPointKey + CLP + symbol + $ + locale + es-CL + + + endPointKey + COP + symbol + $ + locale + es-CO + + + endPointKey + CZK + symbol + + locale + cs-CZ + + + endPointKey + CNY + symbol + ¥ + locale + zh-CN + + + endPointKey + EUR + symbol + + locale + en-IE + + + endPointKey + GBP + symbol + £ + locale + en-GB + + + endPointKey + HRK + symbol + HRK + locale + hr-HR + + + endPointKey + HUF + symbol + Ft + locale + hu-HU + + + endPointKey + ILS + symbol + + locale + he-IL + + + endPointKey + INR + symbol + + locale + hi-HN + + + endPointKey + JPY + symbol + ¥ + locale + ja-JP + + + endPointKey + KES + symbol + Ksh + locale + en-KE + + + endPointKey + KRW + symbol + + locale + ko-KR + + + endPointKey + MXN + symbol + $ + locale + es-MX + + + endPointKey + MYR + symbol + RM + locale + ms-MY + + + endPointKey + NGN + symbol + + locale + en-NG + + + endPointKey + NOK + symbol + kr + locale + nb-NO + + + endPointKey + NZD + symbol + $ + locale + en-NZ + + + endPointKey + PLN + symbol + + locale + pl-PL + + + endPointKey + PHP + symbol + + locale + en-PH + + + endPointKey + RUB + symbol + + locale + ru-RU + + + endPointKey + SGD + symbol + S$ + locale + zh-SG + + + endPointKey + SEK + symbol + kr + locale + sv-SE + + + endPointKey + TRY + symbol + + locale + tr-TR + + + endPointKey + THB + symbol + ฿ + locale + th-TH + + + endPointKey + TWD + symbol + NT$ + locale + zh-Hant-TW + + + endPointKey + UAH + symbol + + locale + uk-UA + + + endPointKey + UYU + symbol + $ + locale + es-UY + + + endPointKey + VEF + symbol + Bs. + locale + es-VE + + + endPointKey + VES + symbol + Bs. + locale + es-VE + dataSource + https://api.yadio.io/json + rateKey + VES + + + endPointKey + ZAR + symbol + R + locale + en-ZA + + + diff --git a/ios/WalletInformationWidget/Widgets/Shared/Views/MarketView.swift b/ios/WalletInformationWidget/Widgets/Shared/Views/MarketView.swift index d7e92f89e..d277455ea 100644 --- a/ios/WalletInformationWidget/Widgets/Shared/Views/MarketView.swift +++ b/ios/WalletInformationWidget/Widgets/Shared/Views/MarketView.swift @@ -28,7 +28,7 @@ struct MarketView: View { Spacer() HStack(alignment: .center, spacing: 0, content: { - Text("Sats/Dollar").bold().lineLimit(1).font(Font.system(size:11, weight: .medium, design: .default)).foregroundColor(.textColor) + Text("Sats/\(WidgetAPI.getUserPreferredCurrency())").bold().lineLimit(1).font(Font.system(size:11, weight: .medium, design: .default)).foregroundColor(.textColor) Spacer() Text(marketData.sats == "..." ? "..." : marketData.sats).padding(EdgeInsets(top: 2, leading: 4, bottom: 2, trailing: 4)).lineLimit(1).minimumScaleFactor(0.1).foregroundColor(.widgetBackground).font(Font.system(size:11, weight: .semibold, design: .default)).background(Color(red: 0.97, green: 0.21, blue: 0.38)).overlay( RoundedRectangle(cornerRadius: 4.0) diff --git a/ios/WalletInformationWidget/Widgets/Shared/WidgetAPI.swift b/ios/WalletInformationWidget/Widgets/Shared/WidgetAPI.swift index ce7794dca..c8cda89f5 100644 --- a/ios/WalletInformationWidget/Widgets/Shared/WidgetAPI.swift +++ b/ios/WalletInformationWidget/Widgets/Shared/WidgetAPI.swift @@ -21,22 +21,22 @@ var numberFormatter: NumberFormatter { class WidgetAPI { static func fetchPrice(currency: String, completion: @escaping ((WidgetDataStore?, Error?) -> Void)) { - guard let url = URL(string: "https://api.coindesk.com/v1/bpi/currentPrice/\(currency).json") else {return} + let currencyToFiatUnit = fiatUnit(currency: currency) + guard let url = currencyToFiatUnit?.rateURL else {return} URLSession.shared.dataTask(with: url) { (data, response, error) in guard let dataResponse = data, - let json = ((try? JSONSerialization.jsonObject(with: dataResponse, options: .mutableContainers) as? Dictionary) as Dictionary??), + let json = (try? JSONSerialization.jsonObject(with: dataResponse, options: .mutableContainers) as? Dictionary), error == nil else { print(error?.localizedDescription ?? "Response Error") completion(nil, error) return } - guard let bpi = json?["bpi"] as? Dictionary, let preferredCurrency = bpi[currency] as? Dictionary, let rateString = preferredCurrency["rate"] as? String, let rateDouble = preferredCurrency["rate_float"] as? Double, let time = json?["time"] as? Dictionary, let lastUpdatedString = time["updatedISO"] as? String - else { + guard let latestRateDataStore = currencyToFiatUnit?.currentRate(json: json) + else { print(error?.localizedDescription ?? "Response Error") completion(nil, error) return } - let latestRateDataStore = WidgetDataStore(rate: rateString, lastUpdate: lastUpdatedString, rateDouble: rateDouble) completion(latestRateDataStore, nil) }.resume() } diff --git a/ios/WalletInformationWidget/Widgets/Shared/WidgetDataStore.swift b/ios/WalletInformationWidget/Widgets/Shared/WidgetDataStore.swift index ebef0d184..1a5813428 100644 --- a/ios/WalletInformationWidget/Widgets/Shared/WidgetDataStore.swift +++ b/ios/WalletInformationWidget/Widgets/Shared/WidgetDataStore.swift @@ -15,12 +15,11 @@ struct WidgetDataStore { var formattedRate: String? { let numberFormatter = NumberFormatter() numberFormatter.locale = Locale(identifier: WidgetAPI.getUserPreferredCurrencyLocale()) - numberFormatter.numberStyle = .decimal + numberFormatter.numberStyle = .currency numberFormatter.maximumFractionDigits = 0 numberFormatter.minimumFractionDigits = 0 - if let rateNumber = numberFormatter.number(from: rate) { - numberFormatter.numberStyle = .currency - return numberFormatter.string(from: rateNumber); + if let rateString = numberFormatter.string(from: NSNumber(value: rateDouble)) { + return rateString } return rate } diff --git a/loc/ar.json b/loc/ar.json index 757fd768d..599a19bed 100644 --- a/loc/ar.json +++ b/loc/ar.json @@ -224,7 +224,7 @@ "about_sm_twitter": "تابعنا على تويتر", "advanced_options": "الخيارات المتقدمة", "currency": "العملة", - "currency_source": "يتم الحصول على الأسعار من CoinDesk", + "currency_source": "يتم الحصول على الأسعار من", "default_desc": "عند تعطيل هذا الإعداد، ستفتح BlueWallet المحفظة المحدَّدة فور التشغيل.", "default_info": "Default info", "default_title": "عند التشغيل", diff --git a/loc/cs_cz.json b/loc/cs_cz.json index 1beb3d02f..00dbcc1d5 100644 --- a/loc/cs_cz.json +++ b/loc/cs_cz.json @@ -233,7 +233,7 @@ "about_sm_twitter": "Sleduj nás na Twitteru", "advanced_options": "Pokročilé možnosti", "currency": "Měna", - "currency_source": "Ceny jsou získány od CoinDesk", + "currency_source": "Ceny jsou získány od", "default_desc": "Pokud je zakázána, BlueWallet při spuštění ihned otevře vybranou peněženku.", "default_info": "Výchozí informace", "default_title": "Při spuštění", diff --git a/loc/de_de.json b/loc/de_de.json index cdce2ef21..85197b94e 100644 --- a/loc/de_de.json +++ b/loc/de_de.json @@ -233,7 +233,7 @@ "about_sm_twitter": "Folgt uns auf Twitter", "advanced_options": "Erweiterte Optionen", "currency": "Währung", - "currency_source": "Die Preisangaben stammen von CoinDesk", + "currency_source": "Die Preisangaben stammen von", "default_desc": "Wenn deaktiviert öffnet BlueWallet beim Start die ausgewählte Wallet.", "default_info": "Standard Info", "default_title": "Beim Start", diff --git a/loc/en.json b/loc/en.json index 298eabee8..f18c9c11b 100644 --- a/loc/en.json +++ b/loc/en.json @@ -234,7 +234,7 @@ "about_sm_twitter": "Follow us on Twitter", "advanced_options": "Advanced Options", "currency": "Currency", - "currency_source": "Prices are obtained from CoinDesk", + "currency_source": "Prices are obtained from", "default_desc": "When disabled, BlueWallet will immediately open the selected wallet at launch.", "default_info": "Default info", "default_title": "On Launch", @@ -293,7 +293,7 @@ }, "notifications": { "would_you_like_to_receive_notifications": "Would you like to receive notifications when you get incoming payments?", - "no_and_dont_ask": "No and dont ask", + "no_and_dont_ask": "No, and Don't Ask Me Again", "ask_me_later": "Ask Me Later" }, "transactions": { @@ -327,14 +327,13 @@ "transactions_count": "transactions count" }, "wallets": { - "add_bitcoin_explain": "Simple and powerful Bitcoin wallet", "add_bitcoin": "Bitcoin", + "add_bitcoin_explain": "Simple and powerful Bitcoin wallet", "add_create": "Create", "add_entropy_generated": "{gen} bytes of generated entropy", "add_entropy_provide": "Provide entropy via dice rolls", "add_entropy_remain": "{gen} bytes of generated entropy. Remaining {rem} bytes will be obtained from the System random number generator.", "add_import_wallet": "Import wallet", - "import_file": "Import File", "add_lightning": "Lightning", "add_lightning_explain": "For spending with instant transactions", "add_lndhub": "Connect to your LNDHub", @@ -344,6 +343,8 @@ "add_title": "add wallet", "add_wallet_name": "name", "add_wallet_type": "type", + "clipboard_bitcoin": "You have a Bitcoin address on your clipboard. Would you like to use it for a transaction?", + "clipboard_lightning": "You have a Lightning Invoice on your clipboard. Would you like to use it for a transaction?", "details_address": "Address", "details_advanced": "Advanced", "details_are_you_sure": "Are you sure?", @@ -365,15 +366,15 @@ "details_use_with_hardware_wallet": "Use with hardware wallet", "details_wallet_updated": "Wallet updated", "details_yes_delete": "Yes, delete", + "enter_bip38_password": "Enter password to decrypt", "export_title": "wallet export", "import_do_import": "Import", "import_error": "Failed to import. Please, make sure that the provided data is valid.", "import_explanation": "Write here your mnemonic, private key, WIF, or anything you've got. BlueWallet will do its best to guess the correct format and import your wallet", + "import_file": "Import File", "import_imported": "Imported", "import_scan_qr": "Scan or import a file", "import_success": "Your wallet has been successfully imported.", - "looks_like_bip38": "This looks like password-protected private key (BIP38)", - "enter_bip38_password": "Enter password to decrypt", "import_title": "import", "list_create_a_button": "Add now", "list_create_a_wallet": "Add a wallet", @@ -389,14 +390,15 @@ "list_long_choose": "Choose Photo", "list_long_clipboard": "Copy from Clipboard", "list_long_scan": "Scan QR Code", - "take_photo": "Take Photo", "list_tap_here_to_buy": "Buy Bitcoin", "list_title": "wallets", "list_tryagain": "Try Again", + "looks_like_bip38": "This looks like password-protected private key (BIP38)", "reorder_title": "Reorder Wallets", "select_no_bitcoin": "There are currently no Bitcoin wallets available.", "select_no_bitcoin_exp": "A Bitcoin wallet is required to refill Lightning wallets. Please, create or import one.", "select_wallet": "Select Wallet", + "take_photo": "Take Photo", "xpub_copiedToClipboard": "Copied to clipboard.", "xpub_title": "wallet XPUB" }, diff --git a/loc/es.json b/loc/es.json index 408997821..f7c056a6c 100644 --- a/loc/es.json +++ b/loc/es.json @@ -233,7 +233,7 @@ "about_sm_twitter": "Síguenos en Twitter", "advanced_options": "Opciones avanzadas", "currency": "Moneda", - "currency_source": "Los precios provienen de CoinDesk", + "currency_source": "Los precios provienen de", "default_desc": "Cuando esté deshabilitado, BlueWallet abrirá por defecto la cartera seleccionada al iniciar la aplicación.", "default_info": "Información por defecto", "default_title": "Al iniciar", diff --git a/loc/es_419.json b/loc/es_419.json index e5bd3c772..b9218e1a7 100644 --- a/loc/es_419.json +++ b/loc/es_419.json @@ -227,7 +227,7 @@ "about_sm_twitter": "Siguenos en Twitter", "advanced_options": "Opciones Avanzadas", "currency": "Moneda", - "currency_source": "Precios obtenidos de CoinDesk", + "currency_source": "Precios obtenidos de", "default_desc": "Cuando está deshabilitado, BlueWallet abrirá inmediatamente la billetera seleccionada al inicio", "default_info": "Informacion por defecto", "default_title": "En incio", diff --git a/loc/fr_fr.json b/loc/fr_fr.json index 341f3ba2c..adbd26470 100644 --- a/loc/fr_fr.json +++ b/loc/fr_fr.json @@ -230,7 +230,7 @@ "about_sm_twitter": "Nous suivre sur Twitter", "advanced_options": "Options avancées", "currency": "Devise", - "currency_source": "Les prix sont obtenus depuis CoinDesk", + "currency_source": "Les prix sont obtenus depuis", "default_desc": "Si désactivé, BlueWallet ouvrira immédiatement le portefeuille sélectionné au lancement.", "default_info": "Information par défaut", "default_title": "Au lancement", diff --git a/loc/he.json b/loc/he.json index 6cb422aa2..5d08b8146 100644 --- a/loc/he.json +++ b/loc/he.json @@ -233,7 +233,7 @@ "about_sm_twitter": "עקבו אחרינו בטוויטר", "advanced_options": "אפשרויות מתקדמות", "currency": "מטבע", - "currency_source": "מחירים מתקבלים מ- CoinDesk", + "currency_source": "מחירים מתקבלים מ-", "default_desc": "כאשר מבוטל, BlueWallet יפתח אוטומטית את הארנק הנבחר בפתיחה.", "default_info": "פתיחת ברירת מחדל", "default_title": "בעת פתיחה", diff --git a/loc/id_id.json b/loc/id_id.json index c199a3d3b..9b90b008a 100644 --- a/loc/id_id.json +++ b/loc/id_id.json @@ -224,7 +224,7 @@ "about_sm_twitter": "Follow us on Twitter", "advanced_options": "Advanced Options", "currency": "Mata Uang", - "currency_source": "Prices are obtained from CoinDesk", + "currency_source": "Prices are obtained from", "default_desc": "When disabled, BlueWallet will immediately open the selected wallet at launch.", "default_info": "Default info", "default_title": "On Launch", diff --git a/loc/index.js b/loc/index.js index a708883fd..8b71a1291 100644 --- a/loc/index.js +++ b/loc/index.js @@ -40,7 +40,7 @@ dayjs.extend(relativeTime); require('dayjs/locale/es'); break; case 'es_419': - // es-do it is the closesd one to es_419 + // es-do it is the closes one to es_419 lang = 'es-do'; require('dayjs/locale/es-do'); break; diff --git a/loc/it.json b/loc/it.json index 442b475d0..68de4a6f6 100644 --- a/loc/it.json +++ b/loc/it.json @@ -224,7 +224,7 @@ "about_sm_twitter": "Follow us on Twitter", "advanced_options": "Advanced Options", "currency": "Valuta", - "currency_source": "Prices are obtained from CoinDesk", + "currency_source": "Prices are obtained from", "default_desc": "When disabled, BlueWallet will immediately open the selected wallet at launch.", "default_info": "Default info", "default_title": "On Launch", diff --git a/loc/nl_nl.json b/loc/nl_nl.json index 86c5810b2..4e02f0392 100644 --- a/loc/nl_nl.json +++ b/loc/nl_nl.json @@ -233,7 +233,7 @@ "about_sm_twitter": "Volg ons op Twitter", "advanced_options": "Geavanceerde opties", "currency": "Valuta", - "currency_source": "Prijzen verstrekt bij CoinDesk", + "currency_source": "Prijzen verstrekt bij", "default_desc": "Indien uitgeschakeld zal BlueWallet meteen de geselecteerde wallet openen bij het opstarten.", "default_info": "Standaard info", "default_title": "Bij opstarten", diff --git a/loc/pt_br.json b/loc/pt_br.json index b32be8355..e15e829ee 100644 --- a/loc/pt_br.json +++ b/loc/pt_br.json @@ -234,7 +234,7 @@ "about_sm_twitter": "Siga-nos no Twitter", "advanced_options": "Opções avançadas", "currency": "Moeda", - "currency_source": "Os preços são obtidos no CoinDesk", + "currency_source": "Os preços são obtidos no", "default_desc": "Quando desativado, o BlueWallet abrirá imediatamente a carteira selecionada no lançamento.", "default_info": "Carteira padrão", "default_title": "No lançamento", diff --git a/loc/pt_pt.json b/loc/pt_pt.json index f61622db9..efdc1eea5 100644 --- a/loc/pt_pt.json +++ b/loc/pt_pt.json @@ -224,7 +224,7 @@ "about_sm_twitter": "Segue-nos no Twitter", "advanced_options": "Opções Avançadas", "currency": "Moeda", - "currency_source": "Os preços são obtidos no CoinDesk", + "currency_source": "Os preços são obtidos no", "default_desc": "Quando desactivado, a BlueWallet abrirá imediatamente a carteira seleccionada no lançamento.", "default_info": "Carteira padrão", "default_title": "A abrir", diff --git a/loc/ru.json b/loc/ru.json index bdabacc55..d3d2e820d 100644 --- a/loc/ru.json +++ b/loc/ru.json @@ -233,7 +233,7 @@ "about_sm_twitter": "Мы в Twitter", "advanced_options": "Расширенные настройки", "currency": "Валюта", - "currency_source": "Источник курсов CoinDesk", + "currency_source": "Источник курсов", "default_desc": "Когда выключено BlueWallet сразу же откроет выбранный кошелек при запуске.", "default_info": "Показать", "default_title": "При старте", diff --git a/loc/sk_sk.json b/loc/sk_sk.json index 0aebfbd29..71d961a02 100644 --- a/loc/sk_sk.json +++ b/loc/sk_sk.json @@ -230,7 +230,7 @@ "about_sm_twitter": "Sledujte nás na Twitteri", "advanced_options": "Pokročilé nastavenia", "currency": "Mena", - "currency_source": "Prices are obtained from CoinDesk", + "currency_source": "Prices are obtained from", "default_desc": "When disabled, BlueWallet will immediately open the selected wallet at launch.", "default_info": "Default info", "default_title": "On Launch", diff --git a/loc/sl_SI.json b/loc/sl_SI.json index 1ffe155ef..8b1fb9c36 100644 --- a/loc/sl_SI.json +++ b/loc/sl_SI.json @@ -233,7 +233,7 @@ "about_sm_twitter": "Sledite nam na Twitterju", "advanced_options": "Napredne Možnosti", "currency": "Valuta", - "currency_source": "Tečaji so pridobljeni iz CoinDesk", + "currency_source": "Tečaji so pridobljeni iz", "default_desc": "Ko je onemogočeno, bo BlueWallet ob zagonu takoj odprl izbrano denarnico.", "default_info": "Privzeto v", "default_title": "Ob zagonu", diff --git a/loc/sv_se.json b/loc/sv_se.json index f3ccf51fe..58e1f5636 100644 --- a/loc/sv_se.json +++ b/loc/sv_se.json @@ -224,7 +224,7 @@ "about_sm_twitter": "Follow us on Twitter", "advanced_options": "Advanced Options", "currency": "Valuta", - "currency_source": "Prices are obtained from CoinDesk", + "currency_source": "Prices are obtained from", "default_desc": "When disabled, BlueWallet will immediately open the selected wallet at launch.", "default_info": "Default info", "default_title": "On Launch", diff --git a/loc/tr_tr.json b/loc/tr_tr.json index 95a983eb0..6c3311e9e 100644 --- a/loc/tr_tr.json +++ b/loc/tr_tr.json @@ -224,7 +224,7 @@ "about_sm_twitter": "Follow us on Twitter", "advanced_options": "Advanced Options", "currency": "Para Birimi", - "currency_source": "Prices are obtained from CoinDesk", + "currency_source": "Prices are obtained from", "default_desc": "When disabled, BlueWallet will immediately open the selected wallet at launch.", "default_info": "Default info", "default_title": "On Launch", diff --git a/loc/zh_cn.json b/loc/zh_cn.json index 553444270..9b0656f82 100644 --- a/loc/zh_cn.json +++ b/loc/zh_cn.json @@ -233,7 +233,7 @@ "about_sm_twitter": "Follow us on Twitter", "advanced_options": "Advanced Options", "currency": "货币", - "currency_source": "Prices are obtained from CoinDesk", + "currency_source": "Prices are obtained from", "default_desc": "When disabled, BlueWallet will immediately open the selected wallet at launch.", "default_info": "Default info", "default_title": "On Launch", diff --git a/loc/zh_tw.json b/loc/zh_tw.json index b9abfc5a3..9551ac93d 100644 --- a/loc/zh_tw.json +++ b/loc/zh_tw.json @@ -230,7 +230,7 @@ "about_sm_twitter": "Follow us on Twitter", "advanced_options": "Advanced Options", "currency": "貨幣", - "currency_source": "Prices are obtained from CoinDesk", + "currency_source": "Prices are obtained from", "default_desc": "When disabled, BlueWallet will immediately open the selected wallet at launch.", "default_info": "Default info", "default_title": "On Launch", diff --git a/models/fiatUnit.js b/models/fiatUnit.js index 428b3a994..a9f35b187 100644 --- a/models/fiatUnit.js +++ b/models/fiatUnit.js @@ -1,37 +1,99 @@ +export const FiatUnitSource = Object.freeze({ CoinDesk: 'CoinDesk', Yadio: 'Yadio' }); + export const FiatUnit = Object.freeze({ - USD: { endPointKey: 'USD', symbol: '$', locale: 'en-US' }, - ARS: { endPointKey: 'ARS', symbol: '$', locale: 'es-AR' }, - AUD: { endPointKey: 'AUD', symbol: '$', locale: 'en-AU' }, - BRL: { endPointKey: 'BRL', symbol: 'R$', locale: 'pt-BR' }, - CAD: { endPointKey: 'CAD', symbol: '$', locale: 'en-CA' }, - CHF: { endPointKey: 'CHF', symbol: 'CHF', locale: 'de-CH' }, - CLP: { endPointKey: 'CLP', symbol: '$', locale: 'es-CL' }, - COP: { endPointKey: 'COP', symbol: '$', locale: 'es-CO' }, - CZK: { endPointKey: 'CZK', symbol: 'Kč', locale: 'cs-CZ' }, - CNY: { endPointKey: 'CNY', symbol: '¥', locale: 'zh-CN' }, - EUR: { endPointKey: 'EUR', symbol: '€', locale: 'en-IE' }, - GBP: { endPointKey: 'GBP', symbol: '£', locale: 'en-GB' }, - HRK: { endPointKey: 'HRK', symbol: 'HRK', locale: 'hr-HR' }, - HUF: { endPointKey: 'HUF', symbol: 'Ft', locale: 'hu-HU' }, - ILS: { endPointKey: 'ILS', symbol: '₪', locale: 'he-IL' }, - INR: { endPointKey: 'INR', symbol: '₹', locale: 'hi-HN' }, - JPY: { endPointKey: 'JPY', symbol: '¥', locale: 'ja-JP' }, - KES: { endPointKey: 'KES', symbol: 'Ksh', locale: 'en-KE' }, - KRW: { endPointKey: 'KRW', symbol: '₩', locale: 'ko-KR' }, - MXN: { endPointKey: 'MXN', symbol: '$', locale: 'es-MX' }, - MYR: { endPointKey: 'MYR', symbol: 'RM', locale: 'ms-MY' }, - NGN: { endPointKey: 'NGN', symbol: '₦', locale: 'en-NG' }, - NOK: { endPointKey: 'NOK', symbol: 'kr', locale: 'nb-NO' }, - NZD: { endPointKey: 'NZD', symbol: '$', locale: 'en-NZ' }, - PLN: { endPointKey: 'PLN', symbol: 'zł', locale: 'pl-PL' }, - PHP: { endPointKey: 'PHP', symbol: '₱', locale: 'en-PH' }, - RUB: { endPointKey: 'RUB', symbol: '₽', locale: 'ru-RU' }, - SGD: { endPointKey: 'SGD', symbol: 'S$', locale: 'zh-SG' }, - SEK: { endPointKey: 'SEK', symbol: 'kr', locale: 'sv-SE' }, - TRY: { endPointKey: 'TRY', symbol: '₺', locale: 'tr-TR' }, - THB: { endPointKey: 'THB', symbol: '฿', locale: 'th-TH' }, - TWD: { endPointKey: 'TWD', symbol: 'NT$', locale: 'zh-Hant-TW' }, - UAH: { endPointKey: 'UAH', symbol: '₴', locale: 'uk-UA' }, - VEF: { endPointKey: 'VEF', symbol: 'Bs.', locale: 'es-VE' }, - ZAR: { endPointKey: 'ZAR', symbol: 'R', locale: 'en-ZA' }, + USD: { endPointKey: 'USD', symbol: '$', locale: 'en-US', source: FiatUnitSource.CoinDesk }, + ARS: { + endPointKey: 'ARS', + symbol: '$', + locale: 'es-AR', + dataSource: 'https://api.yadio.io/json', + rateKey: 'ARS', + source: FiatUnitSource.Yadio, + }, + AUD: { endPointKey: 'AUD', symbol: '$', locale: 'en-AU', source: FiatUnitSource.CoinDesk }, + BRL: { endPointKey: 'BRL', symbol: 'R$', locale: 'pt-BR', source: FiatUnitSource.CoinDesk }, + CAD: { endPointKey: 'CAD', symbol: '$', locale: 'en-CA', source: FiatUnitSource.CoinDesk }, + CHF: { endPointKey: 'CHF', symbol: 'CHF', locale: 'de-CH', source: FiatUnitSource.CoinDesk }, + CLP: { endPointKey: 'CLP', symbol: '$', locale: 'es-CL', source: FiatUnitSource.CoinDesk }, + COP: { endPointKey: 'COP', symbol: '$', locale: 'es-CO', source: FiatUnitSource.CoinDesk }, + CZK: { endPointKey: 'CZK', symbol: 'Kč', locale: 'cs-CZ', source: FiatUnitSource.CoinDesk }, + CNY: { endPointKey: 'CNY', symbol: '¥', locale: 'zh-CN', source: FiatUnitSource.CoinDesk }, + EUR: { endPointKey: 'EUR', symbol: '€', locale: 'en-IE', source: FiatUnitSource.CoinDesk }, + GBP: { endPointKey: 'GBP', symbol: '£', locale: 'en-GB', source: FiatUnitSource.CoinDesk }, + HRK: { endPointKey: 'HRK', symbol: 'HRK', locale: 'hr-HR', source: FiatUnitSource.CoinDesk }, + HUF: { endPointKey: 'HUF', symbol: 'Ft', locale: 'hu-HU', source: FiatUnitSource.CoinDesk }, + ILS: { endPointKey: 'ILS', symbol: '₪', locale: 'he-IL', source: FiatUnitSource.CoinDesk }, + INR: { endPointKey: 'INR', symbol: '₹', locale: 'hi-HN', source: FiatUnitSource.CoinDesk }, + JPY: { endPointKey: 'JPY', symbol: '¥', locale: 'ja-JP', source: FiatUnitSource.CoinDesk }, + KES: { endPointKey: 'KES', symbol: 'Ksh', locale: 'en-KE', source: FiatUnitSource.CoinDesk }, + KRW: { endPointKey: 'KRW', symbol: '₩', locale: 'ko-KR', source: FiatUnitSource.CoinDesk }, + MXN: { endPointKey: 'MXN', symbol: '$', locale: 'es-MX', source: FiatUnitSource.CoinDesk }, + MYR: { endPointKey: 'MYR', symbol: 'RM', locale: 'ms-MY', source: FiatUnitSource.CoinDesk }, + NGN: { endPointKey: 'NGN', symbol: '₦', locale: 'en-NG', source: FiatUnitSource.CoinDesk }, + NOK: { endPointKey: 'NOK', symbol: 'kr', locale: 'nb-NO', source: FiatUnitSource.CoinDesk }, + NZD: { endPointKey: 'NZD', symbol: '$', locale: 'en-NZ', source: FiatUnitSource.CoinDesk }, + PLN: { endPointKey: 'PLN', symbol: 'zł', locale: 'pl-PL', source: FiatUnitSource.CoinDesk }, + PHP: { endPointKey: 'PHP', symbol: '₱', locale: 'en-PH', source: FiatUnitSource.CoinDesk }, + RUB: { endPointKey: 'RUB', symbol: '₽', locale: 'ru-RU', source: FiatUnitSource.CoinDesk }, + SGD: { endPointKey: 'SGD', symbol: 'S$', locale: 'zh-SG', source: FiatUnitSource.CoinDesk }, + SEK: { endPointKey: 'SEK', symbol: 'kr', locale: 'sv-SE', source: FiatUnitSource.CoinDesk }, + TRY: { endPointKey: 'TRY', symbol: '₺', locale: 'tr-TR', source: FiatUnitSource.CoinDesk }, + THB: { endPointKey: 'THB', symbol: '฿', locale: 'th-TH', source: FiatUnitSource.CoinDesk }, + TWD: { endPointKey: 'TWD', symbol: 'NT$', locale: 'zh-Hant-TW', source: FiatUnitSource.CoinDesk }, + UAH: { endPointKey: 'UAH', symbol: '₴', locale: 'uk-UA', source: FiatUnitSource.CoinDesk }, + UYU: { endPointKey: 'UYU', symbol: '$', locale: 'es-UY', source: FiatUnitSource.CoinDesk }, + VEF: { endPointKey: 'VEF', symbol: 'Bs.', locale: 'es-VE', source: FiatUnitSource.CoinDesk }, + VES: { + endPointKey: 'VES', + symbol: 'Bs.', + locale: 'es-VE', + dataSource: 'https://api.yadio.io/json', + rateKey: 'VES', + source: FiatUnitSource.Yadio, + }, + ZAR: { endPointKey: 'ZAR', symbol: 'R', locale: 'en-ZA', source: FiatUnitSource.CoinDesk }, }); + +export class FiatServerResponse { + constructor(fiatUnit) { + this.fiatUnit = fiatUnit; + } + + baseURI = () => { + if (this.fiatUnit.dataSource) { + return this.fiatUnit.dataSource; + } else { + return 'https://api.coindesk.com'; + } + }; + + endPoint = () => { + if (this.fiatUnit.dataSource) { + return `/${this.fiatUnit.endPointKey}`; + } else { + return '/v1/bpi/currentprice/' + this.fiatUnit.endPointKey + '.json'; + } + }; + + rate = response => { + const json = typeof response.body === 'string' ? JSON.parse(response.body) : response.body; + if (this.fiatUnit.dataSource) { + return json[this.fiatUnit.rateKey].price * 1; + } else { + return json.bpi[this.fiatUnit.endPointKey].rate_float * 1; + } + }; + + isErrorFound = response => { + const json = typeof response.body === 'string' ? JSON.parse(response.body) : response.body; + if (this.fiatUnit.dataSource) { + if (!json || !json[this.fiatUnit.rateKey]) { + throw new Error('Could not update currency rate: ' + response.err); + } + } else { + if (!json || !json.bpi || !json.bpi[this.fiatUnit.endPointKey] || !json.bpi[this.fiatUnit.endPointKey].rate_float) { + throw new Error('Could not update currency rate: ' + response.err); + } + } + }; +} diff --git a/screen/settings/currency.js b/screen/settings/currency.js index b84d02f87..7e8b7811c 100644 --- a/screen/settings/currency.js +++ b/screen/settings/currency.js @@ -1,8 +1,8 @@ import React, { useState, useEffect } from 'react'; -import { FlatList, TouchableOpacity, ActivityIndicator, View, StyleSheet } from 'react-native'; +import { FlatList, ActivityIndicator, View, StyleSheet } from 'react-native'; import { SafeBlueArea, BlueListItem, BlueTextHooks, BlueCard, BlueNavigationStyle } from '../../BlueComponents'; import PropTypes from 'prop-types'; -import { FiatUnit } from '../../models/fiatUnit'; +import { FiatUnit, FiatUnitSource } from '../../models/fiatUnit'; import loc from '../../loc'; import { useTheme } from '@react-navigation/native'; const currency = require('../../blue_modules/currency'); @@ -48,16 +48,14 @@ const Currency = () => { style={styles.flex} keyExtractor={(_item, index) => `${index}`} data={data} + initialNumToRender={25} extraData={data} renderItem={({ item }) => { return ( { setIsSavingNewPreferredCurrency(true); setSelectedCurrency(item); @@ -70,7 +68,9 @@ const Currency = () => { }} /> - {loc.settings.currency_source} + + {loc.settings.currency_source} {selectedCurrency.source ?? FiatUnitSource.CoinDesk} + ); diff --git a/screen/settings/settings.js b/screen/settings/settings.js index cb5df02c4..835d4c621 100644 --- a/screen/settings/settings.js +++ b/screen/settings/settings.js @@ -1,6 +1,6 @@ import React from 'react'; import { ScrollView, TouchableOpacity, StyleSheet, StatusBar } from 'react-native'; -import { BlueListItem, BlueHeaderDefaultSubHooks } from '../../BlueComponents'; +import { BlueListItem, BlueNavigationStyle, BlueHeaderDefaultSubHooks } from '../../BlueComponents'; import { useNavigation } from '@react-navigation/native'; import loc from '../../loc'; @@ -47,3 +47,7 @@ const Settings = () => { }; export default Settings; +Settings.navigationOptions = () => ({ + ...BlueNavigationStyle(), + headerTitle: '', +}); diff --git a/screen/wallets/list.js b/screen/wallets/list.js index 1be044a4d..da14e6c2d 100644 --- a/screen/wallets/list.js +++ b/screen/wallets/list.js @@ -141,16 +141,15 @@ const WalletsList = () => { * Forcefully fetches TXs and balance for ALL wallets. * Triggered manually by user on pull-to-refresh. */ - const refreshTransactions = () => { - setIsLoading(true); + const refreshTransactions = (showLoadingIndicator = true) => { + setIsLoading(showLoadingIndicator); refreshAllWalletTransactions().finally(() => setIsLoading(false)); }; - useEffect( - refreshTransactions, + useEffect(() => { + refreshTransactions(false); // eslint-disable-next-line react-hooks/exhaustive-deps - [], - ); // call refreshTransactions() only once, when screen mounts + }, []); // call refreshTransactions() only once, when screen mounts const handleClick = index => { console.log('click', index); @@ -197,7 +196,6 @@ const WalletsList = () => { console.log('onSnapToItem', index); if (wallets[index] && (wallets[index].timeToRefreshBalance() || wallets[index].timeToRefreshTransaction())) { console.log(wallets[index].getLabel(), 'thinks its time to refresh either balance or transactions. refetching both'); - setIsLoading(true); refreshAllWalletTransactions(index).finally(() => setIsLoading(false)); } }; diff --git a/scripts/edit-version-number.sh b/scripts/edit-version-number.sh index 9fd587f0c..53d7a366c 100755 --- a/scripts/edit-version-number.sh +++ b/scripts/edit-version-number.sh @@ -6,6 +6,7 @@ vim ios/BlueWallet.xcodeproj/project.pbxproj vim ios/WalletInformationWidget/Widgets/MarketWidget/Info.plist vim ios/WalletInformationWidget/Widgets/WalletInformationAndMarketWidget/Info.plist vim ios/WalletInformationWidget/Info.plist +vim ios/WalletInformationWidget/Widgets/PriceWidget/Info.plist vim android/app/build.gradle vim package.json vim package-lock.json