mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-03-26 08:55:56 +01:00
Merge branch 'master' into limpbrains-test-walletdetails
This commit is contained in:
commit
daf8cf5b9a
32 changed files with 1623 additions and 1680 deletions
|
@ -7,7 +7,6 @@ import {
|
|||
Alert,
|
||||
Animated,
|
||||
Dimensions,
|
||||
findNodeHandle,
|
||||
Image,
|
||||
InputAccessoryView,
|
||||
Keyboard,
|
||||
|
@ -24,7 +23,7 @@ import {
|
|||
TouchableWithoutFeedback,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import Clipboard from '@react-native-community/clipboard';
|
||||
import Clipboard from '@react-native-clipboard/clipboard';
|
||||
import LinearGradient from 'react-native-linear-gradient';
|
||||
import { LightningCustodianWallet, MultisigHDWallet } from './class';
|
||||
import { BitcoinUnit } from './models/bitcoinUnits';
|
||||
|
@ -33,13 +32,12 @@ import WalletGradient from './class/wallet-gradient';
|
|||
import { BlurView } from '@react-native-community/blur';
|
||||
import NetworkTransactionFees, { NetworkTransactionFee, NetworkTransactionFeeType } from './models/networkTransactionFees';
|
||||
import Biometric from './class/biometrics';
|
||||
import { getSystemName } from 'react-native-device-info';
|
||||
import { encodeUR } from 'bc-ur/dist';
|
||||
import QRCode from 'react-native-qrcode-svg';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import { useNavigation, useTheme } from '@react-navigation/native';
|
||||
import { BlueCurrentTheme } from './components/themes';
|
||||
import loc, { formatBalance, formatBalanceWithoutSuffix, formatBalancePlain, removeTrailingZeros, transactionTimeToReadable } from './loc';
|
||||
import loc, { formatBalance, formatBalanceWithoutSuffix, transactionTimeToReadable } from './loc';
|
||||
import Lnurl from './class/lnurl';
|
||||
import { BlueStorageContext } from './blue_modules/storage-context';
|
||||
import ToolTipMenu from './components/TooltipMenu';
|
||||
|
@ -47,9 +45,6 @@ import ToolTipMenu from './components/TooltipMenu';
|
|||
/** @type {AppStorage} */
|
||||
const { height, width } = Dimensions.get('window');
|
||||
const aspectRatio = height / width;
|
||||
const BigNumber = require('bignumber.js');
|
||||
const currency = require('./blue_modules/currency');
|
||||
const fs = require('./blue_modules/fs');
|
||||
let isIpad;
|
||||
if (aspectRatio > 1.6) {
|
||||
isIpad = false;
|
||||
|
@ -1558,92 +1553,6 @@ export const BlueTransactionListItem = React.memo(({ item, itemPriceUnit = Bitco
|
|||
);
|
||||
});
|
||||
|
||||
const isDesktop = getSystemName() === 'Mac OS X';
|
||||
export const BlueAddressInput = ({
|
||||
isLoading = false,
|
||||
address = '',
|
||||
placeholder = loc.send.details_address,
|
||||
onChangeText,
|
||||
onBarScanned,
|
||||
launchedBy,
|
||||
}) => {
|
||||
const { colors } = useTheme();
|
||||
const scanButtonRef = useRef();
|
||||
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
borderColor: colors.formBorder,
|
||||
borderBottomColor: colors.formBorder,
|
||||
borderWidth: 1.0,
|
||||
borderBottomWidth: 0.5,
|
||||
backgroundColor: colors.inputBackgroundColor,
|
||||
minHeight: 44,
|
||||
height: 44,
|
||||
marginHorizontal: 20,
|
||||
alignItems: 'center',
|
||||
marginVertical: 8,
|
||||
borderRadius: 4,
|
||||
}}
|
||||
>
|
||||
<TextInput
|
||||
testID="AddressInput"
|
||||
onChangeText={onChangeText}
|
||||
placeholder={placeholder}
|
||||
numberOfLines={1}
|
||||
placeholderTextColor="#81868e"
|
||||
value={address}
|
||||
style={{ flex: 1, marginHorizontal: 8, minHeight: 33, color: '#81868e' }}
|
||||
editable={!isLoading}
|
||||
onSubmitEditing={Keyboard.dismiss}
|
||||
/>
|
||||
<TouchableOpacity
|
||||
testID="BlueAddressInputScanQrButton"
|
||||
disabled={isLoading}
|
||||
ref={scanButtonRef}
|
||||
onPress={() => {
|
||||
Keyboard.dismiss();
|
||||
if (isDesktop) {
|
||||
fs.showActionSheet({ anchor: findNodeHandle(scanButtonRef.current) }).then(onBarScanned);
|
||||
} else {
|
||||
NavigationService.navigate('ScanQRCodeRoot', {
|
||||
screen: 'ScanQRCode',
|
||||
params: {
|
||||
launchedBy,
|
||||
onBarScanned,
|
||||
},
|
||||
});
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
height: 36,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
backgroundColor: colors.scanLabel,
|
||||
borderRadius: 4,
|
||||
paddingVertical: 4,
|
||||
paddingHorizontal: 8,
|
||||
marginHorizontal: 4,
|
||||
}}
|
||||
>
|
||||
<Image style={{}} source={require('./img/scan-white.png')} />
|
||||
<Text style={{ marginLeft: 4, color: colors.inverseForegroundColor }}>{loc.send.details_scan}</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
BlueAddressInput.propTypes = {
|
||||
isLoading: PropTypes.bool,
|
||||
onChangeText: PropTypes.func,
|
||||
onBarScanned: PropTypes.func.isRequired,
|
||||
launchedBy: PropTypes.string.isRequired,
|
||||
address: PropTypes.string,
|
||||
placeholder: PropTypes.string,
|
||||
};
|
||||
|
||||
export class BlueReplaceFeeSuggestions extends Component {
|
||||
static propTypes = {
|
||||
onFeeSelected: PropTypes.func.isRequired,
|
||||
|
@ -1799,272 +1708,6 @@ export class BlueReplaceFeeSuggestions extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
export class BlueBitcoinAmount extends Component {
|
||||
static propTypes = {
|
||||
isLoading: PropTypes.bool,
|
||||
/**
|
||||
* amount is a sting thats always in current unit denomination, e.g. '0.001' or '9.43' or '10000'
|
||||
*/
|
||||
amount: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
||||
/**
|
||||
* callback that returns currently typed amount, in current denomination, e.g. 0.001 or 10000 or $9.34
|
||||
* (btc, sat, fiat)
|
||||
*/
|
||||
onChangeText: PropTypes.func,
|
||||
/**
|
||||
* callback thats fired to notify of currently selected denomination, returns <BitcoinUnit.*>
|
||||
*/
|
||||
onAmountUnitChange: PropTypes.func,
|
||||
disabled: PropTypes.bool,
|
||||
};
|
||||
|
||||
/**
|
||||
* cache of conversions fiat amount => satoshi
|
||||
* @type {{}}
|
||||
*/
|
||||
static conversionCache = {};
|
||||
|
||||
static getCachedSatoshis(amount) {
|
||||
return BlueBitcoinAmount.conversionCache[amount + BitcoinUnit.LOCAL_CURRENCY] || false;
|
||||
}
|
||||
|
||||
static setCachedSatoshis(amount, sats) {
|
||||
BlueBitcoinAmount.conversionCache[amount + BitcoinUnit.LOCAL_CURRENCY] = sats;
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { unit: props.unit || BitcoinUnit.BTC, previousUnit: BitcoinUnit.SATS };
|
||||
}
|
||||
|
||||
/**
|
||||
* here we must recalculate old amont value (which was denominated in `previousUnit`) to new denomination `newUnit`
|
||||
* and fill this value in input box, so user can switch between, for example, 0.001 BTC <=> 100000 sats
|
||||
*
|
||||
* @param previousUnit {string} one of {BitcoinUnit.*}
|
||||
* @param newUnit {string} one of {BitcoinUnit.*}
|
||||
*/
|
||||
onAmountUnitChange(previousUnit, newUnit) {
|
||||
const amount = this.props.amount || 0;
|
||||
console.log('was:', amount, previousUnit, '; converting to', newUnit);
|
||||
let sats = 0;
|
||||
switch (previousUnit) {
|
||||
case BitcoinUnit.BTC:
|
||||
sats = new BigNumber(amount).multipliedBy(100000000).toString();
|
||||
break;
|
||||
case BitcoinUnit.SATS:
|
||||
sats = amount;
|
||||
break;
|
||||
case BitcoinUnit.LOCAL_CURRENCY:
|
||||
sats = new BigNumber(currency.fiatToBTC(amount)).multipliedBy(100000000).toString();
|
||||
break;
|
||||
}
|
||||
if (previousUnit === BitcoinUnit.LOCAL_CURRENCY && BlueBitcoinAmount.conversionCache[amount + previousUnit]) {
|
||||
// cache hit! we reuse old value that supposedly doesnt have rounding errors
|
||||
sats = BlueBitcoinAmount.conversionCache[amount + previousUnit];
|
||||
}
|
||||
console.log('so, in sats its', sats);
|
||||
|
||||
const newInputValue = formatBalancePlain(sats, newUnit, false);
|
||||
console.log('and in', newUnit, 'its', newInputValue);
|
||||
|
||||
if (newUnit === BitcoinUnit.LOCAL_CURRENCY && previousUnit === BitcoinUnit.SATS) {
|
||||
// we cache conversion, so when we will need reverse conversion there wont be a rounding error
|
||||
BlueBitcoinAmount.conversionCache[newInputValue + newUnit] = amount;
|
||||
}
|
||||
this.props.onChangeText(newInputValue);
|
||||
if (this.props.onAmountUnitChange) this.props.onAmountUnitChange(newUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
* responsible for cycling currently selected denomination, BTC->SAT->LOCAL_CURRENCY->BTC
|
||||
*/
|
||||
changeAmountUnit = () => {
|
||||
let previousUnit = this.state.unit;
|
||||
let newUnit;
|
||||
if (previousUnit === BitcoinUnit.BTC) {
|
||||
newUnit = BitcoinUnit.SATS;
|
||||
} else if (previousUnit === BitcoinUnit.SATS) {
|
||||
newUnit = BitcoinUnit.LOCAL_CURRENCY;
|
||||
} else if (previousUnit === BitcoinUnit.LOCAL_CURRENCY) {
|
||||
newUnit = BitcoinUnit.BTC;
|
||||
} else {
|
||||
newUnit = BitcoinUnit.BTC;
|
||||
previousUnit = BitcoinUnit.SATS;
|
||||
}
|
||||
this.setState({ unit: newUnit, previousUnit }, () => this.onAmountUnitChange(previousUnit, newUnit));
|
||||
};
|
||||
|
||||
maxLength = () => {
|
||||
switch (this.state.unit) {
|
||||
case BitcoinUnit.BTC:
|
||||
return 10;
|
||||
case BitcoinUnit.SATS:
|
||||
return 15;
|
||||
default:
|
||||
return 15;
|
||||
}
|
||||
};
|
||||
|
||||
textInput = React.createRef();
|
||||
|
||||
handleTextInputOnPress = () => {
|
||||
this.textInput.current.focus();
|
||||
};
|
||||
|
||||
render() {
|
||||
const amount = this.props.amount || 0;
|
||||
let secondaryDisplayCurrency = formatBalanceWithoutSuffix(amount, BitcoinUnit.LOCAL_CURRENCY, false);
|
||||
|
||||
// if main display is sat or btc - secondary display is fiat
|
||||
// if main display is fiat - secondary dislay is btc
|
||||
let sat;
|
||||
switch (this.state.unit) {
|
||||
case BitcoinUnit.BTC:
|
||||
sat = new BigNumber(amount).multipliedBy(100000000).toString();
|
||||
secondaryDisplayCurrency = formatBalanceWithoutSuffix(sat, BitcoinUnit.LOCAL_CURRENCY, false);
|
||||
break;
|
||||
case BitcoinUnit.SATS:
|
||||
secondaryDisplayCurrency = formatBalanceWithoutSuffix((isNaN(amount) ? 0 : amount).toString(), BitcoinUnit.LOCAL_CURRENCY, false);
|
||||
break;
|
||||
case BitcoinUnit.LOCAL_CURRENCY:
|
||||
secondaryDisplayCurrency = currency.fiatToBTC(parseFloat(isNaN(amount) ? 0 : amount));
|
||||
if (BlueBitcoinAmount.conversionCache[isNaN(amount) ? 0 : amount + BitcoinUnit.LOCAL_CURRENCY]) {
|
||||
// cache hit! we reuse old value that supposedly doesn't have rounding errors
|
||||
const sats = BlueBitcoinAmount.conversionCache[isNaN(amount) ? 0 : amount + BitcoinUnit.LOCAL_CURRENCY];
|
||||
secondaryDisplayCurrency = currency.satoshiToBTC(sats);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (amount === BitcoinUnit.MAX) secondaryDisplayCurrency = ''; // we don't want to display NaN
|
||||
return (
|
||||
<TouchableWithoutFeedback disabled={this.props.pointerEvents === 'none'} onPress={() => this.textInput.focus()}>
|
||||
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
|
||||
{!this.props.disabled && <View style={{ alignSelf: 'center', padding: amount === BitcoinUnit.MAX ? 0 : 15 }} />}
|
||||
<View style={{ flex: 1 }}>
|
||||
<View
|
||||
style={{ flexDirection: 'row', alignContent: 'space-between', justifyContent: 'center', paddingTop: 16, paddingBottom: 2 }}
|
||||
>
|
||||
{this.state.unit === BitcoinUnit.LOCAL_CURRENCY && amount !== BitcoinUnit.MAX && (
|
||||
<Text
|
||||
style={{
|
||||
color: this.props.disabled
|
||||
? BlueCurrentTheme.colors.buttonDisabledTextColor
|
||||
: BlueCurrentTheme.colors.alternativeTextColor2,
|
||||
fontSize: 18,
|
||||
marginHorizontal: 4,
|
||||
fontWeight: 'bold',
|
||||
alignSelf: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
{currency.getCurrencySymbol() + ' '}
|
||||
</Text>
|
||||
)}
|
||||
<TextInput
|
||||
{...this.props}
|
||||
testID="BitcoinAmountInput"
|
||||
keyboardType="numeric"
|
||||
adjustsFontSizeToFit
|
||||
onChangeText={text => {
|
||||
text = text.trim();
|
||||
if (this.state.unit !== BitcoinUnit.LOCAL_CURRENCY) {
|
||||
text = text.replace(',', '.');
|
||||
const split = text.split('.');
|
||||
if (split.length >= 2) {
|
||||
text = `${parseInt(split[0], 10)}.${split[1]}`;
|
||||
} else {
|
||||
text = `${parseInt(split[0], 10)}`;
|
||||
}
|
||||
|
||||
text = this.state.unit === BitcoinUnit.BTC ? text.replace(/[^0-9.]/g, '') : text.replace(/[^0-9]/g, '');
|
||||
|
||||
if (text.startsWith('.')) {
|
||||
text = '0.';
|
||||
}
|
||||
} else if (this.state.unit === BitcoinUnit.LOCAL_CURRENCY) {
|
||||
text = text.replace(/,/gi, '');
|
||||
if (text.split('.').length > 2) {
|
||||
// too many dots. stupid code to remove all but first dot:
|
||||
let rez = '';
|
||||
let first = true;
|
||||
for (const part of text.split('.')) {
|
||||
rez += part;
|
||||
if (first) {
|
||||
rez += '.';
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
text = rez;
|
||||
}
|
||||
text = text.replace(/[^\d.,-]/g, ''); // remove all but numbers, dots & commas
|
||||
text = text.replace(/(\..*)\./g, '$1');
|
||||
}
|
||||
this.props.onChangeText(text);
|
||||
}}
|
||||
onBlur={() => {
|
||||
if (this.props.onBlur) this.props.onBlur();
|
||||
}}
|
||||
onFocus={() => {
|
||||
if (this.props.onFocus) this.props.onFocus();
|
||||
}}
|
||||
placeholder="0"
|
||||
maxLength={this.maxLength()}
|
||||
ref={textInput => (this.textInput = textInput)}
|
||||
editable={!this.props.isLoading && !this.props.disabled}
|
||||
value={amount === BitcoinUnit.MAX ? loc.units.MAX : parseFloat(amount) >= 0 ? amount : undefined}
|
||||
placeholderTextColor={
|
||||
this.props.disabled ? BlueCurrentTheme.colors.buttonDisabledTextColor : BlueCurrentTheme.colors.alternativeTextColor2
|
||||
}
|
||||
style={{
|
||||
color: this.props.disabled
|
||||
? BlueCurrentTheme.colors.buttonDisabledTextColor
|
||||
: BlueCurrentTheme.colors.alternativeTextColor2,
|
||||
fontWeight: 'bold',
|
||||
fontSize: amount.length > 10 ? 20 : 36,
|
||||
}}
|
||||
/>
|
||||
{this.state.unit !== BitcoinUnit.LOCAL_CURRENCY && amount !== BitcoinUnit.MAX && (
|
||||
<Text
|
||||
style={{
|
||||
color: this.props.disabled
|
||||
? BlueCurrentTheme.colors.buttonDisabledTextColor
|
||||
: BlueCurrentTheme.colors.alternativeTextColor2,
|
||||
fontSize: 15,
|
||||
marginHorizontal: 4,
|
||||
fontWeight: '600',
|
||||
alignSelf: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
{' ' + loc.units[this.state.unit]}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
<View style={{ alignItems: 'center', marginBottom: 22 }}>
|
||||
<Text style={{ fontSize: 16, color: '#9BA0A9', fontWeight: '600' }}>
|
||||
{this.state.unit === BitcoinUnit.LOCAL_CURRENCY && amount !== BitcoinUnit.MAX
|
||||
? removeTrailingZeros(secondaryDisplayCurrency)
|
||||
: secondaryDisplayCurrency}
|
||||
{this.state.unit === BitcoinUnit.LOCAL_CURRENCY && amount !== BitcoinUnit.MAX ? ` ${loc.units[BitcoinUnit.BTC]}` : null}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
{!this.props.disabled && amount !== BitcoinUnit.MAX && (
|
||||
<TouchableOpacity
|
||||
testID="changeAmountUnitButton"
|
||||
style={{ alignSelf: 'center', marginRight: 16, paddingLeft: 16, paddingVertical: 16 }}
|
||||
onPress={this.changeAmountUnit}
|
||||
>
|
||||
<Image source={require('./img/round-compare-arrows-24-px.png')} />
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
);
|
||||
}
|
||||
}
|
||||
const styles = StyleSheet.create({
|
||||
balanceBlur: {
|
||||
height: 30,
|
||||
|
|
|
@ -76,7 +76,7 @@ import LnurlPaySuccess from './screen/lnd/lnurlPaySuccess';
|
|||
import LoadingScreen from './LoadingScreen';
|
||||
import UnlockWith from './UnlockWith';
|
||||
import DrawerList from './screen/wallets/drawerList';
|
||||
import { isTablet } from 'react-native-device-info';
|
||||
import { isCatalyst, isTablet } from './blue_modules/environment';
|
||||
import SettingsPrivacy from './screen/settings/SettingsPrivacy';
|
||||
import LNDViewAdditionalInvoicePreImage from './screen/lnd/lndViewAdditionalInvoicePreImage';
|
||||
|
||||
|
@ -348,7 +348,8 @@ const ReorderWalletsStackRoot = () => {
|
|||
const Drawer = createDrawerNavigator();
|
||||
function DrawerRoot() {
|
||||
const dimensions = useWindowDimensions();
|
||||
const isLargeScreen = Platform.OS === 'android' ? isTablet() : dimensions.width >= Dimensions.get('screen').width / 2 && isTablet();
|
||||
const isLargeScreen =
|
||||
Platform.OS === 'android' ? isTablet() : dimensions.width >= Dimensions.get('screen').width / 2 && (isTablet() || isCatalyst);
|
||||
const drawerStyle = { width: '0%' };
|
||||
|
||||
return (
|
||||
|
|
|
@ -136,7 +136,7 @@ android {
|
|||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 1
|
||||
versionName "6.0.6"
|
||||
versionName "6.0.7"
|
||||
multiDexEnabled true
|
||||
missingDimensionStrategy 'react-native-camera', 'general'
|
||||
testBuildType System.getProperty('testBuildType', 'debug') // This will later be used to control the test apk build type
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { useAsyncStorage } from '@react-native-async-storage/async-storage';
|
||||
import Clipboard from '@react-native-community/clipboard';
|
||||
import Clipboard from '@react-native-clipboard/clipboard';
|
||||
|
||||
function BlueClipboard() {
|
||||
BlueClipboard.STORAGE_KEY = 'ClipboardReadAllowed';
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { getSystemName } from 'react-native-device-info';
|
||||
import { getSystemName, isTablet } from 'react-native-device-info';
|
||||
import isCatalyst from 'react-native-is-catalyst';
|
||||
|
||||
const isMacCatalina = getSystemName() === 'Mac OS X';
|
||||
|
||||
module.exports.isMacCatalina = isMacCatalina;
|
||||
module.exports.isCatalyst = isCatalyst;
|
||||
module.exports.isTablet = isTablet;
|
||||
|
|
|
@ -7,7 +7,7 @@ import DocumentPicker from 'react-native-document-picker';
|
|||
import isCatalyst from 'react-native-is-catalyst';
|
||||
import { launchCamera, launchImageLibrary } from 'react-native-image-picker';
|
||||
import { presentCameraNotAuthorizedAlert } from '../class/camera';
|
||||
import Clipboard from '@react-native-community/clipboard';
|
||||
import Clipboard from '@react-native-clipboard/clipboard';
|
||||
import ActionSheet from '../screen/ActionSheet';
|
||||
const LocalQRCode = require('@remobile/react-native-qrcode-local-image');
|
||||
|
||||
|
|
120
components/AddressInput.js
Normal file
120
components/AddressInput.js
Normal file
|
@ -0,0 +1,120 @@
|
|||
import React, { useRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Text } from 'react-native-elements';
|
||||
import { findNodeHandle, Image, Keyboard, StyleSheet, TextInput, TouchableOpacity, View } from 'react-native';
|
||||
import { getSystemName } from 'react-native-device-info';
|
||||
import { useTheme } from '@react-navigation/native';
|
||||
|
||||
import loc from '../loc';
|
||||
import * as NavigationService from '../NavigationService';
|
||||
const fs = require('../blue_modules/fs');
|
||||
|
||||
const isDesktop = getSystemName() === 'Mac OS X';
|
||||
|
||||
const AddressInput = ({
|
||||
isLoading = false,
|
||||
address = '',
|
||||
placeholder = loc.send.details_address,
|
||||
onChangeText,
|
||||
onBarScanned,
|
||||
launchedBy,
|
||||
}) => {
|
||||
const { colors } = useTheme();
|
||||
const scanButtonRef = useRef();
|
||||
|
||||
const stylesHook = StyleSheet.create({
|
||||
root: {
|
||||
borderColor: colors.formBorder,
|
||||
borderBottomColor: colors.formBorder,
|
||||
backgroundColor: colors.inputBackgroundColor,
|
||||
},
|
||||
scan: {
|
||||
backgroundColor: colors.scanLabel,
|
||||
},
|
||||
scanText: {
|
||||
color: colors.inverseForegroundColor,
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<View style={[styles.root, stylesHook.root]}>
|
||||
<TextInput
|
||||
testID="AddressInput"
|
||||
onChangeText={onChangeText}
|
||||
placeholder={placeholder}
|
||||
numberOfLines={1}
|
||||
placeholderTextColor="#81868e"
|
||||
value={address}
|
||||
style={styles.input}
|
||||
editable={!isLoading}
|
||||
onSubmitEditing={Keyboard.dismiss}
|
||||
/>
|
||||
<TouchableOpacity
|
||||
testID="BlueAddressInputScanQrButton"
|
||||
disabled={isLoading}
|
||||
onPress={() => {
|
||||
Keyboard.dismiss();
|
||||
if (isDesktop) {
|
||||
fs.showActionSheet({ anchor: findNodeHandle(scanButtonRef.current) }).then(onBarScanned);
|
||||
} else {
|
||||
NavigationService.navigate('ScanQRCodeRoot', {
|
||||
screen: 'ScanQRCode',
|
||||
params: {
|
||||
launchedBy,
|
||||
onBarScanned,
|
||||
},
|
||||
});
|
||||
}
|
||||
}}
|
||||
style={[styles.scan, stylesHook.scan]}
|
||||
>
|
||||
<Image source={require('../img/scan-white.png')} />
|
||||
<Text style={[styles.scanText, stylesHook.scanText]}>{loc.send.details_scan}</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flexDirection: 'row',
|
||||
borderWidth: 1.0,
|
||||
borderBottomWidth: 0.5,
|
||||
minHeight: 44,
|
||||
height: 44,
|
||||
marginHorizontal: 20,
|
||||
alignItems: 'center',
|
||||
marginVertical: 8,
|
||||
borderRadius: 4,
|
||||
},
|
||||
input: {
|
||||
flex: 1,
|
||||
marginHorizontal: 8,
|
||||
minHeight: 33,
|
||||
color: '#81868e',
|
||||
},
|
||||
scan: {
|
||||
height: 36,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
borderRadius: 4,
|
||||
paddingVertical: 4,
|
||||
paddingHorizontal: 8,
|
||||
marginHorizontal: 4,
|
||||
},
|
||||
scanText: {
|
||||
marginLeft: 4,
|
||||
},
|
||||
});
|
||||
|
||||
AddressInput.propTypes = {
|
||||
isLoading: PropTypes.bool,
|
||||
onChangeText: PropTypes.func,
|
||||
onBarScanned: PropTypes.func.isRequired,
|
||||
launchedBy: PropTypes.string,
|
||||
address: PropTypes.string,
|
||||
placeholder: PropTypes.string,
|
||||
};
|
||||
|
||||
export default AddressInput;
|
313
components/AmountInput.js
Normal file
313
components/AmountInput.js
Normal file
|
@ -0,0 +1,313 @@
|
|||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { Text } from 'react-native-elements';
|
||||
import { Image, StyleSheet, TextInput, TouchableOpacity, TouchableWithoutFeedback, View } from 'react-native';
|
||||
import { useTheme } from '@react-navigation/native';
|
||||
|
||||
import { BitcoinUnit } from '../models/bitcoinUnits';
|
||||
import loc, { formatBalanceWithoutSuffix, formatBalancePlain, removeTrailingZeros } from '../loc';
|
||||
const currency = require('../blue_modules/currency');
|
||||
|
||||
class AmountInput extends Component {
|
||||
static propTypes = {
|
||||
isLoading: PropTypes.bool,
|
||||
/**
|
||||
* amount is a sting thats always in current unit denomination, e.g. '0.001' or '9.43' or '10000'
|
||||
*/
|
||||
amount: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
||||
/**
|
||||
* callback that returns currently typed amount, in current denomination, e.g. 0.001 or 10000 or $9.34
|
||||
* (btc, sat, fiat)
|
||||
*/
|
||||
onChangeText: PropTypes.func.isRequired,
|
||||
/**
|
||||
* callback thats fired to notify of currently selected denomination, returns <BitcoinUnit.*>
|
||||
*/
|
||||
onAmountUnitChange: PropTypes.func.isRequired,
|
||||
disabled: PropTypes.bool,
|
||||
colors: PropTypes.object.isRequired,
|
||||
pointerEvents: PropTypes.string,
|
||||
unit: PropTypes.string,
|
||||
onBlur: PropTypes.func,
|
||||
onFocus: PropTypes.func,
|
||||
};
|
||||
|
||||
/**
|
||||
* cache of conversions fiat amount => satoshi
|
||||
* @type {{}}
|
||||
*/
|
||||
static conversionCache = {};
|
||||
|
||||
static getCachedSatoshis = amount => {
|
||||
return AmountInput.conversionCache[amount + BitcoinUnit.LOCAL_CURRENCY] || false;
|
||||
};
|
||||
|
||||
static setCachedSatoshis = (amount, sats) => {
|
||||
AmountInput.conversionCache[amount + BitcoinUnit.LOCAL_CURRENCY] = sats;
|
||||
};
|
||||
|
||||
/**
|
||||
* here we must recalculate old amont value (which was denominated in `previousUnit`) to new denomination `newUnit`
|
||||
* and fill this value in input box, so user can switch between, for example, 0.001 BTC <=> 100000 sats
|
||||
*
|
||||
* @param previousUnit {string} one of {BitcoinUnit.*}
|
||||
* @param newUnit {string} one of {BitcoinUnit.*}
|
||||
*/
|
||||
onAmountUnitChange(previousUnit, newUnit) {
|
||||
const amount = this.props.amount || 0;
|
||||
console.log('was:', amount, previousUnit, '; converting to', newUnit);
|
||||
let sats = 0;
|
||||
switch (previousUnit) {
|
||||
case BitcoinUnit.BTC:
|
||||
sats = new BigNumber(amount).multipliedBy(100000000).toString();
|
||||
break;
|
||||
case BitcoinUnit.SATS:
|
||||
sats = amount;
|
||||
break;
|
||||
case BitcoinUnit.LOCAL_CURRENCY:
|
||||
sats = new BigNumber(currency.fiatToBTC(amount)).multipliedBy(100000000).toString();
|
||||
break;
|
||||
}
|
||||
if (previousUnit === BitcoinUnit.LOCAL_CURRENCY && AmountInput.conversionCache[amount + previousUnit]) {
|
||||
// cache hit! we reuse old value that supposedly doesnt have rounding errors
|
||||
sats = AmountInput.conversionCache[amount + previousUnit];
|
||||
}
|
||||
console.log('so, in sats its', sats);
|
||||
|
||||
const newInputValue = formatBalancePlain(sats, newUnit, false);
|
||||
console.log('and in', newUnit, 'its', newInputValue);
|
||||
|
||||
if (newUnit === BitcoinUnit.LOCAL_CURRENCY && previousUnit === BitcoinUnit.SATS) {
|
||||
// we cache conversion, so when we will need reverse conversion there wont be a rounding error
|
||||
AmountInput.conversionCache[newInputValue + newUnit] = amount;
|
||||
}
|
||||
this.props.onChangeText(newInputValue);
|
||||
this.props.onAmountUnitChange(newUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
* responsible for cycling currently selected denomination, BTC->SAT->LOCAL_CURRENCY->BTC
|
||||
*/
|
||||
changeAmountUnit = () => {
|
||||
let previousUnit = this.props.unit;
|
||||
let newUnit;
|
||||
if (previousUnit === BitcoinUnit.BTC) {
|
||||
newUnit = BitcoinUnit.SATS;
|
||||
} else if (previousUnit === BitcoinUnit.SATS) {
|
||||
newUnit = BitcoinUnit.LOCAL_CURRENCY;
|
||||
} else if (previousUnit === BitcoinUnit.LOCAL_CURRENCY) {
|
||||
newUnit = BitcoinUnit.BTC;
|
||||
} else {
|
||||
newUnit = BitcoinUnit.BTC;
|
||||
previousUnit = BitcoinUnit.SATS;
|
||||
}
|
||||
this.onAmountUnitChange(previousUnit, newUnit);
|
||||
};
|
||||
|
||||
maxLength = () => {
|
||||
switch (this.props.unit) {
|
||||
case BitcoinUnit.BTC:
|
||||
return 10;
|
||||
case BitcoinUnit.SATS:
|
||||
return 15;
|
||||
default:
|
||||
return 15;
|
||||
}
|
||||
};
|
||||
|
||||
textInput = React.createRef();
|
||||
|
||||
handleTextInputOnPress = () => {
|
||||
this.textInput.current.focus();
|
||||
};
|
||||
|
||||
handleChangeText = text => {
|
||||
text = text.trim();
|
||||
if (this.props.unit !== BitcoinUnit.LOCAL_CURRENCY) {
|
||||
text = text.replace(',', '.');
|
||||
const split = text.split('.');
|
||||
if (split.length >= 2) {
|
||||
text = `${parseInt(split[0], 10)}.${split[1]}`;
|
||||
} else {
|
||||
text = `${parseInt(split[0], 10)}`;
|
||||
}
|
||||
|
||||
text = this.props.unit === BitcoinUnit.BTC ? text.replace(/[^0-9.]/g, '') : text.replace(/[^0-9]/g, '');
|
||||
|
||||
if (text.startsWith('.')) {
|
||||
text = '0.';
|
||||
}
|
||||
} else if (this.props.unit === BitcoinUnit.LOCAL_CURRENCY) {
|
||||
text = text.replace(/,/gi, '');
|
||||
if (text.split('.').length > 2) {
|
||||
// too many dots. stupid code to remove all but first dot:
|
||||
let rez = '';
|
||||
let first = true;
|
||||
for (const part of text.split('.')) {
|
||||
rez += part;
|
||||
if (first) {
|
||||
rez += '.';
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
text = rez;
|
||||
}
|
||||
text = text.replace(/[^\d.,-]/g, ''); // remove all but numbers, dots & commas
|
||||
text = text.replace(/(\..*)\./g, '$1');
|
||||
}
|
||||
this.props.onChangeText(text);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { colors, disabled, unit } = this.props;
|
||||
const amount = this.props.amount || 0;
|
||||
let secondaryDisplayCurrency = formatBalanceWithoutSuffix(amount, BitcoinUnit.LOCAL_CURRENCY, false);
|
||||
|
||||
// if main display is sat or btc - secondary display is fiat
|
||||
// if main display is fiat - secondary dislay is btc
|
||||
let sat;
|
||||
switch (unit) {
|
||||
case BitcoinUnit.BTC:
|
||||
sat = new BigNumber(amount).multipliedBy(100000000).toString();
|
||||
secondaryDisplayCurrency = formatBalanceWithoutSuffix(sat, BitcoinUnit.LOCAL_CURRENCY, false);
|
||||
break;
|
||||
case BitcoinUnit.SATS:
|
||||
secondaryDisplayCurrency = formatBalanceWithoutSuffix((isNaN(amount) ? 0 : amount).toString(), BitcoinUnit.LOCAL_CURRENCY, false);
|
||||
break;
|
||||
case BitcoinUnit.LOCAL_CURRENCY:
|
||||
secondaryDisplayCurrency = currency.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);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (amount === BitcoinUnit.MAX) secondaryDisplayCurrency = ''; // we don't want to display NaN
|
||||
|
||||
const stylesHook = StyleSheet.create({
|
||||
center: { padding: amount === BitcoinUnit.MAX ? 0 : 15 },
|
||||
localCurrency: { color: disabled ? colors.buttonDisabledTextColor : colors.alternativeTextColor2 },
|
||||
input: { color: disabled ? colors.buttonDisabledTextColor : colors.alternativeTextColor2, fontSize: amount.length > 10 ? 20 : 36 },
|
||||
cryptoCurrency: { color: disabled ? colors.buttonDisabledTextColor : colors.alternativeTextColor2 },
|
||||
});
|
||||
|
||||
return (
|
||||
<TouchableWithoutFeedback disabled={this.props.pointerEvents === 'none'} onPress={() => this.textInput.focus()}>
|
||||
<View style={styles.root}>
|
||||
{!disabled && <View style={[styles.center, stylesHook.center]} />}
|
||||
<View style={styles.flex}>
|
||||
<View style={styles.container}>
|
||||
{unit === BitcoinUnit.LOCAL_CURRENCY && amount !== BitcoinUnit.MAX && (
|
||||
<Text style={[styles.localCurrency, stylesHook.localCurrency]}>{currency.getCurrencySymbol() + ' '}</Text>
|
||||
)}
|
||||
<TextInput
|
||||
{...this.props}
|
||||
testID="BitcoinAmountInput"
|
||||
keyboardType="numeric"
|
||||
adjustsFontSizeToFit
|
||||
onChangeText={this.handleChangeText}
|
||||
onBlur={() => {
|
||||
if (this.props.onBlur) this.props.onBlur();
|
||||
}}
|
||||
onFocus={() => {
|
||||
if (this.props.onFocus) this.props.onFocus();
|
||||
}}
|
||||
placeholder="0"
|
||||
maxLength={this.maxLength()}
|
||||
ref={textInput => (this.textInput = textInput)}
|
||||
editable={!this.props.isLoading && !disabled}
|
||||
value={amount === BitcoinUnit.MAX ? loc.units.MAX : parseFloat(amount) >= 0 ? String(amount) : undefined}
|
||||
placeholderTextColor={disabled ? colors.buttonDisabledTextColor : colors.alternativeTextColor2}
|
||||
style={[styles.input, stylesHook.input]}
|
||||
/>
|
||||
{unit !== BitcoinUnit.LOCAL_CURRENCY && amount !== BitcoinUnit.MAX && (
|
||||
<Text style={[styles.cryptoCurrency, stylesHook.cryptoCurrency]}>{' ' + loc.units[unit]}</Text>
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.secondaryRoot}>
|
||||
<Text style={styles.secondaryText}>
|
||||
{unit === BitcoinUnit.LOCAL_CURRENCY && amount !== BitcoinUnit.MAX
|
||||
? removeTrailingZeros(secondaryDisplayCurrency)
|
||||
: secondaryDisplayCurrency}
|
||||
{unit === BitcoinUnit.LOCAL_CURRENCY && amount !== BitcoinUnit.MAX ? ` ${loc.units[BitcoinUnit.BTC]}` : null}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
{!disabled && amount !== BitcoinUnit.MAX && (
|
||||
<TouchableOpacity testID="changeAmountUnitButton" style={styles.changeAmountUnit} onPress={this.changeAmountUnit}>
|
||||
<Image source={require('../img/round-compare-arrows-24-px.png')} />
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
root: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
center: {
|
||||
alignSelf: 'center',
|
||||
},
|
||||
flex: {
|
||||
flex: 1,
|
||||
},
|
||||
container: {
|
||||
flexDirection: 'row',
|
||||
alignContent: 'space-between',
|
||||
justifyContent: 'center',
|
||||
paddingTop: 16,
|
||||
paddingBottom: 2,
|
||||
},
|
||||
localCurrency: {
|
||||
fontSize: 18,
|
||||
marginHorizontal: 4,
|
||||
fontWeight: 'bold',
|
||||
alignSelf: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
input: {
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
cryptoCurrency: {
|
||||
fontSize: 15,
|
||||
marginHorizontal: 4,
|
||||
fontWeight: '600',
|
||||
alignSelf: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
secondaryRoot: {
|
||||
alignItems: 'center',
|
||||
marginBottom: 22,
|
||||
},
|
||||
secondaryText: {
|
||||
fontSize: 16,
|
||||
color: '#9BA0A9',
|
||||
fontWeight: '600',
|
||||
},
|
||||
changeAmountUnit: {
|
||||
alignSelf: 'center',
|
||||
marginRight: 16,
|
||||
paddingLeft: 16,
|
||||
paddingVertical: 16,
|
||||
},
|
||||
});
|
||||
|
||||
const AmountInputWithStyle = props => {
|
||||
const { colors } = useTheme();
|
||||
|
||||
return <AmountInput {...props} colors={colors} />;
|
||||
};
|
||||
|
||||
// expose static methods
|
||||
AmountInputWithStyle.conversionCache = AmountInput.conversionCache;
|
||||
AmountInputWithStyle.getCachedSatoshis = AmountInput.getCachedSatoshis;
|
||||
AmountInputWithStyle.setCachedSatoshis = AmountInput.setCachedSatoshis;
|
||||
|
||||
export default AmountInputWithStyle;
|
|
@ -1630,7 +1630,7 @@
|
|||
"$(inherited)",
|
||||
"$(PROJECT_DIR)",
|
||||
);
|
||||
MARKETING_VERSION = 6.0.6;
|
||||
MARKETING_VERSION = 6.0.7;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
|
@ -1673,7 +1673,7 @@
|
|||
"$(inherited)",
|
||||
"$(PROJECT_DIR)",
|
||||
);
|
||||
MARKETING_VERSION = 6.0.6;
|
||||
MARKETING_VERSION = 6.0.7;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
|
@ -1714,7 +1714,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 6.0.6;
|
||||
MARKETING_VERSION = 6.0.7;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.TodayExtension;
|
||||
|
@ -1753,7 +1753,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 6.0.6;
|
||||
MARKETING_VERSION = 6.0.7;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.TodayExtension;
|
||||
PRODUCT_NAME = "BlueWallet - Bitcoin Price";
|
||||
|
@ -1785,7 +1785,7 @@
|
|||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
INFOPLIST_FILE = Stickers/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
MARKETING_VERSION = 6.0.6;
|
||||
MARKETING_VERSION = 6.0.7;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.Stickers;
|
||||
|
@ -1816,7 +1816,7 @@
|
|||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
INFOPLIST_FILE = Stickers/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
MARKETING_VERSION = 6.0.6;
|
||||
MARKETING_VERSION = 6.0.7;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.Stickers;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
@ -1852,7 +1852,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 6.0.6;
|
||||
MARKETING_VERSION = 6.0.7;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.PriceWidget;
|
||||
|
@ -1894,7 +1894,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 6.0.6;
|
||||
MARKETING_VERSION = 6.0.7;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.PriceWidget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
@ -1934,7 +1934,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 6.0.6;
|
||||
MARKETING_VERSION = 6.0.7;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.MarketWidget;
|
||||
|
@ -1977,7 +1977,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 6.0.6;
|
||||
MARKETING_VERSION = 6.0.7;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.MarketWidget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
@ -2018,7 +2018,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 6.0.6;
|
||||
MARKETING_VERSION = 6.0.7;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.WalletInformationAndMarketWidget;
|
||||
|
@ -2062,7 +2062,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 6.0.6;
|
||||
MARKETING_VERSION = 6.0.7;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.WalletInformationAndMarketWidget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
@ -2102,7 +2102,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 6.0.6;
|
||||
MARKETING_VERSION = 6.0.7;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.WalletInformationWidget;
|
||||
|
@ -2144,7 +2144,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 6.0.6;
|
||||
MARKETING_VERSION = 6.0.7;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.WalletInformationWidget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
@ -2286,7 +2286,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 6.0.6;
|
||||
MARKETING_VERSION = 6.0.7;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.watch.extension;
|
||||
|
@ -2326,7 +2326,7 @@
|
|||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 6.0.6;
|
||||
MARKETING_VERSION = 6.0.7;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.watch.extension;
|
||||
PRODUCT_NAME = "${TARGET_NAME}";
|
||||
|
@ -2362,7 +2362,7 @@
|
|||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
IBSC_MODULE = BlueWalletWatch_Extension;
|
||||
INFOPLIST_FILE = BlueWalletWatch/Info.plist;
|
||||
MARKETING_VERSION = 6.0.6;
|
||||
MARKETING_VERSION = 6.0.7;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.watch;
|
||||
|
@ -2401,7 +2401,7 @@
|
|||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
IBSC_MODULE = BlueWalletWatch_Extension;
|
||||
INFOPLIST_FILE = BlueWalletWatch/Info.plist;
|
||||
MARKETING_VERSION = 6.0.6;
|
||||
MARKETING_VERSION = 6.0.7;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.watch;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
|
|
@ -276,7 +276,7 @@ PODS:
|
|||
- react-native-tcp-socket (3.7.1):
|
||||
- CocoaAsyncSocket
|
||||
- React
|
||||
- react-native-webview (11.2.0):
|
||||
- react-native-webview (11.2.1):
|
||||
- React-Core
|
||||
- react-native-widget-center (0.0.4):
|
||||
- React
|
||||
|
@ -347,7 +347,7 @@ PODS:
|
|||
- React
|
||||
- RNCAsyncStorage (1.13.4):
|
||||
- React-Core
|
||||
- RNCClipboard (1.5.1):
|
||||
- RNCClipboard (1.7.0):
|
||||
- React-Core
|
||||
- RNCMaskedView (0.1.10):
|
||||
- React
|
||||
|
@ -470,7 +470,7 @@ DEPENDENCIES:
|
|||
- RealmJS (from `../node_modules/realm`)
|
||||
- "RemobileReactNativeQrcodeLocalImage (from `../node_modules/@remobile/react-native-qrcode-local-image`)"
|
||||
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
|
||||
- "RNCClipboard (from `../node_modules/@react-native-community/clipboard`)"
|
||||
- "RNCClipboard (from `../node_modules/@react-native-clipboard/clipboard`)"
|
||||
- "RNCMaskedView (from `../node_modules/@react-native-community/masked-view`)"
|
||||
- "RNCPushNotificationIOS (from `../node_modules/@react-native-community/push-notification-ios`)"
|
||||
- RNDefaultPreference (from `../node_modules/react-native-default-preference`)
|
||||
|
@ -607,7 +607,7 @@ EXTERNAL SOURCES:
|
|||
RNCAsyncStorage:
|
||||
:path: "../node_modules/@react-native-async-storage/async-storage"
|
||||
RNCClipboard:
|
||||
:path: "../node_modules/@react-native-community/clipboard"
|
||||
:path: "../node_modules/@react-native-clipboard/clipboard"
|
||||
RNCMaskedView:
|
||||
:path: "../node_modules/@react-native-community/masked-view"
|
||||
RNCPushNotificationIOS:
|
||||
|
@ -707,7 +707,7 @@ SPEC CHECKSUMS:
|
|||
react-native-safe-area-context: 86612d2c9a9e94e288319262d10b5f93f0b395f5
|
||||
react-native-slider: b733e17fdd31186707146debf1f04b5d94aa1a93
|
||||
react-native-tcp-socket: 96a4f104cdcc9c6621aafe92937f163d88447c5b
|
||||
react-native-webview: c010115ea45efd0d329ac7746d0cc59579d7860c
|
||||
react-native-webview: dbe6c1ad149740f0e2d84a963f1d3c3e77f2d99c
|
||||
react-native-widget-center: 0f81d17beb163e7fb5848b06754d7d277fe7d99a
|
||||
React-RCTActionSheet: 53ea72699698b0b47a6421cb1c8b4ab215a774aa
|
||||
React-RCTAnimation: 1befece0b5183c22ae01b966f5583f42e69a83c2
|
||||
|
@ -722,7 +722,7 @@ SPEC CHECKSUMS:
|
|||
RealmJS: 5195064e9aeccf94ae3756bd9d0f2301b9074b07
|
||||
RemobileReactNativeQrcodeLocalImage: 57aadc12896b148fb5e04bc7c6805f3565f5c3fa
|
||||
RNCAsyncStorage: 0701cb7395f06d744184641241888a0eec0e2f2a
|
||||
RNCClipboard: 5e299c6df8e0c98f3d7416b86ae563d3a9f768a3
|
||||
RNCClipboard: dac13db8b1ce9b998f1cbc7ca33440113602847f
|
||||
RNCMaskedView: f5c7d14d6847b7b44853f7acb6284c1da30a3459
|
||||
RNCPushNotificationIOS: 5b1cf9ad2aaa107ecb92d5d2d7005ba521b2b97a
|
||||
RNDefaultPreference: 21816c0a6f61a2829ccc0cef034392e9b509ee5f
|
||||
|
|
|
@ -1,3 +1,32 @@
|
|||
v6.0.6
|
||||
======
|
||||
|
||||
* ADD: PSBT cosign
|
||||
* ADD: Long press Transaction Row to get shortcuts
|
||||
* ADD: Tap and hold to Share QRCode image
|
||||
* ADD: qrcode scanner to wallet/broadcast screen
|
||||
* ADD: Apple Watch Price Complication
|
||||
* ADD: Update complication currency based on user preference
|
||||
* ADD: Copying Block Explorer Link
|
||||
* ADD: If unable to connect to server, show alert
|
||||
* FIX: Delete wallet button should be red
|
||||
* FIX: Wallet delete would cause crash
|
||||
* FIX: broken buyBitcoin button for some wallets
|
||||
* FIX: Browser crash when accessing wallet
|
||||
* FIX: sometimes broken webview
|
||||
* FIX: Some widgets were not showing on drawer
|
||||
* FIX: screen titles language
|
||||
* FIX: Complication app update when watch app isnt launched
|
||||
* FIX: QRCode save alert description
|
||||
* FIX: Only send complication updates if watch is reachable
|
||||
* FIX: QRCode size on large devices
|
||||
* FIX: fix size and share button
|
||||
* FIX: sync loc files for ar, ru, ca, he, pl, ja_JP, pt_BR, pt_PT, sv_SE, th_TH, zh_CN, fi_FI, fa_IR, de_DE, nl_NL, fr_FR
|
||||
* REF: transactions/details screen gracefull error handling
|
||||
* REF: electrum protocol error graceful handling
|
||||
* REF: better bitcoinscript error handling
|
||||
* REF: Fee selection in darkmode
|
||||
|
||||
v6.0.4
|
||||
======
|
||||
|
||||
|
@ -48,48 +77,3 @@ v6.0.3
|
|||
* FIX: multisig coin control
|
||||
* REF: Remove "new" from LocalTrader
|
||||
* FIX: locales fr_FR, sl_SI, es_ES, ru, fa_IR, fi_FI
|
||||
|
||||
v6.0.2
|
||||
======
|
||||
|
||||
* ADD: view of QR code of Vault key zpub after vault is created (closes #2410)
|
||||
* ADD: helper text on ms-edit screen
|
||||
* ADD: electrum servers history list
|
||||
* ADD: iMessage stickers
|
||||
* ADD: Privacy settings for iOS 14 widgets
|
||||
* ADD: ability to set electrum server or lndhub via deeplink or by scanning a QR from main screen
|
||||
* ADD: CoinControl multiselect
|
||||
* FIX: better support multisig cosigning with Electrum desktop
|
||||
* FIX: multisig 'Too many signatures' error
|
||||
* FIX: Amount displayed on success invoice payment
|
||||
* FIX: localizations for fr_FR, es_ES, de_DE, fa_IR, cs_CZ, fr_FR, nl_NL, fi_FI
|
||||
* FIX: Hide balance on reorder screen
|
||||
* FIX: disallow importing non-multisignature xpubs into multisig setup
|
||||
* FIX: better multisig wallet descriptors suppport
|
||||
* FIX: Incorrect import from Specter - p2sh wrapped segwit multisig
|
||||
* FIX: Clear quick actions if storage is encrypted
|
||||
* FIX: use dayjs localizedFormat plugin to render tx time
|
||||
* FIX: show more accurate precalculation fee on "Not enough balance." exception
|
||||
* FIX: Wallet Delete on new install was not being triggered
|
||||
* FIX: Fallback to English if case isn't found
|
||||
* FIX: animated qr scan progress readability
|
||||
* FIX: rerender UI after language change
|
||||
* FIX: Hide modal when scanning
|
||||
* FIX: reorder screen bug
|
||||
* FIX: Don't show clipboard modal if user has already acted on it
|
||||
* REF: processing push notifications
|
||||
* REF: Add warning to LN
|
||||
* REF: Github link on about
|
||||
* DOC: Telegram and Discord links on about section
|
||||
|
||||
v6.0.1
|
||||
======
|
||||
|
||||
* ADD: enable batch-send on multisig wallets
|
||||
* FIX: Speed-up multisig wallets (disable handoff for multisig)
|
||||
* FIX: Import Multisig from Specter Desktop - Fingerprint is Incorrect
|
||||
* FIX: broken export .txn file on tx confirmation screen
|
||||
* FIX: backup screen would flash during loading on dark mode
|
||||
* FIX: Handle opening links if the default browser isnt Safari
|
||||
* FIX: contradiction in Vaul introduction text
|
||||
* FIX: localizations for CA, DE, ES, fa_IR, sl_SI, cs_CZ, pt_BR
|
||||
|
|
|
@ -1 +1 @@
|
|||
BlueWallet - Bitcoin portomonnee
|
||||
BlueWallet Bitcoin portomonnee
|
|
@ -137,7 +137,7 @@
|
|||
"ask_yes": "Ja, habe ich.",
|
||||
"ok": "Ja, ich habe sie aufgeschrieben!",
|
||||
"ok_lnd": "Die Sicherung ist erstellt.",
|
||||
"text": "Nimm Dir Zeit die mnemonischen Wörter zur späteren Wiederherstellung des Wallets auf ein Papier zu schreiben. Die Wörter sind dein einziges Backup im Fall eines Geräteverlustes.",
|
||||
"text": "Nimm Dir Zeit die mnemonische Phrase zur späteren Wiederherstellung auf Papier zu schreiben. Die Wörter sind dein Backup im Fall eines Geräteverlustes.",
|
||||
"text_lnd": "Zur Wiederherstellung des Wallet im Verlustfall bitte dieses Wallet-Backup sichern. ",
|
||||
"text_lnd2": "Diese Wallet wird durch BlueWallet verwaltet.",
|
||||
"title": "Dein Wallet ist erstellt."
|
||||
|
@ -274,7 +274,9 @@
|
|||
"electrum_clear_alert_ok": "Ok",
|
||||
"electrum_select": "Auswählen",
|
||||
"electrum_reset": "Auf Standard zurücksetzen",
|
||||
"electrum_unable_to_connect": "Verbindung zu {Server} kann nicht hergestellt werden.",
|
||||
"electrum_history": "Serverhistorie",
|
||||
"electrum_reset_to_default": "Sollen die Electrum-Einstellungen wirklich auf die Standardwerte zurückgesetzt werden?",
|
||||
"electrum_clear": "Löschen",
|
||||
"encrypt_decrypt": "Speicher entschlüsseln",
|
||||
"encrypt_decrypt_q": "Willst du die Speicherverschlüsselung wirklich aufheben? Hiermit wird dein Wallet ohne Passwortschutz direkt benutzbar. ",
|
||||
|
@ -329,7 +331,7 @@
|
|||
"ask_me_later": "Später erneut fragen"
|
||||
},
|
||||
"transactions": {
|
||||
"cancel_explain": "BlueWallet ersetzt diese Transaktion durch eine Transaktion mit höherer Gebühr, welche den Betrag an Dich zurücküberweist. Die Transaktion wird dadurch effektiv abgebrochen. Dies wird RBF genannt - Replace By Fee.",
|
||||
"cancel_explain": "BlueWallet ersetzt diese Transaktion durch eine mit höherer Gebühr, welche den Betrag an Dich zurücküberweist. Die Transaktion wird dadurch effektiv abgebrochen. Dies wird RBF - Replace By Fee - genannt.",
|
||||
"cancel_no": "Diese Transaktion ist nicht ersetzbar.",
|
||||
"cancel_title": "Diese Transaktion abbrechen (RBF)",
|
||||
"confirmations_lowercase": "{confirmations} Bestätigungen",
|
||||
|
@ -349,7 +351,7 @@
|
|||
"details_inputs": "Eingänge",
|
||||
"details_outputs": "Ausgänge",
|
||||
"details_received": "Empfangen",
|
||||
"transaction_note_saved":"Transaktionsbezeichnung erfolgreich gespeichert.",
|
||||
"transaction_note_saved": "Transaktionsbezeichnung erfolgreich gespeichert.",
|
||||
"details_show_in_block_explorer": "Im Block-Explorer zeigen",
|
||||
"details_title": "Transaktion",
|
||||
"details_to": "Ausgehend",
|
||||
|
@ -363,7 +365,7 @@
|
|||
"status_bump": "TRX-Gebühr erhöhen",
|
||||
"status_cancel": "Transaktion abbrechen",
|
||||
"transactions_count": "Anzahl Transaktionen",
|
||||
"txid": "TX-ID",
|
||||
"txid": "Transaktions-ID",
|
||||
"updating": "Aktualisiere...."
|
||||
},
|
||||
"wallets": {
|
||||
|
@ -415,7 +417,7 @@
|
|||
"export_title": "Wallet exportieren",
|
||||
"import_do_import": "Importieren",
|
||||
"import_error": "Fehler beim Import. Ist die Eingabe korrekt?",
|
||||
"import_explanation": "Gib hier die mnemonische Phrase, den privaten Schlüssel, WIF oder was immer Du hast ein. BlueWallet wird bestmöglich das Format interpretieren und die Wallet importieren. Bei Eingabe eines öffentlichen Schlüssels wird ein \"Watch-only\" Wallet hinzugefügt.",
|
||||
"import_explanation": "Gib hier die mnemonische Phrase, den privaten Schlüssel, WIF oder was immer Du hast ein. BlueWallet wird bestmöglich das Format interpretieren und die Wallet importieren.",
|
||||
"import_file": "Datei importieren",
|
||||
"import_imported": "Importiert",
|
||||
"import_placeholder_fail": "Wallet importieren",
|
||||
|
@ -428,7 +430,7 @@
|
|||
"list_create_a_wallet_text": "Wallets sind kostenlos. \nErstelle so viel du magst.",
|
||||
"list_empty_txs1": "Deine Transaktionen erscheinen hier",
|
||||
"list_empty_txs1_lightning": "Verwende das Lightning Wallet für Deine täglichen Bezahlungen. Lightning Transaktionen sind konkurrenzlos günstig und verblüffend schnell.",
|
||||
"list_empty_txs2": "Noch keine Transaktionen",
|
||||
"list_empty_txs2": "Beginne mit deinem Wallet.",
|
||||
"list_empty_txs2_lightning": "\nDrücke zum Starten «Beträge verwalten», um das Wallet aufzuladen.",
|
||||
"list_header": "Eine Wallet beinhaltet ein Schlüsselpaar - einen privaten Schlüssel und einen öffentlichen, welcher veröffentlicht werden kann, um Zahlungen zu erhalten.",
|
||||
"list_import_error": "Beim Versuch, diese Wallet zu importieren, ist ein Fehler aufgetreten. ",
|
||||
|
|
|
@ -180,7 +180,7 @@
|
|||
"details_amount_field_is_not_valid": "The amount is not valid.",
|
||||
"details_amount_field_is_less_than_minimum_amount_sat": "The specified amount is too small. Please enter an amount greater than 500 sats.",
|
||||
"details_create": "Create Invoice",
|
||||
"details_error_decode": "Error: Unable to decode Bitcoin address",
|
||||
"details_error_decode": "Unable to decode Bitcoin address",
|
||||
"details_fee_field_is_not_valid": "The fee is not valid.",
|
||||
"details_next": "Next",
|
||||
"details_no_maximum": "The selected wallet doesn’t support automatic maximum balance calculation. Are you sure to want to select this wallet?",
|
||||
|
@ -189,6 +189,7 @@
|
|||
"details_note_placeholder": "Note to Self",
|
||||
"details_scan": "Scan",
|
||||
"details_total_exceeds_balance": "The sending amount exceeds the available balance.",
|
||||
"details_unrecognized_file_format": "Unrecognized file format",
|
||||
"details_wallet_before_tx": "Before creating a transaction, you must first add a Bitcoin wallet.",
|
||||
"details_wallet_selection": "Wallet Selection",
|
||||
"dynamic_init": "Initializing",
|
||||
|
|
15
loc/fa.json
15
loc/fa.json
|
@ -180,7 +180,7 @@
|
|||
"details_amount_field_is_not_valid": "مقدار معتبر نیست.",
|
||||
"details_amount_field_is_less_than_minimum_amount_sat": "مقدار تعیینشده بسیار کم است. لطفاً مقداری بیشتر از ۵۰۰ ساتوشی را وارد کنید.",
|
||||
"details_create": "ایجاد صورتحساب",
|
||||
"details_error_decode": "خطا: ناموفق در رمزگشایی آدرس بیتکوین",
|
||||
"details_error_decode": "ناموفق در رمزگشایی آدرس بیتکوین",
|
||||
"details_fee_field_is_not_valid": "کارمزد معتبر نیست.",
|
||||
"details_next": "بعدی",
|
||||
"details_no_maximum": "کیف پول انتخابشده از محاسبهٔ خودکار حداکثر موجودی پشتیبانی نمیکند. آیا مطمئن هستید که میخواهید این کیف پول را انتخاب کنید؟",
|
||||
|
@ -189,6 +189,7 @@
|
|||
"details_note_placeholder": "یادداشت به خود",
|
||||
"details_scan": "اسکن",
|
||||
"details_total_exceeds_balance": "مقدار ارسالی بیش از ماندهٔ موجود است.",
|
||||
"details_unrecognized_file_format": "قالب فایل ناشناخته",
|
||||
"details_wallet_before_tx": "قبل از ایجاد تراکنش، ابتدا باید یک کیف پول بیتکوین اضافه کنید.",
|
||||
"details_wallet_selection": "انتخاب کیف پول",
|
||||
"dynamic_init": "درحال راهاندازی",
|
||||
|
@ -274,7 +275,9 @@
|
|||
"electrum_clear_alert_ok": "بله",
|
||||
"electrum_select": "انتخاب",
|
||||
"electrum_reset": "بازنشانی به پیشفرض",
|
||||
"electrum_unable_to_connect": "ناموفق در اتصال به {server}",
|
||||
"electrum_history": "تاریخچهٔ سرورها",
|
||||
"electrum_reset_to_default": "آیا مطمئن هستید که میخواهید تنظیمات الکترام را به حالت پیشفرض بازنشانی کنید؟",
|
||||
"electrum_clear": "پاککردن",
|
||||
"encrypt_decrypt": "رمزگشایی فضای ذخیرهسازی",
|
||||
"encrypt_decrypt_q": "آیا مطمئن هستید که میخواهید فضای ذخیرهسازی خود را رمزگشایی کنید؟ این کار اجازه میدهد تا کیف پولهای شما بدون گذرواژه قابلدسترسی باشند.",
|
||||
|
@ -333,6 +336,10 @@
|
|||
"cancel_no": "این تراکنش قابلجایگزینی نیست.",
|
||||
"cancel_title": "این تراکنش را لغو کن (RBF)",
|
||||
"confirmations_lowercase": "{confirmations} تأیید",
|
||||
"transaction_id": "شناسهٔ تراکنش",
|
||||
"note": "یادداشت",
|
||||
"expand_note": "نمایش کامل یادداشت",
|
||||
"block_explorer_link": "لینک مرورگر بلاک",
|
||||
"cpfp_create": "ایجاد",
|
||||
"cpfp_exp": "ما تراکنش دیگری را ایجاد خواهیم کرد که تراکنش تأییدنشدهٔ شما را خرج میکند. کارمزد کل بالاتر از کارمزد تراکنش اصلی خواهد بود، بنابراین سریعتر استخراج میشود. این کار Child Pays for Parent (بهاختصار CPFP) نام دارد—فرزند بهجای والدین میپردازد.",
|
||||
"cpfp_no_bump": "این تراکنش قابلیت افزایش کارمزد ندارد.",
|
||||
|
@ -345,7 +352,7 @@
|
|||
"details_inputs": "ورودیها",
|
||||
"details_outputs": "خروجیها",
|
||||
"details_received": "دریافتشده",
|
||||
"transaction_note_saved":"یادداشت تراکنش با موفقیت ذخیره شد.",
|
||||
"transaction_note_saved": "یادداشت تراکنش با موفقیت ذخیره شد.",
|
||||
"details_show_in_block_explorer": "مشاهده در مرورگر بلاک",
|
||||
"details_title": "تراکنش",
|
||||
"details_to": "خروجی",
|
||||
|
@ -411,7 +418,7 @@
|
|||
"export_title": "صادرکردن کیف پول",
|
||||
"import_do_import": "واردکردن",
|
||||
"import_error": "واردکردن ناموفق بود. لطفاً از معتبربودن دادهٔ ارائهشده اطمینان حاصل کنید.",
|
||||
"import_explanation": "عبارت یادیار (mnemonic phrase)، کلید خصوصی، WIF، یا هر چیزی را که دارید اینجا بنویسید. BlueWallet تمام تلاش خود را برای حدسزدن قالب صحیح و واردکردن کیف پول شما انجام خواهد داد. درصورت واردکردن کلید عمومی، ما آن را بهصورت کیف پول watch-only اضافه خواهیم کرد.",
|
||||
"import_explanation": "لطفاً کلمههای سید، کلید عمومی، WIF، یا هر چیزی را که دارید وارد کنید. BlueWallet تمام تلاش خود را برای حدسزدن قالب صحیح و واردکردن کیف پول شما انجام خواهد داد.",
|
||||
"import_file": "واردکردن فایل",
|
||||
"import_imported": "وارد شد",
|
||||
"import_placeholder_fail": "واردکردن کیف پول",
|
||||
|
@ -424,7 +431,7 @@
|
|||
"list_create_a_wallet_text": "مجانی است، و میتوانید هر تعداد\nکه دوست داشتید بسازید.",
|
||||
"list_empty_txs1": "تراکنشهای شما در اینجا نمایش داده خواهند شد.",
|
||||
"list_empty_txs1_lightning": "برای تراکنشهای روزمره بهتر است از کیف پول لایتنینگ استفاده شود. کارمزدها بهطرز غیرمنصفانهای ارزان و سرعت فوقالعاده بالاست.",
|
||||
"list_empty_txs2": "با کیف پول خود شروع کنید",
|
||||
"list_empty_txs2": "با کیف پول خود شروع کنید.",
|
||||
"list_empty_txs2_lightning": "\nبرای شروع استفاده، روی «مدیریت دارایی» بزنید و موجودی خود را شارژ کنید.",
|
||||
"list_header": "کیف پول نشانگر یک جفت کلید است—یکی خصوصی و یکی که میتوانید آن را برای دریافت بیتکوین بهاشتراک بگذارید.",
|
||||
"list_import_error": "خطایی هنگام تلاش برای واردکردن این کیف پول رخ داد.",
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
"save": "Tallenna",
|
||||
"seed": "Siemen",
|
||||
"wallet_key": "Lompakkoavain",
|
||||
"invalid_animated_qr_code_fragment": "Virheellinen animoitu QRCode-fragmentti, yritä uudelleen",
|
||||
"invalid_animated_qr_code_fragment" : "Virheellinen animoitu QRCode-fragmentti, yritä uudelleen",
|
||||
"file_saved": "Tiedosto ({filePath}) on tallennettu Lataukset-kansioon.",
|
||||
"discard_changes": "Hylkää muutokset?",
|
||||
"discard_changes_detail": "Sinulla on tallentamattomia muutoksia. Haluatko varmasti hylätä ne ja poistut näytöltä? "
|
||||
|
@ -137,7 +137,7 @@
|
|||
"ask_yes": "Kyllä, olen",
|
||||
"ok": "OK, kirjoitan tämän ylös!",
|
||||
"ok_lnd": "OK, olen tallentanut sen.",
|
||||
"text": "Ole hyvä ja ota hetki kirjoittaaksesi tämä muistilauseke paperille. Se on varmuuskopio, jonka avulla voit palauttaa lompakon toisella laitteella.",
|
||||
"text": "Käytä hetki muistilausekkeen kirjoittamiseen paperille. Se on varmuuskopiosi, jolla voit palauttaa lompakon toisella laitteella. ",
|
||||
"text_lnd": "Tallenna tämä lompakon varmuuskopio. Sen avulla voit palauttaa lompakon, jos lompakko katoaa.",
|
||||
"text_lnd2": "Tätä lompakkoa ylläpitää BlueWallet.",
|
||||
"title": "Lompakkosi on luotu"
|
||||
|
@ -274,7 +274,9 @@
|
|||
"electrum_clear_alert_ok": "Ok",
|
||||
"electrum_select": "Valitse",
|
||||
"electrum_reset": "Palauta oletusasetuksiin",
|
||||
"electrum_unable_to_connect": " Ei saada yhteyttä {server}. ",
|
||||
"electrum_history": "Palvelimen historia",
|
||||
"electrum_reset_to_default": "Haluatko varmasti palauttaa Electrumin asetukset oletusarvoihin? ",
|
||||
"electrum_clear": "Tyhjennä",
|
||||
"encrypt_decrypt": "Pura tallennustilan salaus",
|
||||
"encrypt_decrypt_q": "Haluatko varmasti purkaa tallennustilan salauksen? Tämä mahdollistaa lompakkoihisi pääsyn ilman salasanaa.",
|
||||
|
@ -302,7 +304,7 @@
|
|||
"network_electrum": "Electrum-palvelin",
|
||||
"not_a_valid_uri": "URI ei kelpaa",
|
||||
"notifications": "Ilmoitukset",
|
||||
"open_link_in_explorer": "Avaa linkki selaimessa",
|
||||
"open_link_in_explorer" : "Avaa linkki selaimessa",
|
||||
"password": "Salasana",
|
||||
"password_explain": "Luo salasana, jota käytät tallennustilan salauksen purkamiseen",
|
||||
"passwords_do_not_match": "Salasanat eivät täsmää",
|
||||
|
@ -318,7 +320,7 @@
|
|||
"retype_password": "Salasana uudelleen",
|
||||
"save": "Tallenna",
|
||||
"saved": "Tallennettu",
|
||||
"success_transaction_broadcasted": "Onnistui! Siirtotapahtumasi on lähetetty!",
|
||||
"success_transaction_broadcasted" : "Onnistui! Siirtotapahtumasi on lähetetty!",
|
||||
"total_balance": "Kokonaissaldo",
|
||||
"total_balance_explanation": "Näytä kaikkien lompakoiden kokonaissaldo aloitusnäytön widgeteissä.",
|
||||
"widgets": "Widgetit"
|
||||
|
@ -329,10 +331,14 @@
|
|||
"ask_me_later": "Kysy Minulta Myöhemmin"
|
||||
},
|
||||
"transactions": {
|
||||
"cancel_explain": "Korvaamme tämän siirtotapahtuman sillä, joka maksaa sinulle ja on korkeammat siirtokulut. Tämä peruuttaa siirtotapahtuman tehokkaasti. Tätä kutsutaan RBF - Replace By Fee - Korvaa korkeammilla kuluilla.",
|
||||
"cancel_explain": "Korvaamme tämän siirtotapahtuman sillä, joka maksaa sinulle ja jossa on korkeammat siirtokulut. Tämä peruu siirtotapahtuman käytännössä. Tätä kutsutaan RBF - Replace By Fee. ",
|
||||
"cancel_no": "Tämä siirtotapahtuma ei ole vaihdettavissa",
|
||||
"cancel_title": "Peruuta tämä siirtotapahtuma (RBF)",
|
||||
"confirmations_lowercase": "{confirmations} vahvistukset",
|
||||
"transaction_id": "Siirtotapahtuman tunnus",
|
||||
"note": "Huomautus",
|
||||
"expand_note": "Laajenna huomautus",
|
||||
"block_explorer_link": "Lohkoselain-linkki",
|
||||
"cpfp_create": "Luo",
|
||||
"cpfp_exp": "Luomme toisen siirtotapahtuman, joka kuluttaa vahvistamattoman siirtotapahtuman. Kokonaiskulu on suurempi kuin alkuperäinen siirtokulu, joten sen pitäisi olla louhittu nopeammin. Tätä kutsutaan CPFP - Child Pays For Parent - Lapsi Maksaa Vanhemmalle.",
|
||||
"cpfp_no_bump": "Tämä siirtotapahtuma ei ole nostettavissa",
|
||||
|
@ -359,7 +365,7 @@
|
|||
"status_bump": "Nosta siirtokuluja",
|
||||
"status_cancel": "Peruuta Siirtotapahtuma",
|
||||
"transactions_count": "siirtotapahtumien määrä",
|
||||
"txid": "Siirtotunniste",
|
||||
"txid": "Siirtotapahtuman tunnus",
|
||||
"updating": "Päivitetään..."
|
||||
},
|
||||
"wallets": {
|
||||
|
@ -411,7 +417,7 @@
|
|||
"export_title": "lompakon vienti",
|
||||
"import_do_import": "Tuo",
|
||||
"import_error": "Tuonti epäonnistui. Varmista, että annettu tieto on oikein",
|
||||
"import_explanation": "Kirjoita tähän muistilauseke, yksityinen avain, WIF tai mikä tahansa sinulla on. BlueWallet tekee parhaansa arvatakseen oikean muodon ja tuodakseen lompakkosi. Jos syötetään julkinen avain, lisätään se vain katselu-lompakoksi.",
|
||||
"import_explanation": "Kirjoita siemensanasi, julkinen avain, WIF tai mikä tahansa sinulla on. BlueWallet tekee parhaansa arvatakseen oikean formaatin ja tuodakseen lompakkosi. ",
|
||||
"import_file": "Tuo tiedosto",
|
||||
"import_imported": "Tuotu",
|
||||
"import_placeholder_fail": "Lompakon tuonti",
|
||||
|
@ -424,7 +430,7 @@
|
|||
"list_create_a_wallet_text": "Se on ilmainen ja voit luoda\nniin monta kuin haluat",
|
||||
"list_empty_txs1": "Siirtotapahtumasi näkyvät tässä,",
|
||||
"list_empty_txs1_lightning": "Lightning-lompakkoa tulisi käyttää päivittäisiin siirtotapahtumiin. Siirtokulut ovat kohtuuttoman halpoja ja nopeus on liekehtivän kova.",
|
||||
"list_empty_txs2": "Aloita lompakostasi",
|
||||
"list_empty_txs2": "Aloita lompakostasi. ",
|
||||
"list_empty_txs2_lightning": "Aloita sen käyttäminen napsauttamalla \"hallinnoi varoja\" ja lisää saldoasi.\n",
|
||||
"list_header": "Lompakko edustaa avainparia, yhtä yksityistä ja yhtä, jonka voit jakaa vastaanottaaksesi kolikoita.",
|
||||
"list_import_error": "Tämän lompakon tuomisessa tapahtui virhe.",
|
||||
|
@ -468,7 +474,7 @@
|
|||
"share": "Jaa",
|
||||
"view": "Näytä",
|
||||
"manage_keys": "Hallitse Avaimia",
|
||||
"how_many_signatures_can_bluewallet_make": "kuinka monta allekirjoitusta bluewallet voi tehdä",
|
||||
"how_many_signatures_can_bluewallet_make": "kuinka monta allekirjoitusta BlueWallet voi tehdä",
|
||||
"signatures_required_to_spend": "Vaaditaan allekirjoituksia {number}",
|
||||
"signatures_we_can_make": "voidaan tehdä {number}",
|
||||
"scan_or_import_file": "Skannaa tai tuo tiedosto",
|
||||
|
|
|
@ -274,7 +274,9 @@
|
|||
"electrum_clear_alert_ok": "Ok",
|
||||
"electrum_select": "Selectionner",
|
||||
"electrum_reset": "Réinitialiser au valeurs par défaut",
|
||||
"electrum_unable_to_connect": "Impossible de se connecter à {server}.",
|
||||
"electrum_history": "Historique de serveur",
|
||||
"electrum_reset_to_default": "Etes-vous sûr de vouloir réinitialiser vos paramètres Electrum ?",
|
||||
"electrum_clear": "Effacer",
|
||||
"encrypt_decrypt": "Déchiffrer le stockage",
|
||||
"encrypt_decrypt_q": "Etes-vous sûr de vouloir déchiffrer le stockage ? L'accès à vos portefeuilles pourra alors se faire sans mot de passe.",
|
||||
|
@ -329,10 +331,14 @@
|
|||
"ask_me_later": "Me demander plus tard"
|
||||
},
|
||||
"transactions": {
|
||||
"cancel_explain": "Nous allons remplacer cette transaction par celle où les fonds vous reviennet et a de plus hauts frais. Cela annulera la transaction. On parle de RBF - Replace By Fee.",
|
||||
"cancel_explain": "Nous allons remplacer cette transaction par celle où les fonds vous reviennent, avec de plus hauts frais. Cela annulera la transaction. On parle de RBF - Replace By Fee.",
|
||||
"cancel_no": "Cette transaction n'est pas remplaçable",
|
||||
"cancel_title": "Annuler cette transaction (RBF)",
|
||||
"confirmations_lowercase": "{confirmations} confirmations",
|
||||
"transaction_id": "ID de transaction",
|
||||
"note": "Note",
|
||||
"expand_note": "Développer la note",
|
||||
"block_explorer_link": "Lien vers l'explorateur de blocs",
|
||||
"cpfp_create": "Créer",
|
||||
"cpfp_exp": "Nous allons créer une autre transaction qui dépense votre transaction non-confirmée. Les frais totaux seront supérieurs aux frais de la transaction originale, donc cela devrait être miné plus rapidement. On parle de CPFP - Child Pays For Parent.",
|
||||
"cpfp_no_bump": "Cette transaction n'est pas propulsable",
|
||||
|
@ -345,7 +351,7 @@
|
|||
"details_inputs": "Inputs",
|
||||
"details_outputs": "Outputs",
|
||||
"details_received": "Reçu",
|
||||
"transaction_note_saved":"La note de transaction a été enregistrée avec succès.",
|
||||
"transaction_note_saved": "La note de transaction a été enregistrée avec succès.",
|
||||
"details_show_in_block_explorer": "Afficher dans le \"block explorer\"",
|
||||
"details_title": "Transaction",
|
||||
"details_to": "À",
|
||||
|
@ -359,7 +365,7 @@
|
|||
"status_bump": "Frais de propulsion",
|
||||
"status_cancel": "Annuler la transaction",
|
||||
"transactions_count": "Nombre de transactions",
|
||||
"txid": "Txid",
|
||||
"txid": "ID de transaction",
|
||||
"updating": "Chargement..."
|
||||
},
|
||||
"wallets": {
|
||||
|
@ -411,7 +417,7 @@
|
|||
"export_title": "export du portefeuille",
|
||||
"import_do_import": "Importer",
|
||||
"import_error": "Échec de l'import. Merci, de vérifier que les données saisies sont valides.",
|
||||
"import_explanation": "Écrivez ici vos mnémonique, clés privés, WIF ou tout simplement ce que vous avez. Bluewallet fera de son mieux pour détecter automatiquement le bon format. Si c'est une clé publique, nous créerons une portefeuille en lecture seul. ",
|
||||
"import_explanation": "Entrez ici votre mnémonique, clé privée, WIF, ou quoi que ce soit que vous ayez. BlueWallet fera de son mieux pour deviner le bon format et importer votre portefeuille",
|
||||
"import_file": "Importer le fichier",
|
||||
"import_imported": "Importé",
|
||||
"import_placeholder_fail": "Importation de portefeuille",
|
||||
|
@ -424,7 +430,7 @@
|
|||
"list_create_a_wallet_text": "Cest gratuit et vous pouvez en créer \nautant que vous voulez.",
|
||||
"list_empty_txs1": "Vos transactions apparaîtront ici,",
|
||||
"list_empty_txs1_lightning": "Un portefeuille Lightning devrait être utilisé pour les transactions quotidiennes. Les frais sont très bas et la vitesse est étourdissante.",
|
||||
"list_empty_txs2": "Aucune pour le moment",
|
||||
"list_empty_txs2": "Commencez avec votre portefeuille.",
|
||||
"list_empty_txs2_lightning": "\nPour commencer à l'utiliser taper sur \"Gérer les fonds\" et alimentez votre solde.",
|
||||
"list_header": "Un portefeuille (wallet) représente une paire de clés, une privée et une publique que vous pouvez partager pour recevoir des fonds. ",
|
||||
"list_import_error": "Une erreur est survenue lors de la tentative d'import du portefeuille.",
|
||||
|
@ -468,7 +474,7 @@
|
|||
"share": "Partager",
|
||||
"view": "Vue",
|
||||
"manage_keys": "Gérer les clés",
|
||||
"how_many_signatures_can_bluewallet_make": "Combien de signature peut faire bluewallet",
|
||||
"how_many_signatures_can_bluewallet_make": "Combien de signatures BlueWallet peut-il faire",
|
||||
"signatures_required_to_spend": "Signatures necessaires {number}",
|
||||
"signatures_we_can_make": "peut faire {number}",
|
||||
"scan_or_import_file": "Scanner ou importer fichier",
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
export class BitcoinTransaction {
|
||||
/**
|
||||
*
|
||||
* @param address
|
||||
* @param amount {number}
|
||||
* @param amountSats {integer} satoshi
|
||||
*/
|
||||
constructor(address = '', amount, amountSats) {
|
||||
this.address = address;
|
||||
this.amount = amount;
|
||||
this.amountSats = amountSats;
|
||||
}
|
||||
}
|
52
package-lock.json
generated
52
package-lock.json
generated
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "bluewallet",
|
||||
"version": "6.0.6",
|
||||
"version": "6.0.7",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
@ -5337,6 +5337,11 @@
|
|||
"deep-assign": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"@react-native-clipboard/clipboard": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-clipboard/clipboard/-/clipboard-1.7.0.tgz",
|
||||
"integrity": "sha512-i5dJgR+wM8Om+hFEB/PqNb65/x5WxpaZG+UjEBX2/gmmIrmAWI72tI9rVL1gjPA9RWNpdpzvp+ioGjpdl7MyWQ=="
|
||||
},
|
||||
"@react-native-community/blur": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-community/blur/-/blur-3.6.0.tgz",
|
||||
|
@ -5682,11 +5687,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-4.10.1.tgz",
|
||||
"integrity": "sha512-ael2f1onoPF3vF7YqHGWy7NnafzGu+yp88BbFbP0ydoCP2xGSUzmZVw0zakPTC040Id+JQ9WeFczujMkDy6jYQ=="
|
||||
},
|
||||
"@react-native-community/clipboard": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-community/clipboard/-/clipboard-1.5.1.tgz",
|
||||
"integrity": "sha512-AHAmrkLEH5UtPaDiRqoULERHh3oNv7Dgs0bTC0hO5Z2GdNokAMPT5w8ci8aMcRemcwbtdHjxChgtjbeA38GBdA=="
|
||||
},
|
||||
"@react-native-community/eslint-config": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-community/eslint-config/-/eslint-config-2.0.0.tgz",
|
||||
|
@ -7343,10 +7343,12 @@
|
|||
"integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
|
||||
},
|
||||
"bc-bech32": {
|
||||
"version": "file:blue_modules/bc-bech32"
|
||||
"version": "file:blue_modules/bc-bech32",
|
||||
"integrity": "sha512-lwAn5R4LUhcnyrZgNx3YdDPr5+nseM4kARANcv8i0YOMtnPJRTF7B7TZzS3DYgC6tff/aR2W/3jGoY/SJMs6MA=="
|
||||
},
|
||||
"bc-ur": {
|
||||
"version": "file:blue_modules/bc-ur"
|
||||
"version": "file:blue_modules/bc-ur",
|
||||
"integrity": "sha512-k5jZLNgiCMQH5d/4lwsa6DJjH12vzdTEr9qVH1y9UPzJW32Ga1u8iC0KDAqtYnkvh8NR4DW8Fco6D2hphHZLzg=="
|
||||
},
|
||||
"bcrypt-pbkdf": {
|
||||
"version": "1.0.2",
|
||||
|
@ -8730,9 +8732,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"detox": {
|
||||
"version": "18.2.2",
|
||||
"resolved": "https://registry.npmjs.org/detox/-/detox-18.2.2.tgz",
|
||||
"integrity": "sha512-+4foyz7HraKWAHavkmN4QKaWVUcWdqdnI5ftak1ilIloZaZPGHuIe1ymRC2xoWtpdIpvW6mRJkhm7TeJrZW9HA==",
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/detox/-/detox-18.3.1.tgz",
|
||||
"integrity": "sha512-eYvBTkJ0bvBcaWxubQBhRk+sT0Yd21npebd/s25BFrfB+8Ts4ctGASXh2uqlHkvCzUIDzRTEgFLu9I5k3g89Fw==",
|
||||
"requires": {
|
||||
"bunyan": "^1.8.12",
|
||||
"bunyan-debug-stream": "^1.1.0",
|
||||
|
@ -8851,9 +8853,9 @@
|
|||
"integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg=="
|
||||
},
|
||||
"string-width": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
|
||||
"integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
|
||||
"integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
|
||||
"requires": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
|
@ -8898,9 +8900,9 @@
|
|||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "20.2.4",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
|
||||
"integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA=="
|
||||
"version": "20.2.6",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.6.tgz",
|
||||
"integrity": "sha512-AP1+fQIWSM/sMiET8fyayjx/J+JmTPt2Mr0FkrgqB4todtfa53sOsrSAcIrJRD5XS20bKUwaDIuMkWKCEiQLKA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -18388,9 +18390,9 @@
|
|||
"from": "react-native-blue-crypto@git+https://github.com/Overtorment/react-native-blue-crypto.git"
|
||||
},
|
||||
"react-native-camera": {
|
||||
"version": "3.42.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-camera/-/react-native-camera-3.42.0.tgz",
|
||||
"integrity": "sha512-DFsZeRy9TKP/pGef5iLX1AWxP9eAnlbGcA76fEoFXse6EP56sdgjYe+wudJsGZ//arGrYBqjq6wog13HMsJaoQ==",
|
||||
"version": "3.42.2",
|
||||
"resolved": "https://registry.npmjs.org/react-native-camera/-/react-native-camera-3.42.2.tgz",
|
||||
"integrity": "sha512-sqeVZiHP3hDdSVlVTM62Nry9+Enff06IqicK2bth+NKWPccwOHw4QXLMf7M5rpGFAIfbSGCcy0U1r+biv6R6rw==",
|
||||
"requires": {
|
||||
"prop-types": "^15.6.2"
|
||||
}
|
||||
|
@ -18446,11 +18448,12 @@
|
|||
}
|
||||
},
|
||||
"react-native-gesture-handler": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-1.9.0.tgz",
|
||||
"integrity": "sha512-fkkNeWDBzDdwDxDcxtYbrb9T1g0PLgT1AxBs2iO/p7uEbDbC6mIoL/NzuOnKNEBHcd0lpLoJuNmIfdmucEON5g==",
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-1.10.0.tgz",
|
||||
"integrity": "sha512-ezqA2Hyy6pFF7uxRZA8TeRUZs4zMo5DQQjo0UfFVJyAqjMraDkbz+t/uCfyBowrnOyOiNAhPHB85k6vgPvlZ+g==",
|
||||
"requires": {
|
||||
"@egjs/hammerjs": "^2.0.17",
|
||||
"@types/hammerjs": "^2.0.38",
|
||||
"fbjs": "^3.0.0",
|
||||
"hoist-non-react-statics": "^3.3.0",
|
||||
"invariant": "^2.2.4",
|
||||
|
@ -19557,7 +19560,8 @@
|
|||
}
|
||||
},
|
||||
"scryptsy": {
|
||||
"version": "file:blue_modules/scryptsy"
|
||||
"version": "file:blue_modules/scryptsy",
|
||||
"integrity": "sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w=="
|
||||
},
|
||||
"secp256k1": {
|
||||
"version": "3.8.0",
|
||||
|
|
12
package.json
12
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "bluewallet",
|
||||
"version": "6.0.6",
|
||||
"version": "6.0.7",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -48,7 +48,7 @@
|
|||
"e2e:debug-test": "detox test -c android.emu.debug",
|
||||
"e2e:debug": "(test -f android/app/build/outputs/apk/debug/app-debug.apk && test -f android/app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk) || npm run e2e:debug-build; npm run e2e:debug-test",
|
||||
"e2e:release-build": "npx detox build -c android.emu.release",
|
||||
"e2e:release-test": "detox test -c android.emu.release --record-videos all --take-screenshots all --headless",
|
||||
"e2e:release-test": "detox test -c android.emu.release --record-videos all --take-screenshots all --headless --loglevel trace",
|
||||
"lint": "eslint *.js screen/**/*.js blue_modules/*.js class/**/*.js models/ loc/ tests/**/*.js components/**/*.js",
|
||||
"lint:fix": "npm run lint -- --fix",
|
||||
"lint:quickfix": "git status --porcelain | grep -v '\\.json' | grep '\\.js' --color=never | awk '{print $2}' | xargs eslint --fix; exit 0",
|
||||
|
@ -72,8 +72,8 @@
|
|||
"dependencies": {
|
||||
"@babel/preset-env": "7.12.1",
|
||||
"@react-native-async-storage/async-storage": "1.13.4",
|
||||
"@react-native-clipboard/clipboard": "1.7.0",
|
||||
"@react-native-community/blur": "3.6.0",
|
||||
"@react-native-community/clipboard": "1.5.1",
|
||||
"@react-native-community/masked-view": "0.1.10",
|
||||
"@react-native-community/push-notification-ios": "1.8.0",
|
||||
"@react-native-community/slider": "3.0.3",
|
||||
|
@ -100,7 +100,7 @@
|
|||
"coinselect": "3.1.12",
|
||||
"crypto-js": "3.1.9-1",
|
||||
"dayjs": "1.10.4",
|
||||
"detox": "18.2.2",
|
||||
"detox": "18.3.1",
|
||||
"ecurve": "1.0.6",
|
||||
"electrum-client": "git+https://github.com/BlueWallet/rn-electrum-client.git#f9a827e724a5a2e578fdfdb483f83793af55b030",
|
||||
"electrum-mnemonic": "2.0.0",
|
||||
|
@ -125,14 +125,14 @@
|
|||
"react-localization": "1.0.15",
|
||||
"react-native": "0.63.3",
|
||||
"react-native-blue-crypto": "git+https://github.com/Overtorment/react-native-blue-crypto.git",
|
||||
"react-native-camera": "3.42.0",
|
||||
"react-native-camera": "3.42.2",
|
||||
"react-native-default-preference": "1.4.3",
|
||||
"react-native-device-info": "8.0.1",
|
||||
"react-native-document-picker": "git+https://github.com/BlueWallet/react-native-document-picker.git#3684d4fcc2bc0b47c32be39024e4796004c3e428",
|
||||
"react-native-elements": "2.3.2",
|
||||
"react-native-fingerprint-scanner": "git+https://github.com/BlueWallet/react-native-fingerprint-scanner.git#ce644673681716335d786727bab998f7e632ab5e",
|
||||
"react-native-fs": "2.16.6",
|
||||
"react-native-gesture-handler": "1.9.0",
|
||||
"react-native-gesture-handler": "1.10.0",
|
||||
"react-native-handoff": "git+https://github.com/marcosrdz/react-native-handoff.git#f5becc63f3e36bf2da1ed1fc60fc690323e73602",
|
||||
"react-native-haptic-feedback": "1.11.0",
|
||||
"react-native-idle-timer": "git+https://github.com/BlueWallet/react-native-idle-timer.git#8587876d68ab5920e79619726aeca9e672beaf2b",
|
||||
|
|
|
@ -18,14 +18,9 @@ import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
|
|||
import { Icon } from 'react-native-elements';
|
||||
import { useFocusEffect, useNavigation, useRoute, useTheme } from '@react-navigation/native';
|
||||
|
||||
import {
|
||||
BlueAlertWalletExportReminder,
|
||||
BlueBitcoinAmount,
|
||||
BlueButton,
|
||||
BlueDismissKeyboardInputAccessory,
|
||||
BlueLoading,
|
||||
} from '../../BlueComponents';
|
||||
import { BlueAlertWalletExportReminder, BlueButton, BlueDismissKeyboardInputAccessory, BlueLoading } from '../../BlueComponents';
|
||||
import navigationStyle from '../../components/navigationStyle';
|
||||
import AmountInput from '../../components/AmountInput';
|
||||
import * as NavigationService from '../../NavigationService';
|
||||
import { LightningCustodianWallet } from '../../class/wallets/lightning-custodian-wallet';
|
||||
import { BitcoinUnit, Chain } from '../../models/bitcoinUnits';
|
||||
|
@ -163,7 +158,7 @@ const LNDCreateInvoice = () => {
|
|||
break;
|
||||
case BitcoinUnit.LOCAL_CURRENCY:
|
||||
// trying to fetch cached sat equivalent for this fiat amount
|
||||
invoiceAmount = BlueBitcoinAmount.getCachedSatoshis(invoiceAmount) || currency.btcToSatoshi(currency.fiatToBTC(invoiceAmount));
|
||||
invoiceAmount = AmountInput.getCachedSatoshis(invoiceAmount) || currency.btcToSatoshi(currency.fiatToBTC(invoiceAmount));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -260,7 +255,7 @@ const LNDCreateInvoice = () => {
|
|||
break;
|
||||
case BitcoinUnit.LOCAL_CURRENCY:
|
||||
amount = formatBalancePlain(amount, BitcoinUnit.LOCAL_CURRENCY);
|
||||
BlueBitcoinAmount.setCachedSatoshis(amount, sats);
|
||||
AmountInput.setCachedSatoshis(amount, sats);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -362,7 +357,7 @@ const LNDCreateInvoice = () => {
|
|||
<StatusBar barStyle="light-content" />
|
||||
<View style={[styles.amount, styleHooks.amount]}>
|
||||
<KeyboardAvoidingView enabled={!Platform.isPad} behavior="position">
|
||||
<BlueBitcoinAmount
|
||||
<AmountInput
|
||||
isLoading={isLoading}
|
||||
amount={amount}
|
||||
onAmountUnitChange={setUnit}
|
||||
|
|
|
@ -6,9 +6,7 @@ import AsyncStorage from '@react-native-async-storage/async-storage';
|
|||
import { Image, ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
||||
import { Icon } from 'react-native-elements';
|
||||
|
||||
import navigationStyle from '../../components/navigationStyle';
|
||||
import {
|
||||
BlueBitcoinAmount,
|
||||
BlueButton,
|
||||
BlueCard,
|
||||
BlueDismissKeyboardInputAccessory,
|
||||
|
@ -17,6 +15,8 @@ import {
|
|||
BlueText,
|
||||
SafeBlueArea,
|
||||
} from '../../BlueComponents';
|
||||
import navigationStyle from '../../components/navigationStyle';
|
||||
import AmountInput from '../../components/AmountInput';
|
||||
import { BlueCurrentTheme } from '../../components/themes';
|
||||
import Lnurl from '../../class/lnurl';
|
||||
import { BitcoinUnit, Chain } from '../../models/bitcoinUnits';
|
||||
|
@ -160,7 +160,7 @@ export default class LnurlPay extends Component {
|
|||
<SafeBlueArea style={styles.root}>
|
||||
<ScrollView>
|
||||
<BlueCard>
|
||||
<BlueBitcoinAmount
|
||||
<AmountInput
|
||||
isLoading={this.state.isLoading}
|
||||
amount={this.state.amount.toString()}
|
||||
onAmountUnitChange={unit => {
|
||||
|
|
|
@ -15,16 +15,10 @@ import { Icon } from 'react-native-elements';
|
|||
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
|
||||
import { useFocusEffect, useNavigation, useRoute, useTheme } from '@react-navigation/native';
|
||||
|
||||
import {
|
||||
BlueButton,
|
||||
SafeBlueArea,
|
||||
BlueCard,
|
||||
BlueDismissKeyboardInputAccessory,
|
||||
BlueAddressInput,
|
||||
BlueBitcoinAmount,
|
||||
BlueLoading,
|
||||
} from '../../BlueComponents';
|
||||
import { BlueButton, BlueCard, BlueDismissKeyboardInputAccessory, BlueLoading, SafeBlueArea } from '../../BlueComponents';
|
||||
import navigationStyle from '../../components/navigationStyle';
|
||||
import AddressInput from '../../components/AddressInput';
|
||||
import AmountInput from '../../components/AmountInput';
|
||||
import { LightningCustodianWallet } from '../../class/wallets/lightning-custodian-wallet';
|
||||
import Lnurl from '../../class/lnurl';
|
||||
import { BitcoinUnit, Chain } from '../../models/bitcoinUnits';
|
||||
|
@ -296,7 +290,7 @@ const ScanLndInvoice = () => {
|
|||
<ScrollView contentContainerStyle={styles.scroll}>
|
||||
<KeyboardAvoidingView enabled behavior="position" keyboardVerticalOffset={20}>
|
||||
<View style={styles.scrollMargin}>
|
||||
<BlueBitcoinAmount
|
||||
<AmountInput
|
||||
pointerEvents={isAmountInitiallyEmpty ? 'auto' : 'none'}
|
||||
isLoading={isLoading}
|
||||
amount={amount}
|
||||
|
@ -309,7 +303,7 @@ const ScanLndInvoice = () => {
|
|||
</View>
|
||||
|
||||
<BlueCard>
|
||||
<BlueAddressInput
|
||||
<AddressInput
|
||||
onChangeText={text => {
|
||||
text = text.trim();
|
||||
processTextForInvoice(text);
|
||||
|
|
|
@ -21,7 +21,6 @@ import {
|
|||
SecondButton,
|
||||
BlueButtonLink,
|
||||
is,
|
||||
BlueBitcoinAmount,
|
||||
BlueText,
|
||||
BlueSpacing20,
|
||||
BlueAlertWalletExportReminder,
|
||||
|
@ -31,6 +30,7 @@ import BottomModal from '../../components/BottomModal';
|
|||
import Privacy from '../../blue_modules/Privacy';
|
||||
import { Chain, BitcoinUnit } from '../../models/bitcoinUnits';
|
||||
import HandoffComponent from '../../components/handoff';
|
||||
import AmountInput from '../../components/AmountInput';
|
||||
import DeeplinkSchemaMatch from '../../class/deeplink-schema-match';
|
||||
import loc from '../../loc';
|
||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||
|
@ -297,9 +297,9 @@ const ReceiveDetails = () => {
|
|||
amount = currency.satoshiToBTC(customAmount);
|
||||
break;
|
||||
case BitcoinUnit.LOCAL_CURRENCY:
|
||||
if (BlueBitcoinAmount.conversionCache[amount + 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(BlueBitcoinAmount.conversionCache[amount + BitcoinUnit.LOCAL_CURRENCY]);
|
||||
amount = currency.satoshiToBTC(AmountInput.conversionCache[amount + BitcoinUnit.LOCAL_CURRENCY]);
|
||||
} else {
|
||||
amount = currency.fiatToBTC(customAmount);
|
||||
}
|
||||
|
@ -314,12 +314,7 @@ const ReceiveDetails = () => {
|
|||
<BottomModal isVisible={isCustomModalVisible} onClose={dismissCustomAmountModal}>
|
||||
<KeyboardAvoidingView enabled={!Platform.isPad} behavior={Platform.OS === 'ios' ? 'position' : null}>
|
||||
<View style={styles.modalContent}>
|
||||
<BlueBitcoinAmount
|
||||
unit={customUnit}
|
||||
amount={customAmount || ''}
|
||||
onChangeText={setCustomAmount}
|
||||
onAmountUnitChange={setCustomUnit}
|
||||
/>
|
||||
<AmountInput unit={customUnit} amount={customAmount || ''} onChangeText={setCustomAmount} onAmountUnitChange={setCustomUnit} />
|
||||
<View style={styles.customAmount}>
|
||||
<TextInput
|
||||
onChangeText={setCustomLabel}
|
||||
|
|
|
@ -16,7 +16,7 @@ import {
|
|||
PermissionsAndroid,
|
||||
Alert,
|
||||
} from 'react-native';
|
||||
import Clipboard from '@react-native-community/clipboard';
|
||||
import Clipboard from '@react-native-clipboard/clipboard';
|
||||
import { Icon } from 'react-native-elements';
|
||||
import Share from 'react-native-share';
|
||||
import RNFS from 'react-native-fs';
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -14,7 +14,7 @@ import {
|
|||
Alert,
|
||||
findNodeHandle,
|
||||
} from 'react-native';
|
||||
import Clipboard from '@react-native-community/clipboard';
|
||||
import Clipboard from '@react-native-clipboard/clipboard';
|
||||
import Share from 'react-native-share';
|
||||
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
|
||||
import DocumentPicker from 'react-native-document-picker';
|
||||
|
|
|
@ -12,7 +12,7 @@ import {
|
|||
StyleSheet,
|
||||
KeyboardAvoidingView,
|
||||
} from 'react-native';
|
||||
import Clipboard from '@react-native-community/clipboard';
|
||||
import Clipboard from '@react-native-clipboard/clipboard';
|
||||
import { Text } from 'react-native-elements';
|
||||
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import navigationStyle from '../../components/navigationStyle';
|
|||
import HandoffComponent from '../../components/handoff';
|
||||
import loc from '../../loc';
|
||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||
import Clipboard from '@react-native-community/clipboard';
|
||||
import Clipboard from '@react-native-clipboard/clipboard';
|
||||
import ToolTipMenu from '../../components/TooltipMenu';
|
||||
const dayjs = require('dayjs');
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ import { Icon } from 'react-native-elements';
|
|||
import { useNavigation, useRoute, useTheme } from '@react-navigation/native';
|
||||
import { getSystemName } from 'react-native-device-info';
|
||||
import QRCode from 'react-native-qrcode-svg';
|
||||
import Clipboard from '@react-native-community/clipboard';
|
||||
import Clipboard from '@react-native-clipboard/clipboard';
|
||||
import showPopupMenu from 'react-native-popup-menu-android';
|
||||
import ToolTip from 'react-native-tooltip';
|
||||
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
|
||||
|
|
|
@ -22,13 +22,12 @@ import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
|
|||
import { PlaceholderWallet } from '../../class';
|
||||
import WalletImport from '../../class/wallet-import';
|
||||
import ActionSheet from '../ActionSheet';
|
||||
import Clipboard from '@react-native-community/clipboard';
|
||||
import Clipboard from '@react-native-clipboard/clipboard';
|
||||
import loc from '../../loc';
|
||||
import { FContainer, FButton } from '../../components/FloatButtons';
|
||||
import { isTablet } from 'react-native-device-info';
|
||||
import { useFocusEffect, useNavigation, useRoute, useTheme } from '@react-navigation/native';
|
||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||
import { isCatalyst, isMacCatalina } from '../../blue_modules/environment';
|
||||
import { isCatalyst, isMacCatalina, isTablet } from '../../blue_modules/environment';
|
||||
|
||||
const A = require('../../blue_modules/analytics');
|
||||
const fs = require('../../blue_modules/fs');
|
||||
|
@ -46,7 +45,7 @@ const WalletsList = () => {
|
|||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [itemWidth, setItemWidth] = useState(width * 0.82 > 375 ? 375 : width * 0.82);
|
||||
const [isLargeScreen, setIsLargeScreen] = useState(
|
||||
Platform.OS === 'android' ? isTablet() : width >= Dimensions.get('screen').width / 2 && isTablet(),
|
||||
Platform.OS === 'android' ? isTablet() : width >= Dimensions.get('screen').width / 2 && (isTablet() || isCatalyst),
|
||||
);
|
||||
const [carouselData, setCarouselData] = useState([]);
|
||||
const dataSource = getTransactions(null, 10);
|
||||
|
@ -433,7 +432,7 @@ const WalletsList = () => {
|
|||
};
|
||||
|
||||
const onLayout = _e => {
|
||||
setIsLargeScreen(Platform.OS === 'android' ? isTablet() : width >= Dimensions.get('screen').width / 2 && isTablet());
|
||||
setIsLargeScreen(Platform.OS === 'android' ? isTablet() : width >= Dimensions.get('screen').width / 2 && (isTablet() || isCatalyst));
|
||||
setItemWidth(width * 0.82 > 375 ? 375 : width * 0.82);
|
||||
};
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ import {
|
|||
View,
|
||||
} from 'react-native';
|
||||
import { launchImageLibrary } from 'react-native-image-picker';
|
||||
import Clipboard from '@react-native-community/clipboard';
|
||||
import Clipboard from '@react-native-clipboard/clipboard';
|
||||
import { Icon } from 'react-native-elements';
|
||||
import { useRoute, useNavigation, useTheme, useFocusEffect } from '@react-navigation/native';
|
||||
import { Chain } from '../../models/bitcoinUnits';
|
||||
|
|
Loading…
Add table
Reference in a new issue