mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-03-03 12:06:21 +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 Privacy from './blue_modules/Privacy';
|
||||||
import triggerHapticFeedback, { HapticFeedbackTypes } from './blue_modules/hapticFeedback';
|
import triggerHapticFeedback, { HapticFeedbackTypes } from './blue_modules/hapticFeedback';
|
||||||
import MenuElements from './components/MenuElements';
|
import MenuElements from './components/MenuElements';
|
||||||
|
import { updateExchangeRate } from './blue_modules/currency';
|
||||||
const A = require('./blue_modules/analytics');
|
const A = require('./blue_modules/analytics');
|
||||||
const currency = require('./blue_modules/currency');
|
|
||||||
|
|
||||||
const eventEmitter = Platform.OS === 'ios' ? new NativeEventEmitter(NativeModules.EventEmitter) : undefined;
|
const eventEmitter = Platform.OS === 'ios' ? new NativeEventEmitter(NativeModules.EventEmitter) : undefined;
|
||||||
const { EventEmitter, SplashScreen } = NativeModules;
|
const { EventEmitter, SplashScreen } = NativeModules;
|
||||||
|
@ -203,7 +203,7 @@ const App = () => {
|
||||||
if (wallets.length === 0) return;
|
if (wallets.length === 0) return;
|
||||||
if ((appState.current.match(/background/) && nextAppState === 'active') || nextAppState === undefined) {
|
if ((appState.current.match(/background/) && nextAppState === 'active') || nextAppState === undefined) {
|
||||||
setTimeout(() => A(A.ENUM.APP_UNSUSPENDED), 2000);
|
setTimeout(() => A(A.ENUM.APP_UNSUSPENDED), 2000);
|
||||||
currency.updateExchangeRate();
|
updateExchangeRate();
|
||||||
const processed = await processPushNotifications();
|
const processed = await processPushNotifications();
|
||||||
if (processed) return;
|
if (processed) return;
|
||||||
const clipboard = await BlueClipboard().getClipboardContent();
|
const clipboard = await BlueClipboard().getClipboardContent();
|
||||||
|
|
|
@ -25,6 +25,7 @@ import {
|
||||||
} from './class/';
|
} from './class/';
|
||||||
import { randomBytes } from './class/rng';
|
import { randomBytes } from './class/rng';
|
||||||
import alert from './components/Alert';
|
import alert from './components/Alert';
|
||||||
|
import { initCurrencyDaemon } from './blue_modules/currency';
|
||||||
|
|
||||||
const encryption = require('./blue_modules/encryption');
|
const encryption = require('./blue_modules/encryption');
|
||||||
const Realm = require('realm');
|
const Realm = require('realm');
|
||||||
|
@ -32,7 +33,6 @@ const createHash = require('create-hash');
|
||||||
let usedBucketNum = false;
|
let usedBucketNum = false;
|
||||||
let savingInProgress = 0; // its both a flag and a counter of attempts to write to disk
|
let savingInProgress = 0; // its both a flag and a counter of attempts to write to disk
|
||||||
const prompt = require('./helpers/prompt');
|
const prompt = require('./helpers/prompt');
|
||||||
const currency = require('./blue_modules/currency');
|
|
||||||
const BlueElectrum = require('./blue_modules/BlueElectrum');
|
const BlueElectrum = require('./blue_modules/BlueElectrum');
|
||||||
BlueElectrum.connectMain();
|
BlueElectrum.connectMain();
|
||||||
|
|
||||||
|
@ -939,6 +939,6 @@ const startAndDecrypt = async retry => {
|
||||||
|
|
||||||
BlueApp.startAndDecrypt = startAndDecrypt;
|
BlueApp.startAndDecrypt = startAndDecrypt;
|
||||||
BlueApp.AppStorage = AppStorage;
|
BlueApp.AppStorage = AppStorage;
|
||||||
currency.init();
|
initCurrencyDaemon();
|
||||||
|
|
||||||
module.exports = BlueApp;
|
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 { LegacyWallet, WatchOnlyWallet } from '../class';
|
||||||
import alert from '../components/Alert';
|
import alert from '../components/Alert';
|
||||||
import triggerHapticFeedback, { HapticFeedbackTypes } from './hapticFeedback';
|
import triggerHapticFeedback, { HapticFeedbackTypes } from './hapticFeedback';
|
||||||
|
import { PREFERRED_CURRENCY_STORAGE_KEY } from './currency';
|
||||||
const BlueApp = require('../BlueApp');
|
const BlueApp = require('../BlueApp');
|
||||||
const BlueElectrum = require('./BlueElectrum');
|
const BlueElectrum = require('./BlueElectrum');
|
||||||
const currency = require('../blue_modules/currency');
|
|
||||||
const A = require('../blue_modules/analytics');
|
const A = require('../blue_modules/analytics');
|
||||||
|
|
||||||
const _lastTimeTriedToRefetchWallet = {}; // hashmap of timestamps we _started_ refetching some wallet
|
const _lastTimeTriedToRefetchWallet = {}; // hashmap of timestamps we _started_ refetching some wallet
|
||||||
|
@ -23,7 +23,7 @@ export const BlueStorageProvider = ({ children }) => {
|
||||||
const [walletsInitialized, setWalletsInitialized] = useState(false);
|
const [walletsInitialized, setWalletsInitialized] = useState(false);
|
||||||
const [preferredFiatCurrency, _setPreferredFiatCurrency] = useState(FiatUnit.USD);
|
const [preferredFiatCurrency, _setPreferredFiatCurrency] = useState(FiatUnit.USD);
|
||||||
const [language, _setLanguage] = useState();
|
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 getLanguageAsyncStorage = useAsyncStorage(LOC_STORAGE_KEY).getItem;
|
||||||
const [isHandOffUseEnabled, setIsHandOffUseEnabled] = useState(false);
|
const [isHandOffUseEnabled, setIsHandOffUseEnabled] = useState(false);
|
||||||
const [isElectrumDisabled, setIsElectrumDisabled] = useState(true);
|
const [isElectrumDisabled, setIsElectrumDisabled] = useState(true);
|
||||||
|
|
|
@ -10,7 +10,14 @@ import loc, { formatBalanceWithoutSuffix, formatBalancePlain, removeTrailingZero
|
||||||
import { BlueText } from '../BlueComponents';
|
import { BlueText } from '../BlueComponents';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { useTheme } from './themes';
|
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'));
|
dayjs.extend(require('dayjs/plugin/localizedFormat'));
|
||||||
|
|
||||||
class AmountInput extends Component {
|
class AmountInput extends Component {
|
||||||
|
@ -57,13 +64,12 @@ class AmountInput extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
currency
|
mostRecentFetchedRate()
|
||||||
.mostRecentFetchedRate()
|
.then(mostRecentFetchedRateValue => {
|
||||||
.then(mostRecentFetchedRate => {
|
this.setState({ mostRecentFetchedRate: mostRecentFetchedRateValue });
|
||||||
this.setState({ mostRecentFetchedRate });
|
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.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;
|
sats = amount;
|
||||||
break;
|
break;
|
||||||
case BitcoinUnit.LOCAL_CURRENCY:
|
case BitcoinUnit.LOCAL_CURRENCY:
|
||||||
sats = new BigNumber(currency.fiatToBTC(amount)).multipliedBy(100000000).toString();
|
sats = new BigNumber(fiatToBTC(amount)).multipliedBy(100000000).toString();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (previousUnit === BitcoinUnit.LOCAL_CURRENCY && AmountInput.conversionCache[amount + previousUnit]) {
|
if (previousUnit === BitcoinUnit.LOCAL_CURRENCY && AmountInput.conversionCache[amount + previousUnit]) {
|
||||||
|
@ -191,14 +197,14 @@ class AmountInput extends Component {
|
||||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||||
this.setState({ isRateBeingUpdated: true }, async () => {
|
this.setState({ isRateBeingUpdated: true }, async () => {
|
||||||
try {
|
try {
|
||||||
await currency.updateExchangeRate();
|
await updateExchangeRate();
|
||||||
currency.mostRecentFetchedRate().then(mostRecentFetchedRate => {
|
mostRecentFetchedRate().then(mostRecentFetchedRateValue => {
|
||||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||||
this.setState({ mostRecentFetchedRate });
|
this.setState({ mostRecentFetchedRate: mostRecentFetchedRateValue });
|
||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
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);
|
secondaryDisplayCurrency = formatBalanceWithoutSuffix((isNaN(amount) ? 0 : amount).toString(), BitcoinUnit.LOCAL_CURRENCY, false);
|
||||||
break;
|
break;
|
||||||
case BitcoinUnit.LOCAL_CURRENCY:
|
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]) {
|
if (AmountInput.conversionCache[isNaN(amount) ? 0 : amount + BitcoinUnit.LOCAL_CURRENCY]) {
|
||||||
// cache hit! we reuse old value that supposedly doesn't have rounding errors
|
// cache hit! we reuse old value that supposedly doesn't have rounding errors
|
||||||
const sats = AmountInput.conversionCache[isNaN(amount) ? 0 : amount + BitcoinUnit.LOCAL_CURRENCY];
|
const sats = AmountInput.conversionCache[isNaN(amount) ? 0 : amount + BitcoinUnit.LOCAL_CURRENCY];
|
||||||
secondaryDisplayCurrency = currency.satoshiToBTC(sats);
|
secondaryDisplayCurrency = satoshiToBTC(sats);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -251,7 +257,7 @@ class AmountInput extends Component {
|
||||||
<View style={styles.flex}>
|
<View style={styles.flex}>
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
{unit === BitcoinUnit.LOCAL_CURRENCY && amount !== BitcoinUnit.MAX && (
|
{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 ? (
|
{amount !== BitcoinUnit.MAX ? (
|
||||||
<TextInput
|
<TextInput
|
||||||
|
|
|
@ -65,7 +65,10 @@ const TransactionsNavigationHeader: React.FC<TransactionsNavigationHeaderProps>
|
||||||
}, [wallet, verifyIfWalletAllowsOnchainAddress]);
|
}, [wallet, verifyIfWalletAllowsOnchainAddress]);
|
||||||
|
|
||||||
const handleCopyPress = () => {
|
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) => {
|
const updateWalletVisibility = (w: AbstractWallet, newHideBalance: boolean) => {
|
||||||
|
@ -134,8 +137,8 @@ const TransactionsNavigationHeader: React.FC<TransactionsNavigationHeaderProps>
|
||||||
const balance = useMemo(() => {
|
const balance = useMemo(() => {
|
||||||
const hideBalance = wallet.hideBalance;
|
const hideBalance = wallet.hideBalance;
|
||||||
const balanceUnit = wallet.getPreferredBalanceUnit();
|
const balanceUnit = wallet.getPreferredBalanceUnit();
|
||||||
const balanceFormatted = formatBalance(wallet.getBalance(), balanceUnit, true).toString();
|
const balanceFormatted = formatBalance(wallet.getBalance(), balanceUnit, true);
|
||||||
return !hideBalance && balanceFormatted;
|
return !hideBalance && balanceFormatted?.toString();
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [wallet.hideBalance, wallet.getPreferredBalanceUnit()]);
|
}, [wallet.hideBalance, wallet.getPreferredBalanceUnit()]);
|
||||||
|
|
||||||
|
@ -211,6 +214,7 @@ const TransactionsNavigationHeader: React.FC<TransactionsNavigationHeaderProps>
|
||||||
) : (
|
) : (
|
||||||
<Text
|
<Text
|
||||||
testID="WalletBalance"
|
testID="WalletBalance"
|
||||||
|
// @ts-ignore: Ugh
|
||||||
key={balance} // force component recreation on balance change. To fix right-to-left languages, like Farsi
|
key={balance} // force component recreation on balance change. To fix right-to-left languages, like Farsi
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
adjustsFontSizeToFit
|
adjustsFontSizeToFit
|
||||||
|
|
|
@ -9,7 +9,7 @@ import BigNumber from 'bignumber.js';
|
||||||
import { BitcoinUnit } from '../models/bitcoinUnits';
|
import { BitcoinUnit } from '../models/bitcoinUnits';
|
||||||
import { AvailableLanguages } from './languages';
|
import { AvailableLanguages } from './languages';
|
||||||
import { I18nManager } from 'react-native';
|
import { I18nManager } from 'react-native';
|
||||||
const currency = require('../blue_modules/currency');
|
import { satoshiToLocalCurrency } from '../blue_modules/currency';
|
||||||
|
|
||||||
export const STORAGE_KEY = 'lang';
|
export const STORAGE_KEY = 'lang';
|
||||||
|
|
||||||
|
@ -310,7 +310,7 @@ export function formatBalance(balance: number, toUnit: string, withFormatting =
|
||||||
} else if (toUnit === BitcoinUnit.SATS) {
|
} else if (toUnit === BitcoinUnit.SATS) {
|
||||||
return (withFormatting ? new Intl.NumberFormat().format(balance).toString() : String(balance)) + ' ' + loc.units[BitcoinUnit.SATS];
|
return (withFormatting ? new Intl.NumberFormat().format(balance).toString() : String(balance)) + ' ' + loc.units[BitcoinUnit.SATS];
|
||||||
} else if (toUnit === BitcoinUnit.LOCAL_CURRENCY) {
|
} 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) {
|
} else if (toUnit === BitcoinUnit.SATS) {
|
||||||
return withFormatting ? new Intl.NumberFormat().format(balance).toString() : String(balance);
|
return withFormatting ? new Intl.NumberFormat().format(balance).toString() : String(balance);
|
||||||
} else if (toUnit === BitcoinUnit.LOCAL_CURRENCY) {
|
} else if (toUnit === BitcoinUnit.LOCAL_CURRENCY) {
|
||||||
return currency.satoshiToLocalCurrency(balance);
|
return satoshiToLocalCurrency(balance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return balance.toString();
|
return balance.toString();
|
||||||
|
@ -349,7 +349,7 @@ export function formatBalanceWithoutSuffix(balance = 0, toUnit: string, withForm
|
||||||
export function formatBalancePlain(balance = 0, toUnit: string, withFormatting = false) {
|
export function formatBalancePlain(balance = 0, toUnit: string, withFormatting = false) {
|
||||||
const newInputValue = formatBalanceWithoutSuffix(balance, toUnit, withFormatting);
|
const newInputValue = formatBalanceWithoutSuffix(balance, toUnit, withFormatting);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||||
return _leaveNumbersAndDots(newInputValue);
|
return _leaveNumbersAndDots(newInputValue.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
export function _leaveNumbersAndDots(newInputValue: string) {
|
export function _leaveNumbersAndDots(newInputValue: string) {
|
||||||
|
|
|
@ -18,7 +18,7 @@ import { useTheme } from '../../components/themes';
|
||||||
import Button from '../../components/Button';
|
import Button from '../../components/Button';
|
||||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||||
import SafeArea from '../../components/SafeArea';
|
import SafeArea from '../../components/SafeArea';
|
||||||
const currency = require('../../blue_modules/currency');
|
import { btcToSatoshi, fiatToBTC } from '../../blue_modules/currency';
|
||||||
|
|
||||||
type LdkOpenChannelProps = RouteProp<
|
type LdkOpenChannelProps = RouteProp<
|
||||||
{
|
{
|
||||||
|
@ -223,11 +223,11 @@ const LdkOpenChannel = (props: any) => {
|
||||||
amountSats = parseInt(fundingAmount.amount, 10);
|
amountSats = parseInt(fundingAmount.amount, 10);
|
||||||
break;
|
break;
|
||||||
case BitcoinUnit.BTC:
|
case BitcoinUnit.BTC:
|
||||||
amountSats = currency.btcToSatoshi(fundingAmount.amount);
|
amountSats = btcToSatoshi(fundingAmount.amount);
|
||||||
break;
|
break;
|
||||||
case BitcoinUnit.LOCAL_CURRENCY:
|
case BitcoinUnit.LOCAL_CURRENCY:
|
||||||
// also accounting for cached fiat->sat conversion to avoid rounding error
|
// also accounting for cached fiat->sat conversion to avoid rounding error
|
||||||
amountSats = currency.btcToSatoshi(currency.fiatToBTC(fundingAmount.amount));
|
amountSats = btcToSatoshi(fiatToBTC(fundingAmount.amount));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
setFundingAmount({ amount: fundingAmount.amount, amountSats });
|
setFundingAmount({ amount: fundingAmount.amount, amountSats });
|
||||||
|
@ -237,10 +237,10 @@ const LdkOpenChannel = (props: any) => {
|
||||||
let amountSats = fundingAmount.amountSats;
|
let amountSats = fundingAmount.amountSats;
|
||||||
switch (unit) {
|
switch (unit) {
|
||||||
case BitcoinUnit.BTC:
|
case BitcoinUnit.BTC:
|
||||||
amountSats = currency.btcToSatoshi(text);
|
amountSats = btcToSatoshi(text);
|
||||||
break;
|
break;
|
||||||
case BitcoinUnit.LOCAL_CURRENCY:
|
case BitcoinUnit.LOCAL_CURRENCY:
|
||||||
amountSats = currency.btcToSatoshi(currency.fiatToBTC(text));
|
amountSats = btcToSatoshi(fiatToBTC(Number(text)));
|
||||||
break;
|
break;
|
||||||
case BitcoinUnit.SATS:
|
case BitcoinUnit.SATS:
|
||||||
amountSats = parseInt(text, 10);
|
amountSats = parseInt(text, 10);
|
||||||
|
|
|
@ -31,7 +31,7 @@ import { requestCameraAuthorization } from '../../helpers/scan-qr';
|
||||||
import { useTheme } from '../../components/themes';
|
import { useTheme } from '../../components/themes';
|
||||||
import Button from '../../components/Button';
|
import Button from '../../components/Button';
|
||||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||||
const currency = require('../../blue_modules/currency');
|
import { btcToSatoshi, fiatToBTC, satoshiToBTC } from '../../blue_modules/currency';
|
||||||
|
|
||||||
const LNDCreateInvoice = () => {
|
const LNDCreateInvoice = () => {
|
||||||
const { wallets, saveToDisk, setSelectedWalletID } = useContext(BlueStorageContext);
|
const { wallets, saveToDisk, setSelectedWalletID } = useContext(BlueStorageContext);
|
||||||
|
@ -156,11 +156,11 @@ const LNDCreateInvoice = () => {
|
||||||
invoiceAmount = parseInt(invoiceAmount, 10); // basically nop
|
invoiceAmount = parseInt(invoiceAmount, 10); // basically nop
|
||||||
break;
|
break;
|
||||||
case BitcoinUnit.BTC:
|
case BitcoinUnit.BTC:
|
||||||
invoiceAmount = currency.btcToSatoshi(invoiceAmount);
|
invoiceAmount = btcToSatoshi(invoiceAmount);
|
||||||
break;
|
break;
|
||||||
case BitcoinUnit.LOCAL_CURRENCY:
|
case BitcoinUnit.LOCAL_CURRENCY:
|
||||||
// trying to fetch cached sat equivalent for this fiat amount
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,7 +285,7 @@ const LNDCreateInvoice = () => {
|
||||||
// nop
|
// nop
|
||||||
break;
|
break;
|
||||||
case BitcoinUnit.BTC:
|
case BitcoinUnit.BTC:
|
||||||
newAmount = currency.satoshiToBTC(newAmount);
|
newAmount = satoshiToBTC(newAmount);
|
||||||
break;
|
break;
|
||||||
case BitcoinUnit.LOCAL_CURRENCY:
|
case BitcoinUnit.LOCAL_CURRENCY:
|
||||||
newAmount = formatBalancePlain(newAmount, BitcoinUnit.LOCAL_CURRENCY);
|
newAmount = formatBalancePlain(newAmount, BitcoinUnit.LOCAL_CURRENCY);
|
||||||
|
|
|
@ -17,8 +17,8 @@ import { useTheme } from '../../components/themes';
|
||||||
import Button from '../../components/Button';
|
import Button from '../../components/Button';
|
||||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||||
import SafeArea from '../../components/SafeArea';
|
import SafeArea from '../../components/SafeArea';
|
||||||
|
import { btcToSatoshi, fiatToBTC, satoshiToBTC, satoshiToLocalCurrency } from '../../blue_modules/currency';
|
||||||
const prompt = require('../../helpers/prompt');
|
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
|
* 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) {
|
switch (unit) {
|
||||||
case BitcoinUnit.BTC:
|
case BitcoinUnit.BTC:
|
||||||
newAmount = currency.satoshiToBTC(newAmount);
|
newAmount = satoshiToBTC(newAmount);
|
||||||
break;
|
break;
|
||||||
case BitcoinUnit.LOCAL_CURRENCY:
|
case BitcoinUnit.LOCAL_CURRENCY:
|
||||||
newAmount = currency.satoshiToLocalCurrency(newAmount, false);
|
newAmount = satoshiToLocalCurrency(newAmount, false);
|
||||||
_cacheFiatToSat[newAmount] = originalSatAmount;
|
_cacheFiatToSat[newAmount] = originalSatAmount;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -120,13 +120,13 @@ const LnurlPay = () => {
|
||||||
amountSats = parseInt(amountSats, 10); // nop
|
amountSats = parseInt(amountSats, 10); // nop
|
||||||
break;
|
break;
|
||||||
case BitcoinUnit.BTC:
|
case BitcoinUnit.BTC:
|
||||||
amountSats = currency.btcToSatoshi(amountSats);
|
amountSats = btcToSatoshi(amountSats);
|
||||||
break;
|
break;
|
||||||
case BitcoinUnit.LOCAL_CURRENCY:
|
case BitcoinUnit.LOCAL_CURRENCY:
|
||||||
if (_cacheFiatToSat[amount]) {
|
if (_cacheFiatToSat[amount]) {
|
||||||
amountSats = _cacheFiatToSat[amount];
|
amountSats = _cacheFiatToSat[amount];
|
||||||
} else {
|
} else {
|
||||||
amountSats = currency.btcToSatoshi(currency.fiatToBTC(amountSats));
|
amountSats = btcToSatoshi(fiatToBTC(amountSats));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ import { useTheme } from '../../components/themes';
|
||||||
import Button from '../../components/Button';
|
import Button from '../../components/Button';
|
||||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||||
import SafeArea from '../../components/SafeArea';
|
import SafeArea from '../../components/SafeArea';
|
||||||
const currency = require('../../blue_modules/currency');
|
import { btcToSatoshi, fiatToBTC } from '../../blue_modules/currency';
|
||||||
|
|
||||||
const ScanLndInvoice = () => {
|
const ScanLndInvoice = () => {
|
||||||
const { wallets, fetchAndSaveWalletTransactions } = useContext(BlueStorageContext);
|
const { wallets, fetchAndSaveWalletTransactions } = useContext(BlueStorageContext);
|
||||||
|
@ -182,10 +182,10 @@ const ScanLndInvoice = () => {
|
||||||
amountSats = parseInt(amountSats, 10); // nop
|
amountSats = parseInt(amountSats, 10); // nop
|
||||||
break;
|
break;
|
||||||
case BitcoinUnit.BTC:
|
case BitcoinUnit.BTC:
|
||||||
amountSats = currency.btcToSatoshi(amountSats);
|
amountSats = btcToSatoshi(amountSats);
|
||||||
break;
|
break;
|
||||||
case BitcoinUnit.LOCAL_CURRENCY:
|
case BitcoinUnit.LOCAL_CURRENCY:
|
||||||
amountSats = currency.btcToSatoshi(currency.fiatToBTC(amountSats));
|
amountSats = btcToSatoshi(fiatToBTC(amountSats));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
|
@ -38,7 +38,7 @@ import { SuccessView } from '../send/success';
|
||||||
import { useTheme } from '../../components/themes';
|
import { useTheme } from '../../components/themes';
|
||||||
import Button from '../../components/Button';
|
import Button from '../../components/Button';
|
||||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||||
const currency = require('../../blue_modules/currency');
|
import { fiatToBTC, satoshiToBTC } from '../../blue_modules/currency';
|
||||||
|
|
||||||
const ReceiveDetails = () => {
|
const ReceiveDetails = () => {
|
||||||
const { walletID, address } = useRoute().params;
|
const { walletID, address } = useRoute().params;
|
||||||
|
@ -385,14 +385,14 @@ const ReceiveDetails = () => {
|
||||||
// nop
|
// nop
|
||||||
break;
|
break;
|
||||||
case BitcoinUnit.SATS:
|
case BitcoinUnit.SATS:
|
||||||
amount = currency.satoshiToBTC(customAmount);
|
amount = satoshiToBTC(customAmount);
|
||||||
break;
|
break;
|
||||||
case BitcoinUnit.LOCAL_CURRENCY:
|
case BitcoinUnit.LOCAL_CURRENCY:
|
||||||
if (AmountInput.conversionCache[amount + BitcoinUnit.LOCAL_CURRENCY]) {
|
if (AmountInput.conversionCache[amount + BitcoinUnit.LOCAL_CURRENCY]) {
|
||||||
// cache hit! we reuse old value that supposedly doesnt have rounding errors
|
// 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 {
|
} else {
|
||||||
amount = currency.fiatToBTC(customAmount);
|
amount = fiatToBTC(customAmount);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -447,9 +447,9 @@ const ReceiveDetails = () => {
|
||||||
case BitcoinUnit.BTC:
|
case BitcoinUnit.BTC:
|
||||||
return customAmount + ' BTC';
|
return customAmount + ' BTC';
|
||||||
case BitcoinUnit.SATS:
|
case BitcoinUnit.SATS:
|
||||||
return currency.satoshiToBTC(customAmount) + ' BTC';
|
return satoshiToBTC(customAmount) + ' BTC';
|
||||||
case BitcoinUnit.LOCAL_CURRENCY:
|
case BitcoinUnit.LOCAL_CURRENCY:
|
||||||
return currency.fiatToBTC(customAmount) + ' BTC';
|
return fiatToBTC(customAmount) + ' BTC';
|
||||||
}
|
}
|
||||||
return customAmount + ' ' + customUnit;
|
return customAmount + ' ' + customUnit;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -17,7 +17,7 @@ import { useTheme } from '../../components/themes';
|
||||||
import Button from '../../components/Button';
|
import Button from '../../components/Button';
|
||||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||||
import SafeArea from '../../components/SafeArea';
|
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 BlueElectrum = require('../../blue_modules/BlueElectrum');
|
||||||
const Bignumber = require('bignumber.js');
|
const Bignumber = require('bignumber.js');
|
||||||
const bitcoin = require('bitcoinjs-lib');
|
const bitcoin = require('bitcoinjs-lib');
|
||||||
|
@ -182,11 +182,11 @@ const Confirm = () => {
|
||||||
<>
|
<>
|
||||||
<View style={styles.valueWrap}>
|
<View style={styles.valueWrap}>
|
||||||
<Text testID="TransactionValue" style={[styles.valueValue, stylesHook.valueValue]}>
|
<Text testID="TransactionValue" style={[styles.valueValue, stylesHook.valueValue]}>
|
||||||
{currency.satoshiToBTC(item.value)}
|
{satoshiToBTC(item.value)}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={[styles.valueUnit, stylesHook.valueValue]}>{' ' + loc.units[BitcoinUnit.BTC]}</Text>
|
<Text style={[styles.valueUnit, stylesHook.valueValue]}>{' ' + loc.units[BitcoinUnit.BTC]}</Text>
|
||||||
</View>
|
</View>
|
||||||
<Text style={[styles.transactionAmountFiat, stylesHook.transactionAmountFiat]}>{currency.satoshiToLocalCurrency(item.value)}</Text>
|
<Text style={[styles.transactionAmountFiat, stylesHook.transactionAmountFiat]}>{satoshiToLocalCurrency(item.value)}</Text>
|
||||||
<BlueCard>
|
<BlueCard>
|
||||||
<Text style={[styles.transactionDetailsTitle, stylesHook.transactionDetailsTitle]}>{loc.send.create_to}</Text>
|
<Text style={[styles.transactionDetailsTitle, stylesHook.transactionDetailsTitle]}>{loc.send.create_to}</Text>
|
||||||
<Text testID="TransactionAddress" style={[styles.transactionDetailsSubtitle, stylesHook.transactionDetailsSubtitle]}>
|
<Text testID="TransactionAddress" style={[styles.transactionDetailsSubtitle, stylesHook.transactionDetailsSubtitle]}>
|
||||||
|
@ -233,7 +233,7 @@ const Confirm = () => {
|
||||||
<View style={styles.cardBottom}>
|
<View style={styles.cardBottom}>
|
||||||
<BlueCard>
|
<BlueCard>
|
||||||
<Text style={styles.cardText} testID="TransactionFee">
|
<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>
|
</Text>
|
||||||
{isLoading ? <ActivityIndicator /> : <Button disabled={isElectrumDisabled} onPress={send} title={loc.send.confirm_sendNow} />}
|
{isLoading ? <ActivityIndicator /> : <Button disabled={isElectrumDisabled} onPress={send} title={loc.send.confirm_sendNow} />}
|
||||||
</BlueCard>
|
</BlueCard>
|
||||||
|
|
|
@ -17,8 +17,8 @@ import { useNavigation, useRoute } from '@react-navigation/native';
|
||||||
import alert from '../../components/Alert';
|
import alert from '../../components/Alert';
|
||||||
import { PERMISSIONS, RESULTS, request } from 'react-native-permissions';
|
import { PERMISSIONS, RESULTS, request } from 'react-native-permissions';
|
||||||
import { useTheme } from '../../components/themes';
|
import { useTheme } from '../../components/themes';
|
||||||
|
import { satoshiToBTC } from '../../blue_modules/currency';
|
||||||
const bitcoin = require('bitcoinjs-lib');
|
const bitcoin = require('bitcoinjs-lib');
|
||||||
const currency = require('../../blue_modules/currency');
|
|
||||||
|
|
||||||
const SendCreate = () => {
|
const SendCreate = () => {
|
||||||
const { fee, recipients, memo = '', satoshiPerByte, psbt, showAnimatedQr, tx } = useRoute().params;
|
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.transactionDetailsSubtitle, styleHooks.transactionDetailsSubtitle]}>{item.address}</Text>
|
||||||
<Text style={[styles.transactionDetailsTitle, styleHooks.transactionDetailsTitle]}>{loc.send.create_amount}</Text>
|
<Text style={[styles.transactionDetailsTitle, styleHooks.transactionDetailsTitle]}>{loc.send.create_amount}</Text>
|
||||||
<Text style={[styles.transactionDetailsSubtitle, styleHooks.transactionDetailsSubtitle]}>
|
<Text style={[styles.transactionDetailsSubtitle, styleHooks.transactionDetailsSubtitle]}>
|
||||||
{currency.satoshiToBTC(item.value)} {BitcoinUnit.BTC}
|
{satoshiToBTC(item.value)} {BitcoinUnit.BTC}
|
||||||
</Text>
|
</Text>
|
||||||
{recipients.length > 1 && (
|
{recipients.length > 1 && (
|
||||||
<BlueText style={styles.itemOf}>{loc.formatString(loc._.of, { number: index + 1, total: recipients.length })}</BlueText>
|
<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 Button from '../../components/Button';
|
||||||
import ListItem from '../../components/ListItem';
|
import ListItem from '../../components/ListItem';
|
||||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
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 prompt = require('../../helpers/prompt');
|
||||||
const fs = require('../../blue_modules/fs');
|
const fs = require('../../blue_modules/fs');
|
||||||
const btcAddressRx = /^[a-zA-Z0-9]{26,35}$/;
|
const btcAddressRx = /^[a-zA-Z0-9]{26,35}$/;
|
||||||
|
@ -145,12 +145,12 @@ const SendDetails = () => {
|
||||||
currentAddress.address = address;
|
currentAddress.address = address;
|
||||||
if (Number(amount) > 0) {
|
if (Number(amount) > 0) {
|
||||||
currentAddress.amount = amount;
|
currentAddress.amount = amount;
|
||||||
currentAddress.amountSats = currency.btcToSatoshi(amount);
|
currentAddress.amountSats = btcToSatoshi(amount);
|
||||||
}
|
}
|
||||||
addrs[scrollIndex.current] = currentAddress;
|
addrs[scrollIndex.current] = currentAddress;
|
||||||
return [...addrs];
|
return [...addrs];
|
||||||
} else {
|
} 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) {
|
if (value > 0) {
|
||||||
targets.push({ address: transaction.address, value });
|
targets.push({ address: transaction.address, value });
|
||||||
} else if (transaction.amount) {
|
} else if (transaction.amount) {
|
||||||
if (currency.btcToSatoshi(transaction.amount) > 0) {
|
if (btcToSatoshi(transaction.amount) > 0) {
|
||||||
targets.push({ address: transaction.address, value: currency.btcToSatoshi(transaction.amount) });
|
targets.push({ address: transaction.address, value: btcToSatoshi(transaction.amount) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -517,8 +517,8 @@ const SendDetails = () => {
|
||||||
if (value > 0) {
|
if (value > 0) {
|
||||||
targets.push({ address: transaction.address, value });
|
targets.push({ address: transaction.address, value });
|
||||||
} else if (transaction.amount) {
|
} else if (transaction.amount) {
|
||||||
if (currency.btcToSatoshi(transaction.amount) > 0) {
|
if (btcToSatoshi(transaction.amount) > 0) {
|
||||||
targets.push({ address: transaction.address, value: currency.btcToSatoshi(transaction.amount) });
|
targets.push({ address: transaction.address, value: btcToSatoshi(transaction.amount) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1329,11 +1329,11 @@ const SendDetails = () => {
|
||||||
addr.amountSats = parseInt(addr.amount, 10);
|
addr.amountSats = parseInt(addr.amount, 10);
|
||||||
break;
|
break;
|
||||||
case BitcoinUnit.BTC:
|
case BitcoinUnit.BTC:
|
||||||
addr.amountSats = currency.btcToSatoshi(addr.amount);
|
addr.amountSats = btcToSatoshi(addr.amount);
|
||||||
break;
|
break;
|
||||||
case BitcoinUnit.LOCAL_CURRENCY:
|
case BitcoinUnit.LOCAL_CURRENCY:
|
||||||
// also accounting for cached fiat->sat conversion to avoid rounding error
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1350,10 +1350,10 @@ const SendDetails = () => {
|
||||||
item.amount = text;
|
item.amount = text;
|
||||||
switch (units[index] || amountUnit) {
|
switch (units[index] || amountUnit) {
|
||||||
case BitcoinUnit.BTC:
|
case BitcoinUnit.BTC:
|
||||||
item.amountSats = currency.btcToSatoshi(item.amount);
|
item.amountSats = btcToSatoshi(item.amount);
|
||||||
break;
|
break;
|
||||||
case BitcoinUnit.LOCAL_CURRENCY:
|
case BitcoinUnit.LOCAL_CURRENCY:
|
||||||
item.amountSats = currency.btcToSatoshi(currency.fiatToBTC(item.amount));
|
item.amountSats = btcToSatoshi(fiatToBTC(item.amount));
|
||||||
break;
|
break;
|
||||||
case BitcoinUnit.SATS:
|
case BitcoinUnit.SATS:
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -12,9 +12,9 @@ import alert from '../../components/Alert';
|
||||||
import { useTheme } from '../../components/themes';
|
import { useTheme } from '../../components/themes';
|
||||||
import Button from '../../components/Button';
|
import Button from '../../components/Button';
|
||||||
import SafeArea from '../../components/SafeArea';
|
import SafeArea from '../../components/SafeArea';
|
||||||
|
import { satoshiToBTC, satoshiToLocalCurrency } from '../../blue_modules/currency';
|
||||||
const bitcoin = require('bitcoinjs-lib');
|
const bitcoin = require('bitcoinjs-lib');
|
||||||
const BigNumber = require('bignumber.js');
|
const BigNumber = require('bignumber.js');
|
||||||
const currency = require('../../blue_modules/currency');
|
|
||||||
|
|
||||||
const shortenAddress = addr => {
|
const shortenAddress = addr => {
|
||||||
return addr.substr(0, Math.floor(addr.length / 2) - 1) + '\n' + addr.substr(Math.floor(addr.length / 2) - 1, addr.length);
|
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(', '));
|
destination = shortenAddress(destination.join(', '));
|
||||||
const totalBtc = new BigNumber(totalSat).dividedBy(100000000).toNumber();
|
const totalBtc = new BigNumber(totalSat).dividedBy(100000000).toNumber();
|
||||||
const totalFiat = currency.satoshiToLocalCurrency(totalSat);
|
const totalFiat = satoshiToLocalCurrency(totalSat);
|
||||||
|
|
||||||
const getFee = () => {
|
const getFee = () => {
|
||||||
return wallet.calculateFeeFromPsbt(psbt);
|
return wallet.calculateFeeFromPsbt(psbt);
|
||||||
|
@ -252,9 +252,9 @@ const PsbtMultisig = () => {
|
||||||
<View style={styles.bottomWrapper}>
|
<View style={styles.bottomWrapper}>
|
||||||
<View style={styles.bottomFeesWrapper}>
|
<View style={styles.bottomFeesWrapper}>
|
||||||
<BlueText style={[styles.feeFiatText, stylesHook.feeFiatText]}>
|
<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>
|
||||||
<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>
|
</View>
|
||||||
<View style={styles.marginConfirmButton}>
|
<View style={styles.marginConfirmButton}>
|
||||||
|
|
|
@ -10,16 +10,17 @@ import dayjs from 'dayjs';
|
||||||
import alert from '../../components/Alert';
|
import alert from '../../components/Alert';
|
||||||
import { useTheme } from '../../components/themes';
|
import { useTheme } from '../../components/themes';
|
||||||
import ListItem from '../../components/ListItem';
|
import ListItem from '../../components/ListItem';
|
||||||
|
import {
|
||||||
|
CurrencyRate,
|
||||||
|
getPreferredCurrency,
|
||||||
|
initCurrencyDaemon,
|
||||||
|
mostRecentFetchedRate,
|
||||||
|
setPreferredCurrency,
|
||||||
|
} from '../../blue_modules/currency';
|
||||||
dayjs.extend(require('dayjs/plugin/calendar'));
|
dayjs.extend(require('dayjs/plugin/calendar'));
|
||||||
const currency = require('../../blue_modules/currency');
|
|
||||||
|
|
||||||
const ITEM_HEIGHT = 50;
|
const ITEM_HEIGHT = 50;
|
||||||
|
|
||||||
interface CurrencyRate {
|
|
||||||
LastUpdated: Date | null;
|
|
||||||
Rate: number | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Currency: React.FC = () => {
|
const Currency: React.FC = () => {
|
||||||
const { setPreferredFiatCurrency } = useContext(BlueStorageContext);
|
const { setPreferredFiatCurrency } = useContext(BlueStorageContext);
|
||||||
const [isSavingNewPreferredCurrency, setIsSavingNewPreferredCurrency] = useState(false);
|
const [isSavingNewPreferredCurrency, setIsSavingNewPreferredCurrency] = useState(false);
|
||||||
|
@ -39,18 +40,18 @@ const Currency: React.FC = () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const fetchCurrency = async () => {
|
const fetchCurrency = async () => {
|
||||||
let preferredCurrency = FiatUnit.USD;
|
let preferredCurrency;
|
||||||
try {
|
try {
|
||||||
preferredCurrency = await currency.getPreferredCurrency();
|
preferredCurrency = await getPreferredCurrency();
|
||||||
if (preferredCurrency === null) {
|
if (preferredCurrency === null) {
|
||||||
throw Error();
|
throw Error();
|
||||||
}
|
}
|
||||||
setSelectedCurrency(preferredCurrency);
|
setSelectedCurrency(preferredCurrency);
|
||||||
} catch (_error) {
|
} catch (_error) {
|
||||||
setSelectedCurrency(preferredCurrency);
|
setSelectedCurrency(FiatUnit.USD);
|
||||||
}
|
}
|
||||||
const mostRecentFetchedRate = await currency.mostRecentFetchedRate();
|
const mostRecentFetchedRateValue = await mostRecentFetchedRate();
|
||||||
setCurrencyRate(mostRecentFetchedRate);
|
setCurrencyRate(mostRecentFetchedRateValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
|
@ -78,8 +79,8 @@ const Currency: React.FC = () => {
|
||||||
setIsSavingNewPreferredCurrency(true);
|
setIsSavingNewPreferredCurrency(true);
|
||||||
try {
|
try {
|
||||||
await getFiatRate(item.endPointKey);
|
await getFiatRate(item.endPointKey);
|
||||||
await currency.setPrefferedCurrency(item);
|
await setPreferredCurrency(item);
|
||||||
await currency.init(true);
|
await initCurrencyDaemon(true);
|
||||||
await fetchCurrency();
|
await fetchCurrency();
|
||||||
setSelectedCurrency(item);
|
setSelectedCurrency(item);
|
||||||
setPreferredFiatCurrency();
|
setPreferredFiatCurrency();
|
||||||
|
|
|
@ -2,49 +2,56 @@ import assert from 'assert';
|
||||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
|
|
||||||
import { FiatUnit } from '../../models/fiatUnit';
|
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);
|
jest.setTimeout(90 * 1000);
|
||||||
|
|
||||||
describe('currency', () => {
|
describe('currency', () => {
|
||||||
it('fetches exchange rate and saves to AsyncStorage', async () => {
|
it('fetches exchange rate and saves to AsyncStorage', async () => {
|
||||||
const currency = require('../../blue_modules/currency');
|
await initCurrencyDaemon();
|
||||||
await currency.init();
|
let cur = await AsyncStorage.getItem(EXCHANGE_RATES_STORAGE_KEY);
|
||||||
let cur = await AsyncStorage.getItem(currency.EXCHANGE_RATES);
|
|
||||||
cur = JSON.parse(cur);
|
cur = JSON.parse(cur);
|
||||||
assert.ok(Number.isInteger(cur[currency.LAST_UPDATED]));
|
assert.ok(Number.isInteger(cur[LAST_UPDATED]));
|
||||||
assert.ok(cur[currency.LAST_UPDATED] > 0);
|
assert.ok(cur[LAST_UPDATED] > 0);
|
||||||
assert.ok(cur.BTC_USD > 0);
|
assert.ok(cur.BTC_USD > 0);
|
||||||
|
|
||||||
// now, setting other currency as default
|
// now, setting other currency as default
|
||||||
await AsyncStorage.setItem(currency.PREFERRED_CURRENCY, JSON.stringify(FiatUnit.JPY));
|
await AsyncStorage.setItem(PREFERRED_CURRENCY_STORAGE_KEY, JSON.stringify(FiatUnit.JPY));
|
||||||
await currency.init(true);
|
await initCurrencyDaemon(true);
|
||||||
cur = JSON.parse(await AsyncStorage.getItem(currency.EXCHANGE_RATES));
|
cur = JSON.parse(await AsyncStorage.getItem(EXCHANGE_RATES_STORAGE_KEY));
|
||||||
assert.ok(cur.BTC_JPY > 0);
|
assert.ok(cur.BTC_JPY > 0);
|
||||||
|
|
||||||
// now setting with a proper setter
|
// now setting with a proper setter
|
||||||
await currency.setPrefferedCurrency(FiatUnit.EUR);
|
await setPreferredCurrency(FiatUnit.EUR);
|
||||||
await currency.init(true);
|
await initCurrencyDaemon(true);
|
||||||
const preferred = await currency.getPreferredCurrency();
|
const preferred = await getPreferredCurrency();
|
||||||
assert.strictEqual(preferred.endPointKey, 'EUR');
|
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);
|
assert.ok(cur.BTC_EUR > 0);
|
||||||
|
|
||||||
// test Yadio rate source
|
// test Yadio rate source
|
||||||
await currency.setPrefferedCurrency(FiatUnit.ARS);
|
await setPreferredCurrency(FiatUnit.ARS);
|
||||||
await currency.init(true);
|
await initCurrencyDaemon(true);
|
||||||
cur = JSON.parse(await AsyncStorage.getItem(currency.EXCHANGE_RATES));
|
cur = JSON.parse(await AsyncStorage.getItem(EXCHANGE_RATES_STORAGE_KEY));
|
||||||
assert.ok(cur.BTC_ARS > 0);
|
assert.ok(cur.BTC_ARS > 0);
|
||||||
|
|
||||||
// test YadioConvert rate source
|
// test YadioConvert rate source
|
||||||
await currency.setPrefferedCurrency(FiatUnit.LBP);
|
await setPreferredCurrency(FiatUnit.LBP);
|
||||||
await currency.init(true);
|
await initCurrencyDaemon(true);
|
||||||
cur = JSON.parse(await AsyncStorage.getItem(currency.EXCHANGE_RATES));
|
cur = JSON.parse(await AsyncStorage.getItem(EXCHANGE_RATES_STORAGE_KEY));
|
||||||
assert.ok(cur.BTC_LBP > 0);
|
assert.ok(cur.BTC_LBP > 0);
|
||||||
|
|
||||||
// test Exir rate source
|
// test Exir rate source
|
||||||
await currency.setPrefferedCurrency(FiatUnit.IRT);
|
await setPreferredCurrency(FiatUnit.IRT);
|
||||||
await currency.init(true);
|
await initCurrencyDaemon(true);
|
||||||
cur = JSON.parse(await AsyncStorage.getItem(currency.EXCHANGE_RATES));
|
cur = JSON.parse(await AsyncStorage.getItem(EXCHANGE_RATES_STORAGE_KEY));
|
||||||
assert.ok(cur.BTC_IRT > 0);
|
assert.ok(cur.BTC_IRT > 0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { TABS } from '../../components/addresses/AddressTypeTabs';
|
||||||
|
|
||||||
jest.mock('../../blue_modules/currency', () => {
|
jest.mock('../../blue_modules/currency', () => {
|
||||||
return {
|
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';
|
import { FiatUnit } from '../../models/fiatUnit';
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
|
|
||||||
describe('currency', () => {
|
describe('currency', () => {
|
||||||
it('formats everything correctly', async () => {
|
it('formats everything correctly', async () => {
|
||||||
const currency = require('../../blue_modules/currency');
|
_setExchangeRate('BTC_USD', 10000);
|
||||||
currency._setExchangeRate('BTC_USD', 10000);
|
|
||||||
|
|
||||||
assert.strictEqual(currency.satoshiToLocalCurrency(1), '$0.0001');
|
assert.strictEqual(satoshiToLocalCurrency(1), '$0.0001');
|
||||||
assert.strictEqual(currency.satoshiToLocalCurrency(-1), '-$0.0001');
|
assert.strictEqual(satoshiToLocalCurrency(-1), '-$0.0001');
|
||||||
assert.strictEqual(currency.satoshiToLocalCurrency(123), '$0.01');
|
assert.strictEqual(satoshiToLocalCurrency(123), '$0.01');
|
||||||
assert.strictEqual(currency.satoshiToLocalCurrency(156), '$0.02');
|
assert.strictEqual(satoshiToLocalCurrency(156), '$0.02');
|
||||||
assert.strictEqual(currency.satoshiToLocalCurrency(51), '$0.01');
|
assert.strictEqual(satoshiToLocalCurrency(51), '$0.01');
|
||||||
assert.strictEqual(currency.satoshiToLocalCurrency(45), '$0.0045');
|
assert.strictEqual(satoshiToLocalCurrency(45), '$0.0045');
|
||||||
assert.strictEqual(currency.satoshiToLocalCurrency(123456789), '$12,345.68');
|
assert.strictEqual(satoshiToLocalCurrency(123456789), '$12,345.68');
|
||||||
|
|
||||||
assert.strictEqual(currency.BTCToLocalCurrency(1), '$10,000.00');
|
assert.strictEqual(BTCToLocalCurrency(1), '$10,000.00');
|
||||||
assert.strictEqual(currency.BTCToLocalCurrency(-1), '-$10,000.00');
|
assert.strictEqual(BTCToLocalCurrency(-1), '-$10,000.00');
|
||||||
assert.strictEqual(currency.BTCToLocalCurrency(1.00000001), '$10,000.00');
|
assert.strictEqual(BTCToLocalCurrency(1.00000001), '$10,000.00');
|
||||||
assert.strictEqual(currency.BTCToLocalCurrency(1.0000123), '$10,000.12');
|
assert.strictEqual(BTCToLocalCurrency(1.0000123), '$10,000.12');
|
||||||
assert.strictEqual(currency.BTCToLocalCurrency(1.0000146), '$10,000.15');
|
assert.strictEqual(BTCToLocalCurrency(1.0000146), '$10,000.15');
|
||||||
|
|
||||||
assert.strictEqual(currency.satoshiToBTC(1), '0.00000001');
|
assert.strictEqual(satoshiToBTC(1), '0.00000001');
|
||||||
assert.strictEqual(currency.satoshiToBTC(-1), '-0.00000001');
|
assert.strictEqual(satoshiToBTC(-1), '-0.00000001');
|
||||||
assert.strictEqual(currency.satoshiToBTC(100000000), '1');
|
assert.strictEqual(satoshiToBTC(100000000), '1');
|
||||||
assert.strictEqual(currency.satoshiToBTC(123456789123456789), '1234567891.2345678'); // eslint-disable-line @typescript-eslint/no-loss-of-precision
|
assert.strictEqual(satoshiToBTC(123456789123456789), '1234567891.2345678'); // eslint-disable-line @typescript-eslint/no-loss-of-precision
|
||||||
|
|
||||||
currency._setPreferredFiatCurrency(FiatUnit.JPY);
|
_setPreferredFiatCurrency(FiatUnit.JPY);
|
||||||
currency._setExchangeRate('BTC_JPY', 1043740.8614);
|
_setExchangeRate('BTC_JPY', 1043740.8614);
|
||||||
|
|
||||||
assert.ok(
|
assert.ok(satoshiToLocalCurrency(1) === '¥0.01' || satoshiToLocalCurrency(1) === '¥0.01', 'Unexpected: ' + satoshiToLocalCurrency(1));
|
||||||
currency.satoshiToLocalCurrency(1) === '¥0.01' || currency.satoshiToLocalCurrency(1) === '¥0.01',
|
|
||||||
'Unexpected: ' + currency.satoshiToLocalCurrency(1),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,7 +2,7 @@ import assert from 'assert';
|
||||||
import { BitcoinUnit } from '../../models/bitcoinUnits';
|
import { BitcoinUnit } from '../../models/bitcoinUnits';
|
||||||
import { FiatUnit } from '../../models/fiatUnit';
|
import { FiatUnit } from '../../models/fiatUnit';
|
||||||
import { _leaveNumbersAndDots, formatBalanceWithoutSuffix, formatBalancePlain, formatBalance } from '../../loc';
|
import { _leaveNumbersAndDots, formatBalanceWithoutSuffix, formatBalancePlain, formatBalance } from '../../loc';
|
||||||
const currency = require('../../blue_modules/currency');
|
import { _setExchangeRate, _setPreferredFiatCurrency, _setSkipUpdateExchangeRate } from '../../blue_modules/currency';
|
||||||
|
|
||||||
describe('Localization', () => {
|
describe('Localization', () => {
|
||||||
it('internal formatter', () => {
|
it('internal formatter', () => {
|
||||||
|
@ -12,8 +12,8 @@ describe('Localization', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('formatBalancePlain() && formatBalancePlain()', () => {
|
it('formatBalancePlain() && formatBalancePlain()', () => {
|
||||||
currency._setExchangeRate('BTC_RUB', 660180.143);
|
_setExchangeRate('BTC_RUB', 660180.143);
|
||||||
currency._setPreferredFiatCurrency(FiatUnit.RUB);
|
_setPreferredFiatCurrency(FiatUnit.RUB);
|
||||||
let newInputValue = formatBalanceWithoutSuffix(152, BitcoinUnit.LOCAL_CURRENCY, false);
|
let newInputValue = formatBalanceWithoutSuffix(152, BitcoinUnit.LOCAL_CURRENCY, false);
|
||||||
assert.ok(newInputValue === 'RUB 1.00' || newInputValue === '1,00 ₽', 'Unexpected: ' + newInputValue);
|
assert.ok(newInputValue === 'RUB 1.00' || newInputValue === '1,00 ₽', 'Unexpected: ' + newInputValue);
|
||||||
newInputValue = formatBalancePlain(152, BitcoinUnit.LOCAL_CURRENCY, false);
|
newInputValue = formatBalancePlain(152, BitcoinUnit.LOCAL_CURRENCY, false);
|
||||||
|
@ -32,8 +32,8 @@ describe('Localization', () => {
|
||||||
newInputValue = formatBalancePlain(76, BitcoinUnit.LOCAL_CURRENCY, false);
|
newInputValue = formatBalancePlain(76, BitcoinUnit.LOCAL_CURRENCY, false);
|
||||||
assert.strictEqual(newInputValue, '0.50');
|
assert.strictEqual(newInputValue, '0.50');
|
||||||
|
|
||||||
currency._setExchangeRate('BTC_USD', 10000);
|
_setExchangeRate('BTC_USD', 10000);
|
||||||
currency._setPreferredFiatCurrency(FiatUnit.USD);
|
_setPreferredFiatCurrency(FiatUnit.USD);
|
||||||
newInputValue = formatBalanceWithoutSuffix(16793829, BitcoinUnit.LOCAL_CURRENCY, false);
|
newInputValue = formatBalanceWithoutSuffix(16793829, BitcoinUnit.LOCAL_CURRENCY, false);
|
||||||
assert.strictEqual(newInputValue, '$1,679.38');
|
assert.strictEqual(newInputValue, '$1,679.38');
|
||||||
newInputValue = formatBalancePlain(16793829, BitcoinUnit.LOCAL_CURRENCY, false);
|
newInputValue = formatBalancePlain(16793829, BitcoinUnit.LOCAL_CURRENCY, false);
|
||||||
|
@ -55,11 +55,11 @@ describe('Localization', () => {
|
||||||
])(
|
])(
|
||||||
'can formatBalanceWithoutSuffix',
|
'can formatBalanceWithoutSuffix',
|
||||||
async (balance, toUnit, withFormatting, expectedResult, shouldResetRate) => {
|
async (balance, toUnit, withFormatting, expectedResult, shouldResetRate) => {
|
||||||
currency._setExchangeRate('BTC_USD', 1);
|
_setExchangeRate('BTC_USD', 1);
|
||||||
currency._setPreferredFiatCurrency(FiatUnit.USD);
|
_setPreferredFiatCurrency(FiatUnit.USD);
|
||||||
if (shouldResetRate) {
|
if (shouldResetRate) {
|
||||||
currency._setExchangeRate('BTC_USD', false);
|
_setExchangeRate('BTC_USD', false);
|
||||||
currency._setSkipUpdateExchangeRate();
|
_setSkipUpdateExchangeRate();
|
||||||
}
|
}
|
||||||
const actualResult = formatBalanceWithoutSuffix(balance, toUnit, withFormatting);
|
const actualResult = formatBalanceWithoutSuffix(balance, toUnit, withFormatting);
|
||||||
assert.strictEqual(actualResult, expectedResult);
|
assert.strictEqual(actualResult, expectedResult);
|
||||||
|
@ -74,8 +74,8 @@ describe('Localization', () => {
|
||||||
])(
|
])(
|
||||||
'can formatBalance',
|
'can formatBalance',
|
||||||
async (balance, toUnit, withFormatting, expectedResult) => {
|
async (balance, toUnit, withFormatting, expectedResult) => {
|
||||||
currency._setExchangeRate('BTC_USD', 1);
|
_setExchangeRate('BTC_USD', 1);
|
||||||
currency._setPreferredFiatCurrency(FiatUnit.USD);
|
_setPreferredFiatCurrency(FiatUnit.USD);
|
||||||
const actualResult = formatBalance(balance, toUnit, withFormatting);
|
const actualResult = formatBalance(balance, toUnit, withFormatting);
|
||||||
assert.strictEqual(actualResult, expectedResult);
|
assert.strictEqual(actualResult, expectedResult);
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Reference in a new issue