Merge branch 'master' into limpbrains-missing-loc

This commit is contained in:
Ivan Vershigora 2020-12-24 21:23:27 +03:00
commit e2b7034654
88 changed files with 1441 additions and 646 deletions

31
App.js
View file

@ -43,7 +43,7 @@ const App = () => {
const appState = useRef(AppState.currentState);
const [isClipboardContentModalVisible, setIsClipboardContentModalVisible] = useState(false);
const [clipboardContentType, setClipboardContentType] = useState();
const [clipboardContent, setClipboardContent] = useState('');
const clipboardContent = useRef();
const colorScheme = useColorScheme();
const stylesHook = StyleSheet.create({
modalContent: {
@ -153,7 +153,6 @@ const App = () => {
const notifications2process = await Notifications.getStoredNotifications();
for (const payload of notifications2process) {
const wasTapped = payload.foreground === false || (payload.foreground === true && payload.userInteraction === true);
if (!wasTapped) continue;
console.log('processing push notification:', payload);
let wallet;
@ -171,16 +170,19 @@ const App = () => {
if (wallet) {
const walletID = wallet.getID();
fetchAndSaveWalletTransactions(walletID);
NavigationService.dispatch(
CommonActions.navigate({
name: 'WalletTransactions',
key: `WalletTransactions-${wallet.getID()}`,
params: {
walletID,
walletType: wallet.type,
},
}),
);
if (wasTapped) {
NavigationService.dispatch(
CommonActions.navigate({
name: 'WalletTransactions',
key: `WalletTransactions-${wallet.getID()}`,
params: {
walletID,
walletType: wallet.type,
},
}),
);
}
// no delay (1ms) as we dont need to wait for transaction propagation. 500ms is a delay to wait for the navigation
await Notifications.clearStoredNotifications();
return true;
@ -192,7 +194,6 @@ const App = () => {
// TODO: if we are here - we did not act upon any push, so we need to iterate over _not tapped_ pushes
// and refetch appropriate wallet and redraw screen
await Notifications.clearStoredNotifications();
return false;
};
@ -217,7 +218,7 @@ const App = () => {
const isBothBitcoinAndLightning = DeeplinkSchemaMatch.isBothBitcoinAndLightning(clipboard);
if (
!isAddressFromStoredWallet &&
clipboardContent !== clipboard &&
clipboardContent.current !== clipboard &&
(isBitcoinAddress || isLightningInvoice || isLNURL || isBothBitcoinAndLightning)
) {
if (isBitcoinAddress) {
@ -229,7 +230,7 @@ const App = () => {
}
setIsClipboardContentModalVisible(true);
}
setClipboardContent(clipboard);
clipboardContent.current = clipboard;
}
if (nextAppState) {
appState.current = nextAppState;

View file

@ -37,7 +37,7 @@ 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-community/async-storage';
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';
@ -1397,7 +1397,7 @@ export const BlueTransactionListItem = React.memo(({ item, itemPriceUnit = Bitco
const [subtitleNumberOfLines, setSubtitleNumberOfLines] = useState(1);
const { colors } = useTheme();
const { navigate } = useNavigation();
const { txMetadata, wallets } = useContext(BlueStorageContext);
const { txMetadata, wallets, preferredFiatCurrency, language } = useContext(BlueStorageContext);
const containerStyle = useMemo(
() => ({
backgroundColor: 'transparent',
@ -1415,7 +1415,8 @@ export const BlueTransactionListItem = React.memo(({ item, itemPriceUnit = Bitco
} else {
return transactionTimeToReadable(item.received);
}
}, [item.confirmations, item.received]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [item.confirmations, item.received, language]);
const txMemo = txMetadata[item.hash]?.memo ?? '';
const subtitle = useMemo(() => {
let sub = item.confirmations < 7 ? loc.formatString(loc.transactions.list_conf, { number: item.confirmations }) : '';
@ -1446,7 +1447,8 @@ export const BlueTransactionListItem = React.memo(({ item, itemPriceUnit = Bitco
} else {
return formatBalanceWithoutSuffix(item.value && item.value, itemPriceUnit, true).toString();
}
}, [item, itemPriceUnit]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [item, itemPriceUnit, preferredFiatCurrency]);
const rowTitleStyle = useMemo(() => {
let color = colors.successColor;

View file

@ -7,6 +7,8 @@ When you tag a new release, use the following example:
`git tag -m "REL v1.4.0: 157c9c2" v1.4.0`
You may get the commit hash from git log. Don't forget to push tags `git push origin --tags`
Alternative way to tag: `git tag -a v6.0.0 2e1a00609d5a0dbc91bcda2421df0f61bdfc6b10 -m "v6.0.0"`
When tagging a new release, make sure to increment version in package.json and other files (we have a script for that: `./scripts/edit-version-number.sh`)
In the commit where you up version you can have the commit message as
`"REL vX.X.X: Summary message"`.

View file

@ -341,7 +341,7 @@ const InitRoot = () => (
component={UnlockWithScreenRoot}
options={{ headerShown: false, animationEnabled: false }}
/>
<InitStack.Screen name="ReorderWallets" component={ReorderWalletsStackRoot} options={{ headerShown: false }} />
<InitStack.Screen name="ReorderWallets" component={ReorderWalletsStackRoot} options={{ headerShown: false, gestureEnabled: false }} />
<InitStack.Screen name="DrawerRoot" component={DrawerRoot} options={{ headerShown: false, animationEnabled: false }} />
</InitStack.Navigator>
);

View file

@ -0,0 +1 @@
export default from '@react-native-async-storage/async-storage/jest/async-storage-mock'

View file

@ -1 +0,0 @@
export default from '@react-native-community/async-storage/jest/async-storage-mock'

View file

@ -136,7 +136,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "6.0.1"
versionName "6.0.2"
multiDexEnabled true
missingDimensionStrategy 'react-native-camera', 'general'
testBuildType System.getProperty('testBuildType', 'debug') // This will later be used to control the test apk build type

View file

@ -1,4 +1,4 @@
import AsyncStorage from '@react-native-community/async-storage';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { Platform } from 'react-native';
import { AppStorage, LegacyWallet, SegwitBech32Wallet, SegwitP2SHWallet } from '../class';
import DefaultPreference from 'react-native-default-preference';

View file

@ -1,4 +1,4 @@
import { useAsyncStorage } from '@react-native-community/async-storage';
import { useAsyncStorage } from '@react-native-async-storage/async-storage';
import Clipboard from '@react-native-community/clipboard';
function BlueClipboard() {

View file

@ -1,5 +1,5 @@
import Frisbee from 'frisbee';
import AsyncStorage from '@react-native-community/async-storage';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { AppStorage } from '../class';
import { FiatServerResponse, FiatUnit } from '../models/fiatUnit';
import DefaultPreference from 'react-native-default-preference';

View file

@ -1,8 +1,8 @@
import PushNotificationIOS from '@react-native-community/push-notification-ios';
import { Alert, Platform } from 'react-native';
import { Alert } from 'react-native';
import Frisbee from 'frisbee';
import { getApplicationName, getVersion, getSystemName, getSystemVersion } from 'react-native-device-info';
import AsyncStorage from '@react-native-community/async-storage';
import AsyncStorage from '@react-native-async-storage/async-storage';
import loc from '../loc';
const PushNotification = require('react-native-push-notification');
const constants = require('./constants');
@ -54,14 +54,7 @@ function Notifications(props) {
//
// ...we save notification in internal notifications queue thats gona be processed later (on unsuspend with decrypted storage)
if (Platform.OS === 'ios' && notification.foreground === true && notification.userInteraction === false) {
// iOS hack
// @see https://github.com/zo0r/react-native-push-notification/issues/1585
notification.userInteraction = true;
// also, on iOS app is not suspending/unsuspending when user taps a notification bubble,so we simulate it
// since its where we actually handle notifications:
setTimeout(() => props.onProcessNotifications(), 500);
}
setTimeout(() => props.onProcessNotifications(), 500);
let notifications = [];
try {

View file

@ -1,5 +1,7 @@
/* eslint-disable react/prop-types */
import { useAsyncStorage } from '@react-native-async-storage/async-storage';
import React, { createContext, useEffect, useState } from 'react';
import { AppStorage } from '../class';
const BlueApp = require('../BlueApp');
const BlueElectrum = require('./BlueElectrum');
@ -9,6 +11,10 @@ export const BlueStorageProvider = ({ children }) => {
const [pendingWallets, setPendingWallets] = useState([]);
const [selectedWallet, setSelectedWallet] = useState('');
const [walletsInitialized, setWalletsInitialized] = useState(false);
const [preferredFiatCurrency, _setPreferredFiatCurrency] = useState();
const [language, _setLanguage] = useState();
const getPreferredCurrencyAsyncStorage = useAsyncStorage(AppStorage.PREFERRED_CURRENCY).getItem;
const getLanguageAsyncStorage = useAsyncStorage(AppStorage.LANG).getItem;
const [newWalletAdded, setNewWalletAdded] = useState(false);
const saveToDisk = async () => {
BlueApp.tx_metadata = txMetadata;
@ -21,6 +27,30 @@ export const BlueStorageProvider = ({ children }) => {
setWallets(BlueApp.getWallets());
}, []);
const getPreferredCurrency = async () => {
const item = await getPreferredCurrencyAsyncStorage();
_setPreferredFiatCurrency(item);
};
const setPreferredFiatCurrency = () => {
getPreferredCurrency();
};
const getLanguage = async () => {
const item = await getLanguageAsyncStorage();
_setLanguage(item);
};
const setLanguage = () => {
getLanguage();
};
useEffect(() => {
getPreferredCurrency();
getLanguageAsyncStorage();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const resetWallets = () => {
setWallets(BlueApp.getWallets());
};
@ -149,6 +179,10 @@ export const BlueStorageProvider = ({ children }) => {
setResetOnAppUninstallTo,
isPasswordInUse,
setIsAdancedModeEnabled,
setPreferredFiatCurrency,
preferredFiatCurrency,
setLanguage,
language,
}}
>
{children}

View file

@ -1,5 +1,5 @@
/* global alert */
import AsyncStorage from '@react-native-community/async-storage';
import AsyncStorage from '@react-native-async-storage/async-storage';
import RNSecureKeyStore, { ACCESSIBLE } from 'react-native-secure-key-store';
import {
HDLegacyBreadwalletWallet,

View file

@ -1,5 +1,5 @@
import { AppStorage, LightningCustodianWallet } from './';
import AsyncStorage from '@react-native-community/async-storage';
import AsyncStorage from '@react-native-async-storage/async-storage';
import RNFS from 'react-native-fs';
import url from 'url';
import { Chain } from '../models/bitcoinUnits';
@ -181,7 +181,6 @@ class DeeplinkSchemaMatch {
]);
} else {
const urlObject = url.parse(event.url, true); // eslint-disable-line node/no-deprecated-api
console.log('parsed', event.url, 'into', urlObject);
(async () => {
if (urlObject.protocol === 'bluewallet:' || urlObject.protocol === 'lapp:' || urlObject.protocol === 'blue:') {
switch (urlObject.host) {
@ -244,12 +243,56 @@ class DeeplinkSchemaMatch {
]);
break;
}
case 'setelectrumserver':
completionHandler([
'ElectrumSettings',
{
server: DeeplinkSchemaMatch.getServerFromSetElectrumServerAction(event.url),
},
]);
break;
case 'setlndhuburl':
completionHandler([
'LightningSettings',
{
url: DeeplinkSchemaMatch.getUrlFromSetLndhubUrlAction(event.url),
},
]);
break;
}
}
})();
}
}
/**
* Extracts server from a deeplink like `bluewallet:setelectrumserver?server=electrum1.bluewallet.io%3A443%3As`
* returns FALSE if none found
*
* @param url {string}
* @return {string|boolean}
*/
static getServerFromSetElectrumServerAction(url) {
if (!url.startsWith('bluewallet:setelectrumserver') && !url.startsWith('setelectrumserver')) return false;
const splt = url.split('server=');
if (splt[1]) return decodeURIComponent(splt[1]);
return false;
}
/**
* Extracts url from a deeplink like `bluewallet:setlndhuburl?url=https%3A%2F%2Flndhub.herokuapp.com`
* returns FALSE if none found
*
* @param url {string}
* @return {string|boolean}
*/
static getUrlFromSetLndhubUrlAction(url) {
if (!url.startsWith('bluewallet:setlndhuburl') && !url.startsWith('setlndhuburl')) return false;
const splt = url.split('url=');
if (splt[1]) return decodeURIComponent(splt[1]);
return false;
}
static isTXNFile(filePath) {
return (
(filePath.toLowerCase().startsWith('file:') || filePath.toLowerCase().startsWith('content:')) &&

View file

@ -1,4 +1,4 @@
import AsyncStorage from '@react-native-community/async-storage';
import AsyncStorage from '@react-native-async-storage/async-storage';
const BlueApp = require('../BlueApp');
export default class OnAppLaunch {

View file

@ -1,7 +1,7 @@
import QuickActions from 'react-native-quick-actions';
import { Platform } from 'react-native';
import { formatBalance } from '../loc';
import AsyncStorage from '@react-native-community/async-storage';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { useContext, useEffect } from 'react';
import { BlueStorageContext } from '../blue_modules/storage-context';

View file

@ -276,8 +276,8 @@ export class LegacyWallet extends AbstractWallet {
if (!changeAddress) throw new Error('No change address provided');
let algo = coinSelectAccumulative;
if (targets.length === 1 && targets[0] && !targets[0].value) {
// we want to send MAX
// if targets has output without a value, we want send MAX to it
if (targets.some(i => !('value' in i))) {
algo = coinSelectSplit;
}
@ -285,7 +285,7 @@ export class LegacyWallet extends AbstractWallet {
// .inputs and .outputs will be undefined if no solution was found
if (!inputs || !outputs) {
throw new Error('Not enough balance. Try sending smaller amount');
throw new Error('Not enough balance. Try sending smaller amount or decrease the fee.');
}
return { inputs, outputs, fee };

View file

@ -3,8 +3,6 @@ import bip39 from 'bip39';
import b58 from 'bs58check';
import { decodeUR } from 'bc-ur';
const BlueElectrum = require('../../blue_modules/BlueElectrum');
const coinSelectAccumulative = require('coinselect/accumulative');
const coinSelectSplit = require('coinselect/split');
const HDNode = require('bip32');
const bitcoin = require('bitcoinjs-lib');
const createHash = require('create-hash');
@ -809,22 +807,9 @@ export class MultisigHDWallet extends AbstractHDElectrumWallet {
if (targets.length === 0) throw new Error('No destination provided');
if (this.howManySignaturesCanWeMake() === 0) skipSigning = true;
if (!changeAddress) throw new Error('No change address provided');
const { inputs, outputs, fee } = this.coinselect(utxos, targets, feeRate, changeAddress);
sequence = sequence || AbstractHDElectrumWallet.defaultRBFSequence;
let algo = coinSelectAccumulative;
if (targets.length === 1 && targets[0] && !targets[0].value) {
// we want to send MAX
algo = coinSelectSplit;
}
const { inputs, outputs, fee } = algo(utxos, targets, feeRate);
// .inputs and .outputs will be undefined if no solution was found
if (!inputs || !outputs) {
throw new Error('Not enough balance. Try sending smaller amount');
}
let psbt = new bitcoin.Psbt();
let c = 0;
@ -853,11 +838,16 @@ export class MultisigHDWallet extends AbstractHDElectrumWallet {
psbt.addOutput(outputData);
});
let signaturesMade = 0;
if (!skipSigning) {
for (let cc = 0; cc < c; cc++) {
for (const cosigner of this._cosigners) {
if (!MultisigHDWallet.isXpubString(cosigner)) {
// ok this is a mnemonic, lets try to sign
if (signaturesMade >= this.getM()) {
// dont sign more than we need, otherwise there will be "Too many signatures" error
continue;
}
let seed = bip39.mnemonicToSeed(cosigner);
if (cosigner.startsWith(ELECTRUM_SEED_PREFIX)) {
seed = MultisigHDWallet.convertElectrumMnemonicToSeed(cosigner);
@ -865,6 +855,7 @@ export class MultisigHDWallet extends AbstractHDElectrumWallet {
const hdRoot = bitcoin.bip32.fromSeed(seed);
psbt.signInputHD(cc, hdRoot);
signaturesMade++;
}
}
}

View file

@ -1,4 +1,4 @@
import React, { useRef, useCallback, useState, useImperativeHandle, forwardRef } from 'react';
import React, { useRef, useCallback, useState, useImperativeHandle, forwardRef, useContext } from 'react';
import PropTypes from 'prop-types';
import {
ActivityIndicator,
@ -21,6 +21,8 @@ import { LightningCustodianWallet, MultisigHDWallet, PlaceholderWallet } from '.
import WalletGradient from '../class/wallet-gradient';
import { BluePrivateBalance } from '../BlueComponents';
import { BlueStorageContext } from '../blue_modules/storage-context';
const nStyles = StyleSheet.create({
root: {
marginVertical: 17,
@ -268,6 +270,7 @@ const cStyles = StyleSheet.create({
const WalletsCarousel = forwardRef((props, ref) => {
const carouselRef = useRef();
const [loading, setLoading] = useState(true);
const { preferredFiatCurrency, language } = useContext(BlueStorageContext);
const renderItem = useCallback(
({ item, index }) => (
<WalletCarouselItem
@ -278,7 +281,8 @@ const WalletsCarousel = forwardRef((props, ref) => {
onPress={props.onPress}
/>
),
[props.vertical, props.selectedWallet, props.handleLongPress, props.onPress],
// eslint-disable-next-line react-hooks/exhaustive-deps
[props.vertical, props.selectedWallet, props.handleLongPress, props.onPress, preferredFiatCurrency, language],
);
useImperativeHandle(ref, () => ({

View file

@ -20,6 +20,8 @@
32F0A29A2311DBB20095C559 /* ComplicationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32F0A2992311DBB20095C559 /* ComplicationController.swift */; };
5875B7B2D85DC56E00F292FF /* libPods-WalletInformationWidgetExtension.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CC8A6C610EAE90F810EADCC /* libPods-WalletInformationWidgetExtension.a */; platformFilter = ios; };
590C62D2ED8BF487C33945B0 /* libPods-WalletInformationAndMarketWidgetExtension.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 98455D960744E4E5DD50BA87 /* libPods-WalletInformationAndMarketWidgetExtension.a */; platformFilter = ios; };
6D2A6464258BA92D0092292B /* Stickers.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2A6463258BA92D0092292B /* Stickers.xcassets */; };
6D2A6468258BA92D0092292B /* Stickers.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 6D2A6461258BA92C0092292B /* Stickers.appex */; platformFilter = ios; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
6D2AA7FA2568B8750090B089 /* FiatUnits.plist in Resources */ = {isa = PBXBuildFile; fileRef = 6D2AA7F92568B8750090B089 /* FiatUnits.plist */; };
6D2AA7FB2568B8750090B089 /* FiatUnits.plist in Resources */ = {isa = PBXBuildFile; fileRef = 6D2AA7F92568B8750090B089 /* FiatUnits.plist */; };
6D2AA7FC2568B8750090B089 /* FiatUnits.plist in Resources */ = {isa = PBXBuildFile; fileRef = 6D2AA7F92568B8750090B089 /* FiatUnits.plist */; };
@ -118,6 +120,13 @@
remoteGlobalIDString = 3271B0A8236E2E0700DA766F;
remoteInfo = TodayExtension;
};
6D2A6466258BA92D0092292B /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 6D2A6460258BA92C0092292B;
remoteInfo = Stickers;
};
6D6CA4C1255872E7009312A5 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
@ -176,6 +185,7 @@
dstPath = "";
dstSubfolderSpec = 13;
files = (
6D2A6468258BA92D0092292B /* Stickers.appex in Embed App Extensions */,
6D9946692555A661000E52E8 /* MarketWidgetExtension.appex in Embed App Extensions */,
6D6CA4C3255872E7009312A5 /* PriceWidgetExtension.appex in Embed App Extensions */,
6D9A2E0D254BA348007B5B82 /* WalletInformationAndMarketWidgetExtension.appex in Embed App Extensions */,
@ -298,6 +308,9 @@
6D294A9C24D512770039E22B /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/MainInterface.strings; sourceTree = "<group>"; };
6D294A9D24D5127F0039E22B /* xh */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = xh; path = xh.lproj/Interface.strings; sourceTree = "<group>"; };
6D294A9E24D512800039E22B /* xh */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = xh; path = xh.lproj/MainInterface.strings; sourceTree = "<group>"; };
6D2A6461258BA92C0092292B /* Stickers.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Stickers.appex; sourceTree = BUILT_PRODUCTS_DIR; };
6D2A6463258BA92D0092292B /* Stickers.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Stickers.xcassets; sourceTree = "<group>"; };
6D2A6465258BA92D0092292B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
6D2AA7F92568B8750090B089 /* FiatUnits.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = FiatUnits.plist; sourceTree = "<group>"; };
6D2AA8072568B8F40090B089 /* FiatUnit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FiatUnit.swift; sourceTree = "<group>"; };
6D333B3A252FE1A3004D72DF /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
@ -461,6 +474,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
8889F8F93C39BB72C97DD77E /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
B40D4E39225841ED00428FCC /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@ -566,6 +586,15 @@
name = Resources;
sourceTree = "<group>";
};
6D2A6462258BA92C0092292B /* Stickers */ = {
isa = PBXGroup;
children = (
6D2A6463258BA92D0092292B /* Stickers.xcassets */,
6D2A6465258BA92D0092292B /* Info.plist */,
);
path = Stickers;
sourceTree = "<group>";
};
6D2AA8062568B8E50090B089 /* Fiat */ = {
isa = PBXGroup;
children = (
@ -664,6 +693,7 @@
B40D4E40225841ED00428FCC /* BlueWalletWatch Extension */,
3271B0AC236E2E0700DA766F /* TodayExtension */,
6DEB4B18254FB7D700E9F9AA /* Widgets */,
6D2A6462258BA92C0092292B /* Stickers */,
83CBBA001A601CBA00E9B192 /* Products */,
2D16E6871FA4F8E400B85C8A /* Frameworks */,
B40FE50A21FAD228005D5578 /* Recovered References */,
@ -686,6 +716,7 @@
6DEB4AAD254FB59B00E9F9AA /* WalletInformationWidgetExtension.appex */,
6D99465E2555A660000E52E8 /* MarketWidgetExtension.appex */,
6D6CA4B8255872E3009312A5 /* PriceWidgetExtension.appex */,
6D2A6461258BA92C0092292B /* Stickers.appex */,
);
name = Products;
sourceTree = "<group>";
@ -809,6 +840,7 @@
6D9946452555A583000E52E8 /* PBXTargetDependency */,
6D9946682555A661000E52E8 /* PBXTargetDependency */,
6D6CA4C2255872E7009312A5 /* PBXTargetDependency */,
6D2A6467258BA92D0092292B /* PBXTargetDependency */,
);
name = BlueWallet;
productName = "Hello World";
@ -832,6 +864,22 @@
productReference = 3271B0A9236E2E0700DA766F /* BlueWallet - Bitcoin Price.appex */;
productType = "com.apple.product-type.app-extension";
};
6D2A6460258BA92C0092292B /* Stickers */ = {
isa = PBXNativeTarget;
buildConfigurationList = 6D2A646B258BA92D0092292B /* Build configuration list for PBXNativeTarget "Stickers" */;
buildPhases = (
6D2A645F258BA92C0092292B /* Resources */,
8889F8F93C39BB72C97DD77E /* Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = Stickers;
productName = Stickers;
productReference = 6D2A6461258BA92C0092292B /* Stickers.appex */;
productType = "com.apple.product-type.app-extension.messages-sticker-pack";
};
6D6CA4B7255872E3009312A5 /* PriceWidgetExtension */ = {
isa = PBXNativeTarget;
buildConfigurationList = 6D6CA4C6255872E7009312A5 /* Build configuration list for PBXNativeTarget "PriceWidgetExtension" */;
@ -963,6 +1011,9 @@
CreatedOnToolsVersion = 11.2;
LastSwiftMigration = 1130;
};
6D2A6460258BA92C0092292B = {
CreatedOnToolsVersion = 12.1;
};
6D6CA4B7255872E3009312A5 = {
CreatedOnToolsVersion = 12.1;
};
@ -1040,6 +1091,7 @@
6DEB4AAC254FB59B00E9F9AA /* WalletInformationWidgetExtension */,
6D9A2E01254BA347007B5B82 /* WalletInformationAndMarketWidgetExtension */,
6D6CA4B7255872E3009312A5 /* PriceWidgetExtension */,
6D2A6460258BA92C0092292B /* Stickers */,
);
};
/* End PBXProject section */
@ -1062,6 +1114,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
6D2A645F258BA92C0092292B /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
6D2A6464258BA92D0092292B /* Stickers.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
6D6CA4B6255872E3009312A5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@ -1376,6 +1436,11 @@
target = 3271B0A8236E2E0700DA766F /* TodayExtension */;
targetProxy = 3271B0B3236E2E0700DA766F /* PBXContainerItemProxy */;
};
6D2A6467258BA92D0092292B /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 6D2A6460258BA92C0092292B /* Stickers */;
targetProxy = 6D2A6466258BA92D0092292B /* PBXContainerItemProxy */;
};
6D6CA4C2255872E7009312A5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
platformFilter = ios;
@ -1513,7 +1578,7 @@
"$(inherited)",
"$(PROJECT_DIR)",
);
MARKETING_VERSION = 6.0.1;
MARKETING_VERSION = 6.0.2;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@ -1556,7 +1621,7 @@
"$(inherited)",
"$(PROJECT_DIR)",
);
MARKETING_VERSION = 6.0.1;
MARKETING_VERSION = 6.0.2;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@ -1597,7 +1662,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 6.0.1;
MARKETING_VERSION = 6.0.2;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.TodayExtension;
@ -1636,7 +1701,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 6.0.1;
MARKETING_VERSION = 6.0.2;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.TodayExtension;
PRODUCT_NAME = "BlueWallet - Bitcoin Price";
@ -1649,6 +1714,66 @@
};
name = Release;
};
6D2A6469258BA92D0092292B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = "iMessage App Icon";
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 310;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = A7W54YZ4WU;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = Stickers/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
MARKETING_VERSION = 6.0.2;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.Stickers;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
6D2A646A258BA92D0092292B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = "iMessage App Icon";
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_IDENTITY = "iPhone Distribution";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Manual;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 310;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = A7W54YZ4WU;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = Stickers/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
MARKETING_VERSION = 6.0.2;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.Stickers;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = Stickers;
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
6D6CA4C4255872E7009312A5 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -1675,7 +1800,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 6.0.1;
MARKETING_VERSION = 6.0.2;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.PriceWidget;
@ -1717,7 +1842,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 6.0.1;
MARKETING_VERSION = 6.0.2;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.PriceWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -1757,7 +1882,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 6.0.1;
MARKETING_VERSION = 6.0.2;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.MarketWidget;
@ -1800,7 +1925,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 6.0.1;
MARKETING_VERSION = 6.0.2;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.MarketWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -1841,7 +1966,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 6.0.1;
MARKETING_VERSION = 6.0.2;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.WalletInformationAndMarketWidget;
@ -1885,7 +2010,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 6.0.1;
MARKETING_VERSION = 6.0.2;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.WalletInformationAndMarketWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -1926,7 +2051,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 6.0.1;
MARKETING_VERSION = 6.0.2;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.WalletInformationWidget;
@ -1969,7 +2094,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 6.0.1;
MARKETING_VERSION = 6.0.2;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.WalletInformationWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -2111,7 +2236,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 6.0.1;
MARKETING_VERSION = 6.0.2;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.watch.extension;
@ -2151,7 +2276,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 6.0.1;
MARKETING_VERSION = 6.0.2;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.watch.extension;
PRODUCT_NAME = "${TARGET_NAME}";
@ -2185,7 +2310,7 @@
GCC_C_LANGUAGE_STANDARD = gnu11;
IBSC_MODULE = BlueWalletWatch_Extension;
INFOPLIST_FILE = BlueWalletWatch/Info.plist;
MARKETING_VERSION = 6.0.1;
MARKETING_VERSION = 6.0.2;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.watch;
@ -2221,7 +2346,7 @@
GCC_C_LANGUAGE_STANDARD = gnu11;
IBSC_MODULE = BlueWalletWatch_Extension;
INFOPLIST_FILE = BlueWalletWatch/Info.plist;
MARKETING_VERSION = 6.0.1;
MARKETING_VERSION = 6.0.2;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.bluewallet.bluewallet.watch;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -2257,6 +2382,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
6D2A646B258BA92D0092292B /* Build configuration list for PBXNativeTarget "Stickers" */ = {
isa = XCConfigurationList;
buildConfigurations = (
6D2A6469258BA92D0092292B /* Debug */,
6D2A646A258BA92D0092292B /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
6D6CA4C6255872E7009312A5 /* Build configuration list for PBXNativeTarget "PriceWidgetExtension" */ = {
isa = XCConfigurationList;
buildConfigurations = (

View file

@ -91,48 +91,42 @@ static void InitializeFlipper(UIApplication *application) {
[RNQuickActionManager onQuickActionPress:shortcutItem completionHandler:completionHandler];
}
//Called when a notification is delivered to a foreground app.
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
{
NSDictionary *userInfo = notification.request.content.userInfo;
//Foreground
NSLog(@"APP_PUSH from foreground %@", userInfo);
[RNCPushNotificationIOS didReceiveRemoteNotification:userInfo
fetchCompletionHandler:^void (UIBackgroundFetchResult result){}];
completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge);
}
// Required to register for notifications
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
[RNCPushNotificationIOS didRegisterUserNotificationSettings:notificationSettings];
}
// Required for the register event.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
[RNCPushNotificationIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
// Required for the notification event. You must call the completion handler after handling the remote notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
[RNCPushNotificationIOS didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
// Required for the registrationError event.
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
[RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error];
}
// IOS 10+ Required for localNotification event
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
@ -141,19 +135,11 @@ didReceiveNotificationResponse:(UNNotificationResponse *)response
[RNCPushNotificationIOS didReceiveNotificationResponse:response];
completionHandler();
}
// IOS 4-10 Required for the localNotification event.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
[RNCPushNotificationIOS didReceiveLocalNotification:notification];
}
@end

View file

@ -2,6 +2,10 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>io.bluewallet.bluewallet.fetchTxsForWallet</string>
</array>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
@ -186,6 +190,8 @@
</array>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>processing</string>
<string>remote-notification</string>
</array>
<key>UILaunchStoryboardName</key>

View file

@ -265,7 +265,7 @@ PODS:
- React
- react-native-geolocation (2.0.2):
- React
- react-native-image-picker (3.0.1):
- react-native-image-picker (3.1.1):
- React
- react-native-is-catalyst (1.0.0):
- React
@ -349,13 +349,13 @@ PODS:
- React
- RemobileReactNativeQrcodeLocalImage (1.0.4):
- React
- RNCAsyncStorage (1.12.1):
- React-Core
- RNCAsyncStorage (1.13.2):
- React
- RNCClipboard (1.5.0):
- React-Core
- RNCMaskedView (0.1.10):
- React
- RNCPushNotificationIOS (1.7.1):
- RNCPushNotificationIOS (1.8.0):
- React-Core
- RNDefaultPreference (1.4.3):
- React
@ -472,7 +472,7 @@ DEPENDENCIES:
- ReactNativePrivacySnapshot (from `../node_modules/react-native-privacy-snapshot`)
- RealmJS (from `../node_modules/realm`)
- "RemobileReactNativeQrcodeLocalImage (from `../node_modules/@remobile/react-native-qrcode-local-image`)"
- "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)"
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
- "RNCClipboard (from `../node_modules/@react-native-community/clipboard`)"
- "RNCMaskedView (from `../node_modules/@react-native-community/masked-view`)"
- "RNCPushNotificationIOS (from `../node_modules/@react-native-community/push-notification-ios`)"
@ -609,7 +609,7 @@ EXTERNAL SOURCES:
RemobileReactNativeQrcodeLocalImage:
:path: "../node_modules/@remobile/react-native-qrcode-local-image"
RNCAsyncStorage:
:path: "../node_modules/@react-native-community/async-storage"
:path: "../node_modules/@react-native-async-storage/async-storage"
RNCClipboard:
:path: "../node_modules/@react-native-community/clipboard"
RNCMaskedView:
@ -703,7 +703,7 @@ SPEC CHECKSUMS:
react-native-document-picker: c5752781fbc0c126c627c1549b037c139444a4cf
react-native-fingerprint-scanner: c68136ca57e3704d7bdf5faa554ea535ce15b1d0
react-native-geolocation: cbd9d6bd06bac411eed2671810f454d4908484a8
react-native-image-picker: 4efc5b7f3a780975bcc677335eb670e52d203424
react-native-image-picker: 510ea4e35cbe99ec92ecd89e9449e7e149c930e6
react-native-is-catalyst: 52ee70e0123c82419dd4ce47dc4cc94b22467512
react-native-randombytes: 991545e6eaaf700b4ee384c291ef3d572e0b2ca8
react-native-safe-area-context: 01158a92c300895d79dee447e980672dc3fb85a6
@ -724,10 +724,10 @@ SPEC CHECKSUMS:
ReactNativePrivacySnapshot: cc295e45dc22810e9ff2c93380d643de20a77015
RealmJS: 899b4839a8bee46e248bc277995ad58da855e41f
RemobileReactNativeQrcodeLocalImage: 57aadc12896b148fb5e04bc7c6805f3565f5c3fa
RNCAsyncStorage: cb9a623793918c6699586281f0b51cbc38f046f9
RNCAsyncStorage: bc2f81cc1df90c267ce9ed30bb2dbc93b945a8ee
RNCClipboard: 8f9f12fabf3c06e976f19f87a62c89e28dfedfca
RNCMaskedView: f5c7d14d6847b7b44853f7acb6284c1da30a3459
RNCPushNotificationIOS: eaf01f848a0b872b194d31bcad94bb864299e01e
RNCPushNotificationIOS: 5b1cf9ad2aaa107ecb92d5d2d7005ba521b2b97a
RNDefaultPreference: 21816c0a6f61a2829ccc0cef034392e9b509ee5f
RNDeviceInfo: 57bb2806fb7bd982a1434e9f0b4e6a6ab1f6702e
RNFS: 2bd9eb49dc82fa9676382f0585b992c424cd59df

31
ios/Stickers/Info.plist Normal file
View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>BlueWallet</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.message-payload-provider</string>
<key>NSExtensionPrincipalClass</key>
<string>StickerBrowserViewController</string>
</dict>
</dict>
</plist>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
</dict>
</plist>

View file

@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -0,0 +1,9 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"filename" : "bitcoin@3x.png"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -0,0 +1,9 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"filename" : "bitcoin-logo-png-transparent.png"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

View file

@ -0,0 +1,9 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"filename" : "marketing-1024x1024.png"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 KiB

View file

@ -0,0 +1,29 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"grid-size" : "regular"
},
"stickers" : [
{
"filename" : "Bitcoin.sticker"
},
{
"filename" : "BlueWallet.sticker"
},
{
"filename" : "bluebeast.sticker"
},
{
"filename" : "Lightning.sticker"
},
{
"filename" : "Vault.sticker"
},
{
"filename" : "Bitcoin (Blue).sticker"
}
]
}

View file

@ -0,0 +1,9 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"filename" : "lightning@3x.png"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -0,0 +1,9 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"filename" : "vault_main@3x.png"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View file

@ -0,0 +1,9 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"filename" : "bluebeast.png"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -0,0 +1,91 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"images" : [
{
"size" : "29x29",
"scale" : "2x",
"idiom" : "iphone",
"filename" : "icon-29x29@2x.png"
},
{
"scale" : "3x",
"idiom" : "iphone",
"size" : "29x29",
"filename" : "icon-29x29@3x.png"
},
{
"filename" : "icon-60x45@2x.png",
"scale" : "2x",
"idiom" : "iphone",
"size" : "60x45"
},
{
"scale" : "3x",
"idiom" : "iphone",
"filename" : "icon-60x45@3x.png",
"size" : "60x45"
},
{
"scale" : "2x",
"idiom" : "ipad",
"filename" : "icon-29x29~ipad@2x.png",
"size" : "29x29"
},
{
"size" : "67x50",
"scale" : "2x",
"filename" : "icon-67x50~ipad@2x.png",
"idiom" : "ipad"
},
{
"size" : "74x55",
"idiom" : "ipad",
"filename" : "icon-74x55~ipad@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"filename" : "marketing-1024x1024.png",
"scale" : "1x",
"idiom" : "ios-marketing"
},
{
"filename" : "icon-27x20@2x.png",
"platform" : "ios",
"size" : "27x20",
"idiom" : "universal",
"scale" : "2x"
},
{
"scale" : "3x",
"size" : "27x20",
"platform" : "ios",
"filename" : "icon-27x20@3x.png",
"idiom" : "universal"
},
{
"size" : "32x24",
"idiom" : "universal",
"filename" : "icon-32x24@2x.png",
"platform" : "ios",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "icon-32x24@3x.png",
"scale" : "3x",
"size" : "32x24",
"platform" : "ios"
},
{
"scale" : "1x",
"filename" : "marketing-1024x768.png",
"platform" : "ios",
"size" : "1024x768",
"idiom" : "ios-marketing"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

View file

@ -1,3 +1,15 @@
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
v6.0.0
======
* ADD: Multisig
@ -86,32 +98,3 @@ v5.6.5
* FIX: locales nl_NL, ru
* FIX: Widget Fiat calculation
* FIX: 'RnSksIsAppInstalled' was being read from the wrong suite
v5.6.3
======
* ADD: Market Widget for iOS 14
* ADD: Large iOS widget
* ADD: Turkish Lira
* FIX: Refill not working on Lightning
* FIX: iOS - lightning:lnurl... links
* FIX: hodlhodl - my contracts - sorted by creation time
* FIX: scanQR now has progress bar when scanning animated QRs
* FIX: Backup screen visibility
* REF: brush up locales sl_SI, cs_CZ
* REF: Wallet types style
v5.6.2
======
* ADD: Privacy Settings Screen
* ADD: Clipboard read opt-out
* ADD: support lnurl fallback scheme
* ADD: import LNDHub from QR
* ADD: Electrum server import from QR
* ADD: Philippines Peso currency
* FIX: copy balance on wallet/transactions screen crash
* FIX: remove padding to prevent text concealment
* REF: show numeric keyboard when ask for numbers in prompt
* FIX: locales de_DE, sl_SI, ru, fi_FI, ja_JP, es, pt_BR
* REF: improve wallet import speed

View file

@ -1 +1 @@
BlueWallet - Cartera de Bitcoin
BlueWallet Cartera de Bitcoin

View file

@ -235,7 +235,8 @@
"about_review": "Leave us a review",
"about_selftest": "Run self-test",
"about_sm_github": "GitHub",
"about_sm_telegram": "Telegram chat",
"about_sm_discord": "Discord Server",
"about_sm_telegram": "Telegram channel",
"about_sm_twitter": "Follow us on Twitter",
"advanced_options": "Advanced Options",
"biom": "biometrics",
@ -256,6 +257,8 @@
"electrum_port": "TCP port, usually {example}",
"electrum_port_ssl": "SSL port, usually {example}",
"electrum_saved": "Your changes have been saved successfully. Restart may be required for changes to take effect.",
"set_electrum_server_as_default": "Set {server} as default electrum server?",
"set_lndhub_as_default": "Set {url} as default LNDHub server?",
"electrum_settings": "Electrum Settings",
"electrum_settings_explain": "Set to blank to use default",
"electrum_status": "Status",
@ -420,6 +423,7 @@
"no_ln_wallet_error": "Before paying a Lightning invoice, you must first add a Lightning wallet.",
"looks_like_bip38": "This looks like a password-protected private key (BIP38)",
"reorder_title": "Reorder Wallets",
"please_continue_scanning": "Please continue scanning",
"select_no_bitcoin": "There are currently no Bitcoin wallets available.",
"select_no_bitcoin_exp": "A Bitcoin wallet is required to refill Lightning wallets. Please create or import one.",
"select_wallet": "Select Wallet",

View file

@ -232,7 +232,8 @@
"about_review": "برای ما یک بررسی بگذارید",
"about_selftest": "اجرای خودآزمایی",
"about_sm_github": "گیت‌هاب",
"about_sm_telegram": "گروه تلگرام",
"about_sm_discord": "سرور دیسکورد",
"about_sm_telegram": "کانال تلگرام",
"about_sm_twitter": "ما را در توئیتر دنبال کنید",
"advanced_options": "گزینه‌های پیشرفته",
"currency": "واحد پول",
@ -402,6 +403,7 @@
"list_tryagain": "دوباره امتحان کنید",
"looks_like_bip38": "این به کلید خصوصی محافظت‌شده با گذرواژه (BIP38) شباهت دارد.",
"reorder_title": "بازچینی کیف پول‌ها",
"please_continue_scanning": "لطفاً به اسکن‌کردن ادامه دهید",
"select_no_bitcoin": "هیچ کیف پول بیت‌کوینی درحال‌حاضر دردسترس نیست.",
"select_no_bitcoin_exp": "یک کیف پول بیت‌کوین برای پرکردن کیف پول‌های لایتنینگ نیاز است. لطفاً یکی بسازید یا وارد کنید.",
"select_wallet": "انتخاب کیف پول",
@ -443,6 +445,7 @@
"needs": "به",
"what_is_vault_description_number_of_vault_keys": " {m} کلید گاوصندوق ",
"what_is_vault_description_to_spend": "برای خرج‌کردن نیاز داشته و یک کلید سوم\nکه می‌توانید برای تهیهٔ نسخهٔ پشتیبان از آن استفاده کنید.",
"what_is_vault_description_to_spend_other": "برای خرج‌کردن نیاز دارد.",
"quorum": "حد نصاب {m} از {n}",
"quorum_header": "حد نصاب",
"of": "از",

View file

@ -304,6 +304,7 @@
"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_no": "Tämä siirtotapahtuma ei ole vaihdettavissa",
"cancel_title": "Peruuta tämä siirtotapahtuma (RBF)",
"confirmations_lowercase": "{confirmations} vahvistukset",
"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",
@ -442,6 +443,7 @@
"needs": "Tarpeet",
"what_is_vault_description_number_of_vault_keys": "{m} holvin avaimet",
"what_is_vault_description_to_spend": "kuluttaa ja kolmas sinulle\nvoidaan käyttää varmuuskopiona.",
"what_is_vault_description_to_spend_other": "kuluttaa.",
"quorum": "{m} {n} quorum",
"quorum_header": "Quorum",
"of": "n",

View file

@ -8,7 +8,15 @@
"of": "{number} sur {total}",
"ok": "OK",
"storage_is_encrypted": "L'espace de stockage est chiffré. le mot de passe requis pour le déchiffrer.",
"yes": "Oui"
"allow": "Autoriser",
"dont_allow": "Ne pas autoriser",
"yes": "Oui",
"no": "Non",
"save": "Enregistrer",
"seed": "Graine",
"wallet_key": "Clé de portefeuille",
"invalid_animated_qr_code_fragment" : "Fragment du QR Code animé invalide. Veuillez essayer encore.",
"file_saved": "Le fichier ({filePath}) a été enregistré dans le dossier Téléchargements."
},
"azteco": {
"codeIs": "Votre code promo est",
@ -99,6 +107,7 @@
"lndViewInvoice": {
"additional_info": "Informations complémentaires",
"for": "A :",
"lightning_invoice": "Facture Ligthning",
"has_been_paid": "Cette requête a été réglée",
"open_direct_channel": "Ouvrir un canal direct avec ce noeud :",
"please_pay": "Veuillez payer",
@ -170,34 +179,49 @@
"details_next": "Suivant",
"details_no_maximum": "Le portefeuille sélectionné ne supporte pas le calcul automatique du solde maximum. Etes-vous sûr de vouloir utiliser ce portefeuille ?",
"details_no_multiple": "Le portefeuille sélectionné ne permet pas d'envoyer du Bitcoin à plusieurs destinataires. Etes-vous sûr de vouloir sélectionner ce portefeuille ?",
"details_no_signed_tx": "Le fichier sélectionné ne contient pas de transaction pouvant être importée.",
"details_note_placeholder": "note (optionnelle)",
"details_scan": "Scanner",
"details_total_exceeds_balance": "Le montant à envoyer excède le montant disponible.",
"details_wallet_before_tx": "Avant de créer une transaction, vous devez d'abord importer un ajouter un portefeuille Bitcoin.",
"details_wallet_selection": "Sélection du portefeuille",
"dynamic_init": "Initialisation",
"dynamic_next": "Suivant",
"dynamic_prev": "Précédent",
"dynamic_start": "Commencer",
"dynamic_stop": "Arrêter",
"fee_10m": "10min",
"fee_1d": "1j",
"fee_3h": "3h",
"fee_custom": "Personnalisé ",
"fee_fast": "Rapide",
"fee_medium": "Moyen",
"fee_replace_min": "Le taux des frais (satoshi par octet) que vous voulez payer devrais etre plus que {min} sat/octet",
"fee_satbyte": "En sat/octet",
"fee_slow": "Lent",
"header": "Envoyer",
"input_clear": "Tout effacer",
"input_done": "Terminé",
"input_paste": "Coller",
"input_total": "Total :",
"open_settings": "Ouvrir les paramètres",
"permission_camera_message": "Nous avons besoin de votre permission pour utiliser l'appareil photo",
"permission_camera_title": "Permission d'utiliser l'appareil photo",
"open_settings": "Ouvrir les paramètres",
"permission_storage_later": "Redemander Plus Tard",
"permission_storage_message": "BlueWallet a besoin de votre permission pour accéder a votre stockage pour enregistrer ce fichier.",
"permission_storage_denied_message": "BlueWallet est incapable d'enregistrer ce fichier. Veuillez ouvrir les paramètres de l'appareil et activer Permission Stockage.",
"permission_storage_title": "Permission d'accès au stockage pour BlueWallet",
"psbt_clipboard": "Copier dans le presse-papier",
"psbt_this_is_psbt": "Ceci est une Transaction Bitcoin Partiellement Signée (PSBT). Veuillez la compléter avec votre portefeuille matériel.",
"psbt_tx_export": "Exporter sous forme de fichier",
"no_tx_signing_in_progress": "Il n'y a pas de signature de transaction en cours.",
"psbt_tx_open": "Ouvrir la transaction signée",
"psbt_tx_scan": "Scanner la transaction signée",
"qr_error_no_qrcode": "L'image sélectionnée ne contient pas de QR Code",
"qr_error_no_wallet": "Le fichier sélectionné ne contient pas de portefeuille à importer.",
"success_done": "Terminé",
"txSaved": "Le fichier de transaction ({filePath}) a été enregistré dans votre dossier Téléchargements."
"txSaved": "Le fichier de transaction ({filePath}) a été enregistré dans votre dossier Téléchargements.",
"problem_with_psbt": "Problème avec PSBT"
},
"settings": {
"about": "À propos",
@ -208,7 +232,8 @@
"about_review": "Laissez-nous votre avis",
"about_selftest": "Effectuer un auto-test",
"about_sm_github": "GitHub",
"about_sm_telegram": "Discussion Telegram",
"about_sm_discord": "Serveur discord",
"about_sm_telegram": "Chaîne Telegram",
"about_sm_twitter": "Nous suivre sur Twitter",
"advanced_options": "Options avancées",
"currency": "Devise",
@ -253,34 +278,54 @@
"network_electrum": "Serveur Electrum",
"not_a_valid_uri": "URI invalide",
"notifications": "Notifications",
"open_link_in_explorer" : "Ouvrir le lien dans l'explorateur",
"password": "Mot de passe",
"password_explain": "Créer le mot de passe utilisé pour déchiffrer l'espace de stockage principal",
"passwords_do_not_match": "Les mots de passe ne correspondent pas",
"plausible_deniability": "Déni plausible...",
"privacy": "Vie privée",
"privacy_read_clipboard": "Lecture du presse-papier ",
"privacy_read_clipboard_alert": "BlueWallet affichera des raccourci pour gérer les factures et adresses trouvées dans le presse-papier.",
"privacy_system_settings": "Paramètres système",
"privacy_quickactions": "Raccourci Portefeuille",
"privacy_quickactions_explanation": "Touchez et maintenez l'icone BlueWallet sur votre écran d'accueil pour voir rapidement le solde de vos portefeuilles.",
"privacy_clipboard_explanation": "Fourni un raccourci si une adresse ou une facture est trouvée dans le presse-papier.",
"push_notifications": "Notifications push",
"retype_password": "Re-saisir votre mot de passe",
"save": "save",
"saved": "Enregistré"
"save": "Enregistrer",
"saved": "Enregistré",
"success_transaction_broadcasted" : "Succès! Votre transaction a été difusée!"
},
"notifications": {
"would_you_like_to_receive_notifications": "Voulez vous recevoir les notifications quand vous recevez des paiements entrants ?",
"no_and_dont_ask": "Non, et ne pas me redemander ",
"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_no": "Cette transaction n'est pas remplaçable",
"cancel_title": "Annuler cette transaction (RBF)",
"confirmations_lowercase": "{confirmations} confirmations",
"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",
"cpfp_title": "Frais de propulsion (CPFP)",
"details_balance_hide": "Cacher le solde",
"details_balance_show": "Montrer le solde",
"details_block": "Hauteur de bloc",
"details_copy": "Copier",
"details_from": "De",
"details_inputs": "Inputs",
"details_outputs": "Outputs",
"details_received": "Reçu",
"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": "À",
"details_transaction_details": "Détails de la transaction",
"enable_hw": "Ce portefeuille n'est pas utilisé en conjonction avec un portefeuille matériel. Voulez-vous permettre l'utilisation de portefeuilles matériels ?",
"list_conf": "Conf: {number}",
"pending": "En attente",
"list_title": "transactions",
"rbf_explain": "Nous allons remplacer cette transaction par celle avec des frais plus élevés. Elle devrait donc être minée plus vite. On parle de RBF - Replace By Fee.",
"rbf_title": "Frais de propulsion (RBF)",
@ -290,12 +335,14 @@
},
"wallets": {
"add_bitcoin": "Bitcoin",
"add_bitcoin_explain": "Portefeuille Bitcoin simple et puissant",
"add_create": "Créer",
"add_entropy_generated": "{gen} octets d'entropie générée",
"add_entropy_provide": "Créer de l'entropie par des jets de dé",
"add_entropy_remain": "{gen} octets d'entropie générée. Les {rem} octets restants seront obtenus auprès du générateur de nombres aléatoires du système.",
"add_import_wallet": "Importer un portefeuille",
"add_lightning": "Lightning",
"add_lightning_explain": "Pour payer avec des transactions instantanées",
"add_lndhub": "Connexion à votre LNDHub",
"add_lndhub_error": "L'adresse de noeud fournie n'est pas un noeud LNDHub valide.",
"add_lndhub_placeholder": "l'adresse de votre noeud",
@ -303,6 +350,8 @@
"add_title": "ajouter un portefeuille",
"add_wallet_name": "nom du portefeuille",
"add_wallet_type": "type",
"clipboard_bitcoin": "Vous avez une adresse bitcoin dans votre presse-papier. Voulez vous l'utiliser pour une transaction ?",
"clipboard_lightning": "Vous avez une facture ligthning dans votre presse-papier. Voulez vous l'utiliser pour une transaction ?",
"details_address": "Adresse",
"details_advanced": "Avancé",
"details_are_you_sure": "Êtes vous sur?",
@ -317,13 +366,14 @@
"details_marketplace": "Marketplace",
"details_master_fingerprint": "Empreinte maitresse",
"details_no_cancel": "Non, annuler",
"details_save": "Sauvegarder",
"details_save": "Enregistrer",
"details_show_xpub": "Afficher XPUB du portefeuille",
"details_title": "Portefeuille",
"details_type": "Type",
"details_use_with_hardware_wallet": "Utiliser avec un portefeuille matériel",
"details_wallet_updated": "Portefeuille mis à jour",
"details_yes_delete": "Oui, supprimer",
"enter_bip38_password": "Entrez le mots de passe de déchiffrement",
"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.",
@ -335,6 +385,7 @@
"import_title": "importer",
"list_create_a_button": "Ajouter maintenant",
"list_create_a_wallet": "Ajouter un portefeuille",
"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",
@ -347,14 +398,109 @@
"list_long_clipboard": "Copier depuis le presse-papier",
"list_long_scan": "Scanner le QR Code",
"list_tap_here_to_buy": "Cliquez ici pour acheter du Bitcoin",
"no_ln_wallet_error": "Avant de payer une facture Ligthning, vous devez créer un portefeuille Ligthning.",
"list_title": "portefeuilles",
"list_tryagain": "Réessayer",
"looks_like_bip38": "Ceci ressemble a une clé privée protégée par un mot de passe (BIP38)",
"reorder_title": "Trier vos portefeuilles",
"please_continue_scanning": "Merci de continuer à scaner",
"select_no_bitcoin": "Il n'y a aucun portefeuille Bitcoin disponible pour le moment.",
"select_no_bitcoin_exp": "Un portefeuille Bitcoin est nécessaire pour approvisionner les portefeuilles Lightning. Veuillez en créer ou en importer un.",
"select_wallet": "Choix du portefeuille",
"take_photo": "Prendre une photo",
"xpub_copiedToClipboard": "Copié dans le presse-papiers.",
"pull_to_refresh": "Tirer pour rafraichir",
"warning_do_not_disclose": "Attention! Ne pas divulguer",
"add_ln_wallet_first": "Vous devez d'abord ajouter un portefeuille Lightning.",
"xpub_title": "XPUB portefeuille"
},
"multisig": {
"multisig_vault": "Coffre",
"multisig_vault_explain": "Meilleur sécurité pour les gros montants",
"provide_signature": "Fournir la signature",
"vault_key": "Clé du coffre {number}",
"required_keys_out_of_total": "Clés requises par rapport au total",
"fee": "Frais: {number}",
"fee_btc": "{number} BTC",
"confirm": "Confirmer",
"header": "Envoyer",
"share": "Partager",
"view": "Vue",
"manage_keys": "Gérer les clés",
"how_many_signatures_can_bluewallet_make": "Combien de signatures BleuWallet peut faire",
"scan_or_import_file": "Scanner ou importer fichier",
"export_coordination_setup": "Exporter la configuration de coordination",
"cosign_this_transaction": "Co-signer cette transaction?",
"lets_start": "C'est parti",
"create": "Créer",
"provide_key": "Fournir la clé",
"native_segwit_title": "Pratique recommandée",
"wrapped_segwit_title": "Meilleur compatibilité",
"legacy_title": "Ancien format",
"co_sign_transaction": "Signer une transaction",
"what_is_vault": "Un coffre est un portefeuille de ",
"what_is_vault_numberOfWallets": " {m}-de-{n} multi signaures",
"what_is_vault_wallet": ".",
"vault_advanced_customize": "Paramètres du coffre",
"needs": "Il a besoin",
"what_is_vault_description_number_of_vault_keys": " {m} clés de coffre",
"what_is_vault_description_to_spend": "pour dépenser et une troisième \nque vous pouvez utiliser en backup.",
"what_is_vault_description_to_spend_other": "pour dépenser.",
"quorum": "{m} de {n} quorum",
"quorum_header": "Quorum",
"of": "de",
"wallet_type": "Type portefeuille",
"view_key": "Vue",
"invalid_mnemonics": "Cette phrase mnémonique ne semble pas valide ",
"invalid_cosigner": "Donnée co-signeur non valide",
"invalid_cosigner_format": "Co-signeur incorrecte: Ceci nest pas un co-signeur au {format} format",
"create_new_key": "Créer nouveau",
"scan_or_open_file": "Scanner ou ouvrir fichier",
"i_have_mnemonics": "J'ai une graine pour cette clé...",
"please_write_down_mnemonics": "Veuillez écrire a la main cette phrase mnémonique sur papier. Ne vous inquiétez pas, vous pouvez l'écrire plus tard.",
"i_wrote_it_down": "Ok, Je l'ai écrite sur un papier.",
"type_your_mnemonics": "Insérez une graine pour importer votre clé de coffre existante",
"this_is_cosigners_xpub": "Ceci est l'XPUB du co-signeur, prêt a être importé dans un autre portefeuille. C'est sure de le partager.",
"wallet_key_created": "Votre clé de coffre a été créé. Prenez un moment pour sauvegarder votre graine sous forme de mnémonique ",
"are_you_sure_seed_will_be_lost": "Etes Vous sûr? ",
"forget_this_seed": "Oublier cette graine et utiliser l'XPUB à la place",
"invalid_fingerprint": "L'empreinte pour cette graine ne correspond pas avec l'empreinte des co-signeurs",
"view_edit_cosigners": "Voir/Editer les co-signeurs",
"this_cosigner_is_already_imported": "Ce co-signeur a été déjà importé.",
"export_signed_psbt": "Exporter la PSBT signée",
"input_fp": "Entrer l'empreinte",
"input_fp_explain": "Passer pour utiliser celle par défaut (00000000)",
"input_path": "Saisir le chemin de dérivation",
"input_path_explain": "Passer pour utiliser celui par défaut ({default})",
"ms_help": "Aide",
"ms_help_title": "Comment les coffres Multisig marchent. Conseils et astuces",
"ms_help_text": "Un portefeuille avec plusieurs clés, pour augmenter de façon exponentielle la sécurité ou pour partager la détention.",
"ms_help_title1": "Plusieurs appareils est conseillé",
"ms_help_1": "Le coffre fonctionnera avec d'autre BlueWallet et les portefeuille compatible PSBT, comme Electrum, Specter, Coldcard, Cobo vault, etc...",
"ms_help_title2": "Edition des clés",
"ms_help_2": "Vous pouvez créer toutes les clés du coffre sur cet appareil et supprimer ou modifier ces clés ultérieurement. Avoir toutes les clés sur le même appareil offre la sécurité équivalente à celle d'un portefeuille bitcoin ordinaire.",
"ms_help_title3": "Sauvegardes coffre",
"ms_help_3": "Dans les options de portefeuille, vous trouverez votre sauvegarde Coffre et votre sauvegarde Vue-Seulement. Cette sauvegarde est comme une carte de votre portefeuille. Il est essentiel pour la récupération du portefeuille au cas où vous perdriez l'une de vos graines.",
"ms_help_title4": "importation Coffre",
"ms_help_4": "Pour importer un coffre Multi-signature, utilisez votre fichier de sauvegarde multisig et utilisez la fonction d'importation. Si vous ne disposez que de clés étendues et des graines, vous pouvez utiliser les champs d'importation individuels du flux Ajouter un coffre.\n",
"ms_help_title5": "Options avancées",
"ms_help_5": "Par défaut, BlueWallet générera un coffre 2de3. Pour créer un quorum différent ou pour changer le type d'adresse, activez les options avancées dans les paramètres."
},
"is_it_my_address": {
"title": "Est ce mon adresse?",
"owns": "{label} possède {address}",
"enter_address": "Entrez l'adresse",
"check_address": "Vérifiez l'adresse",
"no_wallet_owns_address": "Aucun des portefeuilles ne possède l'adresse fournie."
},
"cc": {
"change": "monnaie",
"coins_selected": "Pièces sélectionnées ({number})",
"empty": "Ce portefeuille ne possède aucune pièces en ce moment",
"freeze": "Geler",
"freezeLabel": "Gelé",
"header": "Controle de Pièces",
"use_coin": "Utiliser la pièces",
"tip": "Autorise la vue, l'étiquetage, le gel ou la sélection des pièces pour une gestion améliorée du portefeuille."
}
}

View file

@ -1,5 +1,5 @@
import Localization from 'react-localization';
import AsyncStorage from '@react-native-community/async-storage';
import AsyncStorage from '@react-native-async-storage/async-storage';
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
import * as RNLocalize from 'react-native-localize';
@ -13,125 +13,131 @@ const currency = require('../blue_modules/currency');
dayjs.extend(relativeTime);
// first-time loading sequence
(async () => {
const setDateTimeLocale = async () => {
let lang = await AsyncStorage.getItem('lang');
let localeForDayJSAvailable = true;
switch (lang) {
case 'ar':
require('dayjs/locale/ar');
break;
case 'bg_bg':
lang = 'bg';
require('dayjs/locale/bg');
break;
case 'ca':
require('dayjs/locale/ca');
break;
case 'cy':
require('dayjs/locale/cy');
break;
case 'da_dk':
require('dayjs/locale/da');
break;
case 'de_de':
require('dayjs/locale/de');
break;
case 'el':
require('dayjs/locale/el');
break;
case 'es':
require('dayjs/locale/es');
break;
case 'es_419':
// es-do it is the closes one to es_419
lang = 'es-do';
require('dayjs/locale/es-do');
break;
case 'fi_fi':
require('dayjs/locale/fi');
break;
case 'fa':
require('dayjs/locale/fa');
break;
case 'fr_fr':
require('dayjs/locale/fr');
break;
case 'he':
require('dayjs/locale/he');
break;
case 'hr_hr':
require('dayjs/locale/hr');
break;
case 'hu_hu':
require('dayjs/locale/hu');
break;
case 'id_id':
require('dayjs/locale/id');
break;
case 'it':
require('dayjs/locale/it');
break;
case 'jp_jp':
lang = 'ja';
require('dayjs/locale/ja');
break;
case 'nb_no':
require('dayjs/locale/nb');
break;
case 'nl_nl':
require('dayjs/locale/nl');
break;
case 'pt_br':
lang = 'pt-br';
require('dayjs/locale/pt-br');
break;
case 'pt_pt':
lang = 'pt';
require('dayjs/locale/pt');
break;
case 'pl':
require('dayjs/locale/pl');
break;
case 'ru':
require('dayjs/locale/ru');
break;
case 'sk_sk':
require('dayjs/locale/sk');
break;
case 'sl_si':
require('dayjs/locale/sl');
break;
case 'sv_se':
require('dayjs/locale/sv');
break;
case 'th_th':
require('dayjs/locale/th');
break;
case 'tr_tr':
require('dayjs/locale/tr');
break;
case 'vi_vn':
require('dayjs/locale/vi');
break;
case 'zh_cn':
lang = 'zh-cn';
require('dayjs/locale/zh-cn');
break;
case 'zh_tw':
lang = 'zh-tw';
require('dayjs/locale/zh-tw');
break;
default:
localeForDayJSAvailable = false;
break;
}
if (localeForDayJSAvailable) {
dayjs.locale(lang.split('_')[0]);
}
};
const setLanguageLocale = async () => {
// finding out whether lang preference was saved
// For some reason using the AppStorage.LANG constant is not working. Hard coding string for now.
let lang = await AsyncStorage.getItem('lang');
const lang = await AsyncStorage.getItem('lang');
if (lang) {
strings.setLanguage(lang);
let localeForDayJSAvailable = true;
switch (lang) {
case 'ar':
require('dayjs/locale/ar');
break;
case 'bg_bg':
lang = 'bg';
require('dayjs/locale/bg');
break;
case 'ca':
require('dayjs/locale/ca');
break;
case 'cy':
require('dayjs/locale/cy');
break;
case 'da_dk':
require('dayjs/locale/da');
break;
case 'de_de':
require('dayjs/locale/de');
break;
case 'el':
require('dayjs/locale/el');
break;
case 'es':
require('dayjs/locale/es');
break;
case 'es_419':
// es-do it is the closes one to es_419
lang = 'es-do';
require('dayjs/locale/es-do');
break;
case 'fi_fi':
require('dayjs/locale/fi');
break;
case 'fa':
require('dayjs/locale/fa');
break;
case 'fr_fr':
require('dayjs/locale/fr');
break;
case 'he':
require('dayjs/locale/he');
break;
case 'hr_hr':
require('dayjs/locale/hr');
break;
case 'hu_hu':
require('dayjs/locale/hu');
break;
case 'id_id':
require('dayjs/locale/id');
break;
case 'it':
require('dayjs/locale/it');
break;
case 'jp_jp':
lang = 'ja';
require('dayjs/locale/ja');
break;
case 'nb_no':
require('dayjs/locale/nb');
break;
case 'nl_nl':
require('dayjs/locale/nl');
break;
case 'pt_br':
lang = 'pt-br';
require('dayjs/locale/pt-br');
break;
case 'pt_pt':
lang = 'pt';
require('dayjs/locale/pt');
break;
case 'pl':
require('dayjs/locale/pl');
break;
case 'ru':
require('dayjs/locale/ru');
break;
case 'sk_sk':
require('dayjs/locale/sk');
break;
case 'sl_si':
require('dayjs/locale/sl');
break;
case 'sv_se':
require('dayjs/locale/sv');
break;
case 'th_th':
require('dayjs/locale/th');
break;
case 'tr_tr':
require('dayjs/locale/tr');
break;
case 'vi_vn':
require('dayjs/locale/vi');
break;
case 'zh_cn':
lang = 'zh-cn';
require('dayjs/locale/zh-cn');
break;
case 'zh_tw':
lang = 'zh-tw';
require('dayjs/locale/zh-tw');
break;
default:
localeForDayJSAvailable = false;
break;
}
if (localeForDayJSAvailable) {
dayjs.locale(lang.split('_')[0]);
}
await setDateTimeLocale();
} else {
const locales = RNLocalize.getLocales();
if (Object.keys(AvailableLanguages).some(language => language === locales[0])) {
@ -142,7 +148,8 @@ dayjs.extend(relativeTime);
strings.setLanguage('en');
}
}
})();
};
setLanguageLocale();
const strings = new Localization({
en: require('./en.json'),
@ -184,7 +191,11 @@ const strings = new Localization({
zh_tw: require('./zh_tw.json'),
});
strings.saveLanguage = lang => AsyncStorage.setItem(AppStorage.LANG, lang);
strings.saveLanguage = async lang => {
await AsyncStorage.setItem(AppStorage.LANG, lang);
strings.setLanguage(lang);
await setDateTimeLocale();
};
export const transactionTimeToReadable = time => {
if (time === 0) {

View file

@ -1,26 +1,26 @@
{
"_": {
"allow": "Toestaan",
"bad_password": "Onjuist wachtwoord, probeer het opnieuw",
"cancel": "Annuleren",
"continue": "Doorgaan",
"dont_allow": "Niet toestaan",
"enter_password": "Voer wachtwoord in",
"file_saved": "Bestand ({filePath}) is opgeslagen in uw gedownloade bestanden.",
"invalid_animated_qr_code_fragment": "Ongeldig geanimeerde QRCode, probeer het opnieuw",
"never": "nooit",
"no": "Nee",
"of": "{number} van {total}",
"ok": "Oké",
"storage_is_encrypted": "Uw opslag is versleuteld. Wachtwoord is vereist om het te ontcijferen",
"allow": "Toestaan",
"dont_allow": "Niet toestaan",
"yes": "Ja",
"no": "Nee",
"save": "Opslaan",
"seed": "Seed",
"storage_is_encrypted": "Uw opslag is versleuteld. Wachtwoord is vereist om het te ontcijferen",
"wallet_key": "Wallet key",
"yes": "Ja"
"invalid_animated_qr_code_fragment" : "Ongeldig geanimeerde QRCode, probeer het opnieuw",
"file_saved": "Bestand ({filePath}) is opgeslagen in uw gedownloade bestanden."
},
"azteco": {
"codeIs": "De code van uw tegoedbon is",
"errorBeforeRefeem": "Voor het inlossen moet u eerst Bitcoin wallet toevoegen.",
"errorBeforeRefeem": "Voor het inlossen moet u eerst Bitcoin-wallet toevoegen.",
"errorSomething": "Er ging is verkeerd. Is deze tegoedbon nog geldig?",
"redeem": "Inlossen naar wallet.",
"redeemButton": "Inlossen",
@ -33,7 +33,7 @@
"undo": "Herstellen"
},
"errors": {
"broadcast": "Broadcast mislukt",
"broadcast": "Verzenden mislukt",
"error": "Fout",
"network": "Netwerkfout"
},
@ -49,7 +49,7 @@
"cont_how": "Hoe te betalen",
"cont_no": "U heeft geen lopende contracten",
"cont_paid": "Markeer contract als betaald",
"cont_paid_e": "Doe dit alleen als u geld naar de verkoper heeft gestuurd via de overeengekomen betalingsmethode",
"cont_paid_e": "Doe dit alleen als u tegoeden naar de verkoper heeft gestuurd via de overeengekomen betalingsmethode",
"cont_paid_q": "Weet u zeker dat u dit contract als betaald wilt markeren?",
"cont_selling": "verkopen",
"cont_st_completed": "Klaar!",
@ -98,15 +98,16 @@
"potentialFee": "Mogelijke fee: {fee}",
"refill": "Bijvullen",
"refill_card": "Bijvullen met bankpas",
"refill_create": "Om verder te gaan, moet u een Bitcoin wallet maken om mee te vullen.",
"refill_create": "Om verder te gaan, moet u een Bitcoin-wallet maken om mee te vullen.",
"refill_external": "Aanvullen met externe wallet",
"refill_lnd_balance": "Vul Lightning-portemonneesaldo bij",
"sameWalletAsInvoiceError": "U kunt geen factuur betalen met dezelfde portemonnee die is gebruikt om de factuur te maken.",
"title": "fondsen beheren"
"refill_lnd_balance": "Vul Lightning-walletsaldo bij",
"sameWalletAsInvoiceError": "U kunt geen factuur betalen met dezelfde wallet die is gebruikt om de factuur te maken.",
"title": "tegoeden beheren"
},
"lndViewInvoice": {
"additional_info": "Extra informatie",
"for": "Voor:",
"lightning_invoice": "Lightning-factuur",
"has_been_paid": "Deze factuur is betaald",
"open_direct_channel": "Open een rechtstreeks kanaal met deze node:",
"please_pay": "Betaal alstublieft",
@ -114,69 +115,11 @@
"sats": "sats",
"wasnt_paid_and_expired": "Deze factuur is niet betaald en is verlopen"
},
"multisig": {
"are_you_sure_seed_will_be_lost": "Weet u het zeker? Uw mnemonic seed zal verloren gaan als u geen back-up heeft",
"co_sign_transaction": "Signeer een transactie",
"confirm": "Bevestig",
"cosign_this_transaction": "Deze transactie medeondertekenen?",
"create": "Maken",
"create_new_key": "Maak een nieuwe",
"export_coordination_setup": "export coördinatie setup",
"export_signed_psbt": "Ondertekende PSBT exporteren",
"fee": "Fee: {number}",
"fee_btc": "{number} BTC",
"forget_this_seed": "Vergeet deze seed en gebruik xpub",
"header": "Verzenden",
"how_many_signatures_can_bluewallet_make": "hoeveel handtekeningen kan BlueWallet maken",
"i_have_mnemonics": "Ik heb een seed voor deze key...",
"i_wrote_it_down": "Ok, ik heb het opgeschreven",
"invalid_cosigner": "Geen geldige mede-ondertekenaar gegevens",
"invalid_cosigner_format": "Onjuiste mede-ondertekenaar: dit is geen mede-ondertekenaar voor het {format} formaat",
"invalid_fingerprint": "Vingerafdruk voor dit seed komt niet overeen met de vingerafdruk van deze mede-ondertekenaar",
"invalid_mnemonics": "Deze mnemonic phrase lijkt niet te kloppen",
"legacy_title": "Legacy",
"lets_start": "Laten we beginnen",
"multisig_vault": "Kluis",
"multisig_vault_explain": "Beste beveiliging voor grote bedragen",
"native_segwit_title": "Beste oefening",
"needs": "Behoeften",
"of": "van",
"please_write_down_mnemonics": "Schrijf dit mnemonic phrase op papier. Maak je geen zorgen, je kunt het later opschrijven.",
"provide_key": "Geef de key op",
"provide_signature": "Geef een handtekening",
"quorum": "{m} van {n} quorum",
"quorum_header": "Quorum",
"required_keys_out_of_total": "Vereiste sleutels uit het totaal",
"scan_or_import_file": "Scan of importeer bestand",
"scan_or_open_file": "Scan of open bestand",
"share": "Delen",
"this_cosigner_is_already_imported": "Deze mede-ondertekenaar is al geïmporteerd",
"this_is_cosigners_xpub": "Dit is de xpub van mede-ondertekenaar, klaar om in een andere wallet te worden geïmporteerd. Het is veilig om het te delen.",
"type_your_mnemonics": "Voeg een seed in om uw bestaande kluissleutel te importeren",
"vault_advanced_customize": "Kluis-instellingen...",
"vault_key": "Kluisnummer {number}",
"view_edit_cosigners": "Bekijk/bewerk mede-ondertekenaars",
"view_edit_cosigners_title": "Bewerk mede-ontertekenaars",
"view_key": "bekijk",
"wallet_key_created": "Uw kluissleutel is gemaakt. Neem even de tijd om een veilige back-up van uw mnemonic seed te maken",
"wallet_type": "Wallettype",
"what_is_vault": "Een kluis is een",
"what_is_vault_description_number_of_vault_keys": "{m} kluissleutels",
"what_is_vault_description_to_spend": "te besteden en een 3e die u \nals back-up kunt gebruiken.",
"what_is_vault_numberOfWallets": "{m}-van-{n} multisig",
"what_is_vault_wallet": "wallet",
"wrapped_segwit_title": "Beste compatibiliteit"
},
"notifications": {
"ask_me_later": "Vraag het mij later",
"no_and_dont_ask": "Nee, en vraag het me niet nog een keer",
"would_you_like_to_receive_notifications": "Wil je meldingen ontvangen als je binnenkomende betalingen ontvangt?"
},
"plausibledeniability": {
"create_fake_storage": "Creëer versleutelde opslag",
"create_password": "Wachtwoord aanmaken",
"create_password_explanation": "Wachtwoord voor nep-opslag hoort niet overeen te komen met wachtwoord voor uw hoofdopslag",
"help": "Onder bepaalde omstandigheden kunt u worden gedwongen om uw wachtwoord te onthullen. Om uw munten veilig te houden, kan BlueWallet nog een versleutelde opslag aanmaken, met een ander wachtwoord. Onder druk kunt u dit wachtwoord bekendmaken aan de derde partij. Indien ingevoerd in BlueWallet, zal het nieuwe nep'-opslagruimte worden ontgrendeld. Dit lijkt legitiem voor de derde partij, maar zal uw hoofdopslag met munten niet bekend maken aan de derde partij.",
"help": "Onder bepaalde omstandigheden kunt u worden gedwongen om uw wachtwoord te onthullen. Om uw coins veilig te houden, kan BlueWallet nog een versleutelde opslag aanmaken, met een ander wachtwoord. Onder druk kunt u dit wachtwoord bekendmaken aan de derde partij. Indien ingevoerd in BlueWallet, zal het nieuwe nep'-opslagruimte worden ontgrendeld. Dit lijkt legitiem voor de derde partij, maar zal uw hoofdopslag met coins niet bekend maken aan de derde partij.",
"help2": "De nieuwe opslag zal volledig functioneel zijn en u kunt er een minimum aantal munten opslaan zodat het geloofwaardig lijkt.",
"password_should_not_match": "Wachtwoord is momenteel in gebruik. Probeer een ander wachtwoord.",
"passwords_do_not_match": "Wachtwoorden komen niet overeen, probeer het opnieuw",
@ -185,7 +128,7 @@
"title": "Plausibele ontkenning"
},
"pleasebackup": {
"ask": "Heeft u uw back-up zin opgeslagen? Deze back-up zin is nodig om toegang te krijgen tot uw gelden wanneer u dit apparaat verliest. Zonder de back-up zin zijn je gelden voor altijd verloren.",
"ask": "Heeft u uw back-up zin opgeslagen? Deze back-up zin is nodig om toegang te krijgen tot uw tegoeden wanneer u dit apparaat verliest. Zonder de back-up zin zijn je gelden voor altijd verloren.",
"ask_no": "Nee, dat heb ik niet",
"ask_yes": "Ja, dat heb ik.",
"ok": "Oké, ik heb het opgeschreven!",
@ -202,7 +145,7 @@
"header": "Ontvang"
},
"send": {
"broadcastButton": "UITZENDEN",
"broadcastButton": "Verzenden",
"broadcastError": "fout",
"broadcastNone": "Voer transactie-hash in",
"broadcastPending": "in afwachting",
@ -210,7 +153,7 @@
"confirm_header": "Bevestig",
"confirm_sendNow": "Nu verzenden",
"create_amount": "Bedrag",
"create_broadcast": "Uitzenden",
"create_broadcast": "Verzenden",
"create_copy": "Kopieer en verzend lader",
"create_details": "Details",
"create_fee": "Fee",
@ -240,7 +183,7 @@
"details_note_placeholder": "notitie voor mezelf",
"details_scan": "Scan",
"details_total_exceeds_balance": "Het verzendingsbedrag overschrijdt het beschikbare saldo.",
"details_wallet_before_tx": "Voor het maken van een transactie moet u eerst een Bitcoin wallet toevoegen.",
"details_wallet_before_tx": "Voor het maken van een transactie moet u eerst een Bitcoin-wallet toevoegen.",
"details_wallet_selection": "Wallet keuze",
"dynamic_init": "Initialiseren",
"dynamic_next": "Volgende",
@ -261,34 +204,36 @@
"input_done": "Klaar",
"input_paste": "Plak",
"input_total": "Totaal:",
"no_tx_signing_in_progress": "Er is geen ondertekening van een transactie bezig",
"open_settings": "Open instellingen",
"permission_camera_message": "We hebben toestemming nodig om uw camera te gebruiken",
"permission_camera_title": "Toestemming om camera te gebruiken",
"open_settings": "Open instellingen",
"permission_storage_later": "Vraag mij later",
"permission_storage_message": "BlueWallet heeft u toestemming nodig om toegang te krijgen tot uw opslag om deze transactie op te slaan.",
"permission_storage_denied_message": "BlueWallet kan dit bestand niet opslaan. Open uw apparaatinstellingen en schakel Opslagrechten in.",
"permission_storage_title": "BlueWallet opslag toegang toestemming",
"problem_with_psbt": "Probleem met PSBT",
"psbt_clipboard": "Gekopieerd naar Plakbord",
"psbt_this_is_psbt": "Dit is een gedeeltelijk ondertekende bitcoin-transactie (PSBT). Voltooi het door te ondertekenen met uw hardware wallet. ",
"psbt_this_is_psbt": "Dit is een gedeeltelijk ondertekende bitcoin-transactie (PSBT). Voltooi het door te ondertekenen met uw hardware-wallet. ",
"psbt_tx_export": "Exporteer naar bestand",
"no_tx_signing_in_progress": "Er is geen ondertekening van een transactie bezig",
"psbt_tx_open": "Open ondertekende transactie",
"psbt_tx_scan": "Scan ondertekende transactie",
"qr_error_no_qrcode": "De geselecteerde afbeelding bevat geen QR-code.",
"qr_error_no_wallet": "Het geselecteerde bestand bevat geen wallet die geïmporteerd kan worden.",
"success_done": "Klaar",
"txSaved": "Het transactiebestand ({filePath}) is opgeslagen in uw map Downloads."
"txSaved": "Het transactiebestand ({filePath}) is opgeslagen in uw map Downloads.",
"problem_with_psbt": "Probleem met PSBT"
},
"settings": {
"about": "Over",
"about_awesome": "Gebouwt met de geweldige",
"about_backup": "Maak altijd een backup van uw sleutels!",
"about_backup": "Maak altijd een backup van uw keys!",
"about_free": "BlueWallet is een gratis en open-source project. Gemaakt door Bitcoin gebruikers.",
"about_release_notes": "Release-opmerkingen",
"about_review": "Laat een review achter",
"about_selftest": "Voer een zelftest uit",
"about_sm_github": "GitHub",
"about_sm_telegram": "Telegram chat",
"about_sm_discord": "Discord server",
"about_sm_telegram": "Telegram kanaal",
"about_sm_twitter": "Volg ons op Twitter",
"advanced_options": "Geavanceerde opties",
"currency": "Valuta",
@ -321,38 +266,46 @@
"general_continuity": "Continuïteit",
"general_continuity_e": "Indien ingeschakeld, kunt u geselecteerde wallets en transacties bekijken met uw andere Apple iCloud-apparaten.",
"groundcontrol_explanation": "GroundControl is een gratis opensource-server voor pushmeldingen voor bitcoin-wallets. U kunt uw eigen GroundControl-server installeren en de URL hier plaatsen om niet te vertrouwen op de infrastructuur van BlueWallet. Laat leeg om standaard te gebruiken",
"header": "instellingen",
"header": "Instellingen",
"language": "Taal",
"language_restart": "Bij het selecteren van een nieuwe taal kan het nodig zijn om BlueWallet opnieuw op te starten om de wijziging door te voeren.",
"lightning_error_lndhub_uri": "Ongeldige LndHub URI",
"lightning_saved": "Uw wijzigingen zijn succesvol opgeslagen",
"lightning_settings": "Lightning instellingen",
"lightning_settings_explain": "Om verbinding te maken met uw eigen LND-node installeert u LndHub en plaatst u de URL hier in de instellingen. Laat dit leeg om de standaard lndHub (lndhub.io) te gebruiken.",
"lightning_settings": "Lightning-instellingen",
"lightning_settings_explain": "Om verbinding te maken met uw eigen LND-node installeert u LNDHub en plaatst u de URL hier in de instellingen. Laat dit leeg om de standaard LNDHub (lndhub.io) te gebruiken.",
"network": "Netwerk",
"network_broadcast": "Verzend transactie",
"network_electrum": "Electrum server",
"not_a_valid_uri": "Ongeldige URI",
"notifications": "Meldingen",
"open_link_in_explorer" : "Open link in verkenner",
"password": "Wachtwoord",
"password_explain": "Maak een wachtwoord aan dat u wilt gebruiken om de opslag te versleutelen",
"passwords_do_not_match": "Wachtwoorden komen niet overeen",
"plausible_deniability": "Plausibele ontkenning",
"privacy": "Privacy",
"privacy_clipboard_explanation": "Bied snelkoppelingen aan als een adres of factuur op uw klembord staat.",
"privacy_quickactions": "Wallet snelkoppelingen",
"privacy_quickactions_explanation": "Houd het BlueWallet-app-pictogram op uw startscherm ingedrukt om snel het saldo van uw wallet te bekijken.",
"privacy_read_clipboard": "Lees klembord",
"privacy_read_clipboard_alert": "BlueWallet geeft snelkoppelingen weer voor het afhandelen van een factuur of adres op uw klembord.",
"privacy_system_settings": "Systeeminstellingen",
"privacy_quickactions": "Wallet snelkoppelingen",
"privacy_quickactions_explanation": "Houd het BlueWallet-app-pictogram op uw startscherm ingedrukt om snel het saldo van uw wallet te bekijken.",
"privacy_clipboard_explanation": "Bied snelkoppelingen aan als een adres of factuur op uw klembord staat.",
"push_notifications": "Push notificaties",
"retype_password": "Geef nogmaals het wachtwoord op",
"save": "Opslaan",
"saved": "Opgeslagen"
"saved": "Opgeslagen",
"success_transaction_broadcasted" : "Gelukt! Uw transactie is verzonden!"
},
"notifications": {
"would_you_like_to_receive_notifications": "Wil je meldingen ontvangen als je binnenkomende betalingen ontvangt?",
"no_and_dont_ask": "Nee, en vraag het mij niet meer",
"ask_me_later": "Vraag het mij later"
},
"transactions": {
"cancel_explain": "We zullen deze transactie vervangen door degene die u betaalt en hogere fees heeft. Dit annuleert effectief de transactie. Dit heet RBF - Replace By Fee.",
"cancel_no": "Deze transactie is niet vervangbaar",
"cancel_title": "Annuleer deze transcatie (RBF)",
"confirmations_lowercase": "{confirmations} bevestigingen",
"cpfp_create": "Creëer",
"cpfp_exp": "We zullen een andere transactie creëren die uw niet-bevestigde transactie besteedt. De totale vergoeding is hoger dan de oorspronkelijke transactiekosten, dus deze moet sneller worden gemined. Dit heet CPFP - Child Pays For Parent.",
"cpfp_no_bump": "Deze transactie is niet bumpable",
@ -365,19 +318,20 @@
"details_inputs": "Inputs",
"details_outputs": "Outputs",
"details_received": "Ontvangen",
"transaction_note_saved":"Transactie notitie is succesvol opgeslagen.",
"details_show_in_block_explorer": "Weergeven in block explorer",
"details_title": "Transacties",
"details_to": "Uitvoer",
"details_transaction_details": "Transactie details",
"enable_hw": "Deze wallet wordt niet gebruikt in combinatie met een hardware wallet. Wilt u het gebruik van een hardware wallet inschakelen?",
"list_conf": "conf: {number}",
"list_title": "transacties",
"pending": "In afwachting",
"list_title": "Transacties",
"rbf_explain": "We zullen deze transactie vervangen door degene met een hogere fee, dus het zou sneller moeten worden gemined. Dit heet RBF - Replace By Fee.",
"rbf_title": "Bumb fee (RBF)",
"status_bump": "Bumb fee",
"status_cancel": "Annuleer transactie",
"transactions_count": "transactieteller"
"transactions_count": "Transactieteller"
},
"wallets": {
"add_bitcoin": "Bitcoin",
@ -391,11 +345,11 @@
"add_lightning_explain": "Voor uitgaven met directe transacties",
"add_lndhub": "Verbind met uw LNDHub",
"add_lndhub_error": "Het opgegeven node-adres is geen geldige LNDHub-node.",
"add_lndhub_placeholder": "uw node adres",
"add_lndhub_placeholder": "Uw node adres",
"add_or": "of",
"add_title": "wallet toevoegen",
"add_wallet_name": "naam",
"add_wallet_type": "type",
"add_title": "Wallet toevoegen",
"add_wallet_name": "Naam",
"add_wallet_type": "Type",
"clipboard_bitcoin": "U heeft een Bitcoin-adres op uw klembord. Wilt u deze gebruiken voor een transactie?",
"clipboard_lightning": "Je hebt een Lightning-factuur op je klembord. Wilt u deze gebruiken voor een transactie?",
"details_address": "Adres",
@ -404,10 +358,10 @@
"details_connected_to": "Verbonden met",
"details_del_wb": "Wallet saldo",
"details_del_wb_err": "Het opgegeven saldo komt niet overeen met het saldo van deze wallet. Probeer het a.u.b. opnieuw",
"details_del_wb_q": "Deze wallet heeft een saldo. Voordat u verder gaat, moet u er rekening mee houden dat u het geld niet kunt terugkrijgen zonder de seed phrase van deze wallet. Om te voorkomen dat deze wallet per ongeluk wordt verwijderd, moet u het saldo van {balance} satoshis in uw wallet invoeren.",
"details_del_wb_q": "Deze wallet heeft een saldo. Voordat u verder gaat, moet u er rekening mee houden dat u de tegoeden niet kunt terugkrijgen zonder de seed phrase van deze wallet. Om te voorkomen dat deze wallet per ongeluk wordt verwijderd, moet u het saldo van {balance} satoshis in uw wallet invoeren.",
"details_delete": "Verwijderen",
"details_delete_wallet": "Verwijder wallet",
"details_display": "toon in wallet lijst",
"details_display": "Toon in wallet-lijst",
"details_export_backup": "Exporteren / back-up maken",
"details_marketplace": "Marktplaats",
"details_master_fingerprint": "Master vingerafdruk",
@ -416,11 +370,11 @@
"details_show_xpub": "Toon wallet XPUB",
"details_title": "Wallet",
"details_type": "Type",
"details_use_with_hardware_wallet": "Gebruik met hardware wallet",
"details_use_with_hardware_wallet": "Gebruik met hardware-wallet",
"details_wallet_updated": "Wallet bijgewerkt",
"details_yes_delete": "Ja, verwijder",
"enter_bip38_password": "Voer wachtwoord in om te ontgrendelen",
"export_title": "wallet exporteren",
"export_title": "Wallet exporteren",
"import_do_import": "Importeren",
"import_error": "Importeren mislukt. Zorg ervoor dat de verstrekte gegevens geldig zijn.",
"import_explanation": "Schrijf hier je mnemonic phrase, private key, WIF of wat je maar hebt. BlueWallet zal zijn best doen om het juiste formaat te raden en uw wallet te importeren",
@ -428,31 +382,125 @@
"import_imported": "Geïmporteerd",
"import_scan_qr": "QR-code scannen of importeren?",
"import_success": "Succes",
"import_title": "importeren",
"import_title": "Importeren",
"list_create_a_button": "Voeg nu toe",
"list_create_a_wallet": "Wallet aanmaken",
"list_create_a_wallet_text": "Het is gratis en u kunt \ner zoveel maken als u wilt",
"list_empty_txs1": "Uw transacties verschijnen hier",
"list_empty_txs1_lightning": "Lightning-wallet moet worden gebruikt voor uw dagelijkse transacties. De fees zijn oneerlijk goedkoop en het is razendsnel.",
"list_empty_txs2": "Begin met uw wallet",
"list_empty_txs2_lightning": "\nOm het te gebruiken, tikt u op \"beheer fondsen\" en laadt u uw saldo op.",
"list_empty_txs2_lightning": "\nOm het te gebruiken, tikt u op \"tegoeden beheren\" en laadt u uw saldo op.",
"list_header": "Een wallet vertegenwoordigt een paar keys, een private en een die u kunt delen om coins te ontvangen.",
"list_import_error": "Er is een fout opgetreden bij het importeren van deze wallet.",
"list_import_problem": "Er is een probleem opgetreden bij het importeren van deze wallet",
"list_latest_transaction": "laatste transactie",
"list_latest_transaction": "Laatste transactie",
"list_long_choose": "Kies foto",
"list_long_clipboard": "Kopiëren van klembord",
"list_long_scan": "Scan QR-code",
"list_tap_here_to_buy": "Koop Bitcoin",
"list_title": "wallets",
"no_ln_wallet_error": "Voordat u een Lightning-factuur betaalt, moet u eerst een Lightning-wallet toevoegen.",
"list_title": "Wallets",
"list_tryagain": "Probeer opnieuw",
"looks_like_bip38": "Dit lijkt op een met een wachtwoord beveiligde private key (BIP38)",
"reorder_title": "Wallets opnieuw ordenen",
"please_continue_scanning": "Ga door met scannen",
"select_no_bitcoin": "Er is momenteel geen Bitcoin-wallet beschikbaar",
"select_no_bitcoin_exp": "Een Bitcoin-wallet is vereist om Lightning-wallets opnieuw te vullen. Maak of importeer er een.",
"select_wallet": "Selecteer wallet",
"take_photo": "Maak foto",
"xpub_copiedToClipboard": "Gekopieerd naar het klembord.",
"xpub_title": "wallet XPUB"
"pull_to_refresh": "Pull om te refreshen.",
"warning_do_not_disclose": "Waarschuwing! Niet bekendmaken",
"add_ln_wallet_first": "U moet eerst een Lightning-wallet toevoegen.",
"xpub_title": "Wallet XPUB"
},
"multisig": {
"multisig_vault": "Kluis",
"multisig_vault_explain": "Beste beveiliging voor grote bedragen",
"provide_signature": "Geef een handtekening",
"vault_key": "Vault key {number}",
"required_keys_out_of_total": "Vereiste keys uit het totaal",
"fee": "Fee: {number}",
"fee_btc": "{number} BTC",
"confirm": "Bevestig",
"header": "Verzenden",
"share": "Delen",
"view": "Bekijken",
"manage_keys": "Beheer keys",
"how_many_signatures_can_bluewallet_make": "Hoeveel handtekeningen kan BlueWallet maken",
"scan_or_import_file": "Scan of importeer bestand",
"export_coordination_setup": "Export coördinatie setup",
"cosign_this_transaction": "Deze transactie medeondertekenen?",
"lets_start": "Laten we beginnen",
"create": "Maken",
"provide_key": "Geef de key op",
"native_segwit_title": "Beste oefening",
"wrapped_segwit_title": "Beste compatibiliteit",
"legacy_title": "Legacy",
"co_sign_transaction": "Signeer een transactie",
"what_is_vault": "Een kluis is een",
"what_is_vault_numberOfWallets": "{m}-van-{n} multisig",
"what_is_vault_wallet": "Wallet",
"vault_advanced_customize": "Vault-instellingen...",
"needs": "Het is nodig",
"what_is_vault_description_number_of_vault_keys": "{m} Vault Keys",
"what_is_vault_description_to_spend": "te besteden en een 3e die u \nals back-up kunt gebruiken.",
"what_is_vault_description_to_spend_other": "om uit te geven.",
"quorum": "{m} van {n} quorum",
"quorum_header": "Quorum",
"of": "van",
"wallet_type": "Wallettype",
"view_key": "Bekijk",
"invalid_mnemonics": "Deze mnemonic phrase lijkt niet te kloppen",
"invalid_cosigner": "Geen geldige mede-ondertekenaar gegevens",
"invalid_cosigner_format": "Onjuiste mede-ondertekenaar: dit is geen mede-ondertekenaar voor het {format} formaat",
"create_new_key": "Maak een nieuwe",
"scan_or_open_file": "Scan of open bestand",
"i_have_mnemonics": "Ik heb een seed voor deze key...",
"please_write_down_mnemonics": "Schrijf dit mnemonic phrase op papier. Maak je geen zorgen, je kunt het later opschrijven.",
"i_wrote_it_down": "Ok, ik heb het opgeschreven",
"type_your_mnemonics": "Voeg een seed in om uw bestaande Vault key te importeren",
"this_is_cosigners_xpub": "Dit is de XPUB van mede-ondertekenaar, klaar om in een andere wallet te worden geïmporteerd. Het is veilig om het te delen.",
"wallet_key_created": "Uw Vault key is gemaakt. Neem even de tijd om een veilige back-up van uw mnemonic seed te maken",
"are_you_sure_seed_will_be_lost": "Weet u het zeker? Uw mnemonic seed zal verloren gaan als u geen back-up heeft",
"forget_this_seed": "Vergeet deze seed en gebruik XPUB",
"invalid_fingerprint": "Vingerafdruk voor dit seed komt niet overeen met de vingerafdruk van deze mede-ondertekenaar",
"view_edit_cosigners": "Bekijk/bewerk mede-ondertekenaars",
"this_cosigner_is_already_imported": "Deze mede-ondertekenaar is al geïmporteerd",
"export_signed_psbt": "Ondertekende PSBT exporteren",
"input_fp": "Vingerafdruk invoeren",
"input_fp_explain": "Overslaan om de standaard te gebruiken (00000000)",
"input_path": "Voer het derivation path in",
"input_path_explain": "Sla over om de standaard te gebruiken ({default})",
"ms_help": "Help",
"ms_help_title": "Hoe Multisig Vaults werken. Tips en trucs",
"ms_help_text": "Een wallet met meerdere keys, om de veiligheid exponentieel te verhogen of voor gedeelde bewaring.",
"ms_help_title1": "Meerdere apparaten worden geadviseerd",
"ms_help_1": "De Vault werkt met andere BlueWallet-apps en PSBT-compatibele wallets, zoals Electrum, Spectre, Coldcard, Cobo-kluis, enz.",
"ms_help_title2": "Keys bewerken",
"ms_help_2": "U kunt alle Vault-keys op dit apparaat maken en deze keys later verwijderen of bewerken. Het hebben van alle keys op hetzelfde apparaat heeft dezelfde beveiliging als een gewone Bitcoin-wallet.",
"ms_help_title3": "Vault Back-ups",
"ms_help_3": "Op de wallet-opties vindt u uw Vault back-up en watch-only back-up. Deze back-up is als een routekaart voor uw wallet. Het is essentieel voor het herstel van uw wallet voor het geval u een van uw seeds verliest.",
"ms_help_title4": "Vaults importeren",
"ms_help_4": "Om een Multisig te importeren, gebruikt u uw multisig back-upbestand en de importfunctie. Als u alleen uitgebreide keys en seeds heeft, kunt u de afzonderlijke importvelden in het Vaults Toevoegen schema gebruiken.",
"ms_help_title5": "Geavanceerde opties",
"ms_help_5": "BlueWallet genereert standaard een 2of3 Vault. Activeer de geavanceerde opties in de Instellingen om een ander quorum te creëren of om het adrestype te wijzigen."
},
"is_it_my_address": {
"title": "Is het mijn adres?",
"owns": "{label} eigen {address}",
"enter_address": "Adres invoeren",
"check_address": "Adres checken",
"no_wallet_owns_address": "Geen van de beschikbare wallets bezit het opgegeven adres."
},
"cc": {
"change": "Veranderen",
"coins_selected": "Geselecteerde coins ({number})",
"empty": "Deze wallet heeft momenteel geen coins",
"freeze": "Bevriezen",
"freezeLabel": "Bevriezen",
"header": "Coin Control",
"use_coin": "Gebruik Coin",
"tip": "Hiermee kunt u coins zien, labelen, bevriezen of selecteren voor verbeterd walletbeheer."
}
}

62
package-lock.json generated
View file

@ -1,14 +1,37 @@
{
"name": "bluewallet",
"version": "6.0.1",
"version": "6.0.2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@amplitude/eslint-config-typescript": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@amplitude/eslint-config-typescript/-/eslint-config-typescript-1.1.0.tgz",
"integrity": "sha512-N8sKkwtFakPD2/cSOrBnM5Wudjp4qeDD69U1cG7dZ6DDczxBhUEqnJDJ0wiYmKMPXqr+bmFOsDdbCcOmb/CLYA=="
},
"@amplitude/types": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@amplitude/types/-/types-1.1.0.tgz",
"integrity": "sha512-aJebJlI1hfRrzsbcRzW1heTDEClhElwEJ4ODyYZbBacKzH29q3OKZCkgNfaEYdxfgLpoDSh/ffHYpl7fWm3SQA==",
"requires": {
"@amplitude/eslint-config-typescript": "^1.1.0"
}
},
"@amplitude/ua-parser-js": {
"version": "0.7.24",
"resolved": "https://registry.npmjs.org/@amplitude/ua-parser-js/-/ua-parser-js-0.7.24.tgz",
"integrity": "sha512-VbQuJymJ20WEw0HtI2np7EdC3NJGUWi8+Xdbc7uk8WfMIF308T0howpzkQ3JFMN7ejnrcSM/OyNGveeE3TP3TA=="
},
"@amplitude/utils": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@amplitude/utils/-/utils-1.1.0.tgz",
"integrity": "sha512-TbKgBZNSRFu5RfYTKpprn/DFlZqr8jnmjXASZyQ/m8XDdbD2VoRqHDmKUwFiruX9OhAb2m9BhjLuaiwRYHCcqQ==",
"requires": {
"@amplitude/eslint-config-typescript": "^1.1.0",
"@amplitude/types": "^1.1.0",
"tslib": "^1.9.3"
}
},
"@babel/code-frame": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
@ -5962,10 +5985,10 @@
}
}
},
"@react-native-community/async-storage": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@react-native-community/async-storage/-/async-storage-1.12.1.tgz",
"integrity": "sha512-70WGaH3PKYASi4BThuEEKMkyAgE9k7VytBqmgPRx3MzJx9/MkspwqJGmn3QLCgHLIFUgF1pit2mWICbRJ3T3lg==",
"@react-native-async-storage/async-storage": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.13.2.tgz",
"integrity": "sha512-isTDvUApRJPVWFxV15yrQSOGqarX7cIedq/y4N5yWSnotf68D9qvDEv1I7rCXhkBDi0u4OJt6GA9dksUT0D3wg==",
"requires": {
"deep-assign": "^3.0.0"
}
@ -6369,9 +6392,9 @@
"integrity": "sha512-rk4sWFsmtOw8oyx8SD3KSvawwaK7gRBSEIy2TAwURyGt+3TizssXP1r8nx3zY+R7v2vYYHXZ+k2/GULAT/bcaQ=="
},
"@react-native-community/push-notification-ios": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/@react-native-community/push-notification-ios/-/push-notification-ios-1.7.1.tgz",
"integrity": "sha512-cx535+qyGbGTkx5GEHcF+Yd3fT9k1L114VeqQ5hkDYwU8unkKAiItjQz7Utvj/mcffwhqvPFU2FI3eKM3R1VYw==",
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/@react-native-community/push-notification-ios/-/push-notification-ios-1.8.0.tgz",
"integrity": "sha512-vxvkeampafjmtDoQBN8Q4azP21l6cMX93+OQZemyIWZmG++OjCVDQVitobf/kWLm5zyGwdylejbpMGo75qo7rA==",
"requires": {
"invariant": "^2.2.4"
}
@ -6996,11 +7019,12 @@
}
},
"amplitude-js": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/amplitude-js/-/amplitude-js-7.3.0.tgz",
"integrity": "sha512-FI3ziFNfV4kqpLYHLo6t+E7cbZZ1n8VRCNt214Z1CuDbEzPcc/TenmkCwPoYJA5FQibamqZL9qiKtdMTZhSsUg==",
"version": "7.3.3",
"resolved": "https://registry.npmjs.org/amplitude-js/-/amplitude-js-7.3.3.tgz",
"integrity": "sha512-krSXUXeHqbQk15ozx0kC3h0K3i7wQ1ycSG08OfZBga2Vfbi3Y30CP6UXLdtJX4AiBB8EkjMePdMgU6kyuIpi/A==",
"requires": {
"@amplitude/ua-parser-js": "0.7.24",
"@amplitude/utils": "^1.0.5",
"blueimp-md5": "^2.10.0",
"query-string": "5"
},
@ -18987,8 +19011,8 @@
}
},
"react-native-handoff": {
"version": "git+https://github.com/marcosrdz/react-native-handoff.git#05fc7dee3843d8c8ae150c0def753d4a9322230e",
"from": "git+https://github.com/marcosrdz/react-native-handoff.git"
"version": "git+https://github.com/marcosrdz/react-native-handoff.git#f5becc63f3e36bf2da1ed1fc60fc690323e73602",
"from": "git+https://github.com/marcosrdz/react-native-handoff.git#f5becc63f3e36bf2da1ed1fc60fc690323e73602"
},
"react-native-haptic-feedback": {
"version": "1.11.0",
@ -18996,9 +19020,9 @@
"integrity": "sha512-KTIy7lExwMtB6pOpCARyUzFj5EzYTh+A1GN/FB5Eb0LrW5C6hbb1kdj9K2/RHyZC+wyAJD1M823ZaDCU6n6cLA=="
},
"react-native-image-picker": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/react-native-image-picker/-/react-native-image-picker-3.0.1.tgz",
"integrity": "sha512-jVWiKT24jxr7K8dAixlsfHURZd+eDA4WWYeZhhKeJDGITCtFPphcTuFomTMtaWYE/gJgNTEL8TiLedcfeqJ9qw=="
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/react-native-image-picker/-/react-native-image-picker-3.1.1.tgz",
"integrity": "sha512-7ZtOjFzfnsguNimyO1O/aASK5YBAPPtKmfEqWGCdfOft6cWctaQGOhZgbyEa+zWq6y2NIxo7306IlaCs+PXkog=="
},
"react-native-inappbrowser-reborn": {
"version": "git+https://github.com/BlueWallet/react-native-inappbrowser.git#fa2d8e1763e46dd12a7e53081e97a0f908049103",
@ -19037,9 +19061,9 @@
"integrity": "sha512-LAUFsgcVHHJkU6AYjEDi9e6fJfahrep4IBXPNREKzG9uvHhjXno0Lv8TKNRMzrx6wGntpM/1bxs5pSTstpKllg=="
},
"react-native-modal": {
"version": "11.5.6",
"resolved": "https://registry.npmjs.org/react-native-modal/-/react-native-modal-11.5.6.tgz",
"integrity": "sha512-APGNfbvgC4hXbJqcSADu79GLoMKIHUmgR3fDQ7rCGZNBypkStSP8imZ4PKK/OzIZZfjGU9aP49jhMgGbhY9KHA==",
"version": "11.6.1",
"resolved": "https://registry.npmjs.org/react-native-modal/-/react-native-modal-11.6.1.tgz",
"integrity": "sha512-Xsd79nuBvbLOYwpRuur4btwJFQ3WkV9zp5LbAREidUtjl/Ajlp4QbNBx888FOPjo+EpOO3+U0riCRqs1dkdIzQ==",
"requires": {
"prop-types": "^15.6.2",
"react-native-animatable": "1.3.3"

View file

@ -1,6 +1,6 @@
{
"name": "bluewallet",
"version": "6.0.1",
"version": "6.0.2",
"license": "MIT",
"devDependencies": {
"@babel/core": "^7.10.4",
@ -66,19 +66,19 @@
},
"dependencies": {
"@babel/preset-env": "7.12.1",
"@react-native-community/async-storage": "1.12.1",
"@react-native-async-storage/async-storage": "1.13.2",
"@react-native-community/blur": "3.6.0",
"@react-native-community/clipboard": "1.5.0",
"@react-native-community/geolocation": "2.0.2",
"@react-native-community/masked-view": "0.1.10",
"@react-native-community/push-notification-ios": "1.7.1",
"@react-native-community/push-notification-ios": "1.8.0",
"@react-native-community/slider": "3.0.3",
"@react-navigation/drawer": "5.11.2",
"@react-navigation/native": "5.8.9",
"@react-navigation/stack": "5.12.6",
"@remobile/react-native-qrcode-local-image": "git+https://github.com/BlueWallet/react-native-qrcode-local-image.git",
"@sentry/react-native": "1.9.0",
"amplitude-js": "7.3.0",
"amplitude-js": "7.3.3",
"assert": "1.5.0",
"base-x": "3.0.8",
"bc-bech32": "file:blue_modules/bc-bech32",
@ -127,15 +127,15 @@
"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.8.0",
"react-native-handoff": "git+https://github.com/marcosrdz/react-native-handoff.git",
"react-native-handoff": "git+https://github.com/marcosrdz/react-native-handoff.git#f5becc63f3e36bf2da1ed1fc60fc690323e73602",
"react-native-haptic-feedback": "1.11.0",
"react-native-image-picker": "3.0.1",
"react-native-image-picker": "3.1.1",
"react-native-inappbrowser-reborn": "git+https://github.com/BlueWallet/react-native-inappbrowser.git#fa2d8e1763e46dd12a7e53081e97a0f908049103",
"react-native-is-catalyst": "git+https://github.com/BlueWallet/react-native-is-catalyst.git#v1.0.0",
"react-native-level-fs": "3.0.1",
"react-native-linear-gradient": "2.5.6",
"react-native-localize": "1.4.2",
"react-native-modal": "11.5.6",
"react-native-modal": "11.6.1",
"react-native-navigation-bar-color": "git+https://github.com/BlueWallet/react-native-navigation-bar-color.git#34e44b8f44e442133de9d35c35f2679d40982804",
"react-native-obscure": "1.2.1",
"react-native-passcode-auth": "git+https://github.com/BlueWallet/react-native-passcode-auth.git#a2ff977ba92b36f8d0a5567f59c05cc608e8bd12",

View file

@ -1,7 +1,7 @@
/* global alert */
import React, { Component } from 'react';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import AsyncStorage from '@react-native-community/async-storage';
import AsyncStorage from '@react-native-async-storage/async-storage';
import {
BlueBitcoinAmount,
BlueButton,

View file

@ -1,7 +1,7 @@
import React, { Component } from 'react';
import LottieView from 'lottie-react-native';
import { View, Text, Linking, StyleSheet, Image, ScrollView } from 'react-native';
import AsyncStorage from '@react-native-community/async-storage';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { Icon } from 'react-native-elements';
import {
BlueButton,

View file

@ -45,7 +45,7 @@ const ScanLndInvoice = () => {
const [isLoading, setIsLoading] = useState(false);
const [renderWalletSelectionButtonHidden, setRenderWalletSelectionButtonHidden] = useState(false);
const [destination, setDestination] = useState('');
const [unit, setUnit] = useState(wallet?.getPreferredBalanceUnit() || BitcoinUnit.SATS);
const [unit, setUnit] = useState(BitcoinUnit.SATS);
const [decoded, setDecoded] = useState();
const [amount, setAmount] = useState();
const [isAmountInitiallyEmpty, setIsAmountInitiallyEmpty] = useState();

View file

@ -70,7 +70,7 @@ const styles = StyleSheet.create({
position: 'absolute',
},
backdoorInputWrapper: { position: 'absolute', left: '5%', top: '0%', width: '90%', height: '70%', backgroundColor: 'white' },
progressWrapper: { position: 'absolute', right: '50%', top: '50%', backgroundColor: 'rgba(255, 255, 255, 0.1)' },
progressWrapper: { position: 'absolute', alignSelf: 'center', alignItems: 'center', top: '50%', padding: 8, borderRadius: 8 },
backdoorInput: {
height: '50%',
marginTop: 5,
@ -105,6 +105,7 @@ const ScanQRCode = () => {
openSettingsContainer: {
backgroundColor: colors.brandingColor,
},
progressWrapper: { backgroundColor: colors.brandingColor, borderColor: colors.foregroundColor, borderWidth: 4 },
});
const HashIt = function (s) {
return createHash('sha256').update(s).digest().toString('hex');
@ -270,13 +271,13 @@ const ScanQRCode = () => {
</TouchableOpacity>
)}
{urTotal > 0 && (
<View style={styles.progressWrapper} testID="UrProgressBar">
<View style={[styles.progressWrapper, stylesHook.progressWrapper]} testID="UrProgressBar">
<BlueText>{loc.wallets.please_continue_scanning}</BlueText>
<BlueText>
{urHave} / {urTotal}
</BlueText>
</View>
)}
{backdoorVisible && (
<View style={styles.backdoorInputWrapper}>
<BlueText>Provide QR code contents manually:</BlueText>

View file

@ -19,7 +19,7 @@ import {
FlatList,
} from 'react-native';
import { Icon } from 'react-native-elements';
import AsyncStorage from '@react-native-community/async-storage';
import AsyncStorage from '@react-native-async-storage/async-storage';
import {
BlueCreateTxNavigationStyle,
BlueButton,
@ -557,6 +557,11 @@ export default class SendDetails extends Component {
}
}
// if targets is empty, insert dust
if (targets.length === 0) {
targets.push({ address: '36JxaUrpDzkEerkTf1FzwHNE1Hb7cCjgJV', value: 546 });
}
// replace wrong addresses with dump
targets = targets.map(t => {
try {
@ -570,21 +575,15 @@ export default class SendDetails extends Component {
let flag = false;
while (true) {
try {
const { fee } = wallet.coinselect(
utxo,
targets,
opt.fee,
changeAddress,
this.state.isTransactionReplaceable ? HDSegwitBech32Wallet.defaultRBFSequence : HDSegwitBech32Wallet.finalRBFSequence,
);
const { fee } = wallet.coinselect(utxo, targets, opt.fee, changeAddress);
feePrecalc[opt.key] = fee;
break;
} catch (e) {
if (e.message.includes('Not enough') && !flag) {
flag = true;
// if the outputs are too big, replace them with dust
targets = targets.map(t => ({ ...t, value: 546 }));
// if we don't have enough funds, construct maximum possible transaction
targets = targets.map((t, index) => (index > 0 ? { ...t, value: 546 } : { address: t.address }));
continue;
}
@ -1293,13 +1292,15 @@ export default class SendDetails extends Component {
item.address = address || text;
item.amount = amount || item.amount;
transactions[index] = item;
this.setState({
addresses: transactions,
memo: memo || this.state.memo,
isLoading: false,
payjoinUrl,
});
this.reCalcTx();
this.setState(
{
addresses: transactions,
memo: memo || this.state.memo,
isLoading: false,
payjoinUrl,
},
this.reCalcTx,
);
}}
onBarScanned={this.processAddressData}
address={item.address}
@ -1328,11 +1329,14 @@ export default class SendDetails extends Component {
recipient.amount = BitcoinUnit.MAX;
recipient.amountSats = BitcoinUnit.MAX;
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
this.setState({
addresses: [recipient],
units: [BitcoinUnit.BTC],
isAdvancedTransactionOptionsVisible: false,
});
this.setState(
{
addresses: [recipient],
units: [BitcoinUnit.BTC],
isAdvancedTransactionOptionsVisible: false,
},
this.reCalcTx,
);
},
style: 'default',
},

View file

@ -1,5 +1,5 @@
import React, { useState, useContext } from 'react';
import { StyleSheet, View, KeyboardAvoidingView, Platform, TextInput } from 'react-native';
import { StyleSheet, View, KeyboardAvoidingView, Platform, TextInput, Keyboard } from 'react-native';
import loc from '../../loc';
import {
SafeBlueArea,
@ -41,6 +41,7 @@ const IsItMyAddress = () => {
const handleUpdateAddress = nextValue => setAddress(nextValue.trim());
const checkAddress = () => {
Keyboard.dismiss();
const cleanAddress = address.replace('bitcoin:', '').replace('BITCOIN:', '').replace('bitcoin=', '').split('?')[0];
const _result = [];
for (const w of wallets) {

View file

@ -13,7 +13,6 @@ import {
StyleSheet,
Alert,
} from 'react-native';
import { launchCamera } from 'react-native-image-picker';
import Clipboard from '@react-native-community/clipboard';
import {
SecondButton,
@ -31,7 +30,6 @@ import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import RNFS from 'react-native-fs';
import DocumentPicker from 'react-native-document-picker';
import loc from '../../loc';
import ScanQRCode from './ScanQRCode';
import { BlueStorageContext } from '../../blue_modules/storage-context';
import Notifications from '../../blue_modules/notifications';
import { useNavigation, useRoute, useTheme } from '@react-navigation/native';
@ -39,8 +37,8 @@ import isCatalyst from 'react-native-is-catalyst';
const BlueElectrum = require('../../blue_modules/BlueElectrum');
/** @type {AppStorage} */
const bitcoin = require('bitcoinjs-lib');
const LocalQRCode = require('@remobile/react-native-qrcode-local-image');
const isDesktop = getSystemName() === 'Mac OS X';
const fs = require('../../blue_modules/fs');
const PsbtWithHardwareWallet = () => {
const { txMetadata, fetchAndSaveWalletTransactions } = useContext(BlueStorageContext);
@ -244,27 +242,7 @@ const PsbtWithHardwareWallet = () => {
const openScanner = () => {
if (isDesktop) {
launchCamera(
{
title: null,
mediaType: 'photo',
takePhotoButtonTitle: null,
},
response => {
if (response.uri) {
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.uri;
LocalQRCode.decode(uri, (error, result) => {
if (!error) {
onBarScanned(result);
} else {
alert(loc.send.qr_error_no_qrcode);
}
});
} else if (response.error) {
ScanQRCode.presentCameraNotAuthorizedAlert(response.error);
}
},
);
fs.showActionSheet().then(data => onBarScanned({ data }));
} else {
navigation.navigate('ScanQRCodeRoot', {
screen: 'ScanQRCode',

View file

@ -1,5 +1,5 @@
import React from 'react';
import { ScrollView, Linking, Image, View, Text, StyleSheet, useWindowDimensions } from 'react-native';
import { TouchableOpacity, ScrollView, Linking, Image, View, Text, StyleSheet, useWindowDimensions } from 'react-native';
import { useNavigation, useTheme } from '@react-navigation/native';
import {
BlueTextCentered,
@ -10,6 +10,7 @@ import {
BlueListItem,
BlueNavigationStyle,
} from '../../BlueComponents';
import { Icon } from 'react-native-elements';
import { getApplicationName, getVersion, getBundleId, getBuildNumber } from 'react-native-device-info';
import Rate, { AndroidMarket } from 'react-native-rate';
import loc from '../../loc';
@ -53,6 +54,18 @@ const About = () => {
paddingTop: 0,
borderRadius: 8,
},
buttonLink: {
backgroundColor: colors.lightButton,
borderRadius: 12,
justifyContent: 'center',
padding: 8,
flexDirection: 'row',
},
textLink: {
color: colors.foregroundColor,
marginLeft: 8,
fontWeight: '600',
},
});
const handleOnReleaseNotesPress = () => {
@ -71,14 +84,16 @@ const About = () => {
Linking.openURL('https://twitter.com/bluewalletio');
};
const handleOnGithubPress = () => {
Linking.openURL('https://github.com/BlueWallet/BlueWallet');
const handleOnDiscordPress = () => {
Linking.openURL('https://discord.gg/btWq2Aby2z');
};
const handleOnTelegramPress = () => {
Linking.openURL('https://t.me/bluewallet');
Linking.openURL('https://t.me/bluewallethat');
};
const handleOnGithubPress = () => {
Linking.openURL('https://github.com/BlueWallet/BlueWallet');
};
const handleOnRatePress = () => {
const options = {
AppleAppID: '1376878040',
@ -126,12 +141,12 @@ const About = () => {
/>
<BlueListItem
leftIcon={{
name: 'github',
type: 'font-awesome',
color: colors.foregroundColor,
name: 'discord',
type: 'font-awesome-5',
color: '#7289da',
}}
onPress={handleOnGithubPress}
title={loc.settings.about_sm_github}
onPress={handleOnDiscordPress}
title={loc.settings.about_sm_discord}
/>
<BlueCard>
<View style={styles.buildWith}>
@ -143,6 +158,12 @@ const About = () => {
<BlueTextCentered>bitcoinjs-lib</BlueTextCentered>
<BlueTextCentered>Nodejs</BlueTextCentered>
<BlueTextCentered>Electrum server</BlueTextCentered>
<BlueSpacing20 />
<TouchableOpacity onPress={handleOnGithubPress} style={styles.buttonLink}>
<Icon size={22} name="github" type="font-awesome-5" color={colors.foregroundColor} />
<Text style={styles.textLink}>{loc.settings.about_sm_github}</Text>
</TouchableOpacity>
</View>
</BlueCard>
<BlueListItem

View file

@ -1,15 +1,17 @@
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useContext } from 'react';
import { FlatList, ActivityIndicator, View, StyleSheet } from 'react-native';
import { SafeBlueArea, BlueListItem, BlueText, BlueCard, BlueNavigationStyle } from '../../BlueComponents';
import PropTypes from 'prop-types';
import { FiatUnit, FiatUnitSource } from '../../models/fiatUnit';
import loc from '../../loc';
import { useTheme } from '@react-navigation/native';
import { BlueStorageContext } from '../../blue_modules/storage-context';
const currency = require('../../blue_modules/currency');
const data = Object.values(FiatUnit);
const Currency = () => {
const { setPreferredFiatCurrency } = useContext(BlueStorageContext);
const [isSavingNewPreferredCurrency, setIsSavingNewPreferredCurrency] = useState(false);
const [selectedCurrency, setSelectedCurrency] = useState(null);
const { colors } = useTheme();
@ -62,6 +64,7 @@ const Currency = () => {
await currency.setPrefferedCurrency(item);
await currency.startUpdater();
setIsSavingNewPreferredCurrency(false);
setPreferredFiatCurrency();
}}
/>
);

View file

@ -1,8 +1,8 @@
/* global alert */
import React, { Component } from 'react';
import { View, TextInput, StyleSheet } from 'react-native';
import { Alert, View, TextInput, StyleSheet } from 'react-native';
import { AppStorage } from '../../class';
import AsyncStorage from '@react-native-community/async-storage';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { ScrollView } from 'react-native-gesture-handler';
import {
BlueLoading,
@ -19,14 +19,17 @@ import PropTypes from 'prop-types';
import loc from '../../loc';
import DefaultPreference from 'react-native-default-preference';
import RNWidgetCenter from 'react-native-widget-center';
import DeeplinkSchemaMatch from '../../class/deeplink-schema-match';
const BlueElectrum = require('../../blue_modules/BlueElectrum');
export default class ElectrumSettings extends Component {
constructor(props) {
super(props);
const server = props?.route?.params?.server;
this.state = {
isLoading: true,
config: {},
server,
};
}
@ -56,6 +59,24 @@ export default class ElectrumSettings extends Component {
config: await BlueElectrum.getConfig(),
inverval,
});
if (this.state.server) {
Alert.alert(
loc.formatString(loc.settings.set_electrum_server_as_default, { server: this.state.server }),
'',
[
{
text: loc._.ok,
onPress: () => {
this.onBarScanned(this.state.server);
},
style: 'default',
},
{ text: loc._.cancel, onPress: () => {}, style: 'cancel' },
],
{ cancelable: false },
);
}
}
checkServer = async () => {
@ -115,6 +136,10 @@ export default class ElectrumSettings extends Component {
};
onBarScanned = value => {
if (DeeplinkSchemaMatch.getServerFromSetElectrumServerAction(value)) {
// in case user scans a QR with a deeplink like `bluewallet:setelectrumserver?server=electrum1.bluewallet.io%3A443%3As`
value = DeeplinkSchemaMatch.getServerFromSetElectrumServerAction(value);
}
var [host, port, type] = value.split(':');
this.setState({ host: host });
type === 's' ? this.setState({ sslPort: port }) : this.setState({ port: port });
@ -216,6 +241,9 @@ ElectrumSettings.propTypes = {
}),
route: PropTypes.shape({
name: PropTypes.string,
params: PropTypes.shape({
server: PropTypes.string,
}),
}),
};

View file

@ -1,9 +1,12 @@
import React, { useState, useEffect, useCallback } from 'react';
import React, { useState, useEffect, useContext } from 'react';
import { FlatList, StyleSheet } from 'react-native';
import { SafeBlueArea, BlueListItem, BlueCard, BlueLoading, BlueNavigationStyle, BlueText } from '../../BlueComponents';
import { SafeBlueArea, BlueListItem, BlueLoading, BlueNavigationStyle } from '../../BlueComponents';
import { AvailableLanguages } from '../../loc/languages';
import loc from '../../loc';
import { BlueStorageContext } from '../../blue_modules/storage-context';
import { useNavigation, useTheme } from '@react-navigation/native';
const styles = StyleSheet.create({
flex: {
flex: 1,
@ -11,42 +14,50 @@ const styles = StyleSheet.create({
});
const Language = () => {
const { setLanguage, language } = useContext(BlueStorageContext);
const [isLoading, setIsLoading] = useState(true);
const [language, setLanguage] = useState(loc.getLanguage());
const [selectedLanguage, setSelectedLanguage] = useState(loc.getLanguage());
const { setOptions } = useNavigation();
const { colors } = useTheme();
const stylesHook = StyleSheet.create({
flex: {
backgroundColor: colors.background,
},
});
useEffect(() => {
setIsLoading(false);
}, []);
const renderItem = useCallback(
({ item }) => {
return (
<BlueListItem
onPress={() => {
console.log('setLanguage', item.value);
loc.saveLanguage(item.value);
setLanguage(item.value);
}}
title={item.label}
{...(language === item.value
? {
rightIcon: { name: 'check', type: 'octaicon', color: '#0070FF' },
}
: { hideChevron: true })}
/>
);
},
[language],
);
useEffect(() => {
setOptions({ headerTitle: loc.settings.language });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [language]);
const renderItem = item => {
return (
<BlueListItem
onPress={async () => {
await loc.saveLanguage(item.item.value);
setSelectedLanguage(item.item.value);
setLanguage();
}}
title={item.item.label}
checkmark={selectedLanguage === item.item.value}
/>
);
};
return isLoading ? (
<BlueLoading />
) : (
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={styles.flex}>
<FlatList style={styles.flex} keyExtractor={(_item, index) => `${index}`} data={AvailableLanguages} renderItem={renderItem} />
<BlueCard>
<BlueText>{loc.settings.language_restart}</BlueText>
</BlueCard>
<SafeBlueArea forceInset={{ horizontal: 'always' }} style={[styles.flex, stylesHook.flex]}>
<FlatList
style={[styles.flex, stylesHook.flex]}
keyExtractor={(_item, index) => `${index}`}
data={AvailableLanguages}
renderItem={renderItem}
initialNumToRender={25}
/>
</SafeBlueArea>
);
};

View file

@ -1,10 +1,10 @@
/* global alert */
import React, { useState, useEffect, useCallback } from 'react';
import { View, TextInput, Linking, StyleSheet } from 'react-native';
import { View, TextInput, Linking, StyleSheet, Alert } from 'react-native';
import { Button } from 'react-native-elements';
import { useTheme, useNavigation, useRoute } from '@react-navigation/native';
import { AppStorage } from '../../class';
import AsyncStorage from '@react-native-community/async-storage';
import AsyncStorage from '@react-native-async-storage/async-storage';
import {
BlueSpacing20,
BlueButton,
@ -18,6 +18,7 @@ import {
import { LightningCustodianWallet } from '../../class/wallets/lightning-custodian-wallet';
import loc from '../../loc';
import { BlueCurrentTheme } from '../../components/themes';
import DeeplinkSchemaMatch from '../../class/deeplink-schema-match';
const styles = StyleSheet.create({
root: {
@ -48,6 +49,7 @@ const styles = StyleSheet.create({
});
const LightningSettings = () => {
const params = useRoute().params;
const [isLoading, setIsLoading] = useState(true);
const [URI, setURI] = useState();
const { colors } = useTheme();
@ -59,9 +61,31 @@ const LightningSettings = () => {
.then(setURI)
.then(() => setIsLoading(false))
.catch(() => setIsLoading(false));
}, []);
if (params?.url) {
Alert.alert(
loc.formatString(loc.settings.set_lndhub_as_default, { url: params?.url }),
'',
[
{
text: loc._.ok,
onPress: () => {
setLndhubURI(params?.url);
},
style: 'default',
},
{ text: loc._.cancel, onPress: () => {}, style: 'cancel' },
],
{ cancelable: false },
);
}
}, [params?.url]);
const setLndhubURI = value => {
if (DeeplinkSchemaMatch.getUrlFromSetLndhubUrlAction(value)) {
// in case user scans a QR with a deeplink like `bluewallet:setlndhuburl?url=https%3A%2F%2Flndhub.herokuapp.com`
value = DeeplinkSchemaMatch.getUrlFromSetLndhubUrlAction(value);
}
setURI(value.trim());
};

View file

@ -1,8 +1,9 @@
import React from 'react';
import { ScrollView, TouchableOpacity, StyleSheet, StatusBar } from 'react-native';
import React, { useContext } from 'react';
import { ScrollView, StyleSheet, StatusBar } from 'react-native';
import { BlueListItem, BlueNavigationStyle, BlueHeaderDefaultSubHooks } from '../../BlueComponents';
import { useNavigation } from '@react-navigation/native';
import loc from '../../loc';
import { BlueStorageContext } from '../../blue_modules/storage-context';
const styles = StyleSheet.create({
root: {
@ -12,36 +13,22 @@ const styles = StyleSheet.create({
const Settings = () => {
const { navigate } = useNavigation();
// By simply having it here, it'll re-render the UI if language is changed
// eslint-disable-next-line no-unused-vars
const { language } = useContext(BlueStorageContext);
return (
<ScrollView style={styles.root}>
<StatusBar barStyle="default" />
<BlueHeaderDefaultSubHooks leftText={loc.settings.header} rightComponent={null} />
<BlueListItem title={loc.settings.general} component={TouchableOpacity} onPress={() => navigate('GeneralSettings')} chevron />
<BlueListItem title={loc.settings.currency} component={TouchableOpacity} onPress={() => navigate('Currency')} chevron />
<BlueListItem title={loc.settings.language} component={TouchableOpacity} onPress={() => navigate('Language')} chevron />
<BlueListItem
title={loc.settings.encrypt_title}
onPress={() => navigate('EncryptStorage')}
component={TouchableOpacity}
testID="SecurityButton"
chevron
/>
<BlueListItem title={loc.settings.network} component={TouchableOpacity} onPress={() => navigate('NetworkSettings')} chevron />
<BlueListItem
title={loc.settings.notifications}
component={TouchableOpacity}
onPress={() => navigate('NotificationSettings')}
chevron
/>
<BlueListItem title={loc.settings.privacy} component={TouchableOpacity} onPress={() => navigate('SettingsPrivacy')} chevron />
<BlueListItem
title={loc.settings.about}
component={TouchableOpacity}
onPress={() => navigate('About')}
testID="AboutButton"
chevron
/>
<BlueListItem title={loc.settings.general} onPress={() => navigate('GeneralSettings')} chevron />
<BlueListItem title={loc.settings.currency} onPress={() => navigate('Currency')} chevron />
<BlueListItem title={loc.settings.language} onPress={() => navigate('Language')} chevron />
<BlueListItem title={loc.settings.encrypt_title} onPress={() => navigate('EncryptStorage')} testID="SecurityButton" chevron />
<BlueListItem title={loc.settings.network} onPress={() => navigate('NetworkSettings')} chevron />
<BlueListItem title={loc.settings.notifications} onPress={() => navigate('NotificationSettings')} chevron />
<BlueListItem title={loc.settings.privacy} onPress={() => navigate('SettingsPrivacy')} chevron />
<BlueListItem title={loc.settings.about} onPress={() => navigate('About')} testID="AboutButton" chevron />
</ScrollView>
);
};

View file

@ -12,7 +12,7 @@ import {
TextInput,
StyleSheet,
} from 'react-native';
import AsyncStorage from '@react-native-community/async-storage';
import AsyncStorage from '@react-native-async-storage/async-storage';
import {
BlueText,
BlueListItem,

View file

@ -311,7 +311,6 @@ const WalletsAddMultisigStep2 = () => {
};
const onBarScanned = ret => {
setIsProvideMnemonicsModalVisible(false);
if (!isDesktop) navigation.dangerouslyGetParent().pop();
if (!ret.data) ret = { data: ret };
if (ret.data.toUpperCase().startsWith('UR')) {
@ -322,7 +321,7 @@ const WalletsAddMultisigStep2 = () => {
} else {
let cosigner = new MultisigCosigner(ret.data);
if (!cosigner.isValid()) return alert(loc.multisig.invalid_cosigner);
setIsProvideMnemonicsModalVisible(false);
if (cosigner.howManyCosignersWeHave() > 1) {
// lets look for the correct cosigner. thats probably gona be the one with specific corresponding path,
// for example m/48'/0'/0'/2' if user chose to setup native segwit in BW
@ -390,8 +389,9 @@ const WalletsAddMultisigStep2 = () => {
const scanOrOpenFile = () => {
if (isDesktop) {
fs.showActionSheet().then(data => onBarScanned({ data }));
fs.showActionSheet().then(onBarScanned);
} else {
setIsProvideMnemonicsModalVisible(false);
navigation.navigate('ScanQRCodeRoot', {
screen: 'ScanQRCode',
params: {

View file

@ -1,4 +1,3 @@
/* global alert */
import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
import {
StatusBar,
@ -21,17 +20,14 @@ import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import { PlaceholderWallet } from '../../class';
import WalletImport from '../../class/wallet-import';
import ActionSheet from '../ActionSheet';
import { launchImageLibrary, launchCamera } from 'react-native-image-picker';
import Clipboard from '@react-native-community/clipboard';
import loc from '../../loc';
import { FContainer, FButton } from '../../components/FloatButtons';
import { getSystemName, isTablet } from 'react-native-device-info';
import { presentCameraNotAuthorizedAlert } from '../../class/camera';
import { useFocusEffect, useNavigation, useRoute, useTheme } from '@react-navigation/native';
import { BlueStorageContext } from '../../blue_modules/storage-context';
import isCatalyst from 'react-native-is-catalyst';
const A = require('../../blue_modules/analytics');
const LocalQRCode = require('@remobile/react-native-qrcode-local-image');
const fs = require('../../blue_modules/fs');
const WalletsListSections = { CAROUSEL: 'CAROUSEL', LOCALTRADER: 'LOCALTRADER', TRANSACTIONS: 'TRANSACTIONS' };
const isDesktop = getSystemName() === 'Mac OS X';
@ -362,52 +358,6 @@ const WalletsList = () => {
});
};
const choosePhoto = () => {
launchImageLibrary(
{
title: null,
mediaType: 'photo',
takePhotoButtonTitle: null,
},
response => {
if (response.uri) {
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.uri;
LocalQRCode.decode(uri, (error, result) => {
if (!error) {
onBarScanned(result);
} else {
alert(loc.send.qr_error_no_qrcode);
}
});
}
},
);
};
const takePhoto = () => {
launchCamera(
{
title: null,
mediaType: 'photo',
takePhotoButtonTitle: null,
},
response => {
if (response.uri) {
const uri = Platform.OS === 'ios' ? response.uri.toString().replace('file://', '') : response.uri;
LocalQRCode.decode(uri, (error, result) => {
if (!error) {
onBarScanned(result);
} else {
alert(loc.send.qr_error_no_qrcode);
}
});
} else if (response.error) {
presentCameraNotAuthorizedAlert(response.error);
}
},
);
};
const copyFromClipboard = async () => {
onBarScanned(await Clipboard.getString());
};
@ -415,17 +365,17 @@ const WalletsList = () => {
const sendButtonLongPress = async () => {
const isClipboardEmpty = (await Clipboard.getString()).replace(' ', '').length === 0;
if (Platform.OS === 'ios') {
const options = [loc._.cancel, loc.wallets.list_long_choose, isDesktop ? loc.wallets.take_photo : loc.wallets.list_long_scan];
if (!isClipboardEmpty) {
options.push(loc.wallets.list_long_clipboard);
}
ActionSheet.showActionSheetWithOptions({ options, cancelButtonIndex: 0 }, buttonIndex => {
if (buttonIndex === 1) {
choosePhoto();
} else if (buttonIndex === 2) {
if (isDesktop) {
takePhoto();
} else {
if (isDesktop) {
fs.showActionSheet().then(onBarScanned);
} else {
const options = [loc._.cancel, loc.wallets.list_long_choose, loc.wallets.list_long_scan];
if (!isClipboardEmpty) {
options.push(loc.wallets.list_long_clipboard);
}
ActionSheet.showActionSheetWithOptions({ options, cancelButtonIndex: 0 }, buttonIndex => {
if (buttonIndex === 1) {
fs.showImagePickerAndReadImage().then(onBarScanned);
} else if (buttonIndex === 2) {
navigate('ScanQRCodeRoot', {
screen: 'ScanQRCode',
params: {
@ -434,11 +384,11 @@ const WalletsList = () => {
showFileImportButton: false,
},
});
} else if (buttonIndex === 3) {
copyFromClipboard();
}
} else if (buttonIndex === 3) {
copyFromClipboard();
}
});
});
}
} else if (Platform.OS === 'android') {
const buttons = [
{
@ -448,7 +398,7 @@ const WalletsList = () => {
},
{
text: loc.wallets.list_long_choose,
onPress: choosePhoto,
onPress: () => fs.showActionSheet().then(onBarScanned),
},
{
text: loc.wallets.list_long_scan,

View file

@ -64,7 +64,7 @@ const PleaseBackup = () => {
};
return isLoading ? (
<View style={styles.loading}>
<View style={[styles.loading, stylesHook.flex]}>
<ActivityIndicator />
</View>
) : (
@ -99,7 +99,7 @@ const styles = StyleSheet.create({
},
loading: {
flex: 1,
paddingTop: 20,
justifyContent: 'center',
},
word: {
marginRight: 8,

View file

@ -35,8 +35,11 @@ import isCatalyst from 'react-native-is-catalyst';
import BottomModal from '../../components/BottomModal';
import BuyBitcoin from './buyBitcoin';
import { BlueStorageContext } from '../../blue_modules/storage-context';
import { getSystemName } from 'react-native-device-info';
const fs = require('../../blue_modules/fs');
const BlueElectrum = require('../../blue_modules/BlueElectrum');
const LocalQRCode = require('@remobile/react-native-qrcode-local-image');
const isDesktop = getSystemName() === 'Mac OS X';
const buttonFontSize =
PixelRatio.roundToNearestPixel(Dimensions.get('window').width / 26) > 22
@ -509,42 +512,19 @@ const WalletTransactions = () => {
};
const sendButtonLongPress = async () => {
const isClipboardEmpty = (await Clipboard.getString()).replace(' ', '').length === 0;
if (Platform.OS === 'ios') {
const options = [loc._.cancel, loc.wallets.list_long_choose, loc.wallets.list_long_scan];
if (!isClipboardEmpty) {
options.push(loc.wallets.list_long_clipboard);
}
ActionSheet.showActionSheetWithOptions({ options, cancelButtonIndex: 0 }, buttonIndex => {
if (buttonIndex === 1) {
choosePhoto();
} else if (buttonIndex === 2) {
navigate('ScanQRCodeRoot', {
screen: 'ScanQRCode',
params: {
launchedBy: name,
onBarScanned: onBarCodeRead,
showFileImportButton: false,
},
});
} else if (buttonIndex === 3) {
copyFromClipboard();
if (isDesktop) {
fs.showActionSheet().then(onBarCodeRead);
} else {
const isClipboardEmpty = (await Clipboard.getString()).replace(' ', '').length === 0;
if (Platform.OS === 'ios') {
const options = [loc._.cancel, loc.wallets.list_long_choose, loc.wallets.list_long_scan];
if (!isClipboardEmpty) {
options.push(loc.wallets.list_long_clipboard);
}
});
} else if (Platform.OS === 'android') {
const buttons = [
{
text: loc._.cancel,
onPress: () => {},
style: 'cancel',
},
{
text: loc.wallets.list_long_choose,
onPress: choosePhoto,
},
{
text: loc.wallets.list_long_scan,
onPress: () =>
ActionSheet.showActionSheetWithOptions({ options, cancelButtonIndex: 0 }, buttonIndex => {
if (buttonIndex === 1) {
choosePhoto();
} else if (buttonIndex === 2) {
navigate('ScanQRCodeRoot', {
screen: 'ScanQRCode',
params: {
@ -552,20 +532,47 @@ const WalletTransactions = () => {
onBarScanned: onBarCodeRead,
showFileImportButton: false,
},
}),
},
];
if (!isClipboardEmpty) {
buttons.push({
text: loc.wallets.list_long_clipboard,
onPress: copyFromClipboard,
});
} else if (buttonIndex === 3) {
copyFromClipboard();
}
});
} else if (Platform.OS === 'android') {
const buttons = [
{
text: loc._.cancel,
onPress: () => {},
style: 'cancel',
},
{
text: loc.wallets.list_long_choose,
onPress: choosePhoto,
},
{
text: loc.wallets.list_long_scan,
onPress: () =>
navigate('ScanQRCodeRoot', {
screen: 'ScanQRCode',
params: {
launchedBy: name,
onBarScanned: onBarCodeRead,
showFileImportButton: false,
},
}),
},
];
if (!isClipboardEmpty) {
buttons.push({
text: loc.wallets.list_long_clipboard,
onPress: copyFromClipboard,
});
}
ActionSheet.showActionSheetWithOptions({
title: '',
message: '',
buttons,
});
}
ActionSheet.showActionSheetWithOptions({
title: '',
message: '',
buttons,
});
}
};

View file

@ -1,5 +1,5 @@
import { AppStorage } from '../../class';
import AsyncStorage from '@react-native-community/async-storage';
import AsyncStorage from '@react-native-async-storage/async-storage';
import RNFS from 'react-native-fs';
import RNSecureKeyStore, { ACCESSIBLE } from 'react-native-secure-key-store';
import DefaultPreference from 'react-native-default-preference';

View file

@ -548,6 +548,14 @@ describe('BlueWallet UI Tests', () => {
newInstance: true,
url: 'bitcoin:BC1QH6TF004TY7Z7UN2V5NTU4MKF630545GVHS45U7\\?amount=0.0001\\&label=Yo',
});
// setting fee rate:
const feeRate = 2;
await element(by.id('chooseFee')).tap();
await element(by.id('feeCustom')).tap();
await element(by.type('android.widget.EditText')).typeText(feeRate + '');
await element(by.text('OK')).tap();
try {
await element(by.id('CreateTransactionButton')).tap();
} catch (_) {}

View file

@ -1,7 +1,7 @@
/* global describe, it, jest, jasmine */
import { AppStorage } from '../../class';
import { FiatUnit } from '../../models/fiatUnit';
import AsyncStorage from '@react-native-community/async-storage';
import AsyncStorage from '@react-native-async-storage/async-storage';
const assert = require('assert');
jest.useFakeTimers();

View file

@ -90,3 +90,20 @@ jest.mock('react-native-gesture-handler', () => jest.requireActual('react-native
jest.mock('react-native-document-picker', () => ({}));
jest.mock('react-native-haptic-feedback', () => ({}));
const realmInstanceMock = {
close: function () {},
objects: function () {
const wallets = {
filtered: function () {
return [];
},
};
return wallets;
},
};
jest.mock('realm', () => {
return {
open: jest.fn(() => realmInstanceMock),
};
});

View file

@ -165,6 +165,28 @@ describe('unit - DeepLinkSchemaMatch', function () {
},
],
},
{
argument: {
url: 'bluewallet:setelectrumserver?server=electrum1.bluewallet.io%3A443%3As',
},
expected: [
'ElectrumSettings',
{
server: 'electrum1.bluewallet.io:443:s',
},
],
},
{
argument: {
url: 'bluewallet:setlndhuburl?url=https%3A%2F%2Flndhub.herokuapp.com',
},
expected: [
'LightningSettings',
{
url: 'https://lndhub.herokuapp.com',
},
],
},
{
argument: {
url:
@ -291,4 +313,39 @@ describe('unit - DeepLinkSchemaMatch', function () {
assert.ok(DeeplinkSchemaMatch.isPossiblyPSBTFile('content://com.android.externalstorage.documents/document/081D-1403%3Atxhex.psbt'));
assert.ok(DeeplinkSchemaMatch.isPossiblyPSBTFile('file://com.android.externalstorage.documents/document/081D-1403%3Atxhex.psbt'));
});
it('can work with some deeplink actions', () => {
assert.strictEqual(DeeplinkSchemaMatch.getServerFromSetElectrumServerAction('sgasdgasdgasd'), false);
assert.strictEqual(
DeeplinkSchemaMatch.getServerFromSetElectrumServerAction('bluewallet:setelectrumserver?server=electrum1.bluewallet.io%3A443%3As'),
'electrum1.bluewallet.io:443:s',
);
assert.strictEqual(
DeeplinkSchemaMatch.getServerFromSetElectrumServerAction('setelectrumserver?server=electrum1.bluewallet.io%3A443%3As'),
'electrum1.bluewallet.io:443:s',
);
assert.strictEqual(
DeeplinkSchemaMatch.getServerFromSetElectrumServerAction('ololo:setelectrumserver?server=electrum1.bluewallet.io%3A443%3As'),
false,
);
assert.strictEqual(
DeeplinkSchemaMatch.getServerFromSetElectrumServerAction('setTrololo?server=electrum1.bluewallet.io%3A443%3As'),
false,
);
assert.strictEqual(
DeeplinkSchemaMatch.getUrlFromSetLndhubUrlAction('bluewallet:setlndhuburl?url=https%3A%2F%2Flndhub.herokuapp.com'),
'https://lndhub.herokuapp.com',
);
assert.strictEqual(
DeeplinkSchemaMatch.getUrlFromSetLndhubUrlAction('bluewallet:setlndhuburl?url=https%3A%2F%2Flndhub.herokuapp.com%3A443'),
'https://lndhub.herokuapp.com:443',
);
assert.strictEqual(
DeeplinkSchemaMatch.getUrlFromSetLndhubUrlAction('setlndhuburl?url=https%3A%2F%2Flndhub.herokuapp.com%3A443'),
'https://lndhub.herokuapp.com:443',
);
assert.strictEqual(DeeplinkSchemaMatch.getUrlFromSetLndhubUrlAction('gsom?url=https%3A%2F%2Flndhub.herokuapp.com%3A443'), false);
assert.strictEqual(DeeplinkSchemaMatch.getUrlFromSetLndhubUrlAction('sdfhserhsthsd'), false);
});
});

View file

@ -1568,6 +1568,66 @@ describe('multisig-wallet (native segwit)', () => {
assert.strictEqual(w.getN(), 1);
assert.strictEqual(w.getM(), 2);
});
it('can sign valid tx if we have more keys than quorum ("Too many signatures" error)', async () => {
const w = new MultisigHDWallet();
w.setSecret(
'# BlueWallet Multisig setup file\n' +
'# this file may contain private information\n' +
'#\n' +
'Name: Multisig Vault\n' +
'Policy: 3 of 6\n' +
"Derivation: m/48'/0'/0'/2'\n" +
'Format: P2WSH\n' +
'\n' +
'seed: start local figure rose pony artist voice agent pyramid still spot walk\n' +
'# warning! sensitive information, do not disclose ^^^ \n' +
'\n' +
'seed: empty fall vanish sheriff vibrant diary route lock purity noodle ripple clutch\n' +
'# warning! sensitive information, do not disclose ^^^ \n' +
'\n' +
'seed: else heart suggest proof travel announce reason priority trick bargain author duty\n' +
'# warning! sensitive information, do not disclose ^^^ \n' +
'\n' +
'seed: craft response kitchen column feed fitness pill loyal capital together usage either\n' +
'# warning! sensitive information, do not disclose ^^^ \n' +
'\n' +
'seed: trigger zebra image engine inhale employ floor soul glimpse version extra pizza\n' +
'# warning! sensitive information, do not disclose ^^^ \n' +
'\n' +
'seed: thank post talent polar hire model trophy elevator wide green hungry gossip\n' +
'# warning! sensitive information, do not disclose ^^^',
);
const utxos = [
{
height: 662352,
value: 100000,
address: 'bc1qlkh0zgq5ypcdfs9rdvrucra96c5gmjgaufm0au8cglkkrah29nesrkvewg',
txId: 'e112e3b109aff5fe76d4fde90bd3c2df58bfb250280a4404421fff42d6801fd2',
vout: 0,
txid: 'e112e3b109aff5fe76d4fde90bd3c2df58bfb250280a4404421fff42d6801fd2',
amount: 100000,
wif: false,
confirmations: 1,
txhex:
'020000000001020d0f713ba314566ea9b7e7d64eb8538dd0a88826377945464e9bb25eed61d665010000000000000080f570a2bb8faff02b848a4a5b2d334324a1ccc6cebf1c1cc27e231316f579e66d01000000000000008002a086010000000000220020fdaef120142070d4c0a36b07cc0fa5d6288dc91de276fef0f847ed61f6ea2cf3d6eb060000000000160014696154a1ed38813c4c45b58ece291c1a8d9cd7d102483045022100d02ef858d129ba50aeee126e41e9cca5fa58232def7934d6705747e81bcd61a402206d2565c336cd32cb128ae9e80af60d610154af0d4e77cb60e015dead349b368b012103471950f9952608d9db6d3698b731d89387b7b55026ae020919ee7da7a2a4866d0247304402204088a68fc4654c0cedb724f6e8fe3820845d5e7184b0363806ea77f8a739f58702202bf7b3b20d6d6db28617e8edd6d0ea3870ab7e3bc62307ad77fa9717a3689bcb01210371d2366d9fc32c5a83bb78d7ced38d5e318a96dc43a18074742e567defe4585d00000000',
},
];
const { psbt, tx } = w.createTransaction(
utxos,
[{ address: '13HaCAB4jf7FYSZexJxoczyDDnutzZigjS' }], // sendMax
1,
w._getInternalAddressByIndex(0),
);
assert.ok(tx);
assert.ok(psbt);
assert.strictEqual(psbt.data.inputs.length, 1);
assert.strictEqual(psbt.data.outputs.length, 1);
});
});
describe('multisig-cosigner', () => {

View file

@ -1,6 +1,6 @@
/* global it */
import { SegwitP2SHWallet, AppStorage } from '../../class';
import AsyncStorage from '@react-native-community/async-storage';
import AsyncStorage from '@react-native-async-storage/async-storage';
const assert = require('assert');
it('Appstorage - loadFromDisk works', async () => {