mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-03-03 03:59:10 +01:00
REF: Currency module to TS (#6052)
This commit is contained in:
parent
e4adb0f742
commit
bec42fe42d
22 changed files with 392 additions and 402 deletions
4
App.js
4
App.js
|
@ -33,8 +33,8 @@ import HandoffComponent from './components/handoff';
|
|||
import Privacy from './blue_modules/Privacy';
|
||||
import triggerHapticFeedback, { HapticFeedbackTypes } from './blue_modules/hapticFeedback';
|
||||
import MenuElements from './components/MenuElements';
|
||||
import { updateExchangeRate } from './blue_modules/currency';
|
||||
const A = require('./blue_modules/analytics');
|
||||
const currency = require('./blue_modules/currency');
|
||||
|
||||
const eventEmitter = Platform.OS === 'ios' ? new NativeEventEmitter(NativeModules.EventEmitter) : undefined;
|
||||
const { EventEmitter, SplashScreen } = NativeModules;
|
||||
|
@ -203,7 +203,7 @@ const App = () => {
|
|||
if (wallets.length === 0) return;
|
||||
if ((appState.current.match(/background/) && nextAppState === 'active') || nextAppState === undefined) {
|
||||
setTimeout(() => A(A.ENUM.APP_UNSUSPENDED), 2000);
|
||||
currency.updateExchangeRate();
|
||||
updateExchangeRate();
|
||||
const processed = await processPushNotifications();
|
||||
if (processed) return;
|
||||
const clipboard = await BlueClipboard().getClipboardContent();
|
||||
|
|
|
@ -25,6 +25,7 @@ import {
|
|||
} from './class/';
|
||||
import { randomBytes } from './class/rng';
|
||||
import alert from './components/Alert';
|
||||
import { initCurrencyDaemon } from './blue_modules/currency';
|
||||
|
||||
const encryption = require('./blue_modules/encryption');
|
||||
const Realm = require('realm');
|
||||
|
@ -32,7 +33,6 @@ const createHash = require('create-hash');
|
|||
let usedBucketNum = false;
|
||||
let savingInProgress = 0; // its both a flag and a counter of attempts to write to disk
|
||||
const prompt = require('./helpers/prompt');
|
||||
const currency = require('./blue_modules/currency');
|
||||
const BlueElectrum = require('./blue_modules/BlueElectrum');
|
||||
BlueElectrum.connectMain();
|
||||
|
||||
|
@ -939,6 +939,6 @@ const startAndDecrypt = async retry => {
|
|||
|
||||
BlueApp.startAndDecrypt = startAndDecrypt;
|
||||
BlueApp.AppStorage = AppStorage;
|
||||
currency.init();
|
||||
initCurrencyDaemon();
|
||||
|
||||
module.exports = BlueApp;
|
||||
|
|
|
@ -1,261 +0,0 @@
|
|||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import DefaultPreference from 'react-native-default-preference';
|
||||
import * as RNLocalize from 'react-native-localize';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { FiatUnit, getFiatRate } from '../models/fiatUnit';
|
||||
import WidgetCommunication from './WidgetCommunication';
|
||||
|
||||
const PREFERRED_CURRENCY_STORAGE_KEY = 'preferredCurrency';
|
||||
const EXCHANGE_RATES_STORAGE_KEY = 'currency';
|
||||
|
||||
let preferredFiatCurrency = FiatUnit.USD;
|
||||
let exchangeRates = { LAST_UPDATED_ERROR: false };
|
||||
let lastTimeUpdateExchangeRateWasCalled = 0;
|
||||
let skipUpdateExchangeRate = false;
|
||||
|
||||
const LAST_UPDATED = 'LAST_UPDATED';
|
||||
|
||||
/**
|
||||
* Saves to storage preferred currency, whole object
|
||||
* from `./models/fiatUnit`
|
||||
*
|
||||
* @param item {Object} one of the values in `./models/fiatUnit`
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function setPrefferedCurrency(item) {
|
||||
await AsyncStorage.setItem(PREFERRED_CURRENCY_STORAGE_KEY, JSON.stringify(item));
|
||||
await DefaultPreference.setName('group.io.bluewallet.bluewallet');
|
||||
await DefaultPreference.set('preferredCurrency', item.endPointKey);
|
||||
await DefaultPreference.set('preferredCurrencyLocale', item.locale.replace('-', '_'));
|
||||
WidgetCommunication.reloadAllTimelines();
|
||||
}
|
||||
|
||||
async function getPreferredCurrency() {
|
||||
const preferredCurrency = await JSON.parse(await AsyncStorage.getItem(PREFERRED_CURRENCY_STORAGE_KEY));
|
||||
await DefaultPreference.setName('group.io.bluewallet.bluewallet');
|
||||
await DefaultPreference.set('preferredCurrency', preferredCurrency.endPointKey);
|
||||
await DefaultPreference.set('preferredCurrencyLocale', preferredCurrency.locale.replace('-', '_'));
|
||||
return preferredCurrency;
|
||||
}
|
||||
|
||||
async function _restoreSavedExchangeRatesFromStorage() {
|
||||
try {
|
||||
exchangeRates = JSON.parse(await AsyncStorage.getItem(EXCHANGE_RATES_STORAGE_KEY));
|
||||
if (!exchangeRates) exchangeRates = { LAST_UPDATED_ERROR: false };
|
||||
} catch (_) {
|
||||
exchangeRates = { LAST_UPDATED_ERROR: false };
|
||||
}
|
||||
}
|
||||
|
||||
async function _restoreSavedPreferredFiatCurrencyFromStorage() {
|
||||
try {
|
||||
preferredFiatCurrency = JSON.parse(await AsyncStorage.getItem(PREFERRED_CURRENCY_STORAGE_KEY));
|
||||
if (preferredFiatCurrency === null) {
|
||||
throw Error('No Preferred Fiat selected');
|
||||
}
|
||||
|
||||
preferredFiatCurrency = FiatUnit[preferredFiatCurrency.endPointKey] || preferredFiatCurrency;
|
||||
// ^^^ in case configuration in json file changed (and is different from what we stored) we reload it
|
||||
} catch (_) {
|
||||
const deviceCurrencies = RNLocalize.getCurrencies();
|
||||
if (Object.keys(FiatUnit).some(unit => unit === deviceCurrencies[0])) {
|
||||
preferredFiatCurrency = FiatUnit[deviceCurrencies[0]];
|
||||
} else {
|
||||
preferredFiatCurrency = FiatUnit.USD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* actual function to reach api and get fresh currency exchange rate. checks LAST_UPDATED time and skips entirely
|
||||
* if called too soon (30min); saves exchange rate (with LAST_UPDATED info) to storage.
|
||||
* should be called when app thinks its a good time to refresh exchange rate
|
||||
*
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
async function updateExchangeRate() {
|
||||
if (skipUpdateExchangeRate) return;
|
||||
if (+new Date() - lastTimeUpdateExchangeRateWasCalled <= 10 * 1000) {
|
||||
// simple debounce so theres no race conditions
|
||||
return;
|
||||
}
|
||||
lastTimeUpdateExchangeRateWasCalled = +new Date();
|
||||
|
||||
if (+new Date() - exchangeRates[LAST_UPDATED] <= 30 * 60 * 1000) {
|
||||
// not updating too often
|
||||
return;
|
||||
}
|
||||
console.log('updating exchange rate...');
|
||||
|
||||
let rate;
|
||||
try {
|
||||
rate = await getFiatRate(preferredFiatCurrency.endPointKey);
|
||||
exchangeRates[LAST_UPDATED] = +new Date();
|
||||
exchangeRates['BTC_' + preferredFiatCurrency.endPointKey] = rate;
|
||||
exchangeRates.LAST_UPDATED_ERROR = false;
|
||||
await AsyncStorage.setItem(EXCHANGE_RATES_STORAGE_KEY, JSON.stringify(exchangeRates));
|
||||
} catch (Err) {
|
||||
console.log('Error encountered when attempting to update exchange rate...');
|
||||
console.warn(Err.message);
|
||||
rate = JSON.parse(await AsyncStorage.getItem(EXCHANGE_RATES_STORAGE_KEY));
|
||||
rate = rate || {}; // init if its null
|
||||
rate.LAST_UPDATED_ERROR = true;
|
||||
exchangeRates.LAST_UPDATED_ERROR = true;
|
||||
await AsyncStorage.setItem(EXCHANGE_RATES_STORAGE_KEY, JSON.stringify(rate));
|
||||
throw Err;
|
||||
}
|
||||
}
|
||||
|
||||
async function isRateOutdated() {
|
||||
try {
|
||||
const rate = JSON.parse(await AsyncStorage.getItem(EXCHANGE_RATES_STORAGE_KEY));
|
||||
return rate.LAST_UPDATED_ERROR || +new Date() - rate.LAST_UPDATED >= 31 * 60 * 1000;
|
||||
} catch {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* this function reads storage and restores current preferred fiat currency & last saved exchange rate, then calls
|
||||
* updateExchangeRate() to update rates.
|
||||
* should be called when the app starts and when user changes preferred fiat (with TRUE argument so underlying
|
||||
* `updateExchangeRate()` would actually update rates via api).
|
||||
*
|
||||
* @param clearLastUpdatedTime {boolean} set to TRUE for the underlying
|
||||
*
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
async function init(clearLastUpdatedTime = false) {
|
||||
await _restoreSavedExchangeRatesFromStorage();
|
||||
await _restoreSavedPreferredFiatCurrencyFromStorage();
|
||||
|
||||
if (clearLastUpdatedTime) {
|
||||
exchangeRates[LAST_UPDATED] = 0;
|
||||
lastTimeUpdateExchangeRateWasCalled = 0;
|
||||
}
|
||||
|
||||
return updateExchangeRate();
|
||||
}
|
||||
|
||||
function satoshiToLocalCurrency(satoshi, format = true) {
|
||||
if (!exchangeRates['BTC_' + preferredFiatCurrency.endPointKey]) {
|
||||
updateExchangeRate();
|
||||
return '...';
|
||||
}
|
||||
|
||||
let b = new BigNumber(satoshi).dividedBy(100000000).multipliedBy(exchangeRates['BTC_' + preferredFiatCurrency.endPointKey]);
|
||||
|
||||
if (b.isGreaterThanOrEqualTo(0.005) || b.isLessThanOrEqualTo(-0.005)) {
|
||||
b = b.toFixed(2);
|
||||
} else {
|
||||
b = b.toPrecision(2);
|
||||
}
|
||||
|
||||
if (format === false) return b;
|
||||
|
||||
let formatter;
|
||||
try {
|
||||
formatter = new Intl.NumberFormat(preferredFiatCurrency.locale, {
|
||||
style: 'currency',
|
||||
currency: preferredFiatCurrency.endPointKey,
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 8,
|
||||
});
|
||||
} catch (error) {
|
||||
console.warn(error);
|
||||
console.log(error);
|
||||
formatter = new Intl.NumberFormat(FiatUnit.USD.locale, {
|
||||
style: 'currency',
|
||||
currency: preferredFiatCurrency.endPointKey,
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 8,
|
||||
});
|
||||
}
|
||||
|
||||
return formatter.format(b);
|
||||
}
|
||||
|
||||
function BTCToLocalCurrency(bitcoin) {
|
||||
let sat = new BigNumber(bitcoin);
|
||||
sat = sat.multipliedBy(100000000).toNumber();
|
||||
|
||||
return satoshiToLocalCurrency(sat);
|
||||
}
|
||||
|
||||
async function mostRecentFetchedRate() {
|
||||
const currencyInformation = JSON.parse(await AsyncStorage.getItem(EXCHANGE_RATES_STORAGE_KEY));
|
||||
|
||||
const formatter = new Intl.NumberFormat(preferredFiatCurrency.locale, {
|
||||
style: 'currency',
|
||||
currency: preferredFiatCurrency.endPointKey,
|
||||
});
|
||||
return {
|
||||
LastUpdated: currencyInformation[LAST_UPDATED],
|
||||
Rate: formatter.format(currencyInformation[`BTC_${preferredFiatCurrency.endPointKey}`]),
|
||||
};
|
||||
}
|
||||
|
||||
function satoshiToBTC(satoshi) {
|
||||
let b = new BigNumber(satoshi);
|
||||
b = b.dividedBy(100000000);
|
||||
return b.toString(10);
|
||||
}
|
||||
|
||||
function btcToSatoshi(btc) {
|
||||
return new BigNumber(btc).multipliedBy(100000000).toNumber();
|
||||
}
|
||||
|
||||
function fiatToBTC(fiatFloat) {
|
||||
let b = new BigNumber(fiatFloat);
|
||||
b = b.dividedBy(exchangeRates['BTC_' + preferredFiatCurrency.endPointKey]).toFixed(8);
|
||||
return b;
|
||||
}
|
||||
|
||||
function getCurrencySymbol() {
|
||||
return preferredFiatCurrency.symbol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to mock data in tests
|
||||
*
|
||||
* @param {object} currency, one of FiatUnit.*
|
||||
*/
|
||||
function _setPreferredFiatCurrency(currency) {
|
||||
preferredFiatCurrency = currency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to mock data in tests
|
||||
*
|
||||
* @param {string} pair as expected by rest of this module, e.g 'BTC_JPY' or 'BTC_USD'
|
||||
* @param {number} rate exchange rate
|
||||
*/
|
||||
function _setExchangeRate(pair, rate) {
|
||||
exchangeRates[pair] = rate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used in unit tests, so the `currency` module wont launch actual http request
|
||||
*/
|
||||
function _setSkipUpdateExchangeRate() {
|
||||
skipUpdateExchangeRate = true;
|
||||
}
|
||||
|
||||
module.exports.updateExchangeRate = updateExchangeRate;
|
||||
module.exports.init = init;
|
||||
module.exports.satoshiToLocalCurrency = satoshiToLocalCurrency;
|
||||
module.exports.fiatToBTC = fiatToBTC;
|
||||
module.exports.satoshiToBTC = satoshiToBTC;
|
||||
module.exports.BTCToLocalCurrency = BTCToLocalCurrency;
|
||||
module.exports.setPrefferedCurrency = setPrefferedCurrency;
|
||||
module.exports.getPreferredCurrency = getPreferredCurrency;
|
||||
module.exports.btcToSatoshi = btcToSatoshi;
|
||||
module.exports.getCurrencySymbol = getCurrencySymbol;
|
||||
module.exports._setPreferredFiatCurrency = _setPreferredFiatCurrency; // export it to mock data in tests
|
||||
module.exports._setExchangeRate = _setExchangeRate; // export it to mock data in tests
|
||||
module.exports._setSkipUpdateExchangeRate = _setSkipUpdateExchangeRate; // export it to mock data in tests
|
||||
module.exports.PREFERRED_CURRENCY = PREFERRED_CURRENCY_STORAGE_KEY;
|
||||
module.exports.EXCHANGE_RATES = EXCHANGE_RATES_STORAGE_KEY;
|
||||
module.exports.LAST_UPDATED = LAST_UPDATED;
|
||||
module.exports.mostRecentFetchedRate = mostRecentFetchedRate;
|
||||
module.exports.isRateOutdated = isRateOutdated;
|
230
blue_modules/currency.ts
Normal file
230
blue_modules/currency.ts
Normal file
|
@ -0,0 +1,230 @@
|
|||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import DefaultPreference from 'react-native-default-preference';
|
||||
import * as RNLocalize from 'react-native-localize';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { FiatUnit, FiatUnitType, getFiatRate } from '../models/fiatUnit';
|
||||
import WidgetCommunication from './WidgetCommunication';
|
||||
|
||||
const PREFERRED_CURRENCY_STORAGE_KEY = 'preferredCurrency';
|
||||
const EXCHANGE_RATES_STORAGE_KEY = 'exchangeRates';
|
||||
const LAST_UPDATED = 'LAST_UPDATED';
|
||||
const GROUP_IO_BLUEWALLET = 'group.io.bluewallet.bluewallet';
|
||||
const BTC_PREFIX = 'BTC_';
|
||||
|
||||
export interface CurrencyRate {
|
||||
LastUpdated: Date | null;
|
||||
Rate: number | string | null;
|
||||
}
|
||||
|
||||
interface ExchangeRates {
|
||||
[key: string]: number | boolean | undefined;
|
||||
LAST_UPDATED_ERROR: boolean;
|
||||
}
|
||||
|
||||
let preferredFiatCurrency: FiatUnitType = FiatUnit.USD;
|
||||
let exchangeRates: ExchangeRates = { LAST_UPDATED_ERROR: false };
|
||||
let lastTimeUpdateExchangeRateWasCalled: number = 0;
|
||||
let skipUpdateExchangeRate: boolean = false;
|
||||
|
||||
async function setPreferredCurrency(item: FiatUnitType): Promise<void> {
|
||||
await AsyncStorage.setItem(PREFERRED_CURRENCY_STORAGE_KEY, JSON.stringify(item));
|
||||
await DefaultPreference.setName(GROUP_IO_BLUEWALLET);
|
||||
await DefaultPreference.set(PREFERRED_CURRENCY_STORAGE_KEY, item.endPointKey);
|
||||
await DefaultPreference.set('preferredCurrencyLocale', item.locale.replace('-', '_'));
|
||||
// @ts-ignore: Convert to TSX later
|
||||
WidgetCommunication.reloadAllTimelines();
|
||||
}
|
||||
|
||||
async function getPreferredCurrency(): Promise<FiatUnitType> {
|
||||
const preferredCurrency = JSON.parse((await AsyncStorage.getItem(PREFERRED_CURRENCY_STORAGE_KEY)) || '{}');
|
||||
await DefaultPreference.setName(GROUP_IO_BLUEWALLET);
|
||||
await DefaultPreference.set(PREFERRED_CURRENCY_STORAGE_KEY, preferredCurrency.endPointKey);
|
||||
await DefaultPreference.set('preferredCurrencyLocale', preferredCurrency.locale.replace('-', '_'));
|
||||
return preferredCurrency;
|
||||
}
|
||||
|
||||
async function _restoreSavedExchangeRatesFromStorage(): Promise<void> {
|
||||
try {
|
||||
const rates = await AsyncStorage.getItem(EXCHANGE_RATES_STORAGE_KEY);
|
||||
exchangeRates = rates ? JSON.parse(rates) : { LAST_UPDATED_ERROR: false };
|
||||
} catch (_) {
|
||||
exchangeRates = { LAST_UPDATED_ERROR: false };
|
||||
}
|
||||
}
|
||||
|
||||
async function _restoreSavedPreferredFiatCurrencyFromStorage(): Promise<void> {
|
||||
try {
|
||||
const storedCurrency = await AsyncStorage.getItem(PREFERRED_CURRENCY_STORAGE_KEY);
|
||||
if (!storedCurrency) throw new Error('No Preferred Fiat selected');
|
||||
preferredFiatCurrency = JSON.parse(storedCurrency);
|
||||
if (!FiatUnit[preferredFiatCurrency.endPointKey]) {
|
||||
throw new Error('Invalid Fiat Unit');
|
||||
}
|
||||
} catch (_) {
|
||||
const deviceCurrencies = RNLocalize.getCurrencies();
|
||||
preferredFiatCurrency = deviceCurrencies[0] && FiatUnit[deviceCurrencies[0]] ? FiatUnit[deviceCurrencies[0]] : FiatUnit.USD;
|
||||
}
|
||||
}
|
||||
|
||||
async function updateExchangeRate(): Promise<void> {
|
||||
if (skipUpdateExchangeRate) return;
|
||||
if (Date.now() - lastTimeUpdateExchangeRateWasCalled <= 10000) {
|
||||
// simple debounce so there's no race conditions
|
||||
return;
|
||||
}
|
||||
lastTimeUpdateExchangeRateWasCalled = Date.now();
|
||||
|
||||
const lastUpdated = exchangeRates[LAST_UPDATED] as number | undefined;
|
||||
if (lastUpdated && Date.now() - lastUpdated <= 30 * 60 * 1000) {
|
||||
// not updating too often
|
||||
return;
|
||||
}
|
||||
console.log('updating exchange rate...');
|
||||
|
||||
try {
|
||||
const rate = await getFiatRate(preferredFiatCurrency.endPointKey);
|
||||
exchangeRates[LAST_UPDATED] = Date.now();
|
||||
exchangeRates[BTC_PREFIX + preferredFiatCurrency.endPointKey] = rate;
|
||||
exchangeRates.LAST_UPDATED_ERROR = false;
|
||||
await AsyncStorage.setItem(EXCHANGE_RATES_STORAGE_KEY, JSON.stringify(exchangeRates));
|
||||
} catch (error) {
|
||||
console.error('Error encountered when attempting to update exchange rate...', error);
|
||||
const rate = JSON.parse((await AsyncStorage.getItem(EXCHANGE_RATES_STORAGE_KEY)) || '{}');
|
||||
rate.LAST_UPDATED_ERROR = true;
|
||||
exchangeRates.LAST_UPDATED_ERROR = true;
|
||||
await AsyncStorage.setItem(EXCHANGE_RATES_STORAGE_KEY, JSON.stringify(rate));
|
||||
}
|
||||
}
|
||||
|
||||
async function isRateOutdated(): Promise<boolean> {
|
||||
try {
|
||||
const rate = JSON.parse((await AsyncStorage.getItem(EXCHANGE_RATES_STORAGE_KEY)) || '{}');
|
||||
return rate.LAST_UPDATED_ERROR || Date.now() - (rate[LAST_UPDATED] || 0) >= 31 * 60 * 1000;
|
||||
} catch {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
async function initCurrencyDaemon(clearLastUpdatedTime: boolean = false): Promise<void> {
|
||||
await _restoreSavedExchangeRatesFromStorage();
|
||||
await _restoreSavedPreferredFiatCurrencyFromStorage();
|
||||
|
||||
if (clearLastUpdatedTime) {
|
||||
exchangeRates[LAST_UPDATED] = 0;
|
||||
lastTimeUpdateExchangeRateWasCalled = 0;
|
||||
}
|
||||
|
||||
await updateExchangeRate();
|
||||
}
|
||||
|
||||
function satoshiToLocalCurrency(satoshi: number, format: boolean = true): string {
|
||||
const exchangeRateKey = BTC_PREFIX + preferredFiatCurrency.endPointKey;
|
||||
const exchangeRate = exchangeRates[exchangeRateKey];
|
||||
|
||||
if (typeof exchangeRate !== 'number') {
|
||||
updateExchangeRate();
|
||||
return '...';
|
||||
}
|
||||
|
||||
const btcAmount = new BigNumber(satoshi).dividedBy(100000000);
|
||||
const convertedAmount = btcAmount.multipliedBy(exchangeRate);
|
||||
let formattedAmount: string;
|
||||
|
||||
if (convertedAmount.isGreaterThanOrEqualTo(0.005) || convertedAmount.isLessThanOrEqualTo(-0.005)) {
|
||||
formattedAmount = convertedAmount.toFixed(2);
|
||||
} else {
|
||||
formattedAmount = convertedAmount.toPrecision(2);
|
||||
}
|
||||
|
||||
if (format === false) return formattedAmount;
|
||||
|
||||
try {
|
||||
const formatter = new Intl.NumberFormat(preferredFiatCurrency.locale, {
|
||||
style: 'currency',
|
||||
currency: preferredFiatCurrency.endPointKey,
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 8,
|
||||
});
|
||||
return formatter.format(Number(formattedAmount));
|
||||
} catch (error) {
|
||||
console.warn(error);
|
||||
return formattedAmount;
|
||||
}
|
||||
}
|
||||
|
||||
function BTCToLocalCurrency(bitcoin: BigNumber.Value): string {
|
||||
const sat = new BigNumber(bitcoin).multipliedBy(100000000).toNumber();
|
||||
return satoshiToLocalCurrency(sat);
|
||||
}
|
||||
|
||||
async function mostRecentFetchedRate(): Promise<CurrencyRate> {
|
||||
const currencyInformation = JSON.parse((await AsyncStorage.getItem(EXCHANGE_RATES_STORAGE_KEY)) || '{}');
|
||||
|
||||
const formatter = new Intl.NumberFormat(preferredFiatCurrency.locale, {
|
||||
style: 'currency',
|
||||
currency: preferredFiatCurrency.endPointKey,
|
||||
});
|
||||
|
||||
const rate = currencyInformation[BTC_PREFIX + preferredFiatCurrency.endPointKey];
|
||||
return {
|
||||
LastUpdated: currencyInformation[LAST_UPDATED],
|
||||
Rate: rate ? formatter.format(rate) : '...',
|
||||
};
|
||||
}
|
||||
|
||||
function satoshiToBTC(satoshi: number): string {
|
||||
return new BigNumber(satoshi).dividedBy(100000000).toString(10);
|
||||
}
|
||||
|
||||
function btcToSatoshi(btc: BigNumber.Value): number {
|
||||
return new BigNumber(btc).multipliedBy(100000000).toNumber();
|
||||
}
|
||||
|
||||
function fiatToBTC(fiatFloat: number): string {
|
||||
const exchangeRateKey = BTC_PREFIX + preferredFiatCurrency.endPointKey;
|
||||
const exchangeRate = exchangeRates[exchangeRateKey];
|
||||
|
||||
if (typeof exchangeRate !== 'number') {
|
||||
throw new Error('Exchange rate not available');
|
||||
}
|
||||
|
||||
const btcAmount = new BigNumber(fiatFloat).dividedBy(exchangeRate);
|
||||
return btcAmount.toFixed(8);
|
||||
}
|
||||
|
||||
function getCurrencySymbol(): string {
|
||||
return preferredFiatCurrency.symbol;
|
||||
}
|
||||
|
||||
function _setPreferredFiatCurrency(currency: FiatUnitType): void {
|
||||
preferredFiatCurrency = currency;
|
||||
}
|
||||
|
||||
function _setExchangeRate(pair: string, rate: number): void {
|
||||
exchangeRates[pair] = rate;
|
||||
}
|
||||
|
||||
function _setSkipUpdateExchangeRate(): void {
|
||||
skipUpdateExchangeRate = true;
|
||||
}
|
||||
|
||||
export {
|
||||
updateExchangeRate,
|
||||
initCurrencyDaemon,
|
||||
satoshiToLocalCurrency,
|
||||
fiatToBTC,
|
||||
satoshiToBTC,
|
||||
BTCToLocalCurrency,
|
||||
setPreferredCurrency,
|
||||
getPreferredCurrency,
|
||||
btcToSatoshi,
|
||||
getCurrencySymbol,
|
||||
_setPreferredFiatCurrency,
|
||||
_setExchangeRate,
|
||||
_setSkipUpdateExchangeRate,
|
||||
PREFERRED_CURRENCY_STORAGE_KEY,
|
||||
EXCHANGE_RATES_STORAGE_KEY,
|
||||
LAST_UPDATED,
|
||||
mostRecentFetchedRate,
|
||||
isRateOutdated,
|
||||
};
|
|
@ -7,9 +7,9 @@ import loc, { STORAGE_KEY as LOC_STORAGE_KEY } from '../loc';
|
|||
import { LegacyWallet, WatchOnlyWallet } from '../class';
|
||||
import alert from '../components/Alert';
|
||||
import triggerHapticFeedback, { HapticFeedbackTypes } from './hapticFeedback';
|
||||
import { PREFERRED_CURRENCY_STORAGE_KEY } from './currency';
|
||||
const BlueApp = require('../BlueApp');
|
||||
const BlueElectrum = require('./BlueElectrum');
|
||||
const currency = require('../blue_modules/currency');
|
||||
const A = require('../blue_modules/analytics');
|
||||
|
||||
const _lastTimeTriedToRefetchWallet = {}; // hashmap of timestamps we _started_ refetching some wallet
|
||||
|
@ -23,7 +23,7 @@ export const BlueStorageProvider = ({ children }) => {
|
|||
const [walletsInitialized, setWalletsInitialized] = useState(false);
|
||||
const [preferredFiatCurrency, _setPreferredFiatCurrency] = useState(FiatUnit.USD);
|
||||
const [language, _setLanguage] = useState();
|
||||
const getPreferredCurrencyAsyncStorage = useAsyncStorage(currency.PREFERRED_CURRENCY).getItem;
|
||||
const getPreferredCurrencyAsyncStorage = useAsyncStorage(PREFERRED_CURRENCY_STORAGE_KEY).getItem;
|
||||
const getLanguageAsyncStorage = useAsyncStorage(LOC_STORAGE_KEY).getItem;
|
||||
const [isHandOffUseEnabled, setIsHandOffUseEnabled] = useState(false);
|
||||
const [isElectrumDisabled, setIsElectrumDisabled] = useState(true);
|
||||
|
|
|
@ -10,7 +10,14 @@ import loc, { formatBalanceWithoutSuffix, formatBalancePlain, removeTrailingZero
|
|||
import { BlueText } from '../BlueComponents';
|
||||
import dayjs from 'dayjs';
|
||||
import { useTheme } from './themes';
|
||||
const currency = require('../blue_modules/currency');
|
||||
import {
|
||||
fiatToBTC,
|
||||
getCurrencySymbol,
|
||||
isRateOutdated,
|
||||
mostRecentFetchedRate,
|
||||
satoshiToBTC,
|
||||
updateExchangeRate,
|
||||
} from '../blue_modules/currency';
|
||||
dayjs.extend(require('dayjs/plugin/localizedFormat'));
|
||||
|
||||
class AmountInput extends Component {
|
||||
|
@ -57,13 +64,12 @@ class AmountInput extends Component {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
currency
|
||||
.mostRecentFetchedRate()
|
||||
.then(mostRecentFetchedRate => {
|
||||
this.setState({ mostRecentFetchedRate });
|
||||
mostRecentFetchedRate()
|
||||
.then(mostRecentFetchedRateValue => {
|
||||
this.setState({ mostRecentFetchedRate: mostRecentFetchedRateValue });
|
||||
})
|
||||
.finally(() => {
|
||||
currency.isRateOutdated().then(isRateOutdated => this.setState({ isRateOutdated }));
|
||||
isRateOutdated().then(isRateOutdatedValue => this.setState({ isRateOutdated: isRateOutdatedValue }));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -86,7 +92,7 @@ class AmountInput extends Component {
|
|||
sats = amount;
|
||||
break;
|
||||
case BitcoinUnit.LOCAL_CURRENCY:
|
||||
sats = new BigNumber(currency.fiatToBTC(amount)).multipliedBy(100000000).toString();
|
||||
sats = new BigNumber(fiatToBTC(amount)).multipliedBy(100000000).toString();
|
||||
break;
|
||||
}
|
||||
if (previousUnit === BitcoinUnit.LOCAL_CURRENCY && AmountInput.conversionCache[amount + previousUnit]) {
|
||||
|
@ -191,14 +197,14 @@ class AmountInput extends Component {
|
|||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||
this.setState({ isRateBeingUpdated: true }, async () => {
|
||||
try {
|
||||
await currency.updateExchangeRate();
|
||||
currency.mostRecentFetchedRate().then(mostRecentFetchedRate => {
|
||||
await updateExchangeRate();
|
||||
mostRecentFetchedRate().then(mostRecentFetchedRateValue => {
|
||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||
this.setState({ mostRecentFetchedRate });
|
||||
this.setState({ mostRecentFetchedRate: mostRecentFetchedRateValue });
|
||||
});
|
||||
} finally {
|
||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||
this.setState({ isRateBeingUpdated: false, isRateOutdated: await currency.isRateOutdated() });
|
||||
this.setState({ isRateBeingUpdated: false, isRateOutdated: await isRateOutdated() });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -220,11 +226,11 @@ class AmountInput extends Component {
|
|||
secondaryDisplayCurrency = formatBalanceWithoutSuffix((isNaN(amount) ? 0 : amount).toString(), BitcoinUnit.LOCAL_CURRENCY, false);
|
||||
break;
|
||||
case BitcoinUnit.LOCAL_CURRENCY:
|
||||
secondaryDisplayCurrency = currency.fiatToBTC(parseFloat(isNaN(amount) ? 0 : amount));
|
||||
secondaryDisplayCurrency = fiatToBTC(parseFloat(isNaN(amount) ? 0 : amount));
|
||||
if (AmountInput.conversionCache[isNaN(amount) ? 0 : amount + BitcoinUnit.LOCAL_CURRENCY]) {
|
||||
// cache hit! we reuse old value that supposedly doesn't have rounding errors
|
||||
const sats = AmountInput.conversionCache[isNaN(amount) ? 0 : amount + BitcoinUnit.LOCAL_CURRENCY];
|
||||
secondaryDisplayCurrency = currency.satoshiToBTC(sats);
|
||||
secondaryDisplayCurrency = satoshiToBTC(sats);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -251,7 +257,7 @@ class AmountInput extends Component {
|
|||
<View style={styles.flex}>
|
||||
<View style={styles.container}>
|
||||
{unit === BitcoinUnit.LOCAL_CURRENCY && amount !== BitcoinUnit.MAX && (
|
||||
<Text style={[styles.localCurrency, stylesHook.localCurrency]}>{currency.getCurrencySymbol() + ' '}</Text>
|
||||
<Text style={[styles.localCurrency, stylesHook.localCurrency]}>{getCurrencySymbol() + ' '}</Text>
|
||||
)}
|
||||
{amount !== BitcoinUnit.MAX ? (
|
||||
<TextInput
|
||||
|
|
|
@ -65,7 +65,10 @@ const TransactionsNavigationHeader: React.FC<TransactionsNavigationHeaderProps>
|
|||
}, [wallet, verifyIfWalletAllowsOnchainAddress]);
|
||||
|
||||
const handleCopyPress = () => {
|
||||
Clipboard.setString(formatBalance(wallet.getBalance(), wallet.getPreferredBalanceUnit()).toString());
|
||||
const value = formatBalance(wallet.getBalance(), wallet.getPreferredBalanceUnit());
|
||||
if (value) {
|
||||
Clipboard.setString(value);
|
||||
}
|
||||
};
|
||||
|
||||
const updateWalletVisibility = (w: AbstractWallet, newHideBalance: boolean) => {
|
||||
|
@ -134,8 +137,8 @@ const TransactionsNavigationHeader: React.FC<TransactionsNavigationHeaderProps>
|
|||
const balance = useMemo(() => {
|
||||
const hideBalance = wallet.hideBalance;
|
||||
const balanceUnit = wallet.getPreferredBalanceUnit();
|
||||
const balanceFormatted = formatBalance(wallet.getBalance(), balanceUnit, true).toString();
|
||||
return !hideBalance && balanceFormatted;
|
||||
const balanceFormatted = formatBalance(wallet.getBalance(), balanceUnit, true);
|
||||
return !hideBalance && balanceFormatted?.toString();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [wallet.hideBalance, wallet.getPreferredBalanceUnit()]);
|
||||
|
||||
|
@ -211,6 +214,7 @@ const TransactionsNavigationHeader: React.FC<TransactionsNavigationHeaderProps>
|
|||
) : (
|
||||
<Text
|
||||
testID="WalletBalance"
|
||||
// @ts-ignore: Ugh
|
||||
key={balance} // force component recreation on balance change. To fix right-to-left languages, like Farsi
|
||||
numberOfLines={1}
|
||||
adjustsFontSizeToFit
|
||||
|
|
|
@ -9,7 +9,7 @@ import BigNumber from 'bignumber.js';
|
|||
import { BitcoinUnit } from '../models/bitcoinUnits';
|
||||
import { AvailableLanguages } from './languages';
|
||||
import { I18nManager } from 'react-native';
|
||||
const currency = require('../blue_modules/currency');
|
||||
import { satoshiToLocalCurrency } from '../blue_modules/currency';
|
||||
|
||||
export const STORAGE_KEY = 'lang';
|
||||
|
||||
|
@ -310,7 +310,7 @@ export function formatBalance(balance: number, toUnit: string, withFormatting =
|
|||
} else if (toUnit === BitcoinUnit.SATS) {
|
||||
return (withFormatting ? new Intl.NumberFormat().format(balance).toString() : String(balance)) + ' ' + loc.units[BitcoinUnit.SATS];
|
||||
} else if (toUnit === BitcoinUnit.LOCAL_CURRENCY) {
|
||||
return currency.satoshiToLocalCurrency(balance);
|
||||
return satoshiToLocalCurrency(balance);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -332,7 +332,7 @@ export function formatBalanceWithoutSuffix(balance = 0, toUnit: string, withForm
|
|||
} else if (toUnit === BitcoinUnit.SATS) {
|
||||
return withFormatting ? new Intl.NumberFormat().format(balance).toString() : String(balance);
|
||||
} else if (toUnit === BitcoinUnit.LOCAL_CURRENCY) {
|
||||
return currency.satoshiToLocalCurrency(balance);
|
||||
return satoshiToLocalCurrency(balance);
|
||||
}
|
||||
}
|
||||
return balance.toString();
|
||||
|
@ -349,7 +349,7 @@ export function formatBalanceWithoutSuffix(balance = 0, toUnit: string, withForm
|
|||
export function formatBalancePlain(balance = 0, toUnit: string, withFormatting = false) {
|
||||
const newInputValue = formatBalanceWithoutSuffix(balance, toUnit, withFormatting);
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
return _leaveNumbersAndDots(newInputValue);
|
||||
return _leaveNumbersAndDots(newInputValue.toString());
|
||||
}
|
||||
|
||||
export function _leaveNumbersAndDots(newInputValue: string) {
|
||||
|
|
|
@ -18,7 +18,7 @@ import { useTheme } from '../../components/themes';
|
|||
import Button from '../../components/Button';
|
||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||
import SafeArea from '../../components/SafeArea';
|
||||
const currency = require('../../blue_modules/currency');
|
||||
import { btcToSatoshi, fiatToBTC } from '../../blue_modules/currency';
|
||||
|
||||
type LdkOpenChannelProps = RouteProp<
|
||||
{
|
||||
|
@ -223,11 +223,11 @@ const LdkOpenChannel = (props: any) => {
|
|||
amountSats = parseInt(fundingAmount.amount, 10);
|
||||
break;
|
||||
case BitcoinUnit.BTC:
|
||||
amountSats = currency.btcToSatoshi(fundingAmount.amount);
|
||||
amountSats = btcToSatoshi(fundingAmount.amount);
|
||||
break;
|
||||
case BitcoinUnit.LOCAL_CURRENCY:
|
||||
// also accounting for cached fiat->sat conversion to avoid rounding error
|
||||
amountSats = currency.btcToSatoshi(currency.fiatToBTC(fundingAmount.amount));
|
||||
amountSats = btcToSatoshi(fiatToBTC(fundingAmount.amount));
|
||||
break;
|
||||
}
|
||||
setFundingAmount({ amount: fundingAmount.amount, amountSats });
|
||||
|
@ -237,10 +237,10 @@ const LdkOpenChannel = (props: any) => {
|
|||
let amountSats = fundingAmount.amountSats;
|
||||
switch (unit) {
|
||||
case BitcoinUnit.BTC:
|
||||
amountSats = currency.btcToSatoshi(text);
|
||||
amountSats = btcToSatoshi(text);
|
||||
break;
|
||||
case BitcoinUnit.LOCAL_CURRENCY:
|
||||
amountSats = currency.btcToSatoshi(currency.fiatToBTC(text));
|
||||
amountSats = btcToSatoshi(fiatToBTC(Number(text)));
|
||||
break;
|
||||
case BitcoinUnit.SATS:
|
||||
amountSats = parseInt(text, 10);
|
||||
|
|
|
@ -31,7 +31,7 @@ import { requestCameraAuthorization } from '../../helpers/scan-qr';
|
|||
import { useTheme } from '../../components/themes';
|
||||
import Button from '../../components/Button';
|
||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||
const currency = require('../../blue_modules/currency');
|
||||
import { btcToSatoshi, fiatToBTC, satoshiToBTC } from '../../blue_modules/currency';
|
||||
|
||||
const LNDCreateInvoice = () => {
|
||||
const { wallets, saveToDisk, setSelectedWalletID } = useContext(BlueStorageContext);
|
||||
|
@ -156,11 +156,11 @@ const LNDCreateInvoice = () => {
|
|||
invoiceAmount = parseInt(invoiceAmount, 10); // basically nop
|
||||
break;
|
||||
case BitcoinUnit.BTC:
|
||||
invoiceAmount = currency.btcToSatoshi(invoiceAmount);
|
||||
invoiceAmount = btcToSatoshi(invoiceAmount);
|
||||
break;
|
||||
case BitcoinUnit.LOCAL_CURRENCY:
|
||||
// trying to fetch cached sat equivalent for this fiat amount
|
||||
invoiceAmount = AmountInput.getCachedSatoshis(invoiceAmount) || currency.btcToSatoshi(currency.fiatToBTC(invoiceAmount));
|
||||
invoiceAmount = AmountInput.getCachedSatoshis(invoiceAmount) || btcToSatoshi(fiatToBTC(invoiceAmount));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -285,7 +285,7 @@ const LNDCreateInvoice = () => {
|
|||
// nop
|
||||
break;
|
||||
case BitcoinUnit.BTC:
|
||||
newAmount = currency.satoshiToBTC(newAmount);
|
||||
newAmount = satoshiToBTC(newAmount);
|
||||
break;
|
||||
case BitcoinUnit.LOCAL_CURRENCY:
|
||||
newAmount = formatBalancePlain(newAmount, BitcoinUnit.LOCAL_CURRENCY);
|
||||
|
|
|
@ -17,8 +17,8 @@ import { useTheme } from '../../components/themes';
|
|||
import Button from '../../components/Button';
|
||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||
import SafeArea from '../../components/SafeArea';
|
||||
import { btcToSatoshi, fiatToBTC, satoshiToBTC, satoshiToLocalCurrency } from '../../blue_modules/currency';
|
||||
const prompt = require('../../helpers/prompt');
|
||||
const currency = require('../../blue_modules/currency');
|
||||
|
||||
/**
|
||||
* if user has default currency - fiat, attempting to pay will trigger conversion from entered in input field fiat value
|
||||
|
@ -86,10 +86,10 @@ const LnurlPay = () => {
|
|||
}
|
||||
switch (unit) {
|
||||
case BitcoinUnit.BTC:
|
||||
newAmount = currency.satoshiToBTC(newAmount);
|
||||
newAmount = satoshiToBTC(newAmount);
|
||||
break;
|
||||
case BitcoinUnit.LOCAL_CURRENCY:
|
||||
newAmount = currency.satoshiToLocalCurrency(newAmount, false);
|
||||
newAmount = satoshiToLocalCurrency(newAmount, false);
|
||||
_cacheFiatToSat[newAmount] = originalSatAmount;
|
||||
break;
|
||||
}
|
||||
|
@ -120,13 +120,13 @@ const LnurlPay = () => {
|
|||
amountSats = parseInt(amountSats, 10); // nop
|
||||
break;
|
||||
case BitcoinUnit.BTC:
|
||||
amountSats = currency.btcToSatoshi(amountSats);
|
||||
amountSats = btcToSatoshi(amountSats);
|
||||
break;
|
||||
case BitcoinUnit.LOCAL_CURRENCY:
|
||||
if (_cacheFiatToSat[amount]) {
|
||||
amountSats = _cacheFiatToSat[amount];
|
||||
} else {
|
||||
amountSats = currency.btcToSatoshi(currency.fiatToBTC(amountSats));
|
||||
amountSats = btcToSatoshi(fiatToBTC(amountSats));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import { useTheme } from '../../components/themes';
|
|||
import Button from '../../components/Button';
|
||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||
import SafeArea from '../../components/SafeArea';
|
||||
const currency = require('../../blue_modules/currency');
|
||||
import { btcToSatoshi, fiatToBTC } from '../../blue_modules/currency';
|
||||
|
||||
const ScanLndInvoice = () => {
|
||||
const { wallets, fetchAndSaveWalletTransactions } = useContext(BlueStorageContext);
|
||||
|
@ -182,10 +182,10 @@ const ScanLndInvoice = () => {
|
|||
amountSats = parseInt(amountSats, 10); // nop
|
||||
break;
|
||||
case BitcoinUnit.BTC:
|
||||
amountSats = currency.btcToSatoshi(amountSats);
|
||||
amountSats = btcToSatoshi(amountSats);
|
||||
break;
|
||||
case BitcoinUnit.LOCAL_CURRENCY:
|
||||
amountSats = currency.btcToSatoshi(currency.fiatToBTC(amountSats));
|
||||
amountSats = btcToSatoshi(fiatToBTC(amountSats));
|
||||
break;
|
||||
}
|
||||
setIsLoading(true);
|
||||
|
|
|
@ -38,7 +38,7 @@ import { SuccessView } from '../send/success';
|
|||
import { useTheme } from '../../components/themes';
|
||||
import Button from '../../components/Button';
|
||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||
const currency = require('../../blue_modules/currency');
|
||||
import { fiatToBTC, satoshiToBTC } from '../../blue_modules/currency';
|
||||
|
||||
const ReceiveDetails = () => {
|
||||
const { walletID, address } = useRoute().params;
|
||||
|
@ -385,14 +385,14 @@ const ReceiveDetails = () => {
|
|||
// nop
|
||||
break;
|
||||
case BitcoinUnit.SATS:
|
||||
amount = currency.satoshiToBTC(customAmount);
|
||||
amount = satoshiToBTC(customAmount);
|
||||
break;
|
||||
case BitcoinUnit.LOCAL_CURRENCY:
|
||||
if (AmountInput.conversionCache[amount + BitcoinUnit.LOCAL_CURRENCY]) {
|
||||
// cache hit! we reuse old value that supposedly doesnt have rounding errors
|
||||
amount = currency.satoshiToBTC(AmountInput.conversionCache[amount + BitcoinUnit.LOCAL_CURRENCY]);
|
||||
amount = satoshiToBTC(AmountInput.conversionCache[amount + BitcoinUnit.LOCAL_CURRENCY]);
|
||||
} else {
|
||||
amount = currency.fiatToBTC(customAmount);
|
||||
amount = fiatToBTC(customAmount);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -447,9 +447,9 @@ const ReceiveDetails = () => {
|
|||
case BitcoinUnit.BTC:
|
||||
return customAmount + ' BTC';
|
||||
case BitcoinUnit.SATS:
|
||||
return currency.satoshiToBTC(customAmount) + ' BTC';
|
||||
return satoshiToBTC(customAmount) + ' BTC';
|
||||
case BitcoinUnit.LOCAL_CURRENCY:
|
||||
return currency.fiatToBTC(customAmount) + ' BTC';
|
||||
return fiatToBTC(customAmount) + ' BTC';
|
||||
}
|
||||
return customAmount + ' ' + customUnit;
|
||||
} else {
|
||||
|
|
|
@ -17,7 +17,7 @@ import { useTheme } from '../../components/themes';
|
|||
import Button from '../../components/Button';
|
||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||
import SafeArea from '../../components/SafeArea';
|
||||
const currency = require('../../blue_modules/currency');
|
||||
import { satoshiToBTC, satoshiToLocalCurrency } from '../../blue_modules/currency';
|
||||
const BlueElectrum = require('../../blue_modules/BlueElectrum');
|
||||
const Bignumber = require('bignumber.js');
|
||||
const bitcoin = require('bitcoinjs-lib');
|
||||
|
@ -182,11 +182,11 @@ const Confirm = () => {
|
|||
<>
|
||||
<View style={styles.valueWrap}>
|
||||
<Text testID="TransactionValue" style={[styles.valueValue, stylesHook.valueValue]}>
|
||||
{currency.satoshiToBTC(item.value)}
|
||||
{satoshiToBTC(item.value)}
|
||||
</Text>
|
||||
<Text style={[styles.valueUnit, stylesHook.valueValue]}>{' ' + loc.units[BitcoinUnit.BTC]}</Text>
|
||||
</View>
|
||||
<Text style={[styles.transactionAmountFiat, stylesHook.transactionAmountFiat]}>{currency.satoshiToLocalCurrency(item.value)}</Text>
|
||||
<Text style={[styles.transactionAmountFiat, stylesHook.transactionAmountFiat]}>{satoshiToLocalCurrency(item.value)}</Text>
|
||||
<BlueCard>
|
||||
<Text style={[styles.transactionDetailsTitle, stylesHook.transactionDetailsTitle]}>{loc.send.create_to}</Text>
|
||||
<Text testID="TransactionAddress" style={[styles.transactionDetailsSubtitle, stylesHook.transactionDetailsSubtitle]}>
|
||||
|
@ -233,7 +233,7 @@ const Confirm = () => {
|
|||
<View style={styles.cardBottom}>
|
||||
<BlueCard>
|
||||
<Text style={styles.cardText} testID="TransactionFee">
|
||||
{loc.send.create_fee}: {formatBalance(feeSatoshi, BitcoinUnit.BTC)} ({currency.satoshiToLocalCurrency(feeSatoshi)})
|
||||
{loc.send.create_fee}: {formatBalance(feeSatoshi, BitcoinUnit.BTC)} ({satoshiToLocalCurrency(feeSatoshi)})
|
||||
</Text>
|
||||
{isLoading ? <ActivityIndicator /> : <Button disabled={isElectrumDisabled} onPress={send} title={loc.send.confirm_sendNow} />}
|
||||
</BlueCard>
|
||||
|
|
|
@ -17,8 +17,8 @@ import { useNavigation, useRoute } from '@react-navigation/native';
|
|||
import alert from '../../components/Alert';
|
||||
import { PERMISSIONS, RESULTS, request } from 'react-native-permissions';
|
||||
import { useTheme } from '../../components/themes';
|
||||
import { satoshiToBTC } from '../../blue_modules/currency';
|
||||
const bitcoin = require('bitcoinjs-lib');
|
||||
const currency = require('../../blue_modules/currency');
|
||||
|
||||
const SendCreate = () => {
|
||||
const { fee, recipients, memo = '', satoshiPerByte, psbt, showAnimatedQr, tx } = useRoute().params;
|
||||
|
@ -116,7 +116,7 @@ const SendCreate = () => {
|
|||
<Text style={[styles.transactionDetailsSubtitle, styleHooks.transactionDetailsSubtitle]}>{item.address}</Text>
|
||||
<Text style={[styles.transactionDetailsTitle, styleHooks.transactionDetailsTitle]}>{loc.send.create_amount}</Text>
|
||||
<Text style={[styles.transactionDetailsSubtitle, styleHooks.transactionDetailsSubtitle]}>
|
||||
{currency.satoshiToBTC(item.value)} {BitcoinUnit.BTC}
|
||||
{satoshiToBTC(item.value)} {BitcoinUnit.BTC}
|
||||
</Text>
|
||||
{recipients.length > 1 && (
|
||||
<BlueText style={styles.itemOf}>{loc.formatString(loc._.of, { number: index + 1, total: recipients.length })}</BlueText>
|
||||
|
|
|
@ -44,7 +44,7 @@ import { useTheme } from '../../components/themes';
|
|||
import Button from '../../components/Button';
|
||||
import ListItem from '../../components/ListItem';
|
||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||
const currency = require('../../blue_modules/currency');
|
||||
import { btcToSatoshi, fiatToBTC } from '../../blue_modules/currency';
|
||||
const prompt = require('../../helpers/prompt');
|
||||
const fs = require('../../blue_modules/fs');
|
||||
const btcAddressRx = /^[a-zA-Z0-9]{26,35}$/;
|
||||
|
@ -145,12 +145,12 @@ const SendDetails = () => {
|
|||
currentAddress.address = address;
|
||||
if (Number(amount) > 0) {
|
||||
currentAddress.amount = amount;
|
||||
currentAddress.amountSats = currency.btcToSatoshi(amount);
|
||||
currentAddress.amountSats = btcToSatoshi(amount);
|
||||
}
|
||||
addrs[scrollIndex.current] = currentAddress;
|
||||
return [...addrs];
|
||||
} else {
|
||||
return [...addrs, { address, amount, amountSats: currency.btcToSatoshi(amount), key: String(Math.random()) }];
|
||||
return [...addrs, { address, amount, amountSats: btcToSatoshi(amount), key: String(Math.random()) }];
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -285,8 +285,8 @@ const SendDetails = () => {
|
|||
if (value > 0) {
|
||||
targets.push({ address: transaction.address, value });
|
||||
} else if (transaction.amount) {
|
||||
if (currency.btcToSatoshi(transaction.amount) > 0) {
|
||||
targets.push({ address: transaction.address, value: currency.btcToSatoshi(transaction.amount) });
|
||||
if (btcToSatoshi(transaction.amount) > 0) {
|
||||
targets.push({ address: transaction.address, value: btcToSatoshi(transaction.amount) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -517,8 +517,8 @@ const SendDetails = () => {
|
|||
if (value > 0) {
|
||||
targets.push({ address: transaction.address, value });
|
||||
} else if (transaction.amount) {
|
||||
if (currency.btcToSatoshi(transaction.amount) > 0) {
|
||||
targets.push({ address: transaction.address, value: currency.btcToSatoshi(transaction.amount) });
|
||||
if (btcToSatoshi(transaction.amount) > 0) {
|
||||
targets.push({ address: transaction.address, value: btcToSatoshi(transaction.amount) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1329,11 +1329,11 @@ const SendDetails = () => {
|
|||
addr.amountSats = parseInt(addr.amount, 10);
|
||||
break;
|
||||
case BitcoinUnit.BTC:
|
||||
addr.amountSats = currency.btcToSatoshi(addr.amount);
|
||||
addr.amountSats = btcToSatoshi(addr.amount);
|
||||
break;
|
||||
case BitcoinUnit.LOCAL_CURRENCY:
|
||||
// also accounting for cached fiat->sat conversion to avoid rounding error
|
||||
addr.amountSats = AmountInput.getCachedSatoshis(addr.amount) || currency.btcToSatoshi(currency.fiatToBTC(addr.amount));
|
||||
addr.amountSats = AmountInput.getCachedSatoshis(addr.amount) || btcToSatoshi(fiatToBTC(addr.amount));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1350,10 +1350,10 @@ const SendDetails = () => {
|
|||
item.amount = text;
|
||||
switch (units[index] || amountUnit) {
|
||||
case BitcoinUnit.BTC:
|
||||
item.amountSats = currency.btcToSatoshi(item.amount);
|
||||
item.amountSats = btcToSatoshi(item.amount);
|
||||
break;
|
||||
case BitcoinUnit.LOCAL_CURRENCY:
|
||||
item.amountSats = currency.btcToSatoshi(currency.fiatToBTC(item.amount));
|
||||
item.amountSats = btcToSatoshi(fiatToBTC(item.amount));
|
||||
break;
|
||||
case BitcoinUnit.SATS:
|
||||
default:
|
||||
|
|
|
@ -12,9 +12,9 @@ import alert from '../../components/Alert';
|
|||
import { useTheme } from '../../components/themes';
|
||||
import Button from '../../components/Button';
|
||||
import SafeArea from '../../components/SafeArea';
|
||||
import { satoshiToBTC, satoshiToLocalCurrency } from '../../blue_modules/currency';
|
||||
const bitcoin = require('bitcoinjs-lib');
|
||||
const BigNumber = require('bignumber.js');
|
||||
const currency = require('../../blue_modules/currency');
|
||||
|
||||
const shortenAddress = addr => {
|
||||
return addr.substr(0, Math.floor(addr.length / 2) - 1) + '\n' + addr.substr(Math.floor(addr.length / 2) - 1, addr.length);
|
||||
|
@ -81,7 +81,7 @@ const PsbtMultisig = () => {
|
|||
}
|
||||
destination = shortenAddress(destination.join(', '));
|
||||
const totalBtc = new BigNumber(totalSat).dividedBy(100000000).toNumber();
|
||||
const totalFiat = currency.satoshiToLocalCurrency(totalSat);
|
||||
const totalFiat = satoshiToLocalCurrency(totalSat);
|
||||
|
||||
const getFee = () => {
|
||||
return wallet.calculateFeeFromPsbt(psbt);
|
||||
|
@ -252,9 +252,9 @@ const PsbtMultisig = () => {
|
|||
<View style={styles.bottomWrapper}>
|
||||
<View style={styles.bottomFeesWrapper}>
|
||||
<BlueText style={[styles.feeFiatText, stylesHook.feeFiatText]}>
|
||||
{loc.formatString(loc.multisig.fee, { number: currency.satoshiToLocalCurrency(getFee()) })} -{' '}
|
||||
{loc.formatString(loc.multisig.fee, { number: satoshiToLocalCurrency(getFee()) })} -{' '}
|
||||
</BlueText>
|
||||
<BlueText>{loc.formatString(loc.multisig.fee_btc, { number: currency.satoshiToBTC(getFee()) })}</BlueText>
|
||||
<BlueText>{loc.formatString(loc.multisig.fee_btc, { number: satoshiToBTC(getFee()) })}</BlueText>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.marginConfirmButton}>
|
||||
|
|
|
@ -10,16 +10,17 @@ import dayjs from 'dayjs';
|
|||
import alert from '../../components/Alert';
|
||||
import { useTheme } from '../../components/themes';
|
||||
import ListItem from '../../components/ListItem';
|
||||
import {
|
||||
CurrencyRate,
|
||||
getPreferredCurrency,
|
||||
initCurrencyDaemon,
|
||||
mostRecentFetchedRate,
|
||||
setPreferredCurrency,
|
||||
} from '../../blue_modules/currency';
|
||||
dayjs.extend(require('dayjs/plugin/calendar'));
|
||||
const currency = require('../../blue_modules/currency');
|
||||
|
||||
const ITEM_HEIGHT = 50;
|
||||
|
||||
interface CurrencyRate {
|
||||
LastUpdated: Date | null;
|
||||
Rate: number | null;
|
||||
}
|
||||
|
||||
const Currency: React.FC = () => {
|
||||
const { setPreferredFiatCurrency } = useContext(BlueStorageContext);
|
||||
const [isSavingNewPreferredCurrency, setIsSavingNewPreferredCurrency] = useState(false);
|
||||
|
@ -39,18 +40,18 @@ const Currency: React.FC = () => {
|
|||
});
|
||||
|
||||
const fetchCurrency = async () => {
|
||||
let preferredCurrency = FiatUnit.USD;
|
||||
let preferredCurrency;
|
||||
try {
|
||||
preferredCurrency = await currency.getPreferredCurrency();
|
||||
preferredCurrency = await getPreferredCurrency();
|
||||
if (preferredCurrency === null) {
|
||||
throw Error();
|
||||
}
|
||||
setSelectedCurrency(preferredCurrency);
|
||||
} catch (_error) {
|
||||
setSelectedCurrency(preferredCurrency);
|
||||
setSelectedCurrency(FiatUnit.USD);
|
||||
}
|
||||
const mostRecentFetchedRate = await currency.mostRecentFetchedRate();
|
||||
setCurrencyRate(mostRecentFetchedRate);
|
||||
const mostRecentFetchedRateValue = await mostRecentFetchedRate();
|
||||
setCurrencyRate(mostRecentFetchedRateValue);
|
||||
};
|
||||
|
||||
useLayoutEffect(() => {
|
||||
|
@ -78,8 +79,8 @@ const Currency: React.FC = () => {
|
|||
setIsSavingNewPreferredCurrency(true);
|
||||
try {
|
||||
await getFiatRate(item.endPointKey);
|
||||
await currency.setPrefferedCurrency(item);
|
||||
await currency.init(true);
|
||||
await setPreferredCurrency(item);
|
||||
await initCurrencyDaemon(true);
|
||||
await fetchCurrency();
|
||||
setSelectedCurrency(item);
|
||||
setPreferredFiatCurrency();
|
||||
|
|
|
@ -2,49 +2,56 @@ import assert from 'assert';
|
|||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
|
||||
import { FiatUnit } from '../../models/fiatUnit';
|
||||
import {
|
||||
EXCHANGE_RATES_STORAGE_KEY,
|
||||
LAST_UPDATED,
|
||||
PREFERRED_CURRENCY_STORAGE_KEY,
|
||||
getPreferredCurrency,
|
||||
initCurrencyDaemon,
|
||||
setPreferredCurrency,
|
||||
} from '../../blue_modules/currency';
|
||||
|
||||
jest.setTimeout(90 * 1000);
|
||||
|
||||
describe('currency', () => {
|
||||
it('fetches exchange rate and saves to AsyncStorage', async () => {
|
||||
const currency = require('../../blue_modules/currency');
|
||||
await currency.init();
|
||||
let cur = await AsyncStorage.getItem(currency.EXCHANGE_RATES);
|
||||
await initCurrencyDaemon();
|
||||
let cur = await AsyncStorage.getItem(EXCHANGE_RATES_STORAGE_KEY);
|
||||
cur = JSON.parse(cur);
|
||||
assert.ok(Number.isInteger(cur[currency.LAST_UPDATED]));
|
||||
assert.ok(cur[currency.LAST_UPDATED] > 0);
|
||||
assert.ok(Number.isInteger(cur[LAST_UPDATED]));
|
||||
assert.ok(cur[LAST_UPDATED] > 0);
|
||||
assert.ok(cur.BTC_USD > 0);
|
||||
|
||||
// now, setting other currency as default
|
||||
await AsyncStorage.setItem(currency.PREFERRED_CURRENCY, JSON.stringify(FiatUnit.JPY));
|
||||
await currency.init(true);
|
||||
cur = JSON.parse(await AsyncStorage.getItem(currency.EXCHANGE_RATES));
|
||||
await AsyncStorage.setItem(PREFERRED_CURRENCY_STORAGE_KEY, JSON.stringify(FiatUnit.JPY));
|
||||
await initCurrencyDaemon(true);
|
||||
cur = JSON.parse(await AsyncStorage.getItem(EXCHANGE_RATES_STORAGE_KEY));
|
||||
assert.ok(cur.BTC_JPY > 0);
|
||||
|
||||
// now setting with a proper setter
|
||||
await currency.setPrefferedCurrency(FiatUnit.EUR);
|
||||
await currency.init(true);
|
||||
const preferred = await currency.getPreferredCurrency();
|
||||
await setPreferredCurrency(FiatUnit.EUR);
|
||||
await initCurrencyDaemon(true);
|
||||
const preferred = await getPreferredCurrency();
|
||||
assert.strictEqual(preferred.endPointKey, 'EUR');
|
||||
cur = JSON.parse(await AsyncStorage.getItem(currency.EXCHANGE_RATES));
|
||||
cur = JSON.parse(await AsyncStorage.getItem(EXCHANGE_RATES_STORAGE_KEY));
|
||||
assert.ok(cur.BTC_EUR > 0);
|
||||
|
||||
// test Yadio rate source
|
||||
await currency.setPrefferedCurrency(FiatUnit.ARS);
|
||||
await currency.init(true);
|
||||
cur = JSON.parse(await AsyncStorage.getItem(currency.EXCHANGE_RATES));
|
||||
await setPreferredCurrency(FiatUnit.ARS);
|
||||
await initCurrencyDaemon(true);
|
||||
cur = JSON.parse(await AsyncStorage.getItem(EXCHANGE_RATES_STORAGE_KEY));
|
||||
assert.ok(cur.BTC_ARS > 0);
|
||||
|
||||
// test YadioConvert rate source
|
||||
await currency.setPrefferedCurrency(FiatUnit.LBP);
|
||||
await currency.init(true);
|
||||
cur = JSON.parse(await AsyncStorage.getItem(currency.EXCHANGE_RATES));
|
||||
await setPreferredCurrency(FiatUnit.LBP);
|
||||
await initCurrencyDaemon(true);
|
||||
cur = JSON.parse(await AsyncStorage.getItem(EXCHANGE_RATES_STORAGE_KEY));
|
||||
assert.ok(cur.BTC_LBP > 0);
|
||||
|
||||
// test Exir rate source
|
||||
await currency.setPrefferedCurrency(FiatUnit.IRT);
|
||||
await currency.init(true);
|
||||
cur = JSON.parse(await AsyncStorage.getItem(currency.EXCHANGE_RATES));
|
||||
await setPreferredCurrency(FiatUnit.IRT);
|
||||
await initCurrencyDaemon(true);
|
||||
cur = JSON.parse(await AsyncStorage.getItem(EXCHANGE_RATES_STORAGE_KEY));
|
||||
assert.ok(cur.BTC_IRT > 0);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,7 +4,7 @@ import { TABS } from '../../components/addresses/AddressTypeTabs';
|
|||
|
||||
jest.mock('../../blue_modules/currency', () => {
|
||||
return {
|
||||
init: jest.fn(),
|
||||
initCurrencyDaemon: jest.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
@ -1,36 +1,39 @@
|
|||
import {
|
||||
BTCToLocalCurrency,
|
||||
_setExchangeRate,
|
||||
_setPreferredFiatCurrency,
|
||||
satoshiToBTC,
|
||||
satoshiToLocalCurrency,
|
||||
} from '../../blue_modules/currency';
|
||||
import { FiatUnit } from '../../models/fiatUnit';
|
||||
const assert = require('assert');
|
||||
|
||||
describe('currency', () => {
|
||||
it('formats everything correctly', async () => {
|
||||
const currency = require('../../blue_modules/currency');
|
||||
currency._setExchangeRate('BTC_USD', 10000);
|
||||
_setExchangeRate('BTC_USD', 10000);
|
||||
|
||||
assert.strictEqual(currency.satoshiToLocalCurrency(1), '$0.0001');
|
||||
assert.strictEqual(currency.satoshiToLocalCurrency(-1), '-$0.0001');
|
||||
assert.strictEqual(currency.satoshiToLocalCurrency(123), '$0.01');
|
||||
assert.strictEqual(currency.satoshiToLocalCurrency(156), '$0.02');
|
||||
assert.strictEqual(currency.satoshiToLocalCurrency(51), '$0.01');
|
||||
assert.strictEqual(currency.satoshiToLocalCurrency(45), '$0.0045');
|
||||
assert.strictEqual(currency.satoshiToLocalCurrency(123456789), '$12,345.68');
|
||||
assert.strictEqual(satoshiToLocalCurrency(1), '$0.0001');
|
||||
assert.strictEqual(satoshiToLocalCurrency(-1), '-$0.0001');
|
||||
assert.strictEqual(satoshiToLocalCurrency(123), '$0.01');
|
||||
assert.strictEqual(satoshiToLocalCurrency(156), '$0.02');
|
||||
assert.strictEqual(satoshiToLocalCurrency(51), '$0.01');
|
||||
assert.strictEqual(satoshiToLocalCurrency(45), '$0.0045');
|
||||
assert.strictEqual(satoshiToLocalCurrency(123456789), '$12,345.68');
|
||||
|
||||
assert.strictEqual(currency.BTCToLocalCurrency(1), '$10,000.00');
|
||||
assert.strictEqual(currency.BTCToLocalCurrency(-1), '-$10,000.00');
|
||||
assert.strictEqual(currency.BTCToLocalCurrency(1.00000001), '$10,000.00');
|
||||
assert.strictEqual(currency.BTCToLocalCurrency(1.0000123), '$10,000.12');
|
||||
assert.strictEqual(currency.BTCToLocalCurrency(1.0000146), '$10,000.15');
|
||||
assert.strictEqual(BTCToLocalCurrency(1), '$10,000.00');
|
||||
assert.strictEqual(BTCToLocalCurrency(-1), '-$10,000.00');
|
||||
assert.strictEqual(BTCToLocalCurrency(1.00000001), '$10,000.00');
|
||||
assert.strictEqual(BTCToLocalCurrency(1.0000123), '$10,000.12');
|
||||
assert.strictEqual(BTCToLocalCurrency(1.0000146), '$10,000.15');
|
||||
|
||||
assert.strictEqual(currency.satoshiToBTC(1), '0.00000001');
|
||||
assert.strictEqual(currency.satoshiToBTC(-1), '-0.00000001');
|
||||
assert.strictEqual(currency.satoshiToBTC(100000000), '1');
|
||||
assert.strictEqual(currency.satoshiToBTC(123456789123456789), '1234567891.2345678'); // eslint-disable-line @typescript-eslint/no-loss-of-precision
|
||||
assert.strictEqual(satoshiToBTC(1), '0.00000001');
|
||||
assert.strictEqual(satoshiToBTC(-1), '-0.00000001');
|
||||
assert.strictEqual(satoshiToBTC(100000000), '1');
|
||||
assert.strictEqual(satoshiToBTC(123456789123456789), '1234567891.2345678'); // eslint-disable-line @typescript-eslint/no-loss-of-precision
|
||||
|
||||
currency._setPreferredFiatCurrency(FiatUnit.JPY);
|
||||
currency._setExchangeRate('BTC_JPY', 1043740.8614);
|
||||
_setPreferredFiatCurrency(FiatUnit.JPY);
|
||||
_setExchangeRate('BTC_JPY', 1043740.8614);
|
||||
|
||||
assert.ok(
|
||||
currency.satoshiToLocalCurrency(1) === '¥0.01' || currency.satoshiToLocalCurrency(1) === '¥0.01',
|
||||
'Unexpected: ' + currency.satoshiToLocalCurrency(1),
|
||||
);
|
||||
assert.ok(satoshiToLocalCurrency(1) === '¥0.01' || satoshiToLocalCurrency(1) === '¥0.01', 'Unexpected: ' + satoshiToLocalCurrency(1));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,7 +2,7 @@ import assert from 'assert';
|
|||
import { BitcoinUnit } from '../../models/bitcoinUnits';
|
||||
import { FiatUnit } from '../../models/fiatUnit';
|
||||
import { _leaveNumbersAndDots, formatBalanceWithoutSuffix, formatBalancePlain, formatBalance } from '../../loc';
|
||||
const currency = require('../../blue_modules/currency');
|
||||
import { _setExchangeRate, _setPreferredFiatCurrency, _setSkipUpdateExchangeRate } from '../../blue_modules/currency';
|
||||
|
||||
describe('Localization', () => {
|
||||
it('internal formatter', () => {
|
||||
|
@ -12,8 +12,8 @@ describe('Localization', () => {
|
|||
});
|
||||
|
||||
it('formatBalancePlain() && formatBalancePlain()', () => {
|
||||
currency._setExchangeRate('BTC_RUB', 660180.143);
|
||||
currency._setPreferredFiatCurrency(FiatUnit.RUB);
|
||||
_setExchangeRate('BTC_RUB', 660180.143);
|
||||
_setPreferredFiatCurrency(FiatUnit.RUB);
|
||||
let newInputValue = formatBalanceWithoutSuffix(152, BitcoinUnit.LOCAL_CURRENCY, false);
|
||||
assert.ok(newInputValue === 'RUB 1.00' || newInputValue === '1,00 ₽', 'Unexpected: ' + newInputValue);
|
||||
newInputValue = formatBalancePlain(152, BitcoinUnit.LOCAL_CURRENCY, false);
|
||||
|
@ -32,8 +32,8 @@ describe('Localization', () => {
|
|||
newInputValue = formatBalancePlain(76, BitcoinUnit.LOCAL_CURRENCY, false);
|
||||
assert.strictEqual(newInputValue, '0.50');
|
||||
|
||||
currency._setExchangeRate('BTC_USD', 10000);
|
||||
currency._setPreferredFiatCurrency(FiatUnit.USD);
|
||||
_setExchangeRate('BTC_USD', 10000);
|
||||
_setPreferredFiatCurrency(FiatUnit.USD);
|
||||
newInputValue = formatBalanceWithoutSuffix(16793829, BitcoinUnit.LOCAL_CURRENCY, false);
|
||||
assert.strictEqual(newInputValue, '$1,679.38');
|
||||
newInputValue = formatBalancePlain(16793829, BitcoinUnit.LOCAL_CURRENCY, false);
|
||||
|
@ -55,11 +55,11 @@ describe('Localization', () => {
|
|||
])(
|
||||
'can formatBalanceWithoutSuffix',
|
||||
async (balance, toUnit, withFormatting, expectedResult, shouldResetRate) => {
|
||||
currency._setExchangeRate('BTC_USD', 1);
|
||||
currency._setPreferredFiatCurrency(FiatUnit.USD);
|
||||
_setExchangeRate('BTC_USD', 1);
|
||||
_setPreferredFiatCurrency(FiatUnit.USD);
|
||||
if (shouldResetRate) {
|
||||
currency._setExchangeRate('BTC_USD', false);
|
||||
currency._setSkipUpdateExchangeRate();
|
||||
_setExchangeRate('BTC_USD', false);
|
||||
_setSkipUpdateExchangeRate();
|
||||
}
|
||||
const actualResult = formatBalanceWithoutSuffix(balance, toUnit, withFormatting);
|
||||
assert.strictEqual(actualResult, expectedResult);
|
||||
|
@ -74,8 +74,8 @@ describe('Localization', () => {
|
|||
])(
|
||||
'can formatBalance',
|
||||
async (balance, toUnit, withFormatting, expectedResult) => {
|
||||
currency._setExchangeRate('BTC_USD', 1);
|
||||
currency._setPreferredFiatCurrency(FiatUnit.USD);
|
||||
_setExchangeRate('BTC_USD', 1);
|
||||
_setPreferredFiatCurrency(FiatUnit.USD);
|
||||
const actualResult = formatBalance(balance, toUnit, withFormatting);
|
||||
assert.strictEqual(actualResult, expectedResult);
|
||||
},
|
||||
|
|
Loading…
Add table
Reference in a new issue